Introduce some traits for handling incoming activities
This commit is contained in:
+20
-1
@@ -7,8 +7,9 @@ use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods, dsl::
|
||||
use serde_json;
|
||||
|
||||
use activity_pub::{
|
||||
ap_url, IntoId, PUBLIC_VISIBILTY,
|
||||
ap_url, Id, IntoId, PUBLIC_VISIBILTY,
|
||||
actor::Actor,
|
||||
inbox::FromActivity,
|
||||
object::Object
|
||||
};
|
||||
use models::{
|
||||
@@ -123,6 +124,24 @@ impl Comment {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromActivity<Note> for Comment {
|
||||
fn from_activity(conn: &PgConnection, note: Note, actor: Id) -> Comment {
|
||||
let previous_url = note.object_props.in_reply_to.clone().unwrap().as_str().unwrap().to_string();
|
||||
let previous_comment = Comment::find_by_ap_url(conn, previous_url.clone());
|
||||
Comment::insert(conn, NewComment {
|
||||
content: SafeString::new(¬e.object_props.content_string().unwrap()),
|
||||
spoiler_text: note.object_props.summary_string().unwrap_or(String::from("")),
|
||||
ap_url: note.object_props.id_string().ok(),
|
||||
in_response_to_id: previous_comment.clone().map(|c| c.id),
|
||||
post_id: previous_comment
|
||||
.map(|c| c.post_id)
|
||||
.unwrap_or_else(|| Post::find_by_ap_url(conn, previous_url).unwrap().id),
|
||||
author_id: User::from_url(conn, actor.into()).unwrap().id,
|
||||
sensitive: false // "sensitive" is not a standard property, we need to think about how to support it with the activitypub crate
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Object for Comment {
|
||||
fn serialize(&self, conn: &PgConnection) -> serde_json::Value {
|
||||
let mut to = self.get_author(conn).get_followers(conn).into_iter().map(|f| f.ap_url).collect::<Vec<String>>();
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
use activitypub::{Actor, activity::{Accept, Follow as FollowAct}};
|
||||
use diesel::{self, PgConnection, ExpressionMethods, QueryDsl, RunQueryDsl};
|
||||
|
||||
use activity_pub::{broadcast, Id, IntoId, actor::Actor as ApActor, inbox::{FromActivity, WithInbox}, sign::Signer};
|
||||
use models::blogs::Blog;
|
||||
use models::users::User;
|
||||
use schema::follows;
|
||||
|
||||
@@ -33,4 +36,37 @@ impl Follow {
|
||||
.expect("Unable to load follow by id")
|
||||
.into_iter().nth(0)
|
||||
}
|
||||
|
||||
pub fn accept_follow<A: Signer + IntoId + Clone, B: Clone + WithInbox + Actor>(
|
||||
conn: &PgConnection,
|
||||
from: &A,
|
||||
target: &B,
|
||||
follow: FollowAct,
|
||||
from_id: i32,
|
||||
target_id: i32
|
||||
) -> Follow {
|
||||
let res = Follow::insert(conn, NewFollow {
|
||||
follower_id: from_id,
|
||||
following_id: target_id
|
||||
});
|
||||
|
||||
let mut accept = Accept::default();
|
||||
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()]);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl FromActivity<FollowAct> for Follow {
|
||||
fn from_activity(conn: &PgConnection, follow: FollowAct, _actor: Id) -> Follow {
|
||||
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) => Follow::accept_follow(conn, &from, &u, follow, from.id, u.id),
|
||||
None => {
|
||||
let blog = Blog::from_url(conn, follow.follow_props.object.as_str().unwrap().to_string()).unwrap();
|
||||
Follow::accept_follow(conn, &from, &blog, follow, from.id, blog.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods};
|
||||
use serde_json;
|
||||
|
||||
use activity_pub::{
|
||||
Id,
|
||||
IntoId,
|
||||
actor::Actor,
|
||||
inbox::{FromActivity, Deletable},
|
||||
object::Object
|
||||
};
|
||||
use models::{
|
||||
@@ -94,6 +96,29 @@ impl Like {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromActivity<activity::Like> for Like {
|
||||
fn from_activity(conn: &PgConnection, like: activity::Like, _actor: Id) -> Like {
|
||||
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());
|
||||
Like::insert(conn, NewLike {
|
||||
post_id: post.unwrap().id,
|
||||
user_id: liker.unwrap().id,
|
||||
ap_url: like.object_props.id_string().unwrap_or(String::from(""))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Deletable for Like {
|
||||
fn delete_activity(conn: &PgConnection, id: Id) -> bool {
|
||||
if let Some(like) = Like::find_by_ap_url(conn, id.into()) {
|
||||
like.delete(conn);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Object for Like {
|
||||
fn serialize(&self, conn: &PgConnection) -> serde_json::Value {
|
||||
json!({
|
||||
|
||||
@@ -10,6 +10,7 @@ use BASE_URL;
|
||||
use activity_pub::{
|
||||
PUBLIC_VISIBILTY, ap_url, Id, IntoId,
|
||||
actor::Actor,
|
||||
inbox::FromActivity,
|
||||
object::Object
|
||||
};
|
||||
use models::{
|
||||
@@ -195,6 +196,20 @@ impl Post {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromActivity<Article> for Post {
|
||||
fn from_activity(conn: &PgConnection, article: Article, _actor: Id) -> Post {
|
||||
Post::insert(conn, NewPost {
|
||||
blog_id: 0, // TODO
|
||||
slug: String::from(""), // TODO
|
||||
title: article.object_props.name_string().unwrap(),
|
||||
content: SafeString::new(&article.object_props.content_string().unwrap()),
|
||||
published: true,
|
||||
license: String::from("CC-0"),
|
||||
ap_url: article.object_props.url_string().unwrap_or(String::from(""))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoId for Post {
|
||||
fn into_id(self) -> Id {
|
||||
Id::new(self.ap_url.clone())
|
||||
|
||||
+18
-6
@@ -1,8 +1,8 @@
|
||||
use activitypub::activity;
|
||||
use activitypub::activity::{Announce, Undo};
|
||||
use chrono::NaiveDateTime;
|
||||
use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods};
|
||||
|
||||
use activity_pub::{IntoId, actor::Actor, object::Object};
|
||||
use activity_pub::{Id, IntoId, actor::Actor, inbox::FromActivity, object::Object};
|
||||
use models::{posts::Post, users::User};
|
||||
use schema::reshares;
|
||||
|
||||
@@ -80,17 +80,17 @@ impl Reshare {
|
||||
Post::get(conn, self.post_id)
|
||||
}
|
||||
|
||||
pub fn delete(&self, conn: &PgConnection) -> activity::Undo {
|
||||
pub fn delete(&self, conn: &PgConnection) -> Undo {
|
||||
diesel::delete(self).execute(conn).unwrap();
|
||||
|
||||
let mut act = activity::Undo::default();
|
||||
let mut act = Undo::default();
|
||||
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();
|
||||
pub fn into_activity(&self, conn: &PgConnection) -> Announce {
|
||||
let mut act = Announce::default();
|
||||
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();
|
||||
@@ -98,3 +98,15 @@ impl Reshare {
|
||||
act
|
||||
}
|
||||
}
|
||||
|
||||
impl FromActivity<Announce> for Reshare {
|
||||
fn from_activity(conn: &PgConnection, announce: Announce, _actor: Id) -> Reshare {
|
||||
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,
|
||||
ap_url: announce.object_props.id_string().unwrap_or(String::from(""))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user