diff --git a/src/activitypub/activity.rs b/src/activitypub/activity.rs index de10d61..a6d7d5f 100644 --- a/src/activitypub/activity.rs +++ b/src/activitypub/activity.rs @@ -175,12 +175,13 @@ pub fn create_note( for profile in &post.mentions { let actor_id = profile.actor_id(instance_url).unwrap(); if !profile.is_local() { - recipients.push(actor_id.clone()); + recipients.push(actor_id); }; + let actor_url = profile.actor_url(instance_url).unwrap(); let tag = Tag { name: format!("@{}", profile.actor_address(instance_host)), tag_type: MENTION.to_string(), - href: Some(actor_id), + href: Some(actor_url), }; tags.push(tag); }; @@ -478,10 +479,12 @@ mod tests { fn test_create_note_with_remote_parent() { let parent_author_acct = "test@test.net"; let parent_author_actor_id = "https://test.net/user/test"; + let parent_author_actor_url = "https://test.net/@test"; let parent_author = DbActorProfile { acct: parent_author_acct.to_string(), actor_json: Some(json!({ "id": parent_author_actor_id, + "url": parent_author_actor_url, })), ..Default::default() }; @@ -504,7 +507,7 @@ mod tests { let tags = note.tag; assert_eq!(tags.len(), 1); assert_eq!(tags[0].name, format!("@{}", parent_author_acct)); - assert_eq!(tags[0].href.as_ref().unwrap(), parent_author_actor_id); + assert_eq!(tags[0].href.as_ref().unwrap(), parent_author_actor_url); assert_eq!(note.to, vec![AP_PUBLIC, parent_author_actor_id]); } diff --git a/src/activitypub/actor.rs b/src/activitypub/actor.rs index 9f63e6b..25934a4 100644 --- a/src/activitypub/actor.rs +++ b/src/activitypub/actor.rs @@ -87,6 +87,9 @@ pub struct Actor { #[serde(skip_serializing_if = "Option::is_none")] pub attachment: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub url: Option, } impl Actor { @@ -128,7 +131,7 @@ pub fn get_local_actor( instance_url: &str, ) -> Result { let username = &user.profile.username; - let id = get_actor_url(instance_url, username); + let actor_id = get_actor_url(instance_url, username); let inbox = get_inbox_url(instance_url, username); let outbox = get_outbox_url(instance_url, username); let followers = get_followers_url(instance_url, username); @@ -137,8 +140,8 @@ pub fn get_local_actor( let private_key = deserialize_private_key(&user.private_key)?; let public_key_pem = get_public_key_pem(&private_key)?; let public_key = PublicKey { - id: format!("{}#main-key", id), - owner: id.clone(), + id: format!("{}#main-key", actor_id), + owner: actor_id.clone(), public_key_pem: public_key_pem, }; let capabilities = ActorCapabilities { @@ -178,7 +181,7 @@ pub fn get_local_actor( AP_CONTEXT.to_string(), W3ID_CONTEXT.to_string(), ])), - id, + id: actor_id.clone(), object_type: PERSON.to_string(), name: username.to_string(), preferred_username: username.to_string(), @@ -192,6 +195,7 @@ pub fn get_local_actor( image: banner, summary: None, attachment: Some(properties), + url: Some(actor_id), }; Ok(actor) } @@ -227,6 +231,7 @@ pub fn get_instance_actor( image: None, summary: None, attachment: None, + url: None, }; Ok(actor) } diff --git a/src/models/posts/mentions.rs b/src/models/posts/mentions.rs index c9adf0d..1a40222 100644 --- a/src/models/posts/mentions.rs +++ b/src/models/posts/mentions.rs @@ -59,9 +59,10 @@ pub fn replace_mentions( match mention_map.get(&acct) { Some(profile) => { // Replace with a link - let url = profile.actor_id(instance_url).unwrap(); + let url = profile.actor_url(instance_url).unwrap(); format!( - r#"{}@{}"#, + // https://microformats.org/wiki/h-card + r#"{}@{}"#, caps["space"].to_string(), url, profile.username, @@ -112,6 +113,7 @@ mod tests { username: "user2".to_string(), actor_json: Some(json!({ "id": "https://server2.com/actors/user2", + "url": "https://server2.com/@user2", })), ..Default::default() }; @@ -123,8 +125,8 @@ mod tests { let result = replace_mentions(&mention_map, INSTANCE_HOST, INSTANCE_URL, text); let expected_result = concat!( - r#"@user1 "#, - r#"@user2 "#, + r#"@user1 "#, + r#"@user2 "#, r#"sometext @notmention @test@unknown.org"#, ); assert_eq!(result, expected_result); diff --git a/src/models/profiles/types.rs b/src/models/profiles/types.rs index 983374e..225d74e 100644 --- a/src/models/profiles/types.rs +++ b/src/models/profiles/types.rs @@ -86,6 +86,15 @@ impl DbActorProfile { Ok(actor_id) } + pub fn actor_url(&self, instance_url: &str) -> Result { + if let Some(ref actor_value) = self.actor_json { + if let Some(actor_url) = actor_value["url"].as_str() { + return Ok(actor_url.to_string()); + }; + }; + self.actor_id(instance_url) + } + pub fn actor_address(&self, instance_host: &str) -> String { if self.is_local() { format!("{}@{}", self.acct, instance_host)