From e8088c9eedf01c9cc7cc8483ade320143c82fd57 Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Wed, 1 May 2024 20:38:30 -0300 Subject: [PATCH 1/4] feat: define reports endpoint --- src/app.ts | 3 +++ src/controllers/api/reports.ts | 7 +++++++ 2 files changed, 10 insertions(+) create mode 100644 src/controllers/api/reports.ts diff --git a/src/app.ts b/src/app.ts index 7e91a013..1f580634 100644 --- a/src/app.ts +++ b/src/app.ts @@ -77,6 +77,7 @@ import { cache } from '@/middleware/cache.ts'; import { csp } from '@/middleware/csp.ts'; import { adminRelaysController } from '@/controllers/api/ditto.ts'; import { storeMiddleware } from '@/middleware/store.ts'; +import { reportsController } from '@/controllers/api/reports.ts'; interface AppEnv extends HonoEnv { Variables: { @@ -192,6 +193,8 @@ app.delete('/api/v1/pleroma/admin/statuses/:id', requireRole('admin'), pleromaAd app.get('/api/v1/admin/ditto/relays', requireRole('admin'), adminRelaysController); app.put('/api/v1/admin/ditto/relays', requireRole('admin'), adminRelaysController); +app.post('/api/v1/reports', requirePubkey, reportsController); + // Not (yet) implemented. app.get('/api/v1/custom_emojis', emptyArrayController); app.get('/api/v1/filters', emptyArrayController); diff --git a/src/controllers/api/reports.ts b/src/controllers/api/reports.ts new file mode 100644 index 00000000..24d8f459 --- /dev/null +++ b/src/controllers/api/reports.ts @@ -0,0 +1,7 @@ +import { type AppController } from '@/app.ts'; + +const reportsController: AppController = (c) => { + return c.json('Reports endpoint'); +}; + +export { reportsController }; From 23f8377231124197cd140a4766ffa703b9a98b01 Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Thu, 2 May 2024 16:03:15 -0300 Subject: [PATCH 2/4] feat: create reports controller --- src/controllers/api/reports.ts | 51 ++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/src/controllers/api/reports.ts b/src/controllers/api/reports.ts index 24d8f459..8008eaed 100644 --- a/src/controllers/api/reports.ts +++ b/src/controllers/api/reports.ts @@ -1,7 +1,54 @@ import { type AppController } from '@/app.ts'; +import { z } from 'zod'; +import { createEvent, parseBody } from '@/utils/api.ts'; +import { Conf } from '@/config.ts'; +import { hydrateEvents } from '@/storages/hydrate.ts'; +import { renderReports } from '@/views/mastodon/reports.ts'; -const reportsController: AppController = (c) => { - return c.json('Reports endpoint'); +const reportsSchema = z.object({ + account_id: z.string(), + status_ids: z.string().array().default([]), + comment: z.string().max(1000).default(''), + forward: z.boolean().default(false), + category: z.string().default('other'), + // TODO: rules_ids[] is not implemented +}); + +/** https://docs.joinmastodon.org/methods/reports/ */ +const reportsController: AppController = async (c) => { + const store = c.get('store'); + const body = await parseBody(c.req.raw); + const result = reportsSchema.safeParse(body); + + if (!result.success) { + return c.json(result.error, 422); + } + + const { + account_id, + status_ids, + comment, + forward, + category, + } = result.data; + + const [personBeingReported] = await store.query([{ kinds: [0], authors: [account_id] }]); + if (!personBeingReported) { + return c.json({ error: 'Record not found' }, 404); + } + + await hydrateEvents({ events: [personBeingReported], storage: store }); + + const event = await createEvent({ + kind: 1984, + content: JSON.stringify({ account_id, status_ids, comment, forward, category }), + tags: [ + ['p', account_id, category], + ['P', Conf.pubkey], + ], + }, c); + + return c.json(await renderReports(event, personBeingReported, {})); }; export { reportsController }; From 226c356646e1563f5cf3718af1b64dddd8417a5b Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Thu, 2 May 2024 16:03:59 -0300 Subject: [PATCH 3/4] feat: create mastodon response for reports --- src/views/mastodon/reports.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/views/mastodon/reports.ts diff --git a/src/views/mastodon/reports.ts b/src/views/mastodon/reports.ts new file mode 100644 index 00000000..67f9f6da --- /dev/null +++ b/src/views/mastodon/reports.ts @@ -0,0 +1,33 @@ +import { type DittoEvent } from '@/interfaces/DittoEvent.ts'; +import { renderAccount } from '@/views/mastodon/accounts.ts'; +import { nostrDate } from '@/utils.ts'; + +interface reportsOpts { + viewerPubkey?: string; +} + +/** Expects a `reportEvent` of kind 1984 and a `targetAccout` of kind 0 of the person being reported */ +async function renderReports(reportEvent: DittoEvent, targetAccout: DittoEvent, _opts: reportsOpts) { + const { + account_id, + status_ids, + comment, + forward, + category, + } = JSON.parse(reportEvent.content); + + return { + id: account_id, + action_taken: false, + action_taken_at: null, + category, + comment, + forwarded: forward, + created_at: nostrDate(reportEvent.created_at).toISOString(), + status_ids, + rules_ids: null, + target_account: await renderAccount(targetAccout), + }; +} + +export { renderReports }; From ca5433bcc78985c055c7d9b7e29fb7500c4557e7 Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Thu, 2 May 2024 20:21:58 -0300 Subject: [PATCH 4/4] refactor(reports): update code according to code review in MR 210 --- src/app.ts | 2 +- src/controllers/api/reports.ts | 19 +++++++++---------- src/views/mastodon/reports.ts | 14 +++++--------- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/app.ts b/src/app.ts index 4c0e6579..ce53251e 100644 --- a/src/app.ts +++ b/src/app.ts @@ -42,6 +42,7 @@ import { } from '@/controllers/api/pleroma.ts'; import { preferencesController } from '@/controllers/api/preferences.ts'; import { relayController } from '@/controllers/nostr/relay.ts'; +import { reportsController } from '@/controllers/api/reports.ts'; import { searchController } from '@/controllers/api/search.ts'; import { bookmarkController, @@ -77,7 +78,6 @@ import { cache } from '@/middleware/cache.ts'; import { csp } from '@/middleware/csp.ts'; import { adminRelaysController, adminSetRelaysController } from '@/controllers/api/ditto.ts'; import { storeMiddleware } from '@/middleware/store.ts'; -import { reportsController } from '@/controllers/api/reports.ts'; interface AppEnv extends HonoEnv { Variables: { diff --git a/src/controllers/api/reports.ts b/src/controllers/api/reports.ts index 8008eaed..9e1f9339 100644 --- a/src/controllers/api/reports.ts +++ b/src/controllers/api/reports.ts @@ -1,13 +1,14 @@ import { type AppController } from '@/app.ts'; -import { z } from 'zod'; import { createEvent, parseBody } from '@/utils/api.ts'; import { Conf } from '@/config.ts'; import { hydrateEvents } from '@/storages/hydrate.ts'; -import { renderReports } from '@/views/mastodon/reports.ts'; +import { NSchema as n } from '@nostrify/nostrify'; +import { renderReport } from '@/views/mastodon/reports.ts'; +import { z } from 'zod'; const reportsSchema = z.object({ - account_id: z.string(), - status_ids: z.string().array().default([]), + account_id: n.id(), + status_ids: n.id().array().default([]), comment: z.string().max(1000).default(''), forward: z.boolean().default(false), category: z.string().default('other'), @@ -32,13 +33,11 @@ const reportsController: AppController = async (c) => { category, } = result.data; - const [personBeingReported] = await store.query([{ kinds: [0], authors: [account_id] }]); - if (!personBeingReported) { - return c.json({ error: 'Record not found' }, 404); + const [profile] = await store.query([{ kinds: [0], authors: [account_id] }]); + if (profile) { + await hydrateEvents({ events: [profile], storage: store }); } - await hydrateEvents({ events: [personBeingReported], storage: store }); - const event = await createEvent({ kind: 1984, content: JSON.stringify({ account_id, status_ids, comment, forward, category }), @@ -48,7 +47,7 @@ const reportsController: AppController = async (c) => { ], }, c); - return c.json(await renderReports(event, personBeingReported, {})); + return c.json(await renderReport(event, profile)); }; export { reportsController }; diff --git a/src/views/mastodon/reports.ts b/src/views/mastodon/reports.ts index 67f9f6da..03291f7a 100644 --- a/src/views/mastodon/reports.ts +++ b/src/views/mastodon/reports.ts @@ -1,13 +1,9 @@ import { type DittoEvent } from '@/interfaces/DittoEvent.ts'; -import { renderAccount } from '@/views/mastodon/accounts.ts'; +import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts'; import { nostrDate } from '@/utils.ts'; -interface reportsOpts { - viewerPubkey?: string; -} - -/** Expects a `reportEvent` of kind 1984 and a `targetAccout` of kind 0 of the person being reported */ -async function renderReports(reportEvent: DittoEvent, targetAccout: DittoEvent, _opts: reportsOpts) { +/** Expects a `reportEvent` of kind 1984 and a `profile` of kind 0 of the person being reported */ +async function renderReport(reportEvent: DittoEvent, profile: DittoEvent) { const { account_id, status_ids, @@ -26,8 +22,8 @@ async function renderReports(reportEvent: DittoEvent, targetAccout: DittoEvent, created_at: nostrDate(reportEvent.created_at).toISOString(), status_ids, rules_ids: null, - target_account: await renderAccount(targetAccout), + target_account: profile ? await renderAccount(profile) : await accountFromPubkey(account_id), }; } -export { renderReports }; +export { renderReport };