diff options
author | Felix Ableitner <me@nutomic.com> | 2020-03-11 12:29:10 +0100 |
---|---|---|
committer | Felix Ableitner <me@nutomic.com> | 2020-03-11 12:29:10 +0100 |
commit | 18be8b10f583e89b575978b00a5191bc8ab1b4bc (patch) | |
tree | 22eb8a47851e7d7ec3a733d44fb0dcfba002bf46 /server/src/apub | |
parent | 34a827a27012cecc3675b502cdf610204e6bd992 (diff) |
improved community federation (wip)
Diffstat (limited to 'server/src/apub')
-rw-r--r-- | server/src/apub/community.rs | 47 | ||||
-rw-r--r-- | server/src/apub/group_wrapper.rs | 91 | ||||
-rw-r--r-- | server/src/apub/mod.rs | 1 | ||||
-rw-r--r-- | server/src/apub/puller.rs | 31 |
4 files changed, 111 insertions, 59 deletions
diff --git a/server/src/apub/community.rs b/server/src/apub/community.rs index ee3edc1f..2a16eeae 100644 --- a/server/src/apub/community.rs +++ b/server/src/apub/community.rs @@ -1,14 +1,14 @@ +use crate::apub::group_wrapper::GroupHelper; use crate::apub::make_apub_endpoint; use crate::db::community::Community; use crate::db::community_view::CommunityFollowerView; use crate::db::establish_unpooled_connection; -use crate::to_datetime_utc; use activitypub::{actor::Group, collection::UnorderedCollection, context}; use actix_web::body::Body; use actix_web::web::Path; use actix_web::HttpResponse; use serde::Deserialize; -use serde_json::json; +use serde_json::{Value}; impl Community { pub fn as_group(&self) -> Group { @@ -16,42 +16,18 @@ impl Community { let mut group = Group::default(); - // TODO: why the hell is this code so awkward? group.object_props.set_context_object(context()).ok(); - // TODO: id really needs to be a url - group.object_props.set_id_string(self.id.to_string()).ok(); - group - .object_props - .set_name_string(self.title.to_owned()) - .ok(); - group - .object_props - .set_published_utctime(to_datetime_utc(self.published)) - .ok(); - group.object_props.attributed_to = Some(json!(self.creator_id.to_string())); - if let Some(updated) = self.updated { - group - .object_props - .set_updated_utctime(to_datetime_utc(updated)) - .ok(); - } + Group::set_id(&mut group, self.id); + Group::set_title(&mut group, &self.title); + Group::set_published(&mut group, self.published); + Group::set_updated(&mut group, self.updated); + Group::set_creator_id(&mut group, self.creator_id); - if let Some(description) = &self.description { - group.object_props.summary = Some(json!(description.to_string())); - } + Group::set_description(&mut group, &self.description); - group - .ap_actor_props - .set_inbox_string(format!("{}/inbox", &base_url)) - .ok(); - group - .ap_actor_props - .set_outbox_string(format!("{}/outbox", &base_url)) - .ok(); - group - .ap_actor_props - .set_followers_string(format!("{}/followers", &base_url)) - .ok(); + group.ap_actor_props.inbox = Value::String(format!("{}/inbox", &base_url)); + group.ap_actor_props.outbox = Value::String(format!("{}/outbox", &base_url)); + group.ap_actor_props.followers = Some(Value::String(format!("{}/followers", &base_url))); group } @@ -65,7 +41,6 @@ impl Community { let connection = establish_unpooled_connection(); //As we are an object, we validated that the community id was valid - // TODO: add a method that only returns count for better performance let community_followers = CommunityFollowerView::for_community(&connection, self.id).unwrap(); collection diff --git a/server/src/apub/group_wrapper.rs b/server/src/apub/group_wrapper.rs new file mode 100644 index 00000000..dd140df2 --- /dev/null +++ b/server/src/apub/group_wrapper.rs @@ -0,0 +1,91 @@ +use crate::to_datetime_utc; +use activitypub::actor::Group; +use chrono::{DateTime, NaiveDateTime}; +use failure::Error; +use serde_json::Value; + +pub trait GroupHelper { + // TODO: id really needs to be a url + fn set_id(group: &mut Group, id: i32); + fn get_id(group: &Group) -> Result<i32, Error>; + + fn set_title(group: &mut Group, title: &str); + fn get_title(group: &Group) -> Result<String, Error>; + + fn set_description(group: &mut Group, description: &Option<String>); + fn get_description(group: &Group) -> Result<Option<String>, Error>; + + // TODO: also needs to be changed to url + fn set_creator_id(group: &mut Group, creator_id: i32); + fn get_creator_id(group: &Group) -> Result<i32, Error>; + + fn set_published(group: &mut Group, published: NaiveDateTime); + fn get_published(group: &Group) -> Result<NaiveDateTime, Error>; + + fn set_updated(group: &mut Group, updated: Option<NaiveDateTime>); + fn get_updated(group: &Group) -> Result<Option<NaiveDateTime>, Error>; +} + +// TODO: something is crashing and not reporting the error +impl GroupHelper for Group { + fn set_id(group: &mut Group, id: i32) { + group.object_props.id = Some(Value::String(id.to_string())); + } + fn get_id(group: &Group) -> Result<i32, Error> { + Ok(get_string_value(group.clone().object_props.id).parse::<i32>()?) + } + + fn set_title(group: &mut Group, title: &str) { + group.object_props.name = Some(Value::String(title.to_string())); + } + fn get_title(group: &Group) -> Result<String, Error> { + Ok(get_string_value(group.to_owned().object_props.name)) + } + + fn set_description(group: &mut Group, description: &Option<String>) { + group.object_props.summary = description.as_ref().map(|d| Value::String(d.to_string())); + } + fn get_description(group: &Group) -> Result<Option<String>, Error> { + Ok(get_string_value_opt(group.to_owned().object_props.summary)) + } + + fn set_creator_id(group: &mut Group, creator_id: i32) { + group.object_props.attributed_to = Some(Value::String(creator_id.to_string())); + } + fn get_creator_id(group: &Group) -> Result<i32, Error> { + Ok(get_string_value(group.clone().object_props.attributed_to).parse::<i32>()?) + } + + fn set_published(group: &mut Group, published: NaiveDateTime) { + group.object_props.published = Some(Value::String(to_datetime_utc(published).to_string())) + } + fn get_published(group: &Group) -> Result<NaiveDateTime, Error> { + let str = get_string_value(group.to_owned().object_props.published); + // TODO: no idea which date format + let date = DateTime::parse_from_rfc2822(&str)?; + Ok(date.naive_local()) + } + + fn set_updated(group: &mut Group, updated: Option<NaiveDateTime>) { + group.object_props.updated = updated.map(|u| Value::String(u.to_string())); + } + fn get_updated(group: &Group) -> Result<Option<NaiveDateTime>, Error> { + let str = get_string_value_opt(group.to_owned().object_props.updated); + match str { + Some(s) => Ok(Some(DateTime::parse_from_rfc2822(&s)?.naive_local())), + None => Ok(None), + } + } +} + +fn get_string_value_opt(value: Option<Value>) -> Option<String> { + value + .as_ref() + .map(Value::as_str) + .flatten() + .map(str::to_string) +} + +fn get_string_value(value: Option<Value>) -> String { + get_string_value_opt(value).unwrap() +} diff --git a/server/src/apub/mod.rs b/server/src/apub/mod.rs index 9bac64a6..31dc3ced 100644 --- a/server/src/apub/mod.rs +++ b/server/src/apub/mod.rs @@ -1,4 +1,5 @@ pub mod community; +pub mod group_wrapper; pub mod post; pub mod puller; pub mod user; diff --git a/server/src/apub/puller.rs b/server/src/apub/puller.rs index b6877982..ce9469fc 100644 --- a/server/src/apub/puller.rs +++ b/server/src/apub/puller.rs @@ -3,11 +3,10 @@ extern crate reqwest; use self::reqwest::Error; use crate::api::community::{GetCommunityResponse, ListCommunitiesResponse}; use crate::api::post::GetPosts; +use crate::apub::group_wrapper::GroupHelper; use crate::db::community_view::CommunityView; -use crate::naive_now; use crate::settings::Settings; use activitypub::actor::Group; -use serde_json::Value; // TODO: right now all of the data is requested on demand, for production we will need to store // things in the local database to not ruin the performance @@ -43,22 +42,20 @@ pub fn get_remote_community(identifier: String) -> Result<GetCommunityResponse, // TODO: looks like a bunch of data is missing from the activitypub response // TODO: i dont think simple numeric ids are going to work, we probably need something like uuids - // TODO: why are the Group properties not typed? Ok(GetCommunityResponse { moderators: vec![], admins: vec![], community: CommunityView { - // TODO: why does the stupid library have everything stored as value without working autocomplete for methods??? // TODO: we need to merge id and name into a single thing (stuff like @user@instance.com) - id: get_string_value(community.object_props.id).parse::<i32>()?, + id: Group::get_id(&community)?, name, - title: get_string_value(community.object_props.name), - description: get_string_value_opt(community.object_props.summary), + title: Group::get_title(&community)?, + description: Group::get_description(&community)?, category_id: -1, - creator_id: get_string_value(community.object_props.attributed_to).parse::<i32>()?, + creator_id: Group::get_creator_id(&community)?, removed: false, - published: naive_now(), // TODO: need to handle time conversion (or handle it in apub lib) - updated: Some(naive_now()), // TODO: community.object_props.updated + published: Group::get_published(&community)?, + updated: Group::get_updated(&community)?, deleted: false, nsfw: false, creator_name: "".to_string(), @@ -69,24 +66,12 @@ pub fn get_remote_community(identifier: String) -> Result<GetCommunityResponse, number_of_comments: -1, hot_rank: -1, user_id: None, - subscribed: None, // TODO: looks like lemmy uses None/true for this value + subscribed: None, }, online: 0, }) } -fn get_string_value_opt(value: Option<Value>) -> Option<String> { - value - .as_ref() - .map(Value::as_str) - .flatten() - .map(str::to_string) -} - -fn get_string_value(value: Option<Value>) -> String { - get_string_value_opt(value).unwrap() -} - pub fn get_following_instances() -> Result<Vec<String>, Error> { let instance_list = match Settings::get().federated_instance.clone() { Some(f) => vec![f, Settings::get().hostname.clone()], |