From 1479a65d591c759b7ceab4f1101ba2c286415cb1 Mon Sep 17 00:00:00 2001 From: glyph Date: Thu, 3 Mar 2022 08:55:37 +0200 Subject: [PATCH] rename sbot context module to match all scuttlebutt.rs files --- peach-web/src/context/mod.rs | 2 +- peach-web/src/context/sbot.rs | 588 --------------------- peach-web/src/routes/scuttlebutt.rs | 22 +- peach-web/src/routes/status/scuttlebutt.rs | 4 +- 4 files changed, 15 insertions(+), 601 deletions(-) delete mode 100644 peach-web/src/context/sbot.rs diff --git a/peach-web/src/context/mod.rs b/peach-web/src/context/mod.rs index 691bc21..019dd88 100644 --- a/peach-web/src/context/mod.rs +++ b/peach-web/src/context/mod.rs @@ -1,3 +1,3 @@ pub mod dns; pub mod network; -pub mod sbot; +pub mod scuttlebutt; diff --git a/peach-web/src/context/sbot.rs b/peach-web/src/context/sbot.rs deleted file mode 100644 index 9d319a6..0000000 --- a/peach-web/src/context/sbot.rs +++ /dev/null @@ -1,588 +0,0 @@ -use std::collections::HashMap; - -use golgi::{api::friends::RelationshipQuery, blobs, messages::SsbMessageValue, Sbot}; -use peach_lib::sbot::{SbotConfig, SbotStatus}; -use rocket::{futures::TryStreamExt, serde::Serialize}; - -use crate::{error::PeachWebError, utils}; - -// HELPER FUNCTIONS - -pub async fn init_sbot_with_config( - sbot_config: &Option, -) -> Result { - // initialise sbot connection with ip:port and shscap from config file - let sbot_client = match sbot_config { - // TODO: panics if we pass `Some(conf.shscap)` as second arg - Some(conf) => { - let ip_port = conf.lis.clone(); - Sbot::init(Some(ip_port), None).await? - } - None => Sbot::init(None, None).await?, - }; - - Ok(sbot_client) -} - -// CONTEXT STRUCTS AND BUILDERS - -#[derive(Debug, Serialize)] -pub struct StatusContext { - pub back: Option, - pub flash_name: Option, - pub flash_msg: Option, - pub title: Option, - pub theme: Option, - pub sbot_config: Option, - pub sbot_status: Option, - // latest sequence number for the local log - pub latest_seq: Option, -} - -impl StatusContext { - pub fn default() -> Self { - StatusContext { - back: Some("/".to_string()), - flash_name: None, - flash_msg: None, - title: Some("Scuttlebutt Status".to_string()), - theme: None, - sbot_config: None, - sbot_status: None, - latest_seq: None, - } - } - - pub async fn build() -> Result { - let mut context = Self::default(); - - // retrieve current ui theme - context.theme = Some(utils::get_theme()); - - // retrieve go-sbot systemd process status - let sbot_status = SbotStatus::read()?; - - // we only want to try and interact with the sbot if it's active - if sbot_status.state == Some("active".to_string()) { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - let mut sbot_client = init_sbot_with_config(&sbot_config).await?; - - // retrieve the local id - let id = sbot_client.whoami().await?; - - let history_stream = sbot_client.create_history_stream(id).await?; - let mut msgs: Vec = history_stream.try_collect().await?; - - // reverse the list of messages so we can easily reference the latest one - msgs.reverse(); - - // assign the sequence number of the latest msg - context.latest_seq = Some(msgs[0].sequence); - - context.sbot_config = sbot_config; - } else { - // the sbot is not currently active; return a helpful message - context.flash_name = Some("warning".to_string()); - context.flash_msg = Some("The Sbot is currently inactive. As a result, status data cannot be retrieved. Visit the Scuttlebutt settings menu to start the Sbot and then try again".to_string()); - } - - context.sbot_status = Some(sbot_status); - - Ok(context) - } -} - -// peers who are blocked by the local account -#[derive(Debug, Serialize)] -pub struct BlocksContext { - pub back: Option, - pub flash_name: Option, - pub flash_msg: Option, - pub title: Option, - pub theme: Option, - pub sbot_config: Option, - pub sbot_status: Option, - pub peers: Option>>, -} - -impl BlocksContext { - pub fn default() -> Self { - BlocksContext { - back: Some("/scuttlebutt/peers".to_string()), - flash_name: None, - flash_msg: None, - title: Some("Blocks".to_string()), - theme: None, - sbot_config: None, - sbot_status: None, - peers: None, - } - } - - pub async fn build() -> Result { - let mut context = Self::default(); - - // retrieve current ui theme - context.theme = Some(utils::get_theme()); - - // retrieve go-sbot systemd process status - let sbot_status = SbotStatus::read()?; - - // we only want to try and interact with the sbot if it's active - if sbot_status.state == Some("active".to_string()) { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - let mut sbot_client = init_sbot_with_config(&sbot_config).await?; - - let blocks = sbot_client.get_blocks().await?; - - // we'll use this to store the profile info for each peer who follows us - let mut peer_info = Vec::new(); - - if !blocks.is_empty() { - for peer in blocks.iter() { - // trim whitespace (including newline characters) and - // remove the inverted-commas around the id - let key = peer.trim().replace('"', ""); - // retrieve the profile info for the given peer - let mut info = sbot_client.get_profile_info(&key).await?; - // insert the public key of the peer into the info hashmap - info.insert("id".to_string(), key.to_string()); - // we do not even attempt to find the blob for a blocked peer, - // since it may be vulgar to cause distress to the local peer. - info.insert("blob_exists".to_string(), "false".to_string()); - // push profile info to peer_list vec - peer_info.push(info) - } - - context.peers = Some(peer_info) - } - } else { - // the sbot is not currently active; return a helpful message - context.flash_name = Some("warning".to_string()); - context.flash_msg = Some("The Sbot is currently inactive. As a result, peer data cannot be retrieved. Visit the Scuttlebutt settings menu to start the Sbot and then try again".to_string()); - } - - context.sbot_status = Some(sbot_status); - - Ok(context) - } -} - -// peers who are followed by the local account -#[derive(Debug, Serialize)] -pub struct FollowsContext { - pub back: Option, - pub flash_name: Option, - pub flash_msg: Option, - pub title: Option, - pub theme: Option, - pub sbot_config: Option, - pub sbot_status: Option, - pub peers: Option>>, -} - -impl FollowsContext { - pub fn default() -> Self { - FollowsContext { - back: Some("/scuttlebutt/peers".to_string()), - flash_name: None, - flash_msg: None, - title: Some("Follows".to_string()), - theme: None, - sbot_config: None, - sbot_status: None, - peers: None, - } - } - - pub async fn build() -> Result { - let mut context = Self::default(); - - // retrieve current ui theme - context.theme = Some(utils::get_theme()); - - // retrieve go-sbot systemd process status - let sbot_status = SbotStatus::read()?; - - // we only want to try and interact with the sbot if it's active - if sbot_status.state == Some("active".to_string()) { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - let mut sbot_client = init_sbot_with_config(&sbot_config).await?; - - let follows = sbot_client.get_follows().await?; - - // we'll use this to store the profile info for each peer who follows us - let mut peer_info = Vec::new(); - - if !follows.is_empty() { - for peer in follows.iter() { - // trim whitespace (including newline characters) and - // remove the inverted-commas around the id - let key = peer.trim().replace('"', ""); - // retrieve the profile info for the given peer - let mut info = sbot_client.get_profile_info(&key).await?; - // insert the public key of the peer into the info hashmap - info.insert("id".to_string(), key.to_string()); - // retrieve the profile image blob id for the given peer - if let Some(blob_id) = info.get("image") { - // look-up the path for the image blob - if let Ok(blob_path) = blobs::get_blob_path(&blob_id) { - // insert the image blob path of the peer into the info hashmap - info.insert("blob_path".to_string(), blob_path.to_string()); - // check if the blob is in the blobstore - // set a flag in the info hashmap - match utils::blob_is_stored_locally(&blob_path).await { - Ok(exists) if exists == true => { - info.insert("blob_exists".to_string(), "true".to_string()) - } - _ => info.insert("blob_exists".to_string(), "false".to_string()), - }; - } - } - // push profile info to peer_list vec - peer_info.push(info) - } - - context.peers = Some(peer_info) - } - } else { - // the sbot is not currently active; return a helpful message - context.flash_name = Some("warning".to_string()); - context.flash_msg = Some("The Sbot is currently inactive. As a result, peer data cannot be retrieved. Visit the Scuttlebutt settings menu to start the Sbot and then try again".to_string()); - } - - context.sbot_status = Some(sbot_status); - - Ok(context) - } -} - -// peers who follow and are followed by the local account (friends) -#[derive(Debug, Serialize)] -pub struct FriendsContext { - pub back: Option, - pub flash_name: Option, - pub flash_msg: Option, - pub title: Option, - pub theme: Option, - pub sbot_config: Option, - pub sbot_status: Option, - pub peers: Option>>, -} - -impl FriendsContext { - pub fn default() -> Self { - FriendsContext { - back: Some("/scuttlebutt/peers".to_string()), - flash_name: None, - flash_msg: None, - title: Some("Friends".to_string()), - theme: None, - sbot_config: None, - sbot_status: None, - peers: None, - } - } - - pub async fn build() -> Result { - let mut context = Self::default(); - - // retrieve current ui theme - context.theme = Some(utils::get_theme()); - - // retrieve go-sbot systemd process status - let sbot_status = SbotStatus::read()?; - - // we only want to try and interact with the sbot if it's active - if sbot_status.state == Some("active".to_string()) { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - let mut sbot_client = init_sbot_with_config(&sbot_config).await?; - - let local_id = sbot_client.whoami().await?; - - let follows = sbot_client.get_follows().await?; - - // we'll use this to store the profile info for each peer who follows us - let mut peer_info = Vec::new(); - - if !follows.is_empty() { - for peer in follows.iter() { - // trim whitespace (including newline characters) and - // remove the inverted-commas around the id - let peer_id = peer.trim().replace('"', ""); - // retrieve the profile info for the given peer - let mut info = sbot_client.get_profile_info(&peer_id).await?; - // insert the public key of the peer into the info hashmap - info.insert("id".to_string(), peer_id.to_string()); - // retrieve the profile image blob id for the given peer - if let Some(blob_id) = info.get("image") { - // look-up the path for the image blob - if let Ok(blob_path) = blobs::get_blob_path(&blob_id) { - // insert the image blob path of the peer into the info hashmap - info.insert("blob_path".to_string(), blob_path.to_string()); - // check if the blob is in the blobstore - // set a flag in the info hashmap - match utils::blob_is_stored_locally(&blob_path).await { - Ok(exists) if exists == true => { - info.insert("blob_exists".to_string(), "true".to_string()) - } - _ => info.insert("blob_exists".to_string(), "false".to_string()), - }; - } - } - - // check if the peer follows us (making us friends) - let follow_query = RelationshipQuery { - source: peer_id.to_string(), - dest: local_id.clone(), - }; - - // query follow state - match sbot_client.friends_is_following(follow_query).await { - Ok(following) if following == "true" => { - // only push profile info to peer_list vec if they follow us - peer_info.push(info) - } - _ => (), - }; - } - - context.peers = Some(peer_info) - } - } else { - // the sbot is not currently active; return a helpful message - context.flash_name = Some("warning".to_string()); - context.flash_msg = Some("The Sbot is currently inactive. As a result, peer data cannot be retrieved. Visit the Scuttlebutt settings menu to start the Sbot and then try again".to_string()); - } - - context.sbot_status = Some(sbot_status); - - Ok(context) - } -} - -#[derive(Debug, Serialize)] -pub struct ProfileContext { - pub back: Option, - pub flash_name: Option, - pub flash_msg: Option, - pub title: Option, - pub theme: Option, - pub sbot_config: Option, - pub sbot_status: Option, - // is this the local profile or the profile of a peer? - pub is_local_profile: bool, - // an ssb_id which may or may not be the local public key - pub id: Option, - pub name: Option, - pub description: Option, - pub image: Option, - // the path to the blob defined in the `image` field (aka the profile picture) - pub blob_path: Option, - // whether or not the blob exists in the blobstore (ie. is saved on disk) - pub blob_exists: bool, - // relationship state (if the profile being viewed is not for the local public key) - pub following: Option, - pub blocking: Option, -} - -impl ProfileContext { - pub fn default() -> Self { - ProfileContext { - back: Some("/".to_string()), - flash_name: None, - flash_msg: None, - title: Some("Profile".to_string()), - theme: None, - sbot_config: None, - sbot_status: None, - is_local_profile: true, - id: None, - name: None, - description: None, - image: None, - blob_path: None, - blob_exists: false, - following: None, - blocking: None, - } - } - - pub async fn build(ssb_id: Option) -> Result { - let mut context = Self::default(); - - // retrieve current ui theme - context.theme = Some(utils::get_theme()); - - // retrieve go-sbot systemd process status - let sbot_status = SbotStatus::read()?; - - // we only want to try and interact with the sbot if it's active - if sbot_status.state == Some("active".to_string()) { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - let mut sbot_client = init_sbot_with_config(&sbot_config).await?; - - let local_id = sbot_client.whoami().await?; - - // if an ssb_id has been provided to the context builder, we assume that - // the profile info being retrieved is for a peer (ie. not for our local - // profile) - let id = if ssb_id.is_some() { - // we are not dealing with the local profile - context.is_local_profile = false; - - // we're safe to unwrap here because we know it's `Some(id)` - let peer_id = ssb_id.unwrap(); - - // determine relationship between peer and local id - let follow_query = RelationshipQuery { - source: local_id.clone(), - dest: peer_id.clone(), - }; - - // query follow state - context.following = match sbot_client.friends_is_following(follow_query).await { - Ok(following) if following == "true" => Some(true), - Ok(following) if following == "false" => Some(false), - _ => None, - }; - - // TODO: i don't like that we have to instantiate the same query object - // twice. see if we can streamline this in golgi - let block_query = RelationshipQuery { - source: local_id.clone(), - dest: peer_id.clone(), - }; - - // query block state - context.blocking = match sbot_client.friends_is_blocking(block_query).await { - Ok(blocking) if blocking == "true" => Some(true), - Ok(blocking) if blocking == "false" => Some(false), - _ => None, - }; - - peer_id - } else { - // if an ssb_id has not been provided, retrieve the local id using whoami - context.is_local_profile = true; - - local_id - }; - - // TODO: add relationship state context if not local profile - // ie. lookup is_following and is_blocking, set context accordingly - - // retrieve the profile info for the given id - let info = sbot_client.get_profile_info(&id).await?; - // set each context field accordingly - for (key, val) in info { - match key.as_str() { - "name" => context.name = Some(val), - "description" => context.description = Some(val), - "image" => context.image = Some(val), - _ => (), - } - } - - // assign the ssb public key to the context - // (could be for the local profile or a peer) - context.id = Some(id); - - // determine the path to the blob defined by the value of `context.image` - if let Some(ref blob_id) = context.image { - context.blob_path = match blobs::get_blob_path(&blob_id) { - Ok(path) => { - // if we get the path, check if the blob is in the blobstore. - // this allows us to default to a placeholder image in the template - if let Ok(exists) = utils::blob_is_stored_locally(&path).await { - context.blob_exists = exists - }; - - Some(path) - } - Err(_) => None, - } - } - } else { - // the sbot is not currently active; return a helpful message - context.flash_name = Some("warning".to_string()); - context.flash_msg = Some("The Sbot is currently inactive. As a result, profile data cannot be retrieved. Visit the Scuttlebutt settings menu to start the Sbot and then try again".to_string()); - } - - context.sbot_status = Some(sbot_status); - - Ok(context) - } -} - -#[derive(Debug, Serialize)] -pub struct PrivateContext { - pub back: Option, - pub flash_name: Option, - pub flash_msg: Option, - pub title: Option, - pub theme: Option, - pub sbot_config: Option, - pub sbot_status: Option, - // local peer id (whoami) - pub id: Option, - // id of the peer being messaged - pub recipient_id: Option, -} - -impl PrivateContext { - pub fn default() -> Self { - PrivateContext { - back: Some("/".to_string()), - flash_name: None, - flash_msg: None, - title: Some("Private Messages".to_string()), - theme: None, - sbot_config: None, - sbot_status: None, - id: None, - recipient_id: None, - } - } - - pub async fn build(recipient_id: Option) -> Result { - let mut context = Self::default(); - - // retrieve current ui theme - context.theme = Some(utils::get_theme()); - - // retrieve go-sbot systemd process status - let sbot_status = SbotStatus::read()?; - - // we only want to try and interact with the sbot if it's active - if sbot_status.state == Some("active".to_string()) { - // retrieve latest go-sbot configuration parameters - let sbot_config = SbotConfig::read().ok(); - - let mut sbot_client = init_sbot_with_config(&sbot_config).await?; - - context.recipient_id = recipient_id; - - let local_id = sbot_client.whoami().await?; - context.id = Some(local_id); - } else { - // the sbot is not currently active; return a helpful message - context.flash_name = Some("warning".to_string()); - context.flash_msg = Some("The Sbot is currently inactive. As a result, private messages cannot be published. Visit the Scuttlebutt settings menu to start the Sbot and then try again".to_string()); - } - - context.sbot_status = Some(sbot_status); - - Ok(context) - } -} diff --git a/peach-web/src/routes/scuttlebutt.rs b/peach-web/src/routes/scuttlebutt.rs index 04d537c..bb80031 100644 --- a/peach-web/src/routes/scuttlebutt.rs +++ b/peach-web/src/routes/scuttlebutt.rs @@ -14,8 +14,10 @@ use rocket_dyn_templates::{tera::Context, Template}; use crate::{ context::{ - sbot, - sbot::{BlocksContext, FollowsContext, FriendsContext, PrivateContext, ProfileContext}, + scuttlebutt, + scuttlebutt::{ + BlocksContext, FollowsContext, FriendsContext, PrivateContext, ProfileContext, + }, }, routes::authentication::Authenticated, utils, @@ -74,7 +76,7 @@ pub async fn create_invite(invite: Form, _auth: Authenticated) -> Flash< let sbot_config = SbotConfig::read().ok(); // initialise sbot connection with ip:port and shscap from config file - match sbot::init_sbot_with_config(&sbot_config).await { + match scuttlebutt::init_sbot_with_config(&sbot_config).await { Ok(mut sbot_client) => { debug!("Generating Scuttlebutt invite code"); match sbot_client.invite_create(uses).await { @@ -176,7 +178,7 @@ pub async fn private_post(private: Form, _auth: Authenticated) -> Flash let recipients = vec![id.to_string(), recipient.to_string()]; // initialise sbot connection with ip:port and shscap from config file - match sbot::init_sbot_with_config(&sbot_config).await { + match scuttlebutt::init_sbot_with_config(&sbot_config).await { Ok(mut sbot_client) => { debug!("Publishing a new Scuttlebutt private message"); match sbot_client @@ -361,7 +363,7 @@ pub async fn publish(post: Form, _auth: Authenticated) -> Flash let sbot_config = SbotConfig::read().ok(); // initialise sbot connection with ip:port and shscap from config file - match sbot::init_sbot_with_config(&sbot_config).await { + match scuttlebutt::init_sbot_with_config(&sbot_config).await { Ok(mut sbot_client) => { debug!("Publishing new Scuttlebutt public post"); match sbot_client.publish_post(post_text).await { @@ -412,7 +414,7 @@ pub async fn follow(peer: Form, _auth: Authenticated) -> Flash { let sbot_config = SbotConfig::read().ok(); // initialise sbot connection with ip:port and shscap from config file - match sbot::init_sbot_with_config(&sbot_config).await { + match scuttlebutt::init_sbot_with_config(&sbot_config).await { Ok(mut sbot_client) => { debug!("Following Scuttlebutt peer"); match sbot_client.follow(public_key).await { @@ -463,7 +465,7 @@ pub async fn unfollow(peer: Form, _auth: Authenticated) -> Flash let sbot_config = SbotConfig::read().ok(); // initialise sbot connection with ip:port and shscap from config file - match sbot::init_sbot_with_config(&sbot_config).await { + match scuttlebutt::init_sbot_with_config(&sbot_config).await { Ok(mut sbot_client) => { debug!("Unfollowing Scuttlebutt peer"); match sbot_client.unfollow(public_key).await { @@ -514,7 +516,7 @@ pub async fn block(peer: Form, _auth: Authenticated) -> Flash { let sbot_config = SbotConfig::read().ok(); // initialise sbot connection with ip:port and shscap from config file - match sbot::init_sbot_with_config(&sbot_config).await { + match scuttlebutt::init_sbot_with_config(&sbot_config).await { Ok(mut sbot_client) => { debug!("Blocking Scuttlebutt peer"); match sbot_client.block(public_key).await { @@ -565,7 +567,7 @@ pub async fn unblock(peer: Form, _auth: Authenticated) -> Flash let sbot_config = SbotConfig::read().ok(); // initialise sbot connection with ip:port and shscap from config file - match sbot::init_sbot_with_config(&sbot_config).await { + match scuttlebutt::init_sbot_with_config(&sbot_config).await { Ok(mut sbot_client) => { debug!("Unblocking Scuttlebutt peer"); match sbot_client.unblock(public_key).await { @@ -705,7 +707,7 @@ pub async fn update_profile_post( let sbot_config = SbotConfig::read().ok(); // initialise sbot connection with ip:port and shscap from config file - match sbot::init_sbot_with_config(&sbot_config).await { + match scuttlebutt::init_sbot_with_config(&sbot_config).await { Ok(mut sbot_client) => { // track whether the name, description or image have been updated let mut name_updated: bool = false; diff --git a/peach-web/src/routes/status/scuttlebutt.rs b/peach-web/src/routes/status/scuttlebutt.rs index 2e9ff06..34aa61d 100644 --- a/peach-web/src/routes/status/scuttlebutt.rs +++ b/peach-web/src/routes/status/scuttlebutt.rs @@ -2,7 +2,7 @@ use rocket::{get, State}; use rocket_dyn_templates::Template; use crate::routes::authentication::Authenticated; -use crate::{context::sbot::StatusContext, RocketConfig}; +use crate::{context::scuttlebutt::StatusContext, RocketConfig}; // HELPERS AND ROUTES FOR /status/scuttlebutt @@ -25,7 +25,7 @@ pub async fn scuttlebutt_status(_auth: Authenticated, config: &State { + Err(_) => { let mut context = StatusContext::default(); // define back arrow url based on mode