]> Untitled Git - lemmy.git/blob - crates/apub/src/fetcher/post_or_comment.rs
Migrate towards using page.attachment field for url (ref #2144) (#2182)
[lemmy.git] / crates / apub / src / fetcher / post_or_comment.rs
1 use crate::{
2   objects::{comment::ApubComment, post::ApubPost},
3   protocol::objects::{note::Note, page::Page},
4 };
5 use chrono::NaiveDateTime;
6 use lemmy_apub_lib::traits::ApubObject;
7 use lemmy_utils::LemmyError;
8 use lemmy_websocket::LemmyContext;
9 use serde::Deserialize;
10 use url::Url;
11
12 #[derive(Clone, Debug)]
13 pub enum PostOrComment {
14   Post(Box<ApubPost>),
15   Comment(Box<ApubComment>),
16 }
17
18 #[derive(Deserialize)]
19 #[serde(untagged)]
20 pub enum PageOrNote {
21   Page(Box<Page>),
22   Note(Note),
23 }
24
25 #[async_trait::async_trait(?Send)]
26 impl ApubObject for PostOrComment {
27   type DataType = LemmyContext;
28   type ApubType = PageOrNote;
29   type DbType = ();
30   type TombstoneType = ();
31
32   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
33     None
34   }
35
36   // TODO: this can probably be implemented using a single sql query
37   #[tracing::instrument(skip_all)]
38   async fn read_from_apub_id(
39     object_id: Url,
40     data: &Self::DataType,
41   ) -> Result<Option<Self>, LemmyError> {
42     let post = ApubPost::read_from_apub_id(object_id.clone(), data).await?;
43     Ok(match post {
44       Some(o) => Some(PostOrComment::Post(Box::new(o))),
45       None => ApubComment::read_from_apub_id(object_id, data)
46         .await?
47         .map(|c| PostOrComment::Comment(Box::new(c))),
48     })
49   }
50
51   #[tracing::instrument(skip_all)]
52   async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
53     match self {
54       PostOrComment::Post(p) => p.delete(data).await,
55       PostOrComment::Comment(c) => c.delete(data).await,
56     }
57   }
58
59   async fn into_apub(self, _data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
60     unimplemented!()
61   }
62
63   fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError> {
64     unimplemented!()
65   }
66
67   #[tracing::instrument(skip_all)]
68   async fn verify(
69     apub: &Self::ApubType,
70     expected_domain: &Url,
71     data: &Self::DataType,
72     request_counter: &mut i32,
73   ) -> Result<(), LemmyError> {
74     match apub {
75       PageOrNote::Page(a) => ApubPost::verify(a, expected_domain, data, request_counter).await,
76       PageOrNote::Note(a) => ApubComment::verify(a, expected_domain, data, request_counter).await,
77     }
78   }
79
80   #[tracing::instrument(skip_all)]
81   async fn from_apub(
82     apub: PageOrNote,
83     context: &LemmyContext,
84     request_counter: &mut i32,
85   ) -> Result<Self, LemmyError> {
86     Ok(match apub {
87       PageOrNote::Page(p) => PostOrComment::Post(Box::new(
88         ApubPost::from_apub(*p, context, request_counter).await?,
89       )),
90       PageOrNote::Note(n) => PostOrComment::Comment(Box::new(
91         ApubComment::from_apub(n, context, request_counter).await?,
92       )),
93     })
94   }
95 }
96
97 impl PostOrComment {
98   pub(crate) fn ap_id(&self) -> Url {
99     match self {
100       PostOrComment::Post(p) => p.ap_id.clone(),
101       PostOrComment::Comment(c) => c.ap_id.clone(),
102     }
103     .into()
104   }
105 }