use axum::extract::State; use axum::Json; use magnetar_common::config::MagnetarConfig; use magnetar_core::web_model::rel::{RelNodeInfo20, RelNodeInfo21}; use magnetar_core::web_model::Rel; use magnetar_nodeinfo::version_1_0::{ NodeInfo10Services, NodeInfo10Software, NodeInfo10Usage, NodeInfo10UsageUsers, }; use magnetar_nodeinfo::version_2_0::NodeInfo20; use magnetar_nodeinfo::version_2_1::{NodeInfo21, NodeInfo21Software}; use serde::Serialize; use serde_json::{json, Value}; use std::collections::{HashMap, HashSet}; const NODEINFO_PATH: &str = "/nodeinfo"; #[derive(Clone, Debug, Serialize)] pub struct NodeInfoLink { rel: &'static str, href: String, } pub async fn handle_nodeinfo(State(config): State<&'static MagnetarConfig>) -> Json { let links = vec![ NodeInfoLink { href: format!( "{}://{}/nodeinfo/2.0", config.networking.protocol, config.networking.host ), rel: RelNodeInfo20.rel(), }, NodeInfoLink { href: format!( "{}://{}/nodeinfo/2.1", config.networking.protocol, config.networking.host ), rel: RelNodeInfo21.rel(), }, ]; let links_serialized = serde_json::to_value(links).unwrap(); Json(json!({ "links": links_serialized })) } pub async fn handle_nodeinfo_21(State(config): State<&'static MagnetarConfig>) -> Json { Json(NodeInfo21 { software: NodeInfo21Software { name: config.branding.name.clone(), version: config.branding.version.clone(), homepage: Some(config.branding.homepage.clone()), repository: Some(config.branding.repository.clone()), }, protocols: HashSet::from(["activitypub".to_owned()]), services: NodeInfo10Services { inbound: HashSet::new(), outbound: HashSet::new(), }, open_registrations: false, usage: NodeInfo10Usage { users: NodeInfo10UsageUsers { total: Some(0), active_halfyear: Some(0), active_month: Some(0), }, local_posts: Some(0), local_comments: Some(0), }, metadata: HashMap::new(), }) } pub async fn handle_nodeinfo_20(State(config): State<&'static MagnetarConfig>) -> Json { Json(NodeInfo20 { software: NodeInfo10Software { name: config.branding.name.clone(), version: config.branding.version.clone(), }, protocols: HashSet::from(["activitypub".to_owned()]), services: NodeInfo10Services { inbound: HashSet::new(), outbound: HashSet::new(), }, open_registrations: false, usage: NodeInfo10Usage { users: NodeInfo10UsageUsers { total: Some(0), active_halfyear: Some(0), active_month: Some(0), }, local_posts: Some(0), local_comments: None, }, metadata: HashMap::new(), }) } #[cfg(test)] mod tests { use axum::extract::State; use magnetar_common::config::MagnetarConfig; #[tokio::test] async fn test_nodeinfo() { std::env::set_var("MAG_C_HOST", "nattyarch.local"); std::env::set_var("MAG_C_DATABASE_URL", "dummy"); let config = MagnetarConfig::default(); let config_ref = Box::leak(Box::new(config)); let nodeinfo = crate::nodeinfo::handle_nodeinfo(State(config_ref)).await; println!("{:#?}", nodeinfo); } }