diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 6797330442..6cd0111ec0 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -556,6 +556,9 @@ class Receiver switch ($type) { case 'as:Create': if (in_array($object_data['object_type'], self::CONTENT_TYPES)) { + if ($object_data['object_type'] == 'as:Question') { + self::storeUnhandledActivity(false, $type, $object_data, $activity, $body, $uid, $trust_source, $push, $signer); + } $item = ActivityPub\Processor::createItem($object_data); ActivityPub\Processor::postItem($object_data, $item); } elseif (in_array($object_data['object_type'], ['pt:CacheFile'])) { @@ -1436,6 +1439,59 @@ class Receiver return $attachlist; } + /** + * Convert questions from JSON-LD format into a simplified format + * + * @param array $object + * + * @return array Questions in a simplified format + */ + private static function processQuestion(array $object) + { + $question = []; + + if (!empty($object['as:oneOf'])) { + $question['multiple'] = false; + $options = JsonLD::fetchElementArray($object, 'as:oneOf') ?? []; + } elseif (!empty($object['as:anyOf'])) { + $question['multiple'] = true; + $options = JsonLD::fetchElementArray($object, 'as:anyOf') ?? []; + } else { + return []; + } + + // @todo Check if "closed" is a thing, see here: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-closed + $question['voters'] = (int)JsonLD::fetchElement($object, 'toot:votersCount', '@value'); + $question['options'] = []; + + $voters = 0; + + foreach ($options as $option) { + if (JsonLD::fetchElement($option, '@type') != 'as:Note') { + continue; + } + + $name = JsonLD::fetchElement($option, 'as:name', '@value'); + + if (empty($option['as:replies'])) { + continue; + } + + $replies = JsonLD::fetchElement($option['as:replies'], 'as:totalItems', '@value'); + + $question['options'][] = ['name' => $name, 'replies' => $replies]; + + $voters += (int)$replies; + } + + // For single choice question we can count the number of voters if not provided (like with Misskey) + if (empty($question['voters']) && !$question['multiple']) { + $question['voters'] = $voters; + } + + return $question; + } + /** * Fetch the original source or content with the "language" Markdown or HTML * @@ -1687,6 +1743,10 @@ class Receiver $object_data['alternate-url'] = null; } + if ($object_data['object_type'] == 'as:Question') { + $object_data['question'] = self::processQuestion($object); + } + $receiverdata = self::getReceivers($object, $object_data['actor'], $object_data['tags'], true); $receivers = $reception_types = []; foreach ($receiverdata as $key => $data) {