Merge pull request #1917 from LemmyNet/outbox-announce

Community outbox should only contain activities sent by community
fix-1914
Dessalines 2021-11-18 14:31:47 -05:00 committed by GitHub
commit e756e85da7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 199 deletions

View File

@ -1,209 +1,61 @@
{
"type": "OrderedCollection",
"id": "https://ds9.lemmy.ml/c/main/outbox",
"totalItems": 7,
"id": "https://ds9.lemmy.ml/c/testcom/outbox",
"totalItems": 2,
"orderedItems": [
{
"actor": "https://ds9.lemmy.ml/u/dess_ds9",
"actor": "https://ds9.lemmy.ml/c/testcom",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"object": {
"type": "Page",
"id": "https://ds9.lemmy.ml/post/1685",
"attributedTo": "https://ds9.lemmy.ml/u/dess_ds9",
"to": [
"https://ds9.lemmy.ml/c/main",
"https://www.w3.org/ns/activitystreams#Public"
],
"name": "Test post",
"mediaType": "text/html",
"commentsEnabled": true,
"sensitive": false,
"stickied": false,
"published": "2021-09-30T16:37:58.425718+00:00",
"updated": "2021-09-30T16:39:50.934055+00:00"
},
"cc": [
"https://ds9.lemmy.ml/c/main"
],
"type": "Create",
"id": "https://ds9.lemmy.ml/activities/create/157bc329-05cb-4dc3-ad9e-5110fde3f3aa"
},
{
"actor": "https://ds9.lemmy.ml/u/nutomic",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"object": {
"type": "Page",
"id": "https://ds9.lemmy.ml/post/1665",
"id": "https://ds9.lemmy.ml/post/2328",
"attributedTo": "https://ds9.lemmy.ml/u/nutomic",
"to": [
"https://ds9.lemmy.ml/c/main",
"https://ds9.lemmy.ml/c/testcom",
"https://www.w3.org/ns/activitystreams#Public"
],
"name": "another webmention test",
"cc": [],
"name": "another outbox test",
"mediaType": "text/html",
"url": "https://webmention.rocks/test/1",
"commentsEnabled": true,
"sensitive": false,
"stickied": false,
"published": "2021-09-17T13:22:15.026912+00:00"
"published": "2021-11-18T17:19:45.895163+00:00"
},
"cc": [
"https://ds9.lemmy.ml/c/main"
"https://ds9.lemmy.ml/c/testcom/followers"
],
"type": "Create",
"id": "https://ds9.lemmy.ml/activities/create/c54e4509-16ac-42bf-b3b4-0bf8516f8152"
"type": "Announce",
"id": "https://ds9.lemmy.ml/activities/announce/b204fe9f-b13d-4af2-9d22-239ac2d892e6"
},
{
"actor": "https://ds9.lemmy.ml/u/nutomic",
"actor": "https://ds9.lemmy.ml/c/testcom",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"object": {
"type": "Page",
"id": "https://ds9.lemmy.ml/post/1664",
"id": "https://ds9.lemmy.ml/post/2327",
"attributedTo": "https://ds9.lemmy.ml/u/nutomic",
"to": [
"https://ds9.lemmy.ml/c/main",
"https://ds9.lemmy.ml/c/testcom",
"https://www.w3.org/ns/activitystreams#Public"
],
"name": "another test",
"mediaType": "text/html",
"url": "https://webmention.rocks/test/1",
"commentsEnabled": true,
"sensitive": false,
"stickied": false,
"published": "2021-09-17T13:13:21.675891+00:00"
},
"cc": [
"https://ds9.lemmy.ml/c/main"
],
"type": "Create",
"id": "https://ds9.lemmy.ml/activities/create/25f7d2cb-11d5-4c9c-aa3c-85fbff9f9e0c"
},
{
"actor": "https://ds9.lemmy.ml/u/nutomic",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"object": {
"type": "Page",
"id": "https://ds9.lemmy.ml/post/1663",
"attributedTo": "https://ds9.lemmy.ml/u/nutomic",
"to": [
"https://ds9.lemmy.ml/c/main",
"https://www.w3.org/ns/activitystreams#Public"
],
"name": "Webmention test from Lemmy",
"mediaType": "text/html",
"url": "https://webmention.rocks/test/1",
"commentsEnabled": true,
"sensitive": false,
"stickied": false,
"published": "2021-09-17T13:00:15.392844+00:00"
},
"cc": [
"https://ds9.lemmy.ml/c/main"
],
"type": "Create",
"id": "https://ds9.lemmy.ml/activities/create/cfbd12b8-2e11-42b6-a609-b482decbaf11"
},
{
"actor": "https://ds9.lemmy.ml/u/dess_tester_3",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"object": {
"type": "Page",
"id": "https://ds9.lemmy.ml/post/1644",
"attributedTo": "https://ds9.lemmy.ml/u/dess_tester_3",
"to": [
"https://ds9.lemmy.ml/c/main",
"https://www.w3.org/ns/activitystreams#Public"
],
"name": "The best wireless earbuds you can buy right now | Engadget",
"mediaType": "text/html",
"url": "https://www.engadget.com/best-wireless-earbuds-120058222.html",
"image": {
"type": "Image",
"url": "https://ds9.lemmy.ml/pictrs/image/0WWsYOuwAE.jpg"
},
"commentsEnabled": true,
"sensitive": false,
"stickied": false,
"published": "2021-08-26T01:22:06.428368+00:00"
},
"cc": [
"https://ds9.lemmy.ml/c/main"
],
"type": "Create",
"id": "https://ds9.lemmy.ml/activities/create/76c94408-944a-4a2f-a88b-d10f12b472b0"
},
{
"actor": "https://ds9.lemmy.ml/u/dess_ds9",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"object": {
"type": "Page",
"id": "https://ds9.lemmy.ml/post/1643",
"attributedTo": "https://ds9.lemmy.ml/u/dess_ds9",
"to": [
"https://ds9.lemmy.ml/c/main",
"https://www.w3.org/ns/activitystreams#Public"
],
"name": "First Look: Cadillacs luxury EV debut seems like a winner | Engadges",
"content": "<p>test</p>\n",
"mediaType": "text/html",
"source": {
"content": "test",
"mediaType": "text/markdown"
},
"url": "https://www.engadget.com/cadillac-lyriq-luxury-ev-first-look-video-171543752.html",
"image": {
"type": "Image",
"url": "https://ds9.lemmy.ml/pictrs/image/gnmtvgXP31.jpg"
},
"commentsEnabled": true,
"sensitive": false,
"stickied": false,
"published": "2021-08-23T23:43:06.560543+00:00",
"updated": "2021-08-23T23:52:51.832606+00:00"
},
"cc": [
"https://ds9.lemmy.ml/c/main"
],
"type": "Create",
"id": "https://ds9.lemmy.ml/activities/create/b1f95918-f593-4951-91cf-2c3340cd9509"
},
{
"actor": "https://ds9.lemmy.ml/u/dess_ds9_2",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"object": {
"type": "Page",
"id": "https://ds9.lemmy.ml/post/1642",
"attributedTo": "https://ds9.lemmy.ml/u/dess_ds9_2",
"to": [
"https://ds9.lemmy.ml/c/main",
"https://www.w3.org/ns/activitystreams#Public"
],
"name": "A test post from DS9",
"cc": [],
"name": "outbox test",
"mediaType": "text/html",
"commentsEnabled": true,
"sensitive": false,
"stickied": false,
"published": "2021-08-06T14:10:47.493075+00:00"
"published": "2021-11-18T17:19:05.763109+00:00"
},
"cc": [
"https://ds9.lemmy.ml/c/main"
"https://ds9.lemmy.ml/c/testcom/followers"
],
"type": "Create",
"id": "https://ds9.lemmy.ml/activities/create/6359b2e7-badb-4241-b5ee-b093078361bd"
"type": "Announce",
"id": "https://ds9.lemmy.ml/activities/announce/c6c960ce-c8d8-4231-925e-3ba367468f18"
}
]
}

View File

@ -25,7 +25,7 @@ pub(crate) trait GetCommunity {
}
impl AnnounceActivity {
fn new(
pub(crate) fn new(
object: AnnouncableActivities,
community: &ApubCommunity,
context: &LemmyContext,
@ -103,13 +103,20 @@ impl ActivityHandler for AnnounceActivity {
context: &Data<LemmyContext>,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let object_value = serde_json::to_value(&self.object)?;
let object_data: ActivityCommonFields = serde_json::from_value(object_value.to_owned())?;
// TODO: this can probably be implemented in a cleaner way
match self.object {
// Dont insert these into activities table, as they are not activities.
AnnouncableActivities::Page(_) | AnnouncableActivities::Note(_) => {}
_ => {
let object_value = serde_json::to_value(&self.object)?;
let object_data: ActivityCommonFields = serde_json::from_value(object_value.to_owned())?;
if is_activity_already_known(context.pool(), &object_data.id).await? {
return Ok(());
if is_activity_already_known(context.pool(), &object_data.id).await? {
return Ok(());
}
insert_activity(&object_data.id, object_value, false, true, context.pool()).await?;
}
}
insert_activity(&object_data.id, object_value, false, true, context.pool()).await?;
self.object.receive(context, request_counter).await
}
}

View File

@ -1,9 +1,10 @@
use crate::{
activity_lists::AnnouncableActivities,
collections::CommunityContext,
generate_outbox_url,
objects::{person::ApubPerson, post::ApubPost},
objects::post::ApubPost,
protocol::{
activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType},
activities::community::announce::AnnounceActivity,
collections::group_outbox::GroupOutbox,
},
};
@ -15,10 +16,7 @@ use lemmy_apub_lib::{
traits::{ActivityHandler, ApubObject},
verify::verify_domains_match,
};
use lemmy_db_schema::{
source::{person::Person, post::Post},
traits::Crud,
};
use lemmy_db_schema::source::post::Post;
use lemmy_utils::LemmyError;
use url::Url;
@ -63,13 +61,10 @@ impl ApubObject for ApubCommunityOutbox {
async fn into_apub(self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
let mut ordered_items = vec![];
for post in self.0 {
let actor = post.creator_id;
let actor: ApubPerson = blocking(data.1.pool(), move |conn| Person::read(conn, actor))
.await??
.into();
let a =
CreateOrUpdatePost::new(post, &actor, &data.0, CreateOrUpdateType::Create, &data.1).await?;
ordered_items.push(a);
let page = post.into_apub(&data.1).await?;
let announcable = AnnouncableActivities::Page(page);
let announce = AnnounceActivity::new(announcable, &data.0, &data.1)?;
ordered_items.push(announce);
}
Ok(GroupOutbox {
@ -108,11 +103,12 @@ impl ApubObject for ApubCommunityOutbox {
// We intentionally ignore errors here. This is because the outbox might contain posts from old
// Lemmy versions, or from other software which we cant parse. In that case, we simply skip the
// item and only parse the ones that work.
let data = Data::new(data.1.clone());
for activity in outbox_activities {
activity
.receive(&Data::new(data.1.clone()), request_counter)
.await
.ok();
let verify = activity.verify(&data, request_counter).await;
if verify.is_ok() {
activity.receive(&data, request_counter).await.ok();
}
}
// This return value is unused, so just set an empty vec

View File

@ -1,4 +1,4 @@
use crate::protocol::activities::create_or_update::post::CreateOrUpdatePost;
use crate::protocol::activities::community::announce::AnnounceActivity;
use activitystreams::collection::kind::OrderedCollectionType;
use serde::{Deserialize, Serialize};
use url::Url;
@ -9,5 +9,5 @@ pub struct GroupOutbox {
pub(crate) r#type: OrderedCollectionType,
pub(crate) id: Url,
pub(crate) total_items: i32,
pub(crate) ordered_items: Vec<CreateOrUpdatePost>,
pub(crate) ordered_items: Vec<AnnounceActivity>,
}

View File

@ -8,7 +8,7 @@ use chrono::{DateTime, FixedOffset};
use lemmy_apub_lib::{
data::Data,
object_id::ObjectId,
traits::ActivityHandler,
traits::{ActivityHandler, ApubObject},
values::MediaTypeHtml,
};
use lemmy_utils::LemmyError;
@ -79,14 +79,23 @@ impl Page {
}
}
// For Pleroma/Mastodon compat. Unimplemented because its only used for sending.
// Used for community outbox, so that it can be compatible with Pleroma/Mastodon.
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Page {
type DataType = LemmyContext;
async fn verify(&self, _: &Data<Self::DataType>, _: &mut i32) -> Result<(), LemmyError> {
Err(anyhow!("Announce/Page can only be sent, not received").into())
async fn verify(
&self,
data: &Data<Self::DataType>,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
ApubPost::verify(self, self.id.inner(), data, request_counter).await
}
async fn receive(self, _: &Data<Self::DataType>, _: &mut i32) -> Result<(), LemmyError> {
unimplemented!()
async fn receive(
self,
data: &Data<Self::DataType>,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
ApubPost::from_apub(self, data, request_counter).await?;
Ok(())
}
}