Merge branch 'develop' into blocks-status-fix

This commit is contained in:
Hank Grabowski 2023-02-22 12:08:06 -05:00
commit 7224c0fc38
32 changed files with 952 additions and 114 deletions

6
composer.lock generated
View file

@ -671,11 +671,11 @@
}, },
{ {
"name": "friendica/json-ld", "name": "friendica/json-ld",
"version": "1.1.1", "version": "1.1.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://git.friendi.ca/friendica/php-json-ld", "url": "https://git.friendi.ca/friendica/php-json-ld",
"reference": "ca3916d10d2ad9073b3b1eae383978dbe828e1e1" "reference": "5f6ea87b261d346e57f03457ae906e6835f0205f"
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
@ -711,7 +711,7 @@
"Semantic Web", "Semantic Web",
"jsonld" "jsonld"
], ],
"time": "2018-10-08T20:41:00+00:00" "time": "2023-02-20T21:56:16+00:00"
}, },
{ {
"name": "fxp/composer-asset-plugin", "name": "fxp/composer-asset-plugin",

View file

@ -340,22 +340,6 @@ CREATE TABLE IF NOT EXISTS `account-user` (
FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Remote and local accounts'; ) 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 -- TABLE apcontact
-- --

View file

@ -10,7 +10,6 @@ Database Tables
| [2fa_trusted_browser](help/database/db_2fa_trusted_browser) | Two-factor authentication trusted browsers | | [2fa_trusted_browser](help/database/db_2fa_trusted_browser) | Two-factor authentication trusted browsers |
| [account-suggestion](help/database/db_account-suggestion) | Account suggestion | | [account-suggestion](help/database/db_account-suggestion) | Account suggestion |
| [account-user](help/database/db_account-user) | Remote and local accounts | | [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 | | [apcontact](help/database/db_apcontact) | ActivityPub compatible contacts - used in the ActivityPub implementation |
| [application](help/database/db_application) | OAuth application | | [application](help/database/db_application) | OAuth application |
| [application-marker](help/database/db_application-marker) | Timeline marker | | [application-marker](help/database/db_application-marker) | Timeline marker |

View file

@ -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)

View file

@ -107,6 +107,11 @@ HELP;
{ {
$filename = $this->getArgument(1); $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); $this->blocklist->exportToFile($filename);
// Success // Success

View file

@ -1146,8 +1146,8 @@ class Conversation
$emojis[$row['thr-parent-id']][$index]['emoji'] = $emoji; $emojis[$row['thr-parent-id']][$index]['emoji'] = $emoji;
$emojis[$row['thr-parent-id']][$index]['verb'] = $row['verb']; $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]['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']][$emoji]['title'] ?? [], explode($separator, $row['title']))); $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); DBA::close($rows);

View file

@ -59,12 +59,18 @@ class Status extends BaseFactory
/** @var ContentItem */ /** @var ContentItem */
private $contentItem; private $contentItem;
public function __construct(LoggerInterface $logger, Database $dba, public function __construct(
Account $mstdnAccountFactory, Mention $mstdnMentionFactory, LoggerInterface $logger,
Tag $mstdnTagFactory, Card $mstdnCardFactory, Database $dba,
Attachment $mstdnAttachementFactory, Error $mstdnErrorFactory, Account $mstdnAccountFactory,
Poll $mstdnPollFactory, ContentItem $contentItem) Mention $mstdnMentionFactory,
{ Tag $mstdnTagFactory,
Card $mstdnCardFactory,
Attachment $mstdnAttachementFactory,
Error $mstdnErrorFactory,
Poll $mstdnPollFactory,
ContentItem $contentItem
) {
parent::__construct($logger); parent::__construct($logger);
$this->dba = $dba; $this->dba = $dba;
$this->mstdnAccountFactory = $mstdnAccountFactory; $this->mstdnAccountFactory = $mstdnAccountFactory;
@ -144,10 +150,18 @@ class Status extends BaseFactory
'deleted' => false '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( $counts = new \Friendica\Object\Api\Mastodon\Status\Counts(
Post::countPosts(['thr-parent-id' => $uriId, 'gravity' => Item::GRAVITY_COMMENT, 'deleted' => false], []), Post::countPosts(['thr-parent-id' => $uriId, 'gravity' => Item::GRAVITY_COMMENT, 'deleted' => false], []),
$count_announce, $count_announce,
$count_like $count_like,
$count_dislike
); );
$origin_like = ($count_like == 0) ? false : Post::exists([ $origin_like = ($count_like == 0) ? false : Post::exists([
@ -323,7 +337,7 @@ class Status extends BaseFactory
$replies = $this->dba->count('mail', ['thr-parent-id' => $item['uri-id'], 'reply' => true]); $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); $userAttributes = new \Friendica\Object\Api\Mastodon\Status\UserAttributes(false, false, false, false, false);

View file

@ -1212,7 +1212,7 @@ class Item
} }
// The content of activities normally doesn't matter - except for likes from Misskey // 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); Post\Content::insert($item['uri-id'], $item);
} }

View file

@ -0,0 +1,54 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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());
}
}

View file

@ -0,0 +1,62 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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);
}
}

View file

@ -0,0 +1,54 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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());
}
}

View file

@ -0,0 +1,168 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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));
}
}

View file

@ -63,7 +63,8 @@ class Notifications extends BaseApi
'exclude_types' => [], // Array of types to exclude (follow, favourite, reblog, mention, poll, follow_request) 'exclude_types' => [], // Array of types to exclude (follow, favourite, reblog, mention, poll, follow_request)
'account_id' => 0, // Return only notifications received from this account 'account_id' => 0, // Return only notifications received from this account
'with_muted' => false, // Pleroma extension: return activities by muted (not by blocked!) users. 'with_muted' => false, // Pleroma extension: return activities by muted (not by blocked!) users.
'include_all' => false // Include dismissed and undismissed 'include_all' => false, // Include dismissed and undismissed
'summary' => false,
], $request); ], $request);
$params = ['order' => ['id' => true]]; $params = ['order' => ['id' => true]];
@ -87,8 +88,8 @@ class Notifications extends BaseApi
$condition = DBA::mergeConditions( $condition = DBA::mergeConditions(
$condition, $condition,
["(`vid` != ? OR `type` != ? OR NOT `actor-id` IN (SELECT `id` FROM `contact` WHERE `pending`))", ["(`vid` != ? OR `type` != ? OR NOT `actor-id` IN (SELECT `id` FROM `contact` WHERE `pending`))",
Verb::getID(Activity::FOLLOW), Verb::getID(Activity::FOLLOW),
Post\UserNotification::TYPE_NONE] Post\UserNotification::TYPE_NONE]
); );
} }
@ -96,8 +97,8 @@ class Notifications extends BaseApi
$condition = DBA::mergeConditions( $condition = DBA::mergeConditions(
$condition, $condition,
["(`vid` != ? OR `type` != ? OR NOT `actor-id` IN (SELECT `id` FROM `contact` WHERE NOT `pending`))", ["(`vid` != ? OR `type` != ? OR NOT `actor-id` IN (SELECT `id` FROM `contact` WHERE NOT `pending`))",
Verb::getID(Activity::FOLLOW), Verb::getID(Activity::FOLLOW),
Post\UserNotification::TYPE_NONE] Post\UserNotification::TYPE_NONE]
); );
} }
@ -130,26 +131,31 @@ class Notifications extends BaseApi
Verb::getID(Activity::POST), Post\UserNotification::TYPE_SHARED]); 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( $Notifications = DI::notification()->selectByBoundaries(
$condition, $condition,
$params, $params,
$request['min_id'] ?: $request['since_id'], $request['min_id'] ?: $request['since_id'],
$request['max_id'], $request['max_id'],
$request['limit'] $request['limit']
); );
foreach ($Notifications as $Notification) { foreach ($Notifications as $Notification) {
try { try {
$mstdnNotifications[] = DI::mstdnNotification()->createFromNotification($Notification, self::appSupportsQuotes()); $mstdnNotifications[] = DI::mstdnNotification()->createFromNotification($Notification, self::appSupportsQuotes());
self::setBoundaries($Notification->id); self::setBoundaries($Notification->id);
} catch (\Exception $e) { } catch (\Exception $e) {
// Skip this notification // Skip this notification
}
} }
}
self::setLinkHeader(); self::setLinkHeader();
System::jsonExit($mstdnNotifications); System::jsonExit($mstdnNotifications);
}
} }
} }

View file

@ -49,7 +49,7 @@ class FavouritedBy extends BaseApi
DI::mstdnError()->RecordNotFound(); 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 = []; $accounts = [];

View file

@ -34,7 +34,7 @@ use Friendica\Network\HTTPException;
/** /**
* Class Instance * Class Instance
* *
* @see https://docs.joinmastodon.org/api/entities/#instance * @see https://docs.joinmastodon.org/entities/V1_Instance/
*/ */
class Instance extends BaseDataTransferObject class Instance extends BaseDataTransferObject
{ {

View file

@ -0,0 +1,108 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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;
}
}

View file

@ -0,0 +1,54 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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;
}
}

View file

@ -0,0 +1,49 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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;
}
}

View file

@ -0,0 +1,53 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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;
}
}

View file

@ -0,0 +1,43 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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;
}
}

View file

@ -0,0 +1,47 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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;
}
}

View file

@ -0,0 +1,43 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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;
}
}

View file

@ -0,0 +1,43 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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;
}
}

View file

@ -0,0 +1,43 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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;
}
}

View file

@ -0,0 +1,43 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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;
}
}

View file

@ -151,7 +151,7 @@ class Status extends BaseDataTransferObject
$this->emojis = []; $this->emojis = [];
$this->card = $card->toArray() ?: null; $this->card = $card->toArray() ?: null;
$this->poll = $poll; $this->poll = $poll;
$this->friendica = new FriendicaExtension($item['title']); $this->friendica = new FriendicaExtension($item['title'], $counts->dislikes);
} }
/** /**

View file

@ -35,6 +35,9 @@ class Counts
/** @var int */ /** @var int */
protected $favourites; protected $favourites;
/** @var int */
protected $dislikes;
/** /**
* Creates a status count object * Creates a status count object
* *
@ -43,14 +46,16 @@ class Counts
* @param int $favourites * @param int $favourites
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @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->replies = $replies;
$this->reblogs = $reblogs; $this->reblogs = $reblogs;
$this->favourites = $favourites; $this->favourites = $favourites;
$this->dislikes = $dislikes;
} }
public function __get($name) { public function __get($name)
{
return $this->$name; return $this->$name;
} }
} }

View file

@ -35,14 +35,18 @@ class FriendicaExtension extends BaseDataTransferObject
/** @var string */ /** @var string */
protected $title; protected $title;
/** @var int */
protected $dislikes_count;
/** /**
* Creates a status count object * Creates a status count object
* *
* @param string $title * @param string $title
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @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;
} }
} }

View file

@ -496,7 +496,7 @@ class OStatus
$orig_uri = $xpath->query('activity:object/atom:id', $entry)->item(0)->nodeValue; $orig_uri = $xpath->query('activity:object/atom:id', $entry)->item(0)->nodeValue;
Logger::notice('Favorite', ['uri' => $orig_uri, 'item' => $item]); Logger::notice('Favorite', ['uri' => $orig_uri, 'item' => $item]);
$item['verb'] = Activity::LIKE; $item['body'] = $item['verb'] = Activity::LIKE;
$item['thr-parent'] = $orig_uri; $item['thr-parent'] = $orig_uri;
$item['gravity'] = Item::GRAVITY_ACTIVITY; $item['gravity'] = Item::GRAVITY_ACTIVITY;
$item['object-type'] = Activity\ObjectType::NOTE; $item['object-type'] = Activity\ObjectType::NOTE;

View file

@ -399,23 +399,6 @@ return [
"uid_uri-id" => ["uid", "uri-id"], "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" => [ "apcontact" => [
"comment" => "ActivityPub compatible contacts - used in the ActivityPub implementation", "comment" => "ActivityPub compatible contacts - used in the ActivityPub implementation",
"fields" => [ "fields" => [

View file

@ -80,6 +80,9 @@ $apiRoutes = [
'/friendica' => [ '/friendica' => [
'/activity/{verb:attendmaybe|attendno|attendyes|dislike|like|unattendmaybe|unattendno|unattendyes|undislike|unlike}[.{extension:json|xml|rss|atom}]' '/activity/{verb:attendmaybe|attendno|attendyes|dislike|like|unattendmaybe|unattendno|unattendyes|undislike|unlike}[.{extension:json|xml|rss|atom}]'
=> [Module\Api\Friendica\Activity::class, [ R::POST]], => [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/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 ]], '/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 ]], '/notifications[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Notification::class, [R::GET ]],
@ -307,7 +310,7 @@ return [
'/trends/tags' => [Module\Api\Mastodon\Trends\Tags::class, [R::GET ]], '/trends/tags' => [Module\Api\Mastodon\Trends\Tags::class, [R::GET ]],
], ],
'/v2' => [ '/v2' => [
'/instance' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not supported '/instance' => [Module\Api\Mastodon\InstanceV2::class, [R::GET ]], // not supported
], ],
'/v{version:\d+}' => [ '/v{version:\d+}' => [
'/admin/accounts' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not supported '/admin/accounts' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not supported

View file

@ -24,6 +24,7 @@ namespace Friendica\Test\src\Module\Api;
use Friendica\App; use Friendica\App;
use Friendica\Capabilities\ICanCreateResponses; use Friendica\Capabilities\ICanCreateResponses;
use Friendica\Core\Addon; use Friendica\Core\Addon;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Hook; use Friendica\Core\Hook;
use Friendica\Database\Database; use Friendica\Database\Database;
use Friendica\DI; use Friendica\DI;
@ -212,15 +213,14 @@ abstract class ApiTest extends FixtureTest
$func(DI::app()); $func(DI::app());
} }
/** @var Database $dba */ /** @var $config IManageConfigValues */
$dba = $this->dice->create(Database::class); $config = $this->dice->create(IManageConfigValues::class);
$dba->insert('addon', [ $config->set('addons', $addon, [
'name' => $addon, 'name' => $addon,
'installed' => true, 'installed' => true,
'timestamp' => $t, 'timestamp' => $t,
'plugin_admin' => function_exists($addon . '_addon_admin'), 'plugin_admin' => function_exists($addon . '_addon_admin'),
'hidden' => file_exists('addon/' . $addon . '/.hidden')
]); ]);
Addon::loadAddons(); Addon::loadAddons();