add private message publishing

This commit is contained in:
glyph 2022-03-02 11:57:10 +02:00
parent 020d18731b
commit 6cba477f15
5 changed files with 165 additions and 43 deletions

View File

@ -469,3 +469,60 @@ impl ProfileContext {
Ok(context)
}
}
#[derive(Debug, Serialize)]
pub struct PrivateContext {
pub back: Option<String>,
pub flash_name: Option<String>,
pub flash_msg: Option<String>,
pub title: Option<String>,
pub theme: Option<String>,
pub sbot_config: Option<SbotConfig>,
pub sbot_status: Option<SbotStatus>,
// local peer id (whoami)
pub id: Option<String>,
}
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<Self, PeachWebError> {
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)
}
}

View File

@ -81,6 +81,7 @@ pub fn mount_peachpub_routes(rocket: Rocket<Build>) -> Rocket<Build> {
update_profile,
update_profile_post,
private,
private_post,
follow,
unfollow,
block,

View File

@ -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<Invite>, _auth: Authenticated) -> Flash<
// HELPERS AND ROUTES FOR /private
#[derive(Debug, Serialize)]
pub struct PrivateContext {
pub back: Option<String>,
pub flash_name: Option<String>,
pub flash_msg: Option<String>,
pub title: Option<String>,
pub theme: Option<String>,
}
/// A private message composition and publication page.
#[get("/private")]
pub async fn private(flash: Option<FlashMessage<'_>>, _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<FlashMessage>, _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 = "<private>")]
pub async fn private_post(private: Form<Private>, _auth: Authenticated) -> Flash<Redirect> {
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

View File

@ -1,10 +0,0 @@
{%- extends "nav" -%}
{%- block card %}
<!-- SCUTTLEBUTT MESSAGES -->
<div class="card center">
<div class="capsule capsule-container border-ssb">
<!-- FLASH MESSAGE -->
{% include "snippets/flash_message" %}
</div>
</div>
{%- endblock card -%}

View File

@ -0,0 +1,22 @@
{%- extends "nav" -%}
{%- block card %}
<!-- SCUTTLEBUTT PRIVATE MESSAGE FORM -->
<div class="card center">
<form id="sbotConfig" class="center" action="/scuttlebutt/private" method="post">
<div class="capsule capsule-profile border-ssb" title="Scuttlebutt account profile information">
<div class="center" style="display: flex; flex-direction: column; margin-bottom: 2rem;" title="Public key (ID) of the peer being written to">
<label for="publicKey" class="label-small font-gray">PUBLIC KEY</label>
<input type="text" id="publicKey" name="recipient" placeholder="@xYz...=.ed25519" autofocus>
</div>
<!-- input for message contents -->
<textarea id="privatePost" class="center input message-input" name="text" title="Compose a private message" placeholder="Write a private message..."></textarea>
<!-- hidden input field to pass the public key of the local peer -->
<input type="hidden" id="localId" name="id" value="{{ id }}">
</div>
<!-- BUTTONS -->
<input id="publish" class="button button-primary center" type="submit" style="margin-top: 1rem;" title="Publish private message to peer" value="Publish">
</form>
<!-- FLASH MESSAGE -->
{% include "snippets/flash_message" %}
</div>
{%- endblock card -%}