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:
commit
98b19faeee
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue