mirror of
https://github.com/sstent/go-garth-cli.git
synced 2025-12-05 23:52:02 +00:00
184 lines
4.9 KiB
Go
184 lines
4.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"golang.org/x/term"
|
|
|
|
"go-garth/pkg/garmin"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var (
|
|
authCmd = &cobra.Command{
|
|
Use: "auth",
|
|
Short: "Authentication management",
|
|
Long: `Manage authentication with Garmin Connect, including login, logout, and status.`,
|
|
}
|
|
|
|
loginCmd = &cobra.Command{
|
|
Use: "login",
|
|
Short: "Login to Garmin Connect",
|
|
Long: `Login to Garmin Connect interactively or using provided credentials.`,
|
|
RunE: runLogin,
|
|
}
|
|
|
|
logoutCmd = &cobra.Command{
|
|
Use: "logout",
|
|
Short: "Logout from Garmin Connect",
|
|
Long: `Clear the current Garmin Connect session.`,
|
|
RunE: runLogout,
|
|
}
|
|
|
|
statusCmd = &cobra.Command{
|
|
Use: "status",
|
|
Short: "Show Garmin Connect authentication status",
|
|
Long: `Display the current authentication status and session information.`,
|
|
RunE: runStatus,
|
|
}
|
|
|
|
refreshCmd = &cobra.Command{
|
|
Use: "refresh",
|
|
Short: "Refresh Garmin Connect session tokens",
|
|
Long: `Refresh the authentication tokens for the current Garmin Connect session.`,
|
|
RunE: runRefresh,
|
|
}
|
|
|
|
loginEmail string
|
|
loginPassword string
|
|
passwordStdinFlag bool
|
|
)
|
|
|
|
func init() {
|
|
rootCmd.AddCommand(authCmd)
|
|
|
|
authCmd.AddCommand(loginCmd)
|
|
loginCmd.Flags().StringVarP(&loginEmail, "email", "e", "", "Email for Garmin Connect login")
|
|
loginCmd.Flags().BoolVarP(&passwordStdinFlag, "password-stdin", "p", false, "Read password from stdin")
|
|
|
|
authCmd.AddCommand(logoutCmd)
|
|
authCmd.AddCommand(statusCmd)
|
|
authCmd.AddCommand(refreshCmd)
|
|
}
|
|
|
|
func runLogin(cmd *cobra.Command, args []string) error {
|
|
var email, password string
|
|
var err error
|
|
|
|
if loginEmail != "" {
|
|
email = loginEmail
|
|
} else {
|
|
fmt.Print("Enter Garmin Connect email: ")
|
|
_, err = fmt.Scanln(&email)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read email: %w", err)
|
|
}
|
|
}
|
|
|
|
if passwordStdinFlag {
|
|
fmt.Print("Enter password: ")
|
|
passwordBytes, err := term.ReadPassword(int(os.Stdin.Fd()))
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read password from stdin: %w", err)
|
|
}
|
|
password = string(passwordBytes)
|
|
fmt.Println() // Newline after password input
|
|
} else {
|
|
fmt.Print("Enter password: ")
|
|
passwordBytes, err := term.ReadPassword(int(os.Stdin.Fd()))
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read password: %w", err)
|
|
}
|
|
password = string(passwordBytes)
|
|
fmt.Println() // Newline after password input
|
|
}
|
|
|
|
// Create client
|
|
// TODO: Domain should be configurable
|
|
garminClient, err := garmin.NewClient("www.garmin.com")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create client: %w", err)
|
|
}
|
|
|
|
// Try to load existing session first
|
|
sessionFile := "garmin_session.json" // TODO: Make session file configurable
|
|
if err := garminClient.LoadSession(sessionFile); err != nil {
|
|
fmt.Println("No existing session found or session invalid, logging in with credentials...")
|
|
|
|
if err := garminClient.Login(email, password); err != nil {
|
|
return fmt.Errorf("login failed: %w", err)
|
|
}
|
|
|
|
// Save session for future use
|
|
if err := garminClient.SaveSession(sessionFile); err != nil {
|
|
fmt.Printf("Failed to save session: %v\n", err)
|
|
}
|
|
} else {
|
|
fmt.Println("Loaded existing session")
|
|
}
|
|
|
|
fmt.Println("Login successful!")
|
|
return nil
|
|
}
|
|
|
|
func runLogout(cmd *cobra.Command, args []string) error {
|
|
sessionFile := "garmin_session.json" // TODO: Make session file configurable
|
|
|
|
if _, err := os.Stat(sessionFile); os.IsNotExist(err) {
|
|
fmt.Println("No active session to log out from.")
|
|
return nil
|
|
}
|
|
|
|
if err := os.Remove(sessionFile); err != nil {
|
|
return fmt.Errorf("failed to remove session file: %w", err)
|
|
}
|
|
|
|
fmt.Println("Logged out successfully. Session cleared.")
|
|
return nil
|
|
}
|
|
|
|
func runStatus(cmd *cobra.Command, args []string) error {
|
|
sessionFile := "garmin_session.json" // TODO: Make session file configurable
|
|
|
|
garminClient, err := garmin.NewClient("www.garmin.com") // TODO: Domain should be configurable
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create client: %w", err)
|
|
}
|
|
|
|
if err := garminClient.LoadSession(sessionFile); err != nil {
|
|
fmt.Println("Not logged in or session expired.")
|
|
return nil
|
|
}
|
|
|
|
fmt.Println("Logged in. Session is active.")
|
|
// TODO: Add more detailed status information, e.g., session expiry
|
|
return nil
|
|
}
|
|
|
|
func runRefresh(cmd *cobra.Command, args []string) error {
|
|
sessionFile := "garmin_session.json" // TODO: Make session file configurable
|
|
|
|
garminClient, err := garmin.NewClient("www.garmin.com") // TODO: Domain should be configurable
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create client: %w", err)
|
|
}
|
|
|
|
if err := garminClient.LoadSession(sessionFile); err != nil {
|
|
return fmt.Errorf("cannot refresh: no active session found: %w", err)
|
|
}
|
|
|
|
fmt.Println("Attempting to refresh session...")
|
|
if err := garminClient.RefreshSession(); err != nil {
|
|
return fmt.Errorf("failed to refresh session: %w", err)
|
|
}
|
|
|
|
if err := garminClient.SaveSession(sessionFile); err != nil {
|
|
fmt.Printf("Failed to save refreshed session: %v\n", err)
|
|
}
|
|
|
|
fmt.Println("Session refreshed successfully.")
|
|
return nil
|
|
}
|