publish(task 8): outbox-relay-loader (kind:10002 parser + fetcher)
parseOutbox(ev) interpretiert nip-65 r-tags: ohne marker → read+write, "read"/"write"-marker → nur jeweiliges set. ignoriert fremde tag-namen. loadOutbox(bootstrapRelay, pubkey) fragt kind:10002-event via applesauce-relay 2.x und parst das ergebnis. 3 tests grün. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ebe73cbf46
commit
1ec48ad1a9
|
|
@ -0,0 +1,37 @@
|
|||
import { Relay } from 'applesauce-relay'
|
||||
import { firstValueFrom, timeout } from 'rxjs'
|
||||
import type { SignedEvent } from './relays.ts'
|
||||
|
||||
export interface Outbox {
|
||||
read: string[]
|
||||
write: string[]
|
||||
}
|
||||
|
||||
export function parseOutbox(ev: { tags: string[][] }): Outbox {
|
||||
const read: string[] = []
|
||||
const write: string[] = []
|
||||
for (const t of ev.tags) {
|
||||
if (t[0] !== 'r' || !t[1]) continue
|
||||
const marker = t[2]
|
||||
if (marker === 'read') read.push(t[1])
|
||||
else if (marker === 'write') write.push(t[1])
|
||||
else {
|
||||
read.push(t[1])
|
||||
write.push(t[1])
|
||||
}
|
||||
}
|
||||
return { read, write }
|
||||
}
|
||||
|
||||
export async function loadOutbox(
|
||||
bootstrapRelay: string,
|
||||
authorPubkeyHex: string,
|
||||
): Promise<Outbox> {
|
||||
const relay = new Relay(bootstrapRelay)
|
||||
const ev = await firstValueFrom(
|
||||
relay
|
||||
.request({ kinds: [10002], authors: [authorPubkeyHex], limit: 1 })
|
||||
.pipe(timeout({ first: 10_000 })),
|
||||
) as SignedEvent
|
||||
return parseOutbox(ev)
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import { assertEquals } from '@std/assert'
|
||||
import { parseOutbox } from '../src/core/outbox.ts'
|
||||
|
||||
Deno.test('parseOutbox: r-tags ohne marker → beide', () => {
|
||||
const ev = {
|
||||
kind: 10002,
|
||||
tags: [
|
||||
['r', 'wss://damus'],
|
||||
['r', 'wss://nos'],
|
||||
],
|
||||
}
|
||||
assertEquals(parseOutbox(ev), {
|
||||
read: ['wss://damus', 'wss://nos'],
|
||||
write: ['wss://damus', 'wss://nos'],
|
||||
})
|
||||
})
|
||||
|
||||
Deno.test('parseOutbox: marker read ignoriert schreib-nutzung', () => {
|
||||
const ev = {
|
||||
kind: 10002,
|
||||
tags: [
|
||||
['r', 'wss://r-only', 'read'],
|
||||
['r', 'wss://w-only', 'write'],
|
||||
['r', 'wss://both'],
|
||||
],
|
||||
}
|
||||
assertEquals(parseOutbox(ev), {
|
||||
read: ['wss://r-only', 'wss://both'],
|
||||
write: ['wss://w-only', 'wss://both'],
|
||||
})
|
||||
})
|
||||
|
||||
Deno.test('parseOutbox: ignoriert andere tag-namen', () => {
|
||||
const ev = {
|
||||
kind: 10002,
|
||||
tags: [
|
||||
['r', 'wss://x'],
|
||||
['p', 'someone'],
|
||||
],
|
||||
}
|
||||
assertEquals(parseOutbox(ev), { read: ['wss://x'], write: ['wss://x'] })
|
||||
})
|
||||
Loading…
Reference in New Issue