diff --git a/src/db/events.ts b/src/db/events.ts index b86e70d..60f0061 100644 --- a/src/db/events.ts +++ b/src/db/events.ts @@ -1,19 +1,25 @@ import { db, type TagRow } from '@/db.ts'; import { type Event, type Insertable, SqliteError } from '@/deps.ts'; +import { isParameterizedReplaceableKind } from '@/kinds.ts'; +import { jsonMetaContentSchema } from '@/schemas/nostr.ts'; +import { isNostrId, isURL } from '@/utils.ts'; import type { DittoFilter, GetFiltersOpts } from '@/filter.ts'; -import { jsonMetaContentSchema } from '@/schemas/nostr.ts'; -type TagCondition = ({ event, count }: { event: Event; count: number }) => boolean; +type TagCondition = ({ event, count, value }: { + event: Event; + count: number; + value: string; +}) => boolean; /** Conditions for when to index certain tags. */ const tagConditions: Record = { - 'd': ({ event, count }) => 30000 <= event.kind && event.kind < 40000 && count === 0, - 'e': ({ count }) => count < 15, - 'p': ({ event, count }) => event.kind === 3 || count < 15, - 'proxy': ({ count }) => count === 0, - 'q': ({ event, count }) => event.kind === 1 && count === 0, - 't': ({ count }) => count < 5, + 'd': ({ event, count, value }) => isParameterizedReplaceableKind(event.kind) && count === 0 && value.length < 200, + 'e': ({ count, value }) => isNostrId(value) && count < 15, + 'p': ({ event, count, value }) => isNostrId(value) && (event.kind === 3 || count < 15), + 'proxy': ({ count, value }) => isURL(value) && count === 0 && value.length < 200, + 'q': ({ event, count, value }) => isNostrId(value) && event.kind === 1 && count === 0, + 't': ({ count, value }) => count < 5 && value.length < 50, }; /** Insert an event (and its tags) into the database. */ @@ -37,7 +43,7 @@ function insertEvent(event: Event): Promise { const tags = event.tags.reduce[]>((results, [name, value]) => { tagCounts[name] = (tagCounts[name] || 0) + 1; - if (value && tagConditions[name]?.({ event, count: tagCounts[name] - 1 })) { + if (value && tagConditions[name]?.({ event, count: tagCounts[name] - 1, value })) { results.push({ event_id: event.id, tag: name, diff --git a/src/utils.ts b/src/utils.ts index 1836298..11ef0ea 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,7 @@ import { type Event, type EventTemplate, getEventHash, nip19, z } from '@/deps.ts'; import { getAuthor } from '@/queries.ts'; import { lookupNip05Cached } from '@/utils/nip05.ts'; +import { nostrIdSchema } from '@/schemas/nostr.ts'; /** Get the current time in Nostr format. */ const nostrNow = (): number => Math.floor(Date.now() / 1000); @@ -111,6 +112,21 @@ function eventMatchesTemplate(event: Event, template: EventTemplate): boolean { return getEventHash(event) === getEventHash({ pubkey: event.pubkey, ...template }); } +/** Test whether the value is a Nostr ID. */ +function isNostrId(value: unknown): boolean { + return nostrIdSchema.safeParse(value).success; +} + +/** Test whether the value is a URL. */ +function isURL(value: unknown): boolean { + try { + new URL(value as string); + return true; + } catch (_) { + return false; + } +} + export { bech32ToPubkey, dedupeEvents, @@ -119,7 +135,9 @@ export { eventMatchesTemplate, findTag, isFollowing, + isNostrId, isRelay, + isURL, lookupAccount, type Nip05, nostrDate,