X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FProtocol%2FActivityPub%2FProcessor.php;h=c481423a675c495349ad2d27c7d56f8009cbd5a9;hb=ce74a4d9a19770a1f70257f50f77d92e12a29002;hp=2e93e1bc1886eb430df8b31fc0bbff3a25ae034e;hpb=743e7d3ecb4bc06999284bffd977265abc23731f;p=friendica.git diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 2e93e1bc18..c481423a67 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -17,12 +17,15 @@ use Friendica\Core\Config; use Friendica\Protocol\ActivityPub; /** - * @brief ActivityPub Protocol class + * ActivityPub Protocol class + * + * To-Do: + * - Store Diaspora signature */ class Processor { /** - * @brief Converts mentions from Pleroma into the Friendica format + * Converts mentions from Pleroma into the Friendica format * * @param string $body * @@ -37,7 +40,7 @@ class Processor } /** - * @brief Constructs a string with tags for a given tag array + * Constructs a string with tags for a given tag array * * @param array $tags * @param boolean $sensitive @@ -52,7 +55,7 @@ class Processor $tag_text = ''; foreach ($tags as $tag) { - if (in_array($tag['type'], ['Mention', 'Hashtag'])) { + if (in_array(defaults($tag, 'type', ''), ['Mention', 'Hashtag'])) { if (!empty($tag_text)) { $tag_text .= ','; } @@ -67,9 +70,9 @@ class Processor } /** - * @brief + * Add attachment data to the item array * - * @param $attachments + * @param array $attachments * @param array $item * * @return item array @@ -101,12 +104,11 @@ class Processor } /** - * @brief + * Prepares data for a message * - * @param array $activity - * @param $body + * @param array $activity Activity array */ - public static function createItem($activity, $body) + public static function createItem($activity) { $item = []; $item['verb'] = ACTIVITY_POST; @@ -125,65 +127,61 @@ class Processor self::fetchMissingActivity($activity['reply-to-id'], $activity); } - self::postItem($activity, $item, $body); + self::postItem($activity, $item); } /** - * @brief + * Prepare the item array for a "like" * - * @param array $activity - * @param $body + * @param array $activity Activity array */ - public static function likeItem($activity, $body) + public static function likeItem($activity) { $item = []; $item['verb'] = ACTIVITY_LIKE; - $item['parent-uri'] = $activity['object']; + $item['parent-uri'] = $activity['object_id']; $item['gravity'] = GRAVITY_ACTIVITY; $item['object-type'] = ACTIVITY_OBJ_NOTE; - self::postItem($activity, $item, $body); + self::postItem($activity, $item); } /** - * @brief Delete items + * Delete items * * @param array $activity - * @param $body */ public static function deleteItem($activity) { - $owner = Contact::getIdForURL($activity['owner']); - $object = JsonLD::fetchElement($activity, 'object', 'id'); - logger('Deleting item ' . $object . ' from ' . $owner, LOGGER_DEBUG); - Item::delete(['uri' => $object, 'owner-id' => $owner]); + $owner = Contact::getIdForURL($activity['actor']); + + logger('Deleting item ' . $activity['object_id'] . ' from ' . $owner, LOGGER_DEBUG); + Item::delete(['uri' => $activity['object_id'], 'owner-id' => $owner]); } /** - * @brief + * Prepare the item array for a "dislike" * - * @param array $activity - * @param $body + * @param array $activity Activity array */ - public static function dislikeItem($activity, $body) + public static function dislikeItem($activity) { $item = []; $item['verb'] = ACTIVITY_DISLIKE; - $item['parent-uri'] = $activity['object']; + $item['parent-uri'] = $activity['object_id']; $item['gravity'] = GRAVITY_ACTIVITY; $item['object-type'] = ACTIVITY_OBJ_NOTE; - self::postItem($activity, $item, $body); + self::postItem($activity, $item); } /** - * @brief + * Creates an item post * - * @param array $activity - * @param array $item - * @param $body + * @param array $activity Activity data + * @param array $item item array */ - private static function postItem($activity, $item, $body) + private static function postItem($activity, $item) { /// @todo What to do with $activity['context']? @@ -194,8 +192,18 @@ class Processor $item['network'] = Protocol::ACTIVITYPUB; $item['private'] = !in_array(0, $activity['receiver']); + $item['author-link'] = $activity['author']; $item['author-id'] = Contact::getIdForURL($activity['author'], 0, true); - $item['owner-id'] = Contact::getIdForURL($activity['owner'], 0, true); + + if (empty($activity['thread-completion'])) { + $item['owner-link'] = $activity['actor']; + $item['owner-id'] = Contact::getIdForURL($activity['actor'], 0, true); + } else { + logger('Ignoring actor because of thread completion.', LOGGER_DEBUG); + $item['owner-link'] = $item['author-link']; + $item['owner-id'] = $item['author-id']; + } + $item['uri'] = $activity['id']; $item['created'] = $activity['published']; $item['edited'] = $activity['updated']; @@ -203,23 +211,28 @@ class Processor $item['title'] = HTML::toBBCode($activity['name']); $item['content-warning'] = HTML::toBBCode($activity['summary']); $item['body'] = self::convertMentions(HTML::toBBCode($activity['content'])); + + if (($activity['object_type'] == 'as:Video') && !empty($activity['alternate-url'])) { + $item['body'] .= "\n[video]" . $activity['alternate-url'] . '[/video]'; + } + $item['location'] = $activity['location']; + + if (!empty($item['latitude']) && !empty($item['longitude'])) { + $item['coord'] = $item['latitude'] . ' ' . $item['longitude']; + } + $item['tag'] = self::constructTagList($activity['tags'], $activity['sensitive']); - $item['app'] = $activity['service']; + $item['app'] = $activity['generator']; $item['plink'] = defaults($activity, 'alternate-url', $item['uri']); + $item['diaspora_signed_text'] = defaults($activity, 'diaspora:comment', ''); $item = self::constructAttachList($activity['attachments'], $item); - $source = JsonLD::fetchElement($activity, 'source', 'content', 'mediaType', 'text/bbcode'); - if (!empty($source)) { - $item['body'] = $source; + if (!empty($activity['source'])) { + $item['body'] = $activity['source']; } - $item['protocol'] = Conversation::PARCEL_ACTIVITYPUB; - $item['source'] = $body; - $item['conversation-href'] = $activity['context']; - $item['conversation-uri'] = $activity['conversation']; - foreach ($activity['receiver'] as $receiver) { $item['uid'] = $receiver; $item['contact-id'] = Contact::getIdForURL($activity['author'], $receiver, true); @@ -234,7 +247,7 @@ class Processor } /** - * @brief + * Fetches missing posts * * @param $url * @param $child @@ -262,112 +275,115 @@ class Processor $activity['published'] = $object['published']; $activity['type'] = 'Create'; - ActivityPub\Receiver::processActivity($activity); + $ldactivity = JsonLD::compact($activity); + + $ldactivity['thread-completion'] = true; + + ActivityPub\Receiver::processActivity($ldactivity); logger('Activity ' . $url . ' had been fetched and processed.'); } /** - * @brief perform a "follow" request + * perform a "follow" request * * @param array $activity */ public static function followUser($activity) { - $actor = JsonLD::fetchElement($activity, 'object', 'id'); - $uid = User::getIdForURL($actor); + $uid = User::getIdForURL($activity['object_id']); if (empty($uid)) { return; } $owner = User::getOwnerDataById($uid); - $cid = Contact::getIdForURL($activity['owner'], $uid); + $cid = Contact::getIdForURL($activity['actor'], $uid); if (!empty($cid)) { - $contact = DBA::selectFirst('contact', [], ['id' => $cid]); + self::switchContact($cid); + $contact = DBA::selectFirst('contact', [], ['id' => $cid, 'network' => Protocol::NATIVE_SUPPORT]); } else { $contact = false; } - $item = ['author-id' => Contact::getIdForURL($activity['owner']), - 'author-link' => $activity['owner']]; + $item = ['author-id' => Contact::getIdForURL($activity['actor']), + 'author-link' => $activity['actor']]; + + // Ensure that the contact has got the right network type + self::switchContact($item['author-id']); Contact::addRelationship($owner, $contact, $item); - $cid = Contact::getIdForURL($activity['owner'], $uid); + $cid = Contact::getIdForURL($activity['actor'], $uid); if (empty($cid)) { return; } - $contact = DBA::selectFirst('contact', ['network'], ['id' => $cid]); - if ($contact['network'] != Protocol::ACTIVITYPUB) { - Contact::updateFromProbe($cid, Protocol::ACTIVITYPUB); - } - DBA::update('contact', ['hub-verify' => $activity['id']], ['id' => $cid]); logger('Follow user ' . $uid . ' from contact ' . $cid . ' with id ' . $activity['id']); } /** - * @brief Update the given profile + * Update the given profile * * @param array $activity */ public static function updatePerson($activity) { - if (empty($activity['object']['id'])) { + if (empty($activity['object_id'])) { return; } - logger('Updating profile for ' . $activity['object']['id'], LOGGER_DEBUG); - APContact::getByURL($activity['object']['id'], true); + logger('Updating profile for ' . $activity['object_id'], LOGGER_DEBUG); + APContact::getByURL($activity['object_id'], true); } /** - * @brief Delete the given profile + * Delete the given profile * * @param array $activity */ public static function deletePerson($activity) { - if (empty($activity['object']['id']) || empty($activity['object']['actor'])) { + if (empty($activity['object_id']) || empty($activity['actor'])) { logger('Empty object id or actor.', LOGGER_DEBUG); return; } - if ($activity['object']['id'] != $activity['object']['actor']) { + if ($activity['object_id'] != $activity['actor']) { logger('Object id does not match actor.', LOGGER_DEBUG); return; } - $contacts = DBA::select('contact', ['id'], ['nurl' => normalise_link($activity['object']['id'])]); + $contacts = DBA::select('contact', ['id'], ['nurl' => normalise_link($activity['object_id'])]); while ($contact = DBA::fetch($contacts)) { - Contact::remove($contact["id"]); + Contact::remove($contact['id']); } DBA::close($contacts); - logger('Deleted contact ' . $activity['object']['id'], LOGGER_DEBUG); + logger('Deleted contact ' . $activity['object_id'], LOGGER_DEBUG); } /** - * @brief Accept a follow request + * Accept a follow request * * @param array $activity */ public static function acceptFollowUser($activity) { - $actor = JsonLD::fetchElement($activity, 'object', 'actor'); - $uid = User::getIdForURL($actor); + $uid = User::getIdForURL($activity['object_actor']); if (empty($uid)) { return; } $owner = User::getOwnerDataById($uid); - $cid = Contact::getIdForURL($activity['owner'], $uid); + $cid = Contact::getIdForURL($activity['actor'], $uid); if (empty($cid)) { - logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); + logger('No contact found for ' . $activity['actor'], LOGGER_DEBUG); return; } + self::switchContact($cid); + $fields = ['pending' => false]; $contact = DBA::selectFirst('contact', ['rel'], ['id' => $cid]); @@ -381,26 +397,27 @@ class Processor } /** - * @brief Reject a follow request + * Reject a follow request * * @param array $activity */ public static function rejectFollowUser($activity) { - $actor = JsonLD::fetchElement($activity, 'object', 'actor'); - $uid = User::getIdForURL($actor); + $uid = User::getIdForURL($activity['object_actor']); if (empty($uid)) { return; } $owner = User::getOwnerDataById($uid); - $cid = Contact::getIdForURL($activity['owner'], $uid); + $cid = Contact::getIdForURL($activity['actor'], $uid); if (empty($cid)) { - logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); + logger('No contact found for ' . $activity['actor'], LOGGER_DEBUG); return; } + self::switchContact($cid); + if (DBA::exists('contact', ['id' => $cid, 'rel' => Contact::SHARING, 'pending' => true])) { Contact::remove($cid); logger('Rejected contact request from contact ' . $cid . ' for user ' . $uid . ' - contact had been removed.', LOGGER_DEBUG); @@ -410,51 +427,50 @@ class Processor } /** - * @brief Undo activity like "like" or "dislike" + * Undo activity like "like" or "dislike" * * @param array $activity */ public static function undoActivity($activity) { - $activity_url = JsonLD::fetchElement($activity, 'object', 'id'); - if (empty($activity_url)) { + if (empty($activity['object_id'])) { return; } - $actor = JsonLD::fetchElement($activity, 'object', 'actor'); - if (empty($actor)) { + if (empty($activity['object_actor'])) { return; } - $author_id = Contact::getIdForURL($actor); + $author_id = Contact::getIdForURL($activity['object_actor']); if (empty($author_id)) { return; } - Item::delete(['uri' => $activity_url, 'author-id' => $author_id, 'gravity' => GRAVITY_ACTIVITY]); + Item::delete(['uri' => $activity['object_id'], 'author-id' => $author_id, 'gravity' => GRAVITY_ACTIVITY]); } /** - * @brief Activity to remove a follower + * Activity to remove a follower * * @param array $activity */ public static function undoFollowUser($activity) { - $object = JsonLD::fetchElement($activity, 'object', 'object'); - $uid = User::getIdForURL($object); + $uid = User::getIdForURL($activity['object_object']); if (empty($uid)) { return; } $owner = User::getOwnerDataById($uid); - $cid = Contact::getIdForURL($activity['owner'], $uid); + $cid = Contact::getIdForURL($activity['actor'], $uid); if (empty($cid)) { - logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); + logger('No contact found for ' . $activity['actor'], LOGGER_DEBUG); return; } + self::switchContact($cid); + $contact = DBA::selectFirst('contact', [], ['id' => $cid]); if (!DBA::isResult($contact)) { return; @@ -463,4 +479,20 @@ class Processor Contact::removeFollower($owner, $contact); logger('Undo following request from contact ' . $cid . ' for user ' . $uid, LOGGER_DEBUG); } + + /** + * Switches a contact to AP if needed + * + * @param integer $cid Contact ID + */ + private static function switchContact($cid) + { + $contact = DBA::selectFirst('contact', ['network'], ['id' => $cid, 'network' => Protocol::NATIVE_SUPPORT]); + if (!DBA::isResult($contact) || ($contact['network'] == Protocol::ACTIVITYPUB)) { + return; + } + + logger('Change existing contact ' . $cid . ' from ' . $contact['network'] . ' to ActivityPub.'); + Contact::updateFromProbe($cid, Protocol::ACTIVITYPUB); + } }