diff options
Diffstat (limited to 'Digitigrade')
| -rw-r--r-- | Digitigrade/Job/PeriodicFetchRemoteFeed.php | 37 | ||||
| -rw-r--r-- | Digitigrade/Job/ProcessIncomingPush.php | 14 | ||||
| -rw-r--r-- | Digitigrade/Model/Actor.php | 17 |
3 files changed, 64 insertions, 4 deletions
diff --git a/Digitigrade/Job/PeriodicFetchRemoteFeed.php b/Digitigrade/Job/PeriodicFetchRemoteFeed.php new file mode 100644 index 0000000..e84757f --- /dev/null +++ b/Digitigrade/Job/PeriodicFetchRemoteFeed.php @@ -0,0 +1,37 @@ +<?php +namespace Digitigrade\Job; + +use Digitigrade\GlobalSettings; +use Digitigrade\Job; +use Digitigrade\JobQueue; +use Digitigrade\Logger; +use Digitigrade\Model\Actor; + +class PeriodicFetchRemoteFeed extends Job { + public int $actorId; + + public function __construct(Actor $targetActor) { + $this->actorId = $targetActor->id; + $this->remainingTries = 8; + } + + public function run() { + $actor = Actor::find($this->actorId); + $logger = Logger::getInstance(); + // only bother if someone local still follows the actor + if (count(array_filter($actor->findFollowers(), fn(Actor $a) => $a->isLocal)) > 0) { + $logger->info('Fetching feed for simple remote actor ' . $actor->getFullHandle()); + $actor->backfill(GlobalSettings::getInstance()->get('instance.feedUpdateLimit') ?? 50); + $this->submit(); + } else { + $logger->info('No longer fetching feed for ' . $actor->getFullHandle() . ' as nobody follows them anymore'); + } + } + + public function submit() { + JobQueue::getInstance()->submitDelayedUntil( + $this, + (new \DateTimeImmutable)->add(new \DateInterval(GlobalSettings::getInstance()->get('instance.feedUpdateInterval') ?? 'PT1H')) + ); + } +}
\ No newline at end of file diff --git a/Digitigrade/Job/ProcessIncomingPush.php b/Digitigrade/Job/ProcessIncomingPush.php index 600972c..16dd1ce 100644 --- a/Digitigrade/Job/ProcessIncomingPush.php +++ b/Digitigrade/Job/ProcessIncomingPush.php @@ -34,15 +34,21 @@ class ProcessIncomingPush extends Job { break; case 'note': $log->info('importing note with uri ' . $this->object->self); + $alreadyExisted = Note::countWhere('uri = ?', [$this->object->self]) > 0; $note = Note::importFromReceivedObject($this->object); - $note?->processTimelineAdditions(); - $note?->processNotifications(); + if (!$alreadyExisted) { + $note?->processTimelineAdditions(); + $note?->processNotifications(); + } break; case 'interaction': $log->info('importing interaction with uri ' . $this->object->self); + $alreadyExisted = Interaction::countWhere('uri = ?', [$this->object->self]) > 0; $interaction = Interaction::importFromReceivedObject($this->object); - $interaction?->processTimelineAdditions(); - $interaction?->processNotifications(); + if (!$alreadyExisted) { + $interaction?->processTimelineAdditions(); + $interaction?->processNotifications(); + } break; case 'extension': throw new \RuntimeException('object type ' . $this->object->type . ' not yet implemented :('); diff --git a/Digitigrade/Model/Actor.php b/Digitigrade/Model/Actor.php index ffaf4e8..3fb7e4e 100644 --- a/Digitigrade/Model/Actor.php +++ b/Digitigrade/Model/Actor.php @@ -2,6 +2,7 @@ namespace Digitigrade\Model; use Digitigrade\Db; +use Digitigrade\Job\PeriodicFetchRemoteFeed; use Digitigrade\Job\ProcessIncomingPush; use Digitigrade\Job\ProcessIncomingSimplePush; use Digitigrade\Notification\PendingFollowActionedNotif; @@ -254,10 +255,26 @@ class Actor extends PushableModel implements RpcReceiver { * @return FollowRelationStatus PENDING if a request was sent or ACTIVE if the follow went through immediately */ public function follow(self $target): FollowRelationStatus { + // handle actors with no follow endpoint + if (!$target->isLocal && !isset($target->endpoints->follow, $target->endpoints->unfollow)) { + // if this is the first time someone local followed this actor, put a job in to update them + if (count(array_filter($target->findFollowers(), fn(Actor $a) => $a->isLocal)) == 0) { + (new PeriodicFetchRemoteFeed($target))->submit(); + } + FollowRelation::create($this, $target, FollowRelationStatus::ACTIVE); + // no need to processNotifications because it's always going to be a remote user & not pending + return FollowRelationStatus::ACTIVE; + } + return $target->rpcCall('follow', [$this]); } public function unfollow(self $target) { + // handle actors with no follow endpoint + if (!$target->isLocal && !isset($target->endpoints->follow, $target->endpoints->unfollow)) { + FollowRelation::findByActors($this, $target)?->remove(); + return; + } $target->rpcCall('unfollow', [$this]); } |
