Merge pull request #13687 from annando/followers
Distribute incoming posts according to the parent followers collection
This commit is contained in:
commit
e0fb149466
|
@ -1235,7 +1235,7 @@ class Processor
|
||||||
|
|
||||||
$has_parents = false;
|
$has_parents = false;
|
||||||
|
|
||||||
if (!empty($item['parent-uri-id'])) {
|
if (($item['private'] != Item::PRIVATE) && !empty($item['parent-uri-id'])) {
|
||||||
if (Post::exists(['uri-id' => $item['parent-uri-id'], 'uid' => $receiver])) {
|
if (Post::exists(['uri-id' => $item['parent-uri-id'], 'uid' => $receiver])) {
|
||||||
$has_parents = true;
|
$has_parents = true;
|
||||||
} elseif ($add_parent && Post::exists(['uri-id' => $item['parent-uri-id'], 'uid' => 0])) {
|
} elseif ($add_parent && Post::exists(['uri-id' => $item['parent-uri-id'], 'uid' => 0])) {
|
||||||
|
@ -1254,7 +1254,7 @@ class Processor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($item['parent-uri-id']) || ($item['thr-parent-id'] != $item['parent-uri-id'])) {
|
if (($item['private'] == Item::PRIVATE) || empty($item['parent-uri-id']) || ($item['thr-parent-id'] != $item['parent-uri-id'])) {
|
||||||
if (Post::exists(['uri-id' => $item['thr-parent-id'], 'uid' => $receiver])) {
|
if (Post::exists(['uri-id' => $item['thr-parent-id'], 'uid' => $receiver])) {
|
||||||
$has_parents = true;
|
$has_parents = true;
|
||||||
} elseif (($has_parents || $add_parent) && Post::exists(['uri-id' => $item['thr-parent-id'], 'uid' => 0])) {
|
} elseif (($has_parents || $add_parent) && Post::exists(['uri-id' => $item['thr-parent-id'], 'uid' => 0])) {
|
||||||
|
|
|
@ -246,7 +246,7 @@ class Receiver
|
||||||
} else {
|
} else {
|
||||||
Logger::notice('Relayed message had not been fetched', ['id' => $object_id, 'actor' => $actor, 'activity' => $activity]);
|
Logger::notice('Relayed message had not been fetched', ['id' => $object_id, 'actor' => $actor, 'activity' => $activity]);
|
||||||
}
|
}
|
||||||
} elseif (!Fetch::hasWorker($object_id)) {
|
} elseif (!Fetch::hasWorker($object_id)) {
|
||||||
Logger::notice('Fetching is done by worker.', ['id' => $object_id]);
|
Logger::notice('Fetching is done by worker.', ['id' => $object_id]);
|
||||||
Fetch::add($object_id);
|
Fetch::add($object_id);
|
||||||
$activity['recursion-depth'] = 0;
|
$activity['recursion-depth'] = 0;
|
||||||
|
@ -308,13 +308,12 @@ class Receiver
|
||||||
* @param boolean $push Message had been pushed to our system
|
* @param boolean $push Message had been pushed to our system
|
||||||
* @param boolean $trust_source Do we trust the source?
|
* @param boolean $trust_source Do we trust the source?
|
||||||
* @param string $original_actor Actor of the original activity. Used for receiver detection. (Optional)
|
* @param string $original_actor Actor of the original activity. Used for receiver detection. (Optional)
|
||||||
* @param string $http_signer Actor who has signed the HTTP request
|
|
||||||
*
|
*
|
||||||
* @return array with object data
|
* @return array with object data
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
* @throws \ImagickException
|
* @throws \ImagickException
|
||||||
*/
|
*/
|
||||||
public static function prepareObjectData(array $activity, int $uid, bool $push, bool &$trust_source, string $original_actor = '', string $http_signer = ''): array
|
public static function prepareObjectData(array $activity, int $uid, bool $push, bool &$trust_source, string $original_actor = ''): array
|
||||||
{
|
{
|
||||||
$id = JsonLD::fetchElement($activity, '@id');
|
$id = JsonLD::fetchElement($activity, '@id');
|
||||||
$type = JsonLD::fetchElement($activity, '@type');
|
$type = JsonLD::fetchElement($activity, '@type');
|
||||||
|
@ -369,7 +368,7 @@ class Receiver
|
||||||
$type = JsonLD::fetchElement($activity, '@type');
|
$type = JsonLD::fetchElement($activity, '@type');
|
||||||
|
|
||||||
// Fetch all receivers from to, cc, bto and bcc
|
// Fetch all receivers from to, cc, bto and bcc
|
||||||
$receiverdata = self::getReceivers($activity, $original_actor ?: $actor, [], false, $push || $fetched, $http_signer);
|
$receiverdata = self::getReceivers($activity, $original_actor ?: $actor, [], false, $push || $fetched);
|
||||||
$receivers = $reception_types = [];
|
$receivers = $reception_types = [];
|
||||||
foreach ($receiverdata as $key => $data) {
|
foreach ($receiverdata as $key => $data) {
|
||||||
$receivers[$key] = $data['uid'];
|
$receivers[$key] = $data['uid'];
|
||||||
|
@ -393,7 +392,7 @@ class Receiver
|
||||||
|
|
||||||
// We possibly need some user to fetch private content,
|
// We possibly need some user to fetch private content,
|
||||||
// so we fetch one out of the receivers if no uid is provided.
|
// so we fetch one out of the receivers if no uid is provided.
|
||||||
$fetch_uid = $uid ?: self::getBestUserForActivity($activity, $original_actor, $http_signer);
|
$fetch_uid = $uid ?: self::getBestUserForActivity($activity, $original_actor);
|
||||||
|
|
||||||
$object_id = JsonLD::fetchElement($activity, 'as:object', '@id');
|
$object_id = JsonLD::fetchElement($activity, 'as:object', '@id');
|
||||||
if (empty($object_id)) {
|
if (empty($object_id)) {
|
||||||
|
@ -499,19 +498,6 @@ class Receiver
|
||||||
$object_data['receiver'] = array_replace($object_data['receiver'] ?? [], $receivers);
|
$object_data['receiver'] = array_replace($object_data['receiver'] ?? [], $receivers);
|
||||||
$object_data['reception_type'] = array_replace($object_data['reception_type'] ?? [], $reception_types);
|
$object_data['reception_type'] = array_replace($object_data['reception_type'] ?? [], $reception_types);
|
||||||
|
|
||||||
// This check here interferes with Hubzilla posts where the author host differs from the host the post was created
|
|
||||||
// $author = $object_data['author'] ?? $actor;
|
|
||||||
// if (!empty($author) && !empty($object_data['id'])) {
|
|
||||||
// $author_host = parse_url($author, PHP_URL_HOST);
|
|
||||||
// $id_host = parse_url($object_data['id'], PHP_URL_HOST);
|
|
||||||
// if ($author_host == $id_host) {
|
|
||||||
// Logger::info('Valid hosts', ['type' => $type, 'host' => $id_host]);
|
|
||||||
// } else {
|
|
||||||
// Logger::notice('Differing hosts on author and id', ['type' => $type, 'author' => $author_host, 'id' => $id_host]);
|
|
||||||
// $trust_source = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
$account = Contact::selectFirstAccount(['platform'], ['nurl' => Strings::normaliseLink($actor)]);
|
$account = Contact::selectFirstAccount(['platform'], ['nurl' => Strings::normaliseLink($actor)]);
|
||||||
$platform = $account['platform'] ?? '';
|
$platform = $account['platform'] ?? '';
|
||||||
|
|
||||||
|
@ -683,7 +669,7 @@ class Receiver
|
||||||
}
|
}
|
||||||
|
|
||||||
// $trust_source is called by reference and is set to true if the content was retrieved successfully
|
// $trust_source is called by reference and is set to true if the content was retrieved successfully
|
||||||
$object_data = self::prepareObjectData($activity, $uid, $push, $trust_source, $original_actor, $trust_source ? $http_signer : '');
|
$object_data = self::prepareObjectData($activity, $uid, $push, $trust_source, $original_actor);
|
||||||
if (empty($object_data)) {
|
if (empty($object_data)) {
|
||||||
Logger::info('No object data found', ['activity' => $activity]);
|
Logger::info('No object data found', ['activity' => $activity]);
|
||||||
return true;
|
return true;
|
||||||
|
@ -1061,7 +1047,7 @@ class Receiver
|
||||||
* @param boolean $unknown "true" if the activity is unknown, "false" if it is unhandled
|
* @param boolean $unknown "true" if the activity is unknown, "false" if it is unhandled
|
||||||
* @param string $type Activity type
|
* @param string $type Activity type
|
||||||
* @param array $object_data Preprocessed array that is generated out of the received activity
|
* @param array $object_data Preprocessed array that is generated out of the received activity
|
||||||
* @param array $activity Array with activity data
|
* @param array $activity Array with activity data
|
||||||
* @param string $body The unprocessed body
|
* @param string $body The unprocessed body
|
||||||
* @param integer $uid User ID
|
* @param integer $uid User ID
|
||||||
* @param boolean $trust_source Do we trust the source?
|
* @param boolean $trust_source Do we trust the source?
|
||||||
|
@ -1095,16 +1081,15 @@ class Receiver
|
||||||
*
|
*
|
||||||
* @param array $activity
|
* @param array $activity
|
||||||
* @param string $actor
|
* @param string $actor
|
||||||
* @param string $http_signer
|
|
||||||
*
|
*
|
||||||
* @return int user id
|
* @return int user id
|
||||||
*/
|
*/
|
||||||
private static function getBestUserForActivity(array $activity, string $actor, string $http_signer = ''): int
|
private static function getBestUserForActivity(array $activity, string $actor): int
|
||||||
{
|
{
|
||||||
$uid = 0;
|
$uid = 0;
|
||||||
$actor = $actor ?: JsonLD::fetchElement($activity, 'as:actor', '@id') ?? '';
|
$actor = $actor ?: JsonLD::fetchElement($activity, 'as:actor', '@id') ?? '';
|
||||||
|
|
||||||
$receivers = self::getReceivers($activity, $actor, [], false, false, $http_signer);
|
$receivers = self::getReceivers($activity, $actor, [], false, false);
|
||||||
foreach ($receivers as $receiver) {
|
foreach ($receivers as $receiver) {
|
||||||
if ($receiver['type'] == self::TARGET_GLOBAL) {
|
if ($receiver['type'] == self::TARGET_GLOBAL) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1159,12 +1144,11 @@ class Receiver
|
||||||
* @param array $tags
|
* @param array $tags
|
||||||
* @param bool $fetch_unlisted
|
* @param bool $fetch_unlisted
|
||||||
* @param bool $push
|
* @param bool $push
|
||||||
* @param string $http_signer
|
|
||||||
*
|
*
|
||||||
* @return array with receivers (user id)
|
* @return array with receivers (user id)
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
private static function getReceivers(array $activity, string $actor, array $tags, bool $fetch_unlisted, bool $push, string $http_signer = ''): array
|
private static function getReceivers(array $activity, string $actor, array $tags, bool $fetch_unlisted, bool $push): array
|
||||||
{
|
{
|
||||||
$reply = $receivers = $profile = [];
|
$reply = $receivers = $profile = [];
|
||||||
|
|
||||||
|
@ -1200,17 +1184,19 @@ class Receiver
|
||||||
$isGroup = false;
|
$isGroup = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$parent_followers = '';
|
||||||
|
$parent = Post::selectFirstPost(['parent-author-link'], ['uri' => $reply]);
|
||||||
|
if (!empty($parent['parent-author-link'])) {
|
||||||
|
$parent_profile = APContact::getByURL($parent['parent-author-link']);
|
||||||
|
if (!in_array($parent_profile['followers'] ?? '', ['', $followers])) {
|
||||||
|
$parent_followers = $parent_profile['followers'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We have to prevent false follower assumptions upon thread completions
|
// We have to prevent false follower assumptions upon thread completions
|
||||||
$follower_target = empty($activity['thread-completion']) ? self::TARGET_FOLLOWER : self::TARGET_UNKNOWN;
|
$follower_target = empty($activity['thread-completion']) ? self::TARGET_FOLLOWER : self::TARGET_UNKNOWN;
|
||||||
|
|
||||||
if (($actor != $http_signer) && ($http_signer != '') && ($follower_target == self::TARGET_FOLLOWER)) {
|
foreach (['as:to', 'as:cc', 'as:bto', 'as:bcc', 'as:audience'] as $element) {
|
||||||
$signer_profile = APContact::getByURL($http_signer);
|
|
||||||
$signer_followers = $signer_profile['followers'] ?? '';
|
|
||||||
} else {
|
|
||||||
$signer_followers = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (['as:to', 'as:cc', 'as:bto', 'as:bcc','as:audience'] as $element) {
|
|
||||||
$receiver_list = JsonLD::fetchElementArray($activity, $element, '@id');
|
$receiver_list = JsonLD::fetchElementArray($activity, $element, '@id');
|
||||||
if (empty($receiver_list)) {
|
if (empty($receiver_list)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1228,12 +1214,12 @@ class Receiver
|
||||||
|
|
||||||
// Fetch the receivers for the public and the followers collection
|
// Fetch the receivers for the public and the followers collection
|
||||||
if ((($receiver == $followers) || (($receiver == self::PUBLIC_COLLECTION) && !$isGroup) || ($isGroup && ($element == 'as:audience'))) && !empty($actor)) {
|
if ((($receiver == $followers) || (($receiver == self::PUBLIC_COLLECTION) && !$isGroup) || ($isGroup && ($element == 'as:audience'))) && !empty($actor)) {
|
||||||
$receivers = self::getReceiverForActor($actor, $tags, $receivers, $follower_target, $profile);
|
$receivers = self::getReceiverForActor($tags, $receivers, $follower_target, $profile);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($receiver == $signer_followers) {
|
if ($receiver == $parent_followers) {
|
||||||
$receivers = self::getReceiverForActor($http_signer, [], $receivers, $follower_target, $signer_profile);
|
$receivers = self::getReceiverForActor([], $receivers, $follower_target, $parent_profile);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1317,7 +1303,6 @@ class Receiver
|
||||||
/**
|
/**
|
||||||
* Fetch the receiver list of a given actor
|
* Fetch the receiver list of a given actor
|
||||||
*
|
*
|
||||||
* @param string $actor
|
|
||||||
* @param array $tags
|
* @param array $tags
|
||||||
* @param array $receivers
|
* @param array $receivers
|
||||||
* @param integer $target_type
|
* @param integer $target_type
|
||||||
|
@ -1326,41 +1311,20 @@ class Receiver
|
||||||
* @return array with receivers (user id)
|
* @return array with receivers (user id)
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
private static function getReceiverForActor(string $actor, array $tags, array $receivers, int $target_type, array $profile): array
|
private static function getReceiverForActor(array $tags, array $receivers, int $target_type, array $profile): array
|
||||||
{
|
{
|
||||||
$basecondition = ['rel' => [Contact::SHARING, Contact::FRIEND, Contact::FOLLOWER],
|
$basecondition = ['rel' => [Contact::SHARING, Contact::FRIEND, Contact::FOLLOWER],
|
||||||
'network' => Protocol::FEDERATED, 'archive' => false, 'pending' => false];
|
'network' => Protocol::FEDERATED, 'archive' => false, 'pending' => false];
|
||||||
|
|
||||||
if (!empty($profile['uri-id'])) {
|
$condition = DBA::mergeConditions($basecondition, ["`uri-id` = ? AND `uid` != ?", $profile['uri-id'], 0]);
|
||||||
$condition = DBA::mergeConditions($basecondition, ["`uri-id` = ? AND `uid` != ?", $profile['uri-id'], 0]);
|
$contacts = DBA::select('contact', ['uid', 'rel'], $condition);
|
||||||
$contacts = DBA::select('contact', ['uid', 'rel'], $condition);
|
while ($contact = DBA::fetch($contacts)) {
|
||||||
while ($contact = DBA::fetch($contacts)) {
|
if (empty($receivers[$contact['uid']]) && self::isValidReceiverForActor($contact, $tags)) {
|
||||||
if (empty($receivers[$contact['uid']]) && self::isValidReceiverForActor($contact, $tags)) {
|
$receivers[$contact['uid']] = ['uid' => $contact['uid'], 'type' => $target_type];
|
||||||
$receivers[$contact['uid']] = ['uid' => $contact['uid'], 'type' => $target_type];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DBA::close($contacts);
|
|
||||||
} else {
|
|
||||||
// This part will only be called while post update 1426 wasn't finished
|
|
||||||
$condition = DBA::mergeConditions($basecondition, ["`nurl` = ? AND `uid` != ?", Strings::normaliseLink($actor), 0]);
|
|
||||||
$contacts = DBA::select('contact', ['uid', 'rel'], $condition);
|
|
||||||
while ($contact = DBA::fetch($contacts)) {
|
|
||||||
if (empty($receivers[$contact['uid']]) && self::isValidReceiverForActor($contact, $tags)) {
|
|
||||||
$receivers[$contact['uid']] = ['uid' => $contact['uid'], 'type' => $target_type];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DBA::close($contacts);
|
|
||||||
|
|
||||||
// The queries are split because of performance issues
|
|
||||||
$condition = DBA::mergeConditions($basecondition, ["`alias` IN (?, ?) AND `uid` != ?", Strings::normaliseLink($actor), $actor, 0]);
|
|
||||||
$contacts = DBA::select('contact', ['uid', 'rel'], $condition);
|
|
||||||
while ($contact = DBA::fetch($contacts)) {
|
|
||||||
if (empty($receivers[$contact['uid']]) && self::isValidReceiverForActor($contact, $tags)) {
|
|
||||||
$receivers[$contact['uid']] = ['uid' => $contact['uid'], 'type' => $target_type];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DBA::close($contacts);
|
|
||||||
}
|
}
|
||||||
|
DBA::close($contacts);
|
||||||
|
|
||||||
return $receivers;
|
return $receivers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1596,9 +1560,11 @@ class Receiver
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$element = ['type' => str_replace('as:', '', JsonLD::fetchElement($tag, '@type') ?? ''),
|
$element = [
|
||||||
|
'type' => str_replace('as:', '', JsonLD::fetchElement($tag, '@type') ?? ''),
|
||||||
'href' => JsonLD::fetchElement($tag, 'as:href', '@id'),
|
'href' => JsonLD::fetchElement($tag, 'as:href', '@id'),
|
||||||
'name' => JsonLD::fetchElement($tag, 'as:name', '@value')];
|
'name' => JsonLD::fetchElement($tag, 'as:name', '@value')
|
||||||
|
];
|
||||||
|
|
||||||
if (empty($element['type'])) {
|
if (empty($element['type'])) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1629,8 +1595,10 @@ class Receiver
|
||||||
}
|
}
|
||||||
|
|
||||||
$url = JsonLD::fetchElement($emoji['as:icon'], 'as:url', '@id');
|
$url = JsonLD::fetchElement($emoji['as:icon'], 'as:url', '@id');
|
||||||
$element = ['name' => JsonLD::fetchElement($emoji, 'as:name', '@value'),
|
$element = [
|
||||||
'href' => $url];
|
'name' => JsonLD::fetchElement($emoji, 'as:name', '@value'),
|
||||||
|
'href' => $url
|
||||||
|
];
|
||||||
|
|
||||||
$emojilist[] = $element;
|
$emojilist[] = $element;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user