1
0

external_hwid.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. package service
  2. import (
  3. "strings"
  4. "sync"
  5. "github.com/google/uuid"
  6. "github.com/mhsanaei/3x-ui/v3/internal/database"
  7. "github.com/mhsanaei/3x-ui/v3/internal/database/model"
  8. "github.com/mhsanaei/3x-ui/v3/internal/logger"
  9. )
  10. const externalSubHwidKey = "externalSubHwid"
  11. // externalSubHwidMu serializes first-time creation: without it, concurrent first
  12. // fetches each mint and persist their own id.
  13. var externalSubHwidMu sync.Mutex
  14. // ExternalSubscriptionHwid is the X-HWID every subscription fetch sends, so an
  15. // HWID-limited provider counts this panel as one device. Empty: DB unreachable.
  16. func ExternalSubscriptionHwid() string {
  17. externalSubHwidMu.Lock()
  18. defer externalSubHwidMu.Unlock()
  19. db := database.GetDB()
  20. if db == nil {
  21. return ""
  22. }
  23. var row model.Setting
  24. if err := db.Where("key = ?", externalSubHwidKey).First(&row).Error; err == nil {
  25. if strings.TrimSpace(row.Value) != "" {
  26. return strings.TrimSpace(row.Value)
  27. }
  28. }
  29. hwid := "3x-ui-server-" + uuid.NewString()
  30. row = model.Setting{Key: externalSubHwidKey, Value: hwid}
  31. if err := db.Where(model.Setting{Key: externalSubHwidKey}).FirstOrCreate(&row).Error; err != nil {
  32. logger.Warningf("persisting the external subscription hwid failed: %v", err)
  33. return ""
  34. }
  35. if strings.TrimSpace(row.Value) == "" {
  36. return hwid
  37. }
  38. return strings.TrimSpace(row.Value)
  39. }