diff --git a/peach-web/src/context/sbot.rs b/peach-web/src/context/sbot.rs index ac40d85..1af9eb4 100644 --- a/peach-web/src/context/sbot.rs +++ b/peach-web/src/context/sbot.rs @@ -469,3 +469,60 @@ impl ProfileContext { 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, +} + +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, + } + } + + 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?; + 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/router.rs b/peach-web/src/router.rs index 8e9eb75..ee43d47 100644 --- a/peach-web/src/router.rs +++ b/peach-web/src/router.rs @@ -81,6 +81,7 @@ pub fn mount_peachpub_routes(rocket: Rocket) -> Rocket { update_profile, update_profile_post, private, + private_post, follow, unfollow, block, diff --git a/peach-web/src/routes/scuttlebutt.rs b/peach-web/src/routes/scuttlebutt.rs index 462edcf..9ed2d49 100644 --- a/peach-web/src/routes/scuttlebutt.rs +++ b/peach-web/src/routes/scuttlebutt.rs @@ -8,7 +8,6 @@ use rocket::{ get, post, request::FlashMessage, response::{Flash, Redirect}, - serde::Serialize, uri, }; use rocket_dyn_templates::{tera::Context, Template}; @@ -16,7 +15,7 @@ use rocket_dyn_templates::{tera::Context, Template}; use crate::{ context::{ sbot, - sbot::{BlocksContext, FollowsContext, FriendsContext, ProfileContext}, + sbot::{BlocksContext, FollowsContext, FriendsContext, PrivateContext, ProfileContext}, }, routes::authentication::Authenticated, utils, @@ -102,46 +101,99 @@ pub async fn create_invite(invite: Form, _auth: Authenticated) -> Flash< // HELPERS AND ROUTES FOR /private -#[derive(Debug, Serialize)] -pub struct PrivateContext { - pub back: Option, - pub flash_name: Option, - pub flash_msg: Option, - pub title: Option, - pub theme: Option, -} +/// A private message composition and publication page. +#[get("/private")] +pub async fn private(flash: Option>, _auth: Authenticated) -> Template { + // build the private context object + let context = PrivateContext::build().await; -impl PrivateContext { - pub fn build() -> PrivateContext { - PrivateContext { - back: None, - flash_name: None, - flash_msg: None, - title: None, - theme: None, + match context { + // we were able to build the context without errors + Ok(mut context) => { + // check to see if there is a flash message to display + if let Some(flash) = flash { + // add flash message contents to the context object + context.flash_name = Some(flash.kind().to_string()); + context.flash_msg = Some(flash.message().to_string()); + }; + + Template::render("scuttlebutt/private", &context) + } + // an error occurred while building the context + Err(e) => { + // build the default context and pass along the error message + let mut context = PrivateContext::default(); + context.flash_name = Some("error".to_string()); + context.flash_msg = Some(e.to_string()); + + Template::render("scuttlebutt/private", &context) } } } -/// A private message composition and publication page. -#[get("/private")] -pub fn private(flash: Option, _auth: Authenticated) -> Template { - // retrieve current ui theme - let theme = utils::get_theme(); +#[derive(Debug, FromForm)] +pub struct Private { + pub id: String, + pub text: String, + pub recipient: String, +} - let mut context = PrivateContext::build(); - context.back = Some("/".to_string()); - context.title = Some("Private Messages".to_string()); - context.theme = Some(theme); +/// Publish a private message. +#[post("/private", data = "")] +pub async fn private_post(private: Form, _auth: Authenticated) -> Flash { + let url = uri!("/scuttlebutt", private); - // check to see if there is a flash message to display - if let Some(flash) = flash { - // add flash message contents to the context object - context.flash_name = Some(flash.kind().to_string()); - context.flash_msg = Some(flash.message().to_string()); + // retrieve go-sbot systemd process status + let sbot_status = match SbotStatus::read() { + Ok(status) => status, + Err(e) => { + return Flash::error( + Redirect::to(url), + format!("Failed to read sbot status: {}", e), + ) + } }; - Template::render("scuttlebutt/private", &context) + // 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 id = &private.id; + let text = &private.text; + let recipient = &private.recipient; + // now we need to add the local id to the recipients vector, + // otherwise the local id will not be able to read the message. + 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 { + Ok(mut sbot_client) => { + debug!("Publishing a new Scuttlebutt private message"); + match sbot_client + .publish_private(text.to_string(), recipients) + .await + { + Ok(_) => { + Flash::success(Redirect::to(url), format!("Published private message")) + } + Err(e) => Flash::error( + Redirect::to(url), + format!("Failed to publish private message: {}", e), + ), + } + } + Err(e) => Flash::error( + Redirect::to(url), + format!("Failed to initialise sbot: {}", e), + ), + } + } else { + return Flash::warning( + Redirect::to(url), + "The Sbot is currently inactive. As a result, new private message cannot be published. Visit the Scuttlebutt settings menu to start the Sbot and then try again", + ); + } } // HELPERS AND ROUTES FOR /search diff --git a/peach-web/templates/scuttlebutt/messages.html.tera b/peach-web/templates/scuttlebutt/messages.html.tera deleted file mode 100644 index d3da0af..0000000 --- a/peach-web/templates/scuttlebutt/messages.html.tera +++ /dev/null @@ -1,10 +0,0 @@ -{%- extends "nav" -%} -{%- block card %} - -
-
- - {% include "snippets/flash_message" %} -
-
-{%- endblock card -%} diff --git a/peach-web/templates/scuttlebutt/private.html.tera b/peach-web/templates/scuttlebutt/private.html.tera new file mode 100644 index 0000000..b626299 --- /dev/null +++ b/peach-web/templates/scuttlebutt/private.html.tera @@ -0,0 +1,22 @@ +{%- extends "nav" -%} +{%- block card %} + +
+
+
+
+ + +
+ + + + +
+ + +
+ + {% include "snippets/flash_message" %} +
+{%- endblock card -%}