Refactor mention_to_acct to return detailed actor address

This commit is contained in:
silverpill 2021-12-19 22:15:14 +00:00
parent 0fe8423031
commit fae3f5bc2f
3 changed files with 43 additions and 19 deletions

View file

@ -124,6 +124,23 @@ impl DbActorProfile {
} }
} }
pub struct ActorAddress {
pub username: String,
pub instance: String,
pub is_local: bool,
}
impl ActorAddress {
/// Returns acct string, as used in Mastodon
pub fn acct(&self) -> String {
if self.is_local {
self.username.clone()
} else {
format!("{}@{}", self.username, self.instance)
}
}
}
pub type ActorKeyError = rsa::pkcs8::Error; pub type ActorKeyError = rsa::pkcs8::Error;
pub fn get_local_actor( pub fn get_local_actor(

View file

@ -9,7 +9,7 @@ use crate::config::{Config, Instance};
use crate::database::{Pool, get_database_client}; use crate::database::{Pool, get_database_client};
use crate::errors::{DatabaseError, HttpError, ValidationError}; use crate::errors::{DatabaseError, HttpError, ValidationError};
use crate::models::attachments::queries::create_attachment; use crate::models::attachments::queries::create_attachment;
use crate::models::posts::mentions::mention_to_acct; use crate::models::posts::mentions::mention_to_address;
use crate::models::posts::queries::{ use crate::models::posts::queries::{
create_post, create_post,
get_post_by_id, get_post_by_id,
@ -243,8 +243,14 @@ pub async fn process_note(
}; };
} else if tag.tag_type == MENTION { } else if tag.tag_type == MENTION {
// Ignore invalid mentions // Ignore invalid mentions
if let Ok(acct) = mention_to_acct(&instance.host(), &tag.name) { if let Ok(actor_address) = mention_to_address(
let profile = get_profile_by_acct(db_client, &acct).await?; &instance.host(),
&tag.name,
) {
let profile = get_profile_by_acct(
db_client,
&actor_address.acct(),
).await?;
if !mentions.contains(&profile.id) { if !mentions.contains(&profile.id) {
mentions.push(profile.id); mentions.push(profile.id);
}; };

View file

@ -3,6 +3,7 @@ use std::collections::HashMap;
use regex::{Captures, Regex}; use regex::{Captures, Regex};
use tokio_postgres::GenericClient; use tokio_postgres::GenericClient;
use crate::activitypub::actor::ActorAddress;
use crate::errors::{DatabaseError, ValidationError}; use crate::errors::{DatabaseError, ValidationError};
use crate::models::profiles::queries::get_profiles_by_accts; use crate::models::profiles::queries::get_profiles_by_accts;
use crate::models::profiles::types::DbActorProfile; use crate::models::profiles::types::DbActorProfile;
@ -10,11 +11,11 @@ use crate::models::profiles::types::DbActorProfile;
const MENTION_RE: &str = r"@?(?P<user>\w+)@(?P<instance>.+)"; const MENTION_RE: &str = r"@?(?P<user>\w+)@(?P<instance>.+)";
const MENTION_SEARCH_RE: &str = r"(?m)(?P<space>^|\s)@(?P<user>\w+)@(?P<instance>\S+)"; const MENTION_SEARCH_RE: &str = r"(?m)(?P<space>^|\s)@(?P<user>\w+)@(?P<instance>\S+)";
fn pattern_to_acct(caps: &Captures, instance_host: &str) -> String { fn pattern_to_address(caps: &Captures, instance_host: &str) -> ActorAddress {
if &caps["instance"] == instance_host { ActorAddress {
caps["user"].to_string() username: caps["user"].to_string(),
} else { instance: caps["instance"].to_string(),
format!("{}@{}", &caps["user"], &caps["instance"]) is_local: &caps["instance"] == instance_host,
} }
} }
@ -26,7 +27,7 @@ fn find_mentions(
let mention_re = Regex::new(MENTION_SEARCH_RE).unwrap(); let mention_re = Regex::new(MENTION_SEARCH_RE).unwrap();
let mut mentions = vec![]; let mut mentions = vec![];
for caps in mention_re.captures_iter(text) { for caps in mention_re.captures_iter(text) {
let acct = pattern_to_acct(&caps, instance_host); let acct = pattern_to_address(&caps, instance_host).acct();
if !mentions.contains(&acct) { if !mentions.contains(&acct) {
mentions.push(acct); mentions.push(acct);
}; };
@ -56,7 +57,7 @@ pub fn replace_mentions(
) -> String { ) -> String {
let mention_re = Regex::new(MENTION_SEARCH_RE).unwrap(); let mention_re = Regex::new(MENTION_SEARCH_RE).unwrap();
let result = mention_re.replace_all(text, |caps: &Captures| { let result = mention_re.replace_all(text, |caps: &Captures| {
let acct = pattern_to_acct(caps, instance_host); let acct = pattern_to_address(caps, instance_host).acct();
match mention_map.get(&acct) { match mention_map.get(&acct) {
Some(profile) => { Some(profile) => {
// Replace with a link to profile. // Replace with a link to profile.
@ -76,15 +77,15 @@ pub fn replace_mentions(
result.to_string() result.to_string()
} }
pub fn mention_to_acct( pub fn mention_to_address(
instance_host: &str, instance_host: &str,
mention: &str, mention: &str,
) -> Result<String, ValidationError> { ) -> Result<ActorAddress, ValidationError> {
let mention_re = Regex::new(MENTION_RE).unwrap(); let mention_re = Regex::new(MENTION_RE).unwrap();
let mention_caps = mention_re.captures(mention) let mention_caps = mention_re.captures(mention)
.ok_or(ValidationError("invalid mention tag"))?; .ok_or(ValidationError("invalid mention tag"))?;
let acct = pattern_to_acct(&mention_caps, instance_host); let actor_address = pattern_to_address(&mention_caps, instance_host);
Ok(acct) Ok(actor_address)
} }
#[cfg(test)] #[cfg(test)]
@ -146,12 +147,12 @@ mod tests {
} }
#[test] #[test]
fn test_mention_to_acct() { fn test_mention_to_address() {
let mention = "@user@example.com"; let mention = "@user@example.com";
let acct_1 = mention_to_acct("example.com", mention).unwrap(); let address_1 = mention_to_address("example.com", mention).unwrap();
assert_eq!(acct_1, "user"); assert_eq!(address_1.acct(), "user");
let acct_2 = mention_to_acct("server.info", mention).unwrap(); let address_2 = mention_to_address("server.info", mention).unwrap();
assert_eq!(acct_2, "user@example.com"); assert_eq!(address_2.acct(), "user@example.com");
} }
} }