+
+#[async_trait::async_trait]
+impl InCommunity for Page {
+ async fn community(&self, context: &Data<LemmyContext>) -> Result<ApubCommunity, LemmyError> {
+ let community = match &self.attributed_to {
+ AttributedTo::Lemmy(_) => {
+ let mut iter = self.to.iter().merge(self.cc.iter());
+ loop {
+ if let Some(cid) = iter.next() {
+ let cid = ObjectId::from(cid.clone());
+ if let Ok(c) = cid.dereference(context).await {
+ break c;
+ }
+ } else {
+ return Err(LemmyErrorType::NoCommunityFoundInCc)?;
+ }
+ }
+ }
+ AttributedTo::Peertube(p) => {
+ p.iter()
+ .find(|a| a.kind == PersonOrGroupType::Group)
+ .map(|a| ObjectId::<ApubCommunity>::from(a.id.clone().into_inner()))
+ .ok_or(LemmyErrorType::PageDoesNotSpecifyGroup)?
+ .dereference(context)
+ .await?
+ }
+ };
+ if let Some(audience) = &self.audience {
+ verify_community_matches(audience, community.actor_id.clone())?;
+ }
+ Ok(community)
+ }
+}
+
+/// Only allows deserialization if the field is missing or null. If it is present, throws an error.
+pub fn deserialize_not_present<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
+where
+ D: Deserializer<'de>,
+{
+ let result: Option<String> = Deserialize::deserialize(deserializer)?;
+ match result {
+ None => Ok(None),
+ Some(_) => Err(D::Error::custom("Post must not have inReplyTo property")),
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ #![allow(clippy::unwrap_used)]
+ #![allow(clippy::indexing_slicing)]
+
+ use crate::protocol::{objects::page::Page, tests::test_parse_lemmy_item};
+
+ #[test]
+ fn test_not_parsing_note_as_page() {
+ assert!(test_parse_lemmy_item::<Page>("assets/lemmy/objects/note.json").is_err());
+ }
+}