Command Line Arguments added to musicfetch script
--debug for debug mode --search-all will search all music sources as soon as the artist is added to Lidarr. The default behavior is to not search all sources.
This commit is contained in:
parent
5d1a494e77
commit
0cfee8205c
110
musicfetch
110
musicfetch
@ -90,8 +90,10 @@ def search_artist(name, timeout_seconds=15):
|
|||||||
def get_existing_artist(name):
|
def get_existing_artist(name):
|
||||||
print(f"--> Checking if artist '{name}' already exists in Lidarr...")
|
print(f"--> Checking if artist '{name}' already exists in Lidarr...")
|
||||||
try:
|
try:
|
||||||
|
if DEBUG:
|
||||||
print("...Sending request to /api/v1/artist")
|
print("...Sending request to /api/v1/artist")
|
||||||
resp = requests.get(f"{LIDARR_URL}/api/v1/artist", headers=headers, timeout=10)
|
resp = requests.get(f"{LIDARR_URL}/api/v1/artist", headers=headers, timeout=10)
|
||||||
|
if DEBUG:
|
||||||
print("...Got response from Lidarr")
|
print("...Got response from Lidarr")
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
for artist in resp.json():
|
for artist in resp.json():
|
||||||
@ -102,35 +104,62 @@ def get_existing_artist(name):
|
|||||||
except requests.exceptions.Timeout:
|
except requests.exceptions.Timeout:
|
||||||
print("!!! Timeout during existing artist check.")
|
print("!!! Timeout during existing artist check.")
|
||||||
except requests.exceptions.RequestException as e:
|
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
|
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")
|
foreign_id = metadata_artist.get("foreignArtistId") or metadata_artist.get("id")
|
||||||
artist_name = metadata_artist.get("artistName") or metadata_artist.get("title")
|
artist_name = metadata_artist.get("artistName") or metadata_artist.get("title")
|
||||||
|
|
||||||
if not foreign_id or not artist_name:
|
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.")
|
raise ValueError("Could not find foreignArtistId or artistName in metadata.")
|
||||||
|
|
||||||
|
metadata_profile_id = get_default_metadata_profile_id()
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"foreignArtistId": foreign_id,
|
"foreignArtistId": foreign_id,
|
||||||
"artistName": artist_name,
|
"artistName": artist_name,
|
||||||
"qualityProfileId": 1,
|
"qualityProfileId": 1,
|
||||||
|
"metadataProfileId": metadata_profile_id,
|
||||||
"rootFolderPath": ROOT_FOLDER,
|
"rootFolderPath": ROOT_FOLDER,
|
||||||
"monitored": True,
|
"monitored": True,
|
||||||
"addOptions": {
|
"addOptions": {
|
||||||
"searchForMissingAlbums": True,
|
"searchForMissingAlbums": search_for_missing_albums,
|
||||||
"monitor": "all"
|
"monitor": "all"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if DEBUG:
|
||||||
|
print("[DEBUG] Sending payload to Lidarr /api/v1/artist:", json.dumps(data, ensure_ascii=False))
|
||||||
|
|
||||||
|
try:
|
||||||
resp = requests.post(
|
resp = requests.post(
|
||||||
f"{LIDARR_URL}/api/v1/artist",
|
f"{LIDARR_URL}/api/v1/artist",
|
||||||
headers=headers,
|
headers=headers,
|
||||||
json=data
|
json=data,
|
||||||
|
timeout=15
|
||||||
)
|
)
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
return resp.json()
|
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):
|
def search_local_album(track_name, artist_id=None, artist_name=None):
|
||||||
try:
|
try:
|
||||||
@ -154,13 +183,17 @@ def search_local_album(track_name, artist_id=None, artist_name=None):
|
|||||||
continue
|
continue
|
||||||
# Check if track_name matches album title (case insensitive substring)
|
# Check if track_name matches album title (case insensitive substring)
|
||||||
if track_name.lower() in album.get("title", "").lower():
|
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
|
return album
|
||||||
print("!!! No matching local album found.")
|
if DEBUG:
|
||||||
|
print("[DEBUG] No matching local album found.")
|
||||||
except requests.exceptions.Timeout:
|
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:
|
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
|
return None
|
||||||
|
|
||||||
def search_album(track_name, artist_id):
|
def search_album(track_name, artist_id):
|
||||||
@ -171,7 +204,8 @@ def search_album(track_name, artist_id):
|
|||||||
|
|
||||||
# Fallback to external lookup
|
# Fallback to external lookup
|
||||||
try:
|
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(
|
resp = requests.get(
|
||||||
f"{LIDARR_URL}/api/v1/album/lookup",
|
f"{LIDARR_URL}/api/v1/album/lookup",
|
||||||
headers=headers,
|
headers=headers,
|
||||||
@ -180,12 +214,15 @@ def search_album(track_name, artist_id):
|
|||||||
)
|
)
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
results = resp.json()
|
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
|
return results[0] if results else None
|
||||||
except requests.exceptions.Timeout:
|
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:
|
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
|
return None
|
||||||
|
|
||||||
def search_album_by_artist(track_name, artist_name):
|
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
|
# Fallback to external lookup
|
||||||
try:
|
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(
|
resp = requests.get(
|
||||||
f"{LIDARR_URL}/api/v1/album/lookup",
|
f"{LIDARR_URL}/api/v1/album/lookup",
|
||||||
headers=headers,
|
headers=headers,
|
||||||
@ -205,15 +243,17 @@ def search_album_by_artist(track_name, artist_name):
|
|||||||
)
|
)
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
results = resp.json()
|
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
|
return results[0] if results else None
|
||||||
except requests.exceptions.Timeout:
|
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:
|
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
|
return None
|
||||||
|
|
||||||
|
|
||||||
def trigger_album_search(album_id):
|
def trigger_album_search(album_id):
|
||||||
data = {
|
data = {
|
||||||
"name": "AlbumSearch",
|
"name": "AlbumSearch",
|
||||||
@ -225,22 +265,39 @@ def trigger_album_search(album_id):
|
|||||||
json=data
|
json=data
|
||||||
)
|
)
|
||||||
resp.raise_for_status()
|
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():
|
def main():
|
||||||
if len(sys.argv) < 2:
|
global DEBUG
|
||||||
print("Usage: musicfetch.py 'Artist - Track' OR 'https://youtube.com/watch?...'")
|
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)
|
sys.exit(1)
|
||||||
|
|
||||||
input_str = sys.argv[1]
|
|
||||||
|
|
||||||
if is_url(input_str):
|
if is_url(input_str):
|
||||||
|
if DEBUG:
|
||||||
print("Input is a URL. Extracting metadata to find artist...")
|
print("Input is a URL. Extracting metadata to find artist...")
|
||||||
metadata = run_yt_dlp_get_metadata(input_str)
|
metadata = run_yt_dlp_get_metadata(input_str)
|
||||||
if metadata:
|
if metadata:
|
||||||
artist_name = get_artist_from_metadata(metadata)
|
artist_name = get_artist_from_metadata(metadata)
|
||||||
|
if DEBUG:
|
||||||
print(f"Extracted artist name: {artist_name}")
|
print(f"Extracted artist name: {artist_name}")
|
||||||
else:
|
else:
|
||||||
|
if DEBUG:
|
||||||
print("Failed to get metadata from URL.")
|
print("Failed to get metadata from URL.")
|
||||||
artist_name = "Unknown Artist"
|
artist_name = "Unknown Artist"
|
||||||
|
|
||||||
@ -256,6 +313,7 @@ def main():
|
|||||||
artist_name = artist_name.strip()
|
artist_name = artist_name.strip()
|
||||||
track_name = track_name.strip()
|
track_name = track_name.strip()
|
||||||
|
|
||||||
|
if DEBUG:
|
||||||
print(f"Looking up artist: {artist_name}")
|
print(f"Looking up artist: {artist_name}")
|
||||||
artist = get_existing_artist(artist_name)
|
artist = get_existing_artist(artist_name)
|
||||||
|
|
||||||
@ -263,19 +321,25 @@ def main():
|
|||||||
print("Artist not found. Searching Lidarr metadata (with timeout)...")
|
print("Artist not found. Searching Lidarr metadata (with timeout)...")
|
||||||
metadata = search_artist(artist_name)
|
metadata = search_artist(artist_name)
|
||||||
if not metadata:
|
if not metadata:
|
||||||
|
if DEBUG:
|
||||||
print("No match found or search timed out. Falling back to yt-dlp.")
|
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"))
|
yt_dlp_download(f"ytsearch:{input_str}", os.path.join(ROOT_FOLDER, artist_name, "youtube"))
|
||||||
return
|
return
|
||||||
|
|
||||||
print(f"Adding artist: {metadata.get('artistName') or metadata.get('title')}")
|
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)
|
album = search_album(track_name, artist["id"]) or search_album_by_artist(track_name, artist_name)
|
||||||
|
|
||||||
if album:
|
if album:
|
||||||
|
if DEBUG:
|
||||||
print(f"Found album '{album['title']}' for track '{track_name}', triggering search...")
|
print(f"Found album '{album['title']}' for track '{track_name}', triggering search...")
|
||||||
trigger_album_search(album["id"])
|
trigger_album_search(album["id"])
|
||||||
else:
|
else:
|
||||||
|
if DEBUG:
|
||||||
print("No album found in Lidarr. Falling back to yt-dlp.")
|
print("No album found in Lidarr. Falling back to yt-dlp.")
|
||||||
yt_dlp_download(input_str, os.path.join(ROOT_FOLDER, artist_name, "youtube"))
|
yt_dlp_download(input_str, os.path.join(ROOT_FOLDER, artist_name, "youtube"))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user