Plume/src/activity_pub/inbox.rs

109 lines
3.4 KiB
Rust
Raw Normal View History

2018-06-10 13:13:07 +02:00
use activitypub::{
Object,
activity::{Create, Like, Undo}
2018-05-16 20:20:44 +02:00
};
2018-05-01 16:00:29 +02:00
use diesel::PgConnection;
2018-05-16 20:20:44 +02:00
use failure::Error;
2018-05-01 16:00:29 +02:00
use serde_json;
2018-05-19 09:39:59 +02:00
use activity_pub::{
Id
2018-05-19 09:39:59 +02:00
};
use models::{
comments::*,
follows::Follow,
2018-05-19 09:39:59 +02:00
likes,
posts::*,
reshares::*
2018-05-19 09:39:59 +02:00
};
2018-05-01 16:00:29 +02:00
2018-05-16 20:20:44 +02:00
#[derive(Fail, Debug)]
enum InboxError {
#[fail(display = "The `type` property is required, but was not present")]
NoType,
#[fail(display = "Invalid activity type")]
InvalidType,
#[fail(display = "Couldn't undo activity")]
CantUndo
}
pub trait FromActivity<T: Object>: Sized {
fn from_activity(conn: &PgConnection, obj: T, actor: Id) -> Self;
2018-05-01 16:00:29 +02:00
fn try_from_activity(conn: &PgConnection, act: Create) -> bool {
if let Ok(obj) = act.create_props.object_object() {
Self::from_activity(conn, obj, act.create_props.actor_link::<Id>().unwrap());
true
} else {
false
}
2018-05-16 20:20:44 +02:00
}
}
2018-05-16 20:20:44 +02:00
pub trait Notify<T: Object> {
fn notify(conn: &PgConnection, act: T, actor: Id);
}
2018-05-16 20:20:44 +02:00
pub trait Deletable {
/// true if success
fn delete_activity(conn: &PgConnection, id: Id) -> bool;
}
2018-05-16 20:20:44 +02:00
pub trait Inbox {
fn received(&self, conn: &PgConnection, act: serde_json::Value);
2018-05-16 20:20:44 +02:00
fn unlike(&self, conn: &PgConnection, undo: Undo) -> Result<(), Error> {
2018-06-10 13:13:07 +02:00
let like = likes::Like::find_by_ap_url(conn, undo.undo_props.object_object::<Like>()?.object_props.id_string()?).unwrap();
2018-05-16 20:20:44 +02:00
like.delete(conn);
Ok(())
}
fn save(&self, conn: &PgConnection, act: serde_json::Value) -> Result<(), Error> {
let actor_id = Id::new(act["actor"].as_str().unwrap());
2018-05-16 20:20:44 +02:00
match act["type"].as_str() {
Some(t) => {
match t {
"Announce" => {
Reshare::from_activity(conn, serde_json::from_value(act.clone())?, actor_id);
Ok(())
},
2018-05-16 20:20:44 +02:00
"Create" => {
let act: Create = serde_json::from_value(act.clone())?;
if Post::try_from_activity(conn, act.clone()) || Comment::try_from_activity(conn, act) {
Ok(())
} else {
Err(InboxError::InvalidType)?
2018-05-16 20:20:44 +02:00
}
},
"Follow" => {
Follow::from_activity(conn, serde_json::from_value(act.clone())?, actor_id);
Ok(())
},
"Like" => {
likes::Like::from_activity(conn, serde_json::from_value(act.clone())?, actor_id);
Ok(())
},
2018-05-16 20:20:44 +02:00
"Undo" => {
let act: Undo = serde_json::from_value(act.clone())?;
2018-06-10 13:13:07 +02:00
match act.undo_props.object["type"].as_str().unwrap() {
"Like" => {
likes::Like::delete_activity(conn, Id::new(act.undo_props.object_object::<Like>()?.object_props.id_string()?));
Ok(())
},
2018-05-16 20:20:44 +02:00
_ => Err(InboxError::CantUndo)?
}
2018-05-13 12:44:05 +02:00
}
2018-05-16 20:20:44 +02:00
_ => Err(InboxError::InvalidType)?
2018-05-13 12:44:05 +02:00
}
},
2018-05-16 20:20:44 +02:00
None => Err(InboxError::NoType)?
2018-05-01 16:00:29 +02:00
}
}
}
2018-05-18 10:04:40 +02:00
pub trait WithInbox {
fn get_inbox_url(&self) -> String;
fn get_shared_inbox_url(&self) -> Option<String>;
}