Use mention tag name instead of href when parsing incoming notes

This commit is contained in:
silverpill 2021-12-18 01:09:43 +00:00
parent 2df7f7ced7
commit d31d315517
3 changed files with 36 additions and 16 deletions

View file

@ -9,7 +9,7 @@ use crate::config::{Config, Instance};
use crate::database::{Pool, get_database_client};
use crate::errors::{DatabaseError, HttpError, ValidationError};
use crate::models::attachments::queries::create_attachment;
use crate::models::posts::types::{Post, PostCreateData, Visibility};
use crate::models::posts::mentions::mention_to_acct;
use crate::models::posts::queries::{
create_post,
get_post_by_id,
@ -17,6 +17,7 @@ use crate::models::posts::queries::{
delete_post,
};
use crate::models::posts::tags::normalize_tag;
use crate::models::posts::types::{Post, PostCreateData, Visibility};
use crate::models::profiles::queries::{
get_profile_by_actor_id,
get_profile_by_acct,
@ -241,13 +242,9 @@ pub async fn process_note(
tags.push(tag_name);
};
} else if tag.tag_type == MENTION {
if let Some(href) = tag.href {
let profile = get_or_fetch_profile_by_actor_id(
db_client,
&instance,
&href,
&config.media_dir(),
).await?;
// Ignore invalid mentions
if let Ok(acct) = mention_to_acct(&instance.host(), &tag.name) {
let profile = get_profile_by_acct(db_client, &acct).await?;
if !mentions.contains(&profile.id) {
mentions.push(profile.id);
};

View file

@ -3,11 +3,12 @@ use std::collections::HashMap;
use regex::{Captures, Regex};
use tokio_postgres::GenericClient;
use crate::errors::DatabaseError;
use crate::errors::{DatabaseError, ValidationError};
use crate::models::profiles::queries::get_profiles_by_accts;
use crate::models::profiles::types::DbActorProfile;
const MENTION_RE: &str = r"(?m)(?P<space>^|\s)@(?P<user>\w+)@(?P<instance>\S+)";
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+)";
fn pattern_to_acct(caps: &Captures, instance_host: &str) -> String {
if &caps["instance"] == instance_host {
@ -22,7 +23,7 @@ fn find_mentions(
instance_host: &str,
text: &str,
) -> Vec<String> {
let mention_re = Regex::new(MENTION_RE).unwrap();
let mention_re = Regex::new(MENTION_SEARCH_RE).unwrap();
let mut mentions = vec![];
for caps in mention_re.captures_iter(text) {
let acct = pattern_to_acct(&caps, instance_host);
@ -53,12 +54,13 @@ pub fn replace_mentions(
instance_url: &str,
text: &str,
) -> String {
let mention_re = Regex::new(MENTION_RE).unwrap();
let mention_re = Regex::new(MENTION_SEARCH_RE).unwrap();
let result = mention_re.replace_all(text, |caps: &Captures| {
let acct = pattern_to_acct(caps, instance_host);
match mention_map.get(&acct) {
Some(profile) => {
// Replace with a link
// Replace with a link to profile.
// Actor URL may differ from actor ID.
let url = profile.actor_url(instance_url).unwrap();
format!(
// https://microformats.org/wiki/h-card
@ -74,6 +76,17 @@ pub fn replace_mentions(
result.to_string()
}
pub fn mention_to_acct(
instance_host: &str,
mention: &str,
) -> Result<String, ValidationError> {
let mention_re = Regex::new(MENTION_RE).unwrap();
let mention_caps = mention_re.captures(mention)
.ok_or(ValidationError("invalid mention tag"))?;
let acct = pattern_to_acct(&mention_caps, instance_host);
Ok(acct)
}
#[cfg(test)]
mod tests {
use serde_json::json;
@ -131,4 +144,14 @@ mod tests {
);
assert_eq!(result, expected_result);
}
#[test]
fn test_mention_to_acct() {
let mention = "@user@example.com";
let acct_1 = mention_to_acct("example.com", mention).unwrap();
assert_eq!(acct_1, "user");
let acct_2 = mention_to_acct("server.info", mention).unwrap();
assert_eq!(acct_2, "user@example.com");
}
}

View file

@ -1,6 +1,6 @@
use regex::{Captures, Regex};
use crate::errors::ConversionError;
use crate::errors::ValidationError;
use crate::frontend::get_tag_page_url;
const HASHTAG_RE: &str = r"(?m)(?P<before>^|\s)#(?P<tag>\S+)";
@ -52,11 +52,11 @@ pub fn replace_tags(instance_url: &str, text: &str, tags: &[String]) -> String {
result.to_string()
}
pub fn normalize_tag(tag: &str) -> Result<String, ConversionError> {
pub fn normalize_tag(tag: &str) -> Result<String, ValidationError> {
let hashtag_name_re = Regex::new(HASHTAG_NAME_RE).unwrap();
let tag_name = tag.trim_start_matches('#');
if !hashtag_name_re.is_match(tag_name) {
return Err(ConversionError);
return Err(ValidationError("invalid tag name"));
};
Ok(tag_name.to_lowercase())
}