diff --git a/database.sql b/database.sql index a68f3d4e5a..6c4758c249 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2020.06-dev (Red Hot Poker) --- DB_UPDATE_VERSION 1341 +-- DB_UPDATE_VERSION 1343 -- ------------------------------------------ @@ -666,7 +666,8 @@ CREATE TABLE IF NOT EXISTS `item` ( INDEX `uid_eventid` (`uid`,`event-id`), INDEX `icid` (`icid`), INDEX `iaid` (`iaid`), - INDEX `psid_wall` (`psid`,`wall`) + INDEX `psid_wall` (`psid`,`wall`), + INDEX `uri-id` (`uri-id`) ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Structure for all posts'; -- @@ -1539,22 +1540,6 @@ CREATE VIEW `owner-view` AS SELECT INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid` AND `contact`.`self` INNER JOIN `profile` ON `profile`.`uid` = `user`.`uid`; --- --- VIEW participation-view --- -DROP VIEW IF EXISTS `participation-view`; -CREATE VIEW `participation-view` AS SELECT - `participation`.`iid` AS `iid`, - `contact`.`id` AS `id`, - `contact`.`url` AS `url`, - `contact`.`name` AS `name`, - `contact`.`protocol` AS `protocol`, - CASE `contact`.`batch` WHEN '' THEN `fcontact`.`batch` ELSE `contact`.`batch` END AS `batch`, - CASE `fcontact`.`network` WHEN '' THEN `contact`.`network` ELSE `fcontact`.`network` END AS `network` - FROM `participation` - INNER JOIN `contact` ON `contact`.`id` = `participation`.`cid` AND NOT `contact`.`archive` - INNER JOIN `fcontact` ON `fcontact`.`id` = `participation`.`fid`; - -- -- VIEW pending-view -- @@ -1577,6 +1562,27 @@ CREATE VIEW `pending-view` AS SELECT INNER JOIN `contact` ON `register`.`uid` = `contact`.`uid` INNER JOIN `user` ON `register`.`uid` = `user`.`uid`; +-- +-- VIEW tag-search-view +-- +DROP VIEW IF EXISTS `tag-search-view`; +CREATE VIEW `tag-search-view` AS SELECT + `post-tag`.`uri-id` AS `uri-id`, + `item`.`id` AS `iid`, + `item`.`uri` AS `uri`, + `item`.`guid` AS `guid`, + `item`.`uid` AS `uid`, + `item`.`private` AS `private`, + `item`.`wall` AS `wall`, + `item`.`origin` AS `origin`, + `item`.`gravity` AS `gravity`, + `item`.`received` AS `received`, + `tag`.`name` AS `name` + FROM `post-tag` + INNER JOIN `tag` ON `tag`.`id` = `post-tag`.`tid` + INNER JOIN `item` ON `item`.`uri-id` = `post-tag`.`uri-id` + WHERE `post-tag`.`type` = 1; + -- -- VIEW workerqueue-view -- diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index c8d218ac21..a0047d008a 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -252,19 +252,25 @@ class Diaspora * One of the parameters is a contact array. * This is done to avoid duplicates. * - * @param integer $thread The id of the thread - * @param array $contacts The previously fetched contacts + * @param array $parent The parent post + * @param array $contacts The previously fetched contacts * * @return array of relay servers * @throws \Exception */ - public static function participantsForThread($thread, array $contacts) + public static function participantsForThread(array $parent, array $contacts) { - $participation = DBA::select('participation-view', [], ['iid' => $thread]); + if (!in_array($parent['private'], [Item::PUBLIC, Item::UNLISTED])) { + return $contacts; + } - while ($contact = DBA::fetch($participation)) { - if (empty($contact['protocol'])) { - $contact['protocol'] = $contact['network']; + $items = Item::select(['author-id'], ['parent' => $parent['id']], ['group_by' => ['author-id']]); + while ($item = DBA::fetch($items)) { + $contact = DBA::selectFirst('contact', ['id', 'url', 'name', 'protocol', 'batch', 'network'], + ['id' => $item['author-id']]); + if (!DBA::isResult($contact)) { + // Shouldn't happen + continue; } $exists = false; @@ -275,11 +281,11 @@ class Diaspora } if (!$exists) { + Logger::info('Add participant to receiver list', ['item' => $parent['guid'], 'participant' => $contact['url']]); $contacts[] = $contact; } } - - DBA::close($participation); + DBA::close($items); return $contacts; } @@ -2251,18 +2257,32 @@ class Diaspora * @param array $importer Array of the importer user * @param object $data The message object * - * @return bool always true + * @return bool success * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ private static function receiveParticipation(array $importer, $data) { $author = strtolower(Strings::escapeTags(XML::unescape($data->author))); + $guid = Strings::escapeTags(XML::unescape($data->guid)); $parent_guid = Strings::escapeTags(XML::unescape($data->parent_guid)); - $contact_id = Contact::getIdForURL($author); - if (!$contact_id) { - Logger::log('Contact not found: '.$author); + $contact = self::allowedContactByHandle($importer, $author, true); + if (!$contact) { + return false; + } + + if (self::messageExists($importer["uid"], $guid)) { + return true; + } + + $parent_item = self::parentItem($importer["uid"], $parent_guid, $author, $contact); + if (!$parent_item) { + return false; + } + + if (!in_array($parent_item['private'], [Item::PUBLIC, Item::UNLISTED])) { + Logger::info('Item is not public, participation is ignored', ['parent_guid' => $parent_guid, 'guid' => $guid, 'author' => $author]); return false; } @@ -2272,35 +2292,47 @@ class Diaspora return false; } - $item = Item::selectFirst(['id'], ['guid' => $parent_guid, 'origin' => true, 'private' => [Item::PUBLIC, Item::UNLISTED]]); - if (!DBA::isResult($item)) { - Logger::log('Item not found, no origin or private: '.$parent_guid); - return false; - } + $author_contact = self::authorContactByUrl($contact, $person, $importer["uid"]); - $author_parts = explode('@', $author); - if (isset($author_parts[1])) { - $server = $author_parts[1]; - } else { - // Should never happen - $server = $author; - } + // Store participation + $datarray = []; - Logger::log('Received participation for ID: '.$item['id'].' - Contact: '.$contact_id.' - Server: '.$server, Logger::DEBUG); + $datarray["protocol"] = Conversation::PARCEL_DIASPORA; - if (!DBA::exists('participation', ['iid' => $item['id'], 'server' => $server])) { - DBA::insert('participation', ['iid' => $item['id'], 'cid' => $contact_id, 'fid' => $person['id'], 'server' => $server]); - } + $datarray["uid"] = $importer["uid"]; + $datarray["contact-id"] = $author_contact["cid"]; + $datarray["network"] = $author_contact["network"]; + + $datarray["owner-link"] = $datarray["author-link"] = $person["url"]; + $datarray["owner-id"] = $datarray["author-id"] = Contact::getIdForURL($person["url"], 0); + + $datarray["guid"] = $guid; + $datarray["uri"] = self::getUriFromGuid($author, $guid); + + $datarray["verb"] = Activity::FOLLOW; + $datarray["gravity"] = GRAVITY_ACTIVITY; + $datarray["parent-uri"] = $parent_item["uri"]; + + $datarray["object-type"] = Activity\ObjectType::NOTE; + + $datarray["body"] = Activity::FOLLOW; + + // Diaspora doesn't provide a date for a participation + $datarray["changed"] = $datarray["created"] = $datarray["edited"] = DateTimeFormat::utcNow(); + + $message_id = Item::insert($datarray); + + Logger::info('Participation stored', ['id' => $message_id, 'guid' => $guid, 'parent_guid' => $parent_guid, 'author' => $author]); // Send all existing comments and likes to the requesting server - $comments = Item::select(['id', 'parent', 'verb', 'self'], ['parent' => $item['id']]); + $comments = Item::select(['id', 'parent', 'verb', 'self'], ['parent' => $parent_item['id']]); while ($comment = Item::fetch($comments)) { if ($comment['id'] == $comment['parent']) { continue; } - Logger::info('Deliver participation', ['item' => $comment['id'], 'contact' => $contact_id]); - if (Worker::add(PRIORITY_HIGH, 'Delivery', Delivery::POST, $comment['id'], $contact_id)) { + Logger::info('Deliver participation', ['item' => $comment['id'], 'contact' => $author_contact["cid"]]); + if (Worker::add(PRIORITY_HIGH, 'Delivery', Delivery::POST, $comment['id'], $author_contact["cid"])) { ItemDeliveryData::incrementQueueCount($comment['id'], 1); } } diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index 35a228fce1..c9a328e4c0 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -441,7 +441,7 @@ class Notifier // Fetch the participation list // The function will ensure that there are no duplicates - $relay_list = Diaspora::participantsForThread($target_id, $relay_list); + $relay_list = Diaspora::participantsForThread($parent, $relay_list); // Add the relay to the list, avoid duplicates. // Don't send community posts to the relay. Forum posts via the Diaspora protocol are looking ugly. diff --git a/static/dbview.config.php b/static/dbview.config.php index 0f0d691085..13408d27a9 100755 --- a/static/dbview.config.php +++ b/static/dbview.config.php @@ -186,20 +186,6 @@ return [ INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid` AND `contact`.`self` INNER JOIN `profile` ON `profile`.`uid` = `user`.`uid`" ], - "participation-view" => [ - "fields" => [ - "iid" => ["participation", "iid"], - "id" => ["contact", "id"], - "url" => ["contact", "url"], - "name" => ["contact", "name"], - "protocol" => ["contact", "protocol"], - "batch" => "CASE `contact`.`batch` WHEN '' THEN `fcontact`.`batch` ELSE `contact`.`batch` END", - "network" => "CASE `fcontact`.`network` WHEN '' THEN `contact`.`network` ELSE `fcontact`.`network` END", - ], - "query" => "FROM `participation` - INNER JOIN `contact` ON `contact`.`id` = `participation`.`cid` AND NOT `contact`.`archive` - INNER JOIN `fcontact` ON `fcontact`.`id` = `participation`.`fid`" - ], "pending-view" => [ "fields" => [ "id" => ["register", "id"],