#!/usr/bin/env python3 """ Script to mimic the web UI call when hitting "Save Garmin Credentials". This script loads Garmin credentials from a .env file and sends them to the backend API. """ import os import requests import json from dotenv import load_dotenv import sys # Load environment variables from .env file load_dotenv() def save_garmin_credentials(): # Get credentials from environment variables garmin_username = os.getenv('GARMIN_USERNAME') garmin_password = os.getenv('GARMIN_PASSWORD') garmin_is_china = os.getenv('GARMIN_IS_CHINA', 'false').lower() == 'true' if not garmin_username or not garmin_password: print("Error: GARMIN_USERNAME and GARMIN_PASSWORD must be set in the .env file") return False # Backend API details backend_host = os.getenv('BACKEND_HOST', 'localhost') backend_port = os.getenv('BACKEND_PORT', '8000') # Construct the API endpoint URL api_url = f"http://{backend_host}:{backend_port}/api/setup/garmin" # Prepare the payload payload = { "username": garmin_username, "password": garmin_password, "is_china": garmin_is_china } headers = { "Content-Type": "application/json" } print(f"Sending Garmin credentials to: {api_url}") print(f"Username: {garmin_username}") print(f"Is China: {garmin_is_china}") try: # Make the POST request to the API endpoint response = requests.post(api_url, json=payload, headers=headers, timeout=30) print(f"Response Status Code: {response.status_code}") if response.status_code == 200: response_data = response.json() print(f"Response: {json.dumps(response_data, indent=2)}") if response_data.get("status") == "success": print("✓ Garmin credentials saved and authenticated successfully!") return True elif response_data.get("status") == "mfa_required": print("ℹ Multi-factor authentication required!") session_id = response_data.get("session_id") print(f"MFA Session ID: {session_id}") return "mfa_required" # Return special value to indicate MFA required else: print(f"⚠ Unexpected response status: {response_data.get('status')}") return False else: print(f"Error Response: {response.text}") # Provide helpful error messages based on common issues if response.status_code == 500: error_resp = response.json() if response.content else {} error_msg = error_resp.get('message', '') if 'could not translate host name "db" to address' in error_msg: print("\nNote: This error occurs when the database container is not running.") print("You might need to start the full stack with Docker Compose:") print(" docker-compose up -d") elif 'Invalid credentials' in error_msg or 'Authentication' in error_msg: print("\nNote: Invalid Garmin username or password. Please check your credentials.") elif 'MFA' in error_msg or 'mfa' in error_msg: print("\nNote: Multi-factor authentication required.") return False except requests.exceptions.ConnectionError: print(f"❌ Error: Could not connect to the backend at {api_url}") print("Make sure the backend service is running on the specified host and port.") print("\nTo start the backend service:") print(" cd backend") print(" docker-compose up -d") return False except requests.exceptions.Timeout: print(f"❌ Error: Request timed out. The backend at {api_url} might be slow to respond or unavailable.") return False except requests.exceptions.RequestException as e: print(f"❌ Request failed: {str(e)}") return False except json.JSONDecodeError: print(f"❌ Error: Could not parse the response from the server.") print(f"Raw response: {response.text}") return False if __name__ == "__main__": result = save_garmin_credentials() if result is True: print("\n✓ Script executed successfully") sys.exit(0) elif result == "mfa_required": print("\n✓ Script executed successfully (MFA required)") sys.exit(0) # Exit with success code since this is expected behavior else: print("\n❌ Script execution failed") sys.exit(1)