From 5507d2d680be6b672d341de8a56736c8cdd6bc6f Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Fri, 27 Oct 2023 16:21:06 +0200 Subject: [PATCH] include url content type when sending post over apub (fixes #2611) --- Cargo.lock | 1 + Cargo.toml | 1 + crates/api_common/Cargo.toml | 3 ++- crates/api_common/src/request.rs | 4 +++- crates/apub/Cargo.toml | 3 ++- crates/apub/src/objects/post.rs | 15 ++++++++++++++- crates/apub/src/protocol/objects/page.rs | 16 +++++++++------- 7 files changed, 32 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b25d96ab..42e66ea49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2654,6 +2654,7 @@ dependencies = [ "lemmy_db_views", "lemmy_db_views_actor", "lemmy_utils", + "mime", "moka", "once_cell", "reqwest", diff --git a/Cargo.toml b/Cargo.toml index 9b365a95f..f152a86a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -129,6 +129,7 @@ tokio-postgres = "0.7.10" tokio-postgres-rustls = "0.10.0" urlencoding = "2.1.3" enum-map = "2.7" +mime = "0.3.17" [dependencies] lemmy_api = { workspace = true } diff --git a/crates/api_common/Cargo.toml b/crates/api_common/Cargo.toml index b1f4cca71..16a0e6bc6 100644 --- a/crates/api_common/Cargo.toml +++ b/crates/api_common/Cargo.toml @@ -34,6 +34,7 @@ full = [ "futures", "once_cell", "jsonwebtoken", + "mime" ] [dependencies] @@ -62,6 +63,7 @@ actix-web = { workspace = true, optional = true } enum-map = { workspace = true } urlencoding = { workspace = true } async-trait = { workspace = true } +mime = { workspace = true, optional = true } webpage = { version = "1.6", default-features = false, features = [ "serde", ], optional = true } @@ -70,7 +72,6 @@ jsonwebtoken = { version = "8.3.0", optional = true } # necessary for wasmt compilation getrandom = { version = "0.2.10", features = ["js"] } task-local-extensions = "0.1.4" -mime = "0.3.17" [dev-dependencies] serial_test = { workspace = true } diff --git a/crates/api_common/src/request.rs b/crates/api_common/src/request.rs index b22f3ccfc..70912ba48 100644 --- a/crates/api_common/src/request.rs +++ b/crates/api_common/src/request.rs @@ -29,6 +29,8 @@ pub fn client_builder(settings: &Settings) -> ClientBuilder { } /// Fetches metadata for the given link and optionally generates thumbnail. +/// +/// TODO: consider caching the results as it will be called by api then apub send right after each other #[tracing::instrument(skip_all)] pub async fn fetch_link_metadata( url: &Url, @@ -253,7 +255,7 @@ async fn generate_pictrs_thumbnail( } } -// TODO: get rid of this +// TODO: get rid of this by storing content type in db #[tracing::instrument(skip_all)] async fn is_image_content_type(client: &ClientWithMiddleware, url: &Url) -> Result<(), LemmyError> { let response = client.get(url.as_str()).send().await?; diff --git a/crates/apub/Cargo.toml b/crates/apub/Cargo.toml index 66f46392b..b67a9fb74 100644 --- a/crates/apub/Cargo.toml +++ b/crates/apub/Cargo.toml @@ -37,10 +37,11 @@ async-trait = { workspace = true } anyhow = { workspace = true } reqwest = { workspace = true } once_cell = { workspace = true } +serde_with = { workspace = true } +mime = { workspace = true } html2md = "0.2.14" html2text = "0.6.0" stringreader = "0.1.1" -serde_with = { workspace = true } enum_delegate = "0.2.0" moka = { version = "0.11", features = ["future"] } diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index 223103687..d87eaad9f 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -112,6 +112,19 @@ impl Object for ApubPost { let community = Community::read(&mut context.pool(), community_id).await?; let language = LanguageTag::new_single(self.language_id, &mut context.pool()).await?; + let metadata = match &self.url { + Some(url) => fetch_link_metadata(url, false, &context) + .await + .unwrap_or_default(), + _ => Default::default(), + }; + let attachment = self + .url + .clone() + .map(|url| Attachment::new(url, metadata.content_type)) + .into_iter() + .collect(); + let page = Page { kind: PageType::Page, id: self.ap_id.clone().into(), @@ -122,7 +135,7 @@ impl Object for ApubPost { content: self.body.as_ref().map(|b| markdown_to_html(b)), media_type: Some(MediaTypeMarkdownOrHtml::Html), source: self.body.clone().map(Source::new), - attachment: self.url.clone().map(Attachment::new).into_iter().collect(), + attachment, image: self.thumbnail_url.clone().map(ImageObject::new), comments_enabled: Some(!self.locked), sensitive: Some(self.nsfw), diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs index 0d4880383..d84ee053a 100644 --- a/crates/apub/src/protocol/objects/page.rs +++ b/crates/apub/src/protocol/objects/page.rs @@ -72,24 +72,25 @@ pub struct Page { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub(crate) struct Link { - pub(crate) href: Url, - pub(crate) r#type: LinkType, + href: Url, + content_type: Option, + r#type: LinkType, } #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub(crate) struct Image { #[serde(rename = "type")] - pub(crate) kind: ImageType, - pub(crate) url: Url, + kind: ImageType, + url: Url, } #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub(crate) struct Document { #[serde(rename = "type")] - pub(crate) kind: DocumentType, - pub(crate) url: Url, + kind: DocumentType, + url: Url, } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -167,9 +168,10 @@ impl Page { } impl Attachment { - pub(crate) fn new(url: DbUrl) -> Attachment { + pub(crate) fn new(url: DbUrl, content_type: Option) -> Attachment { Attachment::Link(Link { href: url.into(), + content_type, r#type: Default::default(), }) }