package handler import ( "net/http" "time" "goflare/internal/database/queries" "goflare/internal/ipfetcher" "github.com/labstack/echo/v4" ) type IPHandler struct { q *queries.Queries } func NewIPHandler(q *queries.Queries) *IPHandler { return &IPHandler{q: q} } const ( settingKeyCurrentIP = "current_ip" settingKeyCurrentIPUpdatedAt = "current_ip_updated_at" settingKeyCurrentIPSource = "current_ip_source" ) func (h *IPHandler) Get(c echo.Context) error { ctx := c.Request().Context() cached, err := h.q.GetSetting(ctx, settingKeyCurrentIP) if err == nil && cached != "" { resp := map[string]string{"ip": cached} if updatedAt, err := h.q.GetSetting(ctx, settingKeyCurrentIPUpdatedAt); err == nil && updatedAt != "" { resp["ip_updated_at"] = updatedAt } if source, err := h.q.GetSetting(ctx, settingKeyCurrentIPSource); err == nil && source != "" { resp["ip_source"] = source } return c.JSON(http.StatusOK, resp) } urls, err := h.q.ListEnabledIpProviderUrls(ctx) if err != nil { return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to load IP providers"}) } var urlsOrNil []string if len(urls) > 0 { urlsOrNil = urls } res, err := ipfetcher.FetchPublicIPFrom(ctx, urlsOrNil) if err != nil { return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to fetch public IP"}) } now := time.Now().UTC().Format(time.RFC3339) _ = h.q.UpsertSetting(ctx, queries.UpsertSettingParams{Key: settingKeyCurrentIP, Value: res.IP}) _ = h.q.UpsertSetting(ctx, queries.UpsertSettingParams{Key: settingKeyCurrentIPUpdatedAt, Value: now}) _ = h.q.UpsertSetting(ctx, queries.UpsertSettingParams{Key: settingKeyCurrentIPSource, Value: res.Source}) resp := map[string]string{"ip": res.IP, "ip_updated_at": now, "ip_source": res.Source} return c.JSON(http.StatusOK, resp) }