diff --git a/src/main.rs b/src/main.rs index 382833c7..ba8ddfe7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,6 +79,7 @@ fn main() { routes::instance::configure, routes::instance::post_config, routes::instance::shared_inbox, + routes::instance::nodeinfo, routes::likes::create, routes::likes::create_auth, @@ -120,6 +121,7 @@ fn main() { routes::user::create, routes::well_known::host_meta, + routes::well_known::nodeinfo, routes::well_known::webfinger ]) .manage(init_pool()) diff --git a/src/models/comments.rs b/src/models/comments.rs index 042e0f67..691dfc36 100644 --- a/src/models/comments.rs +++ b/src/models/comments.rs @@ -3,7 +3,7 @@ use activitypub::{ object::{Note, properties::ObjectProperties} }; use chrono; -use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods}; +use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods, dsl::any}; use serde_json; use activity_pub::{ @@ -12,6 +12,7 @@ use activity_pub::{ object::Object }; use models::{ + instance::Instance, posts::Post, users::User }; @@ -110,6 +111,15 @@ impl Comment { act.object_props.set_id_string(format!("{}/activity", self.ap_url.clone().unwrap())).unwrap(); act } + + pub fn count_local(conn: &PgConnection) -> usize { + use schema::users; + let local_authors = users::table.filter(users::instance_id.eq(Instance::local_id(conn))).select(users::id); + comments::table.filter(comments::author_id.eq(any(local_authors))) + .load::(conn) + .expect("Couldn't load local comments") + .len() + } } impl Object for Comment { diff --git a/src/models/posts.rs b/src/models/posts.rs index 1ac4116f..ae244394 100644 --- a/src/models/posts.rs +++ b/src/models/posts.rs @@ -1,8 +1,7 @@ use activitypub::activity::Create; use activitystreams_types::object::{Article, properties::ObjectProperties}; use chrono::NaiveDateTime; -use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods, BelongingToDsl}; -use diesel::dsl::any; +use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods, BelongingToDsl, dsl::any}; use serde_json; use BASE_URL; @@ -13,6 +12,7 @@ use activity_pub::{ }; use models::{ blogs::Blog, + instance::Instance, likes::Like, post_authors::PostAuthor, reshares::Reshare, @@ -61,6 +61,17 @@ impl Post { .into_iter().nth(0) } + pub fn count_local(conn: &PgConnection) -> usize { + use schema::post_authors; + use schema::users; + let local_authors = users::table.filter(users::instance_id.eq(Instance::local_id(conn))).select(users::id); + let local_posts_id = post_authors::table.filter(post_authors::author_id.eq(any(local_authors))).select(post_authors::post_id); + posts::table.filter(posts::id.eq(any(local_posts_id))) + .load::(conn) + .expect("Couldn't load local posts") + .len() + } + pub fn find_by_slug(conn: &PgConnection, slug: String) -> Option { posts::table.filter(posts::slug.eq(slug)) .limit(1) diff --git a/src/models/users.rs b/src/models/users.rs index 64a1e6dd..1b58710f 100644 --- a/src/models/users.rs +++ b/src/models/users.rs @@ -119,6 +119,13 @@ impl User { .into_iter().nth(0) } + pub fn count_local(conn: &PgConnection) -> usize { + users::table.filter(users::instance_id.eq(Instance::local_id(conn))) + .load::(conn) + .expect("Couldn't load local users") + .len() + } + pub fn find_by_email(conn: &PgConnection, email: String) -> Option { users::table.filter(users::email.eq(email)) .limit(1) diff --git a/src/routes/instance.rs b/src/routes/instance.rs index 628105bb..2142ad15 100644 --- a/src/routes/instance.rs +++ b/src/routes/instance.rs @@ -1,11 +1,12 @@ use rocket::{request::Form, response::Redirect}; -use rocket_contrib::Template; +use rocket_contrib::{Json, Template}; use serde_json; use BASE_URL; use activity_pub::inbox::Inbox; use db_conn::DbConn; use models::{ + comments::Comment, posts::Post, users::User, instance::* @@ -75,3 +76,28 @@ fn shared_inbox(conn: DbConn, data: String) -> String { instance.received(&*conn, act); String::from("") } + +#[get("/nodeinfo")] +fn nodeinfo(conn: DbConn) -> Json { + Json(json!({ + "version": "2.0", + "software": { + "name": "Plume", + "version": "0.1.0" + }, + "protocols": ["activitypub"], + "services": { + "inbound": [], + "outbound": [] + }, + "openRegistrations": true, + "usage": { + "users": { + "total": User::count_local(&*conn) + }, + "localPosts": Post::count_local(&*conn), + "localComments": Comment::count_local(&*conn) + }, + "metadata": {} + })) +} diff --git a/src/routes/well_known.rs b/src/routes/well_known.rs index e0cdae50..15b3ad2a 100644 --- a/src/routes/well_known.rs +++ b/src/routes/well_known.rs @@ -6,6 +6,18 @@ use activity_pub::{ap_url, webfinger::Webfinger}; use db_conn::DbConn; use models::{blogs::Blog, users::User}; +#[get("/.well-known/nodeinfo")] +fn nodeinfo() -> Content { + Content(ContentType::new("application", "jrd+json"), json!({ + "links": [ + { + "rel": "http://nodeinfo.diaspora.software/ns/schema/2.0", + "href": ap_url(format!("{domain}/nodeinfo", domain = BASE_URL.as_str())) + } + ] + }).to_string()) +} + #[get("/.well-known/host-meta", format = "application/xml")] fn host_meta() -> String { format!(r#"