- async fn from_apub(
- page: Page,
- context: &LemmyContext,
- request_counter: &mut i32,
- ) -> Result<ApubPost, LemmyError> {
- let creator = page
- .attributed_to
- .dereference(context, request_counter)
- .await?;
- let community = page.extract_community(context, request_counter).await?;
-
- let thumbnail_url: Option<Url> = page.image.map(|i| i.url);
- let (metadata_res, pictrs_thumbnail) = if let Some(url) = &page.url {
- fetch_site_data(context.client(), &context.settings(), Some(url)).await
+ #[tracing::instrument(skip_all)]
+ async fn from_json(page: Page, context: &Data<Self::DataType>) -> Result<ApubPost, LemmyError> {
+ let creator = page.creator()?.dereference(context).await?;
+ let community = page.community(context).await?;
+ if community.posting_restricted_to_mods {
+ is_mod_or_admin(&mut context.pool(), creator.id, community.id).await?;
+ }
+ let mut name = page
+ .name
+ .clone()
+ .or_else(|| {
+ page
+ .content
+ .clone()
+ .as_ref()
+ .and_then(|c| parse_html(c).lines().next().map(ToString::to_string))
+ })
+ .ok_or_else(|| anyhow!("Object must have name or content"))?;
+ if name.chars().count() > MAX_TITLE_LENGTH {
+ name = name.chars().take(MAX_TITLE_LENGTH).collect();
+ }
+
+ // read existing, local post if any (for generating mod log)
+ let old_post = page.id.dereference_local(context).await;
+
+ let form = if !page.is_mod_action(context).await? {
+ let first_attachment = page.attachment.into_iter().map(Attachment::url).next();
+ let url = if first_attachment.is_some() {
+ first_attachment
+ } else if page.kind == PageType::Video {
+ // we cant display videos directly, so insert a link to external video page
+ Some(page.id.inner().clone())
+ } else {
+ None
+ };
+ check_url_scheme(&url)?;
+
+ let local_site = LocalSite::read(&mut context.pool()).await.ok();
+ let allow_sensitive = local_site_opt_to_sensitive(&local_site);
+ let page_is_sensitive = page.sensitive.unwrap_or(false);
+ let include_image = allow_sensitive || !page_is_sensitive;
+
+ // Only fetch metadata if the post has a url and was not seen previously. We dont want to
+ // waste resources by fetching metadata for the same post multiple times.
+ // Additionally, only fetch image if content is not sensitive or is allowed on local site.
+ let (metadata_res, thumbnail) = match &url {
+ Some(url) if old_post.is_err() => {
+ fetch_site_data(
+ context.client(),
+ context.settings(),
+ Some(url),
+ include_image,
+ )
+ .await
+ }
+ _ => (None, None),
+ };
+ // If no image was included with metadata, use post image instead when available.
+ let thumbnail_url = thumbnail.or_else(|| page.image.map(|i| i.url.into()));
+
+ let (embed_title, embed_description, embed_video_url) = metadata_res
+ .map(|u| (u.title, u.description, u.embed_video_url))
+ .unwrap_or_default();
+ let slur_regex = &local_site_opt_to_slur_regex(&local_site);
+
+ let body_slurs_removed =
+ read_from_string_or_source_opt(&page.content, &page.media_type, &page.source)
+ .map(|s| remove_slurs(&s, slur_regex));
+ let language_id =
+ LanguageTag::to_language_id_single(page.language, &mut context.pool()).await?;
+
+ let name = sanitize_html(&name);
+ let embed_title = sanitize_html_opt(&embed_title);
+ let embed_description = sanitize_html_opt(&embed_description);
+
+ PostInsertForm {
+ name,
+ url: url.map(Into::into),
+ body: body_slurs_removed,
+ creator_id: creator.id,
+ community_id: community.id,
+ removed: None,
+ locked: page.comments_enabled.map(|e| !e),
+ published: page.published.map(|u| u.naive_local()),
+ updated: page.updated.map(|u| u.naive_local()),
+ deleted: Some(false),
+ nsfw: page.sensitive,
+ embed_title,
+ embed_description,
+ embed_video_url,
+ thumbnail_url,
+ ap_id: Some(page.id.clone().into()),
+ local: Some(false),
+ language_id,
+ featured_community: None,
+ featured_local: None,
+ }