diff options
| author | Julia <julia@insertdomain.name> | 2025-05-29 00:07:38 +0000 |
|---|---|---|
| committer | Julia <julia@insertdomain.name> | 2025-05-29 00:07:38 +0000 |
| commit | 6b554c178b81f13f83a69b19d44b72b282a0c119 (patch) | |
| tree | f5537f1a56323a4dd57ba150b3cb84a2d8b5dc63 /packages/backend/src/server/api/mastodon/endpoints/status.ts | |
| parent | merge: Security fixes (!970) (diff) | |
| parent | bump version for release (diff) | |
| download | sharkey-6b554c178b81f13f83a69b19d44b72b282a0c119.tar.gz sharkey-6b554c178b81f13f83a69b19d44b72b282a0c119.tar.bz2 sharkey-6b554c178b81f13f83a69b19d44b72b282a0c119.zip | |
merge: release 2025.4.2 (!1051)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1051
Approved-by: Hazelnoot <acomputerdog@gmail.com>
Approved-by: Marie <github@yuugi.dev>
Approved-by: Julia <julia@insertdomain.name>
Diffstat (limited to 'packages/backend/src/server/api/mastodon/endpoints/status.ts')
| -rw-r--r-- | packages/backend/src/server/api/mastodon/endpoints/status.ts | 606 |
1 files changed, 241 insertions, 365 deletions
diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index 4c49a6a293..22b8a911ca 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -4,12 +4,11 @@ */ import querystring, { ParsedUrlQueryInput } from 'querystring'; +import { Injectable } from '@nestjs/common'; import { emojiRegexAtStartToEnd } from '@/misc/emoji-regex.js'; -import { getErrorData, MastodonLogger } from '@/server/api/mastodon/MastodonLogger.js'; -import { parseTimelineArgs, TimelineArgs, toBoolean, toInt } from '@/server/api/mastodon/timelineArgs.js'; -import { AuthenticateService } from '@/server/api/AuthenticateService.js'; -import { convertAttachment, convertPoll, MastoConverters } from '../converters.js'; -import { getAccessToken, getClient, MastodonApiServerService } from '../MastodonApiServerService.js'; +import { parseTimelineArgs, TimelineArgs, toBoolean, toInt } from '@/server/api/mastodon/argsUtils.js'; +import { MastodonClientService } from '@/server/api/mastodon/MastodonClientService.js'; +import { convertAttachment, convertPoll, MastodonConverters } from '../MastodonConverters.js'; import type { Entity } from 'megalodon'; import type { FastifyInstance } from 'fastify'; @@ -18,167 +17,112 @@ function normalizeQuery(data: Record<string, unknown>) { return querystring.parse(str); } +@Injectable() export class ApiStatusMastodon { constructor( - private readonly fastify: FastifyInstance, - private readonly mastoConverters: MastoConverters, - private readonly logger: MastodonLogger, - private readonly authenticateService: AuthenticateService, - private readonly mastodon: MastodonApiServerService, + private readonly mastoConverters: MastodonConverters, + private readonly clientService: MastodonClientService, ) {} - public getStatus() { - this.fastify.get<{ Params: { id?: string } }>('/v1/statuses/:id', async (_request, reply) => { - try { - const { client, me } = await this.mastodon.getAuthClient(_request); - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const data = await client.getStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`GET /v1/statuses/${_request.params.id}`, data); - reply.code(_request.is404 ? 404 : 401).send(data); + public register(fastify: FastifyInstance): void { + fastify.get<{ Params: { id?: string } }>('/v1/statuses/:id', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const { client, me } = await this.clientService.getAuthClient(_request); + const data = await client.getStatus(_request.params.id); + const response = await this.mastoConverters.convertStatus(data.data, me); + + // Fixup - Discord ignores CWs and renders the entire post. + if (response.sensitive && _request.headers['user-agent']?.match(/\bDiscordbot\//)) { + response.content = '(preview disabled for sensitive content)'; + response.media_attachments = []; } + + return reply.send(response); }); - } - public getStatusSource() { - this.fastify.get<{ Params: { id?: string } }>('/v1/statuses/:id/source', async (_request, reply) => { - const BASE_URL = `${_request.protocol}://${_request.host}`; - const accessTokens = _request.headers.authorization; - const client = getClient(BASE_URL, accessTokens); - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const data = await client.getStatusSource(_request.params.id); - reply.send(data.data); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`GET /v1/statuses/${_request.params.id}/source`, data); - reply.code(_request.is404 ? 404 : 401).send(data); - } + fastify.get<{ Params: { id?: string } }>('/v1/statuses/:id/source', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const client = this.clientService.getClient(_request); + const data = await client.getStatusSource(_request.params.id); + + return reply.send(data.data); }); - } - public getContext() { - this.fastify.get<{ Params: { id?: string }, Querystring: TimelineArgs }>('/v1/statuses/:id/context', async (_request, reply) => { - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const { client, me } = await this.mastodon.getAuthClient(_request); - const { data } = await client.getStatusContext(_request.params.id, parseTimelineArgs(_request.query)); - const ancestors = await Promise.all(data.ancestors.map(async status => await this.mastoConverters.convertStatus(status, me))); - const descendants = await Promise.all(data.descendants.map(async status => await this.mastoConverters.convertStatus(status, me))); - reply.send({ ancestors, descendants }); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`GET /v1/statuses/${_request.params.id}/context`, data); - reply.code(_request.is404 ? 404 : 401).send(data); - } + fastify.get<{ Params: { id?: string }, Querystring: TimelineArgs }>('/v1/statuses/:id/context', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const { client, me } = await this.clientService.getAuthClient(_request); + const { data } = await client.getStatusContext(_request.params.id, parseTimelineArgs(_request.query)); + const ancestors = await Promise.all(data.ancestors.map(async (status: Entity.Status) => await this.mastoConverters.convertStatus(status, me))); + const descendants = await Promise.all(data.descendants.map(async (status: Entity.Status) => await this.mastoConverters.convertStatus(status, me))); + const response = { ancestors, descendants }; + + return reply.send(response); }); - } - public getHistory() { - this.fastify.get<{ Params: { id?: string } }>('/v1/statuses/:id/history', async (_request, reply) => { - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const [user] = await this.authenticateService.authenticate(getAccessToken(_request.headers.authorization)); - const edits = await this.mastoConverters.getEdits(_request.params.id, user); - reply.send(edits); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`GET /v1/statuses/${_request.params.id}/history`, data); - reply.code(401).send(data); - } + fastify.get<{ Params: { id?: string } }>('/v1/statuses/:id/history', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const user = await this.clientService.getAuth(_request); + const edits = await this.mastoConverters.getEdits(_request.params.id, user); + + return reply.send(edits); }); - } - public getReblogged() { - this.fastify.get<{ Params: { id?: string } }>('/v1/statuses/:id/reblogged_by', async (_request, reply) => { - const BASE_URL = `${_request.protocol}://${_request.host}`; - const accessTokens = _request.headers.authorization; - const client = getClient(BASE_URL, accessTokens); - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const data = await client.getStatusRebloggedBy(_request.params.id); - reply.send(await Promise.all(data.data.map(async (account: Entity.Account) => await this.mastoConverters.convertAccount(account)))); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`GET /v1/statuses/${_request.params.id}/reblogged_by`, data); - reply.code(401).send(data); - } + fastify.get<{ Params: { id?: string } }>('/v1/statuses/:id/reblogged_by', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const client = this.clientService.getClient(_request); + const data = await client.getStatusRebloggedBy(_request.params.id); + const response = await Promise.all(data.data.map((account: Entity.Account) => this.mastoConverters.convertAccount(account))); + + return reply.send(response); }); - } - public getFavourites() { - this.fastify.get<{ Params: { id?: string } }>('/v1/statuses/:id/favourited_by', async (_request, reply) => { - const BASE_URL = `${_request.protocol}://${_request.host}`; - const accessTokens = _request.headers.authorization; - const client = getClient(BASE_URL, accessTokens); - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const data = await client.getStatusFavouritedBy(_request.params.id); - reply.send(await Promise.all(data.data.map(async (account: Entity.Account) => await this.mastoConverters.convertAccount(account)))); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`GET /v1/statuses/${_request.params.id}/favourited_by`, data); - reply.code(401).send(data); - } + fastify.get<{ Params: { id?: string } }>('/v1/statuses/:id/favourited_by', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const client = this.clientService.getClient(_request); + const data = await client.getStatusFavouritedBy(_request.params.id); + const response = await Promise.all(data.data.map((account: Entity.Account) => this.mastoConverters.convertAccount(account))); + + return reply.send(response); }); - } - public getMedia() { - this.fastify.get<{ Params: { id?: string } }>('/v1/media/:id', async (_request, reply) => { - const BASE_URL = `${_request.protocol}://${_request.host}`; - const accessTokens = _request.headers.authorization; - const client = getClient(BASE_URL, accessTokens); - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const data = await client.getMedia(_request.params.id); - reply.send(convertAttachment(data.data)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`GET /v1/media/${_request.params.id}`, data); - reply.code(401).send(data); - } + fastify.get<{ Params: { id?: string } }>('/v1/media/:id', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const client = this.clientService.getClient(_request); + const data = await client.getMedia(_request.params.id); + const response = convertAttachment(data.data); + + return reply.send(response); }); - } - public getPoll() { - this.fastify.get<{ Params: { id?: string } }>('/v1/polls/:id', async (_request, reply) => { - const BASE_URL = `${_request.protocol}://${_request.host}`; - const accessTokens = _request.headers.authorization; - const client = getClient(BASE_URL, accessTokens); - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const data = await client.getPoll(_request.params.id); - reply.send(convertPoll(data.data)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`GET /v1/polls/${_request.params.id}`, data); - reply.code(401).send(data); - } + fastify.get<{ Params: { id?: string } }>('/v1/polls/:id', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const client = this.clientService.getClient(_request); + const data = await client.getPoll(_request.params.id); + const response = convertPoll(data.data); + + return reply.send(response); }); - } - public votePoll() { - this.fastify.post<{ Params: { id?: string }, Body: { choices?: number[] } }>('/v1/polls/:id/votes', async (_request, reply) => { - const BASE_URL = `${_request.protocol}://${_request.host}`; - const accessTokens = _request.headers.authorization; - const client = getClient(BASE_URL, accessTokens); - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - if (!_request.body.choices) return reply.code(400).send({ error: 'Missing required payload "choices"' }); - const data = await client.votePoll(_request.params.id, _request.body.choices); - reply.send(convertPoll(data.data)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`GET /v1/polls/${_request.params.id}/votes`, data); - reply.code(401).send(data); - } + fastify.post<{ Params: { id?: string }, Body: { choices?: number[] } }>('/v1/polls/:id/votes', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + if (!_request.body.choices) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required payload "choices"' }); + + const client = this.clientService.getClient(_request); + const data = await client.votePoll(_request.params.id, _request.body.choices); + const response = convertPoll(data.data); + + return reply.send(response); }); - } - public postStatus() { - this.fastify.post<{ + fastify.post<{ Body: { media_ids?: string[], poll?: { @@ -202,63 +146,58 @@ export class ApiStatusMastodon { } }>('/v1/statuses', async (_request, reply) => { let body = _request.body; - try { - const { client, me } = await this.mastodon.getAuthClient(_request); - if ((!body.poll && body['poll[options][]']) || (!body.media_ids && body['media_ids[]']) - ) { - body = normalizeQuery(body); - } - const text = body.status ??= ' '; - const removed = text.replace(/@\S+/g, '').replace(/\s|/g, ''); - const isDefaultEmoji = emojiRegexAtStartToEnd.test(removed); - const isCustomEmoji = /^:[a-zA-Z0-9@_]+:$/.test(removed); - if ((body.in_reply_to_id && isDefaultEmoji) || (body.in_reply_to_id && isCustomEmoji)) { - const a = await client.createEmojiReaction( - body.in_reply_to_id, - removed, - ); - reply.send(a.data); - } - if (body.in_reply_to_id && removed === '/unreact') { - const id = body.in_reply_to_id; - const post = await client.getStatus(id); - const react = post.data.emoji_reactions.filter(e => e.me)[0].name; - const data = await client.deleteEmojiReaction(id, react); - reply.send(data.data); - } - if (!body.media_ids) body.media_ids = undefined; - if (body.media_ids && !body.media_ids.length) body.media_ids = undefined; - - if (body.poll && !body.poll.options) { - return reply.code(400).send({ error: 'Missing required payload "poll.options"' }); - } - if (body.poll && !body.poll.expires_in) { - return reply.code(400).send({ error: 'Missing required payload "poll.expires_in"' }); - } + if ((!body.poll && body['poll[options][]']) || (!body.media_ids && body['media_ids[]']) + ) { + body = normalizeQuery(body); + } + const text = body.status ??= ' '; + const removed = text.replace(/@\S+/g, '').replace(/\s|/g, ''); + const isDefaultEmoji = emojiRegexAtStartToEnd.test(removed); + const isCustomEmoji = /^:[a-zA-Z0-9@_]+:$/.test(removed); - const options = { - ...body, - sensitive: toBoolean(body.sensitive), - poll: body.poll ? { - options: body.poll.options!, // eslint-disable-line @typescript-eslint/no-non-null-assertion - expires_in: toInt(body.poll.expires_in)!, // eslint-disable-line @typescript-eslint/no-non-null-assertion - multiple: toBoolean(body.poll.multiple), - hide_totals: toBoolean(body.poll.hide_totals), - } : undefined, - }; + const { client, me } = await this.clientService.getAuthClient(_request); + if ((body.in_reply_to_id && isDefaultEmoji) || (body.in_reply_to_id && isCustomEmoji)) { + const a = await client.createEmojiReaction( + body.in_reply_to_id, + removed, + ); + return reply.send(a.data); + } + if (body.in_reply_to_id && removed === '/unreact') { + const id = body.in_reply_to_id; + const post = await client.getStatus(id); + const react = post.data.emoji_reactions.filter((e: Entity.Emoji) => e.me)[0].name; + const data = await client.deleteEmojiReaction(id, react); + return reply.send(data.data); + } + if (!body.media_ids) body.media_ids = undefined; + if (body.media_ids && !body.media_ids.length) body.media_ids = undefined; - const data = await client.postStatus(text, options); - reply.send(await this.mastoConverters.convertStatus(data.data as Entity.Status, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error('POST /v1/statuses', data); - reply.code(401).send(data); + if (body.poll && !body.poll.options) { + return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required payload "poll.options"' }); + } + if (body.poll && !body.poll.expires_in) { + return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required payload "poll.expires_in"' }); } + + const options = { + ...body, + sensitive: toBoolean(body.sensitive), + poll: body.poll ? { + options: body.poll.options!, // eslint-disable-line @typescript-eslint/no-non-null-assertion + expires_in: toInt(body.poll.expires_in)!, // eslint-disable-line @typescript-eslint/no-non-null-assertion + multiple: toBoolean(body.poll.multiple), + hide_totals: toBoolean(body.poll.hide_totals), + } : undefined, + }; + + const data = await client.postStatus(text, options); + const response = await this.mastoConverters.convertStatus(data.data as Entity.Status, me); + + return reply.send(response); }); - } - public updateStatus() { - this.fastify.put<{ + fastify.put<{ Params: { id: string }, Body: { status?: string, @@ -273,201 +212,138 @@ export class ApiStatusMastodon { }, } }>('/v1/statuses/:id', async (_request, reply) => { - try { - const { client, me } = await this.mastodon.getAuthClient(_request); - const body = _request.body; + const { client, me } = await this.clientService.getAuthClient(_request); + const body = _request.body; - if (!body.media_ids || !body.media_ids.length) { - body.media_ids = undefined; - } + if (!body.media_ids || !body.media_ids.length) { + body.media_ids = undefined; + } - const options = { - ...body, - sensitive: toBoolean(body.sensitive), - poll: body.poll ? { - options: body.poll.options, - expires_in: toInt(body.poll.expires_in), - multiple: toBoolean(body.poll.multiple), - hide_totals: toBoolean(body.poll.hide_totals), - } : undefined, - }; + const options = { + ...body, + sensitive: toBoolean(body.sensitive), + poll: body.poll ? { + options: body.poll.options, + expires_in: toInt(body.poll.expires_in), + multiple: toBoolean(body.poll.multiple), + hide_totals: toBoolean(body.poll.hide_totals), + } : undefined, + }; - const data = await client.editStatus(_request.params.id, options); - reply.send(await this.mastoConverters.convertStatus(data.data, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`POST /v1/statuses/${_request.params.id}`, data); - reply.code(401).send(data); - } + const data = await client.editStatus(_request.params.id, options); + const response = await this.mastoConverters.convertStatus(data.data, me); + + return reply.send(response); }); - } - public addFavourite() { - this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/favourite', async (_request, reply) => { - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const { client, me } = await this.mastodon.getAuthClient(_request); - const data = await client.createEmojiReaction(_request.params.id, '❤'); - reply.send(await this.mastoConverters.convertStatus(data.data, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`POST /v1/statuses/${_request.params.id}/favorite`, data); - reply.code(401).send(data); - } + fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/favourite', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const { client, me } = await this.clientService.getAuthClient(_request); + const data = await client.createEmojiReaction(_request.params.id, '❤'); + const response = await this.mastoConverters.convertStatus(data.data, me); + + return reply.send(response); }); - } - public rmFavourite() { - this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/unfavourite', async (_request, reply) => { - try { - const { client, me } = await this.mastodon.getAuthClient(_request); - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const data = await client.deleteEmojiReaction(_request.params.id, '❤'); - reply.send(await this.mastoConverters.convertStatus(data.data, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`GET /v1/statuses/${_request.params.id}/unfavorite`, data); - reply.code(401).send(data); - } + fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/unfavourite', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const { client, me } = await this.clientService.getAuthClient(_request); + const data = await client.deleteEmojiReaction(_request.params.id, '❤'); + const response = await this.mastoConverters.convertStatus(data.data, me); + + return reply.send(response); }); - } - public reblogStatus() { - this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/reblog', async (_request, reply) => { - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const { client, me } = await this.mastodon.getAuthClient(_request); - const data = await client.reblogStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`POST /v1/statuses/${_request.params.id}/reblog`, data); - reply.code(401).send(data); - } + fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/reblog', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const { client, me } = await this.clientService.getAuthClient(_request); + const data = await client.reblogStatus(_request.params.id); + const response = await this.mastoConverters.convertStatus(data.data, me); + + return reply.send(response); }); - } - public unreblogStatus() { - this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/unreblog', async (_request, reply) => { - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const { client, me } = await this.mastodon.getAuthClient(_request); - const data = await client.unreblogStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`POST /v1/statuses/${_request.params.id}/unreblog`, data); - reply.code(401).send(data); - } + fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/unreblog', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const { client, me } = await this.clientService.getAuthClient(_request); + const data = await client.unreblogStatus(_request.params.id); + const response = await this.mastoConverters.convertStatus(data.data, me); + + return reply.send(response); }); - } - public bookmarkStatus() { - this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/bookmark', async (_request, reply) => { - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const { client, me } = await this.mastodon.getAuthClient(_request); - const data = await client.bookmarkStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`POST /v1/statuses/${_request.params.id}/bookmark`, data); - reply.code(401).send(data); - } + fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/bookmark', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const { client, me } = await this.clientService.getAuthClient(_request); + const data = await client.bookmarkStatus(_request.params.id); + const response = await this.mastoConverters.convertStatus(data.data, me); + + return reply.send(response); }); - } - public unbookmarkStatus() { - this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/unbookmark', async (_request, reply) => { - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const { client, me } = await this.mastodon.getAuthClient(_request); - const data = await client.unbookmarkStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`POST /v1/statuses/${_request.params.id}/unbookmark`, data); - reply.code(401).send(data); - } + fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/unbookmark', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const { client, me } = await this.clientService.getAuthClient(_request); + const data = await client.unbookmarkStatus(_request.params.id); + const response = await this.mastoConverters.convertStatus(data.data, me); + + return reply.send(response); }); - } + fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/pin', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); - public pinStatus() { - this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/pin', async (_request, reply) => { - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const { client, me } = await this.mastodon.getAuthClient(_request); - const data = await client.pinStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`POST /v1/statuses/${_request.params.id}/pin`, data); - reply.code(401).send(data); - } + const { client, me } = await this.clientService.getAuthClient(_request); + const data = await client.pinStatus(_request.params.id); + const response = await this.mastoConverters.convertStatus(data.data, me); + + return reply.send(response); }); - } - public unpinStatus() { - this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/unpin', async (_request, reply) => { - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const { client, me } = await this.mastodon.getAuthClient(_request); - const data = await client.unpinStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`POST /v1/statuses/${_request.params.id}/unpin`, data); - reply.code(401).send(data); - } + fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/unpin', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const { client, me } = await this.clientService.getAuthClient(_request); + const data = await client.unpinStatus(_request.params.id); + const response = await this.mastoConverters.convertStatus(data.data, me); + + return reply.send(response); }); - } - public reactStatus() { - this.fastify.post<{ Params: { id?: string, name?: string } }>('/v1/statuses/:id/react/:name', async (_request, reply) => { - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - if (!_request.params.name) return reply.code(400).send({ error: 'Missing required parameter "name"' }); - const { client, me } = await this.mastodon.getAuthClient(_request); - const data = await client.createEmojiReaction(_request.params.id, _request.params.name); - reply.send(await this.mastoConverters.convertStatus(data.data, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`POST /v1/statuses/${_request.params.id}/react/${_request.params.name}`, data); - reply.code(401).send(data); - } + fastify.post<{ Params: { id?: string, name?: string } }>('/v1/statuses/:id/react/:name', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + if (!_request.params.name) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "name"' }); + + const { client, me } = await this.clientService.getAuthClient(_request); + const data = await client.createEmojiReaction(_request.params.id, _request.params.name); + const response = await this.mastoConverters.convertStatus(data.data, me); + + return reply.send(response); }); - } - public unreactStatus() { - this.fastify.post<{ Params: { id?: string, name?: string } }>('/v1/statuses/:id/unreact/:name', async (_request, reply) => { - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - if (!_request.params.name) return reply.code(400).send({ error: 'Missing required parameter "name"' }); - const { client, me } = await this.mastodon.getAuthClient(_request); - const data = await client.deleteEmojiReaction(_request.params.id, _request.params.name); - reply.send(await this.mastoConverters.convertStatus(data.data, me)); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`POST /v1/statuses/${_request.params.id}/unreact/${_request.params.name}`, data); - reply.code(401).send(data); - } + fastify.post<{ Params: { id?: string, name?: string } }>('/v1/statuses/:id/unreact/:name', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + if (!_request.params.name) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "name"' }); + + const { client, me } = await this.clientService.getAuthClient(_request); + const data = await client.deleteEmojiReaction(_request.params.id, _request.params.name); + const response = await this.mastoConverters.convertStatus(data.data, me); + + return reply.send(response); }); - } - public deleteStatus() { - this.fastify.delete<{ Params: { id?: string } }>('/v1/statuses/:id', async (_request, reply) => { - const BASE_URL = `${_request.protocol}://${_request.host}`; - const accessTokens = _request.headers.authorization; - const client = getClient(BASE_URL, accessTokens); - try { - if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' }); - const data = await client.deleteStatus(_request.params.id); - reply.send(data.data); - } catch (e) { - const data = getErrorData(e); - this.logger.error(`DELETE /v1/statuses/${_request.params.id}`, data); - reply.code(401).send(data); - } + fastify.delete<{ Params: { id?: string } }>('/v1/statuses/:id', async (_request, reply) => { + if (!_request.params.id) return reply.code(400).send({ error: 'BAD_REQUEST', error_description: 'Missing required parameter "id"' }); + + const client = this.clientService.getClient(_request); + const data = await client.deleteStatus(_request.params.id); + + return reply.send(data.data); }); } } |