mirror of
https://github.com/adelatour11/codebarr.git
synced 2026-01-05 14:49:30 -06:00
Refactor album handling and update configurations
Updated Lidarr configuration, added monitoring for exact releases, and improved album processing logic.
This commit is contained in:
318
app.py
318
app.py
@@ -8,8 +8,8 @@ app = Flask(__name__)
|
||||
app.secret_key = "your_secret_key_here"
|
||||
|
||||
# Your Lidarr config
|
||||
LIDARR_URL = "XXXX"
|
||||
API_KEY = "XXXX"
|
||||
LIDARR_URL = "https://XXXX"
|
||||
API_KEY = "XXXXX"
|
||||
HEADERS = {"X-Api-Key": API_KEY}
|
||||
|
||||
def check_lidarr_config():
|
||||
@@ -37,12 +37,30 @@ def get_release_from_barcode(barcode):
|
||||
return data['releases'][0]
|
||||
|
||||
def get_album_from_barcode(barcode):
|
||||
release = get_release_from_barcode(barcode)
|
||||
"""
|
||||
Fetch the exact release from MusicBrainz using the barcode.
|
||||
Returns: artist_name, artist_mbid, album_title, release_group_mbid, release_mbid
|
||||
"""
|
||||
url = f"https://musicbrainz.org/ws/2/release/?query=barcode:{barcode}&fmt=json"
|
||||
r = requests.get(url)
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
|
||||
if not data.get('releases'):
|
||||
raise Exception(f"No release found for barcode {barcode}")
|
||||
|
||||
# Take the first exact match (should match the barcode)
|
||||
release = data['releases'][0]
|
||||
release_group_mbid = release['release-group']['id']
|
||||
release_mbid = release['id'] # <-- exact release ID
|
||||
album_title = release['title']
|
||||
artist_name = release['artist-credit'][0]['name']
|
||||
artist_mbid = release['artist-credit'][0]['artist']['id']
|
||||
return artist_name, artist_mbid, album_title, release_group_mbid
|
||||
|
||||
artist_info = release['artist-credit'][0]
|
||||
artist_name = artist_info['name']
|
||||
artist_mbid = artist_info['artist']['id']
|
||||
|
||||
return artist_name, artist_mbid, album_title, release_group_mbid, release_mbid
|
||||
|
||||
|
||||
def find_or_create_artist(artist_name, artist_mbid):
|
||||
existing = requests.get(f"{LIDARR_URL}/api/v1/artist", headers=HEADERS).json()
|
||||
@@ -66,64 +84,284 @@ def find_or_create_artist(artist_name, artist_mbid):
|
||||
flash(f"✅ Artist '{artist_name}' created (no albums monitored).", "info")
|
||||
return data["id"]
|
||||
|
||||
def update_or_add_album(artist_id, release_group_mbid, album_title):
|
||||
albums_url = f"{LIDARR_URL}/api/v1/album?artistId={artist_id}"
|
||||
albums_resp = requests.get(albums_url, headers=HEADERS)
|
||||
albums_resp.raise_for_status()
|
||||
albums = albums_resp.json()
|
||||
def update_or_add_album(artist_id, release_group_mbid, release_mbid, album_title):
|
||||
"""
|
||||
Add or update album in Lidarr, monitoring the exact release.
|
||||
"""
|
||||
# First check if this release already exists
|
||||
albums = requests.get(f"{LIDARR_URL}/api/v1/album?artistId={artist_id}", headers=HEADERS).json()
|
||||
for album in albums:
|
||||
if album['foreignAlbumId'] == release_group_mbid:
|
||||
album_url = f"{LIDARR_URL}/api/v1/album/{album['id']}"
|
||||
album_resp = requests.get(album_url, headers=HEADERS)
|
||||
album_resp.raise_for_status()
|
||||
album_data = album_resp.json()
|
||||
if album.get('foreignAlbumId') == release_group_mbid:
|
||||
# Update monitored to True
|
||||
album_data = requests.get(f"{LIDARR_URL}/api/v1/album/{album['id']}", headers=HEADERS).json()
|
||||
album_data['monitored'] = True
|
||||
update_url = f"{LIDARR_URL}/api/v1/album/{album['id']}"
|
||||
update_resp = requests.put(update_url, headers=HEADERS, json=album_data)
|
||||
update_resp.raise_for_status()
|
||||
flash(f"✅ Album '{album_title}' is now monitored.", "success")
|
||||
return album_data
|
||||
artist_url = f"{LIDARR_URL}/api/v1/artist/{artist_id}"
|
||||
artist_resp = requests.get(artist_url, headers=HEADERS)
|
||||
artist_resp.raise_for_status()
|
||||
artist_data = artist_resp.json()
|
||||
# Set exact release
|
||||
album_data['foreignReleaseId'] = release_mbid
|
||||
r = requests.put(f"{LIDARR_URL}/api/v1/album/{album['id']}", headers=HEADERS, json=album_data)
|
||||
r.raise_for_status()
|
||||
flash(f"✅ Album '{album_title}' is now monitored (exact release).", "success")
|
||||
return r.json()
|
||||
|
||||
# If album not found, create it
|
||||
artist_data = requests.get(f"{LIDARR_URL}/api/v1/artist/{artist_id}", headers=HEADERS).json()
|
||||
payload = {
|
||||
"artistId": artist_id,
|
||||
"artist": artist_data,
|
||||
"foreignAlbumId": release_group_mbid,
|
||||
"foreignReleaseId": release_mbid, # <-- exact release
|
||||
"title": album_title,
|
||||
"monitored": True, # Only this album is monitored
|
||||
"monitored": True,
|
||||
"addOptions": {"searchForNewAlbum": True}
|
||||
}
|
||||
r = requests.post(f"{LIDARR_URL}/api/v1/album", headers=HEADERS, json=payload)
|
||||
r.raise_for_status()
|
||||
flash(f"✅ Album '{album_title}' added and monitored.", "success")
|
||||
flash(f"✅ Album '{album_title}' added and monitored (exact release).", "success")
|
||||
return r.json()
|
||||
|
||||
|
||||
def monitor_exact_release(artist_id, release_group_mbid, release_mbid, album_title):
|
||||
"""
|
||||
Add album if missing, then monitor the exact release after Lidarr fetches releases.
|
||||
"""
|
||||
# 1️⃣ Check if album exists
|
||||
albums = requests.get(f"{LIDARR_URL}/api/v1/album?artistId={artist_id}", headers=HEADERS).json()
|
||||
album_id = None
|
||||
for album in albums:
|
||||
if album.get('foreignAlbumId') == release_group_mbid:
|
||||
album_id = album['id']
|
||||
break
|
||||
|
||||
# 2️⃣ Add album if missing
|
||||
if not album_id:
|
||||
artist_data = requests.get(f"{LIDARR_URL}/api/v1/artist/{artist_id}", headers=HEADERS).json()
|
||||
payload = {
|
||||
"artistId": artist_id,
|
||||
"artist": artist_data,
|
||||
"foreignAlbumId": release_group_mbid,
|
||||
"title": album_title,
|
||||
"monitored": True,
|
||||
"addOptions": {"searchForNewAlbum": True}
|
||||
}
|
||||
album_resp = requests.post(f"{LIDARR_URL}/api/v1/album", headers=HEADERS, json=payload)
|
||||
album_resp.raise_for_status()
|
||||
album_id = album_resp.json()["id"]
|
||||
|
||||
# 3️⃣ Wait for Lidarr to fetch releases (poll until the release appears)
|
||||
timeout = 30 # seconds
|
||||
interval = 3
|
||||
elapsed = 0
|
||||
while elapsed < timeout:
|
||||
album_data = requests.get(f"{LIDARR_URL}/api/v1/album/{album_id}", headers=HEADERS).json()
|
||||
releases = album_data.get("releases", [])
|
||||
target_release = next((r for r in releases if r["id"] == release_mbid), None)
|
||||
if target_release:
|
||||
break
|
||||
time.sleep(interval)
|
||||
elapsed += interval
|
||||
else:
|
||||
raise Exception("❌ Exact release not found in Lidarr after waiting")
|
||||
|
||||
# 4️⃣ Mark the exact release as monitored
|
||||
for r in releases:
|
||||
r["monitored"] = r["id"] == release_mbid # only monitor target release
|
||||
|
||||
album_data["monitored"] = True
|
||||
album_data["releases"] = releases
|
||||
|
||||
update_resp = requests.put(f"{LIDARR_URL}/api/v1/album/{album_id}", headers=HEADERS, json=album_data)
|
||||
update_resp.raise_for_status()
|
||||
return update_resp.json()
|
||||
|
||||
|
||||
def add_album_with_exact_release(barcode):
|
||||
# --- 1️⃣ Get release info from MusicBrainz ---
|
||||
r = requests.get(f"https://musicbrainz.org/ws/2/release/?query=barcode:{barcode}&fmt=json")
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
if not data.get("releases"):
|
||||
raise Exception(f"No release found for barcode {barcode}")
|
||||
|
||||
release = data["releases"][0]
|
||||
release_mbid = release["id"] # exact release MBID
|
||||
release_group_mbid = release["release-group"]["id"]
|
||||
album_title = release["title"]
|
||||
artist_credit = release["artist-credit"][0]
|
||||
artist_name = artist_credit["name"]
|
||||
artist_mbid = artist_credit["artist"]["id"]
|
||||
|
||||
# --- 2️⃣ Find or create artist in Lidarr ---
|
||||
artists = requests.get(f"{LIDARR_URL}/api/v1/artist", headers=HEADERS).json()
|
||||
artist_id = None
|
||||
for a in artists:
|
||||
if a.get("foreignArtistId") == artist_mbid:
|
||||
artist_id = a["id"]
|
||||
break
|
||||
if not artist_id:
|
||||
payload = {
|
||||
"artistName": artist_name,
|
||||
"foreignArtistId": artist_mbid,
|
||||
"rootFolderPath": "/music",
|
||||
"qualityProfileId": 2,
|
||||
"metadataProfileId": 9,
|
||||
"monitored": False,
|
||||
"monitorNewItems": "none",
|
||||
"addOptions": {"searchForMissingAlbums": False}
|
||||
}
|
||||
resp = requests.post(f"{LIDARR_URL}/api/v1/artist", headers=HEADERS, json=payload)
|
||||
resp.raise_for_status()
|
||||
artist_id = resp.json()["id"]
|
||||
|
||||
# --- 3️⃣ Check if album exists ---
|
||||
albums = requests.get(f"{LIDARR_URL}/api/v1/album?artistId={artist_id}", headers=HEADERS).json()
|
||||
album_id = None
|
||||
for alb in albums:
|
||||
if alb.get("foreignAlbumId") == release_group_mbid:
|
||||
album_id = alb["id"]
|
||||
break
|
||||
|
||||
# --- 4️⃣ Add or update album ---
|
||||
if not album_id:
|
||||
# Album does not exist → create it with exact release
|
||||
artist_data = requests.get(f"{LIDARR_URL}/api/v1/artist/{artist_id}", headers=HEADERS).json()
|
||||
payload = {
|
||||
"artistId": artist_id,
|
||||
"artist": artist_data,
|
||||
"foreignAlbumId": release_group_mbid,
|
||||
"title": album_title,
|
||||
"monitored": True,
|
||||
"addOptions": {"searchForNewAlbum": True},
|
||||
"releases": [{"id": release_mbid, "monitored": True}]
|
||||
}
|
||||
album_resp = requests.post(f"{LIDARR_URL}/api/v1/album", headers=HEADERS, json=payload)
|
||||
album_resp.raise_for_status()
|
||||
album_id = album_resp.json()["id"]
|
||||
else:
|
||||
# Album exists → monitor exact release
|
||||
album_data = requests.get(f"{LIDARR_URL}/api/v1/album/{album_id}", headers=HEADERS).json()
|
||||
album_data["monitored"] = True
|
||||
album_data["releases"] = [{"id": release_mbid, "monitored": True}]
|
||||
update_resp = requests.put(f"{LIDARR_URL}/api/v1/album/{album_id}", headers=HEADERS, json=album_data)
|
||||
update_resp.raise_for_status()
|
||||
|
||||
# --- 5️⃣ Ensure release is monitored ---
|
||||
release_payload = {
|
||||
"albumId": album_id,
|
||||
"releaseId": release_mbid,
|
||||
"monitored": True
|
||||
}
|
||||
r = requests.post(f"{LIDARR_URL}/api/v1/release", headers=HEADERS, json=release_payload)
|
||||
r.raise_for_status()
|
||||
|
||||
return {
|
||||
"artist": artist_name,
|
||||
"album": album_title,
|
||||
"release_mbid": release_mbid,
|
||||
"album_id": album_id
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
def update_album_release(album_id, artist_id, album_title, release_mbid):
|
||||
# Fetch current album info
|
||||
r = requests.get(f"{LIDARR_URL}/api/v1/album/{album_id}", headers=HEADERS)
|
||||
r.raise_for_status()
|
||||
album = r.json()
|
||||
|
||||
# Prepare payload
|
||||
payload = {
|
||||
"id": album['id'],
|
||||
"artistId": artist_id,
|
||||
"title": album['title'],
|
||||
"monitored": True,
|
||||
"releases": [{"id": release_mbid, "monitored": True}]
|
||||
}
|
||||
|
||||
# Send update
|
||||
r = requests.put(f"{LIDARR_URL}/api/v1/album/{album_id}", headers=HEADERS, json=payload)
|
||||
r.raise_for_status()
|
||||
return r.json()
|
||||
|
||||
def process_barcode(barcode):
|
||||
try:
|
||||
# Step 1: Processing barcode
|
||||
# Step 1: Fetch exact release from MusicBrainz
|
||||
yield json.dumps({"status": "🔍 Processing barcode...", "progress": 5}) + "\n\n"
|
||||
artist_name, artist_mbid, album_title, release_group_mbid = get_album_from_barcode(barcode)
|
||||
yield json.dumps({"status": f"🎵 Album found: {album_title} by {artist_name}", "progress": 15}) + "\n\n"
|
||||
release = get_release_from_barcode(barcode)
|
||||
release_mbid = release['id'] # exact release MBID
|
||||
release_group_mbid = release['release-group']['id']
|
||||
album_title = release['title']
|
||||
artist_info = release['artist-credit'][0]
|
||||
artist_name = artist_info['name']
|
||||
artist_mbid = artist_info['artist']['id']
|
||||
yield json.dumps({"status": f"🎵 Found release '{album_title}' by {artist_name}", "progress": 15}) + "\n\n"
|
||||
|
||||
# Step 2: Checking artist
|
||||
# Step 2: Ensure artist exists
|
||||
yield json.dumps({"status": f"🔎 Checking artist '{artist_name}'...", "progress": 30}) + "\n\n"
|
||||
artist_id = find_or_create_artist(artist_name, artist_mbid)
|
||||
|
||||
# Step 3: Waiting for Lidarr
|
||||
yield json.dumps({"status": "🕒 Waiting 30 seconds for Lidarr to process the artist...", "progress": 50}) + "\n\n"
|
||||
time.sleep(30)
|
||||
# Step 3: Ensure album exists
|
||||
albums = requests.get(f"{LIDARR_URL}/api/v1/album?artistId={artist_id}", headers=HEADERS).json()
|
||||
album_id = None
|
||||
for alb in albums:
|
||||
if alb.get("foreignAlbumId") == release_group_mbid:
|
||||
album_id = alb['id']
|
||||
break
|
||||
|
||||
# Step 4: Adding/monitoring album
|
||||
yield json.dumps({"status": f"💿 Adding/monitoring album '{album_title}'...", "progress": 80}) + "\n\n"
|
||||
album_info = update_or_add_album(artist_id, release_group_mbid, album_title)
|
||||
if not album_id:
|
||||
# Create album
|
||||
artist_data = requests.get(f"{LIDARR_URL}/api/v1/artist/{artist_id}", headers=HEADERS).json()
|
||||
payload = {
|
||||
"artistId": artist_id,
|
||||
"artist": artist_data,
|
||||
"foreignAlbumId": release_group_mbid,
|
||||
"title": album_title,
|
||||
"monitored": True,
|
||||
"addOptions": {"searchForNewAlbum": True}
|
||||
}
|
||||
album_resp = requests.post(f"{LIDARR_URL}/api/v1/album", headers=HEADERS, json=payload)
|
||||
album_resp.raise_for_status()
|
||||
album_id = album_resp.json()["id"]
|
||||
yield json.dumps({"status": f"💿 Album '{album_title}' created in Lidarr.", "progress": 60}) + "\n\n"
|
||||
else:
|
||||
# Update album monitored flag
|
||||
album_data = requests.get(f"{LIDARR_URL}/api/v1/album/{album_id}", headers=HEADERS).json()
|
||||
album_data['monitored'] = True
|
||||
update_resp = requests.put(f"{LIDARR_URL}/api/v1/album/{album_id}", headers=HEADERS, json=album_data)
|
||||
update_resp.raise_for_status()
|
||||
yield json.dumps({"status": f"💿 Album '{album_title}' already exists. Marked as monitored.", "progress": 60}) + "\n\n"
|
||||
|
||||
# Step 4: Wait for Lidarr to fetch releases and monitor the exact one
|
||||
timeout = 60 # total seconds to wait
|
||||
interval = 3 # seconds between polls
|
||||
elapsed = 0
|
||||
matched_release = None
|
||||
|
||||
while elapsed < timeout:
|
||||
album_data = requests.get(f"{LIDARR_URL}/api/v1/album/{album_id}", headers=HEADERS).json()
|
||||
releases = album_data.get("releases", [])
|
||||
matched_release = next((r for r in releases if r.get("foreignReleaseId") == release_mbid), None)
|
||||
if matched_release:
|
||||
break
|
||||
time.sleep(interval)
|
||||
elapsed += interval
|
||||
else:
|
||||
raise Exception("❌ Exact release not found in Lidarr after waiting")
|
||||
|
||||
# Only monitor the release matching the barcode
|
||||
for r in releases:
|
||||
r["monitored"] = r.get("foreignReleaseId") == release_mbid
|
||||
|
||||
album_data["monitored"] = True
|
||||
album_data["releases"] = releases
|
||||
|
||||
update_resp = requests.put(f"{LIDARR_URL}/api/v1/album/{album_id}", headers=HEADERS, json=album_data)
|
||||
update_resp.raise_for_status()
|
||||
yield json.dumps({"status": f"✅ Album '{album_title}' now monitoring exact release!", "progress": 100}) + "\n\n"
|
||||
|
||||
# Step 5: Done
|
||||
yield json.dumps({"status": "✅ Album added and monitored!", "progress": 100}) + "\n\n"
|
||||
except Exception as e:
|
||||
yield json.dumps({"status": f"❌ Error: {str(e)}", "progress": 100}) + "\n\n"
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
return render_template("index.html")
|
||||
@@ -137,4 +375,4 @@ def submit():
|
||||
return Response(stream_with_context(process_barcode(barcode)), mimetype="text/event-stream")
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True, host="0.0.0.0", port=5000)
|
||||
app.run(debug=True, host="0.0.0.0", port=5083)
|
||||
|
||||
Reference in New Issue
Block a user