From 968c935bf7b47a6eff9ef8a6ddda5411aa387dcd Mon Sep 17 00:00:00 2001
From: Michael <heluecht@pirati.ca>
Date: Fri, 23 Jun 2023 21:05:45 +0000
Subject: [PATCH] Changes variable names / fetch the alias / improved group
 handling

---
 src/Content/Widget/VCard.php           | 14 +++++-----
 src/Model/Item.php                     | 35 ++++++++++++++----------
 src/Protocol/ActivityPub/Processor.php | 37 +++++++++++++++++++-------
 3 files changed, 55 insertions(+), 31 deletions(-)

diff --git a/src/Content/Widget/VCard.php b/src/Content/Widget/VCard.php
index 2cb0b0df13..62a8e90853 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 de95d4e16c..17ac27cc3c 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 2db9f925a9..9758e4fd48 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;