mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 21:03:01 +00:00
173 lines
6.7 KiB
Python
173 lines
6.7 KiB
Python
import requests
|
|
import json
|
|
import os
|
|
import logging
|
|
|
|
# Setup basic logging
|
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
|
|
|
# Define paths relative to this file's location (assuming it's in src)
|
|
CONFIG_DIR = os.path.join(os.path.dirname(__file__), '..', 'config')
|
|
CONFIG_PATH = os.path.join(CONFIG_DIR, 'config.json')
|
|
YTM_AUTH_CONFIG_PATH = os.path.join(CONFIG_DIR, 'ytm_auth.json')
|
|
|
|
# Resolve to absolute paths
|
|
CONFIG_DIR = os.path.abspath(CONFIG_DIR)
|
|
CONFIG_PATH = os.path.abspath(CONFIG_PATH)
|
|
YTM_AUTH_CONFIG_PATH = os.path.abspath(YTM_AUTH_CONFIG_PATH)
|
|
|
|
# YTM Companion App Constants (copied from ytm_client.py)
|
|
YTM_APP_ID = "ledmatrixcontroller"
|
|
YTM_APP_NAME = "LEDMatrixController"
|
|
YTM_APP_VERSION = "1.0.0"
|
|
|
|
def load_ytm_companion_url():
|
|
"""Loads YTM_COMPANION_URL from config.json"""
|
|
default_url = "http://localhost:9863"
|
|
base_url = default_url
|
|
|
|
if not os.path.exists(CONFIG_PATH):
|
|
logging.warning(f"Main config file not found at {CONFIG_PATH}. Using default YTM URL: {base_url}")
|
|
return base_url
|
|
|
|
try:
|
|
with open(CONFIG_PATH, 'r') as f:
|
|
loaded_config = json.load(f)
|
|
music_config = loaded_config.get("music", {})
|
|
base_url = music_config.get("YTM_COMPANION_URL", default_url)
|
|
if not base_url:
|
|
logging.warning("YTM_COMPANION_URL missing or empty in config.json music section. Using default.")
|
|
base_url = default_url
|
|
except json.JSONDecodeError:
|
|
logging.error(f"Error decoding JSON from main config {CONFIG_PATH}. Using default YTM URL.")
|
|
base_url = default_url
|
|
except Exception as e:
|
|
logging.error(f"Error loading YTM_COMPANION_URL from main config {CONFIG_PATH}: {e}. Using default YTM URL.")
|
|
base_url = default_url
|
|
|
|
logging.info(f"YTM Companion URL set to: {base_url}")
|
|
|
|
if base_url.startswith("ws://"):
|
|
base_url = "http://" + base_url[5:]
|
|
elif base_url.startswith("wss://"):
|
|
base_url = "https://" + base_url[6:]
|
|
return base_url
|
|
|
|
def _request_auth_code(base_url):
|
|
"""Requests an authentication code from the YTM Companion server."""
|
|
url = f"{base_url}/api/v1/auth/requestcode"
|
|
payload = {
|
|
"appId": YTM_APP_ID,
|
|
"appName": YTM_APP_NAME,
|
|
"appVersion": YTM_APP_VERSION
|
|
}
|
|
try:
|
|
logging.info(f"Requesting auth code from {url} with appId: {YTM_APP_ID}")
|
|
response = requests.post(url, json=payload, timeout=10)
|
|
response.raise_for_status()
|
|
data = response.json()
|
|
auth_code = data.get('code')
|
|
if auth_code:
|
|
logging.info(f"Received auth code: {auth_code}")
|
|
else:
|
|
logging.error("Auth code not found in response.")
|
|
return auth_code
|
|
except requests.exceptions.RequestException as e:
|
|
logging.error(f"Error requesting YTM auth code: {e}")
|
|
return None
|
|
except json.JSONDecodeError:
|
|
logging.error("Error decoding JSON response when requesting auth code.")
|
|
return None
|
|
|
|
def _request_auth_token(base_url, code):
|
|
"""Requests an authentication token using the provided code."""
|
|
if not code:
|
|
return None
|
|
url = f"{base_url}/api/v1/auth/request"
|
|
payload = {
|
|
"appId": YTM_APP_ID,
|
|
"code": code
|
|
}
|
|
try:
|
|
logging.info("Requesting auth token. PLEASE CHECK YOUR YTM DESKTOP APP TO APPROVE THIS REQUEST.")
|
|
logging.info("You have 30 seconds to approve in the YTM Desktop App.")
|
|
response = requests.post(url, json=payload, timeout=35)
|
|
response.raise_for_status()
|
|
data = response.json()
|
|
token = data.get('token')
|
|
if token:
|
|
logging.info("Successfully received YTM auth token.")
|
|
else:
|
|
logging.warning("Auth token not found in response.")
|
|
return token
|
|
except requests.exceptions.Timeout:
|
|
logging.error("Timeout waiting for YTM auth token. Did you approve the request in YTM Desktop App?")
|
|
return None
|
|
except requests.exceptions.RequestException as e:
|
|
logging.error(f"Error requesting YTM auth token: {e}")
|
|
return None
|
|
except json.JSONDecodeError:
|
|
logging.error("Error decoding JSON response when requesting auth token.")
|
|
return None
|
|
|
|
def save_ytm_token(token):
|
|
"""Saves the YTM token to ytm_auth.json."""
|
|
if not token:
|
|
logging.warning("No YTM token provided to save.")
|
|
return False
|
|
|
|
if not os.path.exists(CONFIG_DIR):
|
|
try:
|
|
os.makedirs(CONFIG_DIR)
|
|
logging.info(f"Created config directory: {CONFIG_DIR}")
|
|
except OSError as e:
|
|
logging.error(f"Could not create config directory {CONFIG_DIR}: {e}")
|
|
return False
|
|
|
|
token_data = {"YTM_COMPANION_TOKEN": token}
|
|
|
|
try:
|
|
with open(YTM_AUTH_CONFIG_PATH, 'w') as f:
|
|
json.dump(token_data, f, indent=4)
|
|
logging.info(f"YTM Companion token saved to {YTM_AUTH_CONFIG_PATH}")
|
|
return True
|
|
except Exception as e:
|
|
logging.error(f"Error saving YTM token to {YTM_AUTH_CONFIG_PATH}: {e}")
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
logging.info("Starting YTM Authentication Process...")
|
|
|
|
# Ensure the config directory exists, create if not
|
|
# This is important because this script is run as the user.
|
|
if not os.path.exists(CONFIG_DIR):
|
|
try:
|
|
logging.info(f"Config directory {CONFIG_DIR} not found. Attempting to create it.")
|
|
os.makedirs(CONFIG_DIR)
|
|
logging.info(f"Successfully created config directory: {CONFIG_DIR}")
|
|
except OSError as e:
|
|
logging.error(f"Fatal: Could not create config directory {CONFIG_DIR}: {e}")
|
|
logging.error("Please ensure the path is correct and you have permissions to create this directory.")
|
|
exit(1) # Exit if we can't create the config directory
|
|
|
|
ytm_url = load_ytm_companion_url()
|
|
if not ytm_url:
|
|
logging.error("Could not determine YTM Companion URL. Exiting.")
|
|
exit(1)
|
|
|
|
auth_code = _request_auth_code(ytm_url)
|
|
if not auth_code:
|
|
logging.error("Failed to get YTM auth code. Cannot proceed with authentication. Exiting.")
|
|
exit(1)
|
|
|
|
auth_token = _request_auth_token(ytm_url, auth_code)
|
|
if auth_token:
|
|
if save_ytm_token(auth_token):
|
|
logging.info("YTM authentication successful and token saved.")
|
|
else:
|
|
logging.error("YTM authentication successful, but FAILED to save token.")
|
|
logging.error(f"Please check permissions for the directory {CONFIG_DIR} and the file {YTM_AUTH_CONFIG_PATH} if it exists.")
|
|
else:
|
|
logging.error("Failed to get YTM auth token. Authentication unsuccessful.")
|
|
|
|
logging.info("YTM Authentication Process Finished.") |