diff --git a/crates/api_common/src/post.rs b/crates/api_common/src/post.rs index 36f971ca7..1db07e451 100644 --- a/crates/api_common/src/post.rs +++ b/crates/api_common/src/post.rs @@ -28,6 +28,9 @@ pub struct CreatePost { pub honeypot: Option, pub nsfw: Option, pub language_id: Option, + #[cfg_attr(feature = "full", ts(type = "string"))] + /// Instead of fetching a thumbnail, use a custom one. + pub custom_thumbnail: Option, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -114,6 +117,9 @@ pub struct EditPost { pub body: Option, pub nsfw: Option, pub language_id: Option, + #[cfg_attr(feature = "full", ts(type = "string"))] + /// Instead of fetching a thumbnail, use a custom one. + pub custom_thumbnail: Option, } #[derive(Debug, Serialize, Deserialize, Clone, Copy, Default, PartialEq, Eq, Hash)] diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 910454d5b..a5a9c013f 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -57,10 +57,12 @@ pub async fn create_post( let data_url = data.url.as_ref(); let url = data_url.map(clean_url_params); // TODO no good way to handle a "clear" + let custom_thumbnail = data.custom_thumbnail.as_ref().map(clean_url_params); is_valid_post_title(&data.name)?; is_valid_body_field(&body, true)?; - check_url_scheme(&data.url)?; + check_url_scheme(&url)?; + check_url_scheme(&custom_thumbnail)?; check_community_user_action( &local_user_view.person, @@ -84,9 +86,17 @@ pub async fn create_post( } } + // Only generate the thumbnail if there's no custom thumbnail provided, + // otherwise it will save it in pictrs + let generate_thumbnail = custom_thumbnail.is_none(); + // Fetch post links and pictrs cached image - let metadata = fetch_link_metadata_opt(url.as_ref(), true, &context).await; + let metadata = fetch_link_metadata_opt(url.as_ref(), generate_thumbnail, &context).await; let url = proxy_image_link_opt_apub(url, &context).await?; + let thumbnail_url = proxy_image_link_opt_apub(custom_thumbnail, &context) + .await? + .map(Into::into) + .or(metadata.thumbnail); // Only need to check if language is allowed in case user set it explicitly. When using default // language, it already only returns allowed languages. @@ -121,7 +131,7 @@ pub async fn create_post( .embed_description(metadata.opengraph_data.description) .embed_video_url(metadata.opengraph_data.embed_video_url) .language_id(language_id) - .thumbnail_url(metadata.thumbnail) + .thumbnail_url(thumbnail_url) .build(); let inserted_post = Post::create(&mut context.pool(), &post_form) diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index c36718615..e858d9b30 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -43,6 +43,7 @@ pub async fn update_post( // TODO No good way to handle a clear. // Issue link: https://github.com/LemmyNet/lemmy/issues/2287 let url = data.url.as_ref().map(clean_url_params); + let custom_thumbnail = data.custom_thumbnail.as_ref().map(clean_url_params); let slur_regex = local_site_to_slur_regex(&local_site); check_slurs_opt(&data.name, &slur_regex)?; @@ -53,7 +54,8 @@ pub async fn update_post( } is_valid_body_field(&body, true)?; - check_url_scheme(&data.url)?; + check_url_scheme(&url)?; + check_url_scheme(&custom_thumbnail)?; let post_id = data.post_id; let orig_post = Post::read(&mut context.pool(), post_id).await?; @@ -70,10 +72,14 @@ pub async fn update_post( Err(LemmyErrorType::NoPostEditAllowed)? } - // Fetch post links and Pictrs cached image if url was updated - let (embed_title, embed_description, embed_video_url, thumbnail_url) = match &url { + // Fetch post links and thumbnail if url was updated + let (embed_title, embed_description, embed_video_url, metadata_thumbnail) = match &url { Some(url) => { - let metadata = fetch_link_metadata(url, true, &context).await?; + // Only generate the thumbnail if there's no custom thumbnail provided, + // otherwise it will save it in pictrs + let generate_thumbnail = custom_thumbnail.is_none(); + + let metadata = fetch_link_metadata(url, generate_thumbnail, &context).await?; ( Some(metadata.opengraph_data.title), Some(metadata.opengraph_data.description), @@ -83,11 +89,21 @@ pub async fn update_post( } _ => Default::default(), }; + let url = match url { Some(url) => Some(proxy_image_link_opt_apub(Some(url), &context).await?), _ => Default::default(), }; + let custom_thumbnail = match custom_thumbnail { + Some(custom_thumbnail) => { + Some(proxy_image_link_opt_apub(Some(custom_thumbnail), &context).await?) + } + _ => Default::default(), + }; + + let thumbnail_url = custom_thumbnail.or(metadata_thumbnail); + let language_id = data.language_id; CommunityLanguage::is_allowed_community_language( &mut context.pool(),