75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
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<ExtractedReviewTip | null> {
|
|
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<ExtractedReviewTip, 'type' | 'id' | 'eventId'> | 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, paymentHash }
|
|
if (!hasRequiredReviewTipFields(required) || amount === undefined) {
|
|
console.error('[metadataExtractor] Invalid review_tip zap receipt: missing required fields', { eventId: event.id })
|
|
return null
|
|
}
|
|
|
|
return {
|
|
payerPubkey: required.payerPubkey,
|
|
reviewerPubkey: required.reviewerPubkey,
|
|
authorPubkey: required.authorPubkey,
|
|
articleId: required.articleId,
|
|
reviewId: required.reviewId,
|
|
amount,
|
|
paymentHash: required.paymentHash,
|
|
}
|
|
}
|
|
|
|
function hasRequiredReviewTipFields(values: {
|
|
payerPubkey: string | undefined
|
|
reviewerPubkey: string | undefined
|
|
authorPubkey: string | undefined
|
|
articleId: string | undefined
|
|
reviewId: string | undefined
|
|
paymentHash: string | undefined
|
|
}): values is {
|
|
payerPubkey: string
|
|
reviewerPubkey: string
|
|
authorPubkey: string
|
|
articleId: string
|
|
reviewId: string
|
|
paymentHash: string
|
|
} {
|
|
const requiredKeys: ReadonlyArray<keyof typeof values> = [
|
|
'payerPubkey',
|
|
'reviewerPubkey',
|
|
'authorPubkey',
|
|
'articleId',
|
|
'reviewId',
|
|
'paymentHash',
|
|
]
|
|
return requiredKeys.every((key) => isNonEmptyString(values[key]))
|
|
}
|
|
|
|
function isNonEmptyString(value: unknown): value is string {
|
|
return typeof value === 'string' && value.length > 0
|
|
}
|