From a6117a2407e8b021db916df627acba57e7af27df Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Mon, 31 Aug 2026 09:41:12 -0600 Subject: [PATCH] Fix reblog handling --- .../HomeFeedPipeline/FeedInsertPipeline.php | 2 +- app/Jobs/SharePipeline/SharePipeline.php | 71 +++++++++++++++---- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/app/Jobs/HomeFeedPipeline/FeedInsertPipeline.php b/app/Jobs/HomeFeedPipeline/FeedInsertPipeline.php index 62724d021..420c91597 100644 --- a/app/Jobs/HomeFeedPipeline/FeedInsertPipeline.php +++ b/app/Jobs/HomeFeedPipeline/FeedInsertPipeline.php @@ -95,7 +95,7 @@ class FeedInsertPipeline implements ShouldBeUniqueUntilProcessing, ShouldQueue return; } - if (! in_array($status['pf_type'], ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album'])) { + if (! in_array($status['pf_type'], ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album', 'share'])) { Log::info("FeedInsertPipeline: Status {$sid} type {$status['pf_type']} not supported, skipping job"); return; diff --git a/app/Jobs/SharePipeline/SharePipeline.php b/app/Jobs/SharePipeline/SharePipeline.php index 3665ac23c..933710477 100644 --- a/app/Jobs/SharePipeline/SharePipeline.php +++ b/app/Jobs/SharePipeline/SharePipeline.php @@ -15,6 +15,7 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Cache; class SharePipeline implements ShouldQueue { @@ -29,6 +30,10 @@ class SharePipeline implements ShouldQueue */ public $deleteWhenMissingModels = true; + public $timeout = 60; + + public $tries = 3; + /** * Create a new job instance. * @@ -47,53 +52,91 @@ class SharePipeline implements ShouldQueue public function handle() { $status = $this->status; - $parent = Status::find($this->status->reblog_of_id); + + if (! $status->reblog_of_id) { + return; + } + + $parent = Status::find($status->reblog_of_id); + if (! $parent) { return; } + $actor = $status->profile; $target = $parent->profile; - if ($status->uri !== null) { - // Ignore notifications to remote statuses + if (! $actor || ! $target) { return; } - if ($target->id === $status->profile_id) { - $this->remoteAnnounceDeliver(); + $isRemoteShare = $status->uri !== null; - return true; - } + $isSelfShare = (int) $target->id === (int) $actor->id; + + $targetIsLocal = $target->domain === null; ReblogService::addPostReblog($parent->profile_id, $status->id); - $parent->reblogs_count = $parent->reblogs_count + 1; - $parent->save(); - StatusService::del($parent->id); + if (Cache::add($this->counterGuardKey($status->id), 1, now()->addDays(30))) { + Status::whereId($parent->id)->increment('reblogs_count'); + StatusService::del($parent->id); + } - NotificationService::firstOrCreateNotification($target->id, $actor->id, 'share', $status->reblog_of_id ?? $status->id, Status::class); + if ($targetIsLocal && ! $isSelfShare) { + NotificationService::firstOrCreateNotification( + $target->id, + $actor->id, + 'share', + $status->reblog_of_id, + Status::class + ); + } FeedInsertPipeline::dispatch($status->id, $status->profile_id)->onQueue('feed'); + if ($isRemoteShare) { + return; + } + return $this->remoteAnnounceDeliver(); } + protected function counterGuardKey($statusId) + { + return 'pf:share-pipeline:counted:'.$statusId; + } + public function remoteAnnounceDeliver() { if (config('app.env') !== 'production' || (bool) config_cache('federation.activitypub.enabled') == false) { return true; } + $status = $this->status; + + if ($status->uri !== null) { + return; + } + $profile = $status->profile; - $activity = FractalService::item($status, new Announce); + if (! $profile || $profile->domain !== null) { + return; + } + + if ($status->scope !== 'public') { + return; + } - $audience = $status->profile->getAudienceInbox(); + $audience = $profile->getAudienceInbox(); - if (empty($audience) || $status->scope != 'public') { + if (empty($audience)) { return; } + $activity = FractalService::item($status, new Announce); + ActivityPubDeliveryService::pool($profile, $audience, $activity); } }