ip.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. package handler
  2. import (
  3. "net/http"
  4. "time"
  5. "goflare/internal/database/queries"
  6. "goflare/internal/ipfetcher"
  7. "github.com/labstack/echo/v4"
  8. )
  9. type IPHandler struct {
  10. q *queries.Queries
  11. }
  12. func NewIPHandler(q *queries.Queries) *IPHandler {
  13. return &IPHandler{q: q}
  14. }
  15. const (
  16. settingKeyCurrentIP = "current_ip"
  17. settingKeyCurrentIPUpdatedAt = "current_ip_updated_at"
  18. settingKeyCurrentIPSource = "current_ip_source"
  19. )
  20. func (h *IPHandler) Get(c echo.Context) error {
  21. ctx := c.Request().Context()
  22. cached, err := h.q.GetSetting(ctx, settingKeyCurrentIP)
  23. if err == nil && cached != "" {
  24. resp := map[string]string{"ip": cached}
  25. if updatedAt, err := h.q.GetSetting(ctx, settingKeyCurrentIPUpdatedAt); err == nil && updatedAt != "" {
  26. resp["ip_updated_at"] = updatedAt
  27. }
  28. if source, err := h.q.GetSetting(ctx, settingKeyCurrentIPSource); err == nil && source != "" {
  29. resp["ip_source"] = source
  30. }
  31. return c.JSON(http.StatusOK, resp)
  32. }
  33. urls, err := h.q.ListEnabledIpProviderUrls(ctx)
  34. if err != nil {
  35. return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to load IP providers"})
  36. }
  37. var urlsOrNil []string
  38. if len(urls) > 0 {
  39. urlsOrNil = urls
  40. }
  41. res, err := ipfetcher.FetchPublicIPFrom(ctx, urlsOrNil)
  42. if err != nil {
  43. return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to fetch public IP"})
  44. }
  45. now := time.Now().UTC().Format(time.RFC3339)
  46. _ = h.q.UpsertSetting(ctx, queries.UpsertSettingParams{Key: settingKeyCurrentIP, Value: res.IP})
  47. _ = h.q.UpsertSetting(ctx, queries.UpsertSettingParams{Key: settingKeyCurrentIPUpdatedAt, Value: now})
  48. _ = h.q.UpsertSetting(ctx, queries.UpsertSettingParams{Key: settingKeyCurrentIPSource, Value: res.Source})
  49. resp := map[string]string{"ip": res.IP, "ip_updated_at": now, "ip_source": res.Source}
  50. return c.JSON(http.StatusOK, resp)
  51. }