2018-09-04 12:37:58 +02:00
use activitypub ::{ Actor , activity ::{ Accept , Follow as FollowAct , Undo } , actor ::Person } ;
2018-09-27 23:06:40 +02:00
use diesel ::{ self , ExpressionMethods , QueryDsl , RunQueryDsl } ;
2018-05-01 15:06:31 +02:00
2018-09-04 12:37:58 +02:00
use plume_common ::activity_pub ::{ broadcast , Id , IntoId , inbox ::{ FromActivity , Notify , WithInbox , Deletable } , sign ::Signer } ;
2018-09-26 17:22:42 +02:00
use Connection ;
2018-06-23 18:36:11 +02:00
use blogs ::Blog ;
use notifications ::* ;
use users ::User ;
2018-05-01 15:06:31 +02:00
use schema ::follows ;
2018-09-27 23:06:40 +02:00
#[ derive(Clone, Queryable, Identifiable, Associations) ]
2018-05-01 15:23:23 +02:00
#[ belongs_to(User, foreign_key = " following_id " ) ]
2018-05-01 15:06:31 +02:00
pub struct Follow {
pub id : i32 ,
pub follower_id : i32 ,
2018-09-04 12:37:58 +02:00
pub following_id : i32 ,
pub ap_url : String ,
2018-05-01 15:06:31 +02:00
}
#[ derive(Insertable) ]
#[ table_name = " follows " ]
pub struct NewFollow {
pub follower_id : i32 ,
2018-09-04 12:37:58 +02:00
pub following_id : i32 ,
pub ap_url : String ,
2018-05-01 15:06:31 +02:00
}
impl Follow {
2018-06-18 15:57:38 +02:00
insert! ( follows , NewFollow ) ;
2018-06-18 15:44:23 +02:00
get! ( follows ) ;
2018-09-04 12:37:58 +02:00
find_by! ( follows , find_by_ap_url , ap_url as String ) ;
2018-09-26 17:22:42 +02:00
pub fn find ( conn : & Connection , from : i32 , to : i32 ) -> Option < Follow > {
2018-09-04 12:37:58 +02:00
follows ::table . filter ( follows ::follower_id . eq ( from ) )
. filter ( follows ::following_id . eq ( to ) )
. get_result ( conn )
. ok ( )
}
2018-09-26 17:22:42 +02:00
pub fn into_activity ( & self , conn : & Connection ) -> FollowAct {
2018-10-20 08:44:33 +02:00
let user = User ::get ( conn , self . follower_id ) . expect ( " Follow::into_activity: actor not found error " ) ;
let target = User ::get ( conn , self . following_id ) . expect ( " Follow::into_activity: target not found error " ) ;
2018-09-04 12:37:58 +02:00
let mut act = FollowAct ::default ( ) ;
act . follow_props . set_actor_link ::< Id > ( user . clone ( ) . into_id ( ) ) . expect ( " Follow::into_activity: actor error " ) ;
2018-10-20 08:44:33 +02:00
act . follow_props . set_object_object ( user . into_activity ( & * conn ) ) . expect ( " Follow::into_activity: object error " ) ;
act . object_props . set_id_string ( self . ap_url . clone ( ) ) . expect ( " Follow::into_activity: id error " ) ;
act . object_props . set_to_link ( target . clone ( ) . into_id ( ) ) . expect ( " Follow::into_activity: target error " ) ;
act . object_props . set_cc_link_vec ::< Id > ( vec! [ ] ) . expect ( " Follow::into_activity: cc error " ) ;
2018-09-04 12:37:58 +02:00
act
}
2018-06-12 21:10:08 +02:00
2018-06-22 17:17:53 +02:00
/// from -> The one sending the follow request
/// target -> The target of the request, responding with Accept
2018-06-23 13:50:14 +02:00
pub fn accept_follow < A : Signer + IntoId + Clone , B : Clone + WithInbox + Actor + IntoId > (
2018-09-26 17:22:42 +02:00
conn : & Connection ,
2018-06-22 17:17:53 +02:00
from : & B ,
target : & A ,
2018-06-12 21:10:08 +02:00
follow : FollowAct ,
from_id : i32 ,
target_id : i32
) -> Follow {
2018-09-04 12:37:58 +02:00
let from_url : String = from . clone ( ) . into_id ( ) . into ( ) ;
let target_url : String = target . clone ( ) . into_id ( ) . into ( ) ;
2018-06-12 21:10:08 +02:00
let res = Follow ::insert ( conn , NewFollow {
follower_id : from_id ,
2018-09-04 12:37:58 +02:00
following_id : target_id ,
ap_url : format ! ( " {}/follow/{} " , from_url , target_url ) ,
2018-06-12 21:10:08 +02:00
} ) ;
let mut accept = Accept ::default ( ) ;
2018-06-23 13:50:14 +02:00
let accept_id = format! ( " {} #accept " , follow . object_props . id_string ( ) . unwrap_or ( String ::new ( ) ) ) ;
2018-10-20 08:44:33 +02:00
accept . object_props . set_id_string ( accept_id ) . expect ( " Follow::accept_follow: id error " ) ;
accept . object_props . set_to_link ( from . clone ( ) . into_id ( ) ) . expect ( " Follow::accept_follow: to error " ) ;
accept . object_props . set_cc_link_vec ::< Id > ( vec! [ ] ) . expect ( " Follow::accept_follow: cc error " ) ;
accept . accept_props . set_actor_link ::< Id > ( target . clone ( ) . into_id ( ) ) . expect ( " Follow::accept_follow: actor error " ) ;
accept . accept_props . set_object_object ( follow ) . expect ( " Follow::accept_follow: object error " ) ;
2018-06-22 17:17:53 +02:00
broadcast ( & * target , accept , vec! [ from . clone ( ) ] ) ;
2018-06-12 21:10:08 +02:00
res
}
}
2018-09-27 23:06:40 +02:00
impl FromActivity < FollowAct , Connection > for Follow {
2018-09-26 17:22:42 +02:00
fn from_activity ( conn : & Connection , follow : FollowAct , _actor : Id ) -> Follow {
2018-07-08 20:01:19 +02:00
let from_id = follow . follow_props . actor_link ::< Id > ( ) . map ( | l | l . into ( ) )
2018-10-20 08:44:33 +02:00
. unwrap_or_else ( | _ | follow . follow_props . actor_object ::< Person > ( ) . expect ( " Follow::from_activity: actor not found error " ) . object_props . id_string ( ) . expect ( " Follow::from_activity: actor not found error " ) ) ;
let from = User ::from_url ( conn , from_id ) . expect ( " Follow::from_activity: actor not found error " ) ;
match User ::from_url ( conn , follow . follow_props . object . as_str ( ) . expect ( " Follow::from_activity: target url parsing error " ) . to_string ( ) ) {
2018-06-22 17:17:53 +02:00
Some ( user ) = > Follow ::accept_follow ( conn , & from , & user , follow , from . id , user . id ) ,
2018-06-12 21:10:08 +02:00
None = > {
2018-10-20 08:44:33 +02:00
let blog = Blog ::from_url ( conn , follow . follow_props . object . as_str ( ) . expect ( " Follow::from_activity: target url parsing error " ) . to_string ( ) )
. expect ( " Follow::from_activity: target not found error " ) ;
2018-06-12 21:10:08 +02:00
Follow ::accept_follow ( conn , & from , & blog , follow , from . id , blog . id )
}
}
}
2018-05-01 15:06:31 +02:00
}
2018-06-17 21:37:10 +02:00
2018-09-27 23:06:40 +02:00
impl Notify < Connection > for Follow {
2018-09-26 17:22:42 +02:00
fn notify ( & self , conn : & Connection ) {
2018-06-17 21:37:10 +02:00
Notification ::insert ( conn , NewNotification {
2018-07-26 15:46:10 +02:00
kind : notification_kind ::FOLLOW . to_string ( ) ,
object_id : self . id ,
2018-06-20 23:51:47 +02:00
user_id : self . following_id
2018-06-17 21:37:10 +02:00
} ) ;
}
}
2018-09-04 12:37:58 +02:00
2018-09-27 23:06:40 +02:00
impl Deletable < Connection , Undo > for Follow {
2018-09-26 17:22:42 +02:00
fn delete ( & self , conn : & Connection ) -> Undo {
2018-10-20 08:44:33 +02:00
diesel ::delete ( self ) . execute ( conn ) . expect ( " Follow::delete: follow deletion error " ) ;
2018-09-04 12:37:58 +02:00
2018-09-08 00:29:50 +02:00
// delete associated notification if any
if let Some ( notif ) = Notification ::find ( conn , notification_kind ::FOLLOW , self . id ) {
2018-10-20 08:44:33 +02:00
diesel ::delete ( & notif ) . execute ( conn ) . expect ( " Follow::delete: notification deletion error " ) ;
2018-09-08 00:29:50 +02:00
}
2018-09-04 12:37:58 +02:00
let mut undo = Undo ::default ( ) ;
2018-10-20 08:44:33 +02:00
undo . undo_props . set_actor_link ( User ::get ( conn , self . follower_id ) . expect ( " Follow::delete: actor error " ) . into_id ( ) ) . expect ( " Follow::delete: actor error " ) ;
2018-09-04 12:37:58 +02:00
undo . object_props . set_id_string ( format! ( " {} /undo " , self . ap_url ) ) . expect ( " Follow::delete: id error " ) ;
undo . undo_props . set_object_object ( self . into_activity ( conn ) ) . expect ( " Follow::delete: object error " ) ;
undo
}
2018-09-26 17:22:42 +02:00
fn delete_id ( id : String , conn : & Connection ) {
2018-09-04 12:37:58 +02:00
if let Some ( follow ) = Follow ::find_by_ap_url ( conn , id ) {
follow . delete ( conn ) ;
}
}
}