Implement create activity
This commit is contained in:
parent
1836d017f9
commit
f7330bf062
7 changed files with 91 additions and 27 deletions
|
@ -1,4 +1,5 @@
|
|||
use super::*;
|
||||
use crate::apub::activities::post_create;
|
||||
use diesel::PgConnection;
|
||||
use std::str::FromStr;
|
||||
|
||||
|
@ -153,6 +154,8 @@ impl Perform<PostResponse> for Oper<CreatePost> {
|
|||
Err(_e) => return Err(APIError::err("couldnt_create_post").into()),
|
||||
};
|
||||
|
||||
post_create(&inserted_post, conn)?;
|
||||
|
||||
// They like their own post by default
|
||||
let like_form = PostLikeForm {
|
||||
post_id: inserted_post.id,
|
||||
|
|
36
server/src/apub/activities.rs
Normal file
36
server/src/apub/activities.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
use crate::apub::{get_apub_protocol_string, get_following_instances};
|
||||
use crate::db::post::Post;
|
||||
use crate::db::user::User_;
|
||||
use crate::db::Crud;
|
||||
use activitystreams::activity::Create;
|
||||
use activitystreams::context;
|
||||
use diesel::PgConnection;
|
||||
use failure::Error;
|
||||
use isahc::prelude::*;
|
||||
|
||||
pub fn post_create(post: &Post, conn: &PgConnection) -> Result<(), Error> {
|
||||
let user = User_::read(conn, post.creator_id)?;
|
||||
let page = post.as_page(conn)?;
|
||||
let mut create = Create::new();
|
||||
create.object_props.set_context_xsd_any_uri(context())?;
|
||||
// TODO: seems like the create activity needs its own id (and be fetchable there)
|
||||
create
|
||||
.object_props
|
||||
.set_id(page.object_props.get_id().unwrap().to_string())?;
|
||||
create.create_props.set_actor_xsd_any_uri(user.actor_id)?;
|
||||
create.create_props.set_object_base_box(page)?;
|
||||
let json = serde_json::to_string(&create)?;
|
||||
for i in get_following_instances() {
|
||||
let inbox = format!(
|
||||
"{}://{}/federation/inbox",
|
||||
get_apub_protocol_string(),
|
||||
i.domain
|
||||
);
|
||||
let res = Request::post(inbox)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(json.to_owned())?
|
||||
.send()?;
|
||||
dbg!(res);
|
||||
}
|
||||
Ok(())
|
||||
}
|
25
server/src/apub/inbox.rs
Normal file
25
server/src/apub/inbox.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use crate::db::post::{Post, PostForm};
|
||||
use crate::db::Crud;
|
||||
use activitystreams::activity::Create;
|
||||
use activitystreams::object::Page;
|
||||
use actix_web::{web, HttpResponse};
|
||||
use diesel::r2d2::{ConnectionManager, Pool};
|
||||
use diesel::PgConnection;
|
||||
use failure::Error;
|
||||
|
||||
pub async fn inbox(
|
||||
create: web::Json<Create>,
|
||||
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let page = create
|
||||
.create_props
|
||||
.get_object_base_box()
|
||||
.unwrap()
|
||||
.to_owned()
|
||||
.to_concrete::<Page>()?;
|
||||
let post = PostForm::from_page(&page, &db.get().unwrap())?;
|
||||
Post::create(&db.get().unwrap(), &post)?;
|
||||
// TODO: send the new post out via websocket
|
||||
dbg!(&post);
|
||||
Ok(HttpResponse::Ok().finish())
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
pub mod activities;
|
||||
pub mod community;
|
||||
pub mod inbox;
|
||||
pub mod post;
|
||||
pub mod puller;
|
||||
pub mod user;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::apub::puller::fetch_remote_user;
|
||||
use crate::apub::puller::{fetch_remote_community, fetch_remote_user};
|
||||
use crate::apub::{create_apub_response, make_apub_endpoint, EndpointType};
|
||||
use crate::convert_datetime;
|
||||
use crate::db::community::Community;
|
||||
use crate::db::post::{Post, PostForm};
|
||||
use crate::db::user::User_;
|
||||
use crate::db::Crud;
|
||||
|
@ -34,6 +35,7 @@ impl Post {
|
|||
let mut page = Page::default();
|
||||
let oprops: &mut ObjectProperties = page.as_mut();
|
||||
let creator = User_::read(conn, self.creator_id)?;
|
||||
let community = Community::read(conn, self.community_id)?;
|
||||
|
||||
oprops
|
||||
// Not needed when the Post is embedded in a collection (like for community outbox)
|
||||
|
@ -41,6 +43,7 @@ impl Post {
|
|||
.set_id(base_url)?
|
||||
.set_name_xsd_string(self.name.to_owned())?
|
||||
.set_published(convert_datetime(self.published))?
|
||||
.set_to_xsd_any_uri(community.actor_id)?
|
||||
.set_attributed_to_xsd_any_uri(make_apub_endpoint(EndpointType::User, &creator.name))?;
|
||||
|
||||
if let Some(body) = &self.body {
|
||||
|
@ -65,14 +68,17 @@ impl Post {
|
|||
impl PostForm {
|
||||
pub fn from_page(page: &Page, conn: &PgConnection) -> Result<PostForm, Error> {
|
||||
let oprops = &page.object_props;
|
||||
let apub_id = Url::parse(&oprops.get_attributed_to_xsd_any_uri().unwrap().to_string())?;
|
||||
let creator = fetch_remote_user(&apub_id, conn)?;
|
||||
let creator_id = Url::parse(&oprops.get_attributed_to_xsd_any_uri().unwrap().to_string())?;
|
||||
let creator = fetch_remote_user(&creator_id, conn)?;
|
||||
let community_id = Url::parse(&oprops.get_to_xsd_any_uri().unwrap().to_string())?;
|
||||
let community = fetch_remote_community(&community_id, conn)?;
|
||||
|
||||
Ok(PostForm {
|
||||
name: oprops.get_name_xsd_string().unwrap().to_string(),
|
||||
url: oprops.get_url_xsd_any_uri().map(|u| u.to_string()),
|
||||
body: oprops.get_content_xsd_string().map(|c| c.to_string()),
|
||||
creator_id: creator.id,
|
||||
community_id: -1,
|
||||
community_id: community.id,
|
||||
removed: None,
|
||||
locked: None,
|
||||
published: oprops
|
||||
|
|
|
@ -91,8 +91,7 @@ fn fetch_remote_community_posts(
|
|||
PostForm::from_page(&page, conn)
|
||||
})
|
||||
.map(|pf: Result<PostForm, Error>| -> Result<Post, Error> {
|
||||
let mut pf2 = pf?;
|
||||
pf2.community_id = community.id;
|
||||
let pf2 = pf?;
|
||||
let existing = Post::read_from_apub_id(conn, &pf2.ap_id);
|
||||
match existing {
|
||||
Err(NotFound {}) => Ok(Post::create(conn, &pf2)?),
|
||||
|
@ -104,6 +103,7 @@ fn fetch_remote_community_posts(
|
|||
)
|
||||
}
|
||||
|
||||
// TODO: can probably merge these two methods?
|
||||
pub fn fetch_remote_user(apub_id: &Url, conn: &PgConnection) -> Result<User_, Error> {
|
||||
let person = fetch_remote_object::<PersonExt>(apub_id)?;
|
||||
let uf = UserForm::from_person(&person)?;
|
||||
|
@ -114,6 +114,16 @@ pub fn fetch_remote_user(apub_id: &Url, conn: &PgConnection) -> Result<User_, Er
|
|||
Err(e) => return Err(Error::from(e)),
|
||||
})
|
||||
}
|
||||
pub fn fetch_remote_community(apub_id: &Url, conn: &PgConnection) -> Result<Community, Error> {
|
||||
let group = fetch_remote_object::<GroupExt>(apub_id)?;
|
||||
let cf = CommunityForm::from_group(&group, conn)?;
|
||||
let existing = Community::read_from_actor_id(conn, &cf.actor_id);
|
||||
Ok(match existing {
|
||||
Err(NotFound {}) => Community::create(conn, &cf)?,
|
||||
Ok(u) => Community::update(conn, u.id, &cf)?,
|
||||
Err(e) => return Err(Error::from(e)),
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: in the future, this should only be done when an instance is followed for the first time
|
||||
// after that, we should rely in the inbox, and fetch on demand when needed
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
use crate::api::community::ListCommunities;
|
||||
use crate::api::Oper;
|
||||
use crate::api::Perform;
|
||||
use crate::apub;
|
||||
use crate::settings::Settings;
|
||||
use actix_web::web::Query;
|
||||
use actix_web::{web, HttpResponse};
|
||||
use diesel::r2d2::{ConnectionManager, Pool};
|
||||
use diesel::PgConnection;
|
||||
use actix_web::web;
|
||||
|
||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
if Settings::get().federation.enabled {
|
||||
|
@ -16,6 +10,8 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
|||
"/federation/communities",
|
||||
web::get().to(apub::community::get_apub_community_list),
|
||||
)
|
||||
// TODO: need a proper actor that has this inbox
|
||||
.route("/federation/inbox", web::post().to(apub::inbox::inbox))
|
||||
.route(
|
||||
"/federation/c/{community_name}",
|
||||
web::get().to(apub::community::get_apub_community_http),
|
||||
|
@ -35,20 +31,6 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
|||
.route(
|
||||
"/federation/p/{post_id}",
|
||||
web::get().to(apub::user::get_apub_user),
|
||||
)
|
||||
// TODO: we should be able to remove this but somehow that breaks the remote community list
|
||||
.route(
|
||||
"/api/v1/communities/list",
|
||||
web::get().to(
|
||||
|query: Query<ListCommunities>, db: web::Data<Pool<ConnectionManager<PgConnection>>>| {
|
||||
let res = Oper::new(query.into_inner())
|
||||
.perform(&db.get().unwrap())
|
||||
.unwrap();
|
||||
HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
.body(serde_json::to_string(&res).unwrap())
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue