diff --git a/doc/API-Mastodon.md b/doc/API-Mastodon.md index 2efa9a9ffa..7f5b55797a 100644 --- a/doc/API-Mastodon.md +++ b/doc/API-Mastodon.md @@ -47,6 +47,7 @@ These endpoints use the [Mastodon API entities](https://docs.joinmastodon.org/en - [`GET /api/v1/lists`](https://docs.joinmastodon.org/methods/timelines/lists/) - [`GET /api/v1/lists/:id`](https://docs.joinmastodon.org/methods/timelines/lists/) - [`GET /api/v1/lists/:id/accounts`](https://docs.joinmastodon.org/methods/timelines/lists/) +- [`GET /api/v1/media/:id`](https://docs.joinmastodon.org/methods/statuses/media/) - [`GET /api/v1/mutes`](https://docs.joinmastodon.org/methods/accounts/mutes/) - [`GET /api/v1/notifications`](https://docs.joinmastodon.org/methods/notifications/) - [`GET /api/v1/notifications/:id`](https://docs.joinmastodon.org/methods/notifications/) diff --git a/src/Factory/Api/Mastodon/Attachment.php b/src/Factory/Api/Mastodon/Attachment.php index 893b4c9f95..7ac45f354e 100644 --- a/src/Factory/Api/Mastodon/Attachment.php +++ b/src/Factory/Api/Mastodon/Attachment.php @@ -23,9 +23,12 @@ namespace Friendica\Factory\Api\Mastodon; use Friendica\App\BaseURL; use Friendica\BaseFactory; +use Friendica\DI; +use Friendica\Model\Photo; use Friendica\Network\HTTPException; use Friendica\Model\Post; use Friendica\Repository\ProfileField; +use Friendica\Util\Images; use Friendica\Util\Proxy; use Psr\Log\LoggerInterface; @@ -93,4 +96,36 @@ class Attachment extends BaseFactory return $attachments; } + + /** + * @param int $id id of the photo + * @return array + * @throws HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + public function createFromPhoto(int $id) + { + $photo = Photo::selectFirst(['resource-id', 'uid', 'id', 'title', 'type'], ['id' => $id]); + if (empty($photo)) { + return null; + } + + $attachment = ['id' => $photo['id'], 'description' => $photo['title']]; + + $phototypes = Images::supportedTypes(); + $ext = $phototypes[$photo['type']]; + + $url = DI::baseUrl() . '/photo/' . $photo['resource-id'] . '-0.' . $ext; + + $preview = Photo::selectFirst(['scale'], ["`resource-id` = ? AND `uid` = ? AND `scale` > ?", $photo['resource-id'], $photo['uid'], 0], ['order' => ['scale']]); + if (empty($scale)) { + $preview_url = DI::baseUrl() . '/photo/' . $photo['resource-id'] . '-' . $preview['scale'] . '.' . $ext; + } else { + $preview_url = ''; + } + + + $object = new \Friendica\Object\Api\Mastodon\Attachment($attachment, 'image', $url, $preview_url, ''); + return $object->toArray(); + } } diff --git a/src/Module/Api/Mastodon/Media.php b/src/Module/Api/Mastodon/Media.php new file mode 100644 index 0000000000..c5fb82a248 --- /dev/null +++ b/src/Module/Api/Mastodon/Media.php @@ -0,0 +1,62 @@ +. + * + */ + +namespace Friendica\Module\Api\Mastodon; + +use Friendica\Core\System; +use Friendica\Database\DBA; +use Friendica\DI; +use Friendica\Model\Contact; +use Friendica\Model\Notification; +use Friendica\Model\Photo; +use Friendica\Module\BaseApi; + +/** + * @see https://docs.joinmastodon.org/methods/statuses/media/ + */ +class Media extends BaseApi +{ + public static function put(array $parameters = []) + { + self::unsupported('put'); + } + + /** + * @param array $parameters + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + */ + public static function rawContent(array $parameters = []) + { + self::login(); + $uid = self::getCurrentUserID(); + + if (empty($parameters['id'])) { + DI::mstdnError()->RecordNotFound(); + } + + $id = $parameters['id']; + if (!Photo::exists(['id' => $id, 'uid' => $uid])) { + DI::mstdnError()->RecordNotFound(); + } + + System::jsonExit(DI::mstdnAttachment()->createFromPhoto($id)); + } +} diff --git a/static/routes.config.php b/static/routes.config.php index e00a7f0e34..a21ff336da 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -90,9 +90,9 @@ return [ '/apps/verify_credentials' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], '/blocks' => [Module\Api\Mastodon\Blocks::class, [R::GET ]], '/bookmarks' => [Module\Api\Mastodon\Bookmarks::class, [R::GET ]], - '/conversations' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // @todo - '/conversations/{id:\d+}' => [Module\Api\Mastodon\Unimplemented::class, [R::DELETE ]], - '/conversations/{id:\d+}/read' => [Module\Api\Mastodon\Unimplemented::class, [R::POST ]], + '/conversations' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not implemented + '/conversations/{id:\d+}' => [Module\Api\Mastodon\Unimplemented::class, [R::DELETE ]], // not implemented + '/conversations/{id:\d+}/read' => [Module\Api\Mastodon\Unimplemented::class, [R::POST ]], // not implemented '/custom_emojis' => [Module\Api\Mastodon\CustomEmojis::class, [R::GET ]], '/domain_blocks' => [Module\Api\Mastodon\Unimplemented::class, [R::GET, R::POST, R::DELETE]], // not implemented '/directory' => [Module\Api\Mastodon\Directory::class, [R::GET ]], @@ -113,7 +113,7 @@ return [ '/lists/{id:\d+}/accounts' => [Module\Api\Mastodon\Lists\Accounts::class, [R::GET, R::POST, R::DELETE]], '/markers' => [Module\Api\Mastodon\Unimplemented::class, [R::GET, R::POST]], // not implemented '/media' => [Module\Api\Mastodon\Unimplemented::class, [ R::POST]], - '/media/{id:\d+}' => [Module\Api\Mastodon\Unimplemented::class, [R::GET, R::PUT]], // @todo + '/media/{id:\d+}' => [Module\Api\Mastodon\Media::class, [R::GET, R::PUT]], '/mutes' => [Module\Api\Mastodon\Mutes::class, [R::GET ]], '/notifications' => [Module\Api\Mastodon\Notifications::class, [R::GET ]], '/notifications/{id:\d+}' => [Module\Api\Mastodon\Notifications::class, [R::GET ]],