]> Untitled Git - lemmy.git/blob - crates/apub/src/activity_lists.rs
4cce3372fa01a6cba14e67efb7e959e97fe05cf3
[lemmy.git] / crates / apub / src / activity_lists.rs
1 use crate::{
2   objects::community::ApubCommunity,
3   protocol::{
4     activities::{
5       block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
6       community::{
7         announce::{AnnounceActivity, RawAnnouncableActivities},
8         collection_add::CollectionAdd,
9         collection_remove::CollectionRemove,
10         lock_page::{LockPage, UndoLockPage},
11         report::Report,
12         update::UpdateCommunity,
13       },
14       create_or_update::{
15         chat_message::CreateOrUpdateChatMessage,
16         note::CreateOrUpdateNote,
17         page::CreateOrUpdatePage,
18       },
19       deletion::{delete::Delete, delete_user::DeleteUser, undo_delete::UndoDelete},
20       following::{accept::AcceptFollow, follow::Follow, undo_follow::UndoFollow},
21       voting::{undo_vote::UndoVote, vote::Vote},
22     },
23     objects::page::Page,
24     InCommunity,
25   },
26 };
27 use activitypub_federation::{
28   config::Data,
29   protocol::context::WithContext,
30   traits::ActivityHandler,
31 };
32 use lemmy_api_common::context::LemmyContext;
33 use lemmy_utils::error::LemmyError;
34 use serde::{Deserialize, Serialize};
35 use url::Url;
36
37 #[derive(Debug, Deserialize, Serialize)]
38 #[serde(untagged)]
39 #[enum_delegate::implement(ActivityHandler)]
40 pub enum SharedInboxActivities {
41   PersonInboxActivities(Box<WithContext<PersonInboxActivities>>),
42   GroupInboxActivities(Box<WithContext<GroupInboxActivities>>),
43 }
44
45 #[derive(Debug, Deserialize, Serialize)]
46 #[serde(untagged)]
47 #[enum_delegate::implement(ActivityHandler)]
48 pub enum GroupInboxActivities {
49   Follow(Follow),
50   UndoFollow(UndoFollow),
51   Report(Report),
52   // This is a catch-all and needs to be last
53   AnnouncableActivities(RawAnnouncableActivities),
54 }
55
56 #[derive(Clone, Debug, Deserialize, Serialize)]
57 #[serde(untagged)]
58 #[enum_delegate::implement(ActivityHandler)]
59 pub enum PersonInboxActivities {
60   Follow(Follow),
61   AcceptFollow(AcceptFollow),
62   UndoFollow(UndoFollow),
63   CreateOrUpdatePrivateMessage(CreateOrUpdateChatMessage),
64   Delete(Delete),
65   UndoDelete(UndoDelete),
66   AnnounceActivity(AnnounceActivity),
67 }
68
69 /// This is necessary for user inbox, which can also receive some "announcable" activities,
70 /// eg a comment mention. This needs to be a separate enum so that announcables received in shared
71 /// inbox can fall through to be parsed as GroupInboxActivities::AnnouncableActivities.
72 #[derive(Clone, Debug, Deserialize, Serialize)]
73 #[serde(untagged)]
74 #[enum_delegate::implement(ActivityHandler)]
75 pub enum PersonInboxActivitiesWithAnnouncable {
76   PersonInboxActivities(Box<PersonInboxActivities>),
77   AnnouncableActivities(Box<AnnouncableActivities>),
78 }
79
80 #[derive(Clone, Debug, Deserialize, Serialize)]
81 #[serde(untagged)]
82 #[enum_delegate::implement(ActivityHandler)]
83 pub enum AnnouncableActivities {
84   CreateOrUpdateComment(CreateOrUpdateNote),
85   CreateOrUpdatePost(CreateOrUpdatePage),
86   Vote(Vote),
87   UndoVote(UndoVote),
88   Delete(Delete),
89   UndoDelete(UndoDelete),
90   UpdateCommunity(UpdateCommunity),
91   BlockUser(BlockUser),
92   UndoBlockUser(UndoBlockUser),
93   CollectionAdd(CollectionAdd),
94   CollectionRemove(CollectionRemove),
95   LockPost(LockPage),
96   UndoLockPost(UndoLockPage),
97   // For compatibility with Pleroma/Mastodon (send only)
98   Page(Page),
99 }
100
101 #[derive(Clone, Debug, Deserialize, Serialize)]
102 #[serde(untagged)]
103 #[enum_delegate::implement(ActivityHandler)]
104 #[allow(clippy::enum_variant_names)]
105 pub enum SiteInboxActivities {
106   BlockUser(BlockUser),
107   UndoBlockUser(UndoBlockUser),
108   DeleteUser(DeleteUser),
109 }
110
111 #[async_trait::async_trait]
112 impl InCommunity for AnnouncableActivities {
113   #[tracing::instrument(skip(self, context))]
114   async fn community(&self, context: &Data<LemmyContext>) -> Result<ApubCommunity, LemmyError> {
115     use AnnouncableActivities::*;
116     match self {
117       CreateOrUpdateComment(a) => a.community(context).await,
118       CreateOrUpdatePost(a) => a.community(context).await,
119       Vote(a) => a.community(context).await,
120       UndoVote(a) => a.community(context).await,
121       Delete(a) => a.community(context).await,
122       UndoDelete(a) => a.community(context).await,
123       UpdateCommunity(a) => a.community(context).await,
124       BlockUser(a) => a.community(context).await,
125       UndoBlockUser(a) => a.community(context).await,
126       CollectionAdd(a) => a.community(context).await,
127       CollectionRemove(a) => a.community(context).await,
128       LockPost(a) => a.community(context).await,
129       UndoLockPost(a) => a.community(context).await,
130       Page(_) => unimplemented!(),
131     }
132   }
133 }
134
135 #[cfg(test)]
136 mod tests {
137   #![allow(clippy::unwrap_used)]
138   #![allow(clippy::indexing_slicing)]
139
140   use crate::{
141     activity_lists::{
142       GroupInboxActivities,
143       PersonInboxActivities,
144       PersonInboxActivitiesWithAnnouncable,
145       SiteInboxActivities,
146     },
147     protocol::tests::{test_json, test_parse_lemmy_item},
148   };
149
150   #[test]
151   fn test_group_inbox() {
152     test_parse_lemmy_item::<GroupInboxActivities>("assets/lemmy/activities/following/follow.json")
153       .unwrap();
154     test_parse_lemmy_item::<GroupInboxActivities>(
155       "assets/lemmy/activities/create_or_update/create_note.json",
156     )
157     .unwrap();
158   }
159
160   #[test]
161   fn test_person_inbox() {
162     test_parse_lemmy_item::<PersonInboxActivities>("assets/lemmy/activities/following/accept.json")
163       .unwrap();
164     test_parse_lemmy_item::<PersonInboxActivitiesWithAnnouncable>(
165       "assets/lemmy/activities/create_or_update/create_note.json",
166     )
167     .unwrap();
168     test_parse_lemmy_item::<PersonInboxActivitiesWithAnnouncable>(
169       "assets/lemmy/activities/create_or_update/create_private_message.json",
170     )
171     .unwrap();
172     test_json::<PersonInboxActivitiesWithAnnouncable>("assets/mastodon/activities/follow.json")
173       .unwrap();
174   }
175
176   #[test]
177   fn test_site_inbox() {
178     test_parse_lemmy_item::<SiteInboxActivities>(
179       "assets/lemmy/activities/deletion/delete_user.json",
180     )
181     .unwrap();
182   }
183 }