From 7eb410bed722a0df72b21231275cab5ce3db298f Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 23 Jul 2022 06:52:43 +0000 Subject: [PATCH] Conversation/context is now stored --- database.sql | 18 ++++++++ doc/database/db_post-thread-user.md | 53 ++++++++++++----------- doc/database/db_post-thread.md | 41 +++++++++--------- src/Model/Item.php | 28 +++++++++--- src/Protocol/ActivityPub/Processor.php | 54 ++++++++++++++++++------ src/Protocol/ActivityPub/Queue.php | 8 ++++ src/Protocol/ActivityPub/Receiver.php | 4 ++ src/Protocol/ActivityPub/Transmitter.php | 22 +--------- src/Worker/ExpirePosts.php | 1 + static/dbstructure.config.php | 4 ++ static/dbview.config.php | 12 ++++++ 11 files changed, 161 insertions(+), 84 deletions(-) diff --git a/database.sql b/database.sql index a16bf24cf3..eb97ec3074 100644 --- a/database.sql +++ b/database.sql @@ -1323,6 +1323,7 @@ CREATE TABLE IF NOT EXISTS `post-tag` ( -- CREATE TABLE IF NOT EXISTS `post-thread` ( `uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri', + `conversation-id` int unsigned COMMENT 'Id of the item-uri table entry that contains the conversation uri', `owner-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Item owner', `author-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Item author', `causer-id` int unsigned COMMENT 'Link to the contact table with uid=0 of the contact that caused the item creation', @@ -1332,12 +1333,14 @@ CREATE TABLE IF NOT EXISTS `post-thread` ( `changed` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Date that something in the conversation changed, indicating clients should fetch the conversation again', `commented` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '', PRIMARY KEY(`uri-id`), + INDEX `conversation-id` (`conversation-id`), INDEX `owner-id` (`owner-id`), INDEX `author-id` (`author-id`), INDEX `causer-id` (`causer-id`), INDEX `received` (`received`), INDEX `commented` (`commented`), FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE, + FOREIGN KEY (`conversation-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE, FOREIGN KEY (`owner-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT, FOREIGN KEY (`author-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT, FOREIGN KEY (`causer-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT @@ -1416,6 +1419,7 @@ CREATE TABLE IF NOT EXISTS `post-user` ( -- CREATE TABLE IF NOT EXISTS `post-thread-user` ( `uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri', + `conversation-id` int unsigned COMMENT 'Id of the item-uri table entry that contains the conversation uri', `owner-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Item owner', `author-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Item author', `causer-id` int unsigned COMMENT 'Link to the contact table with uid=0 of the contact that caused the item creation', @@ -1440,6 +1444,7 @@ CREATE TABLE IF NOT EXISTS `post-thread-user` ( `post-user-id` int unsigned COMMENT 'Id of the post-user table', PRIMARY KEY(`uid`,`uri-id`), INDEX `uri-id` (`uri-id`), + INDEX `conversation-id` (`conversation-id`), INDEX `owner-id` (`owner-id`), INDEX `author-id` (`author-id`), INDEX `causer-id` (`causer-id`), @@ -1454,6 +1459,7 @@ CREATE TABLE IF NOT EXISTS `post-thread-user` ( INDEX `uid_starred` (`uid`,`starred`), INDEX `uid_mention` (`uid`,`mention`), FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE, + FOREIGN KEY (`conversation-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE, FOREIGN KEY (`owner-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT, FOREIGN KEY (`author-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT, FOREIGN KEY (`causer-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT, @@ -1745,6 +1751,8 @@ CREATE VIEW `post-user-view` AS SELECT `post-user`.`parent-uri-id` AS `parent-uri-id`, `thr-parent-item-uri`.`uri` AS `thr-parent`, `post-user`.`thr-parent-id` AS `thr-parent-id`, + `conversation-item-uri`.`uri` AS `conversation`, + `post-thread-user`.`conversation-id` AS `conversation-id`, `item-uri`.`guid` AS `guid`, `post-user`.`wall` AS `wall`, `post-user`.`gravity` AS `gravity`, @@ -1893,6 +1901,7 @@ CREATE VIEW `post-user-view` AS SELECT LEFT JOIN `item-uri` ON `item-uri`.`id` = `post-user`.`uri-id` LEFT JOIN `item-uri` AS `thr-parent-item-uri` ON `thr-parent-item-uri`.`id` = `post-user`.`thr-parent-id` LEFT JOIN `item-uri` AS `parent-item-uri` ON `parent-item-uri`.`id` = `post-user`.`parent-uri-id` + LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread-user`.`conversation-id` LEFT JOIN `item-uri` AS `external-item-uri` ON `external-item-uri`.`id` = `post-user`.`external-id` LEFT JOIN `verb` ON `verb`.`id` = `post-user`.`vid` LEFT JOIN `event` ON `event`.`id` = `post-user`.`event-id` @@ -1919,6 +1928,8 @@ CREATE VIEW `post-thread-user-view` AS SELECT `post-user`.`parent-uri-id` AS `parent-uri-id`, `thr-parent-item-uri`.`uri` AS `thr-parent`, `post-user`.`thr-parent-id` AS `thr-parent-id`, + `conversation-item-uri`.`uri` AS `conversation`, + `post-thread-user`.`conversation-id` AS `conversation-id`, `item-uri`.`guid` AS `guid`, `post-thread-user`.`wall` AS `wall`, `post-user`.`gravity` AS `gravity`, @@ -2066,6 +2077,7 @@ CREATE VIEW `post-thread-user-view` AS SELECT LEFT JOIN `item-uri` ON `item-uri`.`id` = `post-thread-user`.`uri-id` LEFT JOIN `item-uri` AS `thr-parent-item-uri` ON `thr-parent-item-uri`.`id` = `post-user`.`thr-parent-id` LEFT JOIN `item-uri` AS `parent-item-uri` ON `parent-item-uri`.`id` = `post-user`.`parent-uri-id` + LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread-user`.`conversation-id` LEFT JOIN `item-uri` AS `external-item-uri` ON `external-item-uri`.`id` = `post-user`.`external-id` LEFT JOIN `verb` ON `verb`.`id` = `post-user`.`vid` LEFT JOIN `event` ON `event`.`id` = `post-user`.`event-id` @@ -2088,6 +2100,8 @@ CREATE VIEW `post-view` AS SELECT `post`.`parent-uri-id` AS `parent-uri-id`, `thr-parent-item-uri`.`uri` AS `thr-parent`, `post`.`thr-parent-id` AS `thr-parent-id`, + `conversation-item-uri`.`uri` AS `conversation`, + `post-thread`.`conversation-id` AS `conversation-id`, `item-uri`.`guid` AS `guid`, `post`.`gravity` AS `gravity`, `external-item-uri`.`uri` AS `extid`, @@ -2205,6 +2219,7 @@ CREATE VIEW `post-view` AS SELECT LEFT JOIN `item-uri` ON `item-uri`.`id` = `post`.`uri-id` LEFT JOIN `item-uri` AS `thr-parent-item-uri` ON `thr-parent-item-uri`.`id` = `post`.`thr-parent-id` LEFT JOIN `item-uri` AS `parent-item-uri` ON `parent-item-uri`.`id` = `post`.`parent-uri-id` + LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread`.`conversation-id` LEFT JOIN `item-uri` AS `external-item-uri` ON `external-item-uri`.`id` = `post`.`external-id` LEFT JOIN `verb` ON `verb`.`id` = `post`.`vid` LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `post`.`uri-id` @@ -2224,6 +2239,8 @@ CREATE VIEW `post-thread-view` AS SELECT `post`.`parent-uri-id` AS `parent-uri-id`, `thr-parent-item-uri`.`uri` AS `thr-parent`, `post`.`thr-parent-id` AS `thr-parent-id`, + `conversation-item-uri`.`uri` AS `conversation`, + `post-thread`.`conversation-id` AS `conversation-id`, `item-uri`.`guid` AS `guid`, `post`.`gravity` AS `gravity`, `external-item-uri`.`uri` AS `extid`, @@ -2341,6 +2358,7 @@ CREATE VIEW `post-thread-view` AS SELECT LEFT JOIN `item-uri` ON `item-uri`.`id` = `post-thread`.`uri-id` LEFT JOIN `item-uri` AS `thr-parent-item-uri` ON `thr-parent-item-uri`.`id` = `post`.`thr-parent-id` LEFT JOIN `item-uri` AS `parent-item-uri` ON `parent-item-uri`.`id` = `post`.`parent-uri-id` + LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread`.`conversation-id` LEFT JOIN `item-uri` AS `external-item-uri` ON `external-item-uri`.`id` = `post`.`external-id` LEFT JOIN `verb` ON `verb`.`id` = `post`.`vid` LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `post-thread`.`uri-id` diff --git a/doc/database/db_post-thread-user.md b/doc/database/db_post-thread-user.md index 7c6eac868c..9026370491 100644 --- a/doc/database/db_post-thread-user.md +++ b/doc/database/db_post-thread-user.md @@ -6,31 +6,32 @@ Thread related data per user Fields ------ -| Field | Description | Type | Null | Key | Default | Extra | -| ------------ | ------------------------------------------------------------------------------------------------------- | ------------------ | ---- | --- | ------------------- | ----- | -| uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | PRI | NULL | | -| owner-id | Item owner | int unsigned | NO | | 0 | | -| author-id | Item author | int unsigned | NO | | 0 | | -| causer-id | Link to the contact table with uid=0 of the contact that caused the item creation | int unsigned | YES | | NULL | | -| network | | char(4) | NO | | | | -| created | | datetime | NO | | 0001-01-01 00:00:00 | | -| received | | datetime | NO | | 0001-01-01 00:00:00 | | -| changed | Date that something in the conversation changed, indicating clients should fetch the conversation again | datetime | NO | | 0001-01-01 00:00:00 | | -| commented | | datetime | NO | | 0001-01-01 00:00:00 | | -| uid | Owner id which owns this copy of the item | mediumint unsigned | NO | PRI | 0 | | -| pinned | deprecated | boolean | NO | | 0 | | -| starred | | boolean | NO | | 0 | | -| ignored | Ignore updates for this thread | boolean | NO | | 0 | | -| wall | This item was posted to the wall of uid | boolean | NO | | 0 | | -| mention | | boolean | NO | | 0 | | -| pubmail | | boolean | NO | | 0 | | -| forum_mode | Deprecated | tinyint unsigned | NO | | 0 | | -| contact-id | contact.id | int unsigned | NO | | 0 | | -| unseen | post has not been seen | boolean | NO | | 1 | | -| hidden | Marker to hide the post from the user | boolean | NO | | 0 | | -| origin | item originated at this site | boolean | NO | | 0 | | -| psid | ID of the permission set of this post | int unsigned | YES | | NULL | | -| post-user-id | Id of the post-user table | int unsigned | YES | | NULL | | +| Field | Description | Type | Null | Key | Default | Extra | +| --------------- | ------------------------------------------------------------------------------------------------------- | ------------------ | ---- | --- | ------------------- | ----- | +| uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | PRI | NULL | | +| conversation-id | Id of the item-uri table entry that contains the conversation uri | int unsigned | YES | | NULL | | +| owner-id | Item owner | int unsigned | NO | | 0 | | +| author-id | Item author | int unsigned | NO | | 0 | | +| causer-id | Link to the contact table with uid=0 of the contact that caused the item creation | int unsigned | YES | | NULL | | +| network | | char(4) | NO | | | | +| created | | datetime | NO | | 0001-01-01 00:00:00 | | +| received | | datetime | NO | | 0001-01-01 00:00:00 | | +| changed | Date that something in the conversation changed, indicating clients should fetch the conversation again | datetime | NO | | 0001-01-01 00:00:00 | | +| commented | | datetime | NO | | 0001-01-01 00:00:00 | | +| uid | Owner id which owns this copy of the item | mediumint unsigned | NO | PRI | 0 | | +| pinned | deprecated | boolean | NO | | 0 | | +| starred | | boolean | NO | | 0 | | +| ignored | Ignore updates for this thread | boolean | NO | | 0 | | +| wall | This item was posted to the wall of uid | boolean | NO | | 0 | | +| mention | | boolean | NO | | 0 | | +| pubmail | | boolean | NO | | 0 | | +| forum_mode | Deprecated | tinyint unsigned | NO | | 0 | | +| contact-id | contact.id | int unsigned | NO | | 0 | | +| unseen | post has not been seen | boolean | NO | | 1 | | +| hidden | Marker to hide the post from the user | boolean | NO | | 0 | | +| origin | item originated at this site | boolean | NO | | 0 | | +| psid | ID of the permission set of this post | int unsigned | YES | | NULL | | +| post-user-id | Id of the post-user table | int unsigned | YES | | NULL | | Indexes ------------ @@ -39,6 +40,7 @@ Indexes | ----------------- | ------------------- | | PRIMARY | uid, uri-id | | uri-id | uri-id | +| conversation-id | conversation-id | | owner-id | owner-id | | author-id | author-id | | causer-id | causer-id | @@ -59,6 +61,7 @@ Foreign Keys | Field | Target Table | Target Field | |-------|--------------|--------------| | uri-id | [item-uri](help/database/db_item-uri) | id | +| conversation-id | [item-uri](help/database/db_item-uri) | id | | owner-id | [contact](help/database/db_contact) | id | | author-id | [contact](help/database/db_contact) | id | | causer-id | [contact](help/database/db_contact) | id | diff --git a/doc/database/db_post-thread.md b/doc/database/db_post-thread.md index 96fd0d4275..b90fb2ab55 100644 --- a/doc/database/db_post-thread.md +++ b/doc/database/db_post-thread.md @@ -6,29 +6,31 @@ Thread related data Fields ------ -| Field | Description | Type | Null | Key | Default | Extra | -| --------- | ------------------------------------------------------------------------------------------------------- | ------------ | ---- | --- | ------------------- | ----- | -| uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | PRI | NULL | | -| owner-id | Item owner | int unsigned | NO | | 0 | | -| author-id | Item author | int unsigned | NO | | 0 | | -| causer-id | Link to the contact table with uid=0 of the contact that caused the item creation | int unsigned | YES | | NULL | | -| network | | char(4) | NO | | | | -| created | | datetime | NO | | 0001-01-01 00:00:00 | | -| received | | datetime | NO | | 0001-01-01 00:00:00 | | -| changed | Date that something in the conversation changed, indicating clients should fetch the conversation again | datetime | NO | | 0001-01-01 00:00:00 | | -| commented | | datetime | NO | | 0001-01-01 00:00:00 | | +| Field | Description | Type | Null | Key | Default | Extra | +| --------------- | ------------------------------------------------------------------------------------------------------- | ------------ | ---- | --- | ------------------- | ----- | +| uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | PRI | NULL | | +| conversation-id | Id of the item-uri table entry that contains the conversation uri | int unsigned | YES | | NULL | | +| owner-id | Item owner | int unsigned | NO | | 0 | | +| author-id | Item author | int unsigned | NO | | 0 | | +| causer-id | Link to the contact table with uid=0 of the contact that caused the item creation | int unsigned | YES | | NULL | | +| network | | char(4) | NO | | | | +| created | | datetime | NO | | 0001-01-01 00:00:00 | | +| received | | datetime | NO | | 0001-01-01 00:00:00 | | +| changed | Date that something in the conversation changed, indicating clients should fetch the conversation again | datetime | NO | | 0001-01-01 00:00:00 | | +| commented | | datetime | NO | | 0001-01-01 00:00:00 | | Indexes ------------ -| Name | Fields | -| --------- | --------- | -| PRIMARY | uri-id | -| owner-id | owner-id | -| author-id | author-id | -| causer-id | causer-id | -| received | received | -| commented | commented | +| Name | Fields | +| --------------- | --------------- | +| PRIMARY | uri-id | +| conversation-id | conversation-id | +| owner-id | owner-id | +| author-id | author-id | +| causer-id | causer-id | +| received | received | +| commented | commented | Foreign Keys ------------ @@ -36,6 +38,7 @@ Foreign Keys | Field | Target Table | Target Field | |-------|--------------|--------------| | uri-id | [item-uri](help/database/db_item-uri) | id | +| conversation-id | [item-uri](help/database/db_item-uri) | id | | owner-id | [contact](help/database/db_contact) | id | | author-id | [contact](help/database/db_contact) | id | | causer-id | [contact](help/database/db_contact) | id | diff --git a/src/Model/Item.php b/src/Model/Item.php index 7c3eea9eb1..4142953568 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -83,7 +83,7 @@ class Item // Field list that is used to display the items const DISPLAY_FIELDLIST = [ 'uid', 'id', 'parent', 'guid', 'network', 'gravity', - 'uri-id', 'uri', 'thr-parent-id', 'thr-parent', 'parent-uri-id', 'parent-uri', + 'uri-id', 'uri', 'thr-parent-id', 'thr-parent', 'parent-uri-id', 'parent-uri', 'conversation', 'commented', 'created', 'edited', 'received', 'verb', 'object-type', 'postopts', 'plink', 'wall', 'private', 'starred', 'origin', 'parent-origin', 'title', 'body', 'language', 'content-warning', 'location', 'coord', 'app', 'rendered-hash', 'rendered-html', 'object', @@ -103,7 +103,7 @@ class Item // Field list that is used to deliver items via the protocols const DELIVER_FIELDLIST = ['uid', 'id', 'parent', 'uri-id', 'uri', 'thr-parent', 'parent-uri', 'guid', - 'parent-guid', 'received', 'created', 'edited', 'verb', 'object-type', 'object', 'target', + 'parent-guid', 'conversation', 'received', 'created', 'edited', 'verb', 'object-type', 'object', 'target', 'private', 'title', 'body', 'raw-body', 'location', 'coord', 'app', 'inform', 'deleted', 'extid', 'post-type', 'post-reason', 'gravity', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', @@ -116,7 +116,7 @@ class Item // All fields in the item table const ITEM_FIELDLIST = ['id', 'uid', 'parent', 'uri', 'parent-uri', 'thr-parent', - 'guid', 'uri-id', 'parent-uri-id', 'thr-parent-id', 'vid', + 'guid', 'uri-id', 'parent-uri-id', 'thr-parent-id', 'conversation', 'vid', 'contact-id', 'wall', 'gravity', 'extid', 'psid', 'created', 'edited', 'commented', 'received', 'changed', 'verb', 'postopts', 'plink', 'resource-id', 'event-id', 'inform', @@ -687,6 +687,11 @@ class Item $params = ['order' => ['id' => false]]; $parent = Post::selectFirst($fields, $condition, $params); + if (!DBA::isResult($parent) && ($item['thr-parent-id'] != $item['parent-uri-id'])) { + $condition = ['uri-id' => $item['parent-uri-id'], 'uid' => $item['uid']]; + $parent = Post::selectFirst($fields, $condition, $params); + } + if (!DBA::isResult($parent) && $item['origin']) { $stored = Item::storeForUserByUriId($item['thr-parent-id'], $item['uid']); Logger::info('Stored thread parent item for user', ['uri-id' => $item['thr-parent-id'], 'uid' => $item['uid'], 'stored' => $stored]); @@ -787,10 +792,13 @@ class Item // Backward compatibility: parent-uri used to be the direct parent uri. // If it is provided without a thr-parent, it probably is the old behavior. - $item['thr-parent'] = trim($item['thr-parent'] ?? $item['parent-uri'] ?? $item['uri']); - $item['parent-uri'] = $item['thr-parent']; + if (empty($item['thr-parent']) || empty($item['parent-uri'])) { + $item['thr-parent'] = trim($item['thr-parent'] ?? $item['parent-uri'] ?? $item['uri']); + $item['parent-uri'] = $item['thr-parent']; + } - $item['thr-parent-id'] = $item['parent-uri-id'] = ItemURI::getIdByURI($item['thr-parent']); + $item['thr-parent-id'] = ItemURI::getIdByURI($item['thr-parent']); + $item['parent-uri-id'] = ItemURI::getIdByURI($item['parent-uri']); // Store conversation data $item = Conversation::insert($item); @@ -966,11 +974,19 @@ class Item } else { $parent_id = 0; $parent_origin = $item['origin']; + + if ($item['wall'] && empty($item['conversation'])) { + $item['conversation'] = $item['parent-uri'] . '#context'; + } } $item['parent-uri-id'] = ItemURI::getIdByURI($item['parent-uri']); $item['thr-parent-id'] = ItemURI::getIdByURI($item['thr-parent']); + if (!empty($item['conversation']) && empty($item['conversation-id'])) { + $item['conversation-id'] = ItemURI::getIdByURI($item['conversation']); + } + // Is this item available in the global items (with uid=0)? if ($item['uid'] == 0) { $item['global'] = true; diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index b896dfa147..28192d35ba 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -280,15 +280,26 @@ class Processor $item['object-type'] = Activity\ObjectType::COMMENT; } - if (empty($activity['directmessage']) && ($activity['id'] != $activity['reply-to-id']) && !Post::exists(['uri' => $activity['reply-to-id']])) { - if (Queue::hasWorker($activity)) { - Logger::notice('There is already a worker task to dfetch the post.', ['parent' => $activity['reply-to-id']]); - return []; - } + if (!empty($activity['context'])) { + $item['conversation'] = $activity['context']; + } elseif(!empty($activity['conversation'])) { + $item['conversation'] = $activity['conversation']; + } + if (!empty($item['conversation'])) { + $conversation = Post::selectFirstThread(['uri'], ['conversation' => $item['conversation']]); + if (!empty($conversation)) { + Logger::debug('Got conversation', ['conversation' => $item['conversation'], 'parent' => $conversation]); + $item['parent-uri'] = $conversation['uri']; + } + } else { + $conversation = []; + } + + if (empty($activity['directmessage']) && ($activity['id'] != $activity['reply-to-id']) && !Post::exists(['uri' => $activity['reply-to-id']])) { $recursion_depth = $activity['recursion-depth'] ?? 0; Logger::notice('Parent not found. Try to refetch it.', ['parent' => $activity['reply-to-id'], 'recursion-depth' => $recursion_depth]); - if ($recursion_depth < 10) { + if ($recursion_depth < 10000) { $result = self::fetchMissingActivity($activity['reply-to-id'], $activity, '', Receiver::COMPLETION_AUTO); $fetch_by_worker = empty($result); } else { @@ -296,19 +307,32 @@ class Processor $fetch_by_worker = true; } + if ($fetch_by_worker && Queue::hasWorker($activity)) { + Logger::notice('There is already a worker task to fetch the post.', ['id' => $activity['id'], 'parent' => $activity['reply-to-id']]); + $fetch_by_worker = false; + if (!empty($conversation)) { + return []; + } + } + if ($fetch_by_worker) { Logger::notice('Fetching is done by worker.', ['parent' => $activity['reply-to-id'], 'recursion-depth' => $recursion_depth]); $activity['recursion-depth'] = 0; $wid = Worker::add(PRIORITY_HIGH, 'FetchMissingActivity', $activity['reply-to-id'], $activity, '', Receiver::COMPLETION_AUTO); Queue::setWorkerId($activity, $wid); - return []; + if (!empty($conversation)) { + return []; + } + } elseif (!empty($result)) { + if (($item['thr-parent'] != $result) && Post::exists(['uri' => $result])) { + $item['thr-parent'] = $result; + } } } $item['diaspora_signed_text'] = $activity['diaspora:comment'] ?? ''; - /// @todo What to do with $activity['context']? - if (empty($activity['directmessage']) && ($item['gravity'] != GRAVITY_PARENT) && !Post::exists(['uri' => $item['thr-parent']])) { + if (empty($conversation) && empty($activity['directmessage']) && ($item['gravity'] != GRAVITY_PARENT) && !Post::exists(['uri' => $item['thr-parent']])) { Logger::info('Parent not found, message will be discarded.', ['thr-parent' => $item['thr-parent']]); return []; } @@ -484,6 +508,7 @@ class Processor */ public static function createActivity(array $activity, string $verb) { + $activity['reply-to-id'] = $activity['object_id']; $item = self::createItem($activity); if (empty($item)) { return; @@ -663,10 +688,11 @@ class Processor $item['raw-body'] = $content; $item['body'] = Item::improveSharedDataInBody($item); } else { - if (empty($activity['directmessage']) && ($item['thr-parent'] != $item['uri']) && ($item['gravity'] == GRAVITY_COMMENT)) { - $parent = Post::selectFirst(['id', 'uri-id', 'private', 'author-link', 'alias'], ['uri' => $item['thr-parent']]); + $parent_uri = $item['parent-uri'] ?? $item['thr-parent']; + if (empty($activity['directmessage']) && ($parent_uri != $item['uri']) && ($item['gravity'] == GRAVITY_COMMENT)) { + $parent = Post::selectFirst(['id', 'uri-id', 'private', 'author-link', 'alias'], ['uri' => $parent_uri]); if (!DBA::isResult($parent)) { - Logger::warning('Unknown parent item.', ['uri' => $item['thr-parent']]); + Logger::warning('Unknown parent item.', ['uri' => $parent_uri]); return false; } if (($parent['private'] == Item::PRIVATE) && ($parent['private'] != Item::PRIVATE)) { @@ -1327,8 +1353,8 @@ class Processor if (empty($contact)) { Contact::update(['hub-verify' => $activity['id'], 'protocol' => Protocol::ACTIVITYPUB], ['id' => $cid]); } - Logger::notice('Follow user ' . $uid . ' from contact ' . $cid . ' with id ' . $activity['id']); + Queue::remove($activity); } /** @@ -1426,6 +1452,7 @@ class Processor Contact\User::setIsBlocked($cid, $uid, true); Logger::info('Contact blocked user', ['contact' => $cid, 'user' => $uid]); + Queue::remove($activity); } /** @@ -1450,6 +1477,7 @@ class Processor Contact\User::setIsBlocked($cid, $uid, false); Logger::info('Contact unblocked user', ['contact' => $cid, 'user' => $uid]); + Queue::remove($activity); } /** diff --git a/src/Protocol/ActivityPub/Queue.php b/src/Protocol/ActivityPub/Queue.php index d5a308b109..055a728dfb 100644 --- a/src/Protocol/ActivityPub/Queue.php +++ b/src/Protocol/ActivityPub/Queue.php @@ -140,6 +140,14 @@ class Queue $activity['entry-id'] = $entry['id']; $activity['worker-id'] = $entry['wid']; + $receivers = DBA::select('inbox-entry-receiver', ['uid'], ['queue-id' => $entry['id']]); + while ($receiver = DBA::fetch($receivers)) { + if (!in_array($receiver['uid'], $activity['receiver'])) { + $activity['receiver'][] = $receiver['uid']; + } + } + DBA::close($receivers); + if (!Receiver::routeActivities($activity, $type, $push)) { self::remove($activity); } diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 045248e629..1cbd5c9e36 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -516,6 +516,10 @@ class Receiver } } + if (($type == 'as:Add') && is_array($activity['as:object']) && (count($activity['as:object']) == 1)) { + $trust_source = false; + } + // $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); if (empty($object_data)) { diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index a9c163964e..67c0c24801 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -1515,26 +1515,6 @@ class Transmitter return $body; } - /** - * Fetches the "context" value for a givem item array from the "conversation" table - * - * @param array $item Item array - * @return string with context url - * @throws \Exception - */ - private static function fetchContextURLForItem(array $item): string - { - $conversation = DBA::selectFirst('conversation', ['conversation-href', 'conversation-uri'], ['item-uri' => $item['parent-uri']]); - if (DBA::isResult($conversation) && !empty($conversation['conversation-href'])) { - $context_uri = $conversation['conversation-href']; - } elseif (DBA::isResult($conversation) && !empty($conversation['conversation-uri'])) { - $context_uri = $conversation['conversation-uri']; - } else { - $context_uri = $item['parent-uri'] . '#context'; - } - return $context_uri; - } - /** * Returns if the post contains sensitive content ("nsfw") * @@ -1646,7 +1626,7 @@ class Transmitter $data['url'] = $link ?? $item['plink']; $data['attributedTo'] = $item['author-link']; $data['sensitive'] = self::isSensitive($item['uri-id']); - $data['context'] = self::fetchContextURLForItem($item); + $data['conversation'] = $data['context'] = $item['conversation']; if (!empty($item['title'])) { $data['name'] = BBCode::toPlaintext($item['title'], false); diff --git a/src/Worker/ExpirePosts.php b/src/Worker/ExpirePosts.php index d09376d60e..bbdfaa42c7 100644 --- a/src/Worker/ExpirePosts.php +++ b/src/Worker/ExpirePosts.php @@ -183,6 +183,7 @@ class ExpirePosts AND NOT EXISTS(SELECT `parent-uri-id` FROM `post-user` WHERE `parent-uri-id` = `item-uri`.`id`) AND NOT EXISTS(SELECT `thr-parent-id` FROM `post-user` WHERE `thr-parent-id` = `item-uri`.`id`) AND NOT EXISTS(SELECT `external-id` FROM `post-user` WHERE `external-id` = `item-uri`.`id`) + AND NOT EXISTS(SELECT `conversation-id` FROM `post-thread` WHERE `conversation-id` = `item-uri`.`id`) AND NOT EXISTS(SELECT `uri-id` FROM `mail` WHERE `uri-id` = `item-uri`.`id`) AND NOT EXISTS(SELECT `uri-id` FROM `event` WHERE `uri-id` = `item-uri`.`id`) AND NOT EXISTS(SELECT `uri-id` FROM `user-contact` WHERE `uri-id` = `item-uri`.`id`) diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index abaddc8d0a..74bcdc8161 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -1355,6 +1355,7 @@ return [ "comment" => "Thread related data", "fields" => [ "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "conversation-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the conversation uri"], "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item owner"], "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item author"], "causer-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], @@ -1366,6 +1367,7 @@ return [ ], "indexes" => [ "PRIMARY" => ["uri-id"], + "conversation-id" => ["conversation-id"], "owner-id" => ["owner-id"], "author-id" => ["author-id"], "causer-id" => ["causer-id"], @@ -1434,6 +1436,7 @@ return [ "comment" => "Thread related data per user", "fields" => [ "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "conversation-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the conversation uri"], "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item owner"], "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item author"], "causer-id" => ["type" => "int unsigned", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"], @@ -1460,6 +1463,7 @@ return [ "indexes" => [ "PRIMARY" => ["uid", "uri-id"], "uri-id" => ["uri-id"], + "conversation-id" => ["conversation-id"], "owner-id" => ["owner-id"], "author-id" => ["author-id"], "causer-id" => ["causer-id"], diff --git a/static/dbview.config.php b/static/dbview.config.php index 040a9ebc30..0c91016d49 100644 --- a/static/dbview.config.php +++ b/static/dbview.config.php @@ -70,6 +70,8 @@ "parent-uri-id" => ["post-user", "parent-uri-id"], "thr-parent" => ["thr-parent-item-uri", "uri"], "thr-parent-id" => ["post-user", "thr-parent-id"], + "conversation" => ["conversation-item-uri", "uri"], + "conversation-id" => ["post-thread-user", "conversation-id"], "guid" => ["item-uri", "guid"], "wall" => ["post-user", "wall"], "gravity" => ["post-user", "gravity"], @@ -220,6 +222,7 @@ LEFT JOIN `item-uri` ON `item-uri`.`id` = `post-user`.`uri-id` LEFT JOIN `item-uri` AS `thr-parent-item-uri` ON `thr-parent-item-uri`.`id` = `post-user`.`thr-parent-id` LEFT JOIN `item-uri` AS `parent-item-uri` ON `parent-item-uri`.`id` = `post-user`.`parent-uri-id` + LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread-user`.`conversation-id` LEFT JOIN `item-uri` AS `external-item-uri` ON `external-item-uri`.`id` = `post-user`.`external-id` LEFT JOIN `verb` ON `verb`.`id` = `post-user`.`vid` LEFT JOIN `event` ON `event`.`id` = `post-user`.`event-id` @@ -243,6 +246,8 @@ "parent-uri-id" => ["post-user", "parent-uri-id"], "thr-parent" => ["thr-parent-item-uri", "uri"], "thr-parent-id" => ["post-user", "thr-parent-id"], + "conversation" => ["conversation-item-uri", "uri"], + "conversation-id" => ["post-thread-user", "conversation-id"], "guid" => ["item-uri", "guid"], "wall" => ["post-thread-user", "wall"], "gravity" => ["post-user", "gravity"], @@ -392,6 +397,7 @@ LEFT JOIN `item-uri` ON `item-uri`.`id` = `post-thread-user`.`uri-id` LEFT JOIN `item-uri` AS `thr-parent-item-uri` ON `thr-parent-item-uri`.`id` = `post-user`.`thr-parent-id` LEFT JOIN `item-uri` AS `parent-item-uri` ON `parent-item-uri`.`id` = `post-user`.`parent-uri-id` + LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread-user`.`conversation-id` LEFT JOIN `item-uri` AS `external-item-uri` ON `external-item-uri`.`id` = `post-user`.`external-id` LEFT JOIN `verb` ON `verb`.`id` = `post-user`.`vid` LEFT JOIN `event` ON `event`.`id` = `post-user`.`event-id` @@ -411,6 +417,8 @@ "parent-uri-id" => ["post", "parent-uri-id"], "thr-parent" => ["thr-parent-item-uri", "uri"], "thr-parent-id" => ["post", "thr-parent-id"], + "conversation" => ["conversation-item-uri", "uri"], + "conversation-id" => ["post-thread", "conversation-id"], "guid" => ["item-uri", "guid"], "gravity" => ["post", "gravity"], "extid" => ["external-item-uri", "uri"], @@ -530,6 +538,7 @@ LEFT JOIN `item-uri` ON `item-uri`.`id` = `post`.`uri-id` LEFT JOIN `item-uri` AS `thr-parent-item-uri` ON `thr-parent-item-uri`.`id` = `post`.`thr-parent-id` LEFT JOIN `item-uri` AS `parent-item-uri` ON `parent-item-uri`.`id` = `post`.`parent-uri-id` + LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread`.`conversation-id` LEFT JOIN `item-uri` AS `external-item-uri` ON `external-item-uri`.`id` = `post`.`external-id` LEFT JOIN `verb` ON `verb`.`id` = `post`.`vid` LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `post`.`uri-id` @@ -546,6 +555,8 @@ "parent-uri-id" => ["post", "parent-uri-id"], "thr-parent" => ["thr-parent-item-uri", "uri"], "thr-parent-id" => ["post", "thr-parent-id"], + "conversation" => ["conversation-item-uri", "uri"], + "conversation-id" => ["post-thread", "conversation-id"], "guid" => ["item-uri", "guid"], "gravity" => ["post", "gravity"], "extid" => ["external-item-uri", "uri"], @@ -665,6 +676,7 @@ LEFT JOIN `item-uri` ON `item-uri`.`id` = `post-thread`.`uri-id` LEFT JOIN `item-uri` AS `thr-parent-item-uri` ON `thr-parent-item-uri`.`id` = `post`.`thr-parent-id` LEFT JOIN `item-uri` AS `parent-item-uri` ON `parent-item-uri`.`id` = `post`.`parent-uri-id` + LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread`.`conversation-id` LEFT JOIN `item-uri` AS `external-item-uri` ON `external-item-uri`.`id` = `post`.`external-id` LEFT JOIN `verb` ON `verb`.`id` = `post`.`vid` LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `post-thread`.`uri-id`