// }
// }
- Logger::info('Processing ' . $object_data['type'] . ' ' . $object_data['object_type'] . ' ' . $object_data['id']);
+ $account = Contact::selectFirstAccount(['platform'], ['nurl' => Strings::normaliseLink($actor)]);
+ $platform = $account['platform'] ?? '';
+
+ Logger::info('Processing', ['type' => $object_data['type'], 'object_type' => $object_data['object_type'], 'id' => $object_data['id'], 'actor' => $actor, 'platform' => $platform]);
return $object_data;
}
case 'as:Accept':
if ($object_data['object_type'] == 'as:Follow') {
- ActivityPub\Processor::acceptFollowUser($object_data);
+ if (!empty($object_data['object_actor'])) {
+ ActivityPub\Processor::acceptFollowUser($object_data);
+ } else {
+ Logger::notice('Unhandled "accept follow" message.', ['object_data' => $object_data]);
+ }
} elseif (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
ActivityPub\Processor::createActivity($object_data, Activity::ATTEND);
} else {
} elseif (($object_data['object_type'] == 'as:Block') &&
in_array($object_data['object_object_type'], self::ACCOUNT_TYPES)) {
ActivityPub\Processor::unblockAccount($object_data);
- } elseif (in_array($object_data['object_type'], array_merge(self::ACTIVITY_TYPES, ['as:Announce'])) &&
- in_array($object_data['object_object_type'], array_merge(['as:Tombstone'], self::CONTENT_TYPES))) {
- ActivityPub\Processor::undoActivity($object_data);
} elseif (in_array($object_data['object_type'], array_merge(self::ACTIVITY_TYPES, ['as:Announce', 'as:Create', ''])) &&
empty($object_data['object_object_type'])) {
// We cannot detect the target object. So we can ignore it.
Queue::remove($object_data);
+ } elseif (in_array($object_data['object_type'], array_merge(self::ACTIVITY_TYPES, ['as:Announce'])) &&
+ in_array($object_data['object_object_type'], array_merge(['as:Tombstone'], self::CONTENT_TYPES))) {
+ ActivityPub\Processor::undoActivity($object_data);
} elseif (in_array($object_data['object_type'], ['as:Create']) &&
in_array($object_data['object_object_type'], ['pt:CacheFile'])) {
// Unhandled Peertube activity
self::switchContacts($receivers, $actor);
+ // "birdsitelive" is a service that mirrors tweets into the fediverse
+ // These posts can be fetched without authentification, but are not marked as public
+ // We treat them as unlisted posts to be able to handle them.
+ if (empty($receivers) && $fetch_unlisted && Contact::isPlatform($actor, 'birdsitelive')) {
+ $receivers[0] = ['uid' => 0, 'type' => self::TARGET_GLOBAL];
+ $receivers[-1] = ['uid' => -1, 'type' => self::TARGET_GLOBAL];
+ Logger::notice('Post from "birdsitelive" is set to "unlisted"', ['id' => JsonLD::fetchElement($activity, '@id')]);
+ } elseif (empty($receivers)) {
+ Logger::notice('Post has got no receivers', ['fetch_unlisted' => $fetch_unlisted, 'actor' => $actor, 'id' => JsonLD::fetchElement($activity, '@id'), 'type' => JsonLD::fetchElement($activity, '@type')]);
+ }
+
return $receivers;
}
$object_data['diaspora:comment'] = JsonLD::fetchElement($object, 'diaspora:comment', '@value');
$object_data['diaspora:like'] = JsonLD::fetchElement($object, 'diaspora:like', '@value');
$object_data['actor'] = $object_data['author'] = $actor;
- $object_data['context'] = JsonLD::fetchElement($object, 'as:context', '@id');
- $object_data['conversation'] = JsonLD::fetchElement($object, 'ostatus:conversation', '@id');
+ $element = JsonLD::fetchElement($object, 'as:context', '@id');
+ $object_data['context'] = $element != './' ? $element : null;
+ $element = JsonLD::fetchElement($object, 'ostatus:conversation', '@id');
+ $object_data['conversation'] = $element != './' ? $element : null;
$object_data['sensitive'] = JsonLD::fetchElement($object, 'as:sensitive');
$object_data['name'] = JsonLD::fetchElement($object, 'as:name', '@value');
$object_data['summary'] = JsonLD::fetchElement($object, 'as:summary', '@value');
$object_data['attachments'] = array_merge($object_data['attachments'], self::processAttachmentUrls($object['as:url'] ?? []));
}
+ // Support for quoted posts (Pleroma, Fedibird and Misskey)
+ $object_data['quote-url'] = JsonLD::fetchElement($object, 'as:quoteUrl', '@value');
+ if (empty($object_data['quote-url'])) {
+ $object_data['quote-url'] = JsonLD::fetchElement($object, 'fedibird:quoteUri', '@value');
+ }
+ if (empty($object_data['quote-url'])) {
+ $object_data['quote-url'] = JsonLD::fetchElement($object, 'misskey:_misskey_quote', '@value');
+ }
+
+ // Misskey adds some data to the standard "content" value for quoted posts for backwards compatibility.
+ // Their own "_misskey_content" value does then contain the content without this extra data.
+ if (!empty($object_data['quote-url'])) {
+ $misskey_content = JsonLD::fetchElement($object, 'misskey:_misskey_content', '@value');
+ if (!empty($misskey_content)) {
+ $object_data['content'] = $misskey_content;
+ }
+ }
+
// For page types we expect that the alternate url posts to some page.
// So we add this to the attachments if it differs from the id.
// Currently only Lemmy is using the page type.