import type { Event } from 'nostr-tools' import { generateReviewTipHashId } from '../hashIdGenerator' import type { ExtractedReviewTip } from './types' import { readAmountSats, readPaymentHash, readPayerPubkeyFromZapReceipt, readTagValue, readZapReceiptKind } from './utils' export async function extractReviewTipFromEvent(event: Event): Promise { if (event.kind !== 9735 || readZapReceiptKind(event) !== 'review_tip') { return null } const extracted = readReviewTipFields(event) if (!extracted) { return null } const id = await generateReviewTipHashId(extracted) return { type: 'review_tip', id, ...extracted, eventId: event.id } } function readReviewTipFields(event: Event): Omit | null { const payerPubkey = readPayerPubkeyFromZapReceipt(event) const amount = readAmountSats(event) const paymentHash = readPaymentHash(event) const reviewerPubkey = readTagValue(event, 'reviewer') ?? readTagValue(event, 'p') const authorPubkey = readTagValue(event, 'author') const articleId = readTagValue(event, 'article') const reviewId = readTagValue(event, 'review_id') ?? readTagValue(event, 'e') const required = { payerPubkey, reviewerPubkey, authorPubkey, articleId, reviewId } if (!areAllNonEmptyStrings(required) || amount === undefined) { console.error('[metadataExtractor] Invalid review_tip zap receipt: missing required fields', { eventId: event.id }) return null } return { ...required, amount, paymentHash } } function areAllNonEmptyStrings(values: Record): values is Record { return Object.values(values).every((value) => typeof value === 'string' && value.length > 0) }