+ /**
+ * Fetch the receiver list of a given actor
+ *
+ * @param string $actor
+ * @param array $tags
+ *
+ * @return array with receivers (user id)
+ * @throws \Exception
+ */
+ public static function getReceiverForActor($actor, $tags)
+ {
+ $receivers = [];
+ $networks = Protocol::FEDERATED;
+ $condition = ['nurl' => Strings::normaliseLink($actor), 'rel' => [Contact::SHARING, Contact::FRIEND, Contact::FOLLOWER],
+ 'network' => $networks, 'archive' => false, 'pending' => false];
+ $contacts = DBA::select('contact', ['uid', 'rel'], $condition);
+ while ($contact = DBA::fetch($contacts)) {
+ if (self::isValidReceiverForActor($contact, $actor, $tags)) {
+ $receivers['uid:' . $contact['uid']] = $contact['uid'];
+ }
+ }
+ DBA::close($contacts);
+ return $receivers;
+ }
+
+ /**
+ * Tests if the contact is a valid receiver for this actor
+ *
+ * @param array $contact
+ * @param string $actor
+ * @param array $tags
+ *
+ * @return bool with receivers (user id)
+ * @throws \Exception
+ */
+ private static function isValidReceiverForActor($contact, $actor, $tags)
+ {
+ // Public contacts are no valid receiver
+ if ($contact['uid'] == 0) {
+ return false;
+ }
+
+ // Are we following the contact? Then this is a valid receiver
+ if (in_array($contact['rel'], [Contact::SHARING, Contact::FRIEND])) {
+ return true;
+ }
+
+ // When the possible receiver isn't a community, then it is no valid receiver
+ $owner = User::getOwnerDataById($contact['uid']);
+ if (empty($owner) || ($owner['contact-type'] != Contact::TYPE_COMMUNITY)) {
+ return false;
+ }
+
+ // Is the community account tagged?
+ foreach ($tags as $tag) {
+ if ($tag['type'] != 'Mention') {
+ continue;
+ }
+
+ if ($tag['href'] == $owner['url']) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+