diff --git a/crates/apub/assets/lemmy/collections/group_outbox.json b/crates/apub/assets/lemmy/collections/group_outbox.json index cf68742f..14789177 100644 --- a/crates/apub/assets/lemmy/collections/group_outbox.json +++ b/crates/apub/assets/lemmy/collections/group_outbox.json @@ -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: Cadillac’s luxury EV debut seems like a winner | Engadges", - "content": "

test

\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" } ] } \ No newline at end of file diff --git a/crates/apub/src/activities/community/announce.rs b/crates/apub/src/activities/community/announce.rs index 4eebcce3..a86317b5 100644 --- a/crates/apub/src/activities/community/announce.rs +++ b/crates/apub/src/activities/community/announce.rs @@ -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, 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 } } diff --git a/crates/apub/src/collections/community_outbox.rs b/crates/apub/src/collections/community_outbox.rs index 3632f61a..69dfd929 100644 --- a/crates/apub/src/collections/community_outbox.rs +++ b/crates/apub/src/collections/community_outbox.rs @@ -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 { 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 diff --git a/crates/apub/src/protocol/collections/group_outbox.rs b/crates/apub/src/protocol/collections/group_outbox.rs index 3b295003..f7c70792 100644 --- a/crates/apub/src/protocol/collections/group_outbox.rs +++ b/crates/apub/src/protocol/collections/group_outbox.rs @@ -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, + pub(crate) ordered_items: Vec, } diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs index dbf52eee..dd923618 100644 --- a/crates/apub/src/protocol/objects/page.rs +++ b/crates/apub/src/protocol/objects/page.rs @@ -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, _: &mut i32) -> Result<(), LemmyError> { - Err(anyhow!("Announce/Page can only be sent, not received").into()) + async fn verify( + &self, + data: &Data, + request_counter: &mut i32, + ) -> Result<(), LemmyError> { + ApubPost::verify(self, self.id.inner(), data, request_counter).await } - async fn receive(self, _: &Data, _: &mut i32) -> Result<(), LemmyError> { - unimplemented!() + async fn receive( + self, + data: &Data, + request_counter: &mut i32, + ) -> Result<(), LemmyError> { + ApubPost::from_apub(self, data, request_counter).await?; + Ok(()) } }