From 8101739eddd192314a33abda8a729515ece33b42 Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Sun, 19 Feb 2023 17:32:13 -0500 Subject: [PATCH 01/20] Change Mastodon API documentation URL for V1 Instance type --- src/Object/Api/Mastodon/Instance.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Object/Api/Mastodon/Instance.php b/src/Object/Api/Mastodon/Instance.php index 14914cd7fc..007081e914 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 { From 0451f2dfa1510258b7f551ba3224e885c711e6b3 Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 07:51:20 -0500 Subject: [PATCH 02/20] 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 0000000000..e5af34b67a --- /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 0000000000..f3551c5646 --- /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 0000000000..e30561356b --- /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 0000000000..45631b0fb5 --- /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 0000000000..b69b5c0267 --- /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 0000000000..598736c330 --- /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 0000000000..78c5713ea3 --- /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 0000000000..5bf20ec974 --- /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 0000000000..18cb1bf2a7 --- /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 0000000000..cb49348337 --- /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 0000000000..c82cf563ee --- /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 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 From fcf59dc245c07c4a7b74ef569d602b5b62010162 Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 08:05:01 -0500 Subject: [PATCH 03/20] Fix binary_operator_spaces errors --- src/Module/Api/Mastodon/InstanceV2.php | 2 +- src/Object/Api/Mastodon/InstanceV2.php | 26 +++++++++---------- .../Api/Mastodon/InstanceV2/Contact.php | 2 +- .../InstanceV2/FriendicaExtensions.php | 4 +-- .../Api/Mastodon/InstanceV2/Registrations.php | 6 ++--- .../Mastodon/InstanceV2/StatusesConfig.php | 2 +- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Module/Api/Mastodon/InstanceV2.php b/src/Module/Api/Mastodon/InstanceV2.php index e5af34b67a..3177570c94 100644 --- a/src/Module/Api/Mastodon/InstanceV2.php +++ b/src/Module/Api/Mastodon/InstanceV2.php @@ -59,7 +59,7 @@ class InstanceV2 extends BaseApi parent::__construct($app, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->database = $database; - $this->config = $config; + $this->config = $config; } /** diff --git a/src/Object/Api/Mastodon/InstanceV2.php b/src/Object/Api/Mastodon/InstanceV2.php index f3551c5646..20ea45ba3c 100644 --- a/src/Object/Api/Mastodon/InstanceV2.php +++ b/src/Object/Api/Mastodon/InstanceV2.php @@ -79,18 +79,18 @@ class InstanceV2 extends BaseDataTransferObject */ 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(); + $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/Contact.php b/src/Object/Api/Mastodon/InstanceV2/Contact.php index 45631b0fb5..007c0495bc 100644 --- a/src/Object/Api/Mastodon/InstanceV2/Contact.php +++ b/src/Object/Api/Mastodon/InstanceV2/Contact.php @@ -42,7 +42,7 @@ class Contact extends BaseDataTransferObject public function __construct(Database $database) { - $this->email = implode(',', User::getAdminEmailList()); + $this->email = implode(',', User::getAdminEmailList()); $administrator = User::getFirstAdmin(); if ($administrator) { $adminContact = $database->selectFirst( diff --git a/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php b/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php index b69b5c0267..2805e48665 100644 --- a/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php +++ b/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php @@ -24,8 +24,8 @@ class FriendicaExtensions extends BaseDataTransferObject public function __construct() { - $this->version = App::VERSION; - $this->codename = App::CODENAME; + $this->version = App::VERSION; + $this->codename = App::CODENAME; $this->db_version = DI::config()->get('system', 'build'); } } diff --git a/src/Object/Api/Mastodon/InstanceV2/Registrations.php b/src/Object/Api/Mastodon/InstanceV2/Registrations.php index 78c5713ea3..c1e7769e83 100644 --- a/src/Object/Api/Mastodon/InstanceV2/Registrations.php +++ b/src/Object/Api/Mastodon/InstanceV2/Registrations.php @@ -39,9 +39,9 @@ class Registrations extends BaseDataTransferObject public function __construct() { - $config = DI::config(); - $register_policy = intval($config->get('config', 'register_policy')); - $this->enabled = ($register_policy != Register::CLOSED); + $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 index 5bf20ec974..fb74b1d5bd 100644 --- a/src/Object/Api/Mastodon/InstanceV2/StatusesConfig.php +++ b/src/Object/Api/Mastodon/InstanceV2/StatusesConfig.php @@ -36,7 +36,7 @@ class StatusesConfig extends BaseDataTransferObject public function __construct() { - $config = DI::config(); + $config = DI::config(); $this->max_characters = (int)$config->get( 'config', 'api_import_size', From 0bb2d00e703230738ebb2d1c3ce3e8041f1ece82 Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 08:05:46 -0500 Subject: [PATCH 04/20] Add License header to FriendicaExtensions file --- .../InstanceV2/FriendicaExtensions.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php b/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php index 2805e48665..b5ff02ea5d 100644 --- a/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php +++ b/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php @@ -1,4 +1,23 @@ . + * + */ namespace Friendica\Object\Api\Mastodon\InstanceV2; From e594bb72dd871fe1036617f519ea0fb8417643cc Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 08:53:28 -0500 Subject: [PATCH 05/20] Add notifications summary (count only for now) to Mastodon API --- src/Module/Api/Mastodon/Notifications.php | 62 +++++++++++++---------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/src/Module/Api/Mastodon/Notifications.php b/src/Module/Api/Mastodon/Notifications.php index 3cf60b870c..ab94fee55c 100644 --- a/src/Module/Api/Mastodon/Notifications.php +++ b/src/Module/Api/Mastodon/Notifications.php @@ -56,14 +56,15 @@ class Notifications extends BaseApi } $request = $this->getRequest([ - 'max_id' => 0, // Return results older than this ID - 'since_id' => 0, // Return results newer than this ID - 'min_id' => 0, // Return results immediately newer than this ID - 'limit' => 20, // Maximum number of results to return (default 20) + 'max_id' => 0, // Return results older than this ID + 'since_id' => 0, // Return results newer than this ID + 'min_id' => 0, // Return results immediately newer than this ID + 'limit' => 20, // Maximum number of results to return (default 20) 'exclude_types' => [], // Array of types to exclude (follow, favourite, reblog, mention, poll, follow_request) - 'account_id' => 0, // Return only notifications received from this account - 'with_muted' => false, // Pleroma extension: return activities by muted (not by blocked!) users. - 'include_all' => false // Include dismissed and undismissed + 'account_id' => 0, // Return only notifications received from this account + 'with_muted' => false, // Pleroma extension: return activities by muted (not by blocked!) users. + 'include_all' => false, // Include dismissed and undismissed + 'summary' => false, ], $request); $params = ['order' => ['id' => true]]; @@ -87,8 +88,8 @@ class Notifications extends BaseApi $condition = DBA::mergeConditions( $condition, ["(`vid` != ? OR `type` != ? OR NOT `actor-id` IN (SELECT `id` FROM `contact` WHERE `pending`))", - Verb::getID(Activity::FOLLOW), - Post\UserNotification::TYPE_NONE] + Verb::getID(Activity::FOLLOW), + Post\UserNotification::TYPE_NONE] ); } @@ -96,8 +97,8 @@ class Notifications extends BaseApi $condition = DBA::mergeConditions( $condition, ["(`vid` != ? OR `type` != ? OR NOT `actor-id` IN (SELECT `id` FROM `contact` WHERE NOT `pending`))", - Verb::getID(Activity::FOLLOW), - Post\UserNotification::TYPE_NONE] + Verb::getID(Activity::FOLLOW), + Post\UserNotification::TYPE_NONE] ); } @@ -130,26 +131,31 @@ class Notifications extends BaseApi Verb::getID(Activity::POST), Post\UserNotification::TYPE_SHARED]); } - $mstdnNotifications = []; + if ($request['summary']) { + $count = DI::notification()->countForUser($uid, $condition); + System::jsonExit(['count' => $count]); + } else { + $mstdnNotifications = []; - $Notifications = DI::notification()->selectByBoundaries( - $condition, - $params, - $request['min_id'] ?: $request['since_id'], - $request['max_id'], - $request['limit'] - ); + $Notifications = DI::notification()->selectByBoundaries( + $condition, + $params, + $request['min_id'] ?: $request['since_id'], + $request['max_id'], + $request['limit'] + ); - foreach ($Notifications as $Notification) { - try { - $mstdnNotifications[] = DI::mstdnNotification()->createFromNotification($Notification, self::appSupportsQuotes()); - self::setBoundaries($Notification->id); - } catch (\Exception $e) { - // Skip this notification + foreach ($Notifications as $Notification) { + try { + $mstdnNotifications[] = DI::mstdnNotification()->createFromNotification($Notification, self::appSupportsQuotes()); + self::setBoundaries($Notification->id); + } catch (\Exception $e) { + // Skip this notification + } } - } - self::setLinkHeader(); - System::jsonExit($mstdnNotifications); + self::setLinkHeader(); + System::jsonExit($mstdnNotifications); + } } } From 4abb7ed746c12147bdb3b9c185e7a50cb32fd6ef Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 09:07:50 -0500 Subject: [PATCH 06/20] Fix whitespace issue on assignment alignment --- src/Module/Api/Mastodon/Notifications.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Module/Api/Mastodon/Notifications.php b/src/Module/Api/Mastodon/Notifications.php index ab94fee55c..31fe7a57fb 100644 --- a/src/Module/Api/Mastodon/Notifications.php +++ b/src/Module/Api/Mastodon/Notifications.php @@ -56,15 +56,15 @@ class Notifications extends BaseApi } $request = $this->getRequest([ - 'max_id' => 0, // Return results older than this ID - 'since_id' => 0, // Return results newer than this ID - 'min_id' => 0, // Return results immediately newer than this ID - 'limit' => 20, // Maximum number of results to return (default 20) + 'max_id' => 0, // Return results older than this ID + 'since_id' => 0, // Return results newer than this ID + 'min_id' => 0, // Return results immediately newer than this ID + 'limit' => 20, // Maximum number of results to return (default 20) 'exclude_types' => [], // Array of types to exclude (follow, favourite, reblog, mention, poll, follow_request) - 'account_id' => 0, // Return only notifications received from this account - 'with_muted' => false, // Pleroma extension: return activities by muted (not by blocked!) users. - 'include_all' => false, // Include dismissed and undismissed - 'summary' => false, + 'account_id' => 0, // Return only notifications received from this account + 'with_muted' => false, // Pleroma extension: return activities by muted (not by blocked!) users. + 'include_all' => false, // Include dismissed and undismissed + 'summary' => false, ], $request); $params = ['order' => ['id' => true]]; From 71a7c0a4de5800c33fc92f03c0a388c5a8fd3e75 Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 13:22:29 -0500 Subject: [PATCH 07/20] Refactor Mastodon API InstanceV2 so objects are simple and BI in API layer --- src/Module/Api/Mastodon/InstanceV2.php | 95 ++++++++++++++++++- src/Object/Api/Mastodon/InstanceV2.php | 64 ++++++++----- .../Api/Mastodon/InstanceV2/Configuration.php | 21 ++-- .../Api/Mastodon/InstanceV2/Contact.php | 23 ++--- .../InstanceV2/FriendicaExtensions.php | 15 +-- .../InstanceV2/MediaAttachmentsConfig.php | 9 +- .../Api/Mastodon/InstanceV2/Registrations.php | 14 +-- .../Mastodon/InstanceV2/StatusesConfig.php | 15 ++- .../Api/Mastodon/InstanceV2/Thumbnail.php | 8 +- src/Object/Api/Mastodon/InstanceV2/Usage.php | 7 +- .../Api/Mastodon/InstanceV2/UserStats.php | 11 +-- 11 files changed, 197 insertions(+), 85 deletions(-) diff --git a/src/Module/Api/Mastodon/InstanceV2.php b/src/Module/Api/Mastodon/InstanceV2.php index 3177570c94..c1dd8314f0 100644 --- a/src/Module/Api/Mastodon/InstanceV2.php +++ b/src/Module/Api/Mastodon/InstanceV2.php @@ -21,14 +21,19 @@ 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; @@ -67,9 +72,97 @@ class InstanceV2 extends BaseApi * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \Friendica\Network\HTTPException\NotFoundException * @throws \ImagickException + * @throws Exception */ protected function rawContent(array $request = []) { - System::jsonExit(new InstanceEntity($this->config, $this->baseUrl, $this->database, System::getRules())); + $domain = $this->baseUrl->getHostname(); + $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->get() . '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/InstanceV2.php b/src/Object/Api/Mastodon/InstanceV2.php index 20ea45ba3c..ec32b944f0 100644 --- a/src/Object/Api/Mastodon/InstanceV2.php +++ b/src/Object/Api/Mastodon/InstanceV2.php @@ -21,12 +21,7 @@ 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; @@ -69,28 +64,45 @@ class InstanceV2 extends BaseDataTransferObject protected $friendica; /** - * @param IManageConfigValues $config - * @param BaseURL $baseUrl - * @param Database $database - * @param array $rules - * @throws HTTPException\InternalServerErrorException - * @throws HTTPException\NotFoundException - * @throws \ImagickException + * @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(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); + 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 = new FriendicaExtensions(); + $this->friendica = $friendica_extensions; } } diff --git a/src/Object/Api/Mastodon/InstanceV2/Configuration.php b/src/Object/Api/Mastodon/InstanceV2/Configuration.php index e30561356b..a44c2e060f 100644 --- a/src/Object/Api/Mastodon/InstanceV2/Configuration.php +++ b/src/Object/Api/Mastodon/InstanceV2/Configuration.php @@ -22,7 +22,6 @@ namespace Friendica\Object\Api\Mastodon\InstanceV2; use Friendica\BaseDataTransferObject; -use Friendica\DI; /** * Class Configuration @@ -33,15 +32,23 @@ class Configuration extends BaseDataTransferObject { /** @var StatusesConfig */ protected $statuses; - /** @var MediaAttachmentsConfig */ + /** @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'); + /** + * @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 index 007c0495bc..f48b027cf0 100644 --- a/src/Object/Api/Mastodon/InstanceV2/Contact.php +++ b/src/Object/Api/Mastodon/InstanceV2/Contact.php @@ -22,9 +22,6 @@ 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; /** @@ -36,21 +33,17 @@ class Contact extends BaseDataTransferObject { /** @var string */ protected $email; - /** @var Account */ + /** @var Account|null */ protected $account = null; - public function __construct(Database $database) + /** + * @param string $email + * @param Account $account + */ + public function __construct(string $email, Account $account) { - $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']); - } + $this->email = $email; + $this->account = $account; } } diff --git a/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php b/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php index b5ff02ea5d..d3a2372105 100644 --- a/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php +++ b/src/Object/Api/Mastodon/InstanceV2/FriendicaExtensions.php @@ -21,9 +21,7 @@ namespace Friendica\Object\Api\Mastodon\InstanceV2; -use Friendica\App; use Friendica\BaseDataTransferObject; -use Friendica\DI; /** * Class FriendicaExtensions @@ -41,10 +39,15 @@ class FriendicaExtensions extends BaseDataTransferObject /** @var int */ protected $db_version; - public function __construct() + /** + * @param string $version + * @param string $codename + * @param int $db_version + */ + public function __construct(string $version, string $codename, int $db_version) { - $this->version = App::VERSION; - $this->codename = App::CODENAME; - $this->db_version = DI::config()->get('system', 'build'); + $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 index 598736c330..085bdfd0e2 100644 --- a/src/Object/Api/Mastodon/InstanceV2/MediaAttachmentsConfig.php +++ b/src/Object/Api/Mastodon/InstanceV2/MediaAttachmentsConfig.php @@ -22,7 +22,6 @@ namespace Friendica\Object\Api\Mastodon\InstanceV2; use Friendica\BaseDataTransferObject; -use Friendica\Util\Images; /** * Class MediaAttachmentsConfig @@ -33,8 +32,12 @@ class MediaAttachmentsConfig extends BaseDataTransferObject { /** @var string[] */ protected $supported_mime_types; - public function __construct() + + /** + * @param array $supported_mime_types + */ + public function __construct(array $supported_mime_types) { - $this->supported_mime_types = Images::supportedTypes(); + $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 index c1e7769e83..b4a9054568 100644 --- a/src/Object/Api/Mastodon/InstanceV2/Registrations.php +++ b/src/Object/Api/Mastodon/InstanceV2/Registrations.php @@ -22,8 +22,6 @@ namespace Friendica\Object\Api\Mastodon\InstanceV2; use Friendica\BaseDataTransferObject; -use Friendica\DI; -use Friendica\Module\Register; /** * Class Registrations @@ -37,11 +35,13 @@ class Registrations extends BaseDataTransferObject /** @var bool */ protected $approval_required; - public function __construct() + /** + * @param bool $enabled + * @param bool $approval_required + */ + public function __construct(bool $enabled, bool $approval_required) { - $config = DI::config(); - $register_policy = intval($config->get('config', 'register_policy')); - $this->enabled = ($register_policy != Register::CLOSED); - $this->approval_required = ($register_policy == Register::APPROVE); + $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 index fb74b1d5bd..aa2af4f047 100644 --- a/src/Object/Api/Mastodon/InstanceV2/StatusesConfig.php +++ b/src/Object/Api/Mastodon/InstanceV2/StatusesConfig.php @@ -22,7 +22,6 @@ namespace Friendica\Object\Api\Mastodon\InstanceV2; use Friendica\BaseDataTransferObject; -use Friendica\DI; /** * Class StatusConfig @@ -31,16 +30,14 @@ use Friendica\DI; */ class StatusesConfig extends BaseDataTransferObject { - /** @var int */ + /** @var int */ protected $max_characters = 0; - public function __construct() + /** + * @param int $max_characters + */ + public function __construct(int $max_characters) { - $config = DI::config(); - $this->max_characters = (int)$config->get( - 'config', - 'api_import_size', - $config->get('config', 'max_import_size') - ); + $this->max_characters = $max_characters; } } diff --git a/src/Object/Api/Mastodon/InstanceV2/Thumbnail.php b/src/Object/Api/Mastodon/InstanceV2/Thumbnail.php index 18cb1bf2a7..3d4989e367 100644 --- a/src/Object/Api/Mastodon/InstanceV2/Thumbnail.php +++ b/src/Object/Api/Mastodon/InstanceV2/Thumbnail.php @@ -21,7 +21,6 @@ namespace Friendica\Object\Api\Mastodon\InstanceV2; -use Friendica\App\BaseURL; use Friendica\BaseDataTransferObject; /** @@ -34,8 +33,11 @@ class Thumbnail extends BaseDataTransferObject /** @var string (URL) */ protected $url; - public function __construct(BaseURL $baseUrl) + /** + * @param string $url + */ + public function __construct(string $url) { - $this->url = $baseUrl->get() . 'images/friendica-banner.jpg'; + $this->url = $url; } } diff --git a/src/Object/Api/Mastodon/InstanceV2/Usage.php b/src/Object/Api/Mastodon/InstanceV2/Usage.php index cb49348337..69e26b8ab7 100644 --- a/src/Object/Api/Mastodon/InstanceV2/Usage.php +++ b/src/Object/Api/Mastodon/InstanceV2/Usage.php @@ -33,8 +33,11 @@ class Usage extends BaseDataTransferObject /** @var UserStats */ protected $users; - public function __construct() + /** + * @param UserStats $users + */ + public function __construct(UserStats $users) { - $this->users = new UserStats(); + $this->users = $users; } } diff --git a/src/Object/Api/Mastodon/InstanceV2/UserStats.php b/src/Object/Api/Mastodon/InstanceV2/UserStats.php index c82cf563ee..8f398e0d5a 100644 --- a/src/Object/Api/Mastodon/InstanceV2/UserStats.php +++ b/src/Object/Api/Mastodon/InstanceV2/UserStats.php @@ -22,7 +22,6 @@ namespace Friendica\Object\Api\Mastodon\InstanceV2; use Friendica\BaseDataTransferObject; -use Friendica\DI; /** * Class UserStats @@ -34,11 +33,11 @@ class UserStats extends BaseDataTransferObject /** @var int */ protected $active_monthly = 0; - public function __construct() + /** + * @param $active_monthly + */ + public function __construct($active_monthly) { - $config = DI::config(); - if (!empty($config->get('system', 'nodeinfo'))) { - $this->active_monthly = intval(DI::keyValue()->get('nodeinfo_active_users_monthly')); - } + $this->active_monthly = $active_monthly; } } From 06f53d2d1a11783e1e37e757007de5521543ca8a Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 13:31:04 -0500 Subject: [PATCH 08/20] Add missing spaces after colons for function parameters for style check reasons --- src/Module/Api/Mastodon/InstanceV2.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Module/Api/Mastodon/InstanceV2.php b/src/Module/Api/Mastodon/InstanceV2.php index c1dd8314f0..647d292c73 100644 --- a/src/Module/Api/Mastodon/InstanceV2.php +++ b/src/Module/Api/Mastodon/InstanceV2.php @@ -104,7 +104,7 @@ class InstanceV2 extends BaseApi )); } - private function buildConfigurationInfo():InstanceEntity\Configuration + private function buildConfigurationInfo(): InstanceEntity\Configuration { $statuses_config = new InstanceEntity\StatusesConfig((int)$this->config->get( 'config', @@ -119,7 +119,7 @@ class InstanceV2 extends BaseApi ); } - private function buildContactInfo():InstanceEntity\Contact + private function buildContactInfo(): InstanceEntity\Contact { $email = implode(',', User::getAdminEmailList()); $administrator = User::getFirstAdmin(); @@ -137,7 +137,7 @@ class InstanceV2 extends BaseApi return new InstanceEntity\Contact($email, $account); } - private function buildFriendicaExtensionInfo():InstanceEntity\FriendicaExtensions + private function buildFriendicaExtensionInfo(): InstanceEntity\FriendicaExtensions { return new InstanceEntity\FriendicaExtensions( App::VERSION, @@ -146,7 +146,7 @@ class InstanceV2 extends BaseApi ); } - private function buildRegistrationsInfo():InstanceEntity\Registrations + private function buildRegistrationsInfo(): InstanceEntity\Registrations { $register_policy = intval($this->config->get('config', 'register_policy')); $enabled = ($register_policy != Register::CLOSED); @@ -155,7 +155,7 @@ class InstanceV2 extends BaseApi return new InstanceEntity\Registrations($enabled, $approval_required); } - private function buildUsageInfo():InstanceEntity\Usage + private function buildUsageInfo(): InstanceEntity\Usage { if (!empty($this->config->get('system', 'nodeinfo'))) { $active_monthly = intval(DI::keyValue()->get('nodeinfo_active_users_monthly')); From 6cd271b10f892e8d85c4e542ad07dfb2cc616096 Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 13:33:13 -0500 Subject: [PATCH 09/20] Modify to use the new baseURL methods. --- src/Module/Api/Mastodon/InstanceV2.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Module/Api/Mastodon/InstanceV2.php b/src/Module/Api/Mastodon/InstanceV2.php index 647d292c73..2038081d87 100644 --- a/src/Module/Api/Mastodon/InstanceV2.php +++ b/src/Module/Api/Mastodon/InstanceV2.php @@ -76,12 +76,12 @@ class InstanceV2 extends BaseApi */ protected function rawContent(array $request = []) { - $domain = $this->baseUrl->getHostname(); + $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->get() . 'images/friendica-banner.jpg'); + $thumbnail = new InstanceEntity\Thumbnail($this->baseUrl->withPath('images/friendica-banner.jpg')); $languages = [$this->config->get('system', 'language')]; $configuration = $this->buildConfigurationInfo(); $registration = $this->buildRegistrationsInfo(); From 3a8929be1f9db32f39c4e6010c4608a30aaeb257 Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 15:31:15 -0500 Subject: [PATCH 10/20] Add dislike counts to Mastodon API Statuses in FriendicaExtension --- src/Factory/Api/Mastodon/Status.php | 12 ++++++++++-- src/Object/Api/Mastodon/Status.php | 2 +- src/Object/Api/Mastodon/Status/Counts.php | 13 +++++++++---- .../Api/Mastodon/Status/FriendicaExtension.php | 8 ++++++-- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/Factory/Api/Mastodon/Status.php b/src/Factory/Api/Mastodon/Status.php index 9f6d3bcde9..4d93d08927 100644 --- a/src/Factory/Api/Mastodon/Status.php +++ b/src/Factory/Api/Mastodon/Status.php @@ -144,10 +144,18 @@ class Status extends BaseFactory 'deleted' => false ]); + $count_dislike = Post::countPosts([ + 'thr-parent-id' => $uriId, + 'gravity' => Item::GRAVITY_ACTIVITY, + 'vid' => Verb::getID(Activity::DISLIKE), + 'deleted' => false + ]); + $counts = new \Friendica\Object\Api\Mastodon\Status\Counts( Post::countPosts(['thr-parent-id' => $uriId, 'gravity' => Item::GRAVITY_COMMENT, 'deleted' => false], []), $count_announce, - $count_like + $count_like, + $count_dislike ); $origin_like = ($count_like == 0) ? false : Post::exists([ @@ -323,7 +331,7 @@ class Status extends BaseFactory $replies = $this->dba->count('mail', ['thr-parent-id' => $item['uri-id'], 'reply' => true]); - $counts = new \Friendica\Object\Api\Mastodon\Status\Counts($replies, 0, 0); + $counts = new \Friendica\Object\Api\Mastodon\Status\Counts($replies, 0, 0, 0); $userAttributes = new \Friendica\Object\Api\Mastodon\Status\UserAttributes(false, false, false, false, false); diff --git a/src/Object/Api/Mastodon/Status.php b/src/Object/Api/Mastodon/Status.php index 51f0b1c396..30f554bdf5 100644 --- a/src/Object/Api/Mastodon/Status.php +++ b/src/Object/Api/Mastodon/Status.php @@ -151,7 +151,7 @@ class Status extends BaseDataTransferObject $this->emojis = []; $this->card = $card->toArray() ?: null; $this->poll = $poll; - $this->friendica = new FriendicaExtension($item['title']); + $this->friendica = new FriendicaExtension($item['title'], $counts->dislikes); } /** diff --git a/src/Object/Api/Mastodon/Status/Counts.php b/src/Object/Api/Mastodon/Status/Counts.php index 26eb361cf8..207f78a43d 100644 --- a/src/Object/Api/Mastodon/Status/Counts.php +++ b/src/Object/Api/Mastodon/Status/Counts.php @@ -35,6 +35,9 @@ class Counts /** @var int */ protected $favourites; + /** @var int */ + protected $dislikes; + /** * Creates a status count object * @@ -43,14 +46,16 @@ class Counts * @param int $favourites * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public function __construct(int $replies, int $reblogs, int $favourites) + public function __construct(int $replies, int $reblogs, int $favourites, int $dislikes) { - $this->replies = $replies; - $this->reblogs = $reblogs; + $this->replies = $replies; + $this->reblogs = $reblogs; $this->favourites = $favourites; + $this->dislikes = $dislikes; } - public function __get($name) { + public function __get($name) + { return $this->$name; } } diff --git a/src/Object/Api/Mastodon/Status/FriendicaExtension.php b/src/Object/Api/Mastodon/Status/FriendicaExtension.php index 050c5a0268..1db70f7312 100644 --- a/src/Object/Api/Mastodon/Status/FriendicaExtension.php +++ b/src/Object/Api/Mastodon/Status/FriendicaExtension.php @@ -35,14 +35,18 @@ class FriendicaExtension extends BaseDataTransferObject /** @var string */ protected $title; + /** @var int */ + protected $dislikes_count; + /** * Creates a status count object * * @param string $title * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public function __construct(string $title) + public function __construct(string $title, int $dislikes_count) { - $this->title = $title; + $this->title = $title; + $this->dislikes_count = $dislikes_count; } } From dba74c7940da2b074bb12bb507a8e4c566313fce Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 15:32:03 -0500 Subject: [PATCH 11/20] Fix phpcbf style errors in part of code I didn't change --- src/Factory/Api/Mastodon/Status.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Factory/Api/Mastodon/Status.php b/src/Factory/Api/Mastodon/Status.php index 4d93d08927..788841a9bc 100644 --- a/src/Factory/Api/Mastodon/Status.php +++ b/src/Factory/Api/Mastodon/Status.php @@ -59,12 +59,18 @@ class Status extends BaseFactory /** @var ContentItem */ private $contentItem; - public function __construct(LoggerInterface $logger, Database $dba, - Account $mstdnAccountFactory, Mention $mstdnMentionFactory, - Tag $mstdnTagFactory, Card $mstdnCardFactory, - Attachment $mstdnAttachementFactory, Error $mstdnErrorFactory, - Poll $mstdnPollFactory, ContentItem $contentItem) - { + public function __construct( + LoggerInterface $logger, + Database $dba, + Account $mstdnAccountFactory, + Mention $mstdnMentionFactory, + Tag $mstdnTagFactory, + Card $mstdnCardFactory, + Attachment $mstdnAttachementFactory, + Error $mstdnErrorFactory, + Poll $mstdnPollFactory, + ContentItem $contentItem + ) { parent::__construct($logger); $this->dba = $dba; $this->mstdnAccountFactory = $mstdnAccountFactory; From c235bf299eb82ab08f922e8c229d4ff2c69a6aaf Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 15:33:36 -0500 Subject: [PATCH 12/20] Add Mastodon format compatible (un)dislike endpoint in Friendica API space --- src/Module/Api/Friendica/Statuses/Dislike.php | 54 +++++++++++++++++++ .../Api/Friendica/Statuses/Undislike.php | 54 +++++++++++++++++++ static/routes.config.php | 2 + 3 files changed, 110 insertions(+) create mode 100644 src/Module/Api/Friendica/Statuses/Dislike.php create mode 100644 src/Module/Api/Friendica/Statuses/Undislike.php diff --git a/src/Module/Api/Friendica/Statuses/Dislike.php b/src/Module/Api/Friendica/Statuses/Dislike.php new file mode 100644 index 0000000000..e9690d4858 --- /dev/null +++ b/src/Module/Api/Friendica/Statuses/Dislike.php @@ -0,0 +1,54 @@ +. + * + */ + +namespace Friendica\Module\Api\Friendica\Statuses; + +use Friendica\Core\System; +use Friendica\Database\DBA; +use Friendica\DI; +use Friendica\Model\Item; +use Friendica\Model\Post; +use Friendica\Module\BaseApi; + +/** + * @see https://docs.joinmastodon.org/methods/statuses/ + */ +class Dislike extends BaseApi +{ + protected function post(array $request = []) + { + self::checkAllowedScope(self::SCOPE_WRITE); + $uid = self::getCurrentUserID(); + + if (empty($this->parameters['id'])) { + DI::mstdnError()->UnprocessableEntity(); + } + + $item = Post::selectFirstForUser($uid, ['id'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); + if (!DBA::isResult($item)) { + DI::mstdnError()->RecordNotFound(); + } + + Item::performActivity($item['id'], 'dislike', $uid); + + System::jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes())->toArray()); + } +} diff --git a/src/Module/Api/Friendica/Statuses/Undislike.php b/src/Module/Api/Friendica/Statuses/Undislike.php new file mode 100644 index 0000000000..933d7a1ed5 --- /dev/null +++ b/src/Module/Api/Friendica/Statuses/Undislike.php @@ -0,0 +1,54 @@ +. + * + */ + +namespace Friendica\Module\Api\Friendica\Statuses; + +use Friendica\Core\System; +use Friendica\Database\DBA; +use Friendica\DI; +use Friendica\Model\Item; +use Friendica\Model\Post; +use Friendica\Module\BaseApi; + +/** + * @see https://docs.joinmastodon.org/methods/statuses/ + */ +class Undislike extends BaseApi +{ + protected function post(array $request = []) + { + self::checkAllowedScope(self::SCOPE_WRITE); + $uid = self::getCurrentUserID(); + + if (empty($this->parameters['id'])) { + DI::mstdnError()->UnprocessableEntity(); + } + + $item = Post::selectFirstForUser($uid, ['id'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); + if (!DBA::isResult($item)) { + DI::mstdnError()->RecordNotFound(); + } + + Item::performActivity($item['id'], 'undislike', $uid); + + System::jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes())->toArray()); + } +} diff --git a/static/routes.config.php b/static/routes.config.php index 58fce72777..caf24242b3 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -80,6 +80,8 @@ $apiRoutes = [ '/friendica' => [ '/activity/{verb:attendmaybe|attendno|attendyes|dislike|like|unattendmaybe|unattendno|unattendyes|undislike|unlike}[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Activity::class, [ R::POST]], + '/statuses/{id:\d+}/dislike' => [Module\Api\Friendica\Statuses\Dislike::class, [ R::POST]], + '/statuses/{id:\d+}/undislike' => [Module\Api\Friendica\Statuses\Undislike::class, [ R::POST]], '/notification/seen[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Notification\Seen::class, [ R::POST]], '/notification[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Notification::class, [R::GET ]], '/notifications[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Notification::class, [R::GET ]], From c419aabee42f79abe8df31d4c26bc1e63faae72f Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 15:50:21 -0500 Subject: [PATCH 13/20] Add deleted check to FavouritedBy Mastodon endpoint --- src/Module/Api/Mastodon/Statuses/FavouritedBy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Module/Api/Mastodon/Statuses/FavouritedBy.php b/src/Module/Api/Mastodon/Statuses/FavouritedBy.php index 3bf165798b..8f9fe02f17 100644 --- a/src/Module/Api/Mastodon/Statuses/FavouritedBy.php +++ b/src/Module/Api/Mastodon/Statuses/FavouritedBy.php @@ -49,7 +49,7 @@ class FavouritedBy extends BaseApi DI::mstdnError()->RecordNotFound(); } - $activities = Post::selectPosts(['author-id'], ['thr-parent-id' => $id, 'gravity' => Item::GRAVITY_ACTIVITY, 'verb' => Activity::LIKE]); + $activities = Post::selectPosts(['author-id'], ['thr-parent-id' => $id, 'gravity' => Item::GRAVITY_ACTIVITY, 'verb' => Activity::LIKE, 'deleted' => false]); $accounts = []; From 155e3a701e33d526f6af4fe308917c421751bb4b Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 20 Feb 2023 15:51:17 -0500 Subject: [PATCH 14/20] Add DislikedBy Mastodon compatible endpoint in the Friendica API space --- .../Api/Friendica/Statuses/DislikedBy.php | 62 +++++++++++++++++++ static/routes.config.php | 1 + 2 files changed, 63 insertions(+) create mode 100644 src/Module/Api/Friendica/Statuses/DislikedBy.php diff --git a/src/Module/Api/Friendica/Statuses/DislikedBy.php b/src/Module/Api/Friendica/Statuses/DislikedBy.php new file mode 100644 index 0000000000..81860bc40c --- /dev/null +++ b/src/Module/Api/Friendica/Statuses/DislikedBy.php @@ -0,0 +1,62 @@ +. + * + */ + +namespace Friendica\Module\Api\Friendica\Statuses; + +use Friendica\Core\System; +use Friendica\DI; +use Friendica\Model\Item; +use Friendica\Model\Post; +use Friendica\Module\BaseApi; +use Friendica\Protocol\Activity; + +/** + * @see https://docs.joinmastodon.org/methods/statuses/ + */ +class DislikedBy extends BaseApi +{ + /** + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + */ + protected function rawContent(array $request = []) + { + $uid = self::getCurrentUserID(); + + if (empty($this->parameters['id'])) { + DI::mstdnError()->UnprocessableEntity(); + } + + $id = $this->parameters['id']; + if (!Post::exists(['uri-id' => $id, 'uid' => [0, $uid]])) { + DI::mstdnError()->RecordNotFound(); + } + + $activities = Post::selectPosts(['author-id'], ['thr-parent-id' => $id, 'gravity' => Item::GRAVITY_ACTIVITY, 'verb' => Activity::DISLIKE, 'deleted' => false]); + + $accounts = []; + + while ($activity = Post::fetch($activities)) { + $accounts[] = DI::mstdnAccount()->createFromContactId($activity['author-id'], $uid); + } + + System::jsonExit($accounts); + } +} diff --git a/static/routes.config.php b/static/routes.config.php index caf24242b3..eb55c64ab5 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -81,6 +81,7 @@ $apiRoutes = [ '/activity/{verb:attendmaybe|attendno|attendyes|dislike|like|unattendmaybe|unattendno|unattendyes|undislike|unlike}[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Activity::class, [ R::POST]], '/statuses/{id:\d+}/dislike' => [Module\Api\Friendica\Statuses\Dislike::class, [ R::POST]], + '/statuses/{id:\d+}/disliked_by' => [Module\Api\Friendica\Statuses\DislikedBy::class, [R::GET ]], '/statuses/{id:\d+}/undislike' => [Module\Api\Friendica\Statuses\Undislike::class, [ R::POST]], '/notification/seen[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Notification\Seen::class, [ R::POST]], '/notification[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Notification::class, [R::GET ]], From ed86e9ca9676be39e99c7e14b7adc1c33b630fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Feb 2023 12:56:24 +0100 Subject: [PATCH 15/20] Fixed: - added check for empty file name as the export doesn't work without one: `[Error] Argument 1 passed to Friendica\Moderation\DomainPatternBlocklist::exportToFile() must be of the type string, null given, called in /var/www/.../src/Console/ServerBlock.php on line 110` --- src/Console/ServerBlock.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Console/ServerBlock.php b/src/Console/ServerBlock.php index ed9ff5dbde..4d04dcff81 100644 --- a/src/Console/ServerBlock.php +++ b/src/Console/ServerBlock.php @@ -107,6 +107,11 @@ HELP; { $filename = $this->getArgument(1); + if (empty($filename)) { + $this->out('A file name is required, e.g. ./bin/console serverblock export backup.csv'); + return 1; + } + $this->blocklist->exportToFile($filename); // Success From dffd28cf2076721c935dc000a107bbb04ef70b3a Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 21 Feb 2023 09:07:19 -0500 Subject: [PATCH 16/20] Remove addon table from DB structure - It isn't used anymore in favor of a Config key --- database.sql | 56 +++++++++++++---------------------- doc/database/db_addon.md | 29 ------------------ static/dbstructure.config.php | 17 ----------- 3 files changed, 20 insertions(+), 82 deletions(-) delete mode 100644 doc/database/db_addon.md diff --git a/database.sql b/database.sql index fa11843e43..4c404356f6 100644 --- a/database.sql +++ b/database.sql @@ -340,22 +340,6 @@ CREATE TABLE IF NOT EXISTS `account-user` ( FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Remote and local accounts'; --- --- TABLE addon --- -CREATE TABLE IF NOT EXISTS `addon` ( - `id` int unsigned NOT NULL auto_increment COMMENT '', - `name` varchar(50) NOT NULL DEFAULT '' COMMENT 'addon base (file)name', - `version` varchar(50) NOT NULL DEFAULT '' COMMENT 'currently unused', - `installed` boolean NOT NULL DEFAULT '0' COMMENT 'currently always 1', - `hidden` boolean NOT NULL DEFAULT '0' COMMENT 'currently unused', - `timestamp` int unsigned NOT NULL DEFAULT 0 COMMENT 'file timestamp to check for reloads', - `plugin_admin` boolean NOT NULL DEFAULT '0' COMMENT '1 = has admin config, 0 = has no admin config', - PRIMARY KEY(`id`), - INDEX `installed_name` (`installed`,`name`), - UNIQUE INDEX `name` (`name`) -) DEFAULT COLLATE utf8mb4_general_ci COMMENT='registered addons'; - -- -- TABLE apcontact -- @@ -1871,7 +1855,7 @@ CREATE TABLE IF NOT EXISTS `worker-ipc` ( -- VIEW application-view -- DROP VIEW IF EXISTS `application-view`; -CREATE VIEW `application-view` AS SELECT +CREATE VIEW `application-view` AS SELECT `application`.`id` AS `id`, `application-token`.`uid` AS `uid`, `application`.`name` AS `name`, @@ -1894,7 +1878,7 @@ CREATE VIEW `application-view` AS SELECT -- VIEW post-user-view -- DROP VIEW IF EXISTS `post-user-view`; -CREATE VIEW `post-user-view` AS SELECT +CREATE VIEW `post-user-view` AS SELECT `post-user`.`id` AS `id`, `post-user`.`id` AS `post-user-id`, `post-user`.`uid` AS `uid`, @@ -2073,7 +2057,7 @@ CREATE VIEW `post-user-view` AS SELECT -- VIEW post-thread-user-view -- DROP VIEW IF EXISTS `post-thread-user-view`; -CREATE VIEW `post-thread-user-view` AS SELECT +CREATE VIEW `post-thread-user-view` AS SELECT `post-user`.`id` AS `id`, `post-user`.`id` AS `post-user-id`, `post-thread-user`.`uid` AS `uid`, @@ -2250,7 +2234,7 @@ CREATE VIEW `post-thread-user-view` AS SELECT -- VIEW post-view -- DROP VIEW IF EXISTS `post-view`; -CREATE VIEW `post-view` AS SELECT +CREATE VIEW `post-view` AS SELECT `item-uri`.`uri` AS `uri`, `post`.`uri-id` AS `uri-id`, `parent-item-uri`.`uri` AS `parent-uri`, @@ -2390,7 +2374,7 @@ CREATE VIEW `post-view` AS SELECT -- VIEW post-thread-view -- DROP VIEW IF EXISTS `post-thread-view`; -CREATE VIEW `post-thread-view` AS SELECT +CREATE VIEW `post-thread-view` AS SELECT `item-uri`.`uri` AS `uri`, `post-thread`.`uri-id` AS `uri-id`, `parent-item-uri`.`uri` AS `parent-uri`, @@ -2532,7 +2516,7 @@ CREATE VIEW `post-thread-view` AS SELECT -- VIEW category-view -- DROP VIEW IF EXISTS `category-view`; -CREATE VIEW `category-view` AS SELECT +CREATE VIEW `category-view` AS SELECT `post-category`.`uri-id` AS `uri-id`, `post-category`.`uid` AS `uid`, `post-category`.`type` AS `type`, @@ -2546,7 +2530,7 @@ CREATE VIEW `category-view` AS SELECT -- VIEW collection-view -- DROP VIEW IF EXISTS `collection-view`; -CREATE VIEW `collection-view` AS SELECT +CREATE VIEW `collection-view` AS SELECT `post-collection`.`uri-id` AS `uri-id`, `post-collection`.`type` AS `type`, `post-collection`.`author-id` AS `cid`, @@ -2567,7 +2551,7 @@ CREATE VIEW `collection-view` AS SELECT -- VIEW media-view -- DROP VIEW IF EXISTS `media-view`; -CREATE VIEW `media-view` AS SELECT +CREATE VIEW `media-view` AS SELECT `post-media`.`uri-id` AS `uri-id`, `post-media`.`type` AS `type`, `post`.`received` AS `received`, @@ -2585,7 +2569,7 @@ CREATE VIEW `media-view` AS SELECT -- VIEW tag-view -- DROP VIEW IF EXISTS `tag-view`; -CREATE VIEW `tag-view` AS SELECT +CREATE VIEW `tag-view` AS SELECT `post-tag`.`uri-id` AS `uri-id`, `post-tag`.`type` AS `type`, `post-tag`.`tid` AS `tid`, @@ -2601,7 +2585,7 @@ CREATE VIEW `tag-view` AS SELECT -- VIEW network-item-view -- DROP VIEW IF EXISTS `network-item-view`; -CREATE VIEW `network-item-view` AS SELECT +CREATE VIEW `network-item-view` AS SELECT `post-user`.`uri-id` AS `uri-id`, `parent-post`.`id` AS `parent`, `post-user`.`received` AS `received`, @@ -2616,7 +2600,7 @@ CREATE VIEW `network-item-view` AS SELECT `post-user`.`contact-id` AS `contact-id`, `ownercontact`.`contact-type` AS `contact-type` FROM `post-user` - STRAIGHT_JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` + STRAIGHT_JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` INNER JOIN `contact` ON `contact`.`id` = `post-thread-user`.`contact-id` LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `post-thread-user`.`uid` AND `author`.`cid` = `post-thread-user`.`author-id` LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `post-thread-user`.`uid` AND `owner`.`cid` = `post-thread-user`.`owner-id` @@ -2632,7 +2616,7 @@ CREATE VIEW `network-item-view` AS SELECT -- VIEW network-thread-view -- DROP VIEW IF EXISTS `network-thread-view`; -CREATE VIEW `network-thread-view` AS SELECT +CREATE VIEW `network-thread-view` AS SELECT `post-thread-user`.`uri-id` AS `uri-id`, `parent-post`.`id` AS `parent`, `post-thread-user`.`received` AS `received`, @@ -2661,7 +2645,7 @@ CREATE VIEW `network-thread-view` AS SELECT -- VIEW owner-view -- DROP VIEW IF EXISTS `owner-view`; -CREATE VIEW `owner-view` AS SELECT +CREATE VIEW `owner-view` AS SELECT `contact`.`id` AS `id`, `contact`.`uid` AS `uid`, `contact`.`created` AS `created`, @@ -2791,7 +2775,7 @@ CREATE VIEW `owner-view` AS SELECT -- VIEW account-view -- DROP VIEW IF EXISTS `account-view`; -CREATE VIEW `account-view` AS SELECT +CREATE VIEW `account-view` AS SELECT `contact`.`id` AS `id`, `contact`.`url` AS `url`, `contact`.`nurl` AS `nurl`, @@ -2877,7 +2861,7 @@ CREATE VIEW `account-view` AS SELECT -- VIEW account-user-view -- DROP VIEW IF EXISTS `account-user-view`; -CREATE VIEW `account-user-view` AS SELECT +CREATE VIEW `account-user-view` AS SELECT `ucontact`.`id` AS `id`, `contact`.`id` AS `pid`, `ucontact`.`uid` AS `uid`, @@ -2981,7 +2965,7 @@ CREATE VIEW `account-user-view` AS SELECT -- VIEW pending-view -- DROP VIEW IF EXISTS `pending-view`; -CREATE VIEW `pending-view` AS SELECT +CREATE VIEW `pending-view` AS SELECT `register`.`id` AS `id`, `register`.`hash` AS `hash`, `register`.`created` AS `created`, @@ -3003,7 +2987,7 @@ CREATE VIEW `pending-view` AS SELECT -- VIEW tag-search-view -- DROP VIEW IF EXISTS `tag-search-view`; -CREATE VIEW `tag-search-view` AS SELECT +CREATE VIEW `tag-search-view` AS SELECT `post-tag`.`uri-id` AS `uri-id`, `post-user`.`uid` AS `uid`, `post-user`.`id` AS `iid`, @@ -3025,7 +3009,7 @@ CREATE VIEW `tag-search-view` AS SELECT -- VIEW workerqueue-view -- DROP VIEW IF EXISTS `workerqueue-view`; -CREATE VIEW `workerqueue-view` AS SELECT +CREATE VIEW `workerqueue-view` AS SELECT `process`.`pid` AS `pid`, `workerqueue`.`priority` AS `priority` FROM `process` @@ -3036,7 +3020,7 @@ CREATE VIEW `workerqueue-view` AS SELECT -- VIEW profile_field-view -- DROP VIEW IF EXISTS `profile_field-view`; -CREATE VIEW `profile_field-view` AS SELECT +CREATE VIEW `profile_field-view` AS SELECT `profile_field`.`id` AS `id`, `profile_field`.`uid` AS `uid`, `profile_field`.`label` AS `label`, @@ -3056,7 +3040,7 @@ CREATE VIEW `profile_field-view` AS SELECT -- VIEW diaspora-contact-view -- DROP VIEW IF EXISTS `diaspora-contact-view`; -CREATE VIEW `diaspora-contact-view` AS SELECT +CREATE VIEW `diaspora-contact-view` AS SELECT `diaspora-contact`.`uri-id` AS `uri-id`, `item-uri`.`uri` AS `url`, `item-uri`.`guid` AS `guid`, diff --git a/doc/database/db_addon.md b/doc/database/db_addon.md deleted file mode 100644 index 7233b80095..0000000000 --- a/doc/database/db_addon.md +++ /dev/null @@ -1,29 +0,0 @@ -Table addon -=========== - -registered addons - -Fields ------- - -| Field | Description | Type | Null | Key | Default | Extra | -| ------------ | --------------------------------------------- | ------------ | ---- | --- | ------- | -------------- | -| id | | int unsigned | NO | PRI | NULL | auto_increment | -| name | addon base (file)name | varchar(50) | NO | | | | -| version | currently unused | varchar(50) | NO | | | | -| installed | currently always 1 | boolean | NO | | 0 | | -| hidden | currently unused | boolean | NO | | 0 | | -| timestamp | file timestamp to check for reloads | int unsigned | NO | | 0 | | -| plugin_admin | 1 = has admin config, 0 = has no admin config | boolean | NO | | 0 | | - -Indexes ------------- - -| Name | Fields | -| -------------- | --------------- | -| PRIMARY | id | -| installed_name | installed, name | -| name | UNIQUE, name | - - -Return to [database documentation](help/database) diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 9179921d05..cc420a449b 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -399,23 +399,6 @@ return [ "uid_uri-id" => ["uid", "uri-id"], ] ], - "addon" => [ - "comment" => "registered addons", - "fields" => [ - "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""], - "name" => ["type" => "varchar(50)", "not null" => "1", "default" => "", "comment" => "addon base (file)name"], - "version" => ["type" => "varchar(50)", "not null" => "1", "default" => "", "comment" => "currently unused"], - "installed" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "currently always 1"], - "hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "currently unused"], - "timestamp" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "file timestamp to check for reloads"], - "plugin_admin" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 = has admin config, 0 = has no admin config"], - ], - "indexes" => [ - "PRIMARY" => ["id"], - "installed_name" => ["installed", "name"], - "name" => ["UNIQUE", "name"], - ] - ], "apcontact" => [ "comment" => "ActivityPub compatible contacts - used in the ActivityPub implementation", "fields" => [ From 7e92adef6c37b0f19f1660f9e7c276972a00b9b1 Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 21 Feb 2023 21:01:40 +0100 Subject: [PATCH 17/20] Fix API tests without addon table --- tests/src/Module/Api/ApiTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/src/Module/Api/ApiTest.php b/tests/src/Module/Api/ApiTest.php index 90dfa30b0a..812993aa98 100644 --- a/tests/src/Module/Api/ApiTest.php +++ b/tests/src/Module/Api/ApiTest.php @@ -24,6 +24,7 @@ namespace Friendica\Test\src\Module\Api; use Friendica\App; use Friendica\Capabilities\ICanCreateResponses; use Friendica\Core\Addon; +use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Hook; use Friendica\Database\Database; use Friendica\DI; @@ -212,15 +213,14 @@ abstract class ApiTest extends FixtureTest $func(DI::app()); } - /** @var Database $dba */ - $dba = $this->dice->create(Database::class); + /** @var $config IManageConfigValues */ + $config = $this->dice->create(IManageConfigValues::class); - $dba->insert('addon', [ + $config->set('addons', $addon, [ 'name' => $addon, 'installed' => true, 'timestamp' => $t, 'plugin_admin' => function_exists($addon . '_addon_admin'), - 'hidden' => file_exists('addon/' . $addon . '/.hidden') ]); Addon::loadAddons(); From fae2c6632caab1dda8eb5004297900b0c2a0159e Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 21 Feb 2023 21:01:57 +0100 Subject: [PATCH 18/20] Fix database --- database.sql | 40 ++++++++++++++++++++-------------------- doc/database.md | 1 - 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/database.sql b/database.sql index 4c404356f6..ac3eaaf1df 100644 --- a/database.sql +++ b/database.sql @@ -1855,7 +1855,7 @@ CREATE TABLE IF NOT EXISTS `worker-ipc` ( -- VIEW application-view -- DROP VIEW IF EXISTS `application-view`; -CREATE VIEW `application-view` AS SELECT +CREATE VIEW `application-view` AS SELECT `application`.`id` AS `id`, `application-token`.`uid` AS `uid`, `application`.`name` AS `name`, @@ -1878,7 +1878,7 @@ CREATE VIEW `application-view` AS SELECT -- VIEW post-user-view -- DROP VIEW IF EXISTS `post-user-view`; -CREATE VIEW `post-user-view` AS SELECT +CREATE VIEW `post-user-view` AS SELECT `post-user`.`id` AS `id`, `post-user`.`id` AS `post-user-id`, `post-user`.`uid` AS `uid`, @@ -2057,7 +2057,7 @@ CREATE VIEW `post-user-view` AS SELECT -- VIEW post-thread-user-view -- DROP VIEW IF EXISTS `post-thread-user-view`; -CREATE VIEW `post-thread-user-view` AS SELECT +CREATE VIEW `post-thread-user-view` AS SELECT `post-user`.`id` AS `id`, `post-user`.`id` AS `post-user-id`, `post-thread-user`.`uid` AS `uid`, @@ -2234,7 +2234,7 @@ CREATE VIEW `post-thread-user-view` AS SELECT -- VIEW post-view -- DROP VIEW IF EXISTS `post-view`; -CREATE VIEW `post-view` AS SELECT +CREATE VIEW `post-view` AS SELECT `item-uri`.`uri` AS `uri`, `post`.`uri-id` AS `uri-id`, `parent-item-uri`.`uri` AS `parent-uri`, @@ -2374,7 +2374,7 @@ CREATE VIEW `post-view` AS SELECT -- VIEW post-thread-view -- DROP VIEW IF EXISTS `post-thread-view`; -CREATE VIEW `post-thread-view` AS SELECT +CREATE VIEW `post-thread-view` AS SELECT `item-uri`.`uri` AS `uri`, `post-thread`.`uri-id` AS `uri-id`, `parent-item-uri`.`uri` AS `parent-uri`, @@ -2516,7 +2516,7 @@ CREATE VIEW `post-thread-view` AS SELECT -- VIEW category-view -- DROP VIEW IF EXISTS `category-view`; -CREATE VIEW `category-view` AS SELECT +CREATE VIEW `category-view` AS SELECT `post-category`.`uri-id` AS `uri-id`, `post-category`.`uid` AS `uid`, `post-category`.`type` AS `type`, @@ -2530,7 +2530,7 @@ CREATE VIEW `category-view` AS SELECT -- VIEW collection-view -- DROP VIEW IF EXISTS `collection-view`; -CREATE VIEW `collection-view` AS SELECT +CREATE VIEW `collection-view` AS SELECT `post-collection`.`uri-id` AS `uri-id`, `post-collection`.`type` AS `type`, `post-collection`.`author-id` AS `cid`, @@ -2551,7 +2551,7 @@ CREATE VIEW `collection-view` AS SELECT -- VIEW media-view -- DROP VIEW IF EXISTS `media-view`; -CREATE VIEW `media-view` AS SELECT +CREATE VIEW `media-view` AS SELECT `post-media`.`uri-id` AS `uri-id`, `post-media`.`type` AS `type`, `post`.`received` AS `received`, @@ -2569,7 +2569,7 @@ CREATE VIEW `media-view` AS SELECT -- VIEW tag-view -- DROP VIEW IF EXISTS `tag-view`; -CREATE VIEW `tag-view` AS SELECT +CREATE VIEW `tag-view` AS SELECT `post-tag`.`uri-id` AS `uri-id`, `post-tag`.`type` AS `type`, `post-tag`.`tid` AS `tid`, @@ -2585,7 +2585,7 @@ CREATE VIEW `tag-view` AS SELECT -- VIEW network-item-view -- DROP VIEW IF EXISTS `network-item-view`; -CREATE VIEW `network-item-view` AS SELECT +CREATE VIEW `network-item-view` AS SELECT `post-user`.`uri-id` AS `uri-id`, `parent-post`.`id` AS `parent`, `post-user`.`received` AS `received`, @@ -2600,7 +2600,7 @@ CREATE VIEW `network-item-view` AS SELECT `post-user`.`contact-id` AS `contact-id`, `ownercontact`.`contact-type` AS `contact-type` FROM `post-user` - STRAIGHT_JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` + STRAIGHT_JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` INNER JOIN `contact` ON `contact`.`id` = `post-thread-user`.`contact-id` LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `post-thread-user`.`uid` AND `author`.`cid` = `post-thread-user`.`author-id` LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `post-thread-user`.`uid` AND `owner`.`cid` = `post-thread-user`.`owner-id` @@ -2616,7 +2616,7 @@ CREATE VIEW `network-item-view` AS SELECT -- VIEW network-thread-view -- DROP VIEW IF EXISTS `network-thread-view`; -CREATE VIEW `network-thread-view` AS SELECT +CREATE VIEW `network-thread-view` AS SELECT `post-thread-user`.`uri-id` AS `uri-id`, `parent-post`.`id` AS `parent`, `post-thread-user`.`received` AS `received`, @@ -2645,7 +2645,7 @@ CREATE VIEW `network-thread-view` AS SELECT -- VIEW owner-view -- DROP VIEW IF EXISTS `owner-view`; -CREATE VIEW `owner-view` AS SELECT +CREATE VIEW `owner-view` AS SELECT `contact`.`id` AS `id`, `contact`.`uid` AS `uid`, `contact`.`created` AS `created`, @@ -2775,7 +2775,7 @@ CREATE VIEW `owner-view` AS SELECT -- VIEW account-view -- DROP VIEW IF EXISTS `account-view`; -CREATE VIEW `account-view` AS SELECT +CREATE VIEW `account-view` AS SELECT `contact`.`id` AS `id`, `contact`.`url` AS `url`, `contact`.`nurl` AS `nurl`, @@ -2861,7 +2861,7 @@ CREATE VIEW `account-view` AS SELECT -- VIEW account-user-view -- DROP VIEW IF EXISTS `account-user-view`; -CREATE VIEW `account-user-view` AS SELECT +CREATE VIEW `account-user-view` AS SELECT `ucontact`.`id` AS `id`, `contact`.`id` AS `pid`, `ucontact`.`uid` AS `uid`, @@ -2965,7 +2965,7 @@ CREATE VIEW `account-user-view` AS SELECT -- VIEW pending-view -- DROP VIEW IF EXISTS `pending-view`; -CREATE VIEW `pending-view` AS SELECT +CREATE VIEW `pending-view` AS SELECT `register`.`id` AS `id`, `register`.`hash` AS `hash`, `register`.`created` AS `created`, @@ -2987,7 +2987,7 @@ CREATE VIEW `pending-view` AS SELECT -- VIEW tag-search-view -- DROP VIEW IF EXISTS `tag-search-view`; -CREATE VIEW `tag-search-view` AS SELECT +CREATE VIEW `tag-search-view` AS SELECT `post-tag`.`uri-id` AS `uri-id`, `post-user`.`uid` AS `uid`, `post-user`.`id` AS `iid`, @@ -3009,7 +3009,7 @@ CREATE VIEW `tag-search-view` AS SELECT -- VIEW workerqueue-view -- DROP VIEW IF EXISTS `workerqueue-view`; -CREATE VIEW `workerqueue-view` AS SELECT +CREATE VIEW `workerqueue-view` AS SELECT `process`.`pid` AS `pid`, `workerqueue`.`priority` AS `priority` FROM `process` @@ -3020,7 +3020,7 @@ CREATE VIEW `workerqueue-view` AS SELECT -- VIEW profile_field-view -- DROP VIEW IF EXISTS `profile_field-view`; -CREATE VIEW `profile_field-view` AS SELECT +CREATE VIEW `profile_field-view` AS SELECT `profile_field`.`id` AS `id`, `profile_field`.`uid` AS `uid`, `profile_field`.`label` AS `label`, @@ -3040,7 +3040,7 @@ CREATE VIEW `profile_field-view` AS SELECT -- VIEW diaspora-contact-view -- DROP VIEW IF EXISTS `diaspora-contact-view`; -CREATE VIEW `diaspora-contact-view` AS SELECT +CREATE VIEW `diaspora-contact-view` AS SELECT `diaspora-contact`.`uri-id` AS `uri-id`, `item-uri`.`uri` AS `url`, `item-uri`.`guid` AS `guid`, diff --git a/doc/database.md b/doc/database.md index edfb7b8226..461c1c2d9b 100644 --- a/doc/database.md +++ b/doc/database.md @@ -10,7 +10,6 @@ Database Tables | [2fa_trusted_browser](help/database/db_2fa_trusted_browser) | Two-factor authentication trusted browsers | | [account-suggestion](help/database/db_account-suggestion) | Account suggestion | | [account-user](help/database/db_account-user) | Remote and local accounts | -| [addon](help/database/db_addon) | registered addons | | [apcontact](help/database/db_apcontact) | ActivityPub compatible contacts - used in the ActivityPub implementation | | [application](help/database/db_application) | OAuth application | | [application-marker](help/database/db_application-marker) | Timeline marker | From 433dd3e6efc8391d79e2e85e8a87e87ce6f07adf Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 21 Feb 2023 21:37:00 +0100 Subject: [PATCH 19/20] Update json-ld to 1.1.2 - Add support for local files for unsecured document loading --- composer.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.lock b/composer.lock index 0034780263..f9b96b1d9d 100644 --- a/composer.lock +++ b/composer.lock @@ -671,11 +671,11 @@ }, { "name": "friendica/json-ld", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://git.friendi.ca/friendica/php-json-ld", - "reference": "ca3916d10d2ad9073b3b1eae383978dbe828e1e1" + "reference": "5f6ea87b261d346e57f03457ae906e6835f0205f" }, "require": { "ext-json": "*", @@ -711,7 +711,7 @@ "Semantic Web", "jsonld" ], - "time": "2018-10-08T20:41:00+00:00" + "time": "2023-02-20T21:56:16+00:00" }, { "name": "fxp/composer-asset-plugin", From 08ba9e4183718df1941889a572c8bc9ddd190232 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 21 Feb 2023 21:07:41 +0000 Subject: [PATCH 20/20] Fix emoji activities --- src/Content/Conversation.php | 4 ++-- src/Model/Item.php | 2 +- src/Protocol/OStatus.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Content/Conversation.php b/src/Content/Conversation.php index 8107759534..249190b1ad 100644 --- a/src/Content/Conversation.php +++ b/src/Content/Conversation.php @@ -1146,8 +1146,8 @@ class Conversation $emojis[$row['thr-parent-id']][$index]['emoji'] = $emoji; $emojis[$row['thr-parent-id']][$index]['verb'] = $row['verb']; - $emojis[$row['thr-parent-id']][$index]['total'] = $emojis[$row['thr-parent-id']][$emoji]['total'] ?? 0 + $row['total']; - $emojis[$row['thr-parent-id']][$index]['title'] = array_unique(array_merge($emojis[$row['thr-parent-id']][$emoji]['title'] ?? [], explode($separator, $row['title']))); + $emojis[$row['thr-parent-id']][$index]['total'] = ($emojis[$row['thr-parent-id']][$index]['total'] ?? 0) + $row['total']; + $emojis[$row['thr-parent-id']][$index]['title'] = array_unique(array_merge($emojis[$row['thr-parent-id']][$index]['title'] ?? [], explode($separator, $row['title']))); } DBA::close($rows); diff --git a/src/Model/Item.php b/src/Model/Item.php index feb7ae6be6..a62d3c2e6e 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1212,7 +1212,7 @@ class Item } // The content of activities normally doesn't matter - except for likes from Misskey - if (!in_array($item['verb'], self::ACTIVITIES) || in_array($item['verb'], [Activity::LIKE, Activity::DISLIKE]) && !empty($item['body']) && ($item['body'] != $item['verb'])) { + if (!in_array($item['verb'], self::ACTIVITIES) || in_array($item['verb'], [Activity::LIKE, Activity::DISLIKE]) && !empty($item['body']) && (mb_strlen($item['body']) == 1)) { Post\Content::insert($item['uri-id'], $item); } diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index 80644329ff..a93a0584dd 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -496,7 +496,7 @@ class OStatus $orig_uri = $xpath->query('activity:object/atom:id', $entry)->item(0)->nodeValue; Logger::notice('Favorite', ['uri' => $orig_uri, 'item' => $item]); - $item['verb'] = Activity::LIKE; + $item['body'] = $item['verb'] = Activity::LIKE; $item['thr-parent'] = $orig_uri; $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['object-type'] = Activity\ObjectType::NOTE;