feat: auto-detect zap payments, show zapper profiles, fix algorithm

- ZapModal now polls LNURL verify URL for automatic payment detection
  instead of requiring manual "Done" click
- Added lightning bolt celebration animation on zap success with
  random fun quotes
- Show "Zapped by" section on film detail modal with profile pics,
  amounts, and avatar pills (like Primal/Yakihonne)
- useNostr now subscribes to kind 9735 zap receipts per content,
  parses sender pubkey from embedded zap request, and fetches profiles
- Fixed most-zapped algorithm to also parse the description tag in
  zap receipts for content matching (NIP-57 embedded zap requests)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Dorian
2026-02-14 12:42:57 +00:00
parent 92182ca2ad
commit e774d20821
4 changed files with 372 additions and 33 deletions

View File

@@ -129,13 +129,29 @@ function rebuildStats() {
}
// Process zap receipts (kind 9735) from the EventStore.
// Zap receipts reference content via the 'i' tag (external identifiers)
// or via embedded zap request description.
// Zap receipts reference content via:
// 1. Direct 'i' tag on the receipt itself
// 2. 'i' tag embedded in the zap request JSON (description tag)
const zapReceipts = eventStore.getByFilters([{ kinds: [9735] }])
if (zapReceipts) {
for (const event of zapReceipts) {
// Try to find the external content ID from the zap receipt tags
const externalId = getTagValue(event, 'i')
// Try direct 'i' tag first
let externalId = getTagValue(event, 'i')
// Fallback: parse the embedded zap request from the description tag
if (!externalId) {
const descTag = event.tags.find((t) => t[0] === 'description')?.[1]
if (descTag) {
try {
const zapRequest = JSON.parse(descTag)
if (zapRequest.tags) {
const iTag = zapRequest.tags.find((t: string[]) => t[0] === 'i')
if (iTag) externalId = iTag[1]
}
} catch { /* not valid JSON */ }
}
}
if (!externalId) continue
const stats = getOrCreate(externalId)