package payments import ( "context" "log/slog" "strconv" "time" "github.com/noderunners/nip05api/internal/audit" "github.com/noderunners/nip05api/internal/dm" "github.com/noderunners/nip05api/internal/invoice" "github.com/noderunners/nip05api/internal/nostr" "github.com/noderunners/nip05api/internal/user" "github.com/noderunners/nip05api/internal/webhook" ) func (w *Worker) dispatchEvents(ctx context.Context, u *user.User, p *invoice.PendingInvoice, ev dm.EventType) { vars := buildVars(u, w.domain, w.frontend) if err := w.dms.Send(ctx, ev, u.Pubkey, vars); err != nil { slog.Error("dm enqueue", "err", err) } data := map[string]any{ "pubkey": u.Pubkey, "npub": nostr.HexToNpub(u.Pubkey), "username": u.Username, "subscription_type": string(u.SubscriptionType), "amount_sats": p.AmountSats, "payment_hash": p.PaymentHash, "is_renewal": p.IsRenewal, } if u.ExpiresAt != nil { data["expires_at"] = u.ExpiresAt.UTC().Format(time.RFC3339) } if err := w.hooks.Enqueue(ctx, webhook.EventUserPaid, data); err != nil { slog.Error("webhook enqueue", "err", err) } w.audit.Log(ctx, audit.ActionPaymentConfirmed, audit.ActorSystem, u.Pubkey, map[string]any{ "payment_hash": p.PaymentHash, "amount_sats": p.AmountSats, "is_renewal": p.IsRenewal, "event": string(ev), }) slog.Info("payment confirmed", "pubkey", u.Pubkey, "username", u.Username, "amount_sats", p.AmountSats, "renewal", p.IsRenewal) } func buildVars(u *user.User, domain, frontend string) map[string]string { expires := "lifetime" days := "" if u.ExpiresAt != nil { expires = u.ExpiresAt.Format("2006-01-02") d := int(time.Until(*u.ExpiresAt).Hours() / 24) if d < 0 { d = 0 } days = strconv.Itoa(d) } return map[string]string{ "username": u.Username, "npub": nostr.HexToNpub(u.Pubkey), "pubkey": u.Pubkey, "domain": domain, "expires_at": expires, "days_remaining": days, "frontend_url": frontend, "subscription_type": string(u.SubscriptionType), } }