use super::*;
+use crate::apub::activities::post_create;
use diesel::PgConnection;
use std::str::FromStr;
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,
--- /dev/null
+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(())
+}
--- /dev/null
+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())
+}
+pub mod activities;
pub mod community;
+pub mod inbox;
pub mod post;
pub mod puller;
pub mod user;
-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;
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)
.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 {
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
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)?),
)
}
+// 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)?;
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
-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 {
"/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),
.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())
- },
- ),
);
}
}