diff --git a/src/admin.ts b/src/admin.ts deleted file mode 100644 index 85e2fd8..0000000 --- a/src/admin.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Conf } from '@/config.ts'; -import { type Event, type EventTemplate, finishEvent, nip19 } from '@/deps.ts'; - -// deno-lint-ignore require-await -async function signAdminEvent(event: EventTemplate): Promise> { - if (!Conf.nsec) throw new Error('No secret key. Set one with DITTO_NSEC.'); - - const result = nip19.decode(Conf.nsec); - - if (result.type !== 'nsec') throw new Error('Invalid DITTO_NSEC. It should start with "nsec1..."'); - - return finishEvent(event, result.data); -} - -export { signAdminEvent }; diff --git a/src/sign.ts b/src/sign.ts index d78aa4c..732c769 100644 --- a/src/sign.ts +++ b/src/sign.ts @@ -1,5 +1,6 @@ import { type AppContext } from '@/app.ts'; -import { type Event, type EventTemplate, getEventHash, getPublicKey, getSignature, HTTPException, z } from '@/deps.ts'; +import { Conf } from '@/config.ts'; +import { type Event, type EventTemplate, finishEvent, HTTPException, z } from '@/deps.ts'; import { signedEventSchema } from '@/schemas/nostr.ts'; import { ws } from '@/stream.ts'; @@ -61,11 +62,13 @@ async function signEvent(event: EventTemplate, c: }); } - (event as Event).pubkey = getPublicKey(seckey); - (event as Event).id = getEventHash(event as Event); - (event as Event).sig = getSignature(event as Event, seckey); - - return event as Event; + return finishEvent(event, seckey); } -export { signEvent }; +/** Sign event as the Ditto server. */ +// deno-lint-ignore require-await +async function signAdminEvent(event: EventTemplate): Promise> { + return finishEvent(event, Conf.seckey); +} + +export { signAdminEvent, signEvent }; diff --git a/src/utils/web.ts b/src/utils/web.ts index 1504614..91eaacd 100644 --- a/src/utils/web.ts +++ b/src/utils/web.ts @@ -1,16 +1,18 @@ import { Conf } from '@/config.ts'; import { type Context, type Event, EventTemplate, HTTPException, parseFormData, z } from '@/deps.ts'; import * as pipeline from '@/pipeline.ts'; -import { signEvent } from '@/sign.ts'; +import { signAdminEvent, signEvent } from '@/sign.ts'; import { nostrNow } from '@/utils.ts'; import type { AppContext } from '@/app.ts'; -/** Publish an event through the API, throwing a Hono exception on failure. */ -async function createEvent( - t: Omit, 'created_at'>, - c: AppContext, -): Promise> { +/** EventTemplate with or without a timestamp. If no timestamp is given, it will be generated. */ +interface PendingEvent extends Omit, 'created_at'> { + created_at?: number; +} + +/** Publish an event through the pipeline. */ +async function createEvent(t: PendingEvent, c: AppContext): Promise> { const pubkey = c.get('pubkey'); if (!pubkey) { @@ -22,6 +24,21 @@ async function createEvent( ...t, }, c); + return publishEvent(event, c); +} + +/** Publish an admin event through the pipeline. */ +async function createAdminEvent(t: PendingEvent, c: AppContext): Promise> { + const event = await signAdminEvent({ + created_at: nostrNow(), + ...t, + }); + + return publishEvent(event, c); +} + +/** Push the event through the pipeline, rethrowing any RelayError. */ +async function publishEvent(event: Event, c: AppContext): Promise> { try { await pipeline.handleEvent(event); } catch (e) { @@ -90,4 +107,12 @@ function activityJson(c: Context, object: T) { return response; } -export { activityJson, buildLinkHeader, createEvent, type PaginationParams, paginationSchema, parseBody }; +export { + activityJson, + buildLinkHeader, + createAdminEvent, + createEvent, + type PaginationParams, + paginationSchema, + parseBody, +};