diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 0ab2619412..e0ee1f0f90 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -208,7 +208,8 @@ class Receiver } // We had been able to retrieve the object data - so we can trust the source $trust_source = true; - } elseif (in_array($type, ['as:Like', 'as:Dislike'])) { + } elseif (in_array($type, ['as:Like', 'as:Dislike']) || + (($type == 'as:Follow') && in_array($object_type, self::CONTENT_TYPES))) { // Create a mostly empty array out of the activity data (instead of the object). // This way we later don't have to check for the existence of ech individual array element. $object_data = self::processObject($activity); @@ -394,6 +395,9 @@ class Receiver case 'as:Follow': if (in_array($object_data['object_type'], self::ACCOUNT_TYPES)) { 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); } break; diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 7481db9e74..fa8bdc0439 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -601,6 +601,8 @@ class Transmitter $type = 'Reject'; } elseif ($item['verb'] == ACTIVITY_ATTENDMAYBE) { $type = 'TentativeAccept'; + } elseif ($item['verb'] == ACTIVITY_FOLLOW) { + $type = 'Follow'; } else { $type = ''; } @@ -701,6 +703,8 @@ class Transmitter $data['object'] = self::createNote($item); } elseif ($data['type'] == 'Announce') { $data = self::createAnnounce($item, $data); + } elseif ($data['type'] == 'Follow') { + $data['object'] = $item['parent-uri']; } elseif ($data['type'] == 'Undo') { $data['object'] = self::createActivityFromItem($item_id, true); } else { @@ -1275,6 +1279,38 @@ class Transmitter return HTTPSignature::transmit($signed, $profile['inbox'], $uid); } + /** + * Transmits a "follow object" activity to a target + * This is a preparation for sending automated "follow" requests when receiving "Announce" messages + * + * @param string $object Object URL + * @param string $target Target profile + * @param integer $uid User ID + * @return bool + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + * @throws \Exception + */ + public static function sendFollowObject($object, $target, $uid) + { + $profile = APContact::getByURL($target); + + $owner = User::getOwnerDataById($uid); + + $data = ['@context' => ActivityPub::CONTEXT, + 'id' => System::baseUrl() . '/activity/' . System::createGUID(), + 'type' => 'Follow', + 'actor' => $owner['url'], + 'object' => $object, + 'instrument' => ['type' => 'Service', 'name' => BaseObject::getApp()->getUserAgent()], + 'to' => [$profile['url']]]; + + Logger::log('Sending follow ' . $object . ' to ' . $target . ' for user ' . $uid, Logger::DEBUG); + + $signed = LDSignature::sign($data, $owner); + return HTTPSignature::transmit($signed, $profile['inbox'], $uid); + } + /** * Transmit a message that the contact request had been accepted *