mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-12-23 19:31:33 +00:00
When announcing incoming activities, keep extra fields (#2550)
This commit is contained in:
parent
e3bb43542c
commit
a0fed24cee
41 changed files with 243 additions and 271 deletions
|
@ -9,7 +9,7 @@
|
||||||
],
|
],
|
||||||
"target": "http://enterprise.lemmy.ml/c/main",
|
"target": "http://enterprise.lemmy.ml/c/main",
|
||||||
"type": "Block",
|
"type": "Block",
|
||||||
"remove_data": "true",
|
"removeData": true,
|
||||||
"summary": "spam post",
|
"summary": "spam post",
|
||||||
"expires": "2021-11-01T12:23:50.151874+00:00",
|
"expires": "2021-11-01T12:23:50.151874+00:00",
|
||||||
"id": "http://enterprise.lemmy.ml/activities/block/5d42fffb-0903-4625-86d4-0b39bb344fc2"
|
"id": "http://enterprise.lemmy.ml/activities/block/5d42fffb-0903-4625-86d4-0b39bb344fc2"
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
],
|
],
|
||||||
"target": "http://enterprise.lemmy.ml/c/main",
|
"target": "http://enterprise.lemmy.ml/c/main",
|
||||||
"type": "Block",
|
"type": "Block",
|
||||||
"remove_data": "true",
|
"removeData": true,
|
||||||
"summary": "spam post",
|
"summary": "spam post",
|
||||||
"expires": "2021-11-01T12:23:50.151874+00:00",
|
"expires": "2021-11-01T12:23:50.151874+00:00",
|
||||||
"id": "http://enterprise.lemmy.ml/activities/block/726f43ab-bd0e-4ab3-89c8-627e976f553c"
|
"id": "http://enterprise.lemmy.ml/activities/block/726f43ab-bd0e-4ab3-89c8-627e976f553c"
|
||||||
|
|
|
@ -1,61 +1,81 @@
|
||||||
{
|
{
|
||||||
"type": "OrderedCollection",
|
"type":"OrderedCollection",
|
||||||
"id": "https://ds9.lemmy.ml/c/testcom/outbox",
|
"id":"https://ds9.lemmy.ml/c/testcom/outbox",
|
||||||
"totalItems": 2,
|
"totalItems":2,
|
||||||
"orderedItems": [
|
"orderedItems":[
|
||||||
{
|
{
|
||||||
"actor": "https://ds9.lemmy.ml/c/testcom",
|
"actor":"https://ds9.lemmy.ml/c/testcom",
|
||||||
"to": [
|
"to":[
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
],
|
],
|
||||||
"object": {
|
"object":{
|
||||||
"type": "Page",
|
"actor":"https://ds9.lemmy.ml/u/nutomic",
|
||||||
"id": "https://ds9.lemmy.ml/post/2328",
|
"to":[
|
||||||
"attributedTo": "https://ds9.lemmy.ml/u/nutomic",
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
"to": [
|
],
|
||||||
|
"cc":[
|
||||||
|
"https://ds9.lemmy.ml/c/testcom"
|
||||||
|
],
|
||||||
|
"type":"Create",
|
||||||
|
"id":"http://ds9.lemmy.ml/activities/create/eee6a57a-622f-464d-b560-73ae1fcd3ddf",
|
||||||
|
"object":{
|
||||||
|
"type":"Page",
|
||||||
|
"id":"https://ds9.lemmy.ml/post/2328",
|
||||||
|
"attributedTo":"https://ds9.lemmy.ml/u/nutomic",
|
||||||
|
"to":[
|
||||||
"https://ds9.lemmy.ml/c/testcom",
|
"https://ds9.lemmy.ml/c/testcom",
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
],
|
],
|
||||||
"cc": [],
|
"name":"another outbox test",
|
||||||
"name": "another outbox test",
|
"mediaType":"text/html",
|
||||||
"mediaType": "text/html",
|
"commentsEnabled":true,
|
||||||
"commentsEnabled": true,
|
"sensitive":false,
|
||||||
"sensitive": false,
|
"stickied":false,
|
||||||
"stickied": false,
|
"published":"2021-11-18T17:19:45.895163+00:00"
|
||||||
"published": "2021-11-18T17:19:45.895163+00:00"
|
}
|
||||||
},
|
},
|
||||||
"cc": [
|
"cc":[
|
||||||
"https://ds9.lemmy.ml/c/testcom/followers"
|
"https://ds9.lemmy.ml/c/testcom/followers"
|
||||||
],
|
],
|
||||||
"type": "Announce",
|
"type":"Announce",
|
||||||
"id": "https://ds9.lemmy.ml/activities/announce/b204fe9f-b13d-4af2-9d22-239ac2d892e6"
|
"id":"https://ds9.lemmy.ml/activities/announce/b204fe9f-b13d-4af2-9d22-239ac2d892e6"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"actor": "https://ds9.lemmy.ml/c/testcom",
|
"actor":"https://ds9.lemmy.ml/c/testcom",
|
||||||
"to": [
|
"to":[
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
],
|
],
|
||||||
"object": {
|
"object":{
|
||||||
"type": "Page",
|
"actor":"https://ds9.lemmy.ml/u/nutomic",
|
||||||
"id": "https://ds9.lemmy.ml/post/2327",
|
"to":[
|
||||||
"attributedTo": "https://ds9.lemmy.ml/u/nutomic",
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
"to": [
|
],
|
||||||
|
"cc":[
|
||||||
|
"https://ds9.lemmy.ml/c/testcom"
|
||||||
|
],
|
||||||
|
"type":"Create",
|
||||||
|
"id":"http://ds9.lemmy.ml/activities/create/eee6a57a-622f-464d-b560-73ae1fcd3ddf",
|
||||||
|
"object":{
|
||||||
|
"type":"Page",
|
||||||
|
"id":"https://ds9.lemmy.ml/post/2327",
|
||||||
|
"attributedTo":"https://ds9.lemmy.ml/u/nutomic",
|
||||||
|
"to":[
|
||||||
"https://ds9.lemmy.ml/c/testcom",
|
"https://ds9.lemmy.ml/c/testcom",
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
],
|
],
|
||||||
"cc": [],
|
"name":"outbox test",
|
||||||
"name": "outbox test",
|
"mediaType":"text/html",
|
||||||
"mediaType": "text/html",
|
"commentsEnabled":true,
|
||||||
"commentsEnabled": true,
|
"sensitive":false,
|
||||||
"sensitive": false,
|
"stickied":false,
|
||||||
"stickied": false,
|
"published":"2021-11-18T17:19:05.763109+00:00"
|
||||||
"published": "2021-11-18T17:19:05.763109+00:00"
|
}
|
||||||
},
|
},
|
||||||
"cc": [
|
"cc":[
|
||||||
"https://ds9.lemmy.ml/c/testcom/followers"
|
"https://ds9.lemmy.ml/c/testcom/followers"
|
||||||
],
|
],
|
||||||
"type": "Announce",
|
"type":"Announce",
|
||||||
"id": "https://ds9.lemmy.ml/activities/announce/c6c960ce-c8d8-4231-925e-3ba367468f18"
|
"id":"https://ds9.lemmy.ml/activities/announce/c6c960ce-c8d8-4231-925e-3ba367468f18"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -65,7 +65,6 @@ impl BlockUser {
|
||||||
&context.settings().get_protocol_and_hostname(),
|
&context.settings().get_protocol_and_hostname(),
|
||||||
)?,
|
)?,
|
||||||
expires: expires.map(convert_datetime),
|
expires: expires.map(convert_datetime),
|
||||||
unparsed: Default::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,6 @@ impl UndoBlockUser {
|
||||||
cc: generate_cc(target, context.pool()).await?,
|
cc: generate_cc(target, context.pool()).await?,
|
||||||
kind: UndoType::Undo,
|
kind: UndoType::Undo,
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
unparsed: Default::default(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut inboxes = vec![user.shared_inbox_or_inbox()];
|
let mut inboxes = vec![user.shared_inbox_or_inbox()];
|
||||||
|
|
|
@ -55,7 +55,6 @@ impl AddMod {
|
||||||
cc: vec![community.actor_id()],
|
cc: vec![community.actor_id()],
|
||||||
kind: AddType::Add,
|
kind: AddType::Add,
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
unparsed: Default::default(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let activity = AnnouncableActivities::AddMod(add);
|
let activity = AnnouncableActivities::AddMod(add);
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::{generate_activity_id, send_lemmy_activity, verify_is_public},
|
activities::{
|
||||||
|
generate_activity_id,
|
||||||
|
send_lemmy_activity,
|
||||||
|
verify_is_public,
|
||||||
|
verify_person_in_community,
|
||||||
|
},
|
||||||
activity_lists::AnnouncableActivities,
|
activity_lists::AnnouncableActivities,
|
||||||
insert_activity,
|
insert_activity,
|
||||||
objects::community::ApubCommunity,
|
objects::community::ApubCommunity,
|
||||||
protocol::{
|
protocol::{
|
||||||
activities::{community::announce::AnnounceActivity, CreateOrUpdateType},
|
activities::community::announce::{AnnounceActivity, RawAnnouncableActivities},
|
||||||
|
Id,
|
||||||
IdOrNestedObject,
|
IdOrNestedObject,
|
||||||
},
|
},
|
||||||
ActorType,
|
ActorType,
|
||||||
|
@ -13,9 +19,59 @@ use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::Acti
|
||||||
use activitystreams_kinds::{activity::AnnounceType, public};
|
use activitystreams_kinds::{activity::AnnounceType, public};
|
||||||
use lemmy_utils::error::LemmyError;
|
use lemmy_utils::error::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
use serde_json::Value;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl ActivityHandler for RawAnnouncableActivities {
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
type Error = LemmyError;
|
||||||
|
|
||||||
|
fn id(&self) -> &Url {
|
||||||
|
&self.id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn actor(&self) -> &Url {
|
||||||
|
&self.actor
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
async fn verify(
|
||||||
|
&self,
|
||||||
|
_data: &Data<Self::DataType>,
|
||||||
|
_request_counter: &mut i32,
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
async fn receive(
|
||||||
|
self,
|
||||||
|
data: &Data<Self::DataType>,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
let activity: AnnouncableActivities = self.clone().try_into()?;
|
||||||
|
// This is only for sending, not receiving so we reject it.
|
||||||
|
if let AnnouncableActivities::Page(_) = activity {
|
||||||
|
return Err(LemmyError::from_message("Cant receive page"));
|
||||||
|
}
|
||||||
|
let community = activity.get_community(data, &mut 0).await?;
|
||||||
|
let actor_id = ObjectId::new(activity.actor().clone());
|
||||||
|
|
||||||
|
// verify and receive activity
|
||||||
|
activity.verify(data, request_counter).await?;
|
||||||
|
activity.receive(data, request_counter).await?;
|
||||||
|
|
||||||
|
// send to community followers
|
||||||
|
if community.local {
|
||||||
|
verify_person_in_community(&actor_id, &community, data, &mut 0).await?;
|
||||||
|
AnnounceActivity::send(self, &community, data).await?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
pub(crate) trait GetCommunity {
|
pub(crate) trait GetCommunity {
|
||||||
async fn get_community(
|
async fn get_community(
|
||||||
|
@ -27,7 +83,7 @@ pub(crate) trait GetCommunity {
|
||||||
|
|
||||||
impl AnnounceActivity {
|
impl AnnounceActivity {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
object: AnnouncableActivities,
|
object: RawAnnouncableActivities,
|
||||||
community: &ApubCommunity,
|
community: &ApubCommunity,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<AnnounceActivity, LemmyError> {
|
) -> Result<AnnounceActivity, LemmyError> {
|
||||||
|
@ -41,13 +97,12 @@ impl AnnounceActivity {
|
||||||
&AnnounceType::Announce,
|
&AnnounceType::Announce,
|
||||||
&context.settings().get_protocol_and_hostname(),
|
&context.settings().get_protocol_and_hostname(),
|
||||||
)?,
|
)?,
|
||||||
unparsed: Default::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
object: AnnouncableActivities,
|
object: RawAnnouncableActivities,
|
||||||
community: &ApubCommunity,
|
community: &ApubCommunity,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
|
@ -57,13 +112,18 @@ impl AnnounceActivity {
|
||||||
|
|
||||||
// Pleroma and Mastodon can't handle activities like Announce/Create/Page. So for
|
// Pleroma and Mastodon can't handle activities like Announce/Create/Page. So for
|
||||||
// compatibility, we also send Announce/Page so that they can follow Lemmy communities.
|
// compatibility, we also send Announce/Page so that they can follow Lemmy communities.
|
||||||
use AnnouncableActivities::*;
|
let object_parsed = object.try_into()?;
|
||||||
let object = match object {
|
if let AnnouncableActivities::CreateOrUpdatePost(c) = object_parsed {
|
||||||
CreateOrUpdatePost(c) if c.kind == CreateOrUpdateType::Create => Page(c.object),
|
// Hack: need to convert Page into a format which can be sent as activity, which requires
|
||||||
_ => return Ok(()),
|
// adding actor field.
|
||||||
|
let announcable_page = RawAnnouncableActivities {
|
||||||
|
id: c.object.id.clone().into_inner(),
|
||||||
|
actor: c.actor.clone().into_inner(),
|
||||||
|
other: serde_json::to_value(c.object)?.as_object().unwrap().clone(),
|
||||||
};
|
};
|
||||||
let announce_compat = AnnounceActivity::new(object, community, context)?;
|
let announce_compat = AnnounceActivity::new(announcable_page, community, context)?;
|
||||||
send_lemmy_activity(context, announce_compat, community, inboxes, false).await?;
|
send_lemmy_activity(context, announce_compat, community, inboxes, false).await?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,18 +157,21 @@ impl ActivityHandler for AnnounceActivity {
|
||||||
context: &Data<LemmyContext>,
|
context: &Data<LemmyContext>,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let object = self.object.object(context, request_counter).await?;
|
let object: AnnouncableActivities = self
|
||||||
|
.object
|
||||||
|
.object(context, request_counter)
|
||||||
|
.await?
|
||||||
|
.try_into()?;
|
||||||
|
// This is only for sending, not receiving so we reject it.
|
||||||
|
if let AnnouncableActivities::Page(_) = object {
|
||||||
|
return Err(LemmyError::from_message("Cant receive page"));
|
||||||
|
}
|
||||||
|
|
||||||
// we have to verify this here in order to avoid fetching the object twice over http
|
// we have to verify this here in order to avoid fetching the object twice over http
|
||||||
object.verify(context, request_counter).await?;
|
object.verify(context, request_counter).await?;
|
||||||
|
|
||||||
// TODO: this can probably be implemented in a cleaner way
|
|
||||||
match object {
|
|
||||||
// Dont insert these into activities table, as they are not activities.
|
|
||||||
AnnouncableActivities::Page(_) => {}
|
|
||||||
_ => {
|
|
||||||
let object_value = serde_json::to_value(&object)?;
|
let object_value = serde_json::to_value(&object)?;
|
||||||
let insert =
|
let insert = insert_activity(object.id(), object_value, false, true, context.pool()).await?;
|
||||||
insert_activity(object.id(), object_value, false, true, context.pool()).await?;
|
|
||||||
if !insert {
|
if !insert {
|
||||||
debug!(
|
debug!(
|
||||||
"Received duplicate activity in announce {}",
|
"Received duplicate activity in announce {}",
|
||||||
|
@ -116,8 +179,31 @@ impl ActivityHandler for AnnounceActivity {
|
||||||
);
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
object.receive(context, request_counter).await
|
object.receive(context, request_counter).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Id for RawAnnouncableActivities {
|
||||||
|
fn object_id(&self) -> &Url {
|
||||||
|
ActivityHandler::id(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<RawAnnouncableActivities> for AnnouncableActivities {
|
||||||
|
type Error = serde_json::error::Error;
|
||||||
|
|
||||||
|
fn try_from(value: RawAnnouncableActivities) -> Result<Self, Self::Error> {
|
||||||
|
let mut map = value.other.clone();
|
||||||
|
map.insert("id".to_string(), Value::String(value.id.to_string()));
|
||||||
|
map.insert("actor".to_string(), Value::String(value.actor.to_string()));
|
||||||
|
serde_json::from_value(Value::Object(map))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<AnnouncableActivities> for RawAnnouncableActivities {
|
||||||
|
type Error = serde_json::error::Error;
|
||||||
|
|
||||||
|
fn try_from(value: AnnouncableActivities) -> Result<Self, Self::Error> {
|
||||||
|
serde_json::from_value(serde_json::to_value(value)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ where
|
||||||
send_lemmy_activity(context, activity.clone(), actor, inboxes, false).await?;
|
send_lemmy_activity(context, activity.clone(), actor, inboxes, false).await?;
|
||||||
|
|
||||||
if community.local {
|
if community.local {
|
||||||
AnnounceActivity::send(activity, community, context).await?;
|
AnnounceActivity::send(activity.try_into()?, community, context).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -55,7 +55,6 @@ impl RemoveMod {
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
cc: vec![community.actor_id()],
|
cc: vec![community.actor_id()],
|
||||||
kind: RemoveType::Remove,
|
kind: RemoveType::Remove,
|
||||||
unparsed: Default::default(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let activity = AnnouncableActivities::RemoveMod(remove);
|
let activity = AnnouncableActivities::RemoveMod(remove);
|
||||||
|
|
|
@ -47,7 +47,6 @@ impl Report {
|
||||||
summary: reason,
|
summary: reason,
|
||||||
kind,
|
kind,
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
unparsed: Default::default(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let inbox = vec![community.shared_inbox_or_inbox()];
|
let inbox = vec![community.shared_inbox_or_inbox()];
|
||||||
|
|
|
@ -41,7 +41,6 @@ impl UpdateCommunity {
|
||||||
cc: vec![community.actor_id()],
|
cc: vec![community.actor_id()],
|
||||||
kind: UpdateType::Update,
|
kind: UpdateType::Update,
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
unparsed: Default::default(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let activity = AnnouncableActivities::UpdateCommunity(update);
|
let activity = AnnouncableActivities::UpdateCommunity(update);
|
||||||
|
|
|
@ -63,7 +63,6 @@ impl CreateOrUpdateComment {
|
||||||
object: note,
|
object: note,
|
||||||
kind,
|
kind,
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
unparsed: Default::default(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let tagged_users: Vec<ObjectId<ApubPerson>> = create_or_update
|
let tagged_users: Vec<ObjectId<ApubPerson>> = create_or_update
|
||||||
|
|
|
@ -49,7 +49,6 @@ impl CreateOrUpdatePost {
|
||||||
cc: vec![community.actor_id()],
|
cc: vec![community.actor_id()],
|
||||||
kind,
|
kind,
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
unparsed: Default::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +64,8 @@ impl CreateOrUpdatePost {
|
||||||
|
|
||||||
let create_or_update = CreateOrUpdatePost::new(post, actor, &community, kind, context).await?;
|
let create_or_update = CreateOrUpdatePost::new(post, actor, &community, kind, context).await?;
|
||||||
let activity = AnnouncableActivities::CreateOrUpdatePost(Box::new(create_or_update));
|
let activity = AnnouncableActivities::CreateOrUpdatePost(Box::new(create_or_update));
|
||||||
send_activity_in_community(activity, actor, &community, vec![], context).await
|
send_activity_in_community(activity, actor, &community, vec![], context).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,6 @@ impl CreateOrUpdatePrivateMessage {
|
||||||
to: [ObjectId::new(recipient.actor_id())],
|
to: [ObjectId::new(recipient.actor_id())],
|
||||||
object: private_message.into_apub(context).await?,
|
object: private_message.into_apub(context).await?,
|
||||||
kind,
|
kind,
|
||||||
unparsed: Default::default(),
|
|
||||||
};
|
};
|
||||||
let inbox = vec![recipient.shared_inbox_or_inbox()];
|
let inbox = vec![recipient.shared_inbox_or_inbox()];
|
||||||
send_lemmy_activity(context, create_or_update, actor, inbox, true).await
|
send_lemmy_activity(context, create_or_update, actor, inbox, true).await
|
||||||
|
|
|
@ -117,7 +117,6 @@ impl Delete {
|
||||||
kind: DeleteType::Delete,
|
kind: DeleteType::Delete,
|
||||||
summary,
|
summary,
|
||||||
id,
|
id,
|
||||||
unparsed: Default::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,6 @@ impl UndoDelete {
|
||||||
cc: cc.into_iter().collect(),
|
cc: cc.into_iter().collect(),
|
||||||
kind: UndoType::Undo,
|
kind: UndoType::Undo,
|
||||||
id,
|
id,
|
||||||
unparsed: Default::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ impl AcceptFollowCommunity {
|
||||||
AcceptType::Accept,
|
AcceptType::Accept,
|
||||||
&context.settings().get_protocol_and_hostname(),
|
&context.settings().get_protocol_and_hostname(),
|
||||||
)?,
|
)?,
|
||||||
unparsed: Default::default(),
|
|
||||||
};
|
};
|
||||||
let inbox = vec![person.shared_inbox_or_inbox()];
|
let inbox = vec![person.shared_inbox_or_inbox()];
|
||||||
send_lemmy_activity(context, accept, &community, inbox, true).await
|
send_lemmy_activity(context, accept, &community, inbox, true).await
|
||||||
|
|
|
@ -38,7 +38,6 @@ impl FollowCommunity {
|
||||||
FollowType::Follow,
|
FollowType::Follow,
|
||||||
&context.settings().get_protocol_and_hostname(),
|
&context.settings().get_protocol_and_hostname(),
|
||||||
)?,
|
)?,
|
||||||
unparsed: Default::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ impl UndoFollowCommunity {
|
||||||
UndoType::Undo,
|
UndoType::Undo,
|
||||||
&context.settings().get_protocol_and_hostname(),
|
&context.settings().get_protocol_and_hostname(),
|
||||||
)?,
|
)?,
|
||||||
unparsed: Default::default(),
|
|
||||||
};
|
};
|
||||||
let inbox = vec![community.shared_inbox_or_inbox()];
|
let inbox = vec![community.shared_inbox_or_inbox()];
|
||||||
send_lemmy_activity(context, undo, actor, inbox, true).await
|
send_lemmy_activity(context, undo, actor, inbox, true).await
|
||||||
|
|
|
@ -51,7 +51,6 @@ impl UndoVote {
|
||||||
object,
|
object,
|
||||||
kind: UndoType::Undo,
|
kind: UndoType::Undo,
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
unparsed: Default::default(),
|
|
||||||
};
|
};
|
||||||
let activity = AnnouncableActivities::UndoVote(undo_vote);
|
let activity = AnnouncableActivities::UndoVote(undo_vote);
|
||||||
send_activity_in_community(activity, actor, &community, vec![], context).await
|
send_activity_in_community(activity, actor, &community, vec![], context).await
|
||||||
|
|
|
@ -37,7 +37,6 @@ impl Vote {
|
||||||
object: ObjectId::new(object.ap_id()),
|
object: ObjectId::new(object.ap_id()),
|
||||||
kind: kind.clone(),
|
kind: kind.clone(),
|
||||||
id: generate_activity_id(kind, &context.settings().get_protocol_and_hostname())?,
|
id: generate_activity_id(kind, &context.settings().get_protocol_and_hostname())?,
|
||||||
unparsed: Default::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::{community::announce::GetCommunity, verify_person_in_community},
|
activities::community::announce::GetCommunity,
|
||||||
objects::community::ApubCommunity,
|
objects::community::ApubCommunity,
|
||||||
protocol::{
|
protocol::{
|
||||||
activities::{
|
activities::{
|
||||||
block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
|
block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
|
||||||
community::{
|
community::{
|
||||||
add_mod::AddMod,
|
add_mod::AddMod,
|
||||||
announce::AnnounceActivity,
|
announce::{AnnounceActivity, RawAnnouncableActivities},
|
||||||
remove_mod::RemoveMod,
|
remove_mod::RemoveMod,
|
||||||
report::Report,
|
report::Report,
|
||||||
update::UpdateCommunity,
|
update::UpdateCommunity,
|
||||||
|
@ -25,15 +25,9 @@ use crate::{
|
||||||
voting::{undo_vote::UndoVote, vote::Vote},
|
voting::{undo_vote::UndoVote, vote::Vote},
|
||||||
},
|
},
|
||||||
objects::page::Page,
|
objects::page::Page,
|
||||||
Id,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{deser::context::WithContext, traits::activity_handler};
|
||||||
core::object_id::ObjectId,
|
|
||||||
data::Data,
|
|
||||||
deser::context::WithContext,
|
|
||||||
traits::{activity_handler, ActivityHandler},
|
|
||||||
};
|
|
||||||
use lemmy_utils::error::LemmyError;
|
use lemmy_utils::error::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -43,19 +37,19 @@ use url::Url;
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
#[activity_handler(LemmyContext, LemmyError)]
|
#[activity_handler(LemmyContext, LemmyError)]
|
||||||
pub enum SharedInboxActivities {
|
pub enum SharedInboxActivities {
|
||||||
GroupInboxActivities(Box<WithContext<GroupInboxActivities>>),
|
|
||||||
// Note, pm activities need to be at the end, otherwise comments will end up here. We can probably
|
|
||||||
// avoid this problem by replacing createpm.object with our own struct, instead of NoteExt.
|
|
||||||
PersonInboxActivities(Box<WithContext<PersonInboxActivities>>),
|
PersonInboxActivities(Box<WithContext<PersonInboxActivities>>),
|
||||||
|
GroupInboxActivities(Box<WithContext<GroupInboxActivities>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
|
#[activity_handler(LemmyContext, LemmyError)]
|
||||||
pub enum GroupInboxActivities {
|
pub enum GroupInboxActivities {
|
||||||
FollowCommunity(FollowCommunity),
|
FollowCommunity(FollowCommunity),
|
||||||
UndoFollowCommunity(UndoFollowCommunity),
|
UndoFollowCommunity(UndoFollowCommunity),
|
||||||
AnnouncableActivities(Box<AnnouncableActivities>),
|
|
||||||
Report(Report),
|
Report(Report),
|
||||||
|
// This is a catch-all and needs to be last
|
||||||
|
AnnouncableActivities(RawAnnouncableActivities),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
@ -63,14 +57,23 @@ pub enum GroupInboxActivities {
|
||||||
#[activity_handler(LemmyContext, LemmyError)]
|
#[activity_handler(LemmyContext, LemmyError)]
|
||||||
pub enum PersonInboxActivities {
|
pub enum PersonInboxActivities {
|
||||||
AcceptFollowCommunity(AcceptFollowCommunity),
|
AcceptFollowCommunity(AcceptFollowCommunity),
|
||||||
/// Some activities can also be sent from user to user, eg a comment with mentions
|
|
||||||
AnnouncableActivities(AnnouncableActivities),
|
|
||||||
CreateOrUpdatePrivateMessage(CreateOrUpdatePrivateMessage),
|
CreateOrUpdatePrivateMessage(CreateOrUpdatePrivateMessage),
|
||||||
Delete(Delete),
|
Delete(Delete),
|
||||||
UndoDelete(UndoDelete),
|
UndoDelete(UndoDelete),
|
||||||
AnnounceActivity(AnnounceActivity),
|
AnnounceActivity(AnnounceActivity),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is necessary for user inbox, which can also receive some "announcable" activities,
|
||||||
|
/// eg a comment mention. This needs to be a separate enum so that announcables received in shared
|
||||||
|
/// inbox can fall through to be parsed as GroupInboxActivities::AnnouncableActivities.
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
#[activity_handler(LemmyContext, LemmyError)]
|
||||||
|
pub enum PersonInboxActivitiesWithAnnouncable {
|
||||||
|
PersonInboxActivities(PersonInboxActivities),
|
||||||
|
AnnouncableActivities(AnnouncableActivities),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
#[activity_handler(LemmyContext, LemmyError)]
|
#[activity_handler(LemmyContext, LemmyError)]
|
||||||
|
@ -127,77 +130,6 @@ impl GetCommunity for AnnouncableActivities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Id for AnnouncableActivities {
|
|
||||||
fn object_id(&self) -> &Url {
|
|
||||||
ActivityHandler::id(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Need to implement this manually to announce matching activities
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
impl ActivityHandler for GroupInboxActivities {
|
|
||||||
type DataType = LemmyContext;
|
|
||||||
type Error = LemmyError;
|
|
||||||
|
|
||||||
fn id(&self) -> &Url {
|
|
||||||
match self {
|
|
||||||
GroupInboxActivities::FollowCommunity(a) => a.id(),
|
|
||||||
GroupInboxActivities::UndoFollowCommunity(a) => a.id(),
|
|
||||||
GroupInboxActivities::AnnouncableActivities(a) => a.object_id(),
|
|
||||||
GroupInboxActivities::Report(a) => a.id(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn actor(&self) -> &Url {
|
|
||||||
match self {
|
|
||||||
GroupInboxActivities::FollowCommunity(a) => a.actor(),
|
|
||||||
GroupInboxActivities::UndoFollowCommunity(a) => a.actor(),
|
|
||||||
GroupInboxActivities::AnnouncableActivities(a) => a.actor(),
|
|
||||||
GroupInboxActivities::Report(a) => a.actor(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn verify(
|
|
||||||
&self,
|
|
||||||
data: &Data<Self::DataType>,
|
|
||||||
request_counter: &mut i32,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
match self {
|
|
||||||
GroupInboxActivities::FollowCommunity(a) => a.verify(data, request_counter).await,
|
|
||||||
GroupInboxActivities::UndoFollowCommunity(a) => a.verify(data, request_counter).await,
|
|
||||||
GroupInboxActivities::AnnouncableActivities(a) => a.verify(data, request_counter).await,
|
|
||||||
GroupInboxActivities::Report(a) => a.verify(data, request_counter).await,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn receive(
|
|
||||||
self,
|
|
||||||
data: &Data<Self::DataType>,
|
|
||||||
request_counter: &mut i32,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
match self {
|
|
||||||
GroupInboxActivities::FollowCommunity(a) => a.receive(data, request_counter).await,
|
|
||||||
GroupInboxActivities::UndoFollowCommunity(a) => a.receive(data, request_counter).await,
|
|
||||||
GroupInboxActivities::AnnouncableActivities(activity) => {
|
|
||||||
activity.clone().receive(data, request_counter).await?;
|
|
||||||
|
|
||||||
// Ignore failures in get_community(). those happen because Delete/PrivateMessage is not in a
|
|
||||||
// community, but looks identical to Delete/Post or Delete/Comment which are in a community.
|
|
||||||
let community = activity.get_community(data, &mut 0).await;
|
|
||||||
if let Ok(community) = community {
|
|
||||||
if community.local {
|
|
||||||
let actor_id = ObjectId::new(activity.actor().clone());
|
|
||||||
verify_person_in_community(&actor_id, &community, data, &mut 0).await?;
|
|
||||||
AnnounceActivity::send(*activity, &community, data).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
GroupInboxActivities::Report(a) => a.receive(data, request_counter).await,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -4,7 +4,11 @@ use crate::{
|
||||||
generate_outbox_url,
|
generate_outbox_url,
|
||||||
objects::post::ApubPost,
|
objects::post::ApubPost,
|
||||||
protocol::{
|
protocol::{
|
||||||
activities::community::announce::AnnounceActivity,
|
activities::{
|
||||||
|
community::announce::AnnounceActivity,
|
||||||
|
create_or_update::post::CreateOrUpdatePost,
|
||||||
|
CreateOrUpdateType,
|
||||||
|
},
|
||||||
collections::group_outbox::GroupOutbox,
|
collections::group_outbox::GroupOutbox,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -16,7 +20,10 @@ use activitypub_federation::{
|
||||||
use activitystreams_kinds::collection::OrderedCollectionType;
|
use activitystreams_kinds::collection::OrderedCollectionType;
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
use lemmy_db_schema::source::post::Post;
|
use lemmy_db_schema::{
|
||||||
|
source::{person::Person, post::Post},
|
||||||
|
traits::Crud,
|
||||||
|
};
|
||||||
use lemmy_utils::error::LemmyError;
|
use lemmy_utils::error::LemmyError;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -61,9 +68,12 @@ impl ApubObject for ApubCommunityOutbox {
|
||||||
async fn into_apub(self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
|
async fn into_apub(self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
|
||||||
let mut ordered_items = vec![];
|
let mut ordered_items = vec![];
|
||||||
for post in self.0 {
|
for post in self.0 {
|
||||||
let page = post.into_apub(&data.1).await?;
|
let person = Person::read(data.1.pool(), post.creator_id).await?.into();
|
||||||
let announcable = AnnouncableActivities::Page(page);
|
let create =
|
||||||
let announce = AnnounceActivity::new(announcable, &data.0, &data.1)?;
|
CreateOrUpdatePost::new(post, &person, &data.0, CreateOrUpdateType::Create, &data.1)
|
||||||
|
.await?;
|
||||||
|
let announcable = AnnouncableActivities::CreateOrUpdatePost(Box::new(create));
|
||||||
|
let announce = AnnounceActivity::new(announcable.try_into()?, &data.0, &data.1)?;
|
||||||
ordered_items.push(announce);
|
ordered_items.push(announce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activity_lists::PersonInboxActivities,
|
activity_lists::PersonInboxActivitiesWithAnnouncable,
|
||||||
fetcher::user_or_community::UserOrCommunity,
|
fetcher::user_or_community::UserOrCommunity,
|
||||||
generate_outbox_url,
|
generate_outbox_url,
|
||||||
http::{create_apub_response, create_apub_tombstone_response, receive_lemmy_activity},
|
http::{create_apub_response, create_apub_tombstone_response, receive_lemmy_activity},
|
||||||
|
@ -45,7 +45,7 @@ pub async fn person_inbox(
|
||||||
payload: String,
|
payload: String,
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse, LemmyError> {
|
) -> Result<HttpResponse, LemmyError> {
|
||||||
receive_lemmy_activity::<WithContext<PersonInboxActivities>, UserOrCommunity>(
|
receive_lemmy_activity::<WithContext<PersonInboxActivitiesWithAnnouncable>, UserOrCommunity>(
|
||||||
request, payload, context,
|
request, payload, context,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{activities::block::SiteOrCommunity, objects::person::ApubPerson, protocol::Unparsed};
|
use crate::{activities::block::SiteOrCommunity, objects::person::ApubPerson};
|
||||||
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
||||||
use activitystreams_kinds::activity::BlockType;
|
use activitystreams_kinds::activity::BlockType;
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset};
|
||||||
|
@ -25,6 +25,4 @@ pub struct BlockUser {
|
||||||
/// block reason, written to mod log
|
/// block reason, written to mod log
|
||||||
pub(crate) summary: Option<String>,
|
pub(crate) summary: Option<String>,
|
||||||
pub(crate) expires: Option<DateTime<FixedOffset>>,
|
pub(crate) expires: Option<DateTime<FixedOffset>>,
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
use crate::{
|
use crate::{objects::person::ApubPerson, protocol::activities::block::block_user::BlockUser};
|
||||||
objects::person::ApubPerson,
|
|
||||||
protocol::{activities::block::block_user::BlockUser, Unparsed},
|
|
||||||
};
|
|
||||||
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
||||||
use activitystreams_kinds::activity::UndoType;
|
use activitystreams_kinds::activity::UndoType;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -19,7 +16,4 @@ pub struct UndoBlockUser {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: UndoType,
|
pub(crate) kind: UndoType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{objects::person::ApubPerson, protocol::Unparsed};
|
use crate::objects::person::ApubPerson;
|
||||||
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
||||||
use activitystreams_kinds::activity::AddType;
|
use activitystreams_kinds::activity::AddType;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -17,7 +17,4 @@ pub struct AddMod {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: AddType,
|
pub(crate) kind: AddType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
use crate::{
|
use crate::{objects::community::ApubCommunity, protocol::IdOrNestedObject};
|
||||||
activity_lists::AnnouncableActivities,
|
|
||||||
objects::community::ApubCommunity,
|
|
||||||
protocol::{IdOrNestedObject, Unparsed},
|
|
||||||
};
|
|
||||||
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
||||||
use activitystreams_kinds::activity::AnnounceType;
|
use activitystreams_kinds::activity::AnnounceType;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::{Map, Value};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
@ -14,13 +11,20 @@ pub struct AnnounceActivity {
|
||||||
pub(crate) actor: ObjectId<ApubCommunity>,
|
pub(crate) actor: ObjectId<ApubCommunity>,
|
||||||
#[serde(deserialize_with = "deserialize_one_or_many")]
|
#[serde(deserialize_with = "deserialize_one_or_many")]
|
||||||
pub(crate) to: Vec<Url>,
|
pub(crate) to: Vec<Url>,
|
||||||
pub(crate) object: IdOrNestedObject<AnnouncableActivities>,
|
pub(crate) object: IdOrNestedObject<RawAnnouncableActivities>,
|
||||||
#[serde(deserialize_with = "deserialize_one_or_many")]
|
#[serde(deserialize_with = "deserialize_one_or_many")]
|
||||||
pub(crate) cc: Vec<Url>,
|
pub(crate) cc: Vec<Url>,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: AnnounceType,
|
pub(crate) kind: AnnounceType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
}
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
/// Use this to receive community inbox activities, and then announce them if valid. This
|
||||||
|
/// ensures that all json fields are kept, even if Lemmy doesnt understand them.
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct RawAnnouncableActivities {
|
||||||
|
pub(crate) id: Url,
|
||||||
|
pub(crate) actor: Url,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub(crate) other: Map<String, Value>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{objects::person::ApubPerson, protocol::Unparsed};
|
use crate::objects::person::ApubPerson;
|
||||||
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
||||||
use activitystreams_kinds::activity::RemoveType;
|
use activitystreams_kinds::activity::RemoveType;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -17,7 +17,4 @@ pub struct RemoveMod {
|
||||||
pub(crate) kind: RemoveType,
|
pub(crate) kind: RemoveType,
|
||||||
pub(crate) target: Url,
|
pub(crate) target: Url,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
fetcher::post_or_comment::PostOrComment,
|
fetcher::post_or_comment::PostOrComment,
|
||||||
objects::{community::ApubCommunity, person::ApubPerson},
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
protocol::Unparsed,
|
|
||||||
};
|
};
|
||||||
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one};
|
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one};
|
||||||
use activitystreams_kinds::activity::FlagType;
|
use activitystreams_kinds::activity::FlagType;
|
||||||
|
@ -19,7 +18,4 @@ pub struct Report {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: FlagType,
|
pub(crate) kind: FlagType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
use crate::{
|
use crate::{objects::person::ApubPerson, protocol::objects::group::Group};
|
||||||
objects::person::ApubPerson,
|
|
||||||
protocol::{objects::group::Group, Unparsed},
|
|
||||||
};
|
|
||||||
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
||||||
use activitystreams_kinds::activity::UpdateType;
|
use activitystreams_kinds::activity::UpdateType;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -22,7 +19,4 @@ pub struct UpdateCommunity {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: UpdateType,
|
pub(crate) kind: UpdateType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
mentions::MentionOrValue,
|
mentions::MentionOrValue,
|
||||||
objects::person::ApubPerson,
|
objects::person::ApubPerson,
|
||||||
protocol::{activities::CreateOrUpdateType, objects::note::Note, Unparsed},
|
protocol::{activities::CreateOrUpdateType, objects::note::Note},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -21,7 +21,4 @@ pub struct CreateOrUpdateComment {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: CreateOrUpdateType,
|
pub(crate) kind: CreateOrUpdateType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::person::ApubPerson,
|
objects::person::ApubPerson,
|
||||||
protocol::{activities::CreateOrUpdateType, objects::page::Page, Unparsed},
|
protocol::{activities::CreateOrUpdateType, objects::page::Page},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -18,7 +18,4 @@ pub struct CreateOrUpdatePost {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: CreateOrUpdateType,
|
pub(crate) kind: CreateOrUpdateType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::person::ApubPerson,
|
objects::person::ApubPerson,
|
||||||
protocol::{activities::CreateOrUpdateType, objects::chat_message::ChatMessage, Unparsed},
|
protocol::{activities::CreateOrUpdateType, objects::chat_message::ChatMessage},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one};
|
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -16,7 +16,4 @@ pub struct CreateOrUpdatePrivateMessage {
|
||||||
pub(crate) object: ChatMessage,
|
pub(crate) object: ChatMessage,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: CreateOrUpdateType,
|
pub(crate) kind: CreateOrUpdateType,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::person::ApubPerson,
|
objects::person::ApubPerson,
|
||||||
protocol::{objects::tombstone::Tombstone, IdOrNestedObject, Unparsed},
|
protocol::{objects::tombstone::Tombstone, IdOrNestedObject},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
||||||
use activitystreams_kinds::activity::DeleteType;
|
use activitystreams_kinds::activity::DeleteType;
|
||||||
|
@ -27,6 +27,4 @@ pub struct Delete {
|
||||||
/// If summary is present, this is a mod action (Remove in Lemmy terms). Otherwise, its a user
|
/// If summary is present, this is a mod action (Remove in Lemmy terms). Otherwise, its a user
|
||||||
/// deleting their own content.
|
/// deleting their own content.
|
||||||
pub(crate) summary: Option<String>,
|
pub(crate) summary: Option<String>,
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
use crate::{
|
use crate::{objects::person::ApubPerson, protocol::activities::deletion::delete::Delete};
|
||||||
objects::person::ApubPerson,
|
|
||||||
protocol::{activities::deletion::delete::Delete, Unparsed},
|
|
||||||
};
|
|
||||||
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
|
||||||
use activitystreams_kinds::activity::UndoType;
|
use activitystreams_kinds::activity::UndoType;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -21,6 +18,4 @@ pub struct UndoDelete {
|
||||||
#[serde(deserialize_with = "deserialize_one_or_many", default)]
|
#[serde(deserialize_with = "deserialize_one_or_many", default)]
|
||||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||||
pub(crate) cc: Vec<Url>,
|
pub(crate) cc: Vec<Url>,
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::community::ApubCommunity,
|
objects::community::ApubCommunity,
|
||||||
protocol::{activities::following::follow::FollowCommunity, Unparsed},
|
protocol::activities::following::follow::FollowCommunity,
|
||||||
};
|
};
|
||||||
use activitypub_federation::core::object_id::ObjectId;
|
use activitypub_federation::core::object_id::ObjectId;
|
||||||
use activitystreams_kinds::activity::AcceptType;
|
use activitystreams_kinds::activity::AcceptType;
|
||||||
|
@ -15,7 +15,4 @@ pub struct AcceptFollowCommunity {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: AcceptType,
|
pub(crate) kind: AcceptType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
use crate::{
|
use crate::objects::{community::ApubCommunity, person::ApubPerson};
|
||||||
objects::{community::ApubCommunity, person::ApubPerson},
|
|
||||||
protocol::Unparsed,
|
|
||||||
};
|
|
||||||
use activitypub_federation::core::object_id::ObjectId;
|
use activitypub_federation::core::object_id::ObjectId;
|
||||||
use activitystreams_kinds::activity::FollowType;
|
use activitystreams_kinds::activity::FollowType;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -15,7 +12,4 @@ pub struct FollowCommunity {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: FollowType,
|
pub(crate) kind: FollowType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::person::ApubPerson,
|
objects::person::ApubPerson,
|
||||||
protocol::{activities::following::follow::FollowCommunity, Unparsed},
|
protocol::activities::following::follow::FollowCommunity,
|
||||||
};
|
};
|
||||||
use activitypub_federation::core::object_id::ObjectId;
|
use activitypub_federation::core::object_id::ObjectId;
|
||||||
use activitystreams_kinds::activity::UndoType;
|
use activitystreams_kinds::activity::UndoType;
|
||||||
|
@ -15,7 +15,4 @@ pub struct UndoFollowCommunity {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: UndoType,
|
pub(crate) kind: UndoType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
use crate::{
|
use crate::{objects::person::ApubPerson, protocol::activities::voting::vote::Vote};
|
||||||
objects::person::ApubPerson,
|
|
||||||
protocol::{activities::voting::vote::Vote, Unparsed},
|
|
||||||
};
|
|
||||||
use activitypub_federation::core::object_id::ObjectId;
|
use activitypub_federation::core::object_id::ObjectId;
|
||||||
use activitystreams_kinds::activity::UndoType;
|
use activitystreams_kinds::activity::UndoType;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -15,7 +12,4 @@ pub struct UndoVote {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: UndoType,
|
pub(crate) kind: UndoType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
use crate::{
|
use crate::{fetcher::post_or_comment::PostOrComment, objects::person::ApubPerson};
|
||||||
fetcher::post_or_comment::PostOrComment,
|
|
||||||
objects::person::ApubPerson,
|
|
||||||
protocol::Unparsed,
|
|
||||||
};
|
|
||||||
use activitypub_federation::core::object_id::ObjectId;
|
use activitypub_federation::core::object_id::ObjectId;
|
||||||
use lemmy_utils::error::LemmyError;
|
use lemmy_utils::error::LemmyError;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -18,9 +14,6 @@ pub struct Vote {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: VoteType,
|
pub(crate) kind: VoteType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) unparsed: Unparsed,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Display, Deserialize, Serialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Display, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
|
Loading…
Reference in a new issue