Merge branch 'feat-zap-account' into 'main'

Support zapping account directly - Rewrite zapController

See merge request soapbox-pub/ditto!356
This commit is contained in:
Alex Gleason 2024-06-04 23:00:34 +00:00
commit 98b19faeee
2 changed files with 44 additions and 25 deletions

View File

@ -139,7 +139,7 @@ app.get('/relay', relayController);
app.use( app.use(
'*', '*',
cspMiddleware(), cspMiddleware(),
cors({ origin: '*', exposeHeaders: ['link', 'Ln-Invoice'] }), cors({ origin: '*', exposeHeaders: ['link'] }),
signerMiddleware, signerMiddleware,
uploaderMiddleware, uploaderMiddleware,
auth98Middleware(), auth98Middleware(),
@ -188,7 +188,6 @@ app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/bookmark', requireSigner, bookmarkC
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/unbookmark', requireSigner, unbookmarkController); app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/unbookmark', requireSigner, unbookmarkController);
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/pin', requireSigner, pinController); app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/pin', requireSigner, pinController);
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/unpin', requireSigner, unpinController); app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/unpin', requireSigner, unpinController);
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/zap', requireSigner, zapController);
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/reblog', requireSigner, reblogStatusController); app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/reblog', requireSigner, reblogStatusController);
app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/unreblog', requireSigner, unreblogStatusController); app.post('/api/v1/statuses/:id{[0-9a-f]{64}}/unreblog', requireSigner, unreblogStatusController);
app.post('/api/v1/statuses', requireSigner, createStatusController); app.post('/api/v1/statuses', requireSigner, createStatusController);
@ -240,6 +239,8 @@ app.delete('/api/v1/pleroma/admin/statuses/:id', requireRole('admin'), pleromaAd
app.get('/api/v1/admin/ditto/relays', requireRole('admin'), adminRelaysController); app.get('/api/v1/admin/ditto/relays', requireRole('admin'), adminRelaysController);
app.put('/api/v1/admin/ditto/relays', requireRole('admin'), adminSetRelaysController); app.put('/api/v1/admin/ditto/relays', requireRole('admin'), adminSetRelaysController);
app.post('/api/v1/ditto/zap', requireSigner, zapController);
app.post('/api/v1/reports', requireSigner, reportController); app.post('/api/v1/reports', requireSigner, reportController);
app.get('/api/v1/admin/reports', requireSigner, requireRole('admin'), adminReportsController); app.get('/api/v1/admin/reports', requireSigner, requireRole('admin'), adminReportsController);
app.get('/api/v1/admin/reports/:id{[0-9a-f]{64}}', requireSigner, requireRole('admin'), adminReportController); app.get('/api/v1/admin/reports/:id{[0-9a-f]{64}}', requireSigner, requireRole('admin'), adminReportController);

View File

@ -19,6 +19,7 @@ import { getInvoice, getLnurl } from '@/utils/lnurl.ts';
import { lookupPubkey } from '@/utils/lookup.ts'; import { lookupPubkey } from '@/utils/lookup.ts';
import { addTag, deleteTag } from '@/utils/tags.ts'; import { addTag, deleteTag } from '@/utils/tags.ts';
import { asyncReplaceAll } from '@/utils/text.ts'; import { asyncReplaceAll } from '@/utils/text.ts';
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
const createStatusSchema = z.object({ const createStatusSchema = z.object({
in_reply_to_id: n.id().nullish(), in_reply_to_id: n.id().nullish(),
@ -460,47 +461,64 @@ const unpinController: AppController = async (c) => {
}; };
const zapSchema = z.object({ const zapSchema = z.object({
account_id: n.id(),
status_id: n.id().optional(),
amount: z.number().int().positive(), amount: z.number().int().positive(),
comment: z.string().optional(), comment: z.string().optional(),
}); });
const zapController: AppController = async (c) => { const zapController: AppController = async (c) => {
const id = c.req.param('id');
const body = await parseBody(c.req.raw); const body = await parseBody(c.req.raw);
const params = zapSchema.safeParse(body); const result = zapSchema.safeParse(body);
const { signal } = c.req.raw; const { signal } = c.req.raw;
const store = c.get('store');
if (!params.success) { if (!result.success) {
return c.json({ error: 'Bad request', schema: params.error }, 400); return c.json({ error: 'Bad request', schema: result.error }, 400);
} }
const target = await getEvent(id, { kind: 1, relations: ['author', 'event_stats', 'author_stats'], signal }); const { account_id, status_id, amount, comment } = result.data;
const author = target?.author;
const meta = n.json().pipe(n.metadata()).catch({}).parse(author?.content);
const lnurl = getLnurl(meta);
const amount = params.data.amount;
if (target && lnurl) { const tags: string[][] = [];
const nostr = await createEvent({ let target: undefined | DittoEvent;
kind: 9734, let lnurl: undefined | string;
content: params.data.comment ?? '',
tags: [ if (status_id) {
target = await getEvent(status_id, { kind: 1, relations: ['author'], signal });
const author = target?.author;
const meta = n.json().pipe(n.metadata()).catch({}).parse(author?.content);
lnurl = getLnurl(meta);
if (target && lnurl) {
tags.push(
['e', target.id], ['e', target.id],
['p', target.pubkey], ['p', target.pubkey],
['amount', amount.toString()], ['amount', amount.toString()],
['relays', Conf.relay], ['relays', Conf.relay],
['lnurl', lnurl], ['lnurl', lnurl],
], );
}
} else {
[target] = await store.query([{ authors: [account_id], kinds: [0], limit: 1 }]);
const meta = n.json().pipe(n.metadata()).catch({}).parse(target?.content);
lnurl = getLnurl(meta);
if (target && lnurl) {
tags.push(
['p', target.pubkey],
['amount', amount.toString()],
['relays', Conf.relay],
['lnurl', lnurl],
);
}
}
if (target && lnurl) {
const nostr = await createEvent({
kind: 9734,
content: comment ?? '',
tags,
}, c); }, c);
const status = await renderStatus(target, { viewerPubkey: await c.get('signer')?.getPublicKey() }); return c.json({ invoice: await getInvoice({ amount, nostr: purifyEvent(nostr), lnurl }, signal) });
status.zapped = true;
return c.json(status, {
headers: {
'Ln-Invoice': await getInvoice({ amount, nostr: purifyEvent(nostr), lnurl }, signal),
},
});
} else { } else {
return c.json({ error: 'Event not found.' }, 404); return c.json({ error: 'Event not found.' }, 404);
} }