mod actor; pub mod articles; mod comments; mod db; pub mod digester; pub mod federate; mod inbox; pub mod keys; mod types; mod util; mod webfinger; use self::types::ActorExt; use activitystreams::{base::AnyBase, prelude::BaseExt}; use anyhow::anyhow; use axum::{ routing::{get, post, Router}, Extension, }; use log::warn; use once_cell::sync::Lazy; use reqwest::{Client, ClientBuilder}; use sqlx::SqlitePool; use uuid::Uuid; pub static DOMAIN: Lazy = Lazy::new(|| std::env::var("DOMAIN").unwrap_or("shadowfacts.net".to_owned())); pub fn router(pool: SqlitePool) -> Router { Router::new() .route("/.well-known/webfinger", get(webfinger::handle)) .route("/ap/actor", get(actor::handle)) .route("/ap/actor/followers", get(actor::handle_followers)) .layer(Extension(pool)) .route("/ap/inbox", post(inbox::handle)) .route("/comments", get(comments::handle)) .route("/interact", post(webfinger::handle_interact)) } pub fn gen_ap_id() -> String { format!("https://{}/ap/{}", *DOMAIN, Uuid::new_v4()) } pub fn gen_converation_id() -> String { format!("https://{}/ap/conversation/{}", *DOMAIN, Uuid::new_v4()) } pub fn conversation_context() -> AnyBase { AnyBase::from_arbitrary_json(serde_json::json!({ "ostatus": "http://ostatus.org#", "conversation": "ostatus:conversation" })) .unwrap() } const ACCEPT_INVALID_CERTS: bool = cfg!(debug_assertions); pub static CLIENT: Lazy = Lazy::new(|| { if ACCEPT_INVALID_CERTS { warn!("Accepting invalid certs for ActivityPub request"); } ClientBuilder::new() .danger_accept_invalid_certs(ACCEPT_INVALID_CERTS) .build() .expect("couldn't build reqwest client") }); pub async fn get_actor(id: &str, pool: &SqlitePool) -> anyhow::Result { if let Some(actor) = db::fetch_cached_actor(id, pool).await { let actor = serde_json::from_str::(&actor.actor_object)?; Ok(actor) } else { fetch_actor(id, pool).await } } pub async fn fetch_actor(id: &str, pool: &SqlitePool) -> anyhow::Result { let actor = federate::fetch_actor(id).await?; if actor.id_unchecked().unwrap().as_str() != id { return Err(anyhow!("got mismatched id for actor at {}", id)); } db::add_cached_actor(&actor, pool).await?; Ok(actor) }