Merge pull request #8576 from annando/new-participation

Diaspora participations are now stored as activities
This commit is contained in:
Hypolite Petovan 2020-05-05 09:29:04 -04:00 committed by GitHub
commit df7eb7fcc5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 65 deletions

View file

@ -1,6 +1,6 @@
-- ------------------------------------------ -- ------------------------------------------
-- Friendica 2020.06-dev (Red Hot Poker) -- 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 `uid_eventid` (`uid`,`event-id`),
INDEX `icid` (`icid`), INDEX `icid` (`icid`),
INDEX `iaid` (`iaid`), 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'; ) 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 `contact` ON `contact`.`uid` = `user`.`uid` AND `contact`.`self`
INNER JOIN `profile` ON `profile`.`uid` = `user`.`uid`; 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 -- VIEW pending-view
-- --
@ -1577,6 +1562,27 @@ CREATE VIEW `pending-view` AS SELECT
INNER JOIN `contact` ON `register`.`uid` = `contact`.`uid` INNER JOIN `contact` ON `register`.`uid` = `contact`.`uid`
INNER JOIN `user` ON `register`.`uid` = `user`.`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 -- VIEW workerqueue-view
-- --

View file

@ -252,19 +252,25 @@ class Diaspora
* One of the parameters is a contact array. * One of the parameters is a contact array.
* This is done to avoid duplicates. * This is done to avoid duplicates.
* *
* @param integer $thread The id of the thread * @param array $parent The parent post
* @param array $contacts The previously fetched contacts * @param array $contacts The previously fetched contacts
* *
* @return array of relay servers * @return array of relay servers
* @throws \Exception * @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)) { $items = Item::select(['author-id'], ['parent' => $parent['id']], ['group_by' => ['author-id']]);
if (empty($contact['protocol'])) { while ($item = DBA::fetch($items)) {
$contact['protocol'] = $contact['network']; $contact = DBA::selectFirst('contact', ['id', 'url', 'name', 'protocol', 'batch', 'network'],
['id' => $item['author-id']]);
if (!DBA::isResult($contact)) {
// Shouldn't happen
continue;
} }
$exists = false; $exists = false;
@ -275,11 +281,11 @@ class Diaspora
} }
if (!$exists) { if (!$exists) {
Logger::info('Add participant to receiver list', ['item' => $parent['guid'], 'participant' => $contact['url']]);
$contacts[] = $contact; $contacts[] = $contact;
} }
} }
DBA::close($items);
DBA::close($participation);
return $contacts; return $contacts;
} }
@ -2251,18 +2257,32 @@ class Diaspora
* @param array $importer Array of the importer user * @param array $importer Array of the importer user
* @param object $data The message object * @param object $data The message object
* *
* @return bool always true * @return bool success
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException * @throws \ImagickException
*/ */
private static function receiveParticipation(array $importer, $data) private static function receiveParticipation(array $importer, $data)
{ {
$author = strtolower(Strings::escapeTags(XML::unescape($data->author))); $author = strtolower(Strings::escapeTags(XML::unescape($data->author)));
$guid = Strings::escapeTags(XML::unescape($data->guid));
$parent_guid = Strings::escapeTags(XML::unescape($data->parent_guid)); $parent_guid = Strings::escapeTags(XML::unescape($data->parent_guid));
$contact_id = Contact::getIdForURL($author); $contact = self::allowedContactByHandle($importer, $author, true);
if (!$contact_id) { if (!$contact) {
Logger::log('Contact not found: '.$author); 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; return false;
} }
@ -2272,35 +2292,47 @@ class Diaspora
return false; return false;
} }
$item = Item::selectFirst(['id'], ['guid' => $parent_guid, 'origin' => true, 'private' => [Item::PUBLIC, Item::UNLISTED]]); $author_contact = self::authorContactByUrl($contact, $person, $importer["uid"]);
if (!DBA::isResult($item)) {
Logger::log('Item not found, no origin or private: '.$parent_guid);
return false;
}
$author_parts = explode('@', $author); // Store participation
if (isset($author_parts[1])) { $datarray = [];
$server = $author_parts[1];
} else {
// Should never happen
$server = $author;
}
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])) { $datarray["uid"] = $importer["uid"];
DBA::insert('participation', ['iid' => $item['id'], 'cid' => $contact_id, 'fid' => $person['id'], 'server' => $server]); $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 // 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)) { while ($comment = Item::fetch($comments)) {
if ($comment['id'] == $comment['parent']) { if ($comment['id'] == $comment['parent']) {
continue; continue;
} }
Logger::info('Deliver participation', ['item' => $comment['id'], 'contact' => $contact_id]); Logger::info('Deliver participation', ['item' => $comment['id'], 'contact' => $author_contact["cid"]]);
if (Worker::add(PRIORITY_HIGH, 'Delivery', Delivery::POST, $comment['id'], $contact_id)) { if (Worker::add(PRIORITY_HIGH, 'Delivery', Delivery::POST, $comment['id'], $author_contact["cid"])) {
ItemDeliveryData::incrementQueueCount($comment['id'], 1); ItemDeliveryData::incrementQueueCount($comment['id'], 1);
} }
} }

View file

@ -441,7 +441,7 @@ class Notifier
// Fetch the participation list // Fetch the participation list
// The function will ensure that there are no duplicates // 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. // 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. // Don't send community posts to the relay. Forum posts via the Diaspora protocol are looking ugly.

View file

@ -186,20 +186,6 @@ return [
INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid` AND `contact`.`self` INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid` AND `contact`.`self`
INNER JOIN `profile` ON `profile`.`uid` = `user`.`uid`" 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" => [ "pending-view" => [
"fields" => [ "fields" => [
"id" => ["register", "id"], "id" => ["register", "id"],