mirror of
https://github.com/sstent/garminsync-go.git
synced 2025-12-06 08:01:52 +00:00
working build - no ui
This commit is contained in:
BIN
garminsync
Executable file
BIN
garminsync
Executable file
Binary file not shown.
@@ -20,15 +20,15 @@ func NewSQLiteDB(dbPath string) (*SQLiteDB, error) {
|
|||||||
|
|
||||||
sqlite := &SQLiteDB{db: db}
|
sqlite := &SQLiteDB{db: db}
|
||||||
|
|
||||||
// Create tables
|
// Create tables
|
||||||
if err := sqlite.createTables(); err != nil {
|
if err := sqlite.CreateTables(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return sqlite, nil
|
return sqlite, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SQLiteDB) createTables() error {
|
func (s *SQLiteDB) CreateTables() error {
|
||||||
schema := `
|
schema := `
|
||||||
CREATE TABLE IF NOT EXISTS activities (
|
CREATE TABLE IF NOT EXISTS activities (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
@@ -134,6 +134,10 @@ func (s *SQLiteDB) ActivityExists(activityID int) (bool, error) {
|
|||||||
return count > 0, nil
|
return count > 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SQLiteDB) DB() *sql.DB {
|
||||||
|
return s.db
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SQLiteDB) GetActivity(activityID int) (*Activity, error) {
|
func (s *SQLiteDB) GetActivity(activityID int) (*Activity, error) {
|
||||||
query := `
|
query := `
|
||||||
SELECT id, activity_id, start_time, activity_type, duration, distance,
|
SELECT id, activity_id, start_time, activity_type, duration, distance,
|
||||||
|
|||||||
@@ -156,15 +156,20 @@ func (c *Client) GetActivities(start, limit int) ([]GarminActivity, error) {
|
|||||||
return nil, fmt.Errorf("failed to get activities: status %d", resp.StatusCode)
|
return nil, fmt.Errorf("failed to get activities: status %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
var activities []GarminActivity
|
// Garmin API returns an object containing the activity list
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&activities); err != nil {
|
type responseStruct struct {
|
||||||
|
ActivityList []GarminActivity `json:"activityList"`
|
||||||
|
}
|
||||||
|
var response responseStruct
|
||||||
|
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rate limiting
|
// Rate limiting
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
return activities, nil
|
return response.ActivityList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) DownloadActivity(activityID int, format string) ([]byte, error) {
|
func (c *Client) DownloadActivity(activityID int, format string) ([]byte, error) {
|
||||||
|
|||||||
@@ -12,21 +12,21 @@ import (
|
|||||||
"github.com/sstent/garminsync-go/internal/parser"
|
"github.com/sstent/garminsync-go/internal/parser"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Syncer struct {
|
type SyncService struct {
|
||||||
garminClient *garmin.Client
|
garminClient *garmin.Client
|
||||||
db *database.SQLiteDB
|
db *database.SQLiteDB
|
||||||
dataDir string
|
dataDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSyncer(garminClient *garmin.Client, db *database.SQLiteDB, dataDir string) *Syncer {
|
func NewSyncService(garminClient *garmin.Client, db *database.SQLiteDB, dataDir string) *SyncService {
|
||||||
return &Syncer{
|
return &SyncService{
|
||||||
garminClient: garminClient,
|
garminClient: garminClient,
|
||||||
db: db,
|
db: db,
|
||||||
dataDir: dataDir,
|
dataDir: dataDir,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Syncer) FullSync(ctx context.Context) error {
|
func (s *SyncService) FullSync(ctx context.Context) error {
|
||||||
fmt.Println("Starting full sync...")
|
fmt.Println("Starting full sync...")
|
||||||
defer fmt.Println("Sync completed")
|
defer fmt.Println("Sync completed")
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ func (s *Syncer) FullSync(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Syncer) syncActivity(activity *garmin.GarminActivity) error {
|
func (s *SyncService) syncActivity(activity *garmin.GarminActivity) error {
|
||||||
// Skip if already downloaded
|
// Skip if already downloaded
|
||||||
if exists, _ := s.db.ActivityExists(activity.ActivityID); exists {
|
if exists, _ := s.db.ActivityExists(activity.ActivityID); exists {
|
||||||
return nil
|
return nil
|
||||||
@@ -111,6 +111,11 @@ func (s *Syncer) syncActivity(activity *garmin.GarminActivity) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add missing Sync method
|
||||||
|
func (s *SyncService) Sync(ctx context.Context) error {
|
||||||
|
return s.FullSync(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func getActivityType(activity *garmin.GarminActivity) string {
|
func getActivityType(activity *garmin.GarminActivity) string {
|
||||||
if activityType, ok := activity.ActivityType["typeKey"]; ok {
|
if activityType, ok := activity.ActivityType["typeKey"]; ok {
|
||||||
return activityType.(string)
|
return activityType.(string)
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ import (
|
|||||||
|
|
||||||
type WebHandler struct {
|
type WebHandler struct {
|
||||||
db *database.SQLiteDB
|
db *database.SQLiteDB
|
||||||
syncer *sync.Syncer
|
syncer *sync.SyncService
|
||||||
garmin *garmin.Client
|
garmin *garmin.Client
|
||||||
templates map[string]interface{} // Placeholder for template handling
|
templates map[string]interface{} // Placeholder for template handling
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWebHandler(db *database.SQLiteDB, syncer *sync.Syncer, garmin *garmin.Client) *WebHandler {
|
func NewWebHandler(db *database.SQLiteDB, syncer *sync.SyncService, garmin *garmin.Client) *WebHandler {
|
||||||
return &WebHandler{
|
return &WebHandler{
|
||||||
db: db,
|
db: db,
|
||||||
syncer: syncer,
|
syncer: syncer,
|
||||||
@@ -27,6 +27,11 @@ func NewWebHandler(db *database.SQLiteDB, syncer *sync.Syncer, garmin *garmin.Cl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *WebHandler) LoadTemplates(templateDir string) error {
|
||||||
|
// For now, just return nil - templates will be handled later
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (h *WebHandler) RegisterRoutes(router *gin.Engine) {
|
func (h *WebHandler) RegisterRoutes(router *gin.Engine) {
|
||||||
router.GET("/", h.Index)
|
router.GET("/", h.Index)
|
||||||
router.GET("/activities", h.ActivityList)
|
router.GET("/activities", h.ActivityList)
|
||||||
@@ -79,7 +84,7 @@ func (h *WebHandler) ActivityDetail(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *WebHandler) Sync(c *gin.Context) {
|
func (h *WebHandler) Sync(c *gin.Context) {
|
||||||
err := h.syncer.FullSync(context.Background())
|
err := h.syncer.Sync(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithStatus(http.StatusInternalServerError)
|
c.AbortWithStatus(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|||||||
36
main.go
36
main.go
@@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/sstent/garminsync-go/internal/web"
|
"github.com/sstent/garminsync-go/internal/web"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/robfig/cron/v3"
|
"github.com/robfig/cron/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ type App struct {
|
|||||||
server *http.Server
|
server *http.Server
|
||||||
garmin *garmin.Client
|
garmin *garmin.Client
|
||||||
shutdown chan os.Signal
|
shutdown chan os.Signal
|
||||||
syncService *sync.SyncService
|
syncService *sync.SyncService // This should now work
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -63,11 +64,10 @@ func (app *App) init() error {
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
// Initialize database
|
// Initialize database
|
||||||
dbConn, err := initDatabase()
|
app.db, err = initDatabase()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
app.db = database.NewSQLiteDBFromDB(dbConn)
|
|
||||||
|
|
||||||
// Initialize Garmin client
|
// Initialize Garmin client
|
||||||
app.garmin = garmin.NewClient()
|
app.garmin = garmin.NewClient()
|
||||||
@@ -77,13 +77,13 @@ func (app *App) init() error {
|
|||||||
if dataDir == "" {
|
if dataDir == "" {
|
||||||
dataDir = "./data"
|
dataDir = "./data"
|
||||||
}
|
}
|
||||||
app.syncService = sync.NewSyncService(app.garmin, database.NewSQLiteDBFromDB(app.db), dataDir)
|
app.syncService = sync.NewSyncService(app.garmin, app.db, dataDir)
|
||||||
|
|
||||||
// Setup cron scheduler
|
// Setup cron scheduler
|
||||||
app.cron = cron.New()
|
app.cron = cron.New()
|
||||||
|
|
||||||
// Setup HTTP server
|
// Setup HTTP server
|
||||||
webHandler := web.NewWebHandler(app.db)
|
webHandler := web.NewWebHandler(app.db, app.syncService, app.garmin)
|
||||||
templateDir := os.Getenv("TEMPLATE_DIR")
|
templateDir := os.Getenv("TEMPLATE_DIR")
|
||||||
if templateDir == "" {
|
if templateDir == "" {
|
||||||
templateDir = "./internal/web/templates"
|
templateDir = "./internal/web/templates"
|
||||||
@@ -142,7 +142,7 @@ func (app *App) stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Database initialization
|
// Database initialization
|
||||||
func initDatabase() (*sql.DB, error) {
|
func initDatabase() (*database.SQLiteDB, error) {
|
||||||
// Get database path from environment or use default
|
// Get database path from environment or use default
|
||||||
dbPath := os.Getenv("DB_PATH")
|
dbPath := os.Getenv("DB_PATH")
|
||||||
if dbPath == "" {
|
if dbPath == "" {
|
||||||
@@ -172,28 +172,24 @@ func initDatabase() (*sql.DB, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create tables if they don't exist
|
// Create tables if they don't exist
|
||||||
sqliteDB := &database.SQLiteDB{db: db}
|
sqliteDB := database.NewSQLiteDBFromDB(db)
|
||||||
if err := sqliteDB.createTables(); err != nil {
|
if err := sqliteDB.CreateTables(); err != nil {
|
||||||
return nil, fmt.Errorf("failed to create tables: %v", err)
|
return nil, fmt.Errorf("failed to create tables: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return db, nil
|
return sqliteDB, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Application routes
|
func (app *App) setupRoutes(webHandler *web.WebHandler) http.Handler {
|
||||||
func (app *App) setupRoutes(webHandler *web.WebHandler) *http.ServeMux {
|
router := gin.Default()
|
||||||
mux := http.NewServeMux()
|
|
||||||
|
|
||||||
// Health check
|
// Health check
|
||||||
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
|
router.GET("/health", func(c *gin.Context) {
|
||||||
w.WriteHeader(http.StatusOK)
|
c.String(http.StatusOK, "OK")
|
||||||
w.Write([]byte("OK"))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Web UI routes
|
// Register web routes
|
||||||
mux.HandleFunc("/", webHandler.Index)
|
webHandler.RegisterRoutes(router)
|
||||||
mux.HandleFunc("/activities", webHandler.ActivityList)
|
|
||||||
mux.HandleFunc("/activity", webHandler.ActivityDetail)
|
|
||||||
|
|
||||||
return mux
|
return router
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user