1 use crate::check_is_apub_id_valid;
3 base::{AsBase, BaseExt, ExtendsExt},
5 mime::{FromStrError, Mime},
6 object::{ApObjectExt, Object, ObjectExt, Tombstone, TombstoneExt},
8 use anyhow::{anyhow, Context};
9 use chrono::NaiveDateTime;
10 use lemmy_utils::{location_info, utils::convert_datetime, LemmyError};
13 pub(crate) mod comment;
14 pub(crate) mod community;
16 pub(crate) mod private_message;
19 /// Updated is actually the deletion time
20 fn create_tombstone<T>(
23 updated: Option<NaiveDateTime>,
25 ) -> Result<Tombstone, LemmyError>
30 if let Some(updated) = updated {
31 let mut tombstone = Tombstone::new();
32 tombstone.set_id(object_id.parse()?);
33 tombstone.set_former_type(former_type.to_string());
34 tombstone.set_deleted(convert_datetime(updated));
37 Err(anyhow!("Cant convert to tombstone because updated time was None.").into())
40 Err(anyhow!("Cant convert object to tombstone if it wasnt deleted").into())
44 pub(in crate::objects) fn check_object_domain<T, Kind>(
46 expected_domain: Option<Url>,
47 ) -> Result<String, LemmyError>
49 T: Base + AsBase<Kind>,
51 let actor_id = if let Some(url) = expected_domain {
52 check_is_apub_id_valid(&url)?;
53 let domain = url.domain().context(location_info!())?;
54 apub.id(domain)?.context(location_info!())?
56 let actor_id = apub.id_unchecked().context(location_info!())?;
57 check_is_apub_id_valid(&actor_id)?;
60 Ok(actor_id.to_string())
63 pub(in crate::objects) fn set_content_and_source<T, Kind1, Kind2>(
66 ) -> Result<(), LemmyError>
68 T: ApObjectExt<Kind1> + ObjectExt<Kind2> + AsBase<Kind2>,
70 let mut source = Object::<()>::new_none_type();
72 .set_content(markdown_text)
73 .set_media_type(mime_markdown()?);
74 object.set_source(source.into_any_base()?);
76 // set `content` to markdown for compatibility with older Lemmy versions
77 // TODO: change this to HTML in a while
78 object.set_content(markdown_text);
79 object.set_media_type(mime_markdown()?);
80 //object.set_content(markdown_to_html(markdown_text));
84 pub(in crate::objects) fn get_source_markdown_value<T, Kind1, Kind2>(
86 ) -> Result<Option<String>, LemmyError>
88 T: ApObjectExt<Kind1> + ObjectExt<Kind2> + AsBase<Kind2>,
92 .map(|s| s.as_single_xsd_string())
94 .map(|s| s.to_string());
95 if content.is_some() {
96 let source = object.source();
97 // updated lemmy version, read markdown from `source.content`
98 if let Some(source) = source {
99 let source = Object::<()>::from_any_base(source.to_owned())?.context(location_info!())?;
100 check_is_markdown(source.media_type())?;
101 let source_content = source
103 .map(|s| s.as_single_xsd_string())
105 .context(location_info!())?
107 return Ok(Some(source_content));
109 // older lemmy version, read markdown from `content`
110 // TODO: remove this after a while
118 pub(in crate::objects) fn mime_markdown() -> Result<Mime, FromStrError> {
119 "text/markdown".parse()
122 pub(in crate::objects) fn check_is_markdown(mime: Option<&Mime>) -> Result<(), LemmyError> {
123 let mime = mime.context(location_info!())?;
124 if !mime.eq(&mime_markdown()?) {
125 Err(LemmyError::from(anyhow!(
126 "Lemmy only supports markdown content"