From d360e506db334e92bff730d50072d27be8d515e6 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Fri, 15 May 2026 05:28:52 +0200 Subject: [PATCH] feat(ap): handle Undo(Like) inbound activity --- crates/adapters/activitypub-base/src/activities.rs | 14 ++++++++++++++ crates/adapters/activitypub-base/src/content.rs | 3 +++ crates/adapters/activitypub/src/handler.rs | 4 ++++ 3 files changed, 21 insertions(+) diff --git a/crates/adapters/activitypub-base/src/activities.rs b/crates/adapters/activitypub-base/src/activities.rs index 83bb7df..1b2f41c 100644 --- a/crates/adapters/activitypub-base/src/activities.rs +++ b/crates/adapters/activitypub-base/src/activities.rs @@ -279,6 +279,20 @@ impl Activity for UndoActivity { tracing::info!(ap_id = %ap_id_str, "undo Add (watchlist remove)"); } } + "Like" => { + if let Some(obj_url_str) = self.object.get("object").and_then(|o| o.as_str()) + && let Ok(obj_url) = Url::parse(obj_url_str) + && obj_url.host_str().unwrap_or("") == data.domain + { + data.object_handler + .on_unlike(&obj_url, self.actor.inner()) + .await + .unwrap_or_else(|e| { + tracing::warn!(error = %e, "failed to process unlike"); + }); + } + tracing::info!(actor = %self.actor.inner(), "received Undo(Like)"); + } other => { tracing::debug!(kind = %other, "ignoring Undo of unknown activity type"); } diff --git a/crates/adapters/activitypub-base/src/content.rs b/crates/adapters/activitypub-base/src/content.rs index 71eabc2..9d2bde7 100644 --- a/crates/adapters/activitypub-base/src/content.rs +++ b/crates/adapters/activitypub-base/src/content.rs @@ -52,6 +52,9 @@ pub trait ApObjectHandler: Send + Sync { /// `actor_url` is the AP URL of the remote actor who sent the Announce. async fn on_announce_received(&self, object_url: &Url, actor_url: &Url) -> anyhow::Result<()>; + /// Called when a remote actor removes a Like from a local thought. + async fn on_unlike(&self, object_url: &Url, actor_url: &Url) -> anyhow::Result<()>; + /// Total number of locally-authored posts across all users. async fn count_local_posts(&self) -> anyhow::Result; } diff --git a/crates/adapters/activitypub/src/handler.rs b/crates/adapters/activitypub/src/handler.rs index 7c24659..1f93248 100644 --- a/crates/adapters/activitypub/src/handler.rs +++ b/crates/adapters/activitypub/src/handler.rs @@ -221,6 +221,10 @@ impl ApObjectHandler for ThoughtsObjectHandler { Ok(()) } + async fn on_unlike(&self, _object_url: &url::Url, _actor_url: &url::Url) -> anyhow::Result<()> { + Ok(()) + } + async fn on_announce_received(&self, object_url: &Url, actor_url: &Url) -> Result<()> { let thought_uuid = object_url .path()