mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29:46 +00:00
Merge branch 'move-get-zap-split-to-new-endpoint' into 'main'
Create getZapSplitsController - Remove zap split from instance V1 endpoint Closes #182 See merge request soapbox-pub/ditto!442
This commit is contained in:
commit
b2136b35e8
5 changed files with 50 additions and 26 deletions
|
|
@ -40,6 +40,7 @@ import {
|
||||||
adminRelaysController,
|
adminRelaysController,
|
||||||
adminSetRelaysController,
|
adminSetRelaysController,
|
||||||
deleteZapSplitsController,
|
deleteZapSplitsController,
|
||||||
|
getZapSplitsController,
|
||||||
nameRequestController,
|
nameRequestController,
|
||||||
nameRequestsController,
|
nameRequestsController,
|
||||||
updateZapSplitsController,
|
updateZapSplitsController,
|
||||||
|
|
@ -263,6 +264,8 @@ app.put('/api/v1/admin/ditto/relays', requireRole('admin'), adminSetRelaysContro
|
||||||
app.post('/api/v1/ditto/names', requireSigner, nameRequestController);
|
app.post('/api/v1/ditto/names', requireSigner, nameRequestController);
|
||||||
app.get('/api/v1/ditto/names', requireSigner, nameRequestsController);
|
app.get('/api/v1/ditto/names', requireSigner, nameRequestsController);
|
||||||
|
|
||||||
|
app.get('/api/v1/ditto/zap_splits', getZapSplitsController);
|
||||||
|
|
||||||
app.put('/api/v1/admin/ditto/zap_splits', requireRole('admin'), updateZapSplitsController);
|
app.put('/api/v1/admin/ditto/zap_splits', requireRole('admin'), updateZapSplitsController);
|
||||||
app.delete('/api/v1/admin/ditto/zap_splits', requireRole('admin'), deleteZapSplitsController);
|
app.delete('/api/v1/admin/ditto/zap_splits', requireRole('admin'), deleteZapSplitsController);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,21 @@
|
||||||
import { NostrEvent, NostrFilter, NSchema as n } from '@nostrify/nostrify';
|
import { NostrEvent, NostrFilter, NSchema as n } from '@nostrify/nostrify';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { accountFromPubkey } from '@/views/mastodon/accounts.ts';
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
|
import { addTag } from '@/utils/tags.ts';
|
||||||
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||||
import { booleanParamSchema } from '@/schema.ts';
|
import { booleanParamSchema } from '@/schema.ts';
|
||||||
import { Conf } from '@/config.ts';
|
import { Conf } from '@/config.ts';
|
||||||
import { Storages } from '@/storages.ts';
|
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
|
||||||
import { createEvent, paginated, paginationSchema, parseBody } from '@/utils/api.ts';
|
import { createEvent, paginated, paginationSchema, parseBody } from '@/utils/api.ts';
|
||||||
import { renderNameRequest } from '@/views/ditto.ts';
|
|
||||||
import { getZapSplits } from '@/utils/zap-split.ts';
|
|
||||||
import { updateListAdminEvent } from '@/utils/api.ts';
|
|
||||||
import { addTag } from '@/utils/tags.ts';
|
|
||||||
import { deleteTag } from '@/utils/tags.ts';
|
import { deleteTag } from '@/utils/tags.ts';
|
||||||
|
import { DittoZapSplits, getZapSplits } from '@/utils/zap-split.ts';
|
||||||
|
import { getAuthor } from '@/queries.ts';
|
||||||
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
|
import { renderNameRequest } from '@/views/ditto.ts';
|
||||||
|
import { renderAccount } from '@/views/mastodon/accounts.ts';
|
||||||
|
import { Storages } from '@/storages.ts';
|
||||||
|
import { updateListAdminEvent } from '@/utils/api.ts';
|
||||||
|
|
||||||
const markerSchema = z.enum(['read', 'write']);
|
const markerSchema = z.enum(['read', 'write']);
|
||||||
|
|
||||||
|
|
@ -156,7 +159,7 @@ export const nameRequestsController: AppController = async (c) => {
|
||||||
const zapSplitSchema = z.record(
|
const zapSplitSchema = z.record(
|
||||||
n.id(),
|
n.id(),
|
||||||
z.object({
|
z.object({
|
||||||
amount: z.number().int().min(1).max(100),
|
weight: z.number().int().min(1).max(100),
|
||||||
message: z.string().max(500),
|
message: z.string().max(500),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
@ -170,8 +173,8 @@ export const updateZapSplitsController: AppController = async (c) => {
|
||||||
return c.json({ error: result.error }, 400);
|
return c.json({ error: result.error }, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
const zap_split = await getZapSplits(store, Conf.pubkey);
|
const dittoZapSplit = await getZapSplits(store, Conf.pubkey);
|
||||||
if (!zap_split) {
|
if (!dittoZapSplit) {
|
||||||
return c.json({ error: 'Zap split not activated, restart the server.' }, 404);
|
return c.json({ error: 'Zap split not activated, restart the server.' }, 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -186,7 +189,7 @@ export const updateZapSplitsController: AppController = async (c) => {
|
||||||
{ kinds: [30078], authors: [Conf.pubkey], '#d': ['pub.ditto.zapSplits'], limit: 1 },
|
{ kinds: [30078], authors: [Conf.pubkey], '#d': ['pub.ditto.zapSplits'], limit: 1 },
|
||||||
(tags) =>
|
(tags) =>
|
||||||
pubkeys.reduce((accumulator, pubkey) => {
|
pubkeys.reduce((accumulator, pubkey) => {
|
||||||
return addTag(accumulator, ['p', pubkey, data[pubkey].amount.toString(), data[pubkey].message]);
|
return addTag(accumulator, ['p', pubkey, data[pubkey].weight.toString(), data[pubkey].message]);
|
||||||
}, tags),
|
}, tags),
|
||||||
c,
|
c,
|
||||||
);
|
);
|
||||||
|
|
@ -205,8 +208,8 @@ export const deleteZapSplitsController: AppController = async (c) => {
|
||||||
return c.json({ error: result.error }, 400);
|
return c.json({ error: result.error }, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
const zap_split = await getZapSplits(store, Conf.pubkey);
|
const dittoZapSplit = await getZapSplits(store, Conf.pubkey);
|
||||||
if (!zap_split) {
|
if (!dittoZapSplit) {
|
||||||
return c.json({ error: 'Zap split not activated, restart the server.' }, 404);
|
return c.json({ error: 'Zap split not activated, restart the server.' }, 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,3 +226,28 @@ export const deleteZapSplitsController: AppController = async (c) => {
|
||||||
|
|
||||||
return c.json(200);
|
return c.json(200);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getZapSplitsController: AppController = async (c) => {
|
||||||
|
const store = c.get('store');
|
||||||
|
|
||||||
|
const dittoZapSplit: DittoZapSplits | undefined = await getZapSplits(store, Conf.pubkey) ?? {};
|
||||||
|
if (!dittoZapSplit) {
|
||||||
|
return c.json({ error: 'Zap split not activated, restart the server.' }, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pubkeys = Object.keys(dittoZapSplit);
|
||||||
|
|
||||||
|
const zapSplits = await Promise.all(pubkeys.map(async (pubkey) => {
|
||||||
|
const author = await getAuthor(pubkey);
|
||||||
|
|
||||||
|
const account = author ? await renderAccount(author) : await accountFromPubkey(pubkey);
|
||||||
|
|
||||||
|
return {
|
||||||
|
account,
|
||||||
|
weight: dittoZapSplit[pubkey].weight,
|
||||||
|
message: dittoZapSplit[pubkey].message,
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
|
||||||
|
return c.json(zapSplits, 200);
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,12 @@ import { AppController } from '@/app.ts';
|
||||||
import { Conf } from '@/config.ts';
|
import { Conf } from '@/config.ts';
|
||||||
import { Storages } from '@/storages.ts';
|
import { Storages } from '@/storages.ts';
|
||||||
import { getInstanceMetadata } from '@/utils/instance.ts';
|
import { getInstanceMetadata } from '@/utils/instance.ts';
|
||||||
import { DittoZapSplits, getZapSplits } from '@/utils/zap-split.ts';
|
|
||||||
|
|
||||||
const version = `3.0.0 (compatible; Ditto ${denoJson.version})`;
|
const version = `3.0.0 (compatible; Ditto ${denoJson.version})`;
|
||||||
|
|
||||||
const instanceV1Controller: AppController = async (c) => {
|
const instanceV1Controller: AppController = async (c) => {
|
||||||
const { host, protocol } = Conf.url;
|
const { host, protocol } = Conf.url;
|
||||||
const meta = await getInstanceMetadata(await Storages.db(), c.req.raw.signal);
|
const meta = await getInstanceMetadata(await Storages.db(), c.req.raw.signal);
|
||||||
const store = c.get('store');
|
|
||||||
|
|
||||||
const zap_split: DittoZapSplits | undefined = await getZapSplits(store, Conf.pubkey) ?? {};
|
|
||||||
|
|
||||||
/** Protocol to use for WebSocket URLs, depending on the protocol of the `LOCAL_DOMAIN`. */
|
/** Protocol to use for WebSocket URLs, depending on the protocol of the `LOCAL_DOMAIN`. */
|
||||||
const wsProtocol = protocol === 'http:' ? 'ws:' : 'wss:';
|
const wsProtocol = protocol === 'http:' ? 'ws:' : 'wss:';
|
||||||
|
|
@ -72,9 +68,6 @@ const instanceV1Controller: AppController = async (c) => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rules: [],
|
rules: [],
|
||||||
ditto: {
|
|
||||||
zap_split,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -179,12 +179,12 @@ const createStatusController: AppController = async (c) => {
|
||||||
|
|
||||||
const meta = n.json().pipe(n.metadata()).catch({}).parse(author?.content);
|
const meta = n.json().pipe(n.metadata()).catch({}).parse(author?.content);
|
||||||
const lnurl = getLnurl(meta);
|
const lnurl = getLnurl(meta);
|
||||||
const zap_split = await getZapSplits(store, Conf.pubkey);
|
const dittoZapSplit = await getZapSplits(store, Conf.pubkey);
|
||||||
if (lnurl && zap_split) {
|
if (lnurl && dittoZapSplit) {
|
||||||
let totalSplit = 0;
|
let totalSplit = 0;
|
||||||
for (const pubkey in zap_split) {
|
for (const pubkey in dittoZapSplit) {
|
||||||
totalSplit += zap_split[pubkey].amount;
|
totalSplit += dittoZapSplit[pubkey].weight;
|
||||||
tags.push(['zap', pubkey, Conf.relay, zap_split[pubkey].amount.toString()]);
|
tags.push(['zap', pubkey, Conf.relay, dittoZapSplit[pubkey].weight.toString()]);
|
||||||
}
|
}
|
||||||
if (totalSplit) {
|
if (totalSplit) {
|
||||||
tags.push(['zap', author?.pubkey as string, Conf.relay, Math.max(0, 100 - totalSplit).toString()]);
|
tags.push(['zap', author?.pubkey as string, Conf.relay, Math.max(0, 100 - totalSplit).toString()]);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ type ExtraMessage = string;
|
||||||
type splitPercentages = number;
|
type splitPercentages = number;
|
||||||
|
|
||||||
export type DittoZapSplits = {
|
export type DittoZapSplits = {
|
||||||
[key: Pubkey]: { amount: splitPercentages; message: ExtraMessage };
|
[key: Pubkey]: { weight: splitPercentages; message: ExtraMessage };
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Gets zap splits from NIP-78 in DittoZapSplits format. */
|
/** Gets zap splits from NIP-78 in DittoZapSplits format. */
|
||||||
|
|
@ -30,7 +30,7 @@ export async function getZapSplits(store: NStore, pubkey: string): Promise<Ditto
|
||||||
tag[0] === 'p' && n.id().safeParse(tag[1]).success &&
|
tag[0] === 'p' && n.id().safeParse(tag[1]).success &&
|
||||||
percentageSchema.safeParse(tag[2]).success
|
percentageSchema.safeParse(tag[2]).success
|
||||||
) {
|
) {
|
||||||
zapSplits[tag[1]] = { amount: Number(tag[2]), message: tag[3] };
|
zapSplits[tag[1]] = { weight: Number(tag[2]), message: tag[3] };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue