Use the activitypub crate

This commit is contained in:
Bat 2018-06-10 12:13:07 +01:00
parent 40d87e746d
commit 78362feffb
13 changed files with 88 additions and 75 deletions

30
Cargo.lock generated
View file

@ -1,3 +1,16 @@
[[package]]
name = "activitypub"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"activitystreams-derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"activitystreams-traits 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"activitystreams-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "activitystreams"
version = "0.1.1"
@ -41,6 +54,20 @@ dependencies = [
"serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "activitystreams-types"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"activitystreams-derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"activitystreams-traits 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "adler32"
version = "1.0.2"
@ -936,6 +963,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "plume"
version = "0.1.0"
dependencies = [
"activitypub 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"activitystreams 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"activitystreams-derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"activitystreams-traits 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1811,10 +1839,12 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum activitypub 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c87040997a45d9da90327a11191bda4f2b1812d8c3e2062ea8d539eb8e2bfde7"
"checksum activitystreams 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "638541e5169c839f6581302c50e38876312389475cd911ecc7c446c7491004cc"
"checksum activitystreams-derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48db826c588a009960d74530e7c215e21fae130f585362504dc6b6357e5ce86b"
"checksum activitystreams-traits 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "670ef03168e704b0cae242e7a5d8b40506772b339687e01a3496fc4afe2e8542"
"checksum activitystreams-types 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aff9aa0c3412fe4da72a1f6e4b1c2e9792bfdf1308b709389192f17aa8e2b3cd"
"checksum activitystreams-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "14806b3c88c439e1670fdc99d9b18bf1a47d4fa7152fe8a3bd7da08b6ced3e95"
"checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45"
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"

View file

@ -3,6 +3,7 @@ authors = ["Bat' <baptiste@gelez.xyz>"]
name = "plume"
version = "0.1.0"
[dependencies]
activitypub = "0.1"
activitystreams = "0.1"
activitystreams-derive = "0.1"
activitystreams-traits = "0.1"

View file

@ -1,9 +1,10 @@
use activitystreams_traits::Actor;
use activitystreams_types::{
use activitypub::{
Actor,
actor::Person,
activity::{Accept, Announce, Create, Follow, Like, Undo},
object::{Article, Note}
object::Note
};
use activitystreams_types::object::Article;
use diesel::PgConnection;
use failure::Error;
use serde_json;
@ -67,11 +68,11 @@ pub trait Inbox {
}
fn follow(&self, conn: &PgConnection, follow: Follow) -> Result<(), Error> {
let from = User::from_url(conn, follow.actor.as_str().unwrap().to_string()).unwrap();
match User::from_url(conn, follow.object.as_str().unwrap().to_string()) {
let from = User::from_url(conn, follow.follow_props.actor.as_str().unwrap().to_string()).unwrap();
match User::from_url(conn, follow.follow_props.object.as_str().unwrap().to_string()) {
Some(u) => self.accept_follow(conn, &from, &u, follow, from.id, u.id),
None => {
let blog = Blog::from_url(conn, follow.object.as_str().unwrap().to_string()).unwrap();
let blog = Blog::from_url(conn, follow.follow_props.object.as_str().unwrap().to_string()).unwrap();
self.accept_follow(conn, &from, &blog, follow, from.id, blog.id)
}
};
@ -79,8 +80,8 @@ pub trait Inbox {
}
fn like(&self, conn: &PgConnection, like: Like) -> Result<(), Error> {
let liker = User::from_url(conn, like.actor.as_str().unwrap().to_string());
let post = Post::find_by_ap_url(conn, like.object.as_str().unwrap().to_string());
let liker = User::from_url(conn, like.like_props.actor.as_str().unwrap().to_string());
let post = Post::find_by_ap_url(conn, like.like_props.object.as_str().unwrap().to_string());
likes::Like::insert(conn, likes::NewLike {
post_id: post.unwrap().id,
user_id: liker.unwrap().id,
@ -90,14 +91,14 @@ pub trait Inbox {
}
fn unlike(&self, conn: &PgConnection, undo: Undo) -> Result<(), Error> {
let like = likes::Like::find_by_ap_url(conn, undo.object_object::<Like>()?.object_props.id_string()?).unwrap();
let like = likes::Like::find_by_ap_url(conn, undo.undo_props.object_object::<Like>()?.object_props.id_string()?).unwrap();
like.delete(conn);
Ok(())
}
fn announce(&self, conn: &PgConnection, announce: Announce) -> Result<(), Error> {
let user = User::from_url(conn, announce.actor.as_str().unwrap().to_string());
let post = Post::find_by_ap_url(conn, announce.object.as_str().unwrap().to_string());
let user = User::from_url(conn, announce.announce_props.actor.as_str().unwrap().to_string());
let post = Post::find_by_ap_url(conn, announce.announce_props.object.as_str().unwrap().to_string());
Reshare::insert(conn, NewReshare {
post_id: post.unwrap().id,
user_id: user.unwrap().id,
@ -113,9 +114,9 @@ pub trait Inbox {
"Announce" => self.announce(conn, serde_json::from_value(act.clone())?),
"Create" => {
let act: Create = serde_json::from_value(act.clone())?;
match act.object["type"].as_str().unwrap() {
"Article" => self.new_article(conn, act.object_object()?),
"Note" => self.new_comment(conn, act.object_object()?, act.actor_object::<Person>()?.object_props.id_string()?),
match act.create_props.object["type"].as_str().unwrap() {
"Article" => self.new_article(conn, act.create_props.object_object()?),
"Note" => self.new_comment(conn, act.create_props.object_object()?, act.create_props.actor_object::<Person>()?.object_props.id_string()?),
_ => Err(InboxError::InvalidType)?
}
},
@ -123,7 +124,7 @@ pub trait Inbox {
"Like" => self.like(conn, serde_json::from_value(act.clone())?),
"Undo" => {
let act: Undo = serde_json::from_value(act.clone())?;
match act.object["type"].as_str().unwrap() {
match act.undo_props.object["type"].as_str().unwrap() {
"Like" => self.unlike(conn, act),
_ => Err(InboxError::CantUndo)?
}
@ -150,8 +151,8 @@ pub trait Inbox {
});
let mut accept = Accept::default();
accept.set_actor_link::<Id>(from.clone().into_id()).unwrap();
accept.set_object_object(follow).unwrap();
accept.accept_props.set_actor_link::<Id>(from.clone().into_id()).unwrap();
accept.accept_props.set_object_object(follow).unwrap();
broadcast(conn, &*from, accept, vec![target.clone()]);
}
}

View file

@ -1,4 +1,4 @@
use activitystreams_traits::{Activity, Actor, Object, Link};
use activitypub::{Activity, Actor, Object, Link};
use array_tool::vec::Uniq;
use diesel::PgConnection;
use reqwest::Client;

View file

@ -1,10 +1,7 @@
#![feature(plugin, custom_derive, iterator_find_map)]
#![plugin(rocket_codegen)]
extern crate activitystreams;
#[macro_use]
extern crate activitystreams_derive;
extern crate activitystreams_traits;
extern crate activitypub;
extern crate activitystreams_types;
extern crate array_tool;
extern crate base64;

View file

@ -1,5 +1,4 @@
use activitystreams_traits::{Actor, Object};
use activitystreams_types::collection::OrderedCollection;
use activitypub::{Actor, Object, collection::OrderedCollection};
use reqwest::{
Client,
header::{Accept, qitem},

View file

@ -1,4 +1,4 @@
use activitystreams_types::{
use activitypub::{
activity::Create,
object::{Note, properties::ObjectProperties}
};
@ -105,8 +105,8 @@ impl Comment {
pub fn create_activity(&self, conn: &PgConnection) -> Create {
let mut act = Create::default();
act.set_actor_link(self.get_author(conn).into_id()).unwrap();
act.set_object_object(self.into_activity(conn)).unwrap();
act.create_props.set_actor_link(self.get_author(conn).into_id()).unwrap();
act.create_props.set_object_object(self.into_activity(conn)).unwrap();
act.object_props.set_id_string(format!("{}/activity", self.ap_url.clone().unwrap())).unwrap();
act
}

View file

@ -1,4 +1,4 @@
use activitystreams_types::activity;
use activitypub::activity;
use chrono;
use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods};
use serde_json;
@ -76,15 +76,15 @@ impl Like {
diesel::delete(self).execute(conn).unwrap();
let mut act = activity::Undo::default();
act.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
act.set_object_object(self.into_activity(conn)).unwrap();
act.undo_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
act.undo_props.set_object_object(self.into_activity(conn)).unwrap();
act
}
pub fn into_activity(&self, conn: &PgConnection) -> activity::Like {
let mut act = activity::Like::default();
act.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
act.set_object_link(Post::get(conn, self.post_id).unwrap().into_id()).unwrap();
act.like_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
act.like_props.set_object_link(Post::get(conn, self.post_id).unwrap().into_id()).unwrap();
act.object_props.set_id_string(format!("{}/like/{}",
User::get(conn, self.user_id).unwrap().ap_url,
Post::get(conn, self.post_id).unwrap().ap_url

View file

@ -1,7 +1,5 @@
use activitystreams_types::{
activity::Create,
object::{Article, properties::ObjectProperties}
};
use activitypub::activity::Create;
use activitystreams_types::object::{Article, properties::ObjectProperties};
use chrono::NaiveDateTime;
use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods, BelongingToDsl};
use diesel::dsl::any;
@ -177,8 +175,8 @@ impl Post {
pub fn create_activity(&self, conn: &PgConnection) -> Create {
let mut act = Create::default();
act.object_props.set_id_string(format!("{}/activity", self.ap_url)).unwrap();
act.set_actor_link(Id::new(self.get_authors(conn)[0].clone().ap_url)).unwrap();
act.set_object_object(self.into_activity(conn)).unwrap();
act.create_props.set_actor_link(Id::new(self.get_authors(conn)[0].clone().ap_url)).unwrap();
act.create_props.set_object_object(self.into_activity(conn)).unwrap();
act
}
}

View file

@ -1,4 +1,4 @@
use activitystreams_types::activity;
use activitypub::activity;
use chrono::NaiveDateTime;
use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods};
@ -84,15 +84,15 @@ impl Reshare {
diesel::delete(self).execute(conn).unwrap();
let mut act = activity::Undo::default();
act.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
act.set_object_object(self.into_activity(conn)).unwrap();
act.undo_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
act.undo_props.set_object_object(self.into_activity(conn)).unwrap();
act
}
pub fn into_activity(&self, conn: &PgConnection) -> activity::Announce {
let mut act = activity::Announce::default();
act.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
act.set_object_link(Post::get(conn, self.post_id).unwrap().into_id()).unwrap();
act.announce_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
act.announce_props.set_object_link(Post::get(conn, self.post_id).unwrap().into_id()).unwrap();
act.object_props.set_id_string(self.ap_url.clone()).unwrap();
act

View file

@ -1,9 +1,8 @@
use activitystreams_traits::{Actor, Object, Link};
use activitystreams_types::{
actor::Person,
use activitypub::{
Actor, Object,
actor::{Person, properties::ApActorProperties},
collection::OrderedCollection,
object::properties::ObjectProperties,
CustomObject
object::properties::ObjectProperties
};
use bcrypt;
use chrono::NaiveDateTime;
@ -302,7 +301,7 @@ impl User {
PKey::from_rsa(Rsa::private_key_from_pem(self.private_key.clone().unwrap().as_ref()).unwrap()).unwrap()
}
pub fn into_activity(&self, conn: &PgConnection) -> CustomObject<ApProps, Person> {
pub fn into_activity(&self, conn: &PgConnection) -> Person {
let mut actor = Person::default();
actor.object_props = ObjectProperties {
id: Some(serde_json::to_value(self.compute_id(conn)).unwrap()),
@ -311,34 +310,22 @@ impl User {
url: Some(serde_json::to_value(self.compute_id(conn)).unwrap()),
..ObjectProperties::default()
};
CustomObject::new(actor, ApProps {
inbox: Some(serde_json::to_value(self.compute_inbox(conn)).unwrap()),
outbox: Some(serde_json::to_value(self.compute_outbox(conn)).unwrap()),
actor.ap_actor_props = ApActorProperties {
inbox: serde_json::to_value(self.compute_inbox(conn)).unwrap(),
outbox: serde_json::to_value(self.compute_outbox(conn)).unwrap(),
preferred_username: Some(serde_json::to_value(self.get_actor_id()).unwrap()),
endpoints: Some(json!({
"sharedInbox": ap_url(format!("{}/inbox", BASE_URL.as_str()))
}))
})
})),
followers: None,
following: None,
liked: None,
streams: None
};
actor
}
}
#[derive(Serialize, Deserialize, Default, Properties)]
#[serde(rename_all = "camelCase")]
pub struct ApProps {
#[activitystreams(ab(Object, Link))]
inbox: Option<serde_json::Value>,
#[activitystreams(ab(Object, Link))]
outbox: Option<serde_json::Value>,
#[activitystreams(ab(Object, Link))]
preferred_username: Option<serde_json::Value>,
#[activitystreams(ab(Object))]
endpoints: Option<serde_json::Value>
}
impl<'a, 'r> FromRequest<'a, 'r> for User {
type Error = ();

View file

@ -1,4 +1,4 @@
use activitystreams_types::collection::OrderedCollection;
use activitypub::collection::OrderedCollection;
use rocket::{
request::Form,
response::{Redirect, Flash}

View file

@ -1,4 +1,4 @@
use activitystreams_types::{
use activitypub::{
activity::Follow,
collection::OrderedCollection
};
@ -82,8 +82,8 @@ fn follow(name: String, conn: DbConn, user: User) -> Redirect {
following_id: target.id
});
let mut act = Follow::default();
act.set_actor_link::<Id>(user.clone().into_id()).unwrap();
act.set_object_object(user.into_activity(&*conn)).unwrap();
act.follow_props.set_actor_link::<Id>(user.clone().into_id()).unwrap();
act.follow_props.set_object_object(user.into_activity(&*conn)).unwrap();
act.object_props.set_id_string(format!("{}/follow/{}", user.ap_url, target.ap_url)).unwrap();
broadcast(&*conn, &user, act, vec![target]);
Redirect::to(format!("/@/{}/", name).as_ref())