From 46f77f348628b5396e286617f22a43e90086a34b Mon Sep 17 00:00:00 2001
From: Michael <heluecht@pirati.ca>
Date: Sun, 7 Oct 2018 20:36:15 +0000
Subject: [PATCH] Detect the object type

---
 database.sql                          | 30 +++++++++++++++--
 src/Protocol/ActivityPub/Receiver.php | 47 +++++++++++++++++++++++++--
 2 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/database.sql b/database.sql
index 7188558042..a797c8df36 100644
--- a/database.sql
+++ b/database.sql
@@ -1,6 +1,6 @@
 -- ------------------------------------------
 -- Friendica 2018.12-dev (The Tazmans Flax-lily)
--- DB_UPDATE_VERSION 1283
+-- DB_UPDATE_VERSION 1284
 -- ------------------------------------------
 
 
@@ -19,6 +19,32 @@ CREATE TABLE IF NOT EXISTS `addon` (
 	 UNIQUE INDEX `name` (`name`)
 ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='registered addons';
 
+--
+-- TABLE apcontact
+--
+CREATE TABLE IF NOT EXISTS `apcontact` (
+	`url` varbinary(255) NOT NULL COMMENT 'URL of the contact',
+	`uuid` varchar(255) COMMENT '',
+	`type` varchar(20) NOT NULL COMMENT '',
+	`following` varchar(255) COMMENT '',
+	`followers` varchar(255) COMMENT '',
+	`inbox` varchar(255) NOT NULL COMMENT '',
+	`outbox` varchar(255) COMMENT '',
+	`sharedinbox` varchar(255) COMMENT '',
+	`nick` varchar(255) NOT NULL DEFAULT '' COMMENT '',
+	`name` varchar(255) COMMENT '',
+	`about` text COMMENT '',
+	`photo` varchar(255) COMMENT '',
+	`addr` varchar(255) COMMENT '',
+	`alias` varchar(255) COMMENT '',
+	`pubkey` text COMMENT '',
+	`baseurl` varchar(255) COMMENT 'baseurl of the ap contact',
+	`updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '',
+	 PRIMARY KEY(`url`),
+	 INDEX `addr` (`addr`(32)),
+	 INDEX `url` (`followers`(190))
+) DEFAULT COLLATE utf8mb4_general_ci COMMENT='ActivityPub compatible contacts - used in the ActivityPub implementation';
+
 --
 -- TABLE attach
 --
@@ -212,7 +238,7 @@ CREATE TABLE IF NOT EXISTS `conversation` (
 	`reply-to-uri` varbinary(255) NOT NULL DEFAULT '' COMMENT 'URI to which this item is a reply',
 	`conversation-uri` varbinary(255) NOT NULL DEFAULT '' COMMENT 'GNU Social conversation URI',
 	`conversation-href` varbinary(255) NOT NULL DEFAULT '' COMMENT 'GNU Social conversation link',
-	`protocol` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'The protocol of the item',
+	`protocol` tinyint unsigned NOT NULL DEFAULT 255 COMMENT 'The protocol of the item',
 	`source` mediumtext COMMENT 'Original source',
 	`received` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Receiving date',
 	 PRIMARY KEY(`item-uri`),
diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php
index ac66aeb6ec..1dac0bb827 100644
--- a/src/Protocol/ActivityPub/Receiver.php
+++ b/src/Protocol/ActivityPub/Receiver.php
@@ -30,9 +30,6 @@ use Friendica\Protocol\ActivityPub;
  * - Remove
  * - Undo Block
  * - Undo Accept (Problem: This could invert a contact accept or an event accept)
- *
- * General:
- * - Possibly using the LD-JSON parser
  */
 class Receiver
 {
@@ -111,6 +108,44 @@ class Receiver
 		self::processActivity($ldactivity, $body, $uid, $trust_source);
 	}
 
+	/**
+	 * Fetches the object type for a given object id
+	 *
+	 * @param array  $activity
+	 * @param string $object_id Object ID of the the provided object
+	 *
+	 * @return string with object type
+	 */
+	private static function fetchObjectType($activity, $object_id)
+	{
+
+		$object_type = JsonLD::fetchElement($activity['as:object'], '@type');
+		if (!empty($object_type)) {
+			return $object_type;
+		}
+
+		if (Item::exists(['uri' => $object_id, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]])) {
+			// We just assume "note" since it doesn't make a difference for the further processing
+			return 'as:Note';
+		}
+
+		$profile = APContact::getByURL($object_id);
+		if (!empty($profile['type'])) {
+			return 'as:' . $profile['type'];
+		}
+
+		$data = ActivityPub::fetchContent($object_id);
+		if (!empty($data)) {
+			$object = JsonLD::compact($data);
+			$type = JsonLD::fetchElement($object, '@type');
+			if (!empty($type)) {
+				return $type;
+			}
+		}
+
+		return null;
+	}
+
 	/**
 	 * Prepare the object array
 	 *
@@ -148,6 +183,8 @@ class Receiver
 			return [];
 		}
 
+		$object_type = self::fetchObjectType($activity, $object_id);
+
 		// Fetch the content only on activities where this matters
 		if (in_array($type, ['as:Create', 'as:Announce'])) {
 			if ($type == 'as:Announce') {
@@ -179,6 +216,10 @@ class Receiver
 
 		$object_data = self::addActivityFields($object_data, $activity);
 
+		if (empty($object_data['object_type'])) {
+			$object_data['object_type'] = $object_type;
+		}
+
 		$object_data['type'] = $type;
 		$object_data['actor'] = $actor;
 		$object_data['receiver'] = array_merge(defaults($object_data, 'receiver', []), $receivers);
-- 
2.39.5