diff --git a/src/Factory/Api/Mastodon/Status.php b/src/Factory/Api/Mastodon/Status.php index 9f6d3bcde9..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; @@ -144,10 +150,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 +337,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/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/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/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/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 = []; 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; } } diff --git a/static/routes.config.php b/static/routes.config.php index 3271571c44..0ff13224c6 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -80,6 +80,9 @@ $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+}/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 ]], '/notifications[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Notification::class, [R::GET ]],