use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Core\System;
+use Friendica\Database\Database;
use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Model\APContact;
use Friendica\Model\User;
use Friendica\Protocol\Activity;
use Friendica\Protocol\ActivityPub;
+use Friendica\Util\DateTimeFormat;
use Friendica\Util\HTTPSignature;
use Friendica\Util\JsonLD;
use Friendica\Util\LDSignature;
$ldactivity = JsonLD::compact($activity);
$actor = JsonLD::fetchElement($ldactivity, 'as:actor', '@id') ?? '';
+
$apcontact = APContact::getByURL($actor);
if (empty($apcontact)) {
$trust_source = false;
}
- self::processActivity($ldactivity, $body, $uid, $trust_source, true, $signer);
+ $fetchQueue = new FetchQueue();
+ self::processActivity($fetchQueue, $ldactivity, $body, $uid, $trust_source, true, $signer, $http_signer);
+ $fetchQueue->process();
+ }
+
+ private static function enqueuePost(array $ldactivity = [], string $type, int $uid, string $http_signer): array
+ {
+ $fields = [
+ 'activity-id' => $ldactivity['id'],
+ 'object-id' => $ldactivity['object_id'],
+ 'type' => $type,
+ 'object-type' => $ldactivity['object_type'],
+ 'activity' => json_encode($ldactivity, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT),
+ 'received' => DateTimeFormat::utcNow(),
+ ];
+
+ if (!empty($ldactivity['object_object_type'])) {
+ $fields['object-object-type'] = $ldactivity['object_object_type'];
+ }
+
+ if (!empty($http_signer)) {
+ $fields['signer'] = $http_signer;
+ }
+
+ DBA::insert('inbox-entry', $fields, Database::INSERT_IGNORE);
+
+ $queue = DBA::selectFirst('inbox-entry', ['id'], ['activity-id' => $ldactivity['id']]);
+ if (!empty($queue['id'])) {
+ $ldactivity['entry-id'] = $queue['id'];
+ DBA::insert('inbox-entry-receiver', ['queue-id' => $queue['id'], 'uid' => $uid], Database::INSERT_IGNORE);
+ }
+ return $ldactivity;
+ }
+
+ public static function removeFromQueue(array $activity = [])
+ {
+ if (empty($activity['entry-id'])) {
+ return;
+ }
+ DBA::delete('inbox-entry', ['id' => $activity['entry-id']]);
}
/**
return;
}
- $id = Processor::fetchMissingActivity($object_id, [], $actor, self::COMPLETION_RELAY);
+ $fetchQueue = new FetchQueue();
+
+ $id = Processor::fetchMissingActivity($fetchQueue, $object_id, [], $actor, self::COMPLETION_RELAY);
if (empty($id)) {
Logger::notice('Relayed message had not been fetched', ['id' => $object_id]);
return;
}
+ $fetchQueue->process();
+
$item_id = Item::searchByLink($object_id);
if ($item_id) {
Logger::info('Relayed message had been fetched and stored', ['id' => $object_id, 'item' => $item_id]);
/**
* Processes the activity object
*
- * @param array $activity Array with activity data
- * @param string $body The unprocessed body
- * @param integer $uid User ID
- * @param boolean $trust_source Do we trust the source?
- * @param boolean $push Message had been pushed to our system
- * @param array $signer The signer of the post
- * @throws \Exception
+ * @param FetchQueue $fetchQueue
+ * @param array $activity Array with activity data
+ * @param string $body The unprocessed body
+ * @param int|null $uid User ID
+ * @param boolean $trust_source Do we trust the source?
+ * @param boolean $push Message had been pushed to our system
+ * @param array $signer The signer of the post
+ * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ * @throws \ImagickException
*/
- public static function processActivity(array $activity, string $body = '', int $uid = null, bool $trust_source = false, bool $push = false, array $signer = [])
+ public static function processActivity(FetchQueue $fetchQueue, array $activity, string $body = '', int $uid = null, bool $trust_source = false, bool $push = false, array $signer = [], string $http_signer = '')
{
$type = JsonLD::fetchElement($activity, '@type');
if (!$type) {
$object_data['from-relay'] = $activity['from-relay'];
}
+ $object_data = self::enqueuePost($object_data, $type, $uid, $http_signer);
+
if (in_array('as:Question', [$object_data['object_type'] ?? '', $object_data['object_object_type'] ?? ''])) {
self::storeUnhandledActivity(false, $type, $object_data, $activity, $body, $uid, $trust_source, $push, $signer);
}
switch ($type) {
case 'as:Create':
if (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
- $item = ActivityPub\Processor::createItem($object_data);
+ $item = ActivityPub\Processor::createItem($fetchQueue, $object_data);
ActivityPub\Processor::postItem($object_data, $item);
} elseif (in_array($object_data['object_type'], ['pt:CacheFile'])) {
// Unhandled Peertube activity
case 'as:Invite':
if (in_array($object_data['object_type'], ['as:Event'])) {
- $item = ActivityPub\Processor::createItem($object_data);
+ $item = ActivityPub\Processor::createItem($fetchQueue, $object_data);
ActivityPub\Processor::postItem($object_data, $item);
} else {
self::storeUnhandledActivity(true, $type, $object_data, $activity, $body, $uid, $trust_source, $push, $signer);
$object_data['thread-completion'] = Contact::getIdForURL($actor);
$object_data['completion-mode'] = self::COMPLETION_ANNOUCE;
- $item = ActivityPub\Processor::createItem($object_data);
+ $item = ActivityPub\Processor::createItem($fetchQueue, $object_data);
if (empty($item)) {
return;
}
$announce_object_data['raw'] = $body;
}
- ActivityPub\Processor::createActivity($announce_object_data, Activity::ANNOUNCE);
+ ActivityPub\Processor::createActivity($fetchQueue, $announce_object_data, Activity::ANNOUNCE);
} else {
self::storeUnhandledActivity(true, $type, $object_data, $activity, $body, $uid, $trust_source, $push, $signer);
}
case 'as:Like':
if (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
- ActivityPub\Processor::createActivity($object_data, Activity::LIKE);
+ ActivityPub\Processor::createActivity($fetchQueue, $object_data, Activity::LIKE);
} elseif ($object_data['object_type'] == '') {
// The object type couldn't be determined. We don't have it and we can't fetch it. We ignore this activity.
} else {
case 'as:Dislike':
if (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
- ActivityPub\Processor::createActivity($object_data, Activity::DISLIKE);
+ ActivityPub\Processor::createActivity($fetchQueue, $object_data, Activity::DISLIKE);
} elseif ($object_data['object_type'] == '') {
// The object type couldn't be determined. We don't have it and we can't fetch it. We ignore this activity.
} else {
case 'as:TentativeAccept':
if (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
- ActivityPub\Processor::createActivity($object_data, Activity::ATTENDMAYBE);
+ ActivityPub\Processor::createActivity($fetchQueue, $object_data, Activity::ATTENDMAYBE);
} else {
self::storeUnhandledActivity(true, $type, $object_data, $activity, $body, $uid, $trust_source, $push, $signer);
}
case 'as:Update':
if (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
- ActivityPub\Processor::updateItem($object_data);
+ ActivityPub\Processor::updateItem($fetchQueue, $object_data);
} elseif (in_array($object_data['object_type'], self::ACCOUNT_TYPES)) {
ActivityPub\Processor::updatePerson($object_data);
} elseif (in_array($object_data['object_type'], ['pt:CacheFile'])) {
ActivityPub\Processor::followUser($object_data);
} elseif (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
$object_data['reply-to-id'] = $object_data['object_id'];
- ActivityPub\Processor::createActivity($object_data, Activity::FOLLOW);
+ ActivityPub\Processor::createActivity($fetchQueue, $object_data, Activity::FOLLOW);
} else {
self::storeUnhandledActivity(true, $type, $object_data, $activity, $body, $uid, $trust_source, $push, $signer);
}
if ($object_data['object_type'] == 'as:Follow') {
ActivityPub\Processor::acceptFollowUser($object_data);
} elseif (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
- ActivityPub\Processor::createActivity($object_data, Activity::ATTEND);
+ ActivityPub\Processor::createActivity($fetchQueue, $object_data, Activity::ATTEND);
} else {
self::storeUnhandledActivity(true, $type, $object_data, $activity, $body, $uid, $trust_source, $push, $signer);
}
if ($object_data['object_type'] == 'as:Follow') {
ActivityPub\Processor::rejectFollowUser($object_data);
} elseif (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
- ActivityPub\Processor::createActivity($object_data, Activity::ATTENDNO);
+ ActivityPub\Processor::createActivity($fetchQueue, $object_data, Activity::ATTENDNO);
} else {
self::storeUnhandledActivity(true, $type, $object_data, $activity, $body, $uid, $trust_source, $push, $signer);
}
case 'as:View':
if (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
- ActivityPub\Processor::createActivity($object_data, Activity::VIEW);
+ ActivityPub\Processor::createActivity($fetchQueue, $object_data, Activity::VIEW);
} elseif ($object_data['object_type'] == '') {
// The object type couldn't be determined. Most likely we don't have it here. We ignore this activity.
} else {
case 'litepub:EmojiReact':
if (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
- ActivityPub\Processor::createActivity($object_data, Activity::EMOJIREACT);
+ ActivityPub\Processor::createActivity($fetchQueue, $object_data, Activity::EMOJIREACT);
} elseif ($object_data['object_type'] == '') {
// The object type couldn't be determined. We don't have it and we can't fetch it. We ignore this activity.
} else {