Add "streak" app, letting users forfeit through the API

This commit is contained in:
Alex Gleason 2025-02-05 18:05:07 -06:00
parent 430fd196d7
commit ca9246a20a
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
3 changed files with 29 additions and 3 deletions

View file

@ -108,6 +108,7 @@ import {
zapController, zapController,
zappedByController, zappedByController,
} from '@/controllers/api/statuses.ts'; } from '@/controllers/api/statuses.ts';
import streakApp from '@/controllers/api/streak.ts';
import { streamingController } from '@/controllers/api/streaming.ts'; import { streamingController } from '@/controllers/api/streaming.ts';
import { import {
localSuggestionsController, localSuggestionsController,
@ -382,6 +383,7 @@ app.put('/api/v1/admin/ditto/relays', requireRole('admin'), adminSetRelaysContro
app.put('/api/v1/admin/ditto/instance', requireRole('admin'), updateInstanceController); app.put('/api/v1/admin/ditto/instance', requireRole('admin'), updateInstanceController);
app.route('/api/v1/ditto/streak', streakApp);
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);

View file

@ -0,0 +1,24 @@
import { Hono } from '@hono/hono';
import { Conf } from '@/config.ts';
import { requireSigner } from '@/middleware/requireSigner.ts';
import { updateAdminEvent } from '@/utils/api.ts';
const app = new Hono();
app.post('/forfeit', requireSigner, async (c) => {
const pubkey = await c.get('signer').getPublicKey();
await updateAdminEvent(
{ kinds: [30382], authors: [Conf.pubkey], '#d': [pubkey], limit: 1 },
(prev) => {
const tags = prev?.tags.filter(([name]) => !['ditto.streak.start', 'ditto.streak.end'].includes(name)) ?? [];
return { ...prev, kind: 30382, tags };
},
c,
);
return c.newResponse(null, 204);
});
export default app;

View file

@ -80,7 +80,7 @@ function updateListEvent(
} }
/** Publish an admin event through the pipeline. */ /** Publish an admin event through the pipeline. */
async function createAdminEvent(t: EventStub, c: AppContext): Promise<NostrEvent> { async function createAdminEvent(t: EventStub, c: Context): Promise<NostrEvent> {
const signer = new AdminSigner(); const signer = new AdminSigner();
const event = await signer.signEvent({ const event = await signer.signEvent({
@ -110,7 +110,7 @@ function updateListAdminEvent(
async function updateAdminEvent<E extends EventStub>( async function updateAdminEvent<E extends EventStub>(
filter: UpdateEventFilter, filter: UpdateEventFilter,
fn: (prev: NostrEvent | undefined) => E, fn: (prev: NostrEvent | undefined) => E,
c: AppContext, c: Context,
): Promise<NostrEvent> { ): Promise<NostrEvent> {
const store = await Storages.db(); const store = await Storages.db();
const [prev] = await store.query([filter], { limit: 1, signal: c.req.raw.signal }); const [prev] = await store.query([filter], { limit: 1, signal: c.req.raw.signal });
@ -156,7 +156,7 @@ async function updateNames(k: number, d: string, n: Record<string, boolean>, c:
} }
/** Push the event through the pipeline, rethrowing any RelayError. */ /** Push the event through the pipeline, rethrowing any RelayError. */
async function publishEvent(event: NostrEvent, c: AppContext): Promise<NostrEvent> { async function publishEvent(event: NostrEvent, c: Context): Promise<NostrEvent> {
logi({ level: 'info', ns: 'ditto.event', source: 'api', id: event.id, kind: event.kind }); logi({ level: 'info', ns: 'ditto.event', source: 'api', id: event.id, kind: event.kind });
try { try {
await pipeline.handleEvent(event, { source: 'api', signal: c.req.raw.signal }); await pipeline.handleEvent(event, { source: 'api', signal: c.req.raw.signal });