diff --git a/src/activitypub/activity.rs b/src/activitypub/activity.rs index 4ff3bd6..18c3a3b 100644 --- a/src/activitypub/activity.rs +++ b/src/activitypub/activity.rs @@ -5,7 +5,6 @@ use uuid::Uuid; use crate::models::posts::types::Post; use crate::models::profiles::types::DbActorProfile; -use crate::utils::id::new_uuid; use super::constants::{AP_CONTEXT, AP_PUBLIC}; use super::views::{ get_actor_url, @@ -220,34 +219,9 @@ pub fn create_activity_undo_announce( ) } -pub fn create_activity_accept_follow( - instance_url: &str, - actor_profile: &DbActorProfile, - follow_activity_id: &str, - source_actor_id: &str, -) -> Activity { - let object = Object { - context: Some(json!(AP_CONTEXT)), - id: follow_activity_id.to_string(), - object_type: FOLLOW.to_string(), - ..Default::default() - }; - // Accept(Follow) is idempotent so its ID can be random - let activity_id = get_object_url(instance_url, &new_uuid()); - let activity = create_activity( - instance_url, - &actor_profile.username, - ACCEPT, - activity_id, - object, - vec![source_actor_id.to_string()], - vec![], - ); - activity -} - #[cfg(test)] mod tests { + use crate::utils::id::new_uuid; use super::*; const INSTANCE_URL: &str = "https://example.com"; @@ -272,24 +246,4 @@ mod tests { assert_eq!(activity.object, json!(note_id)); assert_eq!(activity.to.unwrap(), json!([AP_PUBLIC, note_author_id])); } - - #[test] - fn test_create_activity_accept_follow() { - let target = DbActorProfile { - username: "user".to_string(), - ..Default::default() - }; - let follow_activity_id = "https://test.remote/objects/999"; - let follower_id = "https://test.remote/users/123"; - let activity = create_activity_accept_follow( - INSTANCE_URL, - &target, - follow_activity_id, - follower_id, - ); - - assert_eq!(activity.id.starts_with(INSTANCE_URL), true); - assert_eq!(activity.object["id"], follow_activity_id); - assert_eq!(activity.to.unwrap(), json!([follower_id])); - } } diff --git a/src/activitypub/builders/accept_follow.rs b/src/activitypub/builders/accept_follow.rs new file mode 100644 index 0000000..0212b53 --- /dev/null +++ b/src/activitypub/builders/accept_follow.rs @@ -0,0 +1,88 @@ +use serde_json::json; + +use crate::activitypub::{ + activity::{create_activity, Activity, Object}, + actor::Actor, + constants::AP_CONTEXT, + deliverer::OutgoingActivity, + views::get_object_url, + vocabulary::{ACCEPT, FOLLOW}, +}; +use crate::config::Instance; +use crate::models::profiles::types::DbActorProfile; +use crate::models::users::types::User; +use crate::utils::id::new_uuid; + +fn build_accept_follow( + instance_url: &str, + actor_profile: &DbActorProfile, + source_actor_id: &str, + follow_activity_id: &str, +) -> Activity { + let object = Object { + context: Some(json!(AP_CONTEXT)), + id: follow_activity_id.to_string(), + object_type: FOLLOW.to_string(), + ..Default::default() + }; + // Accept(Follow) is idempotent so its ID can be random + let activity_id = get_object_url(instance_url, &new_uuid()); + let activity = create_activity( + instance_url, + &actor_profile.username, + ACCEPT, + activity_id, + object, + vec![source_actor_id.to_string()], + vec![], + ); + activity +} + +pub fn prepare_accept_follow( + instance: Instance, + user: &User, + source_actor: &Actor, + follow_activity_id: &str, +) -> OutgoingActivity { + let activity = build_accept_follow( + &instance.url(), + &user.profile, + &source_actor.id, + follow_activity_id, + ); + let recipients = vec![source_actor.clone()]; + OutgoingActivity { + instance, + sender: user.clone(), + activity, + recipients, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const INSTANCE_URL: &str = "https://example.com"; + + #[test] + fn test_create_activity_accept_follow() { + let target = DbActorProfile { + username: "user".to_string(), + ..Default::default() + }; + let follow_activity_id = "https://test.remote/objects/999"; + let follower_id = "https://test.remote/users/123"; + let activity = build_accept_follow( + INSTANCE_URL, + &target, + follower_id, + follow_activity_id, + ); + + assert_eq!(activity.id.starts_with(INSTANCE_URL), true); + assert_eq!(activity.object["id"], follow_activity_id); + assert_eq!(activity.to.unwrap(), json!([follower_id])); + } +} diff --git a/src/activitypub/builders/mod.rs b/src/activitypub/builders/mod.rs index 81088ea..1879bc0 100644 --- a/src/activitypub/builders/mod.rs +++ b/src/activitypub/builders/mod.rs @@ -1,3 +1,4 @@ +pub mod accept_follow; pub mod create_note; pub mod delete_note; pub mod delete_person; diff --git a/src/activitypub/handlers/follow.rs b/src/activitypub/handlers/follow.rs index 20f0dc3..203c001 100644 --- a/src/activitypub/handlers/follow.rs +++ b/src/activitypub/handlers/follow.rs @@ -1,8 +1,8 @@ use tokio_postgres::GenericClient; use crate::activitypub::{ - activity::{create_activity_accept_follow, Activity}, - deliverer::deliver_activity, + activity::Activity, + builders::accept_follow::prepare_accept_follow, fetcher::helpers::{get_or_import_profile_by_actor_id, ImportError}, receiver::{get_object_id, parse_actor_id}, vocabulary::PERSON, @@ -37,13 +37,12 @@ pub async fn handle_follow( }; // Send activity - let new_activity = create_activity_accept_follow( - &config.instance_url(), - &target_user.profile, + prepare_accept_follow( + config.instance(), + &target_user, + &source_actor, &activity.id, - &source_actor.id, - ); - let recipients = vec![source_actor]; - deliver_activity(config, &target_user, new_activity, recipients); + ).spawn_deliver(); + Ok(Some(PERSON)) }