diff --git a/src/Module/Api/Mastodon/InstanceV2.php b/src/Module/Api/Mastodon/InstanceV2.php new file mode 100644 index 0000000000..2038081d87 --- /dev/null +++ b/src/Module/Api/Mastodon/InstanceV2.php @@ -0,0 +1,168 @@ +. + * + */ + +namespace Friendica\Module\Api\Mastodon; + +use Exception; +use Friendica\App; +use Friendica\Core\Config\Capability\IManageConfigValues; +use Friendica\Core\L10n; +use Friendica\Core\System; +use Friendica\Database\Database; +use Friendica\DI; +use Friendica\Model\User; +use Friendica\Module\Api\ApiResponse; +use Friendica\Module\BaseApi; +use Friendica\Module\Register; +use Friendica\Object\Api\Mastodon\InstanceV2 as InstanceEntity; +use Friendica\Util\Images; +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 + * @throws Exception + */ + protected function rawContent(array $request = []) + { + $domain = $this->baseUrl->getHost(); + $title = $this->config->get('config', 'sitename'); + $version = '2.8.0 (compatible; Friendica ' . App::VERSION . ')'; + $description = $this->config->get('config', 'info'); + $usage = $this->buildUsageInfo(); + $thumbnail = new InstanceEntity\Thumbnail($this->baseUrl->withPath('images/friendica-banner.jpg')); + $languages = [$this->config->get('system', 'language')]; + $configuration = $this->buildConfigurationInfo(); + $registration = $this->buildRegistrationsInfo(); + $contact = $this->buildContactInfo(); + $friendica_extensions = $this->buildFriendicaExtensionInfo(); + $rules = System::getRules(); + System::jsonExit(new InstanceEntity( + $domain, + $title, + $version, + $description, + $usage, + $thumbnail, + $languages, + $configuration, + $registration, + $contact, + $friendica_extensions, + $rules + )); + } + + private function buildConfigurationInfo(): InstanceEntity\Configuration + { + $statuses_config = new InstanceEntity\StatusesConfig((int)$this->config->get( + 'config', + 'api_import_size', + $this->config->get('config', 'max_import_size') + )); + + return new InstanceEntity\Configuration( + $statuses_config, + new InstanceEntity\MediaAttachmentsConfig(Images::supportedTypes()), + $this->config->get('system', 'maximagesize') + ); + } + + private function buildContactInfo(): InstanceEntity\Contact + { + $email = implode(',', User::getAdminEmailList()); + $administrator = User::getFirstAdmin(); + $account = null; + + if ($administrator) { + $adminContact = $this->database->selectFirst( + 'contact', + ['uri-id'], + ['nick' => $administrator['nickname'], 'self' => true] + ); + $account = DI::mstdnAccount()->createFromUriId($adminContact['uri-id']); + } + + return new InstanceEntity\Contact($email, $account); + } + + private function buildFriendicaExtensionInfo(): InstanceEntity\FriendicaExtensions + { + return new InstanceEntity\FriendicaExtensions( + App::VERSION, + App::CODENAME, + $this->config->get('system', 'build') + ); + } + + private function buildRegistrationsInfo(): InstanceEntity\Registrations + { + $register_policy = intval($this->config->get('config', 'register_policy')); + $enabled = ($register_policy != Register::CLOSED); + $approval_required = ($register_policy == Register::APPROVE); + + return new InstanceEntity\Registrations($enabled, $approval_required); + } + + private function buildUsageInfo(): InstanceEntity\Usage + { + if (!empty($this->config->get('system', 'nodeinfo'))) { + $active_monthly = intval(DI::keyValue()->get('nodeinfo_active_users_monthly')); + } else { + $active_monthly = 0; + } + + return new InstanceEntity\Usage(new InstanceEntity\UserStats($active_monthly)); + } +} diff --git a/src/Object/Api/Mastodon/Instance.php b/src/Object/Api/Mastodon/Instance.php index b6239550a8..5459694e6a 100644 --- a/src/Object/Api/Mastodon/Instance.php +++ b/src/Object/Api/Mastodon/Instance.php @@ -34,7 +34,7 @@ use Friendica\Network\HTTPException; /** * Class Instance * - * @see https://docs.joinmastodon.org/api/entities/#instance + * @see https://docs.joinmastodon.org/entities/V1_Instance/ */ class Instance extends BaseDataTransferObject { diff --git a/src/Object/Api/Mastodon/InstanceV2.php b/src/Object/Api/Mastodon/InstanceV2.php new file mode 100644 index 0000000000..ec32b944f0 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2.php @@ -0,0 +1,108 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon; + +use Friendica\BaseDataTransferObject; +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 string $domain + * @param string $title + * @param $version + * @param string $description + * @param Usage $usage + * @param Thumbnail $thumbnail + * @param array $languages + * @param Configuration $configuration + * @param Registrations $registrations + * @param Contact $contact + * @param FriendicaExtensions $friendica_extensions + * @param array $rules + */ + public function __construct( + string $domain, + string $title, + string $version, + string $description, + Usage $usage, + Thumbnail $thumbnail, + array $languages, + Configuration $configuration, + Registrations $registrations, + Contact $contact, + FriendicaExtensions $friendica_extensions, + array $rules + ) { + $this->domain = $domain; + $this->title = $title; + $this->version = $version; + $this->source_url = null; //not supported yet + $this->description = $description; + $this->usage = $usage; + $this->thumbnail = $thumbnail; + $this->languages = $languages; + $this->configuration = $configuration; + $this->registrations = $registrations; + $this->contact = $contact; + $this->rules = $rules; + $this->friendica = $friendica_extensions; + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/Configuration.php b/src/Object/Api/Mastodon/InstanceV2/Configuration.php new file mode 100644 index 0000000000..a44c2e060f --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/Configuration.php @@ -0,0 +1,54 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; + +/** + * 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; + + /** + * @param StatusesConfig $statuses + * @param MediaAttachmentsConfig $media_attachments + * @param int $image_size_limit + */ + public function __construct( + StatusesConfig $statuses, + MediaAttachmentsConfig $media_attachments, + int $image_size_limit + ) { + $this->statuses = $statuses; + $this->media_attachments = $media_attachments; + $this->image_size_limit = $image_size_limit; + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/Contact.php b/src/Object/Api/Mastodon/InstanceV2/Contact.php new file mode 100644 index 0000000000..f48b027cf0 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/Contact.php @@ -0,0 +1,49 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; +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|null */ + protected $account = null; + + + /** + * @param string $email + * @param Account $account + */ + public function __construct(string $email, Account $account) + { + $this->email = $email; + $this->account = $account; + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php b/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php new file mode 100644 index 0000000000..d3a2372105 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php @@ -0,0 +1,53 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; + +/** + * Class FriendicaExtensions + * + * Friendica specific additional fields on the Instance V2 object + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class FriendicaExtensions extends BaseDataTransferObject +{ + /** @var string */ + protected $version; + /** @var string */ + protected $codename; + /** @var int */ + protected $db_version; + + /** + * @param string $version + * @param string $codename + * @param int $db_version + */ + public function __construct(string $version, string $codename, int $db_version) + { + $this->version = $version; + $this->codename = $codename; + $this->db_version = $db_version; + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/MediaAttachmentsConfig.php b/src/Object/Api/Mastodon/InstanceV2/MediaAttachmentsConfig.php new file mode 100644 index 0000000000..085bdfd0e2 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/MediaAttachmentsConfig.php @@ -0,0 +1,43 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; + +/** + * Class MediaAttachmentsConfig + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class MediaAttachmentsConfig extends BaseDataTransferObject +{ + /** @var string[] */ + protected $supported_mime_types; + + /** + * @param array $supported_mime_types + */ + public function __construct(array $supported_mime_types) + { + $this->supported_mime_types = $supported_mime_types; + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/Registrations.php b/src/Object/Api/Mastodon/InstanceV2/Registrations.php new file mode 100644 index 0000000000..b4a9054568 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/Registrations.php @@ -0,0 +1,47 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; + +/** + * Class Registrations + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class Registrations extends BaseDataTransferObject +{ + /** @var bool */ + protected $enabled; + /** @var bool */ + protected $approval_required; + + /** + * @param bool $enabled + * @param bool $approval_required + */ + public function __construct(bool $enabled, bool $approval_required) + { + $this->enabled = $enabled; + $this->approval_required = $approval_required; + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/StatusesConfig.php b/src/Object/Api/Mastodon/InstanceV2/StatusesConfig.php new file mode 100644 index 0000000000..aa2af4f047 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/StatusesConfig.php @@ -0,0 +1,43 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; + +/** + * Class StatusConfig + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class StatusesConfig extends BaseDataTransferObject +{ + /** @var int */ + protected $max_characters = 0; + + /** + * @param int $max_characters + */ + public function __construct(int $max_characters) + { + $this->max_characters = $max_characters; + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/Thumbnail.php b/src/Object/Api/Mastodon/InstanceV2/Thumbnail.php new file mode 100644 index 0000000000..3d4989e367 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/Thumbnail.php @@ -0,0 +1,43 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; + +/** + * Class Thumbnail + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class Thumbnail extends BaseDataTransferObject +{ + /** @var string (URL) */ + protected $url; + + /** + * @param string $url + */ + public function __construct(string $url) + { + $this->url = $url; + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/Usage.php b/src/Object/Api/Mastodon/InstanceV2/Usage.php new file mode 100644 index 0000000000..69e26b8ab7 --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/Usage.php @@ -0,0 +1,43 @@ +. + * + */ + +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; + + /** + * @param UserStats $users + */ + public function __construct(UserStats $users) + { + $this->users = $users; + } +} diff --git a/src/Object/Api/Mastodon/InstanceV2/UserStats.php b/src/Object/Api/Mastodon/InstanceV2/UserStats.php new file mode 100644 index 0000000000..8f398e0d5a --- /dev/null +++ b/src/Object/Api/Mastodon/InstanceV2/UserStats.php @@ -0,0 +1,43 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon\InstanceV2; + +use Friendica\BaseDataTransferObject; + +/** + * Class UserStats + * + * @see https://docs.joinmastodon.org/entities/Instance/ + */ +class UserStats extends BaseDataTransferObject +{ + /** @var int */ + protected $active_monthly = 0; + + /** + * @param $active_monthly + */ + public function __construct($active_monthly) + { + $this->active_monthly = $active_monthly; + } +} diff --git a/static/routes.config.php b/static/routes.config.php index 58fce72777..3271571c44 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