From da65f0bea71ac8892a403a711ba63b36232ff3c9 Mon Sep 17 00:00:00 2001
From: Michael <heluecht@pirati.ca>
Date: Thu, 21 Dec 2023 00:33:42 +0000
Subject: [PATCH] Store Pixelfed's capabilities

---
 src/Model/Tag.php                      |  4 ++++
 src/Protocol/ActivityPub/Processor.php | 25 +++++++++++++++++++++++++
 src/Protocol/ActivityPub/Receiver.php  | 16 ++++++++++++++++
 src/Util/JsonLD.php                    |  1 +
 4 files changed, 46 insertions(+)

diff --git a/src/Model/Tag.php b/src/Model/Tag.php
index 94ced6869d..cb891c706d 100644
--- a/src/Model/Tag.php
+++ b/src/Model/Tag.php
@@ -60,6 +60,10 @@ class Tag
 	const AUDIENCE   = 14;
 	const ATTRIBUTED = 15;
 
+	const CAN_ANNOUNCE = 20;
+	const CAN_LIKE     = 21;
+	const CAN_REPLY    = 22;
+
 	const ACCOUNT             = 1;
 	const GENERAL_COLLECTION  = 2;
 	const FOLLOWER_COLLECTION = 3;
diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php
index f42fa245d2..2a70e40289 100644
--- a/src/Protocol/ActivityPub/Processor.php
+++ b/src/Protocol/ActivityPub/Processor.php
@@ -918,6 +918,8 @@ class Processor
 
 		self::storeReceivers($item['uri-id'], $activity['receiver_urls'] ?? []);
 
+		self::storeCapabilities($item['uri-id'], $activity['capabilities'] ?? []);
+
 		$item['location'] = $activity['location'];
 
 		if (!empty($activity['latitude']) && !empty($activity['longitude'])) {
@@ -1343,6 +1345,29 @@ class Processor
 		}
 	}
 
+	private static function storeCapabilities(int $uriid, array $capabilities)
+	{
+		foreach (['pixelfed:canAnnounce' => Tag::CAN_ANNOUNCE, 'pixelfed:canLike' => Tag::CAN_LIKE, 'pixelfed:canReply' => Tag::CAN_REPLY] as $element => $type) {
+			if (!empty($capabilities[$element])) {
+				foreach ($capabilities[$element] as $capability) {
+					if ($capability == ActivityPub::PUBLIC_COLLECTION) {
+						$name = Receiver::PUBLIC_COLLECTION;
+					} elseif (empty($capability) || ($capability == '[]')) {
+						continue;
+					} elseif ($path = parse_url($capability, PHP_URL_PATH)) {
+						$name = trim($path, '/');
+					} elseif ($host = parse_url($capability, PHP_URL_HOST)) {
+						$name = $host;
+					} else {
+						Logger::warning('Unable to coerce name from capability', ['element' => $element, 'type' => $type, 'capability' => $capability]);
+						$name = '';
+					}
+					Tag::store($uriid, $type, $name, $capability);
+				}
+			}
+		}
+	}
+
 	/**
 	 * Creates an mail post
 	 *
diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php
index ff78f0db82..7e8ba6fe01 100644
--- a/src/Protocol/ActivityPub/Receiver.php
+++ b/src/Protocol/ActivityPub/Receiver.php
@@ -1943,6 +1943,10 @@ class Receiver
 		$object_data['receiver']       = $receivers;
 		$object_data['reception_type'] = $reception_types;
 
+		if (!empty($object['pixelfed:capabilities'])) {
+			$object_data['capabilities'] = self::getCapabilities($object);
+		}
+
 		$object_data['unlisted'] = in_array(-1, $object_data['receiver']);
 		unset($object_data['receiver'][-1]);
 		unset($object_data['reception_type'][-1]);
@@ -1950,6 +1954,18 @@ class Receiver
 		return $object_data;
 	}
 
+	private static function getCapabilities($object) {
+		$capabilities = [];
+		foreach (['pixelfed:canAnnounce', 'pixelfed:canLike', 'pixelfed:canReply'] as $element) {
+			$capabilities_list = JsonLD::fetchElementArray($object['pixelfed:capabilities'], $element, '@id');
+			if (empty($capabilities_list)) {
+				continue;
+			}
+			$capabilities[$element] = $capabilities_list;
+		}
+		return $capabilities;
+	}
+
 	/**
 	 * Create an object data array from a given activity
 	 *
diff --git a/src/Util/JsonLD.php b/src/Util/JsonLD.php
index aa83d938a4..5bf6593aed 100644
--- a/src/Util/JsonLD.php
+++ b/src/Util/JsonLD.php
@@ -171,6 +171,7 @@ class JsonLD
 			'mobilizon' => (object)['@id' => 'https://joinmobilizon.org/ns#', '@type' => '@id'],
 			'fedibird' => (object)['@id' => 'http://fedibird.com/ns#', '@type' => '@id'],
 			'misskey' => (object)['@id' => 'https://misskey-hub.net/ns#', '@type' => '@id'],
+			'pixelfed' => (object)['@id' => 'http://pixelfed.org/ns#', '@type' => '@id'],
 		];
 
 		$orig_json = $json;
-- 
2.39.5