Link hashtags in posts to corresponding tag timeline pages

This commit is contained in:
silverpill 2021-12-12 19:11:04 +00:00
parent da918d2296
commit 816cae6b78
5 changed files with 27 additions and 13 deletions

View file

@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use uuid::Uuid;
use crate::frontend::get_tag_page_url;
use crate::models::posts::types::Post;
use crate::models::profiles::types::DbActorProfile;
use crate::models::users::types::User;
@ -186,10 +187,11 @@ pub fn create_note(
tags.push(tag);
};
for tag_name in &post.tags {
let tag_page_url = get_tag_page_url(instance_url, tag_name);
let tag = Tag {
name: format!("#{}", tag_name),
tag_type: HASHTAG.to_string(),
href: None,
href: Some(tag_page_url),
};
tags.push(tag);
};

View file

@ -71,7 +71,7 @@ async fn actor_view(
let db_client = &**get_database_client(&db_pool).await?;
let user = get_user_by_name(db_client, &username).await?;
if !is_activitypub_request(&request) {
let page_url = get_profile_page_url(&user.id, &config.instance_url());
let page_url = get_profile_page_url(&config.instance_url(), &user.id);
let response = HttpResponse::Found()
.header("Location", page_url)
.finish();
@ -203,7 +203,7 @@ pub async fn object_view(
.find(|post| post.id == internal_object_id && post.author.is_local())
.ok_or(HttpError::NotFoundError("post"))?;
if !is_activitypub_request(&request) {
let page_url = get_post_page_url(&post.id, &config.instance_url());
let page_url = get_post_page_url(&config.instance_url(), &post.id);
let response = HttpResponse::Found()
.header("Location", page_url)
.finish();

View file

@ -2,10 +2,14 @@
use uuid::Uuid;
// Assuming frontend is on the same host as backend
pub fn get_profile_page_url(profile_id: &Uuid, instance_url: &str) -> String {
pub fn get_profile_page_url(instance_url: &str, profile_id: &Uuid) -> String {
format!("{}/profile/{}", instance_url, profile_id)
}
pub fn get_post_page_url(post_id: &Uuid, instance_url: &str) -> String {
pub fn get_post_page_url(instance_url: &str, post_id: &Uuid) -> String {
format!("{}/post/{}", instance_url, post_id)
}
pub fn get_tag_page_url(instance_url: &str, tag_name: &str) -> String {
format!("{}/tag/{}", instance_url, tag_name)
}

View file

@ -72,7 +72,11 @@ async fn create_status(
post_data.mentions = mention_map.values()
.map(|profile| profile.id).collect();
post_data.tags = find_tags(&post_data.content);
post_data.content = replace_tags(&post_data.content, &post_data.tags);
post_data.content = replace_tags(
&instance.url(),
&post_data.content,
&post_data.tags,
);
let post = create_post(db_client, &current_user.id, post_data).await?;
// Federate
let maybe_in_reply_to = match post.in_reply_to_id {

View file

@ -1,6 +1,7 @@
use regex::{Captures, Regex};
use crate::errors::ConversionError;
use crate::frontend::get_tag_page_url;
const HASHTAG_RE: &str = r"(?m)(?P<before>^|\s)#(?P<tag>\S+)";
const HASHTAG_SECONDARY_RE: &str = r"^(?P<tag>[0-9A-Za-z]+)(?P<after>(\.|<br>|\.<br>)?)$";
@ -23,7 +24,7 @@ pub fn find_tags(text: &str) -> Vec<String> {
}
/// Replaces hashtags with links
pub fn replace_tags(text: &str, tags: &[String]) -> String {
pub fn replace_tags(instance_url: &str, text: &str, tags: &[String]) -> String {
let hashtag_re = Regex::new(HASHTAG_RE).unwrap();
let hashtag_secondary_re = Regex::new(HASHTAG_SECONDARY_RE).unwrap();
let result = hashtag_re.replace_all(text, |caps: &Captures| {
@ -33,10 +34,11 @@ pub fn replace_tags(text: &str, tags: &[String]) -> String {
let tag_name = tag.to_lowercase();
let after = secondary_caps["after"].to_string();
if tags.contains(&tag_name) {
let tag_page_url = get_tag_page_url(instance_url, &tag_name);
format!(
r#"{}<a class="hashtag" href="/tag/{}">#{}</a>{}"#,
r#"{}<a class="hashtag" href="{}">#{}</a>{}"#,
before,
tag_name,
tag_page_url,
tag,
after,
)
@ -63,6 +65,8 @@ pub fn normalize_tag(tag: &str) -> Result<String, ConversionError> {
mod tests {
use super::*;
const INSTANCE_URL: &str = "https://example.com";
#[test]
fn test_find_tags() {
let text = concat!(
@ -87,13 +91,13 @@ mod tests {
"more text #tag2",
);
let tags = find_tags(text);
let output = replace_tags(&text, &tags);
let output = replace_tags(INSTANCE_URL, &text, &tags);
let expected_output = concat!(
r#"@user1@server1 some text <a class="hashtag" href="/tag/testtag">#TestTag</a>."#, "\n",
r#"<a class="hashtag" href="/tag/tag1">#TAG1</a> <a class="hashtag" href="/tag/tag1">#tag1</a> "#,
r#"@user1@server1 some text <a class="hashtag" href="https://example.com/tag/testtag">#TestTag</a>."#, "\n",
r#"<a class="hashtag" href="https://example.com/tag/tag1">#TAG1</a> <a class="hashtag" href="https://example.com/tag/tag1">#tag1</a> "#,
r#"#test_underscore #test*special "#,
r#"more text <a class="hashtag" href="/tag/tag2">#tag2</a>"#,
r#"more text <a class="hashtag" href="https://example.com/tag/tag2">#tag2</a>"#,
);
assert_eq!(output, expected_output);
}