From 67a67200a769f2e94c8d341453f32acccf217092 Mon Sep 17 00:00:00 2001 From: Michael <heluecht@pirati.ca> Date: Mon, 13 Apr 2020 23:54:28 +0000 Subject: [PATCH] Storing mentions in Diaspora and AP --- src/Protocol/ActivityPub/Processor.php | 50 ++++++++++++++++++++++++ src/Protocol/Diaspora.php | 53 ++++++++++++++++++++++++++ static/dbstructure.config.php | 15 +++++++- 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 7a8179b05..cf1fd114c 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -32,6 +32,7 @@ use Friendica\Model\Contact; use Friendica\Model\Conversation; use Friendica\Model\Event; use Friendica\Model\Item; +use Friendica\Model\ItemURI; use Friendica\Model\Mail; use Friendica\Model\Term; use Friendica\Model\User; @@ -403,6 +404,8 @@ class Processor $item['tag'] = self::constructTagString($activity['tags'], $activity['sensitive']); + self::storeTags($item['uri-id'], $activity['tags'], $activity['sensitive']); + $item['location'] = $activity['location']; if (!empty($item['latitude']) && !empty($item['longitude'])) { @@ -496,6 +499,8 @@ class Processor $item['edited'] = DateTimeFormat::utc($activity['updated']); $item['guid'] = $activity['diaspora:guid'] ?: $activity['sc:identifier'] ?: self::getGUIDByURL($item['uri']); + $item['uri-id'] = ItemURI::insert(['uri' => $item['uri'], 'guid' => $item['guid']]); + $item = self::processContent($activity, $item); if (empty($item)) { return; @@ -571,6 +576,51 @@ class Processor } } + private static function storeTags(int $uriid, array $tags = null, $sensitive = false) + { + // Make sure to delete all existing tags (can happen when called via the update functionality) + DBA::delete('tag', ['uri-id' => $uriid]); + + foreach ($tags as $tag) { + if (empty($tag['name']) || empty($tag['type']) || !in_array($tag['type'], ['Mention', 'Hashtag'])) { + continue; + } + + $fields = ['uri-id' => $uriid, 'name' => $tag['name']]; + + if ($tag['type'] == 'Mention') { + $fields['type'] = Term::MENTION; + + if (substr($fields['name'], 0, 1) == Term::TAG_CHARACTER[Term::MENTION]) { + $fields['name'] = substr($fields['name'], 1); + } elseif (substr($fields['name'], 0, 1) == Term::TAG_CHARACTER[Term::EXCLUSIVE_MENTION]) { + $fields['type'] = Term::EXCLUSIVE_MENTION; + $fields['name'] = substr($fields['name'], 1); + } elseif (substr($fields['name'], 0, 1) == Term::TAG_CHARACTER[Term::IMPLICIT_MENTION]) { + $fields['type'] = Term::IMPLICIT_MENTION; + $fields['name'] = substr($fields['name'], 1); + } + } elseif ($tag['type'] == 'Hashtag') { + $fields['type'] = Term::HASHTAG; + if (substr($fields['name'], 0, 1) == Term::TAG_CHARACTER[Term::HASHTAG]) { + $fields['name'] = substr($fields['name'], 1); + } + } + + if (empty($fields['name'])) { + continue; + } + + if (!empty($tag['href'] && ($tag['href'] != $tag['name']))) { + $fields['url'] = $tag['href']; + } + + DBA::insert('tag', $fields, true); + + Logger::info('Got Tag', ['uriid' => $uriid, 'tag' => $tag, 'sensitive' => $sensitive, 'fields' => $fields]); + } + } + /** * Creates an mail post * diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 8bb407ebd..96c7c7fe1 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -35,6 +35,7 @@ use Friendica\Model\Contact; use Friendica\Model\Conversation; use Friendica\Model\GContact; use Friendica\Model\Item; +use Friendica\Model\ItemURI; use Friendica\Model\ItemDeliveryData; use Friendica\Model\Mail; use Friendica\Model\Profile; @@ -1808,6 +1809,47 @@ class Diaspora return false; } + private static function storeMentions(int $uriid, string $text) + { + preg_match_all('/([@!]){(?:([^}]+?); ?)?([^} ]+)}/', $text, $matches, PREG_SET_ORDER); + if (empty($matches)) { + return; + } + + /* + * Matching values for the preg match + * [1] = mention type (@ or !) + * [2] = name (optional) + * [3] = profile URL + */ + + foreach ($matches as $match) { + if (empty($match)) { + continue; + } + + $person = self::personByHandle($match[3]); + if (empty($person)) { + continue; + } + + $fields = ['uri-id' => $uriid, 'name' => $person['addr'], 'url' => $person['url']]; + + if ($match[1] == Term::TAG_CHARACTER[Term::MENTION]) { + $fields['type'] = Term::MENTION; + } elseif ($match[1] == Term::TAG_CHARACTER[Term::EXCLUSIVE_MENTION]) { + $fields['type'] = Term::EXCLUSIVE_MENTION; + } elseif ($match[1] == Term::TAG_CHARACTER[Term::IMPLICIT_MENTION]) { + $fields['type'] = Term::IMPLICIT_MENTION; + } else { + continue; + } + + DBA::insert('tag', $fields, true); + Logger::info('Stored mention', ['uriid' => $uriid, 'match' => $match, 'fields' => $fields]); + } + } + /** * Processes an incoming comment * @@ -1878,6 +1920,7 @@ class Diaspora $datarray["guid"] = $guid; $datarray["uri"] = self::getUriFromGuid($author, $guid); + $datarray['uri-id'] = ItemURI::insert(['uri' => $datarray['uri'], 'guid' => $datarray['guid']]); $datarray["verb"] = Activity::POST; $datarray["gravity"] = GRAVITY_COMMENT; @@ -1896,6 +1939,9 @@ class Diaspora $datarray["changed"] = $datarray["created"] = $datarray["edited"] = $created_at; $datarray["plink"] = self::plink($author, $guid, $parent_item['guid']); + + self::storeMentions($datarray['uri-id'], $text); + $body = Markdown::toBBCode($text); $datarray["body"] = self::replacePeopleGuid($body, $person["url"]); @@ -2642,6 +2688,7 @@ class Diaspora $datarray['guid'] = $parent['guid'] . '-' . $guid; $datarray['uri'] = self::getUriFromGuid($author, $datarray['guid']); + $datarray['parent-uri'] = $parent['uri']; $datarray['verb'] = $datarray['body'] = Activity::ANNOUNCE; @@ -2716,6 +2763,7 @@ class Diaspora $datarray["guid"] = $guid; $datarray["uri"] = $datarray["parent-uri"] = self::getUriFromGuid($author, $guid); + $datarray['uri-id'] = ItemURI::insert(['uri' => $datarray['uri'], 'guid' => $datarray['guid']]); $datarray["verb"] = Activity::POST; $datarray["gravity"] = GRAVITY_PARENT; @@ -2723,6 +2771,8 @@ class Diaspora $datarray["protocol"] = Conversation::PARCEL_DIASPORA; $datarray["source"] = $xml; + /// @todo Copy tag data from original post + $prefix = share_header( $original_item["author-name"], $original_item["author-link"], @@ -2959,6 +3009,7 @@ class Diaspora $datarray["guid"] = $guid; $datarray["uri"] = $datarray["parent-uri"] = self::getUriFromGuid($author, $guid); + $datarray['uri-id'] = ItemURI::insert(['uri' => $datarray['uri'], 'guid' => $datarray['guid']]); $datarray["verb"] = Activity::POST; $datarray["gravity"] = GRAVITY_PARENT; @@ -2966,6 +3017,8 @@ class Diaspora $datarray["protocol"] = Conversation::PARCEL_DIASPORA; $datarray["source"] = $xml; + self::storeMentions($datarray['uri-id'], $text); + $datarray["body"] = self::replacePeopleGuid($body, $contact["url"]); if ($provider_display_name != "") { diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 94d5a3602..110842cbc 100755 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -51,7 +51,7 @@ use Friendica\Database\DBA; if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1338); + define('DB_UPDATE_VERSION', 1339); } return [ @@ -1292,6 +1292,19 @@ return [ "guid" => ["guid(64)"], ] ], + "tag" => [ + "comment" => "item tags and mentions", + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "relation" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "comment" => ""], + "name" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "primary" => "1", "comment" => ""], + "url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""] + ], + "indexes" => [ + "PRIMARY" => ["uri-id", "type", "name"], + "type_name" => ["type", "name"] + ] + ], "thread" => [ "comment" => "Thread related data", "fields" => [