2 extensions::{context::lemmy_context, group_extension::GroupExtension},
3 fetcher::community::fetch_community_mods,
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_api_common::blocking;
27 use lemmy_db_queries::DbPool;
28 use lemmy_db_schema::{
30 source::community::{Community, CommunityForm},
32 use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
35 utils::{check_slurs, check_slurs_opt, convert_datetime},
38 use lemmy_websocket::LemmyContext;
41 #[async_trait::async_trait(?Send)]
42 impl ToApub for Community {
43 type ApubType = GroupExt;
45 async fn to_apub(&self, pool: &DbPool) -> Result<GroupExt, LemmyError> {
47 let moderators = blocking(pool, move |conn| {
48 CommunityModeratorView::for_community(conn, id)
51 let moderators: Vec<Url> = moderators
53 .map(|m| m.moderator.actor_id.into_inner())
56 let mut group = ApObject::new(Group::new());
58 .set_many_contexts(lemmy_context())
59 .set_id(self.actor_id.to_owned().into())
60 .set_name(self.title.to_owned())
61 .set_published(convert_datetime(self.published))
62 // NOTE: included attritubed_to field for compatibility with lemmy v0.9.9
63 .set_many_attributed_tos(moderators);
65 if let Some(u) = self.updated.to_owned() {
66 group.set_updated(convert_datetime(u));
68 if let Some(d) = self.description.to_owned() {
69 set_content_and_source(&mut group, &d)?;
72 if let Some(icon_url) = &self.icon {
73 let mut image = Image::new();
74 image.set_url::<Url>(icon_url.to_owned().into());
75 group.set_icon(image.into_any_base()?);
78 if let Some(banner_url) = &self.banner {
79 let mut image = Image::new();
80 image.set_url::<Url>(banner_url.to_owned().into());
81 group.set_image(image.into_any_base()?);
84 let mut ap_actor = ApActor::new(self.inbox_url.clone().into(), group);
86 .set_preferred_username(self.name.to_owned())
87 .set_outbox(self.get_outbox_url()?)
88 .set_followers(self.followers_url.clone().into())
89 .set_endpoints(Endpoints {
90 shared_inbox: Some(self.get_shared_inbox_or_inbox_url()),
96 GroupExtension::new(self.nsfw, generate_moderators_url(&self.actor_id)?.into())?,
97 self.get_public_key_ext()?,
101 fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
104 self.actor_id.to_owned().into(),
111 #[async_trait::async_trait(?Send)]
112 impl FromApub for Community {
113 type ApubType = GroupExt;
115 /// Converts a `Group` to `Community`, inserts it into the database and updates moderators.
118 context: &LemmyContext,
119 expected_domain: Url,
120 request_counter: &mut i32,
121 mod_action_allowed: bool,
122 ) -> Result<Community, LemmyError> {
123 get_object_from_apub(
134 #[async_trait::async_trait(?Send)]
135 impl FromApubToForm<GroupExt> for CommunityForm {
138 context: &LemmyContext,
139 expected_domain: Url,
140 request_counter: &mut i32,
141 _mod_action_allowed: bool,
142 ) -> Result<Self, LemmyError> {
143 fetch_community_mods(context, group, request_counter).await?;
147 .preferred_username()
148 .context(location_info!())?
153 .context(location_info!())?
155 .context(location_info!())?
157 .context(location_info!())?
160 let description = get_source_markdown_value(group)?;
163 check_slurs(&title)?;
164 check_slurs_opt(&description)?;
166 let icon = match group.icon() {
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 banner = match group.image() {
179 Some(any_image) => Some(
180 Image::from_any_base(any_image.as_one().context(location_info!())?.clone())
181 .context(location_info!())?
182 .context(location_info!())?
184 .context(location_info!())?
185 .as_single_xsd_any_uri()
186 .map(|u| u.to_owned().into()),
190 let shared_inbox = group
193 .map(|e| e.shared_inbox)
195 .map(|s| s.to_owned().into());
202 published: group.inner.published().map(|u| u.to_owned().naive_local()),
203 updated: group.inner.updated().map(|u| u.to_owned().naive_local()),
205 nsfw: Some(group.ext_one.sensitive.unwrap_or(false)),
206 actor_id: Some(check_object_domain(group, expected_domain, true)?),
209 public_key: Some(group.ext_two.to_owned().public_key.public_key_pem),
210 last_refreshed_at: Some(naive_now()),
217 .context(location_info!())?
221 inbox_url: Some(group.inner.inbox()?.to_owned().into()),
222 shared_inbox_url: Some(shared_inbox),