From 57495dbd7a1bb17d7c92fdbda33bdf54a69a41aa Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Tue, 7 May 2024 20:49:42 -0300 Subject: [PATCH] feat: implement report resolve --- src/app.ts | 15 +++++++++++++-- src/controllers/api/reports.ts | 30 +++++++++++++++++++++++++++++- src/views/mastodon/reports.ts | 5 +++-- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/app.ts b/src/app.ts index 6e5aaae..a3f6a43 100644 --- a/src/app.ts +++ b/src/app.ts @@ -44,7 +44,12 @@ import { } from '@/controllers/api/pleroma.ts'; import { preferencesController } from '@/controllers/api/preferences.ts'; import { relayController } from '@/controllers/nostr/relay.ts'; -import { adminReportController, adminReportsController, reportsController } from '@/controllers/api/reports.ts'; +import { + adminReportController, + adminReportResolveController, + adminReportsController, + reportsController, +} from '@/controllers/api/reports.ts'; import { searchController } from '@/controllers/api/search.ts'; import { bookmarkController, @@ -209,7 +214,13 @@ app.put('/api/v1/admin/ditto/relays', requireRole('admin'), adminSetRelaysContro app.post('/api/v1/reports', requirePubkey, reportsController); app.get('/api/v1/admin/reports', requirePubkey, requireRole('admin'), adminReportsController); -app.get('/api/v1/admin/reports/:id', requirePubkey, requireRole('admin'), adminReportController); +app.get('/api/v1/admin/reports/:id{[0-9a-f]{64}}', requirePubkey, requireRole('admin'), adminReportController); +app.post( + '/api/v1/admin/reports/:id{[0-9a-f]{64}}/resolve', + requirePubkey, + requireRole('admin'), + adminReportResolveController, +); // Not (yet) implemented. app.get('/api/v1/custom_emojis', emptyArrayController); diff --git a/src/controllers/api/reports.ts b/src/controllers/api/reports.ts index 6845020..d363630 100644 --- a/src/controllers/api/reports.ts +++ b/src/controllers/api/reports.ts @@ -88,4 +88,32 @@ const adminReportController: AppController = async (c) => { return c.json(await renderAdminReport(event, { viewerPubkey: pubkey })); }; -export { adminReportController, adminReportsController, reportsController }; +/** https://docs.joinmastodon.org/methods/admin/reports/#resolve */ +const adminReportResolveController: AppController = async (c) => { + const eventId = c.req.param('id'); + const { signal } = c.req.raw; + const store = c.get('store'); + const pubkey = c.get('pubkey'); + + const [event] = await store.query([{ + kinds: [1984], + ids: [eventId], + limit: 1, + }], { signal }); + + if (!event) { + return c.json({ error: 'This action is not allowed' }, 403); + } + + await hydrateEvents({ events: [event], storage: store, signal }); + + await createEvent({ + kind: 5, + tags: [['e', event.id]], + content: 'Report closed.', + }, c); + + return c.json(await renderAdminReport(event, { viewerPubkey: pubkey, action_taken: true })); +}; + +export { adminReportController, adminReportResolveController, adminReportsController, reportsController }; diff --git a/src/views/mastodon/reports.ts b/src/views/mastodon/reports.ts index 850f86b..5ddbe69 100644 --- a/src/views/mastodon/reports.ts +++ b/src/views/mastodon/reports.ts @@ -30,13 +30,14 @@ async function renderReport(reportEvent: DittoEvent, profile: DittoEvent) { interface RenderAdminReportOpts { viewerPubkey?: string; + action_taken?: boolean; } /** Admin-level information about a filed report. * Expects an event of kind 1984 fully hydrated. * https://docs.joinmastodon.org/entities/Admin_Report */ async function renderAdminReport(reportEvent: DittoEvent, opts: RenderAdminReportOpts) { - const { viewerPubkey } = opts; + const { viewerPubkey, action_taken = false } = opts; // The category is present in both the 'e' and 'p' tag, however, it is possible to report a user without reporting a note, so it's better to get the category from the 'p' tag const category = reportEvent.tags.find(([name]) => name === 'p')?.[2]; @@ -50,7 +51,7 @@ async function renderAdminReport(reportEvent: DittoEvent, opts: RenderAdminRepor return { id: reportEvent.id, - action_taken: false, + action_taken, action_taken_at: null, category, comment: reportEvent.content,