package handlers import ( "errors" "net/http" "time" "github.com/go-chi/chi/v5" "github.com/noderunners/nip05api/internal/nostr" "github.com/noderunners/nip05api/internal/user" ) type Users struct { Users *user.Service GraceDays int } func (h *Users) Get(w http.ResponseWriter, r *http.Request) { hexpk, err := nostr.NormalizePubkey(chi.URLParam(r, "pubkey")) if err != nil { WriteError(w, http.StatusBadRequest, "ValidationError", "Invalid pubkey format") return } u, err := h.Users.Repo().GetByPubkey(r.Context(), hexpk) if errors.Is(err, user.ErrUserNotFound) { WriteError(w, http.StatusNotFound, "NotFound", "user not registered") return } if err != nil { WriteError(w, http.StatusInternalServerError, "InternalError", err.Error()) return } resp := map[string]any{ "pubkey": u.Pubkey, "npub": nostr.HexToNpub(u.Pubkey), } if u.IsActive { resp["is_whitelisted"] = true resp["username"] = u.Username if u.ExpiresAt != nil { resp["expires_at"] = u.ExpiresAt.UTC().Format(time.RFC3339) } else { resp["expires_at"] = nil } resp["subscription_type"] = string(u.SubscriptionType) } else { resp["is_whitelisted"] = false if u.ExpiresAt != nil { resp["expired_at"] = u.ExpiresAt.UTC().Format(time.RFC3339) } if u.DeactivatedAt != nil { cutoff := u.DeactivatedAt.Add(time.Duration(h.GraceDays) * 24 * time.Hour) if time.Now().UTC().Before(cutoff) { resp["in_grace"] = true resp["reserved_username"] = u.Username } else { resp["in_grace"] = false } } } WriteJSON(w, http.StatusOK, resp) }