]> git.mxchange.org Git - friendica.git/blobdiff - src/Model/Post/Engagement.php
Merge remote-tracking branch 'upstream/2023.09-rc' into user-defined-channels
[friendica.git] / src / Model / Post / Engagement.php
index 0e284bd41d292921112f3b226c4131dc21fc4366..9ffd48aa004250693db3785c066d3570b9724c86 100644 (file)
@@ -21,6 +21,7 @@
 
 namespace Friendica\Model\Post;
 
+use Friendica\Content\Text\BBCode;
 use Friendica\Core\Logger;
 use Friendica\Core\Protocol;
 use Friendica\Database\Database;
@@ -29,9 +30,12 @@ use Friendica\DI;
 use Friendica\Model\Contact;
 use Friendica\Model\Item;
 use Friendica\Model\Post;
+use Friendica\Model\Tag;
 use Friendica\Model\Verb;
 use Friendica\Protocol\Activity;
+use Friendica\Protocol\Relay;
 use Friendica\Util\DateTimeFormat;
+use Friendica\Util\Strings;
 
 // Channel
 
@@ -45,28 +49,16 @@ class Engagement
         */
        public static function storeFromItem(array $item)
        {
-               if (!in_array($item['network'], Protocol::FEDERATED)) {
-                       Logger::debug('No federated network', ['uri-id' => $item['uri-id'], 'parent-uri-id' => $item['parent-uri-id'], 'network' => $item['network']]);
-                       return;
-               }
-
-               if (($item['uid'] != 0) && ($item['gravity'] == Item::GRAVITY_COMMENT)) {
-                       Logger::debug('Non public comments are not stored', ['uri-id' => $item['uri-id'], 'parent-uri-id' => $item['parent-uri-id'], 'uid' => $item['uid']]);
-                       return;
-               }
-
                if (in_array($item['verb'], [Activity::FOLLOW, Activity::VIEW, Activity::READ])) {
                        Logger::debug('Technical activities are not stored', ['uri-id' => $item['uri-id'], 'parent-uri-id' => $item['parent-uri-id'], 'verb' => $item['verb']]);
                        return;
                }
 
-               $parent = Post::selectFirst(['created', 'owner-id', 'uid', 'private', 'contact-contact-type', 'language'], ['uri-id' => $item['parent-uri-id']]);
-               if ($parent['private'] != Item::PUBLIC) {
-                       Logger::debug('Non public posts are not stored', ['uri-id' => $item['uri-id'], 'parent-uri-id' => $item['parent-uri-id'], 'uid' => $parent['uid'], 'private' => $parent['private']]);
-                       return;
-               }
+               $parent = Post::selectFirst(['uri-id', 'created', 'author-id', 'owner-id', 'uid', 'private', 'contact-contact-type', 'language', 'network',
+                       'title', 'content-warning', 'body', 'author-contact-type', 'author-nick', 'author-addr', 'owner-contact-type', 'owner-nick', 'owner-addr'],
+                       ['uri-id' => $item['parent-uri-id']]);
 
-               if ($parent['created'] < DateTimeFormat::utc('now - ' . DI::config()->get('channel', 'engagement_hours') . ' hour')) {
+               if ($parent['created'] < self::getCreationDateLimit(false)) {
                        Logger::debug('Post is too old', ['uri-id' => $item['uri-id'], 'parent-uri-id' => $item['parent-uri-id'], 'created' => $parent['created']]);
                        return;
                }
@@ -77,6 +69,16 @@ class Engagement
                        $store = Contact::hasFollowers($parent['owner-id']);
                }
 
+               if (!$store) {
+                       $tagList = Relay::getSubscribedTags();
+                       foreach (array_column(Tag::getByURIId($item['parent-uri-id'], [Tag::HASHTAG]), 'name') as $tag) {
+                               if (in_array($tag, $tagList)) {
+                                       $store = true;
+                                       break;
+                               }
+                       }
+               }
+
                $mediatype = self::getMediaType($item['parent-uri-id']);
 
                if (!$store) {
@@ -89,7 +91,9 @@ class Engagement
                        'contact-type' => $parent['contact-contact-type'],
                        'media-type'   => $mediatype,
                        'language'     => $parent['language'],
+                       'searchtext'   => self::getSearchText($parent),
                        'created'      => $parent['created'],
+                       'restricted'   => !in_array($item['network'], Protocol::FEDERATED) || ($parent['private'] != Item::PUBLIC),
                        'comments'     => DBA::count('post', ['parent-uri-id' => $item['parent-uri-id'], 'gravity' => Item::GRAVITY_COMMENT]),
                        'activities'   => DBA::count('post', [
                                "`parent-uri-id` = ? AND `gravity` = ? AND NOT `vid` IN (?, ?, ?)",
@@ -98,13 +102,76 @@ class Engagement
                        ])
                ];
                if (!$store && ($engagement['comments'] == 0) && ($engagement['activities'] == 0)) {
-                       Logger::debug('No media, follower, comments or activities. Engagement not stored', ['fields' => $engagement]);
+                       Logger::debug('No media, follower, subscribed tags, comments or activities. Engagement not stored', ['fields' => $engagement]);
                        return;
                }
                $ret = DBA::insert('post-engagement', $engagement, Database::INSERT_UPDATE);
                Logger::debug('Engagement stored', ['fields' => $engagement, 'ret' => $ret]);
        }
 
+       private static function getSearchText(array $item): string
+       {
+               $body = '[nosmile]network:' . $item['network'];
+
+               switch ($item['private']) {
+                       case Item::PUBLIC:
+                               $body .= ' visibility:public';
+                               break;
+                       case Item::UNLISTED:
+                               $body .= ' visibility:unlisted';
+                               break;
+                       case Item::PRIVATE:
+                               $body .= ' visibility:private';
+                               break;
+               }
+
+               if ($item['author-contact-type'] == Contact::TYPE_COMMUNITY) {
+                       $body .= ' group:' . $item['author-nick'] . ' group:' . $item['author-addr'];
+               } elseif (in_array($item['author-contact-type'], [Contact::TYPE_PERSON, Contact::TYPE_NEWS, Contact::TYPE_ORGANISATION])) {
+                       $body .= ' from:' . $item['author-nick'] . ' from:' . $item['author-addr'];
+               }
+
+               if ($item['author-id'] !=  $item['owner-id']) {
+                       if ($item['owner-contact-type'] == Contact::TYPE_COMMUNITY) {
+                               $body .= ' group:' . $item['owner-nick'] . ' group:' . $item['owner-addr'];
+                       } elseif (in_array($item['owner-contact-type'], [Contact::TYPE_PERSON, Contact::TYPE_NEWS, Contact::TYPE_ORGANISATION])) {
+                               $body .= ' from:' . $item['owner-nick'] . ' from:' . $item['owner-addr'];
+                       }
+               }
+
+               foreach (Tag::getByURIId($item['uri-id'], [Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION, Tag::AUDIENCE]) as $tag) {
+                       $contact = Contact::getByURL($tag['name'], false, ['nick', 'addr', 'contact-type']);
+                       if (empty($contact)) {
+                               continue;
+                       }
+
+                       if (($contact['contact-type'] == Contact::TYPE_COMMUNITY) && !strpos($body, 'group:' . $contact['addr'])) {
+                               $body .= ' group:' . $contact['nick'] . ' group:' . $contact['addr'];
+                       } elseif (in_array($contact['contact-type'], [Contact::TYPE_PERSON, Contact::TYPE_NEWS, Contact::TYPE_ORGANISATION])) {
+                               $body .= ' to:' . $contact['nick'] . ' to:' . $contact['addr'];
+                       }
+               }
+
+               foreach (Tag::getByURIId($item['uri-id'], [Tag::HASHTAG]) as $tag) {
+                       $body .= ' tag:' . $tag['name'];
+               }
+
+               $body .= ' ' . $item['title'] . ' ' . $item['content-warning'] . ' ' . $item['body'];
+
+               $body = preg_replace("~\[url\=.*\]https?:.*\[\/url\]~", '', $body);
+
+               $body = Post\Media::addAttachmentsToBody($item['uri-id'], $body, [Post\Media::IMAGE]);
+               $text = BBCode::toPlaintext($body, false);
+               $text = preg_replace(Strings::autoLinkRegEx(), '', $text);
+
+               do {
+                       $oldtext = $text;
+                       $text = str_replace(['  ', "\n", "\r"], ' ', $text);
+               } while ($oldtext != $text);
+
+               return $text;
+       }
+
        private static function getMediaType(int $uri_id): int
        {
                $media = Post\Media::getByURIId($uri_id);
@@ -128,7 +195,27 @@ class Engagement
         */
        public static function expire()
        {
-               DBA::delete('post-engagement', ["`created` < ?", DateTimeFormat::utc('now - ' . DI::config()->get('channel', 'engagement_hours') . ' hour')]);
-               Logger::notice('Cleared expired engagements', ['rows' => DBA::affectedRows()]);
+               $limit = self::getCreationDateLimit(true);
+               if (empty($limit)) {
+                       Logger::notice('Expiration limit not reached');
+                       return;
+               }
+               DBA::delete('post-engagement', ["`created` < ?", $limit]);
+               Logger::notice('Cleared expired engagements', ['limit' => $limit, 'rows' => DBA::affectedRows()]);
+       }
+
+       private static function getCreationDateLimit(bool $forDeletion): string
+       {
+               $posts = DI::config()->get('channel', 'engagement_post_limit');
+               if (!empty($posts)) {
+                       $limit = DBA::selectToArray('post-engagement', ['created'], [], ['limit' => [$posts, 1], 'order' => ['created' => true]]);
+                       if (!empty($limit)) {
+                               return $limit[0]['created'];
+                       } elseif ($forDeletion) {
+                               return '';
+                       }
+               }
+
+               return DateTimeFormat::utc('now - ' . DI::config()->get('channel', 'engagement_hours') . ' hour');
        }
 }