Introduce some traits for handling incoming activities
This commit is contained in:
parent
7d17751f50
commit
36c11182f4
@ -1,27 +1,21 @@
|
|||||||
use activitypub::{
|
use activitypub::{
|
||||||
Actor,
|
Activity, Object,
|
||||||
activity::{Accept, Announce, Create, Follow, Like, Undo},
|
activity::{Create, Like, Undo}
|
||||||
object::{Article, Note}
|
|
||||||
};
|
};
|
||||||
use diesel::PgConnection;
|
use diesel::PgConnection;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
use activity_pub::{
|
use activity_pub::{
|
||||||
broadcast, Id, IntoId,
|
Id
|
||||||
actor::Actor as APActor,
|
|
||||||
sign::*
|
|
||||||
};
|
};
|
||||||
use models::{
|
use models::{
|
||||||
blogs::Blog,
|
|
||||||
comments::*,
|
comments::*,
|
||||||
follows,
|
follows::Follow,
|
||||||
likes,
|
likes,
|
||||||
posts::*,
|
posts::*,
|
||||||
reshares::*,
|
reshares::*
|
||||||
users::User
|
|
||||||
};
|
};
|
||||||
use safe_string::SafeString;
|
|
||||||
|
|
||||||
#[derive(Fail, Debug)]
|
#[derive(Fail, Debug)]
|
||||||
enum InboxError {
|
enum InboxError {
|
||||||
@ -33,98 +27,69 @@ enum InboxError {
|
|||||||
CantUndo
|
CantUndo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait FromActivity<T: Object>: Sized {
|
||||||
|
fn from_activity(conn: &PgConnection, obj: T, actor: Id) -> Self;
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Notify<T: Activity> {
|
||||||
|
fn notify(conn: &PgConnection, act: T, actor: Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Deletable {
|
||||||
|
/// true if success
|
||||||
|
fn delete_activity(conn: &PgConnection, id: Id) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Inbox {
|
pub trait Inbox {
|
||||||
fn received(&self, conn: &PgConnection, act: serde_json::Value);
|
fn received(&self, conn: &PgConnection, act: serde_json::Value);
|
||||||
|
|
||||||
fn new_article(&self, conn: &PgConnection, article: Article) -> Result<(), Error> {
|
|
||||||
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()?
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_comment(&self, conn: &PgConnection, note: Note, actor_id: String) -> Result<(), Error> {
|
|
||||||
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_id).unwrap().id,
|
|
||||||
sensitive: false // "sensitive" is not a standard property, we need to think about how to support it with the activitystreams crate
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn follow(&self, conn: &PgConnection, follow: Follow) -> Result<(), Error> {
|
|
||||||
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.follow_props.object.as_str().unwrap().to_string()).unwrap();
|
|
||||||
self.accept_follow(conn, &from, &blog, follow, from.id, blog.id)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn like(&self, conn: &PgConnection, like: Like) -> Result<(), Error> {
|
|
||||||
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,
|
|
||||||
ap_url: like.object_props.id_string()?
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unlike(&self, conn: &PgConnection, undo: Undo) -> Result<(), Error> {
|
fn unlike(&self, conn: &PgConnection, undo: Undo) -> Result<(), Error> {
|
||||||
let like = likes::Like::find_by_ap_url(conn, undo.undo_props.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);
|
like.delete(conn);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn announce(&self, conn: &PgConnection, announce: Announce) -> Result<(), Error> {
|
|
||||||
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()?
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn save(&self, conn: &PgConnection, act: serde_json::Value) -> Result<(), Error> {
|
fn save(&self, conn: &PgConnection, act: serde_json::Value) -> Result<(), Error> {
|
||||||
|
let actor_id = Id::new(act["actor"].as_str().unwrap());
|
||||||
match act["type"].as_str() {
|
match act["type"].as_str() {
|
||||||
Some(t) => {
|
Some(t) => {
|
||||||
match t {
|
match t {
|
||||||
"Announce" => self.announce(conn, serde_json::from_value(act.clone())?),
|
"Announce" => {
|
||||||
|
Reshare::from_activity(conn, serde_json::from_value(act.clone())?, actor_id);
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
"Create" => {
|
"Create" => {
|
||||||
let act: Create = serde_json::from_value(act.clone())?;
|
let act: Create = serde_json::from_value(act.clone())?;
|
||||||
match act.create_props.object["type"].as_str().unwrap() {
|
if Post::try_from_activity(conn, act.clone()) || Comment::try_from_activity(conn, act) {
|
||||||
"Article" => self.new_article(conn, act.create_props.object_object()?),
|
Ok(())
|
||||||
"Note" => self.new_comment(conn, act.create_props.object_object()?, act.create_props.actor_link::<Id>()?.0),
|
} else {
|
||||||
_ => Err(InboxError::InvalidType)?
|
Err(InboxError::InvalidType)?
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Follow" => self.follow(conn, serde_json::from_value(act.clone())?),
|
"Follow" => {
|
||||||
"Like" => self.like(conn, serde_json::from_value(act.clone())?),
|
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(())
|
||||||
|
},
|
||||||
"Undo" => {
|
"Undo" => {
|
||||||
let act: Undo = serde_json::from_value(act.clone())?;
|
let act: Undo = serde_json::from_value(act.clone())?;
|
||||||
match act.undo_props.object["type"].as_str().unwrap() {
|
match act.undo_props.object["type"].as_str().unwrap() {
|
||||||
"Like" => self.unlike(conn, act),
|
"Like" => {
|
||||||
|
likes::Like::delete_activity(conn, Id::new(act.undo_props.object_object::<Like>()?.object_props.id_string()?));
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
_ => Err(InboxError::CantUndo)?
|
_ => Err(InboxError::CantUndo)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,26 +99,6 @@ pub trait Inbox {
|
|||||||
None => Err(InboxError::NoType)?
|
None => Err(InboxError::NoType)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn accept_follow<A: Signer + IntoId + Clone, B: Clone + WithInbox + Actor>(
|
|
||||||
&self,
|
|
||||||
conn: &PgConnection,
|
|
||||||
from: &A,
|
|
||||||
target: &B,
|
|
||||||
follow: Follow,
|
|
||||||
from_id: i32,
|
|
||||||
target_id: i32
|
|
||||||
) {
|
|
||||||
follows::Follow::insert(conn, follows::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()]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WithInbox {
|
pub trait WithInbox {
|
||||||
|
@ -111,6 +111,12 @@ impl Id {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Into<String> for Id {
|
||||||
|
fn into(self) -> String {
|
||||||
|
self.0.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait IntoId {
|
pub trait IntoId {
|
||||||
fn into_id(self) -> Id;
|
fn into_id(self) -> Id;
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,9 @@ use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods, dsl::
|
|||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
use activity_pub::{
|
use activity_pub::{
|
||||||
ap_url, IntoId, PUBLIC_VISIBILTY,
|
ap_url, Id, IntoId, PUBLIC_VISIBILTY,
|
||||||
actor::Actor,
|
actor::Actor,
|
||||||
|
inbox::FromActivity,
|
||||||
object::Object
|
object::Object
|
||||||
};
|
};
|
||||||
use models::{
|
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 {
|
impl Object for Comment {
|
||||||
fn serialize(&self, conn: &PgConnection) -> serde_json::Value {
|
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>>();
|
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 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 models::users::User;
|
||||||
use schema::follows;
|
use schema::follows;
|
||||||
|
|
||||||
@ -33,4 +36,37 @@ impl Follow {
|
|||||||
.expect("Unable to load follow by id")
|
.expect("Unable to load follow by id")
|
||||||
.into_iter().nth(0)
|
.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 serde_json;
|
||||||
|
|
||||||
use activity_pub::{
|
use activity_pub::{
|
||||||
|
Id,
|
||||||
IntoId,
|
IntoId,
|
||||||
actor::Actor,
|
actor::Actor,
|
||||||
|
inbox::{FromActivity, Deletable},
|
||||||
object::Object
|
object::Object
|
||||||
};
|
};
|
||||||
use models::{
|
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 {
|
impl Object for Like {
|
||||||
fn serialize(&self, conn: &PgConnection) -> serde_json::Value {
|
fn serialize(&self, conn: &PgConnection) -> serde_json::Value {
|
||||||
json!({
|
json!({
|
||||||
|
@ -10,6 +10,7 @@ use BASE_URL;
|
|||||||
use activity_pub::{
|
use activity_pub::{
|
||||||
PUBLIC_VISIBILTY, ap_url, Id, IntoId,
|
PUBLIC_VISIBILTY, ap_url, Id, IntoId,
|
||||||
actor::Actor,
|
actor::Actor,
|
||||||
|
inbox::FromActivity,
|
||||||
object::Object
|
object::Object
|
||||||
};
|
};
|
||||||
use models::{
|
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 {
|
impl IntoId for Post {
|
||||||
fn into_id(self) -> Id {
|
fn into_id(self) -> Id {
|
||||||
Id::new(self.ap_url.clone())
|
Id::new(self.ap_url.clone())
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use activitypub::activity;
|
use activitypub::activity::{Announce, Undo};
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods};
|
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 models::{posts::Post, users::User};
|
||||||
use schema::reshares;
|
use schema::reshares;
|
||||||
|
|
||||||
@ -80,17 +80,17 @@ impl Reshare {
|
|||||||
Post::get(conn, self.post_id)
|
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();
|
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_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap();
|
||||||
act.undo_props.set_object_object(self.into_activity(conn)).unwrap();
|
act.undo_props.set_object_object(self.into_activity(conn)).unwrap();
|
||||||
act
|
act
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_activity(&self, conn: &PgConnection) -> activity::Announce {
|
pub fn into_activity(&self, conn: &PgConnection) -> Announce {
|
||||||
let mut act = activity::Announce::default();
|
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_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.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.object_props.set_id_string(self.ap_url.clone()).unwrap();
|
||||||
@ -98,3 +98,15 @@ impl Reshare {
|
|||||||
act
|
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(""))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user