aboutsummaryrefslogtreecommitdiffhomepage
path: root/Digitigrade
diff options
context:
space:
mode:
authorwinter2025-05-04 21:04:18 +0100
committerwinter2025-05-04 21:04:18 +0100
commitd86f36e4becbe40766598816f837042aad4ce145 (patch)
treed56c1e90c8637e0bf2f8ca346493e91ed3d5ed06 /Digitigrade
parent8b4bac25d588720f88d178cfd71fc8a8361e2ff5 (diff)
allow following actors with no follow endpoint
Diffstat (limited to 'Digitigrade')
-rw-r--r--Digitigrade/Job/PeriodicFetchRemoteFeed.php37
-rw-r--r--Digitigrade/Job/ProcessIncomingPush.php14
-rw-r--r--Digitigrade/Model/Actor.php17
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]);
}