refactor mastodon API and preserve remote user agent for requests

This commit is contained in:
Hazelnoot 2025-03-20 20:43:05 -04:00
parent 92382b2ed4
commit f61d71ac8c
17 changed files with 1319 additions and 1447 deletions

View file

@ -3,56 +3,95 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { parseTimelineArgs, TimelineArgs } from '@/server/api/mastodon/timelineArgs.js';
import { MiLocalUser } from '@/models/User.js';
import { Injectable } from '@nestjs/common';
import { parseTimelineArgs, TimelineArgs } from '@/server/api/mastodon/argsUtils.js';
import { MastoConverters } from '@/server/api/mastodon/converters.js';
import type { MegalodonInterface } from 'megalodon';
import type { FastifyRequest } from 'fastify';
import { getErrorData, MastodonLogger } from '@/server/api/mastodon/MastodonLogger.js';
import { MastodonClientService } from '../MastodonClientService.js';
import type { FastifyInstance } from 'fastify';
import type multer from 'fastify-multer';
export interface ApiNotifyMastodonRoute {
interface ApiNotifyMastodonRoute {
Params: {
id?: string,
},
Querystring: TimelineArgs,
}
export class ApiNotifyMastodon {
@Injectable()
export class ApiNotificationsMastodon {
constructor(
private readonly request: FastifyRequest<ApiNotifyMastodonRoute>,
private readonly client: MegalodonInterface,
private readonly me: MiLocalUser | null,
private readonly mastoConverters: MastoConverters,
private readonly clientService: MastodonClientService,
private readonly logger: MastodonLogger,
) {}
public async getNotifications() {
const data = await this.client.getNotifications(parseTimelineArgs(this.request.query));
return Promise.all(data.data.map(async n => {
const converted = await this.mastoConverters.convertNotification(n, this.me);
if (converted.type === 'reaction') {
converted.type = 'favourite';
public register(fastify: FastifyInstance, upload: ReturnType<typeof multer>): void {
fastify.get<ApiNotifyMastodonRoute>('/v1/notifications', async (_request, reply) => {
try {
const { client, me } = await this.clientService.getAuthClient(_request);
const data = await client.getNotifications(parseTimelineArgs(_request.query));
const response = Promise.all(data.data.map(async n => {
const converted = await this.mastoConverters.convertNotification(n, me);
if (converted.type === 'reaction') {
converted.type = 'favourite';
}
return converted;
}));
reply.send(response);
} catch (e) {
const data = getErrorData(e);
this.logger.error('GET /v1/notifications', data);
reply.code(401).send(data);
}
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 = await this.mastoConverters.convertNotification(data.data, this.me);
if (converted.type === 'reaction') {
converted.type = 'favourite';
}
return converted;
}
fastify.get<ApiNotifyMastodonRoute & { Params: { id?: string } }>('/v1/notification/:id', async (_request, reply) => {
try {
if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' });
public async rmNotification() {
if (!this.request.params.id) throw new Error('Missing required parameter "id"');
const data = await this.client.dismissNotification(this.request.params.id);
return data.data;
}
const { client, me } = await this.clientService.getAuthClient(_request);
const data = await client.getNotification(_request.params.id);
const converted = await this.mastoConverters.convertNotification(data.data, me);
if (converted.type === 'reaction') {
converted.type = 'favourite';
}
public async rmNotifications() {
const data = await this.client.dismissNotifications();
return data.data;
reply.send(converted);
} catch (e) {
const data = getErrorData(e);
this.logger.error(`GET /v1/notification/${_request.params.id}`, data);
reply.code(401).send(data);
}
});
fastify.post<ApiNotifyMastodonRoute & { Params: { id?: string } }>('/v1/notification/:id/dismiss', { preHandler: upload.single('none') }, async (_request, reply) => {
try {
if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' });
const client = this.clientService.getClient(_request);
const data = await client.dismissNotification(_request.params.id);
reply.send(data.data);
} catch (e) {
const data = getErrorData(e);
this.logger.error(`POST /v1/notification/${_request.params.id}/dismiss`, data);
reply.code(401).send(data);
}
});
fastify.post<ApiNotifyMastodonRoute>('/v1/notifications/clear', { preHandler: upload.single('none') }, async (_request, reply) => {
try {
const client = this.clientService.getClient(_request);
const data = await client.dismissNotifications();
reply.send(data.data);
} catch (e) {
const data = getErrorData(e);
this.logger.error('POST /v1/notifications/clear', data);
reply.code(401).send(data);
}
});
}
}