diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index 8b8ae093b..2b211fff9 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -5,7 +5,7 @@ use crate::{ objects::{read_from_string_or_source_opt, verify_is_remote_object}, protocol::{ objects::{ - page::{Attachment, AttributedTo, Page, PageType}, + page::{Attachment, AttributedTo, Hashtag, HashtagType, Page, PageType}, LanguageTag, }, ImageObject, @@ -124,6 +124,11 @@ impl Object for ApubPost { }) .into_iter() .collect(); + let hashtag = Hashtag { + href: self.ap_id.clone().into(), + name: format!("#{}", &community.name), + kind: HashtagType::Hashtag, + }; let page = Page { kind: PageType::Page, @@ -144,6 +149,7 @@ impl Object for ApubPost { updated: self.updated, audience: Some(community.actor_id.into()), in_reply_to: None, + tag: vec![hashtag], }; Ok(page) } diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs index d6111843e..170778297 100644 --- a/crates/apub/src/protocol/objects/page.rs +++ b/crates/apub/src/protocol/objects/page.rs @@ -66,6 +66,8 @@ pub struct Page { pub(crate) updated: Option>, pub(crate) language: Option, pub(crate) audience: Option>, + #[serde(deserialize_with = "deserialize_skip_error", default)] + pub(crate) tag: Vec, } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -140,6 +142,19 @@ pub(crate) struct AttributedToPeertube { pub id: ObjectId, } +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct Hashtag { + pub(crate) href: Url, + pub(crate) name: String, + #[serde(rename = "type")] + pub(crate) kind: HashtagType, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum HashtagType { + Hashtag, +} + impl Page { /// Only mods can change the post's locked status. So if it is changed from the default value, /// it is a mod action and needs to be verified as such.