1 use actix_web::{error::ErrorBadRequest, web, Error, HttpResponse, Result};
3 use lemmy_api_common::context::LemmyContext;
4 use lemmy_db_schema::source::local_site::RegistrationMode;
5 use lemmy_db_views::structs::SiteView;
6 use lemmy_utils::{error::LemmyError, version};
7 use serde::{Deserialize, Serialize};
10 pub fn config(cfg: &mut web::ServiceConfig) {
12 .route("/nodeinfo/2.0.json", web::get().to(node_info))
13 .route("/.well-known/nodeinfo", web::get().to(node_info_well_known));
16 async fn node_info_well_known(
17 context: web::Data<LemmyContext>,
18 ) -> Result<HttpResponse, LemmyError> {
19 let node_info = NodeInfoWellKnown {
20 links: vec![NodeInfoWellKnownLinks {
21 rel: Url::parse("http://nodeinfo.diaspora.software/ns/schema/2.0")?,
22 href: Url::parse(&format!(
23 "{}/nodeinfo/2.0.json",
24 &context.settings().get_protocol_and_hostname(),
28 Ok(HttpResponse::Ok().json(node_info))
31 async fn node_info(context: web::Data<LemmyContext>) -> Result<HttpResponse, Error> {
32 let site_view = SiteView::read_local(context.pool())
34 .map_err(|_| ErrorBadRequest(LemmyError::from(anyhow!("not_found"))))?;
36 let protocols = if site_view.local_site.federation_enabled {
37 vec!["activitypub".to_string()]
41 let open_registrations = site_view.local_site.registration_mode == RegistrationMode::Open;
43 version: "2.0".to_string(),
44 software: NodeInfoSoftware {
45 name: "lemmy".to_string(),
46 version: version::VERSION.to_string(),
49 usage: NodeInfoUsage {
50 users: NodeInfoUsers {
51 total: site_view.counts.users,
52 active_halfyear: site_view.counts.users_active_half_year,
53 active_month: site_view.counts.users_active_month,
55 local_posts: site_view.counts.posts,
56 local_comments: site_view.counts.comments,
61 Ok(HttpResponse::Ok().json(json))
64 #[derive(Serialize, Deserialize, Debug)]
65 struct NodeInfoWellKnown {
66 pub links: Vec<NodeInfoWellKnownLinks>,
69 #[derive(Serialize, Deserialize, Debug)]
70 struct NodeInfoWellKnownLinks {
75 #[derive(Serialize, Deserialize, Debug)]
76 #[serde(rename_all = "camelCase")]
79 pub software: NodeInfoSoftware,
80 pub protocols: Vec<String>,
81 pub usage: NodeInfoUsage,
82 pub open_registrations: bool,
85 #[derive(Serialize, Deserialize, Debug)]
86 struct NodeInfoSoftware {
91 #[derive(Serialize, Deserialize, Debug)]
92 #[serde(rename_all = "camelCase")]
93 struct NodeInfoUsage {
94 pub users: NodeInfoUsers,
96 pub local_comments: i64,
99 #[derive(Serialize, Deserialize, Debug)]
100 #[serde(rename_all = "camelCase")]
101 struct NodeInfoUsers {
103 pub active_halfyear: i64,
104 pub active_month: i64,