diff --git a/database.sql b/database.sql index cccb233d37..c68ae094c1 100644 --- a/database.sql +++ b/database.sql @@ -2438,6 +2438,7 @@ CREATE VIEW `post-thread-view` AS SELECT 0 AS `has-categories`, EXISTS(SELECT `id` FROM `post-media` WHERE `post-media`.`uri-id` = `post-thread`.`uri-id`) AS `has-media`, (SELECT COUNT(*) FROM `post` WHERE `parent-uri-id` = `post-thread`.`uri-id` AND `gravity` = 6) AS `total-comments`, + (SELECT COUNT(DISTINCT(`author-id`)) FROM `post` WHERE `parent-uri-id` = `post-thread`.`uri-id` AND `gravity` = 6) AS `total-actors`, `diaspora-interaction`.`interaction` AS `signed_text`, `parent-item-uri`.`guid` AS `parent-guid`, `parent-post`.`network` AS `parent-network`, diff --git a/doc/API-Mastodon.md b/doc/API-Mastodon.md index 2850f0ebf0..0e2f574303 100644 --- a/doc/API-Mastodon.md +++ b/doc/API-Mastodon.md @@ -135,6 +135,7 @@ These endpoints use the [Mastodon API entities](https://docs.joinmastodon.org/en - [`GET /api/v1/timelines/public`](https://docs.joinmastodon.org/methods/timelines/) - [`GET /api/v1/timelines/tag/:hashtag`](https://docs.joinmastodon.org/methods/timelines/) - [`GET /api/v1/trends`](https://docs.joinmastodon.org/methods/instance/trends/) +- [`GET /api/v1/trends/links`](https://github.com/mastodon/mastodon/pull/16917) - [`GET /api/v1/trends/statuses`](https://docs.joinmastodon.org/methods/trends/#statuses) - [`GET /api/v1/trends/tags`](https://docs.joinmastodon.org/methods/trends/#tags) - [`GET /api/v2/search`](https://docs.joinmastodon.org/methods/search/) @@ -147,7 +148,6 @@ These emdpoints are planned to be implemented somewhere in the future. - [`POST /api/v1/accounts/:id/remove_from_followers`](https://github.com/mastodon/mastodon/pull/16864) - [`GET /api/v1/accounts/familiar_followers`](https://github.com/mastodon/mastodon/pull/17700) - [`GET /api/v1/accounts/lookup`](https://github.com/mastodon/mastodon/pull/15740) -- [`GET /api/v1/trends/links`](https://github.com/mastodon/mastodon/pull/16917) - [`POST /api/v1/polls/:id/votes`](https://docs.joinmastodon.org/methods/statuses/polls/) - [`GET /api/v1/featured_tags`](https://docs.joinmastodon.org/methods/accounts/featured_tags/) - [`POST /api/v1/featured_tags`](https://docs.joinmastodon.org/methods/accounts/featured_tags/) diff --git a/src/Factory/Api/Mastodon/Card.php b/src/Factory/Api/Mastodon/Card.php index 659ab3a3de..ac50841847 100644 --- a/src/Factory/Api/Mastodon/Card.php +++ b/src/Factory/Api/Mastodon/Card.php @@ -30,13 +30,14 @@ use Friendica\Util\Strings; class Card extends BaseFactory { /** - * @param int $uriId Uri-ID of the item + * @param int $uriId Uri-ID of the item + * @param array $history Link request history * * @return \Friendica\Object\Api\Mastodon\Card * @throws HTTPException\InternalServerErrorException * @throws \ImagickException*@throws \Exception */ - public function createFromUriId(int $uriId): \Friendica\Object\Api\Mastodon\Card + public function createFromUriId(int $uriId, array $history = []): \Friendica\Object\Api\Mastodon\Card { $item = Post::selectFirst(['body'], ['uri-id' => $uriId]); if (!empty($item['body'])) { @@ -76,6 +77,6 @@ class Card extends BaseFactory } } - return new \Friendica\Object\Api\Mastodon\Card($data); + return new \Friendica\Object\Api\Mastodon\Card($data, $history); } } diff --git a/src/Module/Api/Mastodon/Trends/Links.php b/src/Module/Api/Mastodon/Trends/Links.php new file mode 100644 index 0000000000..ee535c7f3c --- /dev/null +++ b/src/Module/Api/Mastodon/Trends/Links.php @@ -0,0 +1,60 @@ +. + * + */ + +namespace Friendica\Module\Api\Mastodon\Trends; + +use Friendica\Core\Protocol; +use Friendica\Core\System; +use Friendica\Database\DBA; +use Friendica\DI; +use Friendica\Model\Post; +use Friendica\Module\BaseApi; +use Friendica\Util\DateTimeFormat; + +/** + * @see https://docs.joinmastodon.org/methods/trends/#links + */ +class Links extends BaseApi +{ + /** + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + */ + protected function rawContent(array $request = []) + { + $request = $this->getRequest([ + 'limit' => 10, // Maximum number of results to return. Defaults to 10. + ], $request); + + $condition = ["EXISTS(SELECT `id` FROM `post-media` WHERE `post-media`.`uri-id` = `post-thread-view`.`uri-id` AND `type` = ? AND NOT `name` IS NULL AND NOT `description` IS NULL) AND NOT `private` AND `commented` > ? AND `created` > ?", + Post\Media::HTML, DateTimeFormat::utc('now -1 day'), DateTimeFormat::utc('now -1 week')]; + $condition = DBA::mergeConditions($condition, ['network' => Protocol::FEDERATED]); + + $trending = []; + $statuses = Post::selectPostThread(['uri-id', 'total-comments', 'total-actors'], $condition, ['limit' => $request['limit'], 'order' => ['total-actors' => true]]); + while ($status = Post::fetch($statuses)) { + $history = [['day' => (string)time(), 'uses' => (string)$status['total-comments'], 'accounts' => (string)$status['total-actors']]]; + $trending[] = DI::mstdnCard()->createFromUriId($status['uri-id'], $history)->toArray(); + } + DBA::close($statuses); + + System::jsonExit($trending); + } +} diff --git a/src/Module/Api/Mastodon/Trends/Statuses.php b/src/Module/Api/Mastodon/Trends/Statuses.php index 8974403d77..26eb52d7ae 100644 --- a/src/Module/Api/Mastodon/Trends/Statuses.php +++ b/src/Module/Api/Mastodon/Trends/Statuses.php @@ -39,6 +39,8 @@ class Statuses extends BaseApi */ protected function rawContent(array $request = []) { + $uid = self::getCurrentUserID(); + $request = $this->getRequest([ 'limit' => 10, // Maximum number of results to return. Defaults to 10. ], $request); @@ -47,9 +49,9 @@ class Statuses extends BaseApi $condition = DBA::mergeConditions($condition, ['network' => Protocol::FEDERATED]); $trending = []; - $statuses = Post::selectPostThread(['uri-id'], $condition, ['limit' => $request['limit'], 'order' => ['total-comments' => true]]); + $statuses = Post::selectPostThread(['uri-id'], $condition, ['limit' => $request['limit'], 'order' => ['total-actors' => true]]); while ($status = Post::fetch($statuses)) { - $trending[] = DI::mstdnStatus()->createFromUriId($status['uri-id']); + $trending[] = DI::mstdnStatus()->createFromUriId($status['uri-id'], $uid); } DBA::close($statuses); diff --git a/src/Object/Api/Mastodon/Card.php b/src/Object/Api/Mastodon/Card.php index 4bd6c6e769..bf87617190 100644 --- a/src/Object/Api/Mastodon/Card.php +++ b/src/Object/Api/Mastodon/Card.php @@ -59,7 +59,7 @@ class Card extends BaseDataTransferObject * @param array $attachment Attachment record * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public function __construct(array $attachment) + public function __construct(array $attachment, array $history = []) { $this->url = $attachment['url'] ?? ''; $this->title = $attachment['title'] ?? ''; @@ -72,6 +72,7 @@ class Card extends BaseDataTransferObject $this->width = $attachment['width'] ?? 0; $this->height = $attachment['height'] ?? 0; $this->image = $attachment['image'] ?? ''; + $this->history = $history; } /** diff --git a/static/dbview.config.php b/static/dbview.config.php index 6c4f00a986..d06904a91f 100644 --- a/static/dbview.config.php +++ b/static/dbview.config.php @@ -665,6 +665,7 @@ "has-categories" => "0", "has-media" => "EXISTS(SELECT `id` FROM `post-media` WHERE `post-media`.`uri-id` = `post-thread`.`uri-id`)", "total-comments" => "(SELECT COUNT(*) FROM `post` WHERE `parent-uri-id` = `post-thread`.`uri-id` AND `gravity` = 6)", + "total-actors" => "(SELECT COUNT(DISTINCT(`author-id`)) FROM `post` WHERE `parent-uri-id` = `post-thread`.`uri-id` AND `gravity` = 6)", "signed_text" => ["diaspora-interaction", "interaction"], "parent-guid" => ["parent-item-uri", "guid"], "parent-network" => ["parent-post", "network"], diff --git a/static/routes.config.php b/static/routes.config.php index 81a9d2e2fd..da5dda0278 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -296,7 +296,7 @@ return [ '/timelines/public' => [Module\Api\Mastodon\Timelines\PublicTimeline::class, [R::GET ]], '/timelines/tag/{hashtag}' => [Module\Api\Mastodon\Timelines\Tag::class, [R::GET ]], '/trends' => [Module\Api\Mastodon\Trends\Tags::class, [R::GET ]], - '/trends/links' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not implemented + '/trends/links' => [Module\Api\Mastodon\Trends\Links::class, [R::GET ]], '/trends/statuses' => [Module\Api\Mastodon\Trends\Statuses::class, [R::GET ]], '/trends/tags' => [Module\Api\Mastodon\Trends\Tags::class, [R::GET ]], ],