peach-workspace/peach-web/src/routes/scuttlebutt/private.rs

132 lines
5.6 KiB
Rust

use maud::{html, Markup, PreEscaped};
use peach_lib::sbot::SbotStatus;
use rouille::{post_input, try_or_400, Request, Response};
use crate::{
templates,
utils::{
flash::{FlashRequest, FlashResponse},
sbot, theme,
},
};
// ROUTE: /scuttlebutt/private
fn public_key_input_template(ssb_id: &Option<String>) -> Markup {
match ssb_id {
Some(id) => {
html! { input type="text" id="publicKey" name="recipient" placeholder="@xYz...=.ed25519" value=(id); }
}
// render the input with autofocus if no ssb_id has been provided
None => {
html! { input type="text" id="publicKey" name="recipient" placeholder="@xYz...=.ed25519" autofocus; }
}
}
}
fn private_message_textarea_template(ssb_id: &Option<String>) -> Markup {
match ssb_id {
Some(_) => {
html! { textarea id="privatePost" class="center input message-input" name="text" title="Compose a private message" placeholder="Write a private message..." autofocus { "" } }
}
// render the textarea with autofocus if an ssb_id has been provided
None => {
html! { textarea id="privatePost" class="center input message-input" name="text" title="Compose a private message" placeholder="Write a private message..." { "" } }
}
}
}
/// Scuttlebutt private message template builder.
///
/// Render a form for publishing a provate message. The recipient input field
/// is populated with the provided ssb_id. If no recipient is provided, the
/// template autofocuses on the recipient input field.
pub fn build_template(request: &Request, ssb_id: Option<String>) -> PreEscaped<String> {
// check for flash cookies; will be (None, None) if no flash cookies are found
let (flash_name, flash_msg) = request.retrieve_flash();
let profile_template = match SbotStatus::read() {
// only render the private message elements if the sbot is active
Ok(status) if status.state == Some("active".to_string()) => {
// retrieve the local public key (set to blank if an error is returned)
let local_id = match sbot::get_local_id() {
Ok(id) => id,
Err(_) => "".to_string(),
};
html! {
(PreEscaped("<!-- SCUTTLEBUTT PRIVATE MESSAGE FORM -->"))
div class="card card-wide center" {
form id="sbotConfig" class="center" action="/scuttlebutt/private" method="post" {
div class="center" style="display: flex; flex-direction: column; margin-bottom: 1rem;" title="Public key (ID) of the peer being written to" {
label for="publicKey" class="label-small font-gray" {
"PUBLIC KEY"
}
(public_key_input_template(&ssb_id))
}
(PreEscaped("<!-- input for message contents -->"))
(private_message_textarea_template(&ssb_id))
(PreEscaped("<!-- hidden input field to pass the public key of the local peer -->"))
input type="hidden" id="localId" name="id" value=(local_id);
(PreEscaped("<!-- BUTTONS -->"))
input id="publish" class="button button-primary center" type="submit" style="margin-top: 1rem;" title="Publish private message to peer" value="Publish";
}
// render flash message if cookies were found in the request
@if let (Some(name), Some(msg)) = (flash_name, flash_msg) {
(PreEscaped("<!-- FLASH MESSAGE -->"))
(templates::flash::build_template(name, msg))
}
}
}
}
_ => templates::inactive::build_template("Private messaging is unavailable."),
};
let body = templates::nav::build_template(profile_template, "Profile", Some("/"));
// query the current theme so we can pass it into the base template builder
let theme = theme::get_theme();
templates::base::build_template(body, theme)
}
/// Publish a private message.
///
/// Parse the public key and private message text from the submitted form
/// and publish the message. Set a flash message communicating the outcome
/// of the publishing attempt and redirect to the private message page.
pub fn handle_form(request: &Request) -> Response {
// query the request body for form data
// return a 400 error if the admin_id field is missing
let data = try_or_400!(post_input!(request, {
id: String,
text: String,
recipient: String
}));
// 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![data.id, data.recipient];
let (flash_name, flash_msg) = match SbotStatus::read() {
Ok(status) if status.state == Some("active".to_string()) => {
match sbot::publish_private_msg(data.text, recipients) {
Ok(success_msg) => (
"flash_name=success".to_string(),
format!("flash_msg={}", success_msg),
),
Err(error_msg) => (
"flash_name=error".to_string(),
format!("flash_msg={}", error_msg),
),
}
}
_ => (
"flash_name=warning".to_string(),
"Private messaging is unavailable.".to_string(),
),
};
Response::redirect_303("/scuttlebutt/private").add_flash(flash_name, flash_msg)
}