]> git.mxchange.org Git - friendica.git/commitdiff
Improved Mastodon API compatibility
authorMichael <heluecht@pirati.ca>
Sat, 1 Mar 2025 12:38:09 +0000 (12:38 +0000)
committerMichael <heluecht@pirati.ca>
Sat, 1 Mar 2025 12:38:09 +0000 (12:38 +0000)
src/BaseModule.php
src/Factory/Api/Mastodon/Relationship.php
src/Module/Api/Mastodon/Accounts/Relationships.php
src/Module/Api/Mastodon/Search.php
src/Object/Api/Mastodon/Account.php
src/Object/Api/Mastodon/Application.php
src/Object/Api/Mastodon/Attachment.php
src/Object/Api/Mastodon/Card.php
src/Object/Api/Mastodon/Relationship.php
src/Object/Api/Mastodon/Status.php
src/Object/Api/Mastodon/Tag.php

index 27f156bef0745e666dfd299c42e858bfdfbf518a..933f38600b7ba4f93ac08265a1d7f0b32a2f6e50 100644 (file)
@@ -512,7 +512,7 @@ abstract class BaseModule implements ICanHandleRequests
         * @throws HTTPException\InternalServerErrorException
         * @see json_encode()
         */
-       public function jsonExit($content, string $content_type = 'application/json', int $options = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)
+       public function jsonExit($content, string $content_type = 'application/json; charset=utf-8', int $options = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)
        {
                $this->httpExit(json_encode($content, $options), ICanCreateResponses::TYPE_JSON, $content_type);
        }
index d12b563f103c7134e8ddb16bd260194b6f28847d..7411f063f93709dea5b72a30280509622224c611 100644 (file)
@@ -38,7 +38,8 @@ class Relationship extends BaseFactory
                        $pcid,
                        $contact,
                        Contact\User::isBlocked($cid, $uid),
-                       Contact\User::isIgnored($cid, $uid)
+                       Contact\User::isIgnored($cid, $uid),
+                       Contact\User::isIsBlocked($cid, $uid),
                );
        }
 }
index 4f0c79ebfcfd0435bf93d61ce2d25e532ae71ccd..afdcf4cdeb557ea336c3f9eedb834fa0bce4b4e7 100644 (file)
@@ -28,7 +28,7 @@ class Relationships extends BaseApi
                ], $request);
 
                if (empty($request['id'])) {
-                       $this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
+                       $this->jsonExit([]);
                }
 
                if (!is_array($request['id'])) {
index 9301c60cdcf36733ba3e7fa4ad37faed2b4a8860..668bb4d8d079ad81c06ed45deeb8d6b57965e183 100644 (file)
@@ -50,6 +50,10 @@ class Search extends BaseApi
 
                $limit = min($request['limit'], 40);
 
+               if (Network::isValidHttpUrl($request['q']) && ($request['offset'] == 0)) {
+                       $this->searchLinks($uid, $request['q'], $request['type']);
+               }
+
                $result = ['accounts' => [], 'statuses' => [], 'hashtags' => []];
 
                if (empty($request['type']) || ($request['type'] == 'accounts')) {
@@ -79,6 +83,43 @@ class Search extends BaseApi
                $this->jsonExit($result);
        }
 
+       /**
+        * Search for links (either accounts or statuses). Return an empty result otherwise
+        *
+        * @param integer $uid  User id
+        * @param string  $q    Search term (HTTP link)
+        * @param string  $type Search type (or empty if not provided)
+        */
+       private function searchLinks(int $uid, string $q, string $type)
+       {
+               $result = ['accounts' => [], 'statuses' => [], 'hashtags' => []];
+
+               $data = ['uri-id' => -1, 'type' => Post\Media::UNKNOWN, 'url' => $q];
+               $data = Post\Media::fetchAdditionalData($data);
+
+               if ((empty($type) || ($type == 'statuses')) && in_array($data['type'], [Post\Media::HTML, Post\Media::ACTIVITY, Post\Media::UNKNOWN])) {
+                       $q = Network::convertToIdn($q);
+                       // If the user-specific search failed, we search and probe a public post
+                       $item_id = Item::fetchByLink($q, $uid) ?: Item::fetchByLink($q);
+                       if ($item_id && $item = Post::selectFirst(['uri-id'], ['id' => $item_id])) {
+                               $result['statuses'] = [DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, self::appSupportsQuotes())];
+                               $this->jsonExit($result);
+                       }
+               }
+
+               if ((empty($type) || ($type == 'accounts')) && in_array($data['type'], [Post\Media::HTML, Post\Media::ACCOUNT, Post\Media::UNKNOWN])) {
+                       $id = Contact::getIdForURL($q, 0, false);
+                       if ($id) {
+                               $result['accounts'] = [DI::mstdnAccount()->createFromContactId($id, $uid)];
+                               $this->jsonExit($result);
+                       }
+               }
+
+               if (in_array($data['type'], [Post\Media::HTML, Post\Media::TEXT, Post\Media::ACCOUNT, Post\Media::ACTIVITY, Post\Media::UNKNOWN])) {
+                       $this->jsonExit($result);
+               }
+       }
+
        /**
         * @param int    $uid
         * @param string $q
@@ -93,9 +134,7 @@ class Search extends BaseApi
         */
        private function searchAccounts(int $uid, string $q, bool $resolve, int $limit, int $offset, bool $following)
        {
-               if (($offset == 0) && (strrpos($q, '@') > 0 || Network::isValidHttpUrl($q))
-                       && $id = Contact::getIdForURL($q, 0, $resolve ? null : false)
-               ) {
+               if (($offset == 0) && (strrpos($q, '@') > 0) && $id = Contact::getIdForURL($q, 0, $resolve ? null : false)) {
                        return DI::mstdnAccount()->createFromContactId($id, $uid);
                }
 
@@ -122,19 +161,6 @@ class Search extends BaseApi
         */
        private function searchStatuses(int $uid, string $q, string $account_id, int $max_id, int $min_id, int $limit, int $offset)
        {
-               if (Network::isValidHttpUrl($q)) {
-                       // Unique post search, any offset greater than 0 should return empty result
-                       if ($offset > 0) {
-                               return [];
-                       }
-                       $q = Network::convertToIdn($q);
-                       // If the user-specific search failed, we search and probe a public post
-                       $item_id = Item::fetchByLink($q, $uid) ?: Item::fetchByLink($q);
-                       if ($item_id && $item = Post::selectFirst(['uri-id'], ['id' => $item_id])) {
-                               return DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, self::appSupportsQuotes());
-                       }
-               }
-
                $params = ['order' => ['uri-id' => true], 'limit' => [$offset, $limit]];
 
                if (substr($q, 0, 1) == '#') {
index de6cac6041df32952ef6ee5882d4dfc9b5f0e42a..864b263ccaeffea076cb704d4b951e5ed7ff9d7b 100644 (file)
@@ -38,6 +38,8 @@ class Account extends BaseDataTransferObject
        /** @var bool */
        protected $discoverable;
        /** @var bool */
+       protected $indexable;
+       /** @var bool */
        protected $group;
        /** @var string|null (Datetime) */
        protected $created_at;
@@ -45,6 +47,8 @@ class Account extends BaseDataTransferObject
        protected $note;
        /** @var string (URL)*/
        protected $url;
+       /** @var string (URL)*/
+       protected $uri;
        /** @var string (URL) */
        protected $avatar;
        /** @var string (URL) */
@@ -61,6 +65,8 @@ class Account extends BaseDataTransferObject
        protected $statuses_count;
        /** @var string|null (Datetime) */
        protected $last_status_at = null;
+       /** @var bool */
+       protected $hide_collections = false;
        /** @var Emoji[] */
        protected $emojis;
        /** @var Account|null */
@@ -88,12 +94,14 @@ class Account extends BaseDataTransferObject
                $this->locked          = (bool)$account['manually-approve'];
                $this->bot             = ($account['contact-type'] == Contact::TYPE_NEWS);
                $this->discoverable    = !$account['unsearchable'];
+               $this->indexable       = $this->discoverable;
                $this->group           = ($account['contact-type'] == Contact::TYPE_COMMUNITY);
 
                $this->created_at      = DateTimeFormat::utc($account['created'] ?: DBA::NULL_DATETIME, DateTimeFormat::JSON);
 
                $this->note            = BBCode::convertForUriId($account['uri-id'], $account['about'], BBCode::EXTERNAL);
-               $this->url             = $account['url'];
+               $this->url             = $account['alias'] ?: $account['url'];
+               $this->uri             = $account['url'];
                $this->avatar          = Contact::getAvatarUrlForId($account['id'] ?? 0 ?: $account['pid'], Proxy::SIZE_SMALL, $account['updated'], $account['guid'] ?? '');
                $this->avatar_static   = Contact::getAvatarUrlForId($account['id'] ?? 0 ?: $account['pid'], Proxy::SIZE_SMALL, $account['updated'], $account['guid'] ?? '', true);
                $this->header          = Contact::getHeaderUrlForId($account['id'] ?? 0 ?: $account['pid'], '', $account['updated'], $account['guid'] ?? '');
index 50837f90cb3c22488209dc73742d0d7f29fbe71b..8126bebe550be5d56e5938cdd744c750e4f3b50c 100644 (file)
@@ -63,8 +63,8 @@ class Application extends BaseDataTransferObject
                        unset($application['redirect_uri']);
                }
 
-               if (empty($application['website'])) {
-                       unset($application['website']);
+               if (empty($application['vapid_key'])) {
+                       unset($application['vapid_key']);
                }
 
                return $application;
index e3d7600f16f0e7171af0a9cc04330fa724de95a3..604ef41fac84a5c1190968680c0a602a37bf279e 100644 (file)
@@ -27,6 +27,8 @@ class Attachment extends BaseDataTransferObject
        /** @var string */
        protected $remote_url;
        /** @var string */
+       protected $preview_remote_url;
+       /** @var string */
        protected $text_url;
        /** @var string */
        protected $description;
@@ -52,7 +54,6 @@ class Attachment extends BaseDataTransferObject
                $this->url         = $url;
                $this->preview_url = $preview;
                $this->remote_url  = $remote;
-               $this->text_url    = $this->remote_url ?? $this->url;
                $this->description = $attachment['description'];
                $this->blurhash    = $attachment['blurhash'];
                if ($type === 'image') {
index 7f097abe228a7d0bf12a85df1935b6f5a2edfdda..9b9c58db1bb373477ca6db7bceadb812eb66f608 100644 (file)
@@ -41,9 +41,15 @@ class Card extends BaseDataTransferObject
        /** @var string */
        protected $image;
        /** @var string */
+       protected $image_description = '';
+       /** @var string */
        protected $embed_url;
        /** @var string */
        protected $blurhash;
+       /** @var string|null (Datetime) */
+       protected $published_at;
+       /** @var array */
+       protected $authors = [];
        /** @var array */
        protected $history;
 
@@ -83,6 +89,10 @@ class Card extends BaseDataTransferObject
                        return [];
                }
 
+               if (empty($this->history)) {
+                       unset($this->history);
+               }
+
                return parent::toArray();
        }
 }
index 1d708425cd673823c997ddd97732b8d2d5f55555..1158aa545925037ea48fbb24910656f9d08035b1 100644 (file)
@@ -46,15 +46,19 @@ class Relationship extends BaseDataTransferObject
        protected $blocking = false;
        /** @var bool */
        protected $domain_blocking = false;
+       /** @var bool */
+       protected $blocked_by = false;
        /**
         * Unsupported
-        * @var bool
+        * @var array
         */
-       protected $blocked_by = false;
+       protected $languages = [];
        /**
         * Unsupported
-        * @var string
+        * @var bool
         */
+       protected $requested_by = false;
+       /** @var string */
        protected $note = '';
 
        /**
@@ -63,7 +67,7 @@ class Relationship extends BaseDataTransferObject
         * @param bool  $blocked "true" if user is blocked
         * @param bool  $muted "true" if user is muted
         */
-       public function __construct(int $contactId, array $contactRecord, bool $blocked = false, bool $muted = false)
+       public function __construct(int $contactId, array $contactRecord, bool $blocked = false, bool $muted = false, bool $isBlocked = false)
        {
                $this->id                   = (string)$contactId;
                $this->following            = false;
@@ -86,6 +90,7 @@ class Relationship extends BaseDataTransferObject
                        $this->muting      = (bool)($contactRecord['readonly'] ?? false) || $muted;
                        $this->notifying   = (bool)$contactRecord['notify_new_posts'] ?? false;
                        $this->blocking    = (bool)($contactRecord['blocked'] ?? false) || $blocked;
+                       $this->blocked_by  = $isBlocked;
                        $this->note        = $contactRecord['info'];
                }
 
index 0e487a989c0246101663d0ffd8814d1bc89cffb0..16eba0afcb45a9a9e943e0882c156e7727902bf2 100644 (file)
@@ -64,6 +64,8 @@ class Status extends BaseDataTransferObject
        protected $pinned = false;
        /** @var string */
        protected $content;
+       /** @var array */
+       protected $filtered = [];
        /** @var Status|null */
        protected $reblog = null;
        /** @var Status|null - Akkoma extension, see issue https://github.com/friendica/friendica/issues/12603 */
index 3c14a5e61650c2f24e14c974bf6368909f1d2796..808e4c3cea63f1a4cd3c860fd1ac13631e00b210 100644 (file)
@@ -42,4 +42,13 @@ class Tag extends BaseDataTransferObject
                $this->history   = $history;
                $this->following = $following;
        }
+
+       public function toArray(): array
+       {
+               if (empty($this->history)) {
+                       unset($this->history);
+               }
+
+               return parent::toArray();
+       }
 }