diff options
| author | Hazelnoot <acomputerdog@gmail.com> | 2025-01-31 12:54:18 -0500 |
|---|---|---|
| committer | Hazelnoot <acomputerdog@gmail.com> | 2025-02-08 13:17:50 -0500 |
| commit | 1e43162ba777d471c5406f614b72425e0800bf2f (patch) | |
| tree | 52f9110bda18186ae0a7e1c0137f5f2145bedfa7 /packages/backend/src/server/api/mastodon/endpoints | |
| parent | hide restricted edit history from mastodon api (resolves #811) (diff) | |
| download | sharkey-1e43162ba777d471c5406f614b72425e0800bf2f.tar.gz sharkey-1e43162ba777d471c5406f614b72425e0800bf2f.tar.bz2 sharkey-1e43162ba777d471c5406f614b72425e0800bf2f.zip | |
improve mastodon note conversion and use access checks in more places (resolves #509)
Diffstat (limited to 'packages/backend/src/server/api/mastodon/endpoints')
5 files changed, 68 insertions, 94 deletions
diff --git a/packages/backend/src/server/api/mastodon/endpoints/account.ts b/packages/backend/src/server/api/mastodon/endpoints/account.ts index 1481a48924..79cdddcb9e 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/account.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/account.ts @@ -5,6 +5,7 @@ import { Injectable } from '@nestjs/common'; import { parseTimelineArgs, TimelineArgs } from '@/server/api/mastodon/timelineArgs.js'; +import { MiLocalUser } from '@/models/User.js'; import { MastoConverters, convertRelationship } from '../converters.js'; import type { MegalodonInterface } from 'megalodon'; import type { FastifyRequest } from 'fastify'; @@ -20,6 +21,7 @@ export class ApiAccountMastodon { constructor( private readonly request: FastifyRequest<ApiAccountMastodonRoute>, private readonly client: MegalodonInterface, + private readonly me: MiLocalUser | null, private readonly mastoConverters: MastoConverters, ) {} @@ -51,7 +53,7 @@ export class ApiAccountMastodon { public async getStatuses() { if (!this.request.params.id) throw new Error('Missing required parameter "id"'); const data = await this.client.getAccountStatuses(this.request.params.id, parseTimelineArgs(this.request.query)); - return await Promise.all(data.data.map(async (status) => await this.mastoConverters.convertStatus(status))); + return await Promise.all(data.data.map(async (status) => await this.mastoConverters.convertStatus(status, this.me))); } public async getFollowers() { @@ -117,12 +119,12 @@ export class ApiAccountMastodon { public async getBookmarks() { const data = await this.client.getBookmarks(parseTimelineArgs(this.request.query)); - return Promise.all(data.data.map((status) => this.mastoConverters.convertStatus(status))); + return Promise.all(data.data.map((status) => this.mastoConverters.convertStatus(status, this.me))); } public async getFavourites() { const data = await this.client.getFavourites(parseTimelineArgs(this.request.query)); - return Promise.all(data.data.map((status) => this.mastoConverters.convertStatus(status))); + return Promise.all(data.data.map((status) => this.mastoConverters.convertStatus(status, this.me))); } public async getMutes() { diff --git a/packages/backend/src/server/api/mastodon/endpoints/notifications.ts b/packages/backend/src/server/api/mastodon/endpoints/notifications.ts index c228e17ddc..14eee8565a 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/notifications.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/notifications.ts @@ -4,7 +4,8 @@ */ import { parseTimelineArgs, TimelineArgs } from '@/server/api/mastodon/timelineArgs.js'; -import { convertNotification } from '../converters.js'; +import { MiLocalUser } from '@/models/User.js'; +import { MastoConverters } from '@/server/api/mastodon/converters.js'; import type { MegalodonInterface } from 'megalodon'; import type { FastifyRequest } from 'fastify'; @@ -19,23 +20,25 @@ export class ApiNotifyMastodon { constructor( private readonly request: FastifyRequest<ApiNotifyMastodonRoute>, private readonly client: MegalodonInterface, + private readonly me: MiLocalUser | null, + private readonly mastoConverters: MastoConverters, ) {} public async getNotifications() { const data = await this.client.getNotifications(parseTimelineArgs(this.request.query)); - return data.data.map(n => { - const converted = convertNotification(n); + return Promise.all(data.data.map(async n => { + const converted = await this.mastoConverters.convertNotification(n, this.me); if (converted.type === 'reaction') { converted.type = 'favourite'; } return converted; - }); + })); } public async getNotification() { if (!this.request.params.id) throw new Error('Missing required parameter "id"'); const data = await this.client.getNotification(this.request.params.id); - const converted = convertNotification(data.data); + const converted = await this.mastoConverters.convertNotification(data.data, this.me); if (converted.type === 'reaction') { converted.type = 'favourite'; } diff --git a/packages/backend/src/server/api/mastodon/endpoints/search.ts b/packages/backend/src/server/api/mastodon/endpoints/search.ts index ac5b836c1e..4850b4652f 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/search.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/search.ts @@ -3,6 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { MiLocalUser } from '@/models/User.js'; import { MastoConverters } from '../converters.js'; import { parseTimelineArgs, TimelineArgs } from '../timelineArgs.js'; import Account = Entity.Account; @@ -21,8 +22,9 @@ export class ApiSearchMastodon { constructor( private readonly request: FastifyRequest<ApiSearchMastodonRoute>, private readonly client: MegalodonInterface, + private readonly me: MiLocalUser | null, private readonly BASE_URL: string, - private readonly mastoConverter: MastoConverters, + private readonly mastoConverters: MastoConverters, ) {} public async SearchV1() { @@ -40,8 +42,8 @@ export class ApiSearchMastodon { const stat = !type || type === 'statuses' ? await this.client.search(this.request.query.q, { type: 'statuses', ...query }) : null; const tags = !type || type === 'hashtags' ? await this.client.search(this.request.query.q, { type: 'hashtags', ...query }) : null; return { - accounts: await Promise.all(acct?.data.accounts.map(async (account: Account) => await this.mastoConverter.convertAccount(account)) ?? []), - statuses: await Promise.all(stat?.data.statuses.map(async (status: Status) => await this.mastoConverter.convertStatus(status)) ?? []), + accounts: await Promise.all(acct?.data.accounts.map(async (account: Account) => await this.mastoConverters.convertAccount(account)) ?? []), + statuses: await Promise.all(stat?.data.statuses.map(async (status: Status) => await this.mastoConverters.convertStatus(status, this.me)) ?? []), hashtags: tags?.data.hashtags ?? [], }; } @@ -54,10 +56,12 @@ export class ApiSearchMastodon { 'Accept': 'application/json', 'Content-Type': 'application/json', }, - body: '{}', + body: JSON.stringify({ + i: this.request.headers.authorization?.replace('Bearer ', ''), + }), }) .then(res => res.json() as Promise<Status[]>) - .then(data => data.map(status => this.mastoConverter.convertStatus(status))); + .then(data => data.map(status => this.mastoConverters.convertStatus(status, this.me))); return Promise.all(data); } @@ -83,7 +87,7 @@ export class ApiSearchMastodon { account: entry, })))); return Promise.all(data.map(async suggestion => { - suggestion.account = await this.mastoConverter.convertAccount(suggestion.account); + suggestion.account = await this.mastoConverters.convertAccount(suggestion.account); return suggestion; })); } diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index 99259d2542..4c49a6a293 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -9,7 +9,7 @@ import { getErrorData, MastodonLogger } from '@/server/api/mastodon/MastodonLogg 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 } from '../MastodonApiServerService.js'; +import { getAccessToken, getClient, MastodonApiServerService } from '../MastodonApiServerService.js'; import type { Entity } from 'megalodon'; import type { FastifyInstance } from 'fastify'; @@ -24,17 +24,16 @@ export class ApiStatusMastodon { private readonly mastoConverters: MastoConverters, private readonly logger: MastodonLogger, private readonly authenticateService: AuthenticateService, + private readonly mastodon: MastodonApiServerService, ) {} public getStatus() { this.fastify.get<{ 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 { + 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)); + 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); @@ -62,14 +61,12 @@ export class ApiStatusMastodon { public getContext() { this.fastify.get<{ Params: { id?: string }, Querystring: TimelineArgs }>('/v1/statuses/:id/context', 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 { 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))); - const descendants = await Promise.all(data.descendants.map(async status => await this.mastoConverters.convertStatus(status))); + 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); @@ -204,11 +201,9 @@ export class ApiStatusMastodon { 'media_ids[]'?: string[], } }>('/v1/statuses', async (_request, reply) => { - const BASE_URL = `${_request.protocol}://${_request.host}`; - const accessTokens = _request.headers.authorization; - const client = getClient(BASE_URL, accessTokens); 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); @@ -253,7 +248,7 @@ export class ApiStatusMastodon { }; const data = await client.postStatus(text, options); - reply.send(await this.mastoConverters.convertStatus(data.data as Entity.Status)); + 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); @@ -278,10 +273,8 @@ export class ApiStatusMastodon { }, } }>('/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 { + const { client, me } = await this.mastodon.getAuthClient(_request); const body = _request.body; if (!body.media_ids || !body.media_ids.length) { @@ -300,7 +293,7 @@ export class ApiStatusMastodon { }; const data = await client.editStatus(_request.params.id, options); - reply.send(await this.mastoConverters.convertStatus(data.data)); + 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); @@ -311,13 +304,11 @@ export class ApiStatusMastodon { public addFavourite() { this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/favourite', 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 { client, me } = await this.mastodon.getAuthClient(_request); const data = await client.createEmojiReaction(_request.params.id, '❤'); - reply.send(await this.mastoConverters.convertStatus(data.data)); + 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); @@ -328,13 +319,11 @@ export class ApiStatusMastodon { public rmFavourite() { this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/unfavourite', async (_request, reply) => { - const BASE_URL = `${_request.protocol}://${_request.host}`; - const accessTokens = _request.headers.authorization; - const client = getClient(BASE_URL, accessTokens); 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)); + 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); @@ -345,13 +334,11 @@ export class ApiStatusMastodon { public reblogStatus() { this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/reblog', 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 { client, me } = await this.mastodon.getAuthClient(_request); const data = await client.reblogStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data)); + 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); @@ -362,13 +349,11 @@ export class ApiStatusMastodon { public unreblogStatus() { this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/unreblog', 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 { client, me } = await this.mastodon.getAuthClient(_request); const data = await client.unreblogStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data)); + 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); @@ -379,13 +364,11 @@ export class ApiStatusMastodon { public bookmarkStatus() { this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/bookmark', 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 { client, me } = await this.mastodon.getAuthClient(_request); const data = await client.bookmarkStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data)); + 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); @@ -396,13 +379,11 @@ export class ApiStatusMastodon { public unbookmarkStatus() { this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/unbookmark', 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 { client, me } = await this.mastodon.getAuthClient(_request); const data = await client.unbookmarkStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data)); + 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); @@ -413,13 +394,11 @@ export class ApiStatusMastodon { public pinStatus() { this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/pin', 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 { client, me } = await this.mastodon.getAuthClient(_request); const data = await client.pinStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data)); + 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); @@ -430,13 +409,11 @@ export class ApiStatusMastodon { public unpinStatus() { this.fastify.post<{ Params: { id?: string } }>('/v1/statuses/:id/unpin', 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 { client, me } = await this.mastodon.getAuthClient(_request); const data = await client.unpinStatus(_request.params.id); - reply.send(await this.mastoConverters.convertStatus(data.data)); + 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); @@ -447,14 +424,12 @@ export class ApiStatusMastodon { public reactStatus() { this.fastify.post<{ Params: { id?: string, name?: string } }>('/v1/statuses/:id/react/:name', 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.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)); + 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); @@ -465,14 +440,12 @@ export class ApiStatusMastodon { public unreactStatus() { this.fastify.post<{ Params: { id?: string, name?: string } }>('/v1/statuses/:id/unreact/:name', 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.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)); + 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); diff --git a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts index a6a778721a..1a732d62de 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts @@ -4,8 +4,8 @@ */ import { getErrorData, MastodonLogger } from '@/server/api/mastodon/MastodonLogger.js'; -import { convertConversation, convertList, MastoConverters } from '../converters.js'; -import { getClient } from '../MastodonApiServerService.js'; +import { convertList, MastoConverters } from '../converters.js'; +import { getClient, MastodonApiServerService } from '../MastodonApiServerService.js'; import { parseTimelineArgs, TimelineArgs, toBoolean } from '../timelineArgs.js'; import type { Entity } from 'megalodon'; import type { FastifyInstance } from 'fastify'; @@ -15,18 +15,17 @@ export class ApiTimelineMastodon { private readonly fastify: FastifyInstance, private readonly mastoConverters: MastoConverters, private readonly logger: MastodonLogger, + private readonly mastodon: MastodonApiServerService, ) {} public getTL() { this.fastify.get<{ Querystring: TimelineArgs }>('/v1/timelines/public', async (_request, reply) => { - const BASE_URL = `${_request.protocol}://${_request.host}`; - const accessTokens = _request.headers.authorization; - const client = getClient(BASE_URL, accessTokens); try { + const { client, me } = await this.mastodon.getAuthClient(_request); const data = toBoolean(_request.query.local) ? await client.getLocalTimeline(parseTimelineArgs(_request.query)) : await client.getPublicTimeline(parseTimelineArgs(_request.query)); - reply.send(await Promise.all(data.data.map(async (status: Entity.Status) => await this.mastoConverters.convertStatus(status)))); + reply.send(await Promise.all(data.data.map(async (status: Entity.Status) => await this.mastoConverters.convertStatus(status, me)))); } catch (e) { const data = getErrorData(e); this.logger.error('GET /v1/timelines/public', data); @@ -37,12 +36,10 @@ export class ApiTimelineMastodon { public getHomeTl() { this.fastify.get<{ Querystring: TimelineArgs }>('/v1/timelines/home', async (_request, reply) => { - const BASE_URL = `${_request.protocol}://${_request.host}`; - const accessTokens = _request.headers.authorization; - const client = getClient(BASE_URL, accessTokens); try { + const { client, me } = await this.mastodon.getAuthClient(_request); const data = await client.getHomeTimeline(parseTimelineArgs(_request.query)); - reply.send(await Promise.all(data.data.map(async (status: Entity.Status) => await this.mastoConverters.convertStatus(status)))); + reply.send(await Promise.all(data.data.map(async (status: Entity.Status) => await this.mastoConverters.convertStatus(status, me)))); } catch (e) { const data = getErrorData(e); this.logger.error('GET /v1/timelines/home', data); @@ -53,13 +50,11 @@ export class ApiTimelineMastodon { public getTagTl() { this.fastify.get<{ Params: { hashtag?: string }, Querystring: TimelineArgs }>('/v1/timelines/tag/:hashtag', 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.hashtag) return reply.code(400).send({ error: 'Missing required parameter "hashtag"' }); + const { client, me } = await this.mastodon.getAuthClient(_request); const data = await client.getTagTimeline(_request.params.hashtag, parseTimelineArgs(_request.query)); - reply.send(await Promise.all(data.data.map(async (status: Entity.Status) => await this.mastoConverters.convertStatus(status)))); + reply.send(await Promise.all(data.data.map(async (status: Entity.Status) => await this.mastoConverters.convertStatus(status, me)))); } catch (e) { const data = getErrorData(e); this.logger.error(`GET /v1/timelines/tag/${_request.params.hashtag}`, data); @@ -70,13 +65,11 @@ export class ApiTimelineMastodon { public getListTL() { this.fastify.get<{ Params: { id?: string }, Querystring: TimelineArgs }>('/v1/timelines/list/: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 { client, me } = await this.mastodon.getAuthClient(_request); const data = await client.getListTimeline(_request.params.id, parseTimelineArgs(_request.query)); - reply.send(await Promise.all(data.data.map(async (status: Entity.Status) => await this.mastoConverters.convertStatus(status)))); + reply.send(await Promise.all(data.data.map(async (status: Entity.Status) => await this.mastoConverters.convertStatus(status, me)))); } catch (e) { const data = getErrorData(e); this.logger.error(`GET /v1/timelines/list/${_request.params.id}`, data); @@ -87,12 +80,11 @@ export class ApiTimelineMastodon { public getConversations() { this.fastify.get<{ Querystring: TimelineArgs }>('/v1/conversations', async (_request, reply) => { - const BASE_URL = `${_request.protocol}://${_request.host}`; - const accessTokens = _request.headers.authorization; - const client = getClient(BASE_URL, accessTokens); try { + const { client, me } = await this.mastodon.getAuthClient(_request); const data = await client.getConversationTimeline(parseTimelineArgs(_request.query)); - reply.send(data.data.map((conversation: Entity.Conversation) => convertConversation(conversation))); + const conversations = await Promise.all(data.data.map(async (conversation: Entity.Conversation) => await this.mastoConverters.convertConversation(conversation, me))); + reply.send(conversations); } catch (e) { const data = getErrorData(e); this.logger.error('GET /v1/conversations', data); |