feat: finalize root api.py with X-Auth-Secret auth security and clean pure sales cohort
This commit is contained in:
1 parent
85e6395770
commit
78a46a8dbe
629 files changed
+123965
-755
No files matched your search
@@ -0,0 +1,116 @@
|
||||
"""
|
||||
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()
|
||||
Reference in new issue
Block a user