From f6aab8998e9876094578b90040efde13d8675c33 Mon Sep 17 00:00:00 2001 From: Astro Date: Fri, 5 May 2023 21:47:21 +0200 Subject: [PATCH] main: implement nodeinfo 2.1 --- Cargo.toml | 2 ++ src/db.rs | 22 ++++++++++++++++++++++ src/main.rs | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index e4527e5..38de600 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,8 @@ name = "buzzrelay" version = "0.1.0" edition = "2021" +repository = "https://github.com/astro/buzzrelay" +homepage = "https://relay.fedi.buzz" [dependencies] axum = "0.6" diff --git a/src/db.rs b/src/db.rs index f249770..cb004ea 100644 --- a/src/db.rs +++ b/src/db.rs @@ -18,6 +18,8 @@ struct DatabaseInner { add_follow: Statement, del_follow: Statement, get_following_inboxes: Statement, + get_follows_count: Statement, + get_followers_count: Statement, } impl Database { @@ -46,6 +48,12 @@ impl Database { let get_following_inboxes = client.prepare("SELECT DISTINCT inbox FROM follows WHERE actor=$1") .await .unwrap(); + let get_follows_count = client.prepare("SELECT COUNT(id) FROM follows") + .await + .unwrap(); + let get_followers_count = client.prepare("SELECT COUNT(DISTINCT id) FROM follows") + .await + .unwrap(); Database { inner: Arc::new(DatabaseInner { @@ -53,6 +61,8 @@ impl Database { add_follow, del_follow, get_following_inboxes, + get_follows_count, + get_followers_count, }), } } @@ -85,4 +95,16 @@ impl Database { .map(|row| row.get(0)) ) } + + pub async fn get_follows_count(&self) -> Result { + let row = self.inner.client.query_one(&self.inner.get_follows_count, &[]) + .await?; + Ok(row.get(0)) + } + + pub async fn get_followers_count(&self) -> Result { + let row = self.inner.client.query_one(&self.inner.get_followers_count, &[]) + .await?; + Ok(row.get(0)) + } } diff --git a/src/main.rs b/src/main.rs index 59b7856..eac2e46 100644 --- a/src/main.rs +++ b/src/main.rs @@ -231,6 +231,43 @@ async fn post_relay( } } +async fn nodeinfo(axum::extract::State(state): axum::extract::State) -> Response { + let follows_count = state.database.get_follows_count() + .await + .unwrap_or(0); + let followers_count = state.database.get_followers_count() + .await + .unwrap_or(0); + + Json(json!({ + "version": "2.1", + "software": { + "name": env!("CARGO_PKG_NAME"), + "version": env!("CARGO_PKG_VERSION"), + "repository": env!("CARGO_PKG_REPOSITORY"), + "homepage": env!("CARGO_PKG_HOMEPAGE"), + }, + "protocols": ["activitypub"], + "services": { + "inbound": [], + "outbound": [] + }, + "openRegistrations": false, + "usage": { + "users": { + "total": followers_count, + "activeHalfyear": followers_count, + "activeMonth": followers_count, + }, + "localPosts": follows_count, + "localComments": 0 + }, + "metadata": { + "rust_version": env!("CARGO_PKG_RUST_VERSION"), + } + })).into_response() +} + #[tokio::main] async fn main() { exit_on_panic(); @@ -280,6 +317,7 @@ async fn main() { .route("/tag/:tag", get(get_tag_actor).post(post_tag_relay)) .route("/instance/:instance", get(get_instance_actor).post(post_instance_relay)) .route("/.well-known/webfinger", get(webfinger)) + .route("/.well-known/nodeinfo", get(nodeinfo)) .route("/metrics", get(|| async move { recorder.render().into_response() }))