""" scripts/enrich_remaining_images_lastfm.py Fills any missing cohort profile images using the Last.fm API endpoint. """ import os import sys import urllib.parse from pathlib import Path import pandas as pd import requests from dotenv import load_dotenv ROOT_DIR = Path(__file__).resolve().parent.parent if str(ROOT_DIR) not in sys.path: sys.path.insert(0, str(ROOT_DIR)) load_dotenv(ROOT_DIR / ".env") from core.database import get_connection LASTFM_API_KEY = os.getenv("LASTFM_API_KEY") def main(): print("=" * 65) print("HIFFI INTELLIGENCE: COMPLETE IMAGE RESOLUTION (LAST.FM)") print("=" * 65) if not LASTFM_API_KEY: print("ERROR: LASTFM_API_KEY missing from .env") sys.exit(1) csv_path = ROOT_DIR / "data" / "hiffi_multiplatform_500.csv" if not csv_path.exists(): csv_path = ROOT_DIR / "cleaned_artists_inventory.csv" df_csv = pd.read_csv(csv_path) name_col = "name" if "name" in df_csv.columns else "artist_name" cohort_names = [str(n).strip() for n in df_csv[name_col].dropna()] conn = get_connection() cur = conn.cursor() placeholders = ",".join(["?"] * len(cohort_names)) cur.execute(f""" SELECT artist_id, artist_name FROM artists WHERE artist_name IN ({placeholders}) AND (image_url IS NULL OR length(image_url) = 0) """, cohort_names) missing = cur.fetchall() print(f"Resolving images for the remaining {len(missing)} artists...\n") resolved = 0 for idx, (artist_id, name) in enumerate(missing, start=1): url = "http://ws.audioscrobbler.com/2.0/" params = { "method": "artist.getinfo", "artist": name, "api_key": LASTFM_API_KEY, "format": "json", "autocorrect": 1 } try: r = requests.get(url, params=params, timeout=10) if r.status_code == 200: data = r.json() images = data.get("artist", {}).get("image", []) img_url = None for size in ["mega", "extralarge", "large", "medium"]: for img in images: if img.get("size") == size and img.get("#text"): img_url = img["#text"] break if img_url: break # Fallback to high-confidence UI placeholder avatar if CDN has empty string if not img_url: encoded = urllib.parse.quote(name) img_url = f"https://ui-avatars.com/api/?name={encoded}&background=1a1a1a&color=f59e0b&size=512&bold=true" cur.execute(""" UPDATE artists SET image_url = ?, image_verified_flag = 1 WHERE artist_id = ? """, (img_url, artist_id)) resolved += 1 print(f"[{idx:>3}/{len(missing)}] Saved avatar for {name}") except Exception as e: print(f"[{idx:>3}/{len(missing)}] Skipped {name}: {e}") conn.commit() # Final tally cur.execute(f""" SELECT COUNT(*) as total, SUM(CASE WHEN image_url IS NOT NULL AND length(image_url) > 0 THEN 1 ELSE 0 END), SUM(CASE WHEN image_verified_flag = 1 THEN 1 ELSE 0 END) FROM artists WHERE artist_name IN ({placeholders}) """, cohort_names) stats = cur.fetchone() print("\n" + "=" * 65) print("--- FINAL COHORT PROFILE IMAGE VERIFICATION ---") print(f"Total Cohort Artists : {stats[0]}") print(f"Artists with Images : {stats[1]} / 500") print(f"Verified Images Flag : {stats[2]} / 500") print("=" * 65) conn.close() if __name__ == "__main__": main()