From 0451f2dfa1510258b7f551ba3224e885c711e6b3 Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 07:51:20 -0500 Subject: [PATCH] Add Mastodon Instance V2 API endpoint /api/v2/instance --- src/Module/Api/Mastodon/InstanceV2.php | 75 +++++++++++++++ src/Object/Api/Mastodon/InstanceV2.php | 96 +++++++++++++++++++ .../Api/Mastodon/InstanceV2/Configuration.php | 47 +++++++++ .../Api/Mastodon/InstanceV2/Contact.php | 56 +++++++++++ .../InstanceV2/FriendicaExtensions.php | 31 ++++++ .../InstanceV2/MediaAttachmentsConfig.php | 40 ++++++++ .../Api/Mastodon/InstanceV2/Registrations.php | 47 +++++++++ .../Mastodon/InstanceV2/StatusesConfig.php | 46 +++++++++ .../Api/Mastodon/InstanceV2/Thumbnail.php | 41 ++++++++ src/Object/Api/Mastodon/InstanceV2/Usage.php | 40 ++++++++ .../Api/Mastodon/InstanceV2/UserStats.php | 44 +++++++++ static/routes.config.php | 2 +- 12 files changed, 564 insertions(+), 1 deletion(-) create mode 100644 src/Module/Api/Mastodon/InstanceV2.php create mode 100644 src/Object/Api/Mastodon/InstanceV2.php create mode 100644 src/Object/Api/Mastodon/InstanceV2/Configuration.php create mode 100644 src/Object/Api/Mastodon/InstanceV2/Contact.php create mode 100644 src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php create mode 100644 src/Object/Api/Mastodon/InstanceV2/MediaAttachmentsConfig.php create mode 100644 src/Object/Api/Mastodon/InstanceV2/Registrations.php create mode 100644 src/Object/Api/Mastodon/InstanceV2/StatusesConfig.php create mode 100644 src/Object/Api/Mastodon/InstanceV2/Thumbnail.php create mode 100644 src/Object/Api/Mastodon/InstanceV2/Usage.php create mode 100644 src/Object/Api/Mastodon/InstanceV2/UserStats.php diff --git a/src/Module/Api/Mastodon/InstanceV2.php b/src/Module/Api/Mastodon/InstanceV2.php new file mode 100644 index 000000000..e5af34b67 --- /dev/null +++ b/src/Module/Api/Mastodon/InstanceV2.php @@ -0,0 +1,75 @@ +. + * + */ + +namespace Friendica\Module\Api\Mastodon; + +use Friendica\App; +use Friendica\Core\Config\Capability\IManageConfigValues; +use Friendica\Core\L10n; +use Friendica\Core\System; +use Friendica\Database\Database; +use Friendica\Module\Api\ApiResponse; +use Friendica\Module\BaseApi; +use Friendica\Object\Api\Mastodon\InstanceV2 as InstanceEntity; +use Friendica\Util\Profiler; +use Psr\Log\LoggerInterface; + +/** + * @see https://docs.joinmastodon.org/methods/instance/ + */ +class InstanceV2 extends BaseApi +{ + /** @var Database */ + private $database; + + /** @var IManageConfigValues */ + private $config; + + public function __construct( + App $app, + L10n $l10n, + App\BaseURL $baseUrl, + App\Arguments $args, + LoggerInterface $logger, + Profiler $profiler, + ApiResponse $response, + Database $database, + IManageConfigValues $config, + array $server, + array $parameters = [] + ) { + parent::__construct($app, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + + $this->database = $database; + $this->config = $config; + } + + /** + * @param array $request + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \Friendica\Network\HTTPException\NotFoundException + * @throws \ImagickException + */ + protected function rawContent(array $request = []) + { + System::jsonExit(new InstanceEntity($this->config, $this->baseUrl, $this->database, System::getRules())); + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2.php b/src/Object/Api/Mastodon/InstanceV2.php new file mode 100644 index 000000000..f3551c564 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2.php @@ -0,0 +1,96 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon; + +use Friendica\App; +use Friendica\App\BaseURL; +use Friendica\BaseDataTransferObject; +use Friendica\Core\Config\Capability\IManageConfigValues; +use Friendica\Database\Database; +use Friendica\Network\HTTPException; +use Friendica\Object\Api\Mastodon\InstanceV2\Configuration; +use Friendica\Object\Api\Mastodon\InstanceV2\Contact; +use Friendica\Object\Api\Mastodon\InstanceV2\FriendicaExtensions; +use Friendica\Object\Api\Mastodon\InstanceV2\Registrations; +use Friendica\Object\Api\Mastodon\InstanceV2\Thumbnail; +use Friendica\Object\Api\Mastodon\InstanceV2\Usage; + +/** + * Class Instance + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class InstanceV2 extends BaseDataTransferObject +{ + /** @var string */ + protected $domain; + /** @var string */ + protected $title; + /** @var string */ + protected $version; + /** @var string */ + protected $source_url; + /** @var string */ + protected $description; + /** @var Usage */ + protected $usage; + /** @var Thumbnail */ + protected $thumbnail; + /** @var array */ + protected $languages; + /** @var Configuration */ + protected $configuration; + /** @var Registrations */ + protected $registrations; + /** @var Contact */ + protected $contact; + /** @var array */ + protected $rules = []; + /** @var FriendicaExtensions */ + protected $friendica; + + /** + * @param IManageConfigValues $config + * @param BaseURL $baseUrl + * @param Database $database + * @param array $rules + * @throws HTTPException\InternalServerErrorException + * @throws HTTPException\NotFoundException + * @throws \ImagickException + */ + public function __construct(IManageConfigValues $config, BaseURL $baseUrl, Database $database, array $rules = []) + { + $this->domain = $baseUrl->getHostname(); + $this->title = $config->get('config', 'sitename'); + $this->version = '2.8.0 (compatible; Friendica ' . App::VERSION . ')'; + $this->source_url = null; //not supported yet + $this->description = $config->get('config', 'info'); + $this->usage = new Usage($config); + $this->thumbnail = new Thumbnail($baseUrl); + $this->languages = [$config->get('system', 'language')]; + $this->configuration = new Configuration(); + $this->registrations = new Registrations(); + $this->contact = new Contact($database); + $this->rules = $rules; + $this->friendica = new FriendicaExtensions(); + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/Configuration.php b/src/Object/Api/Mastodon/InstanceV2/Configuration.php new file mode 100644 index 000000000..e30561356 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/Configuration.php @@ -0,0 +1,47 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; +use Friendica\DI; + +/** + * Class Configuration + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class Configuration extends BaseDataTransferObject +{ + /** @var StatusesConfig */ + protected $statuses; + /** @var MediaAttachmentsConfig */ + protected $media_attachments; + /** @var int */ + protected $image_size_limit; + + public function __construct() + { + $this->statuses = new StatusesConfig(); + $this->media_attachments = new MediaAttachmentsConfig(); + $this->image_size_limit = DI::config()->get('system', 'maximagesize'); + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/Contact.php b/src/Object/Api/Mastodon/InstanceV2/Contact.php new file mode 100644 index 000000000..45631b0fb --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/Contact.php @@ -0,0 +1,56 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; +use Friendica\Database\Database; +use Friendica\DI; +use Friendica\Model\User; +use Friendica\Object\Api\Mastodon\Account; + +/** + * Class Contact + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class Contact extends BaseDataTransferObject +{ + /** @var string */ + protected $email; + /** @var Account */ + protected $account = null; + + + public function __construct(Database $database) + { + $this->email = implode(',', User::getAdminEmailList()); + $administrator = User::getFirstAdmin(); + if ($administrator) { + $adminContact = $database->selectFirst( + 'contact', + ['uri-id'], + ['nick' => $administrator['nickname'], 'self' => true] + ); + $this->account = DI::mstdnAccount()->createFromUriId($adminContact['uri-id']); + } + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php b/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php new file mode 100644 index 000000000..b69b5c026 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php @@ -0,0 +1,31 @@ +version = App::VERSION; + $this->codename = App::CODENAME; + $this->db_version = DI::config()->get('system', 'build'); + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/MediaAttachmentsConfig.php b/src/Object/Api/Mastodon/InstanceV2/MediaAttachmentsConfig.php new file mode 100644 index 000000000..598736c33 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/MediaAttachmentsConfig.php @@ -0,0 +1,40 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; +use Friendica\Util\Images; + +/** + * Class MediaAttachmentsConfig + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class MediaAttachmentsConfig extends BaseDataTransferObject +{ + /** @var string[] */ + protected $supported_mime_types; + public function __construct() + { + $this->supported_mime_types = Images::supportedTypes(); + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/Registrations.php b/src/Object/Api/Mastodon/InstanceV2/Registrations.php new file mode 100644 index 000000000..78c5713ea --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/Registrations.php @@ -0,0 +1,47 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; +use Friendica\DI; +use Friendica\Module\Register; + +/** + * Class Registrations + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class Registrations extends BaseDataTransferObject +{ + /** @var bool */ + protected $enabled; + /** @var bool */ + protected $approval_required; + + public function __construct() + { + $config = DI::config(); + $register_policy = intval($config->get('config', 'register_policy')); + $this->enabled = ($register_policy != Register::CLOSED); + $this->approval_required = ($register_policy == Register::APPROVE); + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/StatusesConfig.php b/src/Object/Api/Mastodon/InstanceV2/StatusesConfig.php new file mode 100644 index 000000000..5bf20ec97 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/StatusesConfig.php @@ -0,0 +1,46 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; +use Friendica\DI; + +/** + * Class StatusConfig + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class StatusesConfig extends BaseDataTransferObject +{ + /** @var int */ + protected $max_characters = 0; + + public function __construct() + { + $config = DI::config(); + $this->max_characters = (int)$config->get( + 'config', + 'api_import_size', + $config->get('config', 'max_import_size') + ); + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/Thumbnail.php b/src/Object/Api/Mastodon/InstanceV2/Thumbnail.php new file mode 100644 index 000000000..18cb1bf2a --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/Thumbnail.php @@ -0,0 +1,41 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\App\BaseURL; +use Friendica\BaseDataTransferObject; + +/** + * Class Thumbnail + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class Thumbnail extends BaseDataTransferObject +{ + /** @var string (URL) */ + protected $url; + + public function __construct(BaseURL $baseUrl) + { + $this->url = $baseUrl->get() . 'images/friendica-banner.jpg'; + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/Usage.php b/src/Object/Api/Mastodon/InstanceV2/Usage.php new file mode 100644 index 000000000..cb4934833 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/Usage.php @@ -0,0 +1,40 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; + +/** + * Class Usage + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class Usage extends BaseDataTransferObject +{ + /** @var UserStats */ + protected $users; + + public function __construct() + { + $this->users = new UserStats(); + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/UserStats.php b/src/Object/Api/Mastodon/InstanceV2/UserStats.php new file mode 100644 index 000000000..c82cf563e --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/UserStats.php @@ -0,0 +1,44 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; +use Friendica\DI; + +/** + * Class UserStats + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class UserStats extends BaseDataTransferObject +{ + /** @var int */ + protected $active_monthly = 0; + + public function __construct() + { + $config = DI::config(); + if (!empty($config->get('system', 'nodeinfo'))) { + $this->active_monthly = intval(DI::keyValue()->get('nodeinfo_active_users_monthly')); + } + } +} diff --git a/static/routes.config.php b/static/routes.config.php index 58fce7277..3271571c4 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -307,7 +307,7 @@ return [ '/trends/tags' => [Module\Api\Mastodon\Trends\Tags::class, [R::GET ]], ], '/v2' => [ - '/instance' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not supported + '/instance' => [Module\Api\Mastodon\InstanceV2::class, [R::GET ]], // not supported ], '/v{version:\d+}' => [ '/admin/accounts' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not supported