From da65f0bea71ac8892a403a711ba63b36232ff3c9 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 21 Dec 2023 00:33:42 +0000 Subject: [PATCH 1/3] 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; From 1b13c76d2ef7119b6f05fb79711796941add74b8 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 21 Dec 2023 05:01:24 +0000 Subject: [PATCH 2/3] Simplyfied code --- src/Protocol/ActivityPub/Processor.php | 58 ++++++++++++-------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 2a70e40289..efd1e00ced 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -1324,23 +1324,21 @@ class Processor public static function storeReceivers(int $uriid, array $receivers) { foreach (['as:to' => Tag::TO, 'as:cc' => Tag::CC, 'as:bto' => Tag::BTO, 'as:bcc' => Tag::BCC, 'as:audience' => Tag::AUDIENCE, 'as:attributedTo' => Tag::ATTRIBUTED] as $element => $type) { - if (!empty($receivers[$element])) { - foreach ($receivers[$element] as $receiver) { - if ($receiver == ActivityPub::PUBLIC_COLLECTION) { - $name = Receiver::PUBLIC_COLLECTION; - } elseif ($path = parse_url($receiver, PHP_URL_PATH)) { - $name = trim($path, '/'); - } elseif ($host = parse_url($receiver, PHP_URL_HOST)) { - $name = $host; - } else { - Logger::warning('Unable to coerce name from receiver', ['element' => $element, 'type' => $type, 'receiver' => $receiver]); - $name = ''; - } - - $target = Tag::getTargetType($receiver); - Logger::debug('Got target type', ['type' => $target, 'url' => $receiver]); - Tag::store($uriid, $type, $name, $receiver, $target); + foreach ($receivers[$element] ?? [] as $receiver) { + if ($receiver == ActivityPub::PUBLIC_COLLECTION) { + $name = Receiver::PUBLIC_COLLECTION; + } elseif ($path = parse_url($receiver, PHP_URL_PATH)) { + $name = trim($path, '/'); + } elseif ($host = parse_url($receiver, PHP_URL_HOST)) { + $name = $host; + } else { + Logger::warning('Unable to coerce name from receiver', ['element' => $element, 'type' => $type, 'receiver' => $receiver]); + $name = ''; } + + $target = Tag::getTargetType($receiver); + Logger::debug('Got target type', ['type' => $target, 'url' => $receiver]); + Tag::store($uriid, $type, $name, $receiver, $target); } } } @@ -1348,22 +1346,20 @@ 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); + 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); } } } From b4a380e9de570c6692bec151cf562cac8d41a440 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 21 Dec 2023 10:26:34 +0000 Subject: [PATCH 3/3] Handle "commentsEnabled" --- src/Protocol/ActivityPub/Processor.php | 19 +++++++++++++++++-- src/Protocol/ActivityPub/Receiver.php | 5 +++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index efd1e00ced..3c0d57caa5 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -918,7 +918,15 @@ class Processor self::storeReceivers($item['uri-id'], $activity['receiver_urls'] ?? []); - self::storeCapabilities($item['uri-id'], $activity['capabilities'] ?? []); + if (!empty($activity['capabilities'])) { + $restrictions = self::storeCapabilities($item['uri-id'], $activity['capabilities']); + } elseif (!is_null($activity['can-comment']) && !$activity['can-comment']) { + $restrictions = [Tag::CAN_REPLY]; + } else { + $restrictions = []; + } + + // @todo Store restrictions $item['location'] = $activity['location']; @@ -1343,9 +1351,11 @@ class Processor } } - private static function storeCapabilities(int $uriid, array $capabilities) + private static function storeCapabilities(int $uriid, array $capabilities): array { + $restrictions = []; foreach (['pixelfed:canAnnounce' => Tag::CAN_ANNOUNCE, 'pixelfed:canLike' => Tag::CAN_LIKE, 'pixelfed:canReply' => Tag::CAN_REPLY] as $element => $type) { + $restricted = true; foreach ($capabilities[$element] ?? [] as $capability) { if ($capability == ActivityPub::PUBLIC_COLLECTION) { $name = Receiver::PUBLIC_COLLECTION; @@ -1359,9 +1369,14 @@ class Processor Logger::warning('Unable to coerce name from capability', ['element' => $element, 'type' => $type, 'capability' => $capability]); $name = ''; } + $restricted = false; Tag::store($uriid, $type, $name, $capability); } + if ($restricted) { + $restrictions[] = $type; + } } + return $restrictions; } /** diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 7e8ba6fe01..94233c8a89 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -2074,6 +2074,11 @@ class Receiver $object_data['attachments'] = array_merge($object_data['attachments'], self::processAttachmentUrls($object['as:url'] ?? [])); } + $object_data['can-comment'] = JsonLD::fetchElement($object, 'pt:commentsEnabled', '@value'); + if (is_null($object_data['can-comment'])) { + $object_data['can-comment'] = JsonLD::fetchElement($object, 'pixelfed:commentsEnabled', '@value'); + } + // Support for quoted posts (Pleroma, Fedibird and Misskey) $object_data['quote-url'] = JsonLD::fetchElement($object, 'as:quoteUrl', '@value'); if (empty($object_data['quote-url'])) {