diff --git a/src/app.ts b/src/app.ts index 25b7a232..6e2f2aa1 100644 --- a/src/app.ts +++ b/src/app.ts @@ -43,6 +43,7 @@ import { getZapSplitsController, nameRequestController, nameRequestsController, + statusZapSplitsController, updateZapSplitsController, } from '@/controllers/api/ditto.ts'; import { emptyArrayController, emptyObjectController, notImplementedController } from '@/controllers/api/fallback.ts'; @@ -270,6 +271,7 @@ app.post('/api/v1/ditto/names', requireSigner, nameRequestController); app.get('/api/v1/ditto/names', requireSigner, nameRequestsController); app.get('/api/v1/ditto/zap_splits', getZapSplitsController); +app.get('/api/v1/ditto/:id{[0-9a-f]{64}}/zap_splits', statusZapSplitsController); app.put('/api/v1/admin/ditto/zap_splits', requireRole('admin'), updateZapSplitsController); app.delete('/api/v1/admin/ditto/zap_splits', requireRole('admin'), deleteZapSplitsController); diff --git a/src/controllers/api/ditto.ts b/src/controllers/api/ditto.ts index 49faebb9..899456a4 100644 --- a/src/controllers/api/ditto.ts +++ b/src/controllers/api/ditto.ts @@ -5,10 +5,11 @@ import { accountFromPubkey } from '@/views/mastodon/accounts.ts'; import { AppController } from '@/app.ts'; import { addTag } from '@/utils/tags.ts'; import { AdminSigner } from '@/signers/AdminSigner.ts'; -import { booleanParamSchema } from '@/schema.ts'; +import { booleanParamSchema, percentageSchema } from '@/schema.ts'; import { Conf } from '@/config.ts'; import { createEvent, paginated, parseBody } from '@/utils/api.ts'; import { deleteTag } from '@/utils/tags.ts'; +import { DittoEvent } from '@/interfaces/DittoEvent.ts'; import { DittoZapSplits, getZapSplits } from '@/utils/zap-split.ts'; import { getAuthor } from '@/queries.ts'; import { hydrateEvents } from '@/storages/hydrate.ts'; @@ -251,3 +252,36 @@ export const getZapSplitsController: AppController = async (c) => { return c.json(zapSplits, 200); }; + +export const statusZapSplitsController: AppController = async (c) => { + const store = c.get('store'); + const id = c.req.param('id'); + const { signal } = c.req.raw; + + const [event] = await store.query([{ kinds: [1], ids: [id], limit: 1 }], { signal }); + if (!event) { + return c.json({ error: 'Event not found' }, 404); + } + + const zapsTag = event.tags.filter(([name]) => name === 'zap'); + + const pubkeys = zapsTag.map((name) => name[1]); + + const users = await store.query([{ authors: pubkeys, kinds: [0], limit: pubkeys.length }], { signal }); + await hydrateEvents({ events: users, store, signal }); + + const zapSplits = (await Promise.all(pubkeys.map(async (pubkey) => { + const author = (users.find((event) => event.pubkey === pubkey) as DittoEvent | undefined)?.author; + const account = author ? await renderAccount(author) : await accountFromPubkey(pubkey); + + const weight = percentageSchema.catch(0).parse(zapsTag.find((name) => name[1] === pubkey)![3]) ?? 0; + + return { + account, + message: '', + weight: weight, + }; + }))).filter((zapSplit) => zapSplit.weight > 0); + + return c.json(zapSplits, 200); +};