]> Untitled Git - lemmy.git/blob - crates/apub/src/fetcher/post_or_comment.rs
Implement separate mod activities for feature, lock post (#2716)
[lemmy.git] / crates / apub / src / fetcher / post_or_comment.rs
1 use crate::{
2   objects::{comment::ApubComment, community::ApubCommunity, post::ApubPost},
3   protocol::{
4     objects::{note::Note, page::Page},
5     InCommunity,
6   },
7 };
8 use activitypub_federation::traits::ApubObject;
9 use chrono::NaiveDateTime;
10 use lemmy_api_common::context::LemmyContext;
11 use lemmy_db_schema::{
12   source::{community::Community, post::Post},
13   traits::Crud,
14 };
15 use lemmy_utils::error::LemmyError;
16 use serde::Deserialize;
17 use url::Url;
18
19 #[derive(Clone, Debug)]
20 pub enum PostOrComment {
21   Post(ApubPost),
22   Comment(ApubComment),
23 }
24
25 #[derive(Deserialize)]
26 #[serde(untagged)]
27 pub enum PageOrNote {
28   Page(Box<Page>),
29   Note(Note),
30 }
31
32 #[async_trait::async_trait(?Send)]
33 impl ApubObject for PostOrComment {
34   type DataType = LemmyContext;
35   type ApubType = PageOrNote;
36   type DbType = ();
37   type Error = LemmyError;
38
39   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
40     None
41   }
42
43   #[tracing::instrument(skip_all)]
44   async fn read_from_apub_id(
45     object_id: Url,
46     data: &Self::DataType,
47   ) -> Result<Option<Self>, LemmyError> {
48     let post = ApubPost::read_from_apub_id(object_id.clone(), data).await?;
49     Ok(match post {
50       Some(o) => Some(PostOrComment::Post(o)),
51       None => ApubComment::read_from_apub_id(object_id, data)
52         .await?
53         .map(PostOrComment::Comment),
54     })
55   }
56
57   #[tracing::instrument(skip_all)]
58   async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
59     match self {
60       PostOrComment::Post(p) => p.delete(data).await,
61       PostOrComment::Comment(c) => c.delete(data).await,
62     }
63   }
64
65   async fn into_apub(self, _data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
66     unimplemented!()
67   }
68
69   #[tracing::instrument(skip_all)]
70   async fn verify(
71     apub: &Self::ApubType,
72     expected_domain: &Url,
73     data: &Self::DataType,
74     request_counter: &mut i32,
75   ) -> Result<(), LemmyError> {
76     match apub {
77       PageOrNote::Page(a) => ApubPost::verify(a, expected_domain, data, request_counter).await,
78       PageOrNote::Note(a) => ApubComment::verify(a, expected_domain, data, request_counter).await,
79     }
80   }
81
82   #[tracing::instrument(skip_all)]
83   async fn from_apub(
84     apub: PageOrNote,
85     context: &LemmyContext,
86     request_counter: &mut i32,
87   ) -> Result<Self, LemmyError> {
88     Ok(match apub {
89       PageOrNote::Page(p) => {
90         PostOrComment::Post(ApubPost::from_apub(*p, context, request_counter).await?)
91       }
92       PageOrNote::Note(n) => {
93         PostOrComment::Comment(ApubComment::from_apub(n, context, request_counter).await?)
94       }
95     })
96   }
97 }
98
99 #[async_trait::async_trait(?Send)]
100 impl InCommunity for PostOrComment {
101   async fn community(
102     &self,
103     context: &LemmyContext,
104     _: &mut i32,
105   ) -> Result<ApubCommunity, LemmyError> {
106     let cid = match self {
107       PostOrComment::Post(p) => p.community_id,
108       PostOrComment::Comment(c) => Post::read(context.pool(), c.post_id).await?.community_id,
109     };
110     Ok(Community::read(context.pool(), cid).await?.into())
111   }
112 }