2 extensions::{context::lemmy_context, group_extensions::GroupExtension},
3 fetcher::{community::fetch_community_mods, person::get_or_fetch_and_upsert_person},
4 generate_moderators_url,
9 get_source_markdown_value,
10 set_content_and_source,
18 use activitystreams::{
19 actor::{kind::GroupType, ApActor, Endpoints, Group},
21 object::{ApObject, Image, Tombstone},
24 use activitystreams_ext::Ext2;
26 use lemmy_db_queries::DbPool;
27 use lemmy_db_schema::{
29 source::community::{Community, CommunityForm},
33 utils::{check_slurs, check_slurs_opt, convert_datetime},
36 use lemmy_websocket::LemmyContext;
39 #[async_trait::async_trait(?Send)]
40 impl ToApub for Community {
41 type ApubType = GroupExt;
43 async fn to_apub(&self, _pool: &DbPool) -> Result<GroupExt, LemmyError> {
44 let mut group = ApObject::new(Group::new());
46 .set_many_contexts(lemmy_context()?)
47 .set_id(self.actor_id.to_owned().into())
48 .set_name(self.title.to_owned())
49 .set_published(convert_datetime(self.published));
51 if let Some(u) = self.updated.to_owned() {
52 group.set_updated(convert_datetime(u));
54 if let Some(d) = self.description.to_owned() {
55 set_content_and_source(&mut group, &d)?;
58 if let Some(icon_url) = &self.icon {
59 let mut image = Image::new();
60 image.set_url::<Url>(icon_url.to_owned().into());
61 group.set_icon(image.into_any_base()?);
64 if let Some(banner_url) = &self.banner {
65 let mut image = Image::new();
66 image.set_url::<Url>(banner_url.to_owned().into());
67 group.set_image(image.into_any_base()?);
70 let mut ap_actor = ApActor::new(self.inbox_url.clone().into(), group);
72 .set_preferred_username(self.name.to_owned())
73 .set_outbox(self.get_outbox_url()?)
74 .set_followers(self.followers_url.clone().into())
75 .set_endpoints(Endpoints {
76 shared_inbox: Some(self.get_shared_inbox_or_inbox_url()),
82 GroupExtension::new(self.nsfw, generate_moderators_url(&self.actor_id)?.into())?,
83 self.get_public_key_ext()?,
87 fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
90 self.actor_id.to_owned().into(),
97 #[async_trait::async_trait(?Send)]
98 impl FromApub for Community {
99 type ApubType = GroupExt;
101 /// Converts a `Group` to `Community`, inserts it into the database and updates moderators.
104 context: &LemmyContext,
105 expected_domain: Url,
106 request_counter: &mut i32,
107 mod_action_allowed: bool,
108 ) -> Result<Community, LemmyError> {
109 get_object_from_apub(
120 #[async_trait::async_trait(?Send)]
121 impl FromApubToForm<GroupExt> for CommunityForm {
124 context: &LemmyContext,
125 expected_domain: Url,
126 request_counter: &mut i32,
127 _mod_action_allowed: bool,
128 ) -> Result<Self, LemmyError> {
129 let moderator_uris = fetch_community_mods(context, group, request_counter).await?;
130 let creator_uri = moderator_uris.first().context(location_info!())?;
132 let creator = get_or_fetch_and_upsert_person(creator_uri, context, request_counter).await?;
135 .preferred_username()
136 .context(location_info!())?
141 .context(location_info!())?
143 .context(location_info!())?
145 .context(location_info!())?
148 let description = get_source_markdown_value(group)?;
151 check_slurs(&title)?;
152 check_slurs_opt(&description)?;
154 let icon = match group.icon() {
155 Some(any_image) => Some(
156 Image::from_any_base(any_image.as_one().context(location_info!())?.clone())
157 .context(location_info!())?
158 .context(location_info!())?
160 .context(location_info!())?
161 .as_single_xsd_any_uri()
162 .map(|u| u.to_owned().into()),
166 let banner = match group.image() {
167 Some(any_image) => Some(
168 Image::from_any_base(any_image.as_one().context(location_info!())?.clone())
169 .context(location_info!())?
170 .context(location_info!())?
172 .context(location_info!())?
173 .as_single_xsd_any_uri()
174 .map(|u| u.to_owned().into()),
178 let shared_inbox = group
181 .map(|e| e.shared_inbox)
183 .map(|s| s.to_owned().into());
189 creator_id: creator.id,
191 published: group.inner.published().map(|u| u.to_owned().naive_local()),
192 updated: group.inner.updated().map(|u| u.to_owned().naive_local()),
194 nsfw: group.ext_one.sensitive.unwrap_or(false),
195 actor_id: Some(check_object_domain(group, expected_domain)?),
198 public_key: Some(group.ext_two.to_owned().public_key.public_key_pem),
199 last_refreshed_at: Some(naive_now()),
206 .context(location_info!())?
210 inbox_url: Some(group.inner.inbox()?.to_owned().into()),
211 shared_inbox_url: Some(shared_inbox),