diff --git a/src/Content/Widget/VCard.php b/src/Content/Widget/VCard.php index 2cb0b0df1..62a8e9085 100644 --- a/src/Content/Widget/VCard.php +++ b/src/Content/Widget/VCard.php @@ -52,14 +52,14 @@ class VCard } if (!Network::isValidHttpUrl($contact['url']) && Network::isValidHttpUrl($contact['alias'])) { - $url = $contact['alias']; + $contact_url = $contact['alias']; } else { - $url = $contact['url']; + $contact_url = $contact['url']; } if ($contact['network'] != '') { - $network_link = Strings::formatNetworkName($contact['network'], $url); - $network_avatar = ContactSelector::networkToIcon($contact['network'], $url); + $network_link = Strings::formatNetworkName($contact['network'], $contact_url); + $network_avatar = ContactSelector::networkToIcon($contact['network'], $contact_url); } else { $network_link = ''; $network_avatar = ''; @@ -90,9 +90,9 @@ class VCard if (empty($contact['self']) && Protocol::supportsFollow($contact['network'])) { if (in_array($rel, [Contact::SHARING, Contact::FRIEND])) { - $unfollow_link = 'contact/unfollow?url=' . urlencode($url) . '&auto=1'; + $unfollow_link = 'contact/unfollow?url=' . urlencode($contact_url) . '&auto=1'; } elseif (!$pending) { - $follow_link = 'contact/follow?url=' . urlencode($url) . '&auto=1'; + $follow_link = 'contact/follow?url=' . urlencode($contact_url) . '&auto=1'; } } @@ -104,7 +104,7 @@ class VCard return Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/vcard.tpl'), [ '$contact' => $contact, '$photo' => $photo, - '$url' => Contact::magicLinkByContact($contact, $url), + '$url' => Contact::magicLinkByContact($contact, $contact_url), '$about' => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['about'] ?? ''), '$xmpp' => DI::l10n()->t('XMPP:'), '$matrix' => DI::l10n()->t('Matrix:'), diff --git a/src/Model/Item.php b/src/Model/Item.php index de95d4e16..17ac27cc3 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -94,7 +94,7 @@ class Item 'wall', 'private', 'starred', 'origin', 'parent-origin', 'title', 'body', 'language', 'content-warning', 'location', 'coord', 'app', 'rendered-hash', 'rendered-html', 'object', 'quote-uri', 'quote-uri-id', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'mention', 'global', - 'author-id', 'author-link', 'author-name', 'author-avatar', 'author-network', 'author-updated', 'author-gsid', 'author-addr', 'author-uri-id', + 'author-id', 'author-link', 'author-alias', 'author-name', 'author-avatar', 'author-network', 'author-updated', 'author-gsid', 'author-addr', 'author-uri-id', 'owner-id', 'owner-link', 'owner-name', 'owner-avatar', 'owner-network', 'owner-contact-type', 'owner-updated', 'causer-id', 'causer-link', 'causer-name', 'causer-avatar', 'causer-contact-type', 'causer-network', 'contact-id', 'contact-uid', 'contact-link', 'contact-name', 'contact-avatar', @@ -490,6 +490,23 @@ class Item return $owner['id']; } + $contact_id = 0; + $user_contact_id = 0; + foreach (['group-link', 'causer-link', 'owner-link', 'author-link'] as $field) { + if (empty($item[$field])) { + continue; + } + if (!$user_contact_id && Contact::isSharingByURL($item[$field], $item['uid'], true)) { + $user_contact_id = Contact::getIdForURL($item[$field], $item['uid']); + } elseif (!$contact_id) { + $contact_id = Contact::getIdForURL($item[$field]); + } + } + + if ($user_contact_id) { + return $user_contact_id; + } + if (!empty($item['causer-id']) && Contact::isSharing($item['causer-id'], $item['uid'], true)) { $cdata = Contact::getPublicAndUserContactID($item['causer-id'], $item['uid']); if (!empty($cdata['user'])) { @@ -497,18 +514,8 @@ class Item } } - foreach (['owner-link', 'author-link', 'causer-link'] as $field) { - if (empty($item[$field])) { - continue; - } - if (Contact::isSharingByURL($item[$field], $item['uid'], true)) { - $contact_id = Contact::getIdForURL($item[$field], $item['uid']); - } else { - $contact_id = Contact::getIdForURL($item[$field]); - } - if (!empty($contact_id)) { - return $contact_id; - } + if ($contact_id) { + return $contact_id; } Logger::warning('contact-id could not be fetched, using self contact instead.', ['uid' => $item['uid'], 'item' => $item]); @@ -3733,7 +3740,7 @@ class Item /** * Does the given uri-id belongs to a post that is sent as starting post to a group? - * This does not apply to posts that are sent only in parallel to a group. + * This does apply to posts that are sent via ! and not in parallel to a group via @ * * @param int $uri_id * diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 2db9f925a..9758e4fd4 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -432,21 +432,38 @@ class Processor $item['owner-link'] = $item['author-link']; $item['owner-id'] = $item['author-id']; - } else { - $actor = APContact::getByURL($item['owner-link'], false); - $item['isGroup'] = ($actor['type'] ?? 'Person') == 'Group'; } if (!$item['isGroup'] && !empty($activity['receiver_urls']['as:audience'])) { foreach ($activity['receiver_urls']['as:audience'] as $audience) { $actor = APContact::getByURL($audience, false); if (($actor['type'] ?? 'Person') == 'Group') { - Logger::debug('Set owner to audience', ['audience' => $audience, 'actor' => $activity['actor'], 'author' => $activity['author']]); + Logger::debug('Group post detected via audience.', ['audience' => $audience, 'actor' => $activity['actor'], 'author' => $activity['author']]); $item['isGroup'] = true; - $item['owner-link'] = $audience; - $item['owner-id'] = Contact::getIdForURL($audience); + $item['group-link'] = $audience; } } + } else { + $owner = APContact::getByURL($item['owner-link'], false); + } + + if (!$item['isGroup'] && (($owner['type'] ?? 'Person') == 'Group')) { + Logger::debug('Group post detected via owner.', ['actor' => $activity['actor'], 'author' => $activity['author']]); + $item['isGroup'] = true; + $item['group-link'] = $item['owner-link']; + } elseif (!empty($item['causer-link'])) { + $causer = APContact::getByURL($item['causer-link'], false); + } + + if (!$item['isGroup'] && (($causer['type'] ?? 'Person') == 'Group')) { + Logger::debug('Group post detected via causer.', ['actor' => $activity['actor'], 'author' => $activity['author'], 'causer' => $item['causer-link']]); + $item['isGroup'] = true; + $item['group-link'] = $item['causer-link']; + } + + if (!empty($item['group-link']) && empty($item['causer-link'])) { + $item['causer-link'] = $item['group-link']; + $item['causer-id'] = Contact::getIdForURL($item['causer-link']); } $item['uri'] = $activity['id']; @@ -1071,8 +1088,8 @@ class Processor $item['causer-id'] = ($item['gravity'] == Item::GRAVITY_PARENT) ? $item['owner-id'] : $item['author-id']; } - if ($item['isGroup'] ?? false) { - $item['contact-id'] = Contact::getIdForURL($item['owner-link'], $receiver); + if ($item['isGroup']) { + $item['contact-id'] = Contact::getIdForURL($item['group-link'], $receiver); } else { $item['contact-id'] = Contact::getIdForURL($item['author-link'], $receiver); } @@ -1087,7 +1104,7 @@ class Processor } if (($receiver != 0) && ($item['gravity'] == Item::GRAVITY_PARENT) && !in_array($item['post-reason'], [Item::PR_FOLLOWER, Item::PR_TAG, item::PR_TO, Item::PR_CC, Item::PR_AUDIENCE])) { - if (!($item['isGroup'] ?? false)) { + if (!$item['isGroup']) { if ($item['post-reason'] == Item::PR_BCC) { Logger::info('Top level post via BCC from a non sharer, ignoring', ['uid' => $receiver, 'contact' => $item['contact-id'], 'url' => $item['uri']]); continue; @@ -1108,7 +1125,7 @@ class Processor } if ((DI::pConfig()->get($receiver, 'system', 'accept_only_sharer') == Item::COMPLETION_NONE) - && ((!$isGroup && !($item['isGroup'] ?? false) && ($activity['type'] != 'as:Announce')) + && ((!$isGroup && !$item['isGroup'] && ($activity['type'] != 'as:Announce')) || !Contact::isSharingByURL($activity['actor'], $receiver))) { Logger::info('Actor is a non sharer, is no group or it is no announce', ['uid' => $receiver, 'actor' => $activity['actor'], 'url' => $item['uri'], 'type' => $activity['type']]); continue;