mirror of
https://github.com/friendica/friendica
synced 2024-12-22 18:00:16 +00:00
API: The media upload (audio, video) is now possible
This commit is contained in:
parent
e3c782010f
commit
7dc75d585e
9 changed files with 151 additions and 41 deletions
|
@ -23,6 +23,7 @@ namespace Friendica\Factory\Api\Mastodon;
|
||||||
|
|
||||||
use Friendica\App\BaseURL;
|
use Friendica\App\BaseURL;
|
||||||
use Friendica\BaseFactory;
|
use Friendica\BaseFactory;
|
||||||
|
use Friendica\Model\Attach;
|
||||||
use Friendica\Model\Photo;
|
use Friendica\Model\Photo;
|
||||||
use Friendica\Network\HTTPException;
|
use Friendica\Network\HTTPException;
|
||||||
use Friendica\Model\Post;
|
use Friendica\Model\Post;
|
||||||
|
@ -144,4 +145,37 @@ class Attachment extends BaseFactory
|
||||||
$object = new \Friendica\Object\Api\Mastodon\Attachment($attachment, 'image', $url, $preview_url, '');
|
$object = new \Friendica\Object\Api\Mastodon\Attachment($attachment, 'image', $url, $preview_url, '');
|
||||||
return $object->toArray();
|
return $object->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id id of the attachment
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* @throws HTTPException\InternalServerErrorException
|
||||||
|
*/
|
||||||
|
public function createFromAttach(int $id): array
|
||||||
|
{
|
||||||
|
$media = Attach::selectFirst(['id', 'filetype'], ['id' => $id]);
|
||||||
|
if (empty($media)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$attachment = [
|
||||||
|
'id' => 'attach:' . $media['id'],
|
||||||
|
'description' => null,
|
||||||
|
'blurhash' => null,
|
||||||
|
];
|
||||||
|
|
||||||
|
$types = [Post\Media::AUDIO => 'audio', Post\Media::VIDEO => 'video', Post\Media::IMAGE => 'image'];
|
||||||
|
|
||||||
|
$type = Post\Media::getType($media['filetype']);
|
||||||
|
|
||||||
|
$url = $this->baseUrl . '/attach/' . $id;
|
||||||
|
|
||||||
|
$object = new \Friendica\Object\Api\Mastodon\Attachment($attachment, $types[$type] ?? 'unknown', $url, '', '');
|
||||||
|
return $object->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isAttach(string $id): bool
|
||||||
|
{
|
||||||
|
return substr($id, 0, 7) == 'attach:';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -245,6 +245,7 @@ class Attach
|
||||||
* @param string $src Source file name
|
* @param string $src Source file name
|
||||||
* @param int $uid User id
|
* @param int $uid User id
|
||||||
* @param string $filename Optional file name
|
* @param string $filename Optional file name
|
||||||
|
* @param string $filetype Optional file type
|
||||||
* @param string $allow_cid
|
* @param string $allow_cid
|
||||||
* @param string $allow_gid
|
* @param string $allow_gid
|
||||||
* @param string $deny_cid
|
* @param string $deny_cid
|
||||||
|
@ -252,7 +253,7 @@ class Attach
|
||||||
* @return boolean|int Insert id or false on failure
|
* @return boolean|int Insert id or false on failure
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function storeFile(string $src, int $uid, string $filename = '', string $allow_cid = '', string $allow_gid = '', string $deny_cid = '', string $deny_gid = '')
|
public static function storeFile(string $src, int $uid, string $filename = '', string $filetype = '', string $allow_cid = '', string $allow_gid = '', string $deny_cid = '', string $deny_gid = '')
|
||||||
{
|
{
|
||||||
if ($filename === '') {
|
if ($filename === '') {
|
||||||
$filename = basename($src);
|
$filename = basename($src);
|
||||||
|
@ -260,7 +261,7 @@ class Attach
|
||||||
|
|
||||||
$data = @file_get_contents($src);
|
$data = @file_get_contents($src);
|
||||||
|
|
||||||
return self::store($data, $uid, $filename, '', null, $allow_cid, $allow_gid, $deny_cid, $deny_gid);
|
return self::store($data, $uid, $filename, $filetype, null, $allow_cid, $allow_gid, $deny_cid, $deny_gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -345,6 +346,16 @@ class Attach
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function setPermissionForId(int $id, int $uid, string $str_contact_allow, string $str_circle_allow, string $str_contact_deny, string $str_circle_deny)
|
||||||
|
{
|
||||||
|
$fields = [
|
||||||
|
'allow_cid' => $str_contact_allow, 'allow_gid' => $str_circle_allow,
|
||||||
|
'deny_cid' => $str_contact_deny, 'deny_gid' => $str_circle_deny,
|
||||||
|
];
|
||||||
|
|
||||||
|
self::update($fields, ['id' => $id, 'uid' => $uid]);
|
||||||
|
}
|
||||||
|
|
||||||
public static function addAttachmentToBody(string $body, int $uid): string
|
public static function addAttachmentToBody(string $body, int $uid): string
|
||||||
{
|
{
|
||||||
preg_match_all("/\[attachment\](.*?)\[\/attachment\]/ism", $body, $matches, PREG_SET_ORDER);
|
preg_match_all("/\[attachment\](.*?)\[\/attachment\]/ism", $body, $matches, PREG_SET_ORDER);
|
||||||
|
|
|
@ -444,42 +444,46 @@ class Media
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
$type = explode('/', current(explode(';', $data['mimetype'])));
|
$data['type'] = self::getType($data['mimetype']);
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getType(string $mimeType): int
|
||||||
|
{
|
||||||
|
$type = explode('/', current(explode(';', $mimeType)));
|
||||||
if (count($type) < 2) {
|
if (count($type) < 2) {
|
||||||
Logger::info('Unknown MimeType', ['type' => $type, 'media' => $data]);
|
Logger::info('Unknown MimeType', ['type' => $type, 'media' => $mimeType]);
|
||||||
$data['type'] = self::UNKNOWN;
|
return self::UNKNOWN;
|
||||||
return $data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$filetype = strtolower($type[0]);
|
$filetype = strtolower($type[0]);
|
||||||
$subtype = strtolower($type[1]);
|
$subtype = strtolower($type[1]);
|
||||||
|
|
||||||
if ($filetype == 'image') {
|
if ($filetype == 'image') {
|
||||||
$data['type'] = self::IMAGE;
|
$type = self::IMAGE;
|
||||||
} elseif ($filetype == 'video') {
|
} elseif ($filetype == 'video') {
|
||||||
$data['type'] = self::VIDEO;
|
$type = self::VIDEO;
|
||||||
} elseif ($filetype == 'audio') {
|
} elseif ($filetype == 'audio') {
|
||||||
$data['type'] = self::AUDIO;
|
$type = self::AUDIO;
|
||||||
} elseif (($filetype == 'text') && ($subtype == 'html')) {
|
} elseif (($filetype == 'text') && ($subtype == 'html')) {
|
||||||
$data['type'] = self::HTML;
|
$type = self::HTML;
|
||||||
} elseif (($filetype == 'text') && ($subtype == 'xml')) {
|
} elseif (($filetype == 'text') && ($subtype == 'xml')) {
|
||||||
$data['type'] = self::XML;
|
$type = self::XML;
|
||||||
} elseif (($filetype == 'text') && ($subtype == 'plain')) {
|
} elseif (($filetype == 'text') && ($subtype == 'plain')) {
|
||||||
$data['type'] = self::PLAIN;
|
$type = self::PLAIN;
|
||||||
} elseif ($filetype == 'text') {
|
} elseif ($filetype == 'text') {
|
||||||
$data['type'] = self::TEXT;
|
$type = self::TEXT;
|
||||||
} elseif (($filetype == 'application') && ($subtype == 'x-bittorrent')) {
|
} elseif (($filetype == 'application') && ($subtype == 'x-bittorrent')) {
|
||||||
$data['type'] = self::TORRENT;
|
$type = self::TORRENT;
|
||||||
} elseif ($filetype == 'application') {
|
} elseif ($filetype == 'application') {
|
||||||
$data['type'] = self::APPLICATION;
|
$type = self::APPLICATION;
|
||||||
} else {
|
} else {
|
||||||
$data['type'] = self::UNKNOWN;
|
$type = self::UNKNOWN;
|
||||||
Logger::info('Unknown type', ['filetype' => $filetype, 'subtype' => $subtype, 'media' => $data]);
|
Logger::info('Unknown type', ['filetype' => $filetype, 'subtype' => $subtype, 'media' => $mimeType]);
|
||||||
return $data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::debug('Detected type', ['filetype' => $filetype, 'subtype' => $subtype, 'media' => $data]);
|
Logger::debug('Detected type', ['filetype' => $filetype, 'subtype' => $subtype, 'media' => $mimeType]);
|
||||||
return $data;
|
return $type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -131,12 +131,19 @@ class InstanceV2 extends BaseApi
|
||||||
|
|
||||||
return new InstanceEntity\Configuration(
|
return new InstanceEntity\Configuration(
|
||||||
$statuses_config,
|
$statuses_config,
|
||||||
new InstanceEntity\MediaAttachmentsConfig(Images::supportedMimeTypes(), $image_size_limit, $image_matrix_limit),
|
new InstanceEntity\MediaAttachmentsConfig($this->supportedMimeTypes(), $image_size_limit, $image_matrix_limit),
|
||||||
new InstanceEntity\Polls(),
|
new InstanceEntity\Polls(),
|
||||||
new InstanceEntity\Accounts(),
|
new InstanceEntity\Accounts(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function supportedMimeTypes(): array
|
||||||
|
{
|
||||||
|
$mimetypes = ['audio/aac', 'audio/flac', 'audio/mpeg', 'audio/mp4', 'audio/ogg', 'audio/wav',
|
||||||
|
'audio/webm', 'video/mp4', 'video/ogg', 'video/webm'];
|
||||||
|
return array_merge(Images::supportedMimeTypes(), $mimetypes);
|
||||||
|
}
|
||||||
|
|
||||||
private function buildContactInfo(): InstanceEntity\Contact
|
private function buildContactInfo(): InstanceEntity\Contact
|
||||||
{
|
{
|
||||||
$email = implode(',', User::getAdminEmailList());
|
$email = implode(',', User::getAdminEmailList());
|
||||||
|
|
|
@ -22,8 +22,9 @@
|
||||||
namespace Friendica\Module\Api\Mastodon;
|
namespace Friendica\Module\Api\Mastodon;
|
||||||
|
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
use Friendica\Core\System;
|
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
|
use Friendica\Model\Attach;
|
||||||
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Photo;
|
use Friendica\Model\Photo;
|
||||||
use Friendica\Model\Post;
|
use Friendica\Model\Post;
|
||||||
use Friendica\Module\BaseApi;
|
use Friendica\Module\BaseApi;
|
||||||
|
@ -51,14 +52,38 @@ class Media extends BaseApi
|
||||||
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||||
}
|
}
|
||||||
|
|
||||||
$media = Photo::upload($uid, $_FILES['file'], '', null, null, '', '', $request['description']);
|
$type = Post\Media::getType($_FILES['file']['type']);
|
||||||
if (empty($media)) {
|
|
||||||
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
if (in_array($type, [Post\Media::IMAGE, Post\Media::UNKNOWN])) {
|
||||||
|
$media = Photo::upload($uid, $_FILES['file'], '', null, null, '', '', $request['description']);
|
||||||
|
if (empty($media)) {
|
||||||
|
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::info('Uploaded photo', ['media' => $media]);
|
||||||
|
|
||||||
|
$this->jsonExit(DI::mstdnAttachment()->createFromPhoto($media['id']));
|
||||||
|
} else {
|
||||||
|
$tempFileName = $_FILES['file']['tmp_name'];
|
||||||
|
$fileName = basename($_FILES['file']['name']);
|
||||||
|
$fileSize = intval($_FILES['file']['size']);
|
||||||
|
$maxFileSize = DI::config()->get('system', 'maxfilesize');
|
||||||
|
|
||||||
|
if ($fileSize <= 0) {
|
||||||
|
@unlink($tempFileName);
|
||||||
|
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($maxFileSize && $fileSize > $maxFileSize) {
|
||||||
|
@unlink($tempFileName);
|
||||||
|
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = Attach::storeFile($tempFileName, self::getCurrentUserID(), $fileName, $_FILES['file']['type'], '<' . Contact::getPublicIdByUserId(self::getCurrentUserID()) . '>');
|
||||||
|
@unlink($tempFileName);
|
||||||
|
Logger::info('Uploaded media', ['id' => $id]);
|
||||||
|
$this->jsonExit(DI::mstdnAttachment()->createFromAttach($id));
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::info('Uploaded photo', ['media' => $media]);
|
|
||||||
|
|
||||||
$this->jsonExit(DI::mstdnAttachment()->createFromPhoto($media['id']));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function put(array $request = [])
|
public function put(array $request = [])
|
||||||
|
@ -77,6 +102,10 @@ class Media extends BaseApi
|
||||||
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DI::mstdnAttachment()->isAttach($this->parameters['id']) && Attach::exists(['id' => substr($this->parameters['id'], 7)])) {
|
||||||
|
$this->jsonExit(DI::mstdnAttachment()->createFromAttach(substr($this->parameters['id'], 7)));
|
||||||
|
}
|
||||||
|
|
||||||
$photo = Photo::selectFirst(['resource-id'], ['id' => $this->parameters['id'], 'uid' => $uid]);
|
$photo = Photo::selectFirst(['resource-id'], ['id' => $this->parameters['id'], 'uid' => $uid]);
|
||||||
if (empty($photo['resource-id'])) {
|
if (empty($photo['resource-id'])) {
|
||||||
$media = Post\Media::getById($this->parameters['id']);
|
$media = Post\Media::getById($this->parameters['id']);
|
||||||
|
@ -108,10 +137,15 @@ class Media extends BaseApi
|
||||||
}
|
}
|
||||||
|
|
||||||
$id = $this->parameters['id'];
|
$id = $this->parameters['id'];
|
||||||
if (!Photo::exists(['id' => $id, 'uid' => $uid])) {
|
|
||||||
$this->logAndJsonError(404, $this->errorFactory->RecordNotFound());
|
if (Photo::exists(['id' => $id, 'uid' => $uid])) {
|
||||||
|
$this->jsonExit(DI::mstdnAttachment()->createFromPhoto($id));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->jsonExit(DI::mstdnAttachment()->createFromPhoto($id));
|
if (DI::mstdnAttachment()->isAttach($id) && Attach::exists(['id' => substr($id, 7)])) {
|
||||||
|
$this->jsonExit(DI::mstdnAttachment()->createFromAttach(substr($id, 7)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logAndJsonError(404, $this->errorFactory->RecordNotFound());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ use Friendica\Core\Protocol;
|
||||||
use Friendica\Core\Worker;
|
use Friendica\Core\Worker;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
|
use Friendica\Model\Attach;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Circle;
|
use Friendica\Model\Circle;
|
||||||
use Friendica\Model\Item;
|
use Friendica\Model\Item;
|
||||||
|
@ -397,6 +398,20 @@ class Statuses extends BaseApi
|
||||||
$item['attachments'] = [];
|
$item['attachments'] = [];
|
||||||
|
|
||||||
foreach ($media_ids as $id) {
|
foreach ($media_ids as $id) {
|
||||||
|
if (DI::mstdnAttachment()->isAttach($id) && Attach::exists(['id' => substr($id, 7)])) {
|
||||||
|
$attach = Attach::selectFirst([], ['id' => substr($id, 7)]);
|
||||||
|
$attachment = [
|
||||||
|
'type' => Post\Media::getType($attach['filetype']),
|
||||||
|
'mimetype' => $attach['filetype'],
|
||||||
|
'url' => DI::baseUrl() . '/attach/' . substr($id, 7),
|
||||||
|
'size' => $attach['filetype'],
|
||||||
|
'name' => $attach['filename']
|
||||||
|
];
|
||||||
|
$item['attachments'][] = $attachment;
|
||||||
|
Attach::setPermissionForId(substr($id, 7), $item['uid'], $item['allow_cid'], $item['allow_gid'], $item['deny_cid'], $item['deny_gid']);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$media = DBA::toArray(DBA::p("SELECT `resource-id`, `scale`, `type`, `desc`, `filename`, `datasize`, `width`, `height` FROM `photo`
|
$media = DBA::toArray(DBA::p("SELECT `resource-id`, `scale`, `type`, `desc`, `filename`, `datasize`, `width`, `height` FROM `photo`
|
||||||
WHERE `resource-id` IN (SELECT `resource-id` FROM `photo` WHERE `id` = ?) AND `photo`.`uid` = ?
|
WHERE `resource-id` IN (SELECT `resource-id` FROM `photo` WHERE `id` = ?) AND `photo`.`uid` = ?
|
||||||
ORDER BY `photo`.`width` DESC LIMIT 2", $id, $item['uid']));
|
ORDER BY `photo`.`width` DESC LIMIT 2", $id, $item['uid']));
|
||||||
|
@ -409,13 +424,16 @@ class Statuses extends BaseApi
|
||||||
|
|
||||||
$ext = Images::getExtensionByMimeType($media[0]['type']);
|
$ext = Images::getExtensionByMimeType($media[0]['type']);
|
||||||
|
|
||||||
$attachment = ['type' => Post\Media::IMAGE, 'mimetype' => $media[0]['type'],
|
$attachment = [
|
||||||
'url' => DI::baseUrl() . '/photo/' . $media[0]['resource-id'] . '-' . $media[0]['scale'] . $ext,
|
'type' => Post\Media::IMAGE,
|
||||||
'size' => $media[0]['datasize'],
|
'mimetype' => $media[0]['type'],
|
||||||
'name' => $media[0]['filename'] ?: $media[0]['resource-id'],
|
'url' => DI::baseUrl() . '/photo/' . $media[0]['resource-id'] . '-' . $media[0]['scale'] . $ext,
|
||||||
|
'size' => $media[0]['datasize'],
|
||||||
|
'name' => $media[0]['filename'] ?: $media[0]['resource-id'],
|
||||||
'description' => $media[0]['desc'] ?? '',
|
'description' => $media[0]['desc'] ?? '',
|
||||||
'width' => $media[0]['width'],
|
'width' => $media[0]['width'],
|
||||||
'height' => $media[0]['height']];
|
'height' => $media[0]['height']
|
||||||
|
];
|
||||||
|
|
||||||
if (count($media) > 1) {
|
if (count($media) > 1) {
|
||||||
$attachment['preview'] = DI::baseUrl() . '/photo/' . $media[1]['resource-id'] . '-' . $media[1]['scale'] . $ext;
|
$attachment['preview'] = DI::baseUrl() . '/photo/' . $media[1]['resource-id'] . '-' . $media[1]['scale'] . $ext;
|
||||||
|
|
|
@ -106,7 +106,7 @@ class Upload extends \Friendica\BaseModule
|
||||||
$this->return(401, $msg);
|
$this->return(401, $msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
$newid = Attach::storeFile($tempFileName, $owner['uid'], $fileName, '<' . $owner['id'] . '>');
|
$newid = Attach::storeFile($tempFileName, $_FILES['userfile']['type'] ?? '', $owner['uid'], $fileName, '<' . $owner['id'] . '>');
|
||||||
|
|
||||||
@unlink($tempFileName);
|
@unlink($tempFileName);
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ class MediaAttachmentsConfig extends BaseDataTransferObject
|
||||||
/** @var int */
|
/** @var int */
|
||||||
protected $video_size_limit = 0;
|
protected $video_size_limit = 0;
|
||||||
/** @var int */
|
/** @var int */
|
||||||
protected $video_frame_rate_limit = 0;
|
protected $video_frame_rate_limit = 60;
|
||||||
/** @var int */
|
/** @var int */
|
||||||
protected $video_matrix_limit = 0;
|
protected $video_matrix_limit = 0;
|
||||||
|
|
||||||
|
@ -51,5 +51,7 @@ class MediaAttachmentsConfig extends BaseDataTransferObject
|
||||||
$this->supported_mime_types = $supported_mime_types;
|
$this->supported_mime_types = $supported_mime_types;
|
||||||
$this->image_size_limit = $image_size_limit;
|
$this->image_size_limit = $image_size_limit;
|
||||||
$this->image_matrix_limit = $image_matrix_limit;
|
$this->image_matrix_limit = $image_matrix_limit;
|
||||||
|
$this->video_size_limit = $image_size_limit;
|
||||||
|
$this->video_matrix_limit = $image_matrix_limit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,7 +261,7 @@ return [
|
||||||
'/lists/{id:\d+}' => [Module\Api\Mastodon\Lists::class, [R::GET, R::PUT, R::DELETE]],
|
'/lists/{id:\d+}' => [Module\Api\Mastodon\Lists::class, [R::GET, R::PUT, R::DELETE]],
|
||||||
'/lists/{id:\d+}/accounts' => [Module\Api\Mastodon\Lists\Accounts::class, [R::GET, R::POST, R::DELETE]],
|
'/lists/{id:\d+}/accounts' => [Module\Api\Mastodon\Lists\Accounts::class, [R::GET, R::POST, R::DELETE]],
|
||||||
'/markers' => [Module\Api\Mastodon\Markers::class, [R::GET, R::POST]],
|
'/markers' => [Module\Api\Mastodon\Markers::class, [R::GET, R::POST]],
|
||||||
'/media/{id:\d+}' => [Module\Api\Mastodon\Media::class, [R::GET, R::PUT ]],
|
'/media/{id}' => [Module\Api\Mastodon\Media::class, [R::GET, R::PUT ]],
|
||||||
'/mutes' => [Module\Api\Mastodon\Mutes::class, [R::GET ]],
|
'/mutes' => [Module\Api\Mastodon\Mutes::class, [R::GET ]],
|
||||||
'/notifications' => [Module\Api\Mastodon\Notifications::class, [R::GET ]],
|
'/notifications' => [Module\Api\Mastodon\Notifications::class, [R::GET ]],
|
||||||
'/notifications/{id:\d+}' => [Module\Api\Mastodon\Notifications::class, [R::GET ]],
|
'/notifications/{id:\d+}' => [Module\Api\Mastodon\Notifications::class, [R::GET ]],
|
||||||
|
|
Loading…
Reference in a new issue