#[derive(Serialize, Deserialize, Debug)]
pub(crate) struct WithContext<T> {
#[serde(rename = "@context")]
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
context: Vec<serde_json::Value>,
#[serde(flatten)]
inner: T,
use lemmy_api_common::blocking;
use lemmy_db_schema::{newtypes::DbUrl, source::activity::Activity, DbPool};
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
+use serde::{Deserialize, Deserializer};
use std::net::IpAddr;
use url::{ParseError, Url};
Ok(())
}
+pub(crate) fn deserialize_one_or_many<'de, T, D>(deserializer: D) -> Result<Vec<T>, D::Error>
+where
+ T: Deserialize<'de>,
+ D: Deserializer<'de>,
+{
+ #[derive(Deserialize)]
+ #[serde(untagged)]
+ enum OneOrMany<T> {
+ One(T),
+ Many(Vec<T>),
+ }
+
+ let result: OneOrMany<T> = Deserialize::deserialize(deserializer)?;
+ Ok(match result {
+ OneOrMany::Many(list) => list,
+ OneOrMany::One(value) => vec![value],
+ })
+}
+
pub enum EndpointType {
Community,
Person,
#[serde(rename_all = "camelCase")]
pub struct AddMod {
pub(crate) actor: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
pub(crate) object: ObjectId<ApubPerson>,
pub(crate) target: Url,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
#[serde(rename = "type")]
pub(crate) kind: AddType,
#[serde(rename_all = "camelCase")]
pub struct AnnounceActivity {
pub(crate) actor: ObjectId<ApubCommunity>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
pub(crate) object: AnnouncableActivities,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
#[serde(rename = "type")]
pub(crate) kind: AnnounceType,
#[serde(rename_all = "camelCase")]
pub struct BlockUserFromCommunity {
pub(crate) actor: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
pub(crate) object: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
pub(crate) target: ObjectId<ApubCommunity>,
#[serde(rename = "type")]
#[serde(rename_all = "camelCase")]
pub struct RemoveMod {
pub(crate) actor: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
pub(crate) object: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
#[serde(rename = "type")]
pub(crate) kind: RemoveType,
#[serde(rename_all = "camelCase")]
pub struct UndoBlockUserFromCommunity {
pub(crate) actor: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
pub(crate) object: BlockUserFromCommunity,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
#[serde(rename = "type")]
pub(crate) kind: UndoType,
#[serde(rename_all = "camelCase")]
pub struct UpdateCommunity {
pub(crate) actor: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
// TODO: would be nice to use a separate struct here, which only contains the fields updated here
pub(crate) object: Box<Group>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
#[serde(rename = "type")]
pub(crate) kind: UpdateType,
#[serde(rename_all = "camelCase")]
pub struct CreateOrUpdateComment {
pub(crate) actor: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
pub(crate) object: Note,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
#[serde(default)]
pub(crate) tag: Vec<Mention>,
#[serde(rename_all = "camelCase")]
pub struct CreateOrUpdatePost {
pub(crate) actor: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
pub(crate) object: Page,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
#[serde(rename = "type")]
pub(crate) kind: CreateOrUpdateType,
#[serde(rename_all = "camelCase")]
pub struct Delete {
pub(crate) actor: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
pub(crate) object: Tombstone,
#[serde(rename = "type")]
#[serde(rename_all = "camelCase")]
pub struct UndoDelete {
pub(crate) actor: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
pub(crate) object: Delete,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
#[serde(rename = "type")]
pub(crate) kind: UndoType,
#[serde(rename_all = "camelCase")]
pub struct UndoVote {
pub(crate) actor: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
pub(crate) object: Vote,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
#[serde(rename = "type")]
pub(crate) kind: UndoType,
#[serde(rename_all = "camelCase")]
pub struct Vote {
pub(crate) actor: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
pub(crate) object: ObjectId<PostOrComment>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
#[serde(rename = "type")]
pub(crate) kind: VoteType,
pub(crate) r#type: NoteType,
pub(crate) id: ObjectId<ApubComment>,
pub(crate) attributed_to: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
#[serde(default)]
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
pub(crate) content: String,
pub(crate) media_type: Option<MediaTypeHtml>,
pub(crate) r#type: PageType,
pub(crate) id: ObjectId<ApubPost>,
pub(crate) attributed_to: ObjectId<ApubPerson>,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
#[serde(default)]
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
pub(crate) name: String,
pub(crate) content: Option<String>,