aboutsummaryrefslogtreecommitdiffhomepage
path: root/Digitigrade
diff options
context:
space:
mode:
Diffstat (limited to 'Digitigrade')
-rw-r--r--Digitigrade/Model/Actor.php44
-rw-r--r--Digitigrade/Notification/AdminEditedNoteNotif.php9
-rw-r--r--Digitigrade/Notification/PokeNotif.php62
-rw-r--r--Digitigrade/PokeVerb.php14
4 files changed, 123 insertions, 6 deletions
diff --git a/Digitigrade/Model/Actor.php b/Digitigrade/Model/Actor.php
index 0541e1b..18aba15 100644
--- a/Digitigrade/Model/Actor.php
+++ b/Digitigrade/Model/Actor.php
@@ -3,12 +3,16 @@ namespace Digitigrade\Model;
use Digitigrade\Db;
use Digitigrade\Notification\PendingFollowActionedNotif;
+use Digitigrade\Notification\PokeNotif;
use Digitigrade\Notification\UnblockNotif;
use Digitigrade\Notification\UnfollowNotif;
+use Digitigrade\PokeVerb;
use Digitigrade\RpcException;
use Digitigrade\RpcReceiver;
class Actor extends PushableModel implements RpcReceiver {
+ public const EXTENSION_POKE = 'https://pawpub.entities.org.uk/extension/poke';
+
public ?int $id;
public string $uri;
public bool $isLocal = false;
@@ -135,15 +139,15 @@ class Actor extends PushableModel implements RpcReceiver {
return self::findByUri($uri);
}
- public function rpcCall(string $method, array $args) {
- // $args = [Actor $actingAs]
+ public function rpcCall(string $method, array $args, string $customEndpoint = null) {
+ // $args = [Actor $actingAs, ?string $requestBody]
if (!$this->isLocal) {
// trigger the same action on the remote server
- $endpoint = $this->endpoints->{$method} ?? null;
+ $endpoint = $customEndpoint ?? $this->endpoints->{$method} ?? null;
if (!isset($endpoint)) {
throw new RpcException("Actor `$this->uri` has no $method endpoint");
}
- $result = send_request_authenticated($endpoint, method: 'POST', actingAs: $args[0]);
+ $result = send_request_authenticated($endpoint, method: 'POST', actingAs: $args[0], body: $args[1] ?? null);
if (!str_contains($result->headers[0], ' 20')) {
throw new RpcException('remote call did not indicate success: ' . $result->headers[0]);
}
@@ -188,6 +192,16 @@ class Actor extends PushableModel implements RpcReceiver {
(new UnblockNotif($args[0], $this))->processNotifications();
return;
+ case 'poke':
+ $obj = json_decode($args[1] ?? '');
+ (new PokeNotif(
+ $args[0],
+ PokeVerb::tryFrom($obj?->verb ?? '') ?? PokeVerb::POKE,
+ $this,
+ $obj?->urgent ?? false
+ ))->processNotifications();
+ return;
+
default:
throw new \RuntimeException("behaviour for actor rpc method $method not (yet?) implemented");
}
@@ -329,6 +343,25 @@ class Actor extends PushableModel implements RpcReceiver {
return '/@/' . $this->getFullHandle();
}
+ private function getPokeEndpoint(): ?string {
+ return $this->extensions[self::EXTENSION_POKE] ?? null;
+ }
+
+ public function poke(self $target, PokeVerb $verb = PokeVerb::POKE, bool $urgent = false) {
+ $target->rpcCall('poke', [$this, json_encode([
+ 'verb' => $verb->value,
+ 'urgent' => $urgent
+ ])], $target->getPokeEndpoint());
+ }
+
+ public function isPokeable(): bool {
+ return isset($this->extensions[self::EXTENSION_POKE]);
+ }
+
+ public function setPokeable(bool $pokeable) {
+ $this->extensions[self::EXTENSION_POKE] = $pokeable ? path_to_uri("/actor/$this->id/poke") : null;
+ }
+
public function jsonSerialize(): array {
if ($this->deleted) {
return [
@@ -359,7 +392,8 @@ class Actor extends PushableModel implements RpcReceiver {
'rejectedFollow' => path_to_uri("/actor/$this->id/rejectedFollow"),
'block' => path_to_uri("/actor/$this->id/block"),
'unblock' => path_to_uri("/actor/$this->id/unblock"),
- ]
+ ],
+ 'extensions' => $this->extensions
];
}
}
diff --git a/Digitigrade/Notification/AdminEditedNoteNotif.php b/Digitigrade/Notification/AdminEditedNoteNotif.php
index f3c18a1..888130b 100644
--- a/Digitigrade/Notification/AdminEditedNoteNotif.php
+++ b/Digitigrade/Notification/AdminEditedNoteNotif.php
@@ -2,6 +2,7 @@
namespace Digitigrade\Notification;
use Digitigrade\Model\Note;
+use Digitigrade\Model\Notification;
use Digitigrade\Model\UserAccount;
class AdminEditedNoteNotif implements Notifyable {
@@ -22,7 +23,7 @@ class AdminEditedNoteNotif implements Notifyable {
}
public function getNotificationTitle(): string {
- return __f('notification.adminEditedNote', $this->admin->actor->displayName);
+ return __f('notifications.adminEditedNote', $this->admin->actor->displayName);
}
public function getNotificationTitleLink(): ?string {
@@ -40,4 +41,10 @@ class AdminEditedNoteNotif implements Notifyable {
public function getNotificationImageLink(): ?string {
return $this->admin->actor->getLocalUiHref();
}
+
+ public function processNotifications() {
+ if (!$this->note->author->isLocal)
+ return;
+ Notification::fromNotifyable($this, UserAccount::findByLinkedActor($this->note->author))->send();
+ }
} \ No newline at end of file
diff --git a/Digitigrade/Notification/PokeNotif.php b/Digitigrade/Notification/PokeNotif.php
new file mode 100644
index 0000000..5446098
--- /dev/null
+++ b/Digitigrade/Notification/PokeNotif.php
@@ -0,0 +1,62 @@
+<?php
+namespace Digitigrade\Notification;
+
+use Digitigrade\Model\Actor;
+use Digitigrade\Model\Notification;
+use Digitigrade\Model\UserAccount;
+use Digitigrade\PokeVerb;
+
+class PokeNotif implements Notifyable {
+ private Actor $subject;
+ private PokeVerb $verb;
+ private Actor $object;
+ private bool $urgent;
+
+ public function __construct(Actor $subject, PokeVerb $verb, Actor $object, bool $urgent) {
+ $this->subject = $subject;
+ $this->verb = $verb;
+ $this->object = $object;
+ $this->urgent = $urgent;
+ }
+
+ public function toJsonReference(): mixed {
+ return [$this->subject->id, $this->verb->value, $this->object->id, $this->urgent];
+ }
+
+ public static function fromJsonReference(mixed $reference): ?self {
+ return new self(
+ Actor::find($reference[0]),
+ PokeVerb::from($reference[1]),
+ Actor::find($reference[2]),
+ $reference[3]
+ );
+ }
+
+ public function getNotificationTitle(): string {
+ $kind = $this->urgent ? 'urgent' : 'normal';
+ $verb = $this->verb->value;
+ return __f("notifications.poke.$kind", $this->subject->displayName, __("notifications.poke.verb.$verb"));
+ }
+
+ public function getNotificationTitleLink(): ?string {
+ return $this->subject->getLocalUiHref();
+ }
+
+ public function getNotificationBody(): ?string {
+ return null;
+ }
+
+ public function getNotificationImageUrl(): ?string {
+ return $this->subject->avatar ?? '/static/default-avatar.png';
+ }
+
+ public function getNotificationImageLink(): ?string {
+ return $this->subject->getLocalUiHref();
+ }
+
+ public function processNotifications() {
+ if (!$this->object->isLocal)
+ return;
+ Notification::fromNotifyable($this, UserAccount::findByLinkedActor($this->object))->send();
+ }
+} \ No newline at end of file
diff --git a/Digitigrade/PokeVerb.php b/Digitigrade/PokeVerb.php
new file mode 100644
index 0000000..6490b78
--- /dev/null
+++ b/Digitigrade/PokeVerb.php
@@ -0,0 +1,14 @@
+<?php
+namespace Digitigrade;
+
+enum PokeVerb: string {
+ case POKE = 'poke';
+ case BITE = 'bite';
+ case PUNCH = 'punch';
+ case KICK = 'kick';
+ case WAVE = 'wave';
+ case YELL = 'yell';
+ case HUG = 'hug';
+ case KISS = 'kiss';
+ case PET = 'pet';
+} \ No newline at end of file