use std::collections::HashMap; use chrono::{DateTime, Utc}; use serde::{ Deserialize, Deserializer, Serialize, de::{Error as DeserializerError}, }; use serde_json::Value; use super::constants::{ AP_CONTEXT, MITRA_CONTEXT, W3ID_DATA_INTEGRITY_CONTEXT, W3ID_SECURITY_CONTEXT, }; use super::receiver::parse_property_value; use super::vocabulary::HASHTAG; #[derive(Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Attachment { #[serde(rename = "type")] pub attachment_type: String, pub name: Option, pub media_type: Option, pub url: Option, } #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub struct Link { pub href: String, } fn default_tag_type() -> String { HASHTAG.to_string() } #[derive(Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Tag { pub name: Option, #[serde(rename = "type", default = "default_tag_type")] pub tag_type: String, pub href: Option, } #[derive(Serialize)] #[serde(rename_all = "camelCase")] pub struct SimpleTag { #[serde(rename = "type")] pub tag_type: String, pub href: String, pub name: String, } /// https://codeberg.org/fediverse/fep/src/branch/main/feps/fep-e232.md #[derive(Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct LinkTag { #[serde(rename = "type")] pub tag_type: String, pub href: String, pub media_type: String, pub name: Option, } #[derive(Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct EmojiTagImage { #[serde(rename = "type")] pub object_type: String, pub url: String, pub media_type: Option, } #[derive(Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct EmojiTag { #[serde(rename = "type")] pub tag_type: String, pub icon: EmojiTagImage, pub id: String, pub name: String, pub updated: DateTime, } pub fn deserialize_value_array<'de, D>( deserializer: D, ) -> Result, D::Error> where D: Deserializer<'de> { let maybe_value: Option = Option::deserialize(deserializer)?; let values = if let Some(value) = maybe_value { parse_property_value(&value).map_err(DeserializerError::custom)? } else { vec![] }; Ok(values) } #[derive(Deserialize)] #[cfg_attr(test, derive(Default))] #[serde(rename_all = "camelCase")] pub struct Object { // https://www.w3.org/TR/activitypub/#obj-id // "id" and "type" are required properties pub id: String, #[serde(rename = "type")] pub object_type: String, pub name: Option, pub attachment: Option, pub cc: Option, pub media_type: Option, pub published: Option>, pub attributed_to: Option, pub in_reply_to: Option, pub content: Option, pub quote_url: Option, pub sensitive: Option, #[serde( default, deserialize_with = "deserialize_value_array", )] pub tag: Vec, pub to: Option, pub updated: Option>, pub url: Option, } pub type Context = ( &'static str, &'static str, &'static str, HashMap<&'static str, &'static str>, ); pub fn build_default_context() -> Context { ( AP_CONTEXT, W3ID_SECURITY_CONTEXT, W3ID_DATA_INTEGRITY_CONTEXT, HashMap::from([ ("proofValue", "sec:proofValue"), ("proofPurpose", "sec:proofPurpose"), ("verificationMethod", "sec:verificationMethod"), ("mitra", MITRA_CONTEXT), ("MitraJcsRsaSignature2022", "mitra:MitraJcsRsaSignature2022"), ]), ) }