diff --git a/backend/app/services/sync.py b/backend/app/services/sync.py index c3bb70f..f0ac679 100644 --- a/backend/app/services/sync.py +++ b/backend/app/services/sync.py @@ -22,13 +22,33 @@ async def fetch_radarr_movies() -> List[Dict]: async with httpx.AsyncClient() as client: try: + # First test connection with system status + status_response = await client.get( + f"{settings.radarr_url}/api/v3/system/status", + headers={"X-Api-Key": settings.radarr_api_key}, + timeout=10.0 + ) + if status_response.status_code == 401: + logger.error("Radarr: Invalid API key") + return [] + status_response.raise_for_status() + + # Fetch movies response = await client.get( f"{settings.radarr_url}/api/v3/movie", headers={"X-Api-Key": settings.radarr_api_key}, timeout=30.0 ) response.raise_for_status() - return response.json() + movies = response.json() + logger.info(f"Radarr: Fetched {len(movies)} movies") + return movies + except httpx.HTTPStatusError as e: + logger.error(f"Radarr HTTP error: {e.response.status_code} - {e.response.text[:200]}") + return [] + except httpx.ConnectError as e: + logger.error(f"Radarr connection error: {e}. Check if Radarr is running on {settings.radarr_url}") + return [] except Exception as e: logger.error(f"Failed to fetch Radarr movies: {e}") return [] @@ -48,7 +68,15 @@ async def fetch_sonarr_series() -> List[Dict]: timeout=30.0 ) response.raise_for_status() - return response.json() + series = response.json() + logger.info(f"Sonarr: Fetched {len(series)} series") + return series + except httpx.HTTPStatusError as e: + logger.error(f"Sonarr HTTP error: {e.response.status_code} - {e.response.text[:200]}") + return [] + except httpx.ConnectError as e: + logger.error(f"Sonarr connection error: {e}. Check if Sonarr is running on {settings.sonarr_url}") + return [] except Exception as e: logger.error(f"Failed to fetch Sonarr series: {e}") return [] @@ -68,7 +96,15 @@ async def fetch_lidarr_artists() -> List[Dict]: timeout=30.0 ) response.raise_for_status() - return response.json() + artists = response.json() + logger.info(f"Lidarr: Fetched {len(artists)} artists") + return artists + except httpx.HTTPStatusError as e: + logger.error(f"Lidarr HTTP error: {e.response.status_code} - {e.response.text[:200]}") + return [] + except httpx.ConnectError as e: + logger.error(f"Lidarr connection error: {e}. Check if Lidarr is running on {settings.lidarr_url}") + return [] except Exception as e: logger.error(f"Failed to fetch Lidarr artists: {e}") return [] @@ -269,9 +305,14 @@ async def upsert_media_item(source_kind: str, source_item_id: int, title: str, async def sync_radarr(): """Sync movies from Radarr""" + logger.info(f"Starting Radarr sync from {settings.radarr_url}") movies = await fetch_radarr_movies() - synced = 0 + if not movies: + logger.warning("Radarr: No movies fetched. Check API key and connection.") + return {"radarr": 0} + + synced = 0 for movie in movies: try: # Try to get country from TMDB if tmdbId is available and no country in Radarr data @@ -369,6 +410,9 @@ async def sync_lidarr(): async def sync_all_arrs() -> Dict: """Sync from all *arr instances""" logger.info("Starting sync from all *arr instances") + logger.info(f"Radarr URL: {settings.radarr_url}, API key configured: {bool(settings.radarr_api_key)}") + logger.info(f"Sonarr URL: {settings.sonarr_url}, API key configured: {bool(settings.sonarr_api_key)}") + logger.info(f"Lidarr URL: {settings.lidarr_url}, API key configured: {bool(settings.lidarr_api_key)}") results = {} @@ -376,7 +420,7 @@ async def sync_all_arrs() -> Dict: try: results.update(await sync_radarr()) except Exception as e: - logger.error(f"Radarr sync failed: {e}") + logger.error(f"Radarr sync failed: {e}", exc_info=True) results["radarr"] = 0 try: