- Remove `whoami` from managed state and instead call it when required

- Replace `Context::insert()` with `context!` macro
- Simplify `src/routes.rs` by moving composite follow / unfollow
  functions into `src/sbot.rs`
This commit is contained in:
glyph 2022-08-16 17:12:18 +01:00
parent ebc6fea762
commit 8aef6fb0b9
3 changed files with 75 additions and 71 deletions

View File

@ -110,7 +110,7 @@ mod utils;
use std::env; use std::env;
use async_std::channel; use async_std::channel;
use log::info; use log::{info, warn};
use rocket::{ use rocket::{
fairing::AdHoc, fairing::AdHoc,
fs::{relative, FileServer}, fs::{relative, FileServer},
@ -119,18 +119,17 @@ use rocket::{
use rocket_dyn_templates::Template; use rocket_dyn_templates::Template;
use xdg::BaseDirectories; use xdg::BaseDirectories;
use crate::{db::Database, routes::*, sbot::WhoAmI, task_loop::Task}; use crate::{db::Database, routes::*, task_loop::Task};
#[launch] #[launch]
async fn rocket() -> _ { async fn rocket() -> _ {
env_logger::init(); env_logger::init();
// Retrieve and store the public key of the local sbot. // Retrieve and store the public key of the local sbot.
let public_key: String = sbot::whoami() match sbot::whoami().await {
.await Ok(id) => info!("Public key of the local sbot instance: {}", id),
.expect("whoami rpc call failed. please ensure the sbot is running before trying again"); Err(e) => warn!("Failed to retrieve the public key of the local sbot instance (`whoami` RPC call failed). Please ensure the sbot is running before trying again. Error details: {}", e)
info!("Public key of the local sbot instance: {}", public_key); }
let whoami = WhoAmI(public_key);
// Create the key-value database. // Create the key-value database.
let xdg_dirs = BaseDirectories::with_prefix("lykin").unwrap(); let xdg_dirs = BaseDirectories::with_prefix("lykin").unwrap();
@ -151,7 +150,6 @@ async fn rocket() -> _ {
info!("Launching web server"); info!("Launching web server");
rocket::build() rocket::build()
.manage(db) .manage(db)
.manage(whoami)
.manage(tx) .manage(tx)
.mount( .mount(
"/", "/",

View File

@ -3,13 +3,13 @@
use async_std::channel::Sender; use async_std::channel::Sender;
use log::{info, warn}; use log::{info, warn};
use rocket::{form::Form, get, post, response::Redirect, uri, FromForm, State}; use rocket::{form::Form, get, post, response::Redirect, uri, FromForm, State};
use rocket_dyn_templates::{tera::Context, Template}; use rocket_dyn_templates::{context, Template};
use crate::{ use crate::{
db::{Database, Peer}, db::{Database, Peer},
sbot, sbot,
task_loop::Task, task_loop::Task,
utils, WhoAmI, utils,
}; };
#[derive(FromForm)] #[derive(FromForm)]
@ -26,10 +26,7 @@ pub async fn home(db: &State<Database>) -> Template {
peers_unread.push((peer, unread_count.to_string())); peers_unread.push((peer, unread_count.to_string()));
} }
let mut context = Context::new(); Template::render("base", context! { peers: &peers_unread })
context.insert("peers", &peers_unread);
Template::render("base", &context.into_json())
} }
#[get("/posts/<public_key>/<msg_id>/delete")] #[get("/posts/<public_key>/<msg_id>/delete")]
@ -61,12 +58,14 @@ pub async fn posts(db: &State<Database>, public_key: &str) -> Template {
let posts = db.get_posts(public_key).unwrap(); let posts = db.get_posts(public_key).unwrap();
let mut context = Context::new(); // Define context data to be rendered in the template.
context.insert("selected_peer", &public_key); let context = context! {
context.insert("peers", &peers_unread); selected_peer: &public_key,
context.insert("posts", &posts); peers: &peers_unread,
posts: &posts
};
Template::render("base", &context.into_json()) Template::render("base", context)
} }
#[get("/posts/<public_key>/<msg_id>")] #[get("/posts/<public_key>/<msg_id>")]
@ -81,23 +80,18 @@ pub async fn post(db: &State<Database>, public_key: &str, msg_id: &str) -> Templ
let posts = db.get_posts(public_key).unwrap(); let posts = db.get_posts(public_key).unwrap();
let post = db.get_post(public_key, msg_id).unwrap(); let post = db.get_post(public_key, msg_id).unwrap();
let mut context = Context::new(); let context = context! {
context.insert("peers", &peers_unread); peers: &peers_unread,
context.insert("selected_peer", &public_key); selected_peer: &public_key,
context.insert( selected_peer_encoded: &uri_encode::encode_uri_component(public_key),
"selected_peer_encoded", selected_post: &msg_id,
&uri_encode::encode_uri_component(public_key), selected_post_encoded: &uri_encode::encode_uri_component(msg_id),
); posts: &posts,
context.insert("selected_post", &msg_id); post: &post,
context.insert( post_is_selected: &true
"selected_post_encoded", };
&uri_encode::encode_uri_component(msg_id),
);
context.insert("posts", &posts);
context.insert("post", &post);
context.insert("post_is_selected", &true);
Template::render("base", &context.into_json()) Template::render("base", context)
} }
#[get("/posts/<public_key>/<msg_id>/read")] #[get("/posts/<public_key>/<msg_id>/read")]
@ -157,7 +151,6 @@ pub async fn download_latest_posts(db: &State<Database>, tx: &State<Sender<Task>
#[post("/subscribe", data = "<peer>")] #[post("/subscribe", data = "<peer>")]
pub async fn subscribe_form( pub async fn subscribe_form(
db: &State<Database>, db: &State<Database>,
whoami: &State<WhoAmI>,
tx: &State<Sender<Task>>, tx: &State<Sender<Task>>,
peer: Form<PeerForm>, peer: Form<PeerForm>,
) -> Redirect { ) -> Redirect {
@ -182,21 +175,7 @@ pub async fn subscribe_form(
// Follow the peer if our local instance is not already following. // Follow the peer if our local instance is not already following.
if db.add_peer(peer_info).is_ok() { if db.add_peer(peer_info).is_ok() {
info!("Added {} to 'peers' database tree", &peer.public_key); info!("Added {} to 'peers' database tree", &peer.public_key);
match sbot::is_following(&whoami.0, &peer.public_key).await { sbot::follow_if_not_following(&peer.public_key).await;
Ok(status) if status.as_str() == "false" => {
match sbot::follow_peer(&peer.public_key).await {
Ok(_) => info!("Followed peer {}", &peer.public_key),
Err(e) => warn!("Failed to follow peer {}: {}", &peer.public_key, e),
}
}
Ok(status) if status.as_str() == "true" => {
info!(
"Already following peer {}. No further action taken",
&peer.public_key
)
}
_ => (),
}
let peer_id = peer.public_key.to_string(); let peer_id = peer.public_key.to_string();
// Fetch all root posts authored by the peer we're subscribing // Fetch all root posts authored by the peer we're subscribing
@ -216,11 +195,7 @@ pub async fn subscribe_form(
} }
#[post("/unsubscribe", data = "<peer>")] #[post("/unsubscribe", data = "<peer>")]
pub async fn unsubscribe_form( pub async fn unsubscribe_form(db: &State<Database>, peer: Form<PeerForm>) -> Redirect {
db: &State<Database>,
whoami: &State<WhoAmI>,
peer: Form<PeerForm>,
) -> Redirect {
info!("Unsubscribing from peer {}", &peer.public_key); info!("Unsubscribing from peer {}", &peer.public_key);
if let Err(e) = utils::validate_public_key(&peer.public_key) { if let Err(e) = utils::validate_public_key(&peer.public_key) {
@ -232,18 +207,7 @@ pub async fn unsubscribe_form(
"Removed peer {} from 'peers' database tree", "Removed peer {} from 'peers' database tree",
&peer.public_key &peer.public_key
); );
match sbot::is_following(&whoami.0, &peer.public_key).await { sbot::unfollow_if_following(&peer.public_key).await;
Ok(status) if status.as_str() == "true" => {
info!("Unfollowing peer {}", &peer.public_key);
match sbot::unfollow_peer(&peer.public_key).await {
Ok(_) => {
info!("Unfollowed peer {}", &peer.public_key);
}
Err(e) => warn!("Failed to unfollow peer {}: {}", &peer.public_key, e),
}
}
_ => (),
}
} else { } else {
warn!( warn!(
"Failed to remove peer {} from 'peers' database tree", "Failed to remove peer {} from 'peers' database tree",

View File

@ -13,10 +13,52 @@ use golgi::{
use log::{debug, info, warn}; use log::{debug, info, warn};
use serde_json::value::Value; use serde_json::value::Value;
use crate::db::Post; use crate::{db::Post, sbot};
/// The public key of the local sbot instance. /// Check the follow status of a remote peer and follow them if not already
pub struct WhoAmI(pub String); /// following.
pub async fn follow_if_not_following(remote_peer: &str) {
if let Ok(whoami) = sbot::whoami().await {
match sbot::is_following(&whoami, remote_peer).await {
Ok(status) if status.as_str() == "false" => {
match sbot::follow_peer(remote_peer).await {
Ok(_) => info!("Followed peer {}", &remote_peer),
Err(e) => warn!("Failed to follow peer {}: {}", &remote_peer, e),
}
}
Ok(status) if status.as_str() == "true" => {
info!(
"Already following peer {}. No further action taken",
&remote_peer
)
}
_ => (),
}
} else {
warn!("Received an error during `whoami` RPC call. Please ensure the go-sbot is running and try again")
}
}
/// Check the follow status of a remote peer and unfollow them if already
/// following.
pub async fn unfollow_if_following(remote_peer: &str) {
if let Ok(whoami) = sbot::whoami().await {
match sbot::is_following(&whoami, remote_peer).await {
Ok(status) if status.as_str() == "true" => {
info!("Unfollowing peer {}", &remote_peer);
match sbot::unfollow_peer(remote_peer).await {
Ok(_) => {
info!("Unfollowed peer {}", &remote_peer);
}
Err(e) => warn!("Failed to unfollow peer {}: {}", &remote_peer, e),
}
}
_ => (),
}
} else {
warn!("Received an error during `whoami` RPC call. Please ensure the go-sbot is running and try again")
}
}
/// Initialise a connection to a Scuttlebutt server. /// Initialise a connection to a Scuttlebutt server.
async fn init_sbot() -> Result<Sbot, String> { async fn init_sbot() -> Result<Sbot, String> {