use antigravity to rewrite all your code to migrate from flat files to relational database. YOLO
All checks were successful
pedestrian-simulator / build (push) Successful in 58s
All checks were successful
pedestrian-simulator / build (push) Successful in 58s
This commit is contained in:
106
server/user.go
106
server/user.go
@@ -1,11 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -16,104 +16,38 @@ type User struct {
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type UserRegistry struct {
|
||||
Users map[string]*User `json:"users"` // Map of FitbitUserID -> User
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
var userRegistry *UserRegistry
|
||||
|
||||
// InitUserRegistry loads or creates the user registry
|
||||
func InitUserRegistry() {
|
||||
userRegistry = &UserRegistry{
|
||||
Users: make(map[string]*User),
|
||||
}
|
||||
userRegistry.Load()
|
||||
}
|
||||
|
||||
// Load reads the user registry from disk
|
||||
func (ur *UserRegistry) Load() error {
|
||||
ur.mu.Lock()
|
||||
defer ur.mu.Unlock()
|
||||
|
||||
data, err := os.ReadFile("data/users.json")
|
||||
// GetUser retrieves a user by Fitbit user ID from the database
|
||||
func GetUser(fitbitUserID string) (*User, error) {
|
||||
var user User
|
||||
err := db.QueryRow("SELECT fitbit_user_id, display_name, avatar_url, created_at FROM users WHERE fitbit_user_id = ?", fitbitUserID).
|
||||
Scan(&user.FitbitUserID, &user.DisplayName, &user.AvatarURL, &user.CreatedAt)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil // First run, no users yet
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Unmarshal(data, ur)
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// Save writes the user registry to disk
|
||||
func (ur *UserRegistry) Save() error {
|
||||
ur.mu.RLock()
|
||||
defer ur.mu.RUnlock()
|
||||
return ur.saveUnlocked()
|
||||
}
|
||||
|
||||
// saveUnlocked writes the user registry to disk without locking (caller must hold lock)
|
||||
func (ur *UserRegistry) saveUnlocked() error {
|
||||
if err := os.MkdirAll("data", 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(ur, "", " ")
|
||||
// CreateOrUpdateUser adds or updates a user in the database
|
||||
func CreateOrUpdateUser(fitbitUserID, displayName, avatarURL string) (*User, error) {
|
||||
_, err := db.Exec(`
|
||||
INSERT INTO users (fitbit_user_id, display_name, avatar_url, created_at)
|
||||
VALUES (?, ?, ?, NOW())
|
||||
ON DUPLICATE KEY UPDATE display_name = ?, avatar_url = ?
|
||||
`, fitbitUserID, displayName, avatarURL, displayName, avatarURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile("data/users.json", data, 0644)
|
||||
}
|
||||
|
||||
// GetUser retrieves a user by Fitbit user ID
|
||||
func (ur *UserRegistry) GetUser(fitbitUserID string) (*User, bool) {
|
||||
ur.mu.RLock()
|
||||
defer ur.mu.RUnlock()
|
||||
|
||||
user, exists := ur.Users[fitbitUserID]
|
||||
return user, exists
|
||||
}
|
||||
|
||||
// CreateOrUpdateUser adds or updates a user in the registry
|
||||
func (ur *UserRegistry) CreateOrUpdateUser(fitbitUserID, displayName, avatarURL string) (*User, error) {
|
||||
ur.mu.Lock()
|
||||
defer ur.mu.Unlock()
|
||||
|
||||
user, exists := ur.Users[fitbitUserID]
|
||||
if exists {
|
||||
// Update existing user
|
||||
user.DisplayName = displayName
|
||||
user.AvatarURL = avatarURL
|
||||
} else {
|
||||
// Create new user
|
||||
user = &User{
|
||||
FitbitUserID: fitbitUserID,
|
||||
DisplayName: displayName,
|
||||
AvatarURL: avatarURL,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
ur.Users[fitbitUserID] = user
|
||||
}
|
||||
|
||||
// Save without locking (we already have the lock)
|
||||
if err := ur.saveUnlocked(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create user directory
|
||||
userDir := fmt.Sprintf("data/users/%s", fitbitUserID)
|
||||
// Create user directory for KML files
|
||||
userDir := fmt.Sprintf("data/users/%s/kml", fitbitUserID)
|
||||
if err := os.MkdirAll(userDir, 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kmlDir := fmt.Sprintf("data/users/%s/kml", fitbitUserID)
|
||||
if err := os.MkdirAll(kmlDir, 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
return GetUser(fitbitUserID)
|
||||
}
|
||||
|
||||
// FetchFitbitUserProfile fetches the user's profile from Fitbit API
|
||||
|
||||
Reference in New Issue
Block a user