diff --git a/src/activitypub/handlers/create.rs b/src/activitypub/handlers/create.rs index bc9429c..2123fc5 100644 --- a/src/activitypub/handlers/create.rs +++ b/src/activitypub/handlers/create.rs @@ -36,7 +36,6 @@ use crate::models::{ }, emojis::types::{DbEmoji, EmojiImage}, posts::{ - hashtags::normalize_hashtag, queries::create_post, types::{Post, PostCreateData, Visibility}, }, @@ -55,6 +54,7 @@ use crate::validators::{ CONTENT_MAX_SIZE, EMOJIS_MAX_NUM, }, + tags::validate_hashtag, }; use crate::webfinger::types::ActorAddress; use super::HandlerResult; @@ -200,6 +200,12 @@ pub async fn get_object_attachments( Ok((attachments, unprocessed)) } +fn normalize_hashtag(tag: &str) -> Result { + let tag_name = tag.trim_start_matches('#'); + validate_hashtag(tag_name)?; + Ok(tag_name.to_lowercase()) +} + pub fn get_object_links( object: &Object, ) -> Vec { @@ -707,6 +713,14 @@ mod tests { ); } + #[test] + fn test_normalize_hashtag() { + let tag = "#ActivityPub"; + let output = normalize_hashtag(tag).unwrap(); + + assert_eq!(output, "activitypub"); + } + #[test] fn test_get_object_visibility_public() { let author = DbActorProfile::default(); diff --git a/src/models/posts/hashtags.rs b/src/models/posts/hashtags.rs index f25da50..ad3039f 100644 --- a/src/models/posts/hashtags.rs +++ b/src/models/posts/hashtags.rs @@ -1,12 +1,11 @@ use regex::{Captures, Regex}; use crate::activitypub::identifiers::local_tag_collection; -use crate::errors::ValidationError; use super::links::is_inside_code_block; +// See also: HASHTAG_NAME_RE in validators::tags const HASHTAG_RE: &str = r"(?m)(?P^|\s|>|[\(])#(?P[^\s<]+)"; const HASHTAG_SECONDARY_RE: &str = r"^(?P[0-9A-Za-z]+)(?P[\.,:?!\)]?)$"; -const HASHTAG_NAME_RE: &str = r"^\w+$"; /// Finds anything that looks like a hashtag pub fn find_hashtags(text: &str) -> Vec { @@ -60,15 +59,6 @@ pub fn replace_hashtags(instance_url: &str, text: &str, tags: &[String]) -> Stri result.to_string() } -pub fn normalize_hashtag(tag: &str) -> Result { - 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(ValidationError("invalid tag name")); - }; - Ok(tag_name.to_lowercase()) -} - #[cfg(test)] mod tests { use super::*; @@ -112,12 +102,4 @@ mod tests { ); assert_eq!(output, expected_output); } - - #[test] - fn test_normalize_hashtag() { - let tag = "#ActivityPub"; - let output = normalize_hashtag(tag).unwrap(); - - assert_eq!(output, "activitypub"); - } } diff --git a/src/validators/mod.rs b/src/validators/mod.rs index c659e77..36df82d 100644 --- a/src/validators/mod.rs +++ b/src/validators/mod.rs @@ -1,4 +1,5 @@ pub mod emojis; pub mod posts; pub mod profiles; +pub mod tags; pub mod users; diff --git a/src/validators/tags.rs b/src/validators/tags.rs new file mode 100644 index 0000000..85e6055 --- /dev/null +++ b/src/validators/tags.rs @@ -0,0 +1,13 @@ +use regex::Regex; + +use crate::errors::ValidationError; + +const HASHTAG_NAME_RE: &str = r"^\w+$"; + +pub fn validate_hashtag(tag_name: &str) -> Result<(), ValidationError> { + let hashtag_name_re = Regex::new(HASHTAG_NAME_RE).unwrap(); + if !hashtag_name_re.is_match(tag_name) { + return Err(ValidationError("invalid tag name")); + }; + Ok(()) +}