Replace actor ID with actor URL in mentions, add microformats

This commit is contained in:
silverpill 2021-12-11 23:25:00 +00:00
parent 2a58f567b9
commit a4dd06d6e9
4 changed files with 30 additions and 11 deletions

View file

@ -175,12 +175,13 @@ pub fn create_note(
for profile in &post.mentions { for profile in &post.mentions {
let actor_id = profile.actor_id(instance_url).unwrap(); let actor_id = profile.actor_id(instance_url).unwrap();
if !profile.is_local() { 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 { let tag = Tag {
name: format!("@{}", profile.actor_address(instance_host)), name: format!("@{}", profile.actor_address(instance_host)),
tag_type: MENTION.to_string(), tag_type: MENTION.to_string(),
href: Some(actor_id), href: Some(actor_url),
}; };
tags.push(tag); tags.push(tag);
}; };
@ -478,10 +479,12 @@ mod tests {
fn test_create_note_with_remote_parent() { fn test_create_note_with_remote_parent() {
let parent_author_acct = "test@test.net"; let parent_author_acct = "test@test.net";
let parent_author_actor_id = "https://test.net/user/test"; let parent_author_actor_id = "https://test.net/user/test";
let parent_author_actor_url = "https://test.net/@test";
let parent_author = DbActorProfile { let parent_author = DbActorProfile {
acct: parent_author_acct.to_string(), acct: parent_author_acct.to_string(),
actor_json: Some(json!({ actor_json: Some(json!({
"id": parent_author_actor_id, "id": parent_author_actor_id,
"url": parent_author_actor_url,
})), })),
..Default::default() ..Default::default()
}; };
@ -504,7 +507,7 @@ mod tests {
let tags = note.tag; let tags = note.tag;
assert_eq!(tags.len(), 1); assert_eq!(tags.len(), 1);
assert_eq!(tags[0].name, format!("@{}", parent_author_acct)); 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]); assert_eq!(note.to, vec![AP_PUBLIC, parent_author_actor_id]);
} }

View file

@ -87,6 +87,9 @@ pub struct Actor {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub attachment: Option<Vec<ActorProperty>>, pub attachment: Option<Vec<ActorProperty>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
} }
impl Actor { impl Actor {
@ -128,7 +131,7 @@ pub fn get_local_actor(
instance_url: &str, instance_url: &str,
) -> Result<Actor, ActorKeyError> { ) -> Result<Actor, ActorKeyError> {
let username = &user.profile.username; 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 inbox = get_inbox_url(instance_url, username);
let outbox = get_outbox_url(instance_url, username); let outbox = get_outbox_url(instance_url, username);
let followers = get_followers_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 private_key = deserialize_private_key(&user.private_key)?;
let public_key_pem = get_public_key_pem(&private_key)?; let public_key_pem = get_public_key_pem(&private_key)?;
let public_key = PublicKey { let public_key = PublicKey {
id: format!("{}#main-key", id), id: format!("{}#main-key", actor_id),
owner: id.clone(), owner: actor_id.clone(),
public_key_pem: public_key_pem, public_key_pem: public_key_pem,
}; };
let capabilities = ActorCapabilities { let capabilities = ActorCapabilities {
@ -178,7 +181,7 @@ pub fn get_local_actor(
AP_CONTEXT.to_string(), AP_CONTEXT.to_string(),
W3ID_CONTEXT.to_string(), W3ID_CONTEXT.to_string(),
])), ])),
id, id: actor_id.clone(),
object_type: PERSON.to_string(), object_type: PERSON.to_string(),
name: username.to_string(), name: username.to_string(),
preferred_username: username.to_string(), preferred_username: username.to_string(),
@ -192,6 +195,7 @@ pub fn get_local_actor(
image: banner, image: banner,
summary: None, summary: None,
attachment: Some(properties), attachment: Some(properties),
url: Some(actor_id),
}; };
Ok(actor) Ok(actor)
} }
@ -227,6 +231,7 @@ pub fn get_instance_actor(
image: None, image: None,
summary: None, summary: None,
attachment: None, attachment: None,
url: None,
}; };
Ok(actor) Ok(actor)
} }

View file

@ -59,9 +59,10 @@ pub fn replace_mentions(
match mention_map.get(&acct) { match mention_map.get(&acct) {
Some(profile) => { Some(profile) => {
// Replace with a link // Replace with a link
let url = profile.actor_id(instance_url).unwrap(); let url = profile.actor_url(instance_url).unwrap();
format!( format!(
r#"{}<a class="mention" href="{}">@{}</a>"#, // https://microformats.org/wiki/h-card
r#"{}<span class="h-card"><a class="u-url mention" href="{}">@{}</a></span>"#,
caps["space"].to_string(), caps["space"].to_string(),
url, url,
profile.username, profile.username,
@ -112,6 +113,7 @@ mod tests {
username: "user2".to_string(), username: "user2".to_string(),
actor_json: Some(json!({ actor_json: Some(json!({
"id": "https://server2.com/actors/user2", "id": "https://server2.com/actors/user2",
"url": "https://server2.com/@user2",
})), })),
..Default::default() ..Default::default()
}; };
@ -123,8 +125,8 @@ mod tests {
let result = replace_mentions(&mention_map, INSTANCE_HOST, INSTANCE_URL, text); let result = replace_mentions(&mention_map, INSTANCE_HOST, INSTANCE_URL, text);
let expected_result = concat!( let expected_result = concat!(
r#"<a class="mention" href="https://server1.com/users/user1">@user1</a> "#, r#"<span class="h-card"><a class="u-url mention" href="https://server1.com/users/user1">@user1</a></span> "#,
r#"<a class="mention" href="https://server2.com/actors/user2">@user2</a> "#, r#"<span class="h-card"><a class="u-url mention" href="https://server2.com/@user2">@user2</a></span> "#,
r#"sometext @notmention @test@unknown.org"#, r#"sometext @notmention @test@unknown.org"#,
); );
assert_eq!(result, expected_result); assert_eq!(result, expected_result);

View file

@ -86,6 +86,15 @@ impl DbActorProfile {
Ok(actor_id) Ok(actor_id)
} }
pub fn actor_url(&self, instance_url: &str) -> Result<String, ConversionError> {
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 { pub fn actor_address(&self, instance_host: &str) -> String {
if self.is_local() { if self.is_local() {
format!("{}@{}", self.acct, instance_host) format!("{}@{}", self.acct, instance_host)