]> git.mxchange.org Git - friendica.git/commitdiff
Improve emoji federation and mastodon api compliance
authorgudzpoz <gudzpoz@live.com>
Sun, 12 Nov 2023 12:59:49 +0000 (20:59 +0800)
committergudzpoz <gudzpoz@live.com>
Sun, 12 Nov 2023 12:59:49 +0000 (20:59 +0800)
src/Content/Smilies.php
src/Factory/Api/Mastodon/Emoji.php
src/Factory/Api/Mastodon/Status.php
src/Object/Api/Mastodon/Status.php
src/Protocol/ActivityPub/Transmitter.php

index 2e1a6cf19c158db52b4b25a2155f5831c426a952..760bfbce9e331945234a6db05906f78ed01f3081 100644 (file)
@@ -152,6 +152,34 @@ class Smilies
                return $params;
        }
 
+       /**
+        * Finds all used smilies (like :heart: or :p) in the provided text.
+        *
+        * @param string $text that might contain smilie usages (denoted by a starting colon)
+        * @param bool   $extract_url whether to further extract image urls
+        * @return array with smilie codes (colon included) as the keys, the smilie images as values
+        */
+       public static function extractUsedSmilies(string $text, bool $extract_url = false): array
+       {
+               $emojis = [];
+
+               $smilies = self::getList();
+               $icons = $smilies['icons'];
+               foreach ($smilies['texts'] as $i => $name) {
+                       if (strstr($text, $name)) {
+                               $image = $icons[$i];
+                               if ($extract_url) {
+                                       if (preg_match('/src="(.+?)"/', $image, $match)) {
+                                               $image = $match[1];
+                                       } else {
+                                               continue;
+                                       }
+                               }
+                               $emojis[$name] = $image;
+                       }
+               }
+               return $emojis;
+       }
 
        /**
         * Copied from http://php.net/manual/en/function.str-replace.php#88569
index 157b91bf91b412b1b743d0b6ff3434bfeee561e2..b7f4ee6eadf20a9af1f61f5d82efcd0a9a09444f 100644 (file)
@@ -32,19 +32,22 @@ class Emoji extends BaseFactory
        }
 
        /**
+        * Creates an emoji collection from shortcode => image mappings.
+        *
         * @param array $smilies
         *
         * @return Emojis
         */
-       public function createCollectionFromSmilies(array $smilies): Emojis
+       public function createCollectionFromArray(array $smilies): Emojis
        {
                $prototype = null;
 
                $emojis = [];
 
-               foreach ($smilies['texts'] as $key => $shortcode) {
-                       if (preg_match('/src="(.+?)"/', $smilies['icons'][$key], $matches)) {
+               foreach ($smilies as $shortcode => $icon) {
+                       if (preg_match('/src="(.+?)"/', $icon, $matches)) {
                                $url = $matches[1];
+                               $shortcode = trim($shortcode, ':');
 
                                if ($prototype === null) {
                                        $prototype = $this->create($shortcode, $url);
@@ -52,9 +55,19 @@ class Emoji extends BaseFactory
                                } else {
                                        $emojis[] = \Friendica\Object\Api\Mastodon\Emoji::createFromPrototype($prototype, $shortcode, $url);
                                }
-                       };
+                       }
                }
 
                return new Emojis($emojis);
        }
+
+       /**
+        * @param array $smilies
+        *
+        * @return Emojis
+        */
+       public function createCollectionFromSmilies(array $smilies): Emojis
+       {
+               return self::createCollectionFromArray(array_combine($smilies['texts'], $smilies['icons']));
+       }
 }
index 4bf5609b9ab9e8e611cdbe374281a9179f7c5162..aaaa8d3d94bb95149bc828209c32f32e92fa7571 100644 (file)
@@ -24,6 +24,7 @@ namespace Friendica\Factory\Api\Mastodon;
 use Friendica\BaseFactory;
 use Friendica\Content\ContactSelector;
 use Friendica\Content\Item as ContentItem;
+use Friendica\Content\Smilies;
 use Friendica\Content\Text\BBCode;
 use Friendica\Core\Logger;
 use Friendica\Database\Database;
@@ -57,6 +58,8 @@ class Status extends BaseFactory
        private $mstdnCardFactory;
        /** @var Attachment */
        private $mstdnAttachmentFactory;
+       /** @var Emoji */
+       private $mstdnEmojiFactory;
        /** @var Error */
        private $mstdnErrorFactory;
        /** @var Poll */
@@ -74,6 +77,7 @@ class Status extends BaseFactory
                Tag $mstdnTagFactory,
                Card $mstdnCardFactory,
                Attachment $mstdnAttachmentFactory,
+               Emoji $mstdnEmojiFactory,
                Error $mstdnErrorFactory,
                Poll $mstdnPollFactory,
                ContentItem $contentItem,
@@ -86,6 +90,7 @@ class Status extends BaseFactory
                $this->mstdnTagFactory        = $mstdnTagFactory;
                $this->mstdnCardFactory       = $mstdnCardFactory;
                $this->mstdnAttachmentFactory = $mstdnAttachmentFactory;
+               $this->mstdnEmojiFactory      = $mstdnEmojiFactory;
                $this->mstdnErrorFactory      = $mstdnErrorFactory;
                $this->mstdnPollFactory       = $mstdnPollFactory;
                $this->contentItem            = $contentItem;
@@ -283,6 +288,9 @@ class Status extends BaseFactory
                        }
                }
 
+               $used_smilies = Smilies::extractUsedSmilies($item['body'] ?: $item['raw-body']);
+               $emojis = $this->mstdnEmojiFactory->createCollectionFromArray($used_smilies)->getArrayCopy(true);
+
                if ($is_reshare) {
                        try {
                                $reshare = $this->createFromUriId($uriId, $uid, $display_quote, false, false)->toArray();
@@ -309,7 +317,7 @@ class Status extends BaseFactory
                $visibility_data = $uid != $item['uid'] ? null : new FriendicaVisibility($this->aclFormatter->expand($item['allow_cid']), $this->aclFormatter->expand($item['deny_cid']), $this->aclFormatter->expand($item['allow_gid']), $this->aclFormatter->expand($item['deny_gid']));
                $friendica       = new FriendicaExtension($item['title'] ?? '', $item['changed'], $item['commented'], $item['received'], $counts->dislikes, $origin_dislike, $delivery_data, $visibility_data);
 
-               return new \Friendica\Object\Api\Mastodon\Status($item, $account, $counts, $userAttributes, $sensitive, $application, $mentions, $tags, $card, $attachments, $in_reply, $reshare, $friendica, $quote, $poll);
+               return new \Friendica\Object\Api\Mastodon\Status($item, $account, $counts, $userAttributes, $sensitive, $application, $mentions, $tags, $card, $attachments, $in_reply, $reshare, $friendica, $quote, $poll, $emojis);
        }
 
        /**
index 122e62f9caa103ec58fcdf7cc3c0e34a6cdd062f..59d2a6cc58e9f874eaa268ab02193f8a8479efcc 100644 (file)
@@ -107,7 +107,7 @@ class Status extends BaseDataTransferObject
         * @param array   $item
         * @throws \Friendica\Network\HTTPException\InternalServerErrorException
         */
-       public function __construct(array $item, Account $account, Counts $counts, UserAttributes $userAttributes, bool $sensitive, Application $application, array $mentions, array $tags, Card $card, array $attachments, array $in_reply, array $reblog, FriendicaExtension $friendica, array $quote = null, array $poll = null)
+       public function __construct(array $item, Account $account, Counts $counts, UserAttributes $userAttributes, bool $sensitive, Application $application, array $mentions, array $tags, Card $card, array $attachments, array $in_reply, array $reblog, FriendicaExtension $friendica, array $quote = null, array $poll = null, array $emojis = null)
        {
                $reblogged          = !empty($reblog);
                $this->id           = (string)$item['uri-id'];
@@ -152,7 +152,7 @@ class Status extends BaseDataTransferObject
                $this->media_attachments = $reblogged ? [] : $attachments;
                $this->mentions = $reblogged ? [] : $mentions;
                $this->tags = $reblogged ? [] : $tags;
-               $this->emojis = $reblogged ? [] : [];
+               $this->emojis = $reblogged ? [] : ($emojis ?: []);
                $this->card = $reblogged ? null : ($card->toArray() ?: null);
                $this->poll = $reblogged ? null : $poll;
                $this->friendica = $reblogged ? null : $friendica;
index b18e247eacd597468da011d07eaf15775c7dee0a..130aa3ab08020bde88d7dd05148c5bdcc1fcbee4 100644 (file)
@@ -23,6 +23,7 @@ namespace Friendica\Protocol\ActivityPub;
 
 use Friendica\App;
 use Friendica\Content\Feature;
+use Friendica\Content\Smilies;
 use Friendica\Content\Text\BBCode;
 use Friendica\Core\Cache\Enum\Duration;
 use Friendica\Core\Logger;
@@ -1506,6 +1507,26 @@ class Transmitter
                return $location;
        }
 
+       /**
+        * Appends emoji tags to a tag array according to the tags used.
+        *
+        * @param array $tags Tag array
+        * @param string $text Text containing tags like :tag:
+        */
+       private static function addEmojiTags(array &$tags, string $text)
+       {
+               foreach (Smilies::extractUsedSmilies($text, true) as $name => $url) {
+                       $tags[] = [
+                               'type' => 'Emoji',
+                               'name' => $name,
+                               'icon' => [
+                                       'type' => 'Image',
+                                       'url' => $url,
+                               ],
+                       ];
+               }
+       }
+
        /**
         * Returns a tag array for a given item array
         *
@@ -1538,6 +1559,8 @@ class Transmitter
                        }
                }
 
+               self::addEmojiTags($tags, $item['body']);
+
                $announce = self::getAnnounceArray($item);
                // Mention the original author upon commented reshares
                if (!empty($announce['comment'])) {