Merge functions for formatting local urls (#5394)

* Merge functions for formatting local urls

* move methods to db structs

* typo
This commit is contained in:
Nutomic 2025-02-07 16:11:16 +00:00 committed by GitHub
parent f0b00ccf94
commit ba7d4bd117
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 92 additions and 137 deletions

View file

@ -141,14 +141,6 @@ pub async fn send_local_notifs(
};
let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
let comment_link = |comment: &Comment| {
format!(
"{}/post/{}/{}",
context.settings().get_protocol_and_hostname(),
post.id,
comment.id
)
};
// Send the local mentions
for mention in mentions
@ -177,7 +169,10 @@ pub async fn send_local_notifs(
PersonCommentMention::create(&mut context.pool(), &person_comment_mention_form)
.await
.ok();
(comment_link(comment), comment.content.clone())
(
comment.local_url(context.settings())?,
comment.content.clone(),
)
} else {
let person_post_mention_form = PersonPostMentionInsertForm {
recipient_id: mention_user_view.person.id,
@ -189,12 +184,10 @@ pub async fn send_local_notifs(
PersonPostMention::create(&mut context.pool(), &person_post_mention_form)
.await
.ok();
let post_link = format!(
"{}/post/{}",
context.settings().get_protocol_and_hostname(),
post.id,
);
(post_link, post.body.clone().unwrap_or_default())
(
post.local_url(context.settings())?,
post.body.clone().unwrap_or_default(),
)
};
// Send an email to those local users that have notifications on
@ -258,7 +251,7 @@ pub async fn send_local_notifs(
&parent_user_view,
&lang.notification_comment_reply_subject(&person.name),
&lang.notification_comment_reply_body(
comment_link(comment),
comment.local_url(context.settings())?,
&content,
&inbox_link,
&parent_comment.content,
@ -311,7 +304,7 @@ pub async fn send_local_notifs(
&parent_user_view,
&lang.notification_post_reply_subject(&person.name),
&lang.notification_post_reply_body(
comment_link(comment),
comment.local_url(context.settings())?,
&content,
&inbox_link,
&post.name,

View file

@ -954,31 +954,6 @@ pub async fn purge_user_account(person_id: PersonId, context: &LemmyContext) ->
Ok(())
}
pub enum EndpointType {
Community,
Person,
Post,
Comment,
PrivateMessage,
}
/// Generates an apub endpoint for a given domain, IE xyz.tld
pub fn generate_local_apub_endpoint(
endpoint_type: EndpointType,
name: &str,
domain: &str,
) -> Result<DbUrl, ParseError> {
let point = match endpoint_type {
EndpointType::Community => "c",
EndpointType::Person => "u",
EndpointType::Post => "post",
EndpointType::Comment => "comment",
EndpointType::PrivateMessage => "private_message",
};
Ok(Url::parse(&format!("{domain}/{point}/{name}"))?.into())
}
pub fn generate_followers_url(ap_id: &DbUrl) -> Result<DbUrl, ParseError> {
Ok(Url::parse(&format!("{ap_id}/followers"))?.into())
}

View file

@ -8,12 +8,10 @@ use lemmy_api_common::{
utils::{
generate_followers_url,
generate_inbox_url,
generate_local_apub_endpoint,
get_url_blocklist,
is_admin,
local_site_to_slur_regex,
process_markdown_opt,
EndpointType,
},
};
use lemmy_db_schema::{
@ -81,12 +79,8 @@ pub async fn create_community(
check_community_visibility_allowed(data.visibility, &local_user_view)?;
// Double check for duplicate community ap_ids
let community_ap_id = generate_local_apub_endpoint(
EndpointType::Community,
&data.name,
&context.settings().get_protocol_and_hostname(),
)?;
// Double check for duplicate community actor_ids
let community_ap_id = Community::local_url(&data.name, context.settings())?;
let community_dupe = Community::read_from_apub_id(&mut context.pool(), &community_ap_id).await?;
if community_dupe.is_some() {
Err(LemmyErrorType::CommunityAlreadyExists)?

View file

@ -10,13 +10,11 @@ use lemmy_api_common::{
check_registration_application,
check_user_valid,
generate_inbox_url,
generate_local_apub_endpoint,
honeypot_check,
local_site_to_slur_regex,
password_length_check,
send_new_applicant_email_to_admins,
send_verification_email,
EndpointType,
},
};
use lemmy_db_schema::{
@ -414,11 +412,7 @@ async fn create_person(
) -> Result<Person, LemmyError> {
let actor_keypair = generate_actor_keypair()?;
is_valid_actor_name(&username, local_site.actor_name_max_length as usize)?;
let ap_id = generate_local_apub_endpoint(
EndpointType::Person,
&username,
&context.settings().get_protocol_and_hostname(),
)?;
let ap_id = Person::local_url(&username, context.settings())?;
// Register the new person
let person_form = PersonInsertForm {

View file

@ -1,10 +1,7 @@
use super::{search::SearchableObjects, user_or_community::UserOrCommunity};
use crate::fetcher::post_or_comment::PostOrComment;
use activitypub_federation::{config::Data, fetch::object_id::ObjectId};
use lemmy_api_common::{
context::LemmyContext,
utils::{generate_local_apub_endpoint, EndpointType},
};
use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::{newtypes::InstanceId, source::instance::Instance};
use lemmy_utils::{
error::LemmyResult,
@ -61,12 +58,8 @@ pub(crate) async fn to_local_url(url: &str, context: &Data<LemmyContext>) -> Opt
let dereferenced = object_id.dereference(context).await.ok()?;
match dereferenced {
SearchableObjects::PostOrComment(pc) => match *pc {
PostOrComment::Post(post) => {
generate_local_apub_endpoint(EndpointType::Post, &post.id.to_string(), local_domain)
}
PostOrComment::Comment(comment) => {
generate_local_apub_endpoint(EndpointType::Comment, &comment.id.to_string(), local_domain)
}
PostOrComment::Post(post) => post.local_url(context.settings()),
PostOrComment::Comment(comment) => comment.local_url(context.settings()),
}
.ok()
.map(Into::into),

View file

@ -25,6 +25,7 @@ use diesel::{
};
use diesel_async::RunQueryDsl;
use diesel_ltree::Ltree;
use lemmy_utils::{error::LemmyResult, settings::structs::Settings};
use url::Url;
impl Comment {
@ -116,6 +117,11 @@ impl Comment {
None
}
}
pub fn local_url(&self, settings: &Settings) -> LemmyResult<DbUrl> {
let domain = settings.get_protocol_and_hostname();
Ok(Url::parse(&format!("{domain}/comment/{}", self.id))?.into())
}
}
#[async_trait]

View file

@ -47,7 +47,11 @@ use diesel::{
Queryable,
};
use diesel_async::RunQueryDsl;
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
use lemmy_utils::{
error::{LemmyErrorType, LemmyResult},
settings::structs::Settings,
};
use url::Url;
#[async_trait]
impl Crud for Community {
@ -273,6 +277,11 @@ impl Community {
.eq(false)
.and(community::deleted.eq(false))
}
pub fn local_url(name: &str, settings: &Settings) -> LemmyResult<DbUrl> {
let domain = settings.get_protocol_and_hostname();
Ok(Url::parse(&format!("{domain}/c/{name}"))?.into())
}
}
impl CommunityModerator {

View file

@ -24,7 +24,11 @@ use diesel::{
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
use lemmy_utils::{
error::{LemmyErrorType, LemmyResult},
settings::structs::Settings,
};
use url::Url;
#[async_trait]
impl Crud for Person {
@ -138,6 +142,11 @@ impl Person {
.then_some(())
.ok_or(LemmyErrorType::UsernameAlreadyExists.into())
}
pub fn local_url(name: &str, settings: &Settings) -> LemmyResult<DbUrl> {
let domain = settings.get_protocol_and_hostname();
Ok(Url::parse(&format!("{domain}/u/{name}"))?.into())
}
}
impl PersonInsertForm {

View file

@ -41,7 +41,10 @@ use diesel::{
TextExpressionMethods,
};
use diesel_async::RunQueryDsl;
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
use lemmy_utils::{
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
settings::structs::Settings,
};
#[async_trait]
impl Crud for Post {
@ -270,6 +273,11 @@ impl Post {
.first::<i64>(conn)
.await
}
pub fn local_url(&self, settings: &Settings) -> LemmyResult<DbUrl> {
let domain = settings.get_protocol_and_hostname();
Ok(Url::parse(&format!("{domain}/post/{}", self.id))?.into())
}
}
#[async_trait]

View file

@ -9,6 +9,7 @@ use crate::{
use chrono::{DateTime, Utc};
use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
use lemmy_utils::{error::LemmyResult, settings::structs::Settings};
use url::Url;
#[async_trait]
@ -82,6 +83,10 @@ impl PrivateMessage {
.await
.optional()
}
pub fn local_url(&self, settings: &Settings) -> LemmyResult<DbUrl> {
let domain = settings.get_protocol_and_hostname();
Ok(Url::parse(&format!("{domain}/private_message/{}", self.id))?.into())
}
}
#[cfg(test)]

View file

@ -20,6 +20,7 @@ use lemmy_db_views::{
use lemmy_utils::{
cache_header::cache_1hour,
error::{LemmyError, LemmyErrorType, LemmyResult},
settings::structs::Settings,
utils::markdown::markdown_to_html,
};
use rss::{
@ -143,7 +144,7 @@ async fn get_feed_data(
.list(&site_view.site, &mut context.pool())
.await?;
let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?;
let items = create_post_items(posts, context.settings())?;
let mut channel = Channel {
namespaces: RSS_NAMESPACE.clone(),
@ -250,7 +251,7 @@ async fn get_feed_user(
.list(&site_view.site, &mut context.pool())
.await?;
let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?;
let items = create_post_items(posts, context.settings())?;
let channel = Channel {
namespaces: RSS_NAMESPACE.clone(),
title: format!("{} - {}", site_view.site.name, person.name),
@ -289,7 +290,7 @@ async fn get_feed_community(
.list(&site_view.site, &mut context.pool())
.await?;
let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?;
let items = create_post_items(posts, context.settings())?;
let mut channel = Channel {
namespaces: RSS_NAMESPACE.clone(),
@ -330,7 +331,7 @@ async fn get_feed_front(
.await?;
let protocol_and_hostname = context.settings().get_protocol_and_hostname();
let items = create_post_items(posts, &protocol_and_hostname)?;
let items = create_post_items(posts, context.settings())?;
let mut channel = Channel {
namespaces: RSS_NAMESPACE.clone(),
title: format!("{} - Subscribed", site_view.site.name),
@ -362,7 +363,7 @@ async fn get_feed_inbox(context: &LemmyContext, jwt: &str) -> LemmyResult<Channe
.await?;
let protocol_and_hostname = context.settings().get_protocol_and_hostname();
let items = create_reply_and_mention_items(inbox, &protocol_and_hostname)?;
let items = create_reply_and_mention_items(inbox, &protocol_and_hostname, context)?;
let mut channel = Channel {
namespaces: RSS_NAMESPACE.clone(),
@ -382,36 +383,37 @@ async fn get_feed_inbox(context: &LemmyContext, jwt: &str) -> LemmyResult<Channe
fn create_reply_and_mention_items(
inbox: Vec<InboxCombinedView>,
protocol_and_hostname: &str,
context: &LemmyContext,
) -> LemmyResult<Vec<Item>> {
let reply_items: Vec<Item> = inbox
.iter()
.map(|r| match r {
InboxCombinedView::CommentReply(v) => {
let reply_url = format!("{}/comment/{}", protocol_and_hostname, v.comment.id);
let reply_url = v.comment.local_url(context.settings())?;
build_item(
&v.creator.name,
&v.comment.published,
&reply_url,
reply_url.as_str(),
&v.comment.content,
protocol_and_hostname,
)
}
InboxCombinedView::CommentMention(v) => {
let mention_url = format!("{}/comment/{}", protocol_and_hostname, v.comment.id);
let mention_url = v.comment.local_url(context.settings())?;
build_item(
&v.creator.name,
&v.comment.published,
&mention_url,
mention_url.as_str(),
&v.comment.content,
protocol_and_hostname,
)
}
InboxCombinedView::PostMention(v) => {
let mention_url = format!("{}/post/{}", protocol_and_hostname, v.post.id);
let mention_url = v.post.local_url(context.settings())?;
build_item(
&v.creator.name,
&v.post.published,
&mention_url,
mention_url.as_str(),
&v.post.body.clone().unwrap_or_default(),
protocol_and_hostname,
)
@ -461,19 +463,19 @@ fn build_item(
})
}
fn create_post_items(posts: Vec<PostView>, protocol_and_hostname: &str) -> LemmyResult<Vec<Item>> {
fn create_post_items(posts: Vec<PostView>, settings: &Settings) -> LemmyResult<Vec<Item>> {
let mut items: Vec<Item> = Vec::new();
for p in posts {
let post_url = format!("{}/post/{}", protocol_and_hostname, p.post.id);
let community_url = format!("{}/c/{}", protocol_and_hostname, &p.community.name);
let post_url = p.post.local_url(settings)?;
let community_url = Community::local_url(&p.community.name, settings)?;
let dublin_core_ext = Some(DublinCoreExtension {
creators: vec![p.creator.ap_id.to_string()],
..DublinCoreExtension::default()
});
let guid = Some(Guid {
permalink: true,
value: post_url.clone(),
value: post_url.to_string(),
});
let mut description = format!("submitted by <a href=\"{}\">{}</a> to <a href=\"{}\">{}</a><br>{} points | <a href=\"{}\">{} comments</a>",
p.creator.ap_id,
@ -532,11 +534,11 @@ fn create_post_items(posts: Vec<PostView>, protocol_and_hostname: &str) -> Lemmy
let i = Item {
title: Some(p.post.name),
pub_date: Some(p.post.published.to_rfc2822()),
comments: Some(post_url.clone()),
comments: Some(post_url.to_string()),
guid,
description: Some(description),
dublin_core_ext,
link: Some(post_url.clone()),
link: Some(post_url.to_string()),
extensions,
enclosure: enclosure_opt,
categories: vec![category],

View file

@ -11,7 +11,7 @@ use diesel::{
use diesel_async::RunQueryDsl;
use lemmy_api_common::{
lemmy_db_views::structs::SiteView,
utils::{generate_followers_url, generate_inbox_url, generate_local_apub_endpoint, EndpointType},
utils::{generate_followers_url, generate_inbox_url},
};
use lemmy_db_schema::{
source::{
@ -41,11 +41,11 @@ pub async fn run_advanced_migrations(
settings: &Settings,
) -> LemmyResult<()> {
let protocol_and_hostname = &settings.get_protocol_and_hostname();
user_updates_2020_04_02(pool, protocol_and_hostname).await?;
community_updates_2020_04_02(pool, protocol_and_hostname).await?;
post_updates_2020_04_03(pool, protocol_and_hostname).await?;
comment_updates_2020_04_03(pool, protocol_and_hostname).await?;
private_message_updates_2020_05_05(pool, protocol_and_hostname).await?;
user_updates_2020_04_02(pool, settings).await?;
community_updates_2020_04_02(pool, settings).await?;
post_updates_2020_04_03(pool, settings).await?;
comment_updates_2020_04_03(pool, settings).await?;
private_message_updates_2020_05_05(pool, settings).await?;
post_thumbnail_url_updates_2020_07_27(pool, protocol_and_hostname).await?;
apub_columns_2021_02_02(pool).await?;
instance_actor_2022_01_28(pool, protocol_and_hostname).await?;
@ -55,10 +55,7 @@ pub async fn run_advanced_migrations(
Ok(())
}
async fn user_updates_2020_04_02(
pool: &mut DbPool<'_>,
protocol_and_hostname: &str,
) -> LemmyResult<()> {
async fn user_updates_2020_04_02(pool: &mut DbPool<'_>, settings: &Settings) -> LemmyResult<()> {
use lemmy_db_schema::schema::person::dsl::{ap_id, local, person};
let conn = &mut get_conn(pool).await?;
@ -75,11 +72,7 @@ async fn user_updates_2020_04_02(
let keypair = generate_actor_keypair()?;
let form = PersonUpdateForm {
ap_id: Some(generate_local_apub_endpoint(
EndpointType::Person,
&cperson.name,
protocol_and_hostname,
)?),
ap_id: Some(Person::local_url(&cperson.name, settings)?),
private_key: Some(Some(keypair.private_key)),
public_key: Some(keypair.public_key),
last_refreshed_at: Some(Utc::now()),
@ -96,7 +89,7 @@ async fn user_updates_2020_04_02(
async fn community_updates_2020_04_02(
pool: &mut DbPool<'_>,
protocol_and_hostname: &str,
settings: &Settings,
) -> LemmyResult<()> {
use lemmy_db_schema::schema::community::dsl::{ap_id, community, local};
let conn = &mut get_conn(pool).await?;
@ -112,11 +105,7 @@ async fn community_updates_2020_04_02(
for ccommunity in &incorrect_communities {
let keypair = generate_actor_keypair()?;
let community_ap_id = generate_local_apub_endpoint(
EndpointType::Community,
&ccommunity.name,
protocol_and_hostname,
)?;
let community_ap_id = Community::local_url(&ccommunity.name, settings)?;
let form = CommunityUpdateForm {
ap_id: Some(community_ap_id.clone()),
@ -134,10 +123,7 @@ async fn community_updates_2020_04_02(
Ok(())
}
async fn post_updates_2020_04_03(
pool: &mut DbPool<'_>,
protocol_and_hostname: &str,
) -> LemmyResult<()> {
async fn post_updates_2020_04_03(pool: &mut DbPool<'_>, settings: &Settings) -> LemmyResult<()> {
use lemmy_db_schema::schema::post::dsl::{ap_id, local, post};
let conn = &mut get_conn(pool).await?;
@ -151,11 +137,7 @@ async fn post_updates_2020_04_03(
.await?;
for cpost in &incorrect_posts {
let apub_id = generate_local_apub_endpoint(
EndpointType::Post,
&cpost.id.to_string(),
protocol_and_hostname,
)?;
let apub_id = cpost.local_url(settings)?;
Post::update(
pool,
cpost.id,
@ -172,10 +154,7 @@ async fn post_updates_2020_04_03(
Ok(())
}
async fn comment_updates_2020_04_03(
pool: &mut DbPool<'_>,
protocol_and_hostname: &str,
) -> LemmyResult<()> {
async fn comment_updates_2020_04_03(pool: &mut DbPool<'_>, settings: &Settings) -> LemmyResult<()> {
use lemmy_db_schema::schema::comment::dsl::{ap_id, comment, local};
let conn = &mut get_conn(pool).await?;
@ -189,11 +168,7 @@ async fn comment_updates_2020_04_03(
.await?;
for ccomment in &incorrect_comments {
let apub_id = generate_local_apub_endpoint(
EndpointType::Comment,
&ccomment.id.to_string(),
protocol_and_hostname,
)?;
let apub_id = ccomment.local_url(settings)?;
Comment::update(
pool,
ccomment.id,
@ -212,7 +187,7 @@ async fn comment_updates_2020_04_03(
async fn private_message_updates_2020_05_05(
pool: &mut DbPool<'_>,
protocol_and_hostname: &str,
settings: &Settings,
) -> LemmyResult<()> {
use lemmy_db_schema::schema::private_message::dsl::{ap_id, local, private_message};
let conn = &mut get_conn(pool).await?;
@ -227,11 +202,7 @@ async fn private_message_updates_2020_05_05(
.await?;
for cpm in &incorrect_pms {
let apub_id = generate_local_apub_endpoint(
EndpointType::PrivateMessage,
&cpm.id.to_string(),
protocol_and_hostname,
)?;
let apub_id = cpm.local_url(settings)?;
PrivateMessage::update(
pool,
cpm.id,
@ -431,11 +402,7 @@ async fn initialize_local_site_2022_10_10(
if let Some(setup) = &settings.setup {
let person_keypair = generate_actor_keypair()?;
let person_ap_id = generate_local_apub_endpoint(
EndpointType::Person,
&setup.admin_username,
&settings.get_protocol_and_hostname(),
)?;
let person_ap_id = Person::local_url(&setup.admin_username, settings)?;
// Register the user if there's a site setup
let person_form = PersonInsertForm {