All checks were successful
pedestrian-simulator / build (push) Successful in 58s
91 lines
2.4 KiB
Go
91 lines
2.4 KiB
Go
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
type User struct {
|
|
FitbitUserID string `json:"fitbit_user_id"`
|
|
DisplayName string `json:"display_name"`
|
|
AvatarURL string `json:"avatar_url"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
// 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 err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
return &user, nil
|
|
}
|
|
|
|
// 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 nil, err
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
return GetUser(fitbitUserID)
|
|
}
|
|
|
|
// FetchFitbitUserProfile fetches the user's profile from Fitbit API
|
|
func FetchFitbitUserProfile(accessToken string) (userID, displayName, avatarURL string, err error) {
|
|
apiURL := "https://api.fitbit.com/1/user/-/profile.json"
|
|
|
|
req, _ := http.NewRequest("GET", apiURL, nil)
|
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
|
|
|
client := &http.Client{Timeout: 10 * time.Second}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return "", "", "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != 200 {
|
|
return "", "", "", fmt.Errorf("fitbit profile api error: %s", resp.Status)
|
|
}
|
|
|
|
var result struct {
|
|
User struct {
|
|
EncodedID string `json:"encodedId"`
|
|
DisplayName string `json:"displayName"`
|
|
Avatar string `json:"avatar"`
|
|
Avatar150 string `json:"avatar150"`
|
|
} `json:"user"`
|
|
}
|
|
|
|
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
|
return "", "", "", err
|
|
}
|
|
|
|
avatar := result.User.Avatar150
|
|
if avatar == "" {
|
|
avatar = result.User.Avatar
|
|
}
|
|
|
|
return result.User.EncodedID, result.User.DisplayName, avatar, nil
|
|
}
|