diff --git a/musicfetch b/musicfetch index b5671cc..fe45096 100644 --- a/musicfetch +++ b/musicfetch @@ -90,9 +90,11 @@ def search_artist(name, timeout_seconds=15): def get_existing_artist(name): print(f"--> Checking if artist '{name}' already exists in Lidarr...") try: - print("...Sending request to /api/v1/artist") + if DEBUG: + print("...Sending request to /api/v1/artist") resp = requests.get(f"{LIDARR_URL}/api/v1/artist", headers=headers, timeout=10) - print("...Got response from Lidarr") + if DEBUG: + print("...Got response from Lidarr") resp.raise_for_status() for artist in resp.json(): if artist["artistName"].lower() == name.lower(): @@ -102,35 +104,62 @@ def get_existing_artist(name): except requests.exceptions.Timeout: print("!!! Timeout during existing artist check.") except requests.exceptions.RequestException as e: - print(f"!!! Exception during existing artist check: {e}") + if DEBUG: + print(f"[DEBUG] Exception during existing artist check: {e}") return None -def add_artist(metadata_artist): +def get_default_metadata_profile_id(): + try: + resp = requests.get(f"{LIDARR_URL}/api/v1/metadataprofile", headers=headers, timeout=10) + resp.raise_for_status() + profiles = resp.json() + if profiles: + return profiles[0]["id"] + except Exception as e: + print(f"[ERROR] Could not fetch metadata profiles: {e}") + return 1 # fallback to 1 if not found + +def add_artist(metadata_artist, search_for_missing_albums=False): foreign_id = metadata_artist.get("foreignArtistId") or metadata_artist.get("id") artist_name = metadata_artist.get("artistName") or metadata_artist.get("title") if not foreign_id or not artist_name: + if DEBUG: + print("[DEBUG] Metadata received:", metadata_artist) raise ValueError("Could not find foreignArtistId or artistName in metadata.") + metadata_profile_id = get_default_metadata_profile_id() + data = { "foreignArtistId": foreign_id, "artistName": artist_name, "qualityProfileId": 1, + "metadataProfileId": metadata_profile_id, "rootFolderPath": ROOT_FOLDER, "monitored": True, "addOptions": { - "searchForMissingAlbums": True, + "searchForMissingAlbums": search_for_missing_albums, "monitor": "all" } } - resp = requests.post( - f"{LIDARR_URL}/api/v1/artist", - headers=headers, - json=data - ) - resp.raise_for_status() - return resp.json() + if DEBUG: + print("[DEBUG] Sending payload to Lidarr /api/v1/artist:", json.dumps(data, ensure_ascii=False)) + + try: + resp = requests.post( + f"{LIDARR_URL}/api/v1/artist", + headers=headers, + json=data, + timeout=15 + ) + resp.raise_for_status() + return resp.json() + except requests.RequestException as e: + print("Lidarr add_artist failed. Falling back to yt-dlp.") + if DEBUG: + print(f"[DEBUG] Lidarr add_artist exception: {e}") + return None def search_local_album(track_name, artist_id=None, artist_name=None): try: @@ -154,13 +183,17 @@ def search_local_album(track_name, artist_id=None, artist_name=None): continue # Check if track_name matches album title (case insensitive substring) if track_name.lower() in album.get("title", "").lower(): - print(f"!!! Found local album: {album.get('title')} by {album.get('artist', {}).get('artistName')}") + if DEBUG: + print(f"[DEBUG] Found local album: {album.get('title')} by {album.get('artist', {}).get('artistName')}") return album - print("!!! No matching local album found.") + if DEBUG: + print("[DEBUG] No matching local album found.") except requests.exceptions.Timeout: - print("!!! Timeout during local album search.") + if DEBUG: + print("[DEBUG] Timeout during local album search.") except requests.exceptions.RequestException as e: - print(f"!!! Exception during local album search: {e}") + if DEBUG: + print(f"[DEBUG] Exception during local album search: {e}") return None def search_album(track_name, artist_id): @@ -171,7 +204,8 @@ def search_album(track_name, artist_id): # Fallback to external lookup try: - print(f"--> Searching album externally with track: '{track_name}' and artist ID: {artist_id}") + if DEBUG: + print(f"[DEBUG] Searching album externally with track: '{track_name}' and artist ID: {artist_id}") resp = requests.get( f"{LIDARR_URL}/api/v1/album/lookup", headers=headers, @@ -180,12 +214,15 @@ def search_album(track_name, artist_id): ) resp.raise_for_status() results = resp.json() - print(f"...Found {len(results)} results from album lookup with artist ID.") + if DEBUG: + print(f"[DEBUG] Found {len(results)} results from album lookup with artist ID.") return results[0] if results else None except requests.exceptions.Timeout: - print("!!! Timeout during album search (with artist ID).") + if DEBUG: + print("[DEBUG] Timeout during album search (with artist ID).") except requests.exceptions.RequestException as e: - print(f"!!! Exception during album search (with artist ID): {e}") + if DEBUG: + print(f"[DEBUG] Exception during album search (with artist ID): {e}") return None def search_album_by_artist(track_name, artist_name): @@ -196,7 +233,8 @@ def search_album_by_artist(track_name, artist_name): # Fallback to external lookup try: - print(f"--> Fallback external search: '{artist_name} {track_name}'") + if DEBUG: + print(f"[DEBUG] Fallback external search: '{artist_name} {track_name}'") resp = requests.get( f"{LIDARR_URL}/api/v1/album/lookup", headers=headers, @@ -205,15 +243,17 @@ def search_album_by_artist(track_name, artist_name): ) resp.raise_for_status() results = resp.json() - print(f"...Found {len(results)} results from fallback search.") + if DEBUG: + print(f"[DEBUG] Found {len(results)} results from fallback search.") return results[0] if results else None except requests.exceptions.Timeout: - print("!!! Timeout during fallback album search.") + if DEBUG: + print("[DEBUG] Timeout during fallback album search.") except requests.exceptions.RequestException as e: - print(f"!!! Exception during fallback album search: {e}") + if DEBUG: + print(f"[DEBUG] Exception during fallback album search: {e}") return None - def trigger_album_search(album_id): data = { "name": "AlbumSearch", @@ -225,23 +265,40 @@ def trigger_album_search(album_id): json=data ) resp.raise_for_status() - print(f"Triggered Lidarr search for album ID {album_id}") + if DEBUG: + print(f"[DEBUG] Triggered Lidarr search for album ID {album_id}") def main(): - if len(sys.argv) < 2: - print("Usage: musicfetch.py 'Artist - Track' OR 'https://youtube.com/watch?...'") + global DEBUG + DEBUG = False + search_for_missing_albums = False + + # Parse extra arguments + args = sys.argv[1:] + input_str = None + for arg in args: + if arg == '--debug': + DEBUG = True + elif arg == '--search-all': + search_for_missing_albums = True + elif not input_str: + input_str = arg + + if not input_str: + print("Usage: musicfetch.py [--debug] [--search-all] 'Artist - Track' OR 'https://youtube.com/watch?...'") sys.exit(1) - input_str = sys.argv[1] - if is_url(input_str): - print("Input is a URL. Extracting metadata to find artist...") + if DEBUG: + print("Input is a URL. Extracting metadata to find artist...") metadata = run_yt_dlp_get_metadata(input_str) if metadata: artist_name = get_artist_from_metadata(metadata) - print(f"Extracted artist name: {artist_name}") + if DEBUG: + print(f"Extracted artist name: {artist_name}") else: - print("Failed to get metadata from URL.") + if DEBUG: + print("Failed to get metadata from URL.") artist_name = "Unknown Artist" target_folder = os.path.join(ROOT_FOLDER, artist_name, "youtube") @@ -256,27 +313,34 @@ def main(): artist_name = artist_name.strip() track_name = track_name.strip() - print(f"Looking up artist: {artist_name}") + if DEBUG: + print(f"Looking up artist: {artist_name}") artist = get_existing_artist(artist_name) if not artist: print("Artist not found. Searching Lidarr metadata (with timeout)...") metadata = search_artist(artist_name) if not metadata: - print("No match found or search timed out. Falling back to yt-dlp.") + if DEBUG: + print("No match found or search timed out. Falling back to yt-dlp.") yt_dlp_download(f"ytsearch:{input_str}", os.path.join(ROOT_FOLDER, artist_name, "youtube")) return print(f"Adding artist: {metadata.get('artistName') or metadata.get('title')}") - artist = add_artist(metadata) + artist = add_artist(metadata, search_for_missing_albums=search_for_missing_albums) + if not artist: + yt_dlp_download(f"ytsearch:{input_str}", os.path.join(ROOT_FOLDER, artist_name, "youtube")) + return album = search_album(track_name, artist["id"]) or search_album_by_artist(track_name, artist_name) if album: - print(f"Found album '{album['title']}' for track '{track_name}', triggering search...") + if DEBUG: + print(f"Found album '{album['title']}' for track '{track_name}', triggering search...") trigger_album_search(album["id"]) else: - print("No album found in Lidarr. Falling back to yt-dlp.") + if DEBUG: + print("No album found in Lidarr. Falling back to yt-dlp.") yt_dlp_download(input_str, os.path.join(ROOT_FOLDER, artist_name, "youtube")) if __name__ == "__main__":