2020-04-03 05:02:43 +00:00
|
|
|
use crate::api::community::ListCommunities;
|
|
|
|
use crate::api::{Oper, Perform};
|
|
|
|
use crate::apub::puller::{fetch_remote_object, format_community_name};
|
|
|
|
use crate::apub::{
|
|
|
|
create_apub_response, get_apub_protocol_string, make_apub_endpoint, EndpointType, GroupExt,
|
|
|
|
};
|
2020-03-12 00:01:25 +00:00
|
|
|
use crate::convert_datetime;
|
2019-12-19 21:59:13 +00:00
|
|
|
use crate::db::community::Community;
|
2020-04-03 05:02:43 +00:00
|
|
|
use crate::db::community_view::{CommunityFollowerView, CommunityView};
|
2020-01-12 15:31:51 +00:00
|
|
|
use crate::db::establish_unpooled_connection;
|
2020-03-14 00:05:42 +00:00
|
|
|
use crate::db::post_view::{PostQueryBuilder, PostView};
|
2020-04-03 05:02:43 +00:00
|
|
|
use crate::settings::Settings;
|
|
|
|
use activitystreams::actor::properties::ApActorProperties;
|
2020-03-19 01:16:17 +00:00
|
|
|
use activitystreams::collection::OrderedCollection;
|
2020-03-12 00:01:25 +00:00
|
|
|
use activitystreams::{
|
2020-04-03 05:02:43 +00:00
|
|
|
actor::Group, collection::UnorderedCollection, context, ext::Extensible,
|
2020-03-12 00:01:25 +00:00
|
|
|
object::properties::ObjectProperties,
|
|
|
|
};
|
2019-12-19 21:59:13 +00:00
|
|
|
use actix_web::body::Body;
|
|
|
|
use actix_web::web::Path;
|
|
|
|
use actix_web::HttpResponse;
|
2020-03-16 17:30:25 +00:00
|
|
|
use actix_web::{web, Result};
|
|
|
|
use diesel::r2d2::{ConnectionManager, Pool};
|
|
|
|
use diesel::PgConnection;
|
2020-03-12 00:01:25 +00:00
|
|
|
use failure::Error;
|
2019-12-19 21:59:13 +00:00
|
|
|
use serde::Deserialize;
|
|
|
|
|
2020-03-16 17:30:25 +00:00
|
|
|
#[derive(Deserialize)]
|
|
|
|
pub struct CommunityQuery {
|
|
|
|
community_name: String,
|
|
|
|
}
|
2020-03-12 00:01:25 +00:00
|
|
|
|
2020-04-03 05:02:43 +00:00
|
|
|
pub async fn get_apub_community_list(
|
2020-03-16 17:30:25 +00:00
|
|
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
|
|
|
) -> Result<HttpResponse<Body>, Error> {
|
2020-04-03 05:02:43 +00:00
|
|
|
// TODO: implement pagination
|
|
|
|
let query = ListCommunities {
|
|
|
|
sort: "Hot".to_string(),
|
|
|
|
page: None,
|
|
|
|
limit: None,
|
|
|
|
auth: None,
|
|
|
|
local_only: Some(true),
|
|
|
|
};
|
|
|
|
let communities = Oper::new(query)
|
|
|
|
.perform(&db.get().unwrap())
|
|
|
|
.unwrap()
|
|
|
|
.communities
|
|
|
|
.iter()
|
|
|
|
.map(|c| c.as_group())
|
|
|
|
.collect::<Result<Vec<GroupExt>, failure::Error>>()?;
|
|
|
|
let mut collection = UnorderedCollection::default();
|
|
|
|
let oprops: &mut ObjectProperties = collection.as_mut();
|
|
|
|
oprops.set_context_xsd_any_uri(context())?.set_id(format!(
|
|
|
|
"{}://{}/federation/communities",
|
|
|
|
get_apub_protocol_string(),
|
|
|
|
Settings::get().hostname
|
|
|
|
))?;
|
2020-03-12 00:01:25 +00:00
|
|
|
|
2020-04-03 05:02:43 +00:00
|
|
|
collection
|
|
|
|
.collection_props
|
|
|
|
.set_total_items(communities.len() as u64)?
|
|
|
|
.set_many_items_base_boxes(communities)?;
|
|
|
|
Ok(create_apub_response(&collection))
|
|
|
|
}
|
2019-12-19 21:59:13 +00:00
|
|
|
|
2020-04-03 05:02:43 +00:00
|
|
|
impl CommunityView {
|
|
|
|
fn as_group(&self) -> Result<GroupExt, Error> {
|
|
|
|
let base_url = make_apub_endpoint(EndpointType::Community, &self.name);
|
|
|
|
|
|
|
|
let mut group = Group::default();
|
|
|
|
let oprops: &mut ObjectProperties = group.as_mut();
|
|
|
|
|
|
|
|
oprops
|
|
|
|
.set_context_xsd_any_uri(context())?
|
|
|
|
.set_id(base_url.to_owned())?
|
|
|
|
.set_name_xsd_string(self.name.to_owned())?
|
|
|
|
.set_published(convert_datetime(self.published))?
|
|
|
|
.set_attributed_to_xsd_any_uri(make_apub_endpoint(
|
|
|
|
EndpointType::User,
|
|
|
|
&self.creator_id.to_string(),
|
|
|
|
))?;
|
|
|
|
|
|
|
|
if let Some(u) = self.updated.to_owned() {
|
|
|
|
oprops.set_updated(convert_datetime(u))?;
|
|
|
|
}
|
|
|
|
if let Some(d) = self.description.to_owned() {
|
|
|
|
oprops.set_summary_xsd_string(d)?;
|
|
|
|
}
|
2020-03-14 00:05:42 +00:00
|
|
|
|
2020-04-03 05:02:43 +00:00
|
|
|
let mut actor_props = ApActorProperties::default();
|
2020-03-19 01:16:17 +00:00
|
|
|
|
2020-04-03 05:02:43 +00:00
|
|
|
actor_props
|
|
|
|
.set_preferred_username(self.title.to_owned())?
|
|
|
|
.set_inbox(format!("{}/inbox", &base_url))?
|
|
|
|
.set_outbox(format!("{}/outbox", &base_url))?
|
|
|
|
.set_followers(format!("{}/followers", &base_url))?;
|
2020-03-14 00:05:42 +00:00
|
|
|
|
2020-04-03 05:02:43 +00:00
|
|
|
Ok(group.extend(actor_props))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn from_group(group: &GroupExt, domain: &str) -> Result<CommunityView, Error> {
|
|
|
|
let followers_uri = &group.extension.get_followers().unwrap().to_string();
|
|
|
|
let outbox_uri = &group.extension.get_outbox().to_string();
|
|
|
|
let outbox = fetch_remote_object::<OrderedCollection>(outbox_uri)?;
|
|
|
|
let followers = fetch_remote_object::<UnorderedCollection>(followers_uri)?;
|
|
|
|
let oprops = &group.base.object_props;
|
|
|
|
let aprops = &group.extension;
|
|
|
|
Ok(CommunityView {
|
|
|
|
// TODO: we need to merge id and name into a single thing (stuff like @user@instance.com)
|
|
|
|
id: 1337, //community.object_props.get_id()
|
|
|
|
name: format_community_name(&oprops.get_name_xsd_string().unwrap().to_string(), domain),
|
|
|
|
title: aprops.get_preferred_username().unwrap().to_string(),
|
|
|
|
description: oprops.get_summary_xsd_string().map(|s| s.to_string()),
|
|
|
|
category_id: -1,
|
|
|
|
creator_id: -1, //community.object_props.get_attributed_to_xsd_any_uri()
|
|
|
|
removed: false,
|
|
|
|
published: oprops
|
|
|
|
.get_published()
|
|
|
|
.unwrap()
|
|
|
|
.as_ref()
|
|
|
|
.naive_local()
|
|
|
|
.to_owned(),
|
|
|
|
updated: oprops
|
|
|
|
.get_updated()
|
|
|
|
.map(|u| u.as_ref().to_owned().naive_local()),
|
|
|
|
deleted: false,
|
|
|
|
nsfw: false,
|
|
|
|
creator_name: "".to_string(),
|
|
|
|
creator_avatar: None,
|
|
|
|
category_name: "".to_string(),
|
|
|
|
number_of_subscribers: *followers
|
|
|
|
.collection_props
|
|
|
|
.get_total_items()
|
|
|
|
.unwrap()
|
|
|
|
.as_ref() as i64,
|
|
|
|
number_of_posts: *outbox.collection_props.get_total_items().unwrap().as_ref() as i64,
|
|
|
|
number_of_comments: -1,
|
|
|
|
hot_rank: -1,
|
|
|
|
user_id: None,
|
|
|
|
subscribed: None,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn get_apub_community_http(
|
|
|
|
info: Path<CommunityQuery>,
|
|
|
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
|
|
|
) -> Result<HttpResponse<Body>, Error> {
|
|
|
|
let community = Community::read_from_name(&&db.get()?, info.community_name.to_owned())?;
|
|
|
|
let community_view = CommunityView::read(&&db.get()?, community.id, None)?;
|
|
|
|
let c = community_view.as_group()?;
|
|
|
|
Ok(create_apub_response(&c))
|
2019-12-19 21:59:13 +00:00
|
|
|
}
|
|
|
|
|
2020-03-12 00:01:25 +00:00
|
|
|
pub async fn get_apub_community_followers(
|
|
|
|
info: Path<CommunityQuery>,
|
2020-03-16 17:30:25 +00:00
|
|
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
2020-03-12 00:01:25 +00:00
|
|
|
) -> Result<HttpResponse<Body>, Error> {
|
2020-03-16 17:30:25 +00:00
|
|
|
let community = Community::read_from_name(&&db.get()?, info.community_name.to_owned())?;
|
2020-03-16 18:19:04 +00:00
|
|
|
let base_url = make_apub_endpoint(EndpointType::Community, &community.name);
|
2019-12-19 21:59:13 +00:00
|
|
|
|
2020-03-16 17:30:25 +00:00
|
|
|
let connection = establish_unpooled_connection();
|
|
|
|
//As we are an object, we validated that the community id was valid
|
|
|
|
let community_followers =
|
|
|
|
CommunityFollowerView::for_community(&connection, community.id).unwrap();
|
|
|
|
|
|
|
|
let mut collection = UnorderedCollection::default();
|
|
|
|
let oprops: &mut ObjectProperties = collection.as_mut();
|
|
|
|
oprops
|
|
|
|
.set_context_xsd_any_uri(context())?
|
|
|
|
.set_id(base_url)?;
|
|
|
|
collection
|
|
|
|
.collection_props
|
|
|
|
.set_total_items(community_followers.len() as u64)?;
|
2020-03-19 01:16:17 +00:00
|
|
|
Ok(create_apub_response(&collection))
|
2020-03-14 00:05:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn get_apub_community_outbox(
|
|
|
|
info: Path<CommunityQuery>,
|
2020-03-16 17:30:25 +00:00
|
|
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
2020-03-14 00:05:42 +00:00
|
|
|
) -> Result<HttpResponse<Body>, Error> {
|
2020-03-16 17:30:25 +00:00
|
|
|
let community = Community::read_from_name(&&db.get()?, info.community_name.to_owned())?;
|
2020-03-16 18:19:04 +00:00
|
|
|
let base_url = make_apub_endpoint(EndpointType::Community, &community.name);
|
2020-03-14 00:05:42 +00:00
|
|
|
|
2020-03-16 17:30:25 +00:00
|
|
|
let connection = establish_unpooled_connection();
|
|
|
|
//As we are an object, we validated that the community id was valid
|
|
|
|
let community_posts: Vec<PostView> = PostQueryBuilder::create(&connection)
|
|
|
|
.for_community_id(community.id)
|
|
|
|
.list()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let mut collection = OrderedCollection::default();
|
|
|
|
let oprops: &mut ObjectProperties = collection.as_mut();
|
|
|
|
oprops
|
|
|
|
.set_context_xsd_any_uri(context())?
|
|
|
|
.set_id(base_url)?;
|
|
|
|
collection
|
|
|
|
.collection_props
|
2020-04-03 05:02:43 +00:00
|
|
|
.set_many_items_base_boxes(
|
2020-03-16 17:30:25 +00:00
|
|
|
community_posts
|
|
|
|
.iter()
|
|
|
|
.map(|c| c.as_page().unwrap())
|
|
|
|
.collect(),
|
|
|
|
)?
|
|
|
|
.set_total_items(community_posts.len() as u64)?;
|
|
|
|
|
2020-03-19 01:16:17 +00:00
|
|
|
Ok(create_apub_response(&collection))
|
2019-12-19 21:59:13 +00:00
|
|
|
}
|