Files
SingBox-Gopanel/internal/service/device_state.go
CN-JS-HuiBai 1ed31b9292
All checks were successful
build / build (api, amd64, linux) (push) Successful in -47s
build / build (api, arm64, linux) (push) Successful in -48s
build / build (api.exe, amd64, windows) (push) Successful in -47s
first commit
2026-04-17 09:49:16 +08:00

98 lines
2.2 KiB
Go

package service
import (
"fmt"
"sort"
"strings"
"time"
"xboard-go/internal/database"
)
const deviceStateTTL = 10 * time.Minute
type userDevicesSnapshot map[string][]string
func SaveUserNodeDevices(userID, nodeID int, ips []string) error {
unique := make([]string, 0, len(ips))
seen := make(map[string]struct{})
for _, ip := range ips {
trimmed := strings.TrimSpace(ip)
if trimmed == "" {
continue
}
if _, ok := seen[trimmed]; ok {
continue
}
seen[trimmed] = struct{}{}
unique = append(unique, trimmed)
}
sort.Strings(unique)
return database.CacheSet(deviceStateKey(userID, nodeID), unique, deviceStateTTL)
}
func GetUsersDevices(userIDs []int) map[int][]string {
result := make(map[int][]string, len(userIDs))
for _, userID := range userIDs {
snapshot, ok := database.CacheGetJSON[userDevicesSnapshot](deviceStateUserIndexKey(userID))
if !ok {
result[userID] = []string{}
continue
}
merged := make([]string, 0)
seen := make(map[string]struct{})
for _, ips := range snapshot {
for _, ip := range ips {
if _, exists := seen[ip]; exists {
continue
}
seen[ip] = struct{}{}
merged = append(merged, ip)
}
}
sort.Strings(merged)
result[userID] = merged
}
return result
}
func SetDevices(userID, nodeID int, ips []string) error {
if err := SaveUserNodeDevices(userID, nodeID, ips); err != nil {
return err
}
indexKey := deviceStateUserIndexKey(userID)
indexSnapshot, _ := database.CacheGetJSON[userDevicesSnapshot](indexKey)
indexSnapshot[fmt.Sprintf("%d", nodeID)] = normalizeIPs(ips)
return database.CacheSet(indexKey, indexSnapshot, deviceStateTTL)
}
func normalizeIPs(ips []string) []string {
seen := make(map[string]struct{})
result := make([]string, 0, len(ips))
for _, ip := range ips {
ip = strings.TrimSpace(ip)
if ip == "" {
continue
}
if _, ok := seen[ip]; ok {
continue
}
seen[ip] = struct{}{}
result = append(result, ip)
}
sort.Strings(result)
return result
}
func deviceStateKey(userID, nodeID int) string {
return fmt.Sprintf("device_state:user:%d:node:%d", userID, nodeID)
}
func deviceStateUserIndexKey(userID int) string {
return fmt.Sprintf("device_state:user:%d:index", userID)
}