fediversion/backend/import_setlists_direct.py
fullsizemalt b4cddf41ea feat: Initialize Fediversion multi-band platform
- Fork elmeg-demo codebase for multi-band support
- Add data importer infrastructure with base class
- Create band-specific importers:
  - phish.py: Phish.net API v5
  - grateful_dead.py: Grateful Stats API
  - setlistfm.py: Dead & Company, Billy Strings (Setlist.fm)
- Add spec-kit configuration for Gemini
- Update README with supported bands and architecture
2025-12-28 12:39:28 -08:00

167 lines
5.8 KiB
Python

"""
Direct setlist import - bypasses broken show_map logic
Imports setlists by matching dates directly
"""
import requests
import time
from datetime import datetime
from sqlmodel import Session, select, func
from database import engine
from models import Show, Song, Performance
from slugify import generate_slug
BASE_URL = "https://elgoose.net/api/v2"
def fetch_json(endpoint, params=None):
"""Fetch JSON from El Goose API"""
url = f"{BASE_URL}/{endpoint}.json"
try:
response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
data = response.json()
if data.get('error') == 1:
return None
return data.get('data', [])
except Exception as e:
print(f"Error fetching {endpoint}: {e}")
return None
def main():
print("=" * 60)
print("DIRECT SETLIST IMPORTER")
print("=" * 60)
with Session(engine) as session:
# Build date -> show_id mapping from our database
print("\n1. Building date->show mapping from database...")
shows = session.exec(select(Show)).all()
date_to_show = {}
for show in shows:
date_str = show.date.strftime('%Y-%m-%d')
date_to_show[date_str] = show.id
print(f" Found {len(date_to_show)} shows in database")
# Build song title -> song_id mapping
print("\n2. Building song mappings from database...")
songs = session.exec(select(Song)).all()
song_title_to_id = {s.title.lower(): s.id for s in songs}
print(f" Found {len(song_title_to_id)} songs in database")
# Fetch setlists from ElGoose
print("\n3. Fetching setlists from ElGoose API...")
page = 1
total_added = 0
total_skipped = 0
while True:
print(f" Page {page}...", end="", flush=True)
data = fetch_json("setlists", {"page": page})
if not data:
print(" Done.")
break
added_this_page = 0
for perf in data:
# Get the show date from the setlist item
show_date = perf.get('showdate')
song_name = perf.get('songname', '').lower()
if not show_date or not song_name:
total_skipped += 1
continue
# Find our show by date
our_show_id = date_to_show.get(show_date)
if not our_show_id:
total_skipped += 1
continue
# Find our song by title
our_song_id = song_title_to_id.get(song_name)
if not our_song_id:
total_skipped += 1
continue
position = perf.get('position', 0)
# Check if performance already exists
existing = session.exec(
select(Performance).where(
Performance.show_id == our_show_id,
Performance.song_id == our_song_id,
Performance.position == position
)
).first()
if existing:
continue
# Map setnumber
set_val = str(perf.get('setnumber', '1'))
if set_val.isdigit():
set_name = f"Set {set_val}"
elif set_val.lower() == 'e':
set_name = "Encore"
elif set_val.lower() == 'e2':
set_name = "Encore 2"
elif set_val.lower() == 's':
set_name = "Soundcheck"
else:
set_name = f"Set {set_val}"
# Create performance
new_perf = Performance(
show_id=our_show_id,
song_id=our_song_id,
position=position,
set_name=set_name,
segue=bool(perf.get('segue', 0)),
notes=perf.get('footnote')
)
session.add(new_perf)
added_this_page += 1
total_added += 1
session.commit()
print(f" added {added_this_page} performances")
if page > 500: # Safety limit
print(" Safety limit reached")
break
page += 1
time.sleep(0.1) # Be nice to the API
# Generate slugs for all performances
print("\n4. Generating slugs for performances...")
perfs_without_slugs = session.exec(
select(Performance).where(Performance.slug == None)
).all()
for perf in perfs_without_slugs:
if perf.song and perf.show:
song_slug = perf.song.slug or generate_slug(perf.song.title)
date_str = perf.show.date.strftime('%Y-%m-%d')
perf.slug = f"{song_slug}-{date_str}"
session.commit()
print(f" Generated {len(perfs_without_slugs)} slugs")
# Final count
total_perfs = session.exec(select(func.count(Performance.id))).one()
shows_with_perfs = session.exec(
select(func.count(func.distinct(Performance.show_id)))
).one()
print("\n" + "=" * 60)
print("IMPORT COMPLETE!")
print("=" * 60)
print(f"\nStats:")
print(f" • Added: {total_added} new performances")
print(f" • Skipped: {total_skipped} (no match)")
print(f" • Total performances: {total_perfs}")
print(f" • Shows with setlists: {shows_with_perfs}")
if __name__ == "__main__":
main()