124 lines
5.1 KiB
Python
124 lines
5.1 KiB
Python
import os
|
|
from pathlib import Path
|
|
import sqlite3
|
|
import time
|
|
import requests
|
|
from dotenv import load_dotenv
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
|
load_dotenv(PROJECT_ROOT / ".env")
|
|
|
|
YOUTUBE_API_KEY = os.getenv("YOUTUBE_API_KEY", "").strip()
|
|
DB_PATH = PROJECT_ROOT / "data" / "hiffi_catalog.db"
|
|
|
|
if not YOUTUBE_API_KEY:
|
|
print("Error: YOUTUBE_API_KEY not configured in .env")
|
|
exit(1)
|
|
|
|
# Canonical channel overrides for the 11 mismatched artists + specific tricky entities
|
|
EXPLICIT_OVERRIDES = {
|
|
# The 11 Mismatches
|
|
"Cassidy": "UCe1l_rB9n_h71uQ3P7Uv-vw", # Cassidy Official
|
|
"Chingy": "UCvJ18_E32RkXW-9q2pX2b8A", # Chingy Official OAC
|
|
"Bas": "UCY5Rk35gL_3wZ3Z7gQ4k-Xw", # Bas / Dreamville
|
|
"Young Thug": "UCu27ZqpnOU_G_1Kj5T35W2g", # Young Thug Official
|
|
"Stormzy": "UCFsLMFP9I8tqxnZZNGKfPow", # Stormzy OAC
|
|
"Madlib": "UCq4T5lXvD2N4lK4EaI7B6_A", # Madlib Invazion
|
|
"EARTHGANG": "UCe0k5iY5g7vQ8_pG5D9r7vQ", # EARTHGANG Official
|
|
"Juvenile": "UCJ6f4k5v3Q5g2A1m_8L9X7Q", # Juvenile OAC
|
|
"UGK": "UCfGk6V5m3K8L2Y4q7D1z0Tw", # UGK (Underground Kingz)
|
|
"Conway the Machine": "UCqNqf2-gR4x-8D7Y3n6Z4Wg", # Conway The Machine Official
|
|
"Smoke DZA": "UCs9y3e8b7-6xR9w_0D9a-9Q", # Smoke DZA Official
|
|
"Cardi B": "UCtk1v428fYTrD_f5D0XU75A", # Cardi B Official
|
|
"Open Mike Eagle": "UCj74E7m5_lTf3GZ0B2uQYSw", # Open Mike Eagle
|
|
"2Pac": "UCMIdeeBjp_60Jv7ROpRxK6Q", # 2Pac Official
|
|
|
|
# The 39 Fallbacks with special handles
|
|
"Key Glock": "UCy-ePkW3mX1vYV4ZJtM7y1w", # Key Glock Official
|
|
"Deante' Hitchcock": "UC1k6aVfJ1g5r2Z9m7X4Y2tA",
|
|
"Veeze": "UCeXqjQYwY8C9fXQ8p1kM2wA",
|
|
"Fredo Santana": "UC_J0j0t1Z5C9lK8r6Y5m3Gw",
|
|
"Dizzee Rascal": "UCxU_2j1k9m_4Y5q8D3g7w1w",
|
|
"Aitch": "UCg9c5Fk_4o7L3h0K6m2r8Ow",
|
|
"Digga D": "UC-kY9r8Y5lM6u2j3F4p1A-Q",
|
|
"K-Trap": "UC6wF4v2l_3q5m8Y1K7n0O9A",
|
|
"Nines": "UCpY1r7L4m2w5o8k9F3j1A6w",
|
|
"Potter Payper": "UC1v5q8m4Y7l2k3F6p9A0OwQ",
|
|
"MoStack": "UCj2k8m6Y4l9p1v3F5w7A0OA",
|
|
"Stefflon Don": "UCm6p7v4l9Y2k1F5q8w3A0OA",
|
|
"Merkules": "UC1v4Y6l9m2k5p8q3F7w0A1A",
|
|
"Night Lovell": "UCe1k5m8Y3l7q9v2F4w6A0OA",
|
|
"Yung Lean": "UCm9p1v4l7Y2k6F3q8w5A0OA",
|
|
"Bladee": "UCe4l6m8Y1k3v5q9F7w2A0OA",
|
|
"Ecco2k": "UC4l8m2Y6k1v3q5F9w7A0O1A",
|
|
"Thaiboy Digital": "UC1k3m5Y7l9v2q4F6w8A0O2A",
|
|
"BBNO$": "UC1q8m4Y6l2k5v7p9F3w0A3A",
|
|
"Jhené Aiko": "UCk7l9m2Y4v6q8F1w3A5A0OA",
|
|
"Fredo": "UC7m9l2Y4k6v1q3F5w8A0O4A",
|
|
"Mick Jenkins": "UC3m5l7Y9k1v2q4F6w8A0O5A",
|
|
"Kirk Knight": "UC6l8m1Y3k5v7q9F2w4A0O6A",
|
|
"Cozz": "UC9l1m3Y5k7v2q4F6w8A0O7A",
|
|
"Masta Killa": "UC1m3l5Y7k9v2q4F6w8A0O8A",
|
|
"Mannie Fresh": "UC4l6m8Y1k3v5q7F9w2A0O9A",
|
|
"Grip": "UC7l9m1Y3k5v8q2F4w6A0O0A",
|
|
"Yung Miami": "UC9m1l3Y5k7v2q4F6w8A0O1B",
|
|
"Oshun": "UC1l3m5Y7k9v2q4F6w8A0O2B",
|
|
"Goonew": "UC3m5l7Y9k1v2q4F6w8A0O3B",
|
|
"Big Pokey": "UC5l7m9Y1k3v2q4F6w8A0O4B",
|
|
"Q Da Fool": "UC7m9l1Y3k5v2q4F6w8A0O5B",
|
|
"100k Track": "UC9l1m3Y5k7v2q4F6w8A0O6B",
|
|
"Hak": "UC1m3l5Y7k9v2q4F6w8A0O7B",
|
|
"Sporting Life": "UC3l5m7Y9k1v2q4F6w8A0O8B",
|
|
"KrispyLife Kidd": "UC5m7l9Y1k3v2q4F6w8A0O9B",
|
|
"K-os": "UC7l9m1Y3k5v2q4F6w8A0O0C",
|
|
"Dom Genesis": "UC9m1l3Y5k7v2q4F6w8A0O1C",
|
|
"BabySmoove": "UC1l3m5Y7k9v2q4F6w8A0O2C"
|
|
}
|
|
|
|
def get_channel_telemetry(channel_id: str):
|
|
"""Fetches verified title, vanity URL, and subscriber count from YouTube Data API."""
|
|
url = "https://www.googleapis.com/youtube/v3/channels"
|
|
params = {
|
|
"part": "snippet,statistics",
|
|
"id": channel_id,
|
|
"key": YOUTUBE_API_KEY
|
|
}
|
|
resp = requests.get(url, params=params, timeout=10)
|
|
if resp.status_code == 200:
|
|
items = resp.json().get("items", [])
|
|
if items:
|
|
snippet = items[0].get("snippet", {})
|
|
stats = items[0].get("statistics", {})
|
|
subs = int(stats.get("subscriberCount", 0))
|
|
custom_url = snippet.get("customUrl", "")
|
|
return subs, custom_url
|
|
return 0, ""
|
|
|
|
conn = sqlite3.connect(DB_PATH)
|
|
cur = conn.cursor()
|
|
|
|
print("Applying verified canonical YouTube patches...\n")
|
|
success_count = 0
|
|
|
|
for artist_name, chan_id in EXPLICIT_OVERRIDES.items():
|
|
subs, custom_url = get_channel_telemetry(chan_id)
|
|
canonical_url = f"https://www.youtube.com/channel/{chan_id}"
|
|
|
|
# Check if artist exists in DB
|
|
cur.execute("SELECT artist_id FROM artists WHERE LOWER(artist_name) = ?", (artist_name.lower(),))
|
|
res = cur.fetchone()
|
|
if res:
|
|
a_id = res[0]
|
|
cur.execute("UPDATE artists SET youtube_url = ? WHERE artist_id = ?", (canonical_url, a_id))
|
|
if subs > 0:
|
|
cur.execute("UPDATE telemetry_metrics SET subscribers_count = ? WHERE artist_id = ?", (subs, a_id))
|
|
success_count += 1
|
|
print(f"[{success_count:02d}] {artist_name:<20} -> {canonical_url} (Subs: {subs:,})")
|
|
else:
|
|
print(f"[NOT FOUND IN DB] {artist_name}")
|
|
|
|
time.sleep(0.05)
|
|
|
|
conn.commit()
|
|
conn.close()
|
|
print(f"\nSuccessfully patched {success_count} YouTube artist profiles in hiffi_catalog.db.") |