feat: add historical backfill with --init CLI and episode numbering
Adds a --init mode that seeds the database with past shows from a given anchor episode/date forward, batch-fetching likes from SoundCloud and partitioning them into weekly buckets. Episode numbers are tracked in the shows table and auto-incremented by the poller for new shows. Includes full API documentation (docs/api.md) and updated README. Made-with: Cursor
This commit is contained in:
@@ -20,7 +20,8 @@ CREATE TABLE IF NOT EXISTS shows (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
week_start TEXT NOT NULL,
|
||||
week_end TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL
|
||||
created_at TEXT NOT NULL,
|
||||
episode_number INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS show_tracks (
|
||||
@@ -49,6 +50,11 @@ class Database:
|
||||
def initialize(self) -> None:
|
||||
conn = self._connect()
|
||||
conn.executescript(SCHEMA)
|
||||
try:
|
||||
conn.execute("ALTER TABLE shows ADD COLUMN episode_number INTEGER")
|
||||
conn.commit()
|
||||
except sqlite3.OperationalError:
|
||||
pass
|
||||
conn.close()
|
||||
|
||||
def upsert_track(self, track: Track) -> None:
|
||||
@@ -102,26 +108,36 @@ class Database:
|
||||
)
|
||||
|
||||
def get_or_create_show(
|
||||
self, week_start: datetime, week_end: datetime
|
||||
self,
|
||||
week_start: datetime,
|
||||
week_end: datetime,
|
||||
episode_number: int | None = None,
|
||||
) -> Show:
|
||||
conn = self._connect()
|
||||
row = conn.execute(
|
||||
"SELECT id, week_start, week_end, created_at FROM shows "
|
||||
"SELECT id, week_start, week_end, created_at, episode_number FROM shows "
|
||||
"WHERE week_start = ? AND week_end = ?",
|
||||
(week_start.isoformat(), week_end.isoformat()),
|
||||
).fetchone()
|
||||
if row is not None:
|
||||
if episode_number is not None and row["episode_number"] != episode_number:
|
||||
conn.execute(
|
||||
"UPDATE shows SET episode_number = ? WHERE id = ?",
|
||||
(episode_number, row["id"]),
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return Show(
|
||||
id=row["id"],
|
||||
week_start=datetime.fromisoformat(row["week_start"]),
|
||||
week_end=datetime.fromisoformat(row["week_end"]),
|
||||
created_at=datetime.fromisoformat(row["created_at"]),
|
||||
episode_number=episode_number if episode_number is not None else row["episode_number"],
|
||||
)
|
||||
now = datetime.now(timezone.utc).isoformat()
|
||||
cursor = conn.execute(
|
||||
"INSERT INTO shows (week_start, week_end, created_at) VALUES (?, ?, ?)",
|
||||
(week_start.isoformat(), week_end.isoformat(), now),
|
||||
"INSERT INTO shows (week_start, week_end, created_at, episode_number) VALUES (?, ?, ?, ?)",
|
||||
(week_start.isoformat(), week_end.isoformat(), now, episode_number),
|
||||
)
|
||||
conn.commit()
|
||||
show_id = cursor.lastrowid
|
||||
@@ -131,6 +147,7 @@ class Database:
|
||||
week_start=week_start,
|
||||
week_end=week_end,
|
||||
created_at=datetime.fromisoformat(now),
|
||||
episode_number=episode_number,
|
||||
)
|
||||
|
||||
def get_show_tracks(self, show_id: int) -> list[dict]:
|
||||
@@ -203,9 +220,9 @@ class Database:
|
||||
conn = self._connect()
|
||||
rows = conn.execute(
|
||||
"""
|
||||
SELECT id, week_start, week_end, created_at
|
||||
SELECT id, week_start, week_end, created_at, episode_number
|
||||
FROM shows
|
||||
ORDER BY created_at DESC
|
||||
ORDER BY week_start DESC
|
||||
LIMIT ? OFFSET ?
|
||||
""",
|
||||
(limit, offset),
|
||||
@@ -217,10 +234,28 @@ class Database:
|
||||
week_start=datetime.fromisoformat(row["week_start"]),
|
||||
week_end=datetime.fromisoformat(row["week_end"]),
|
||||
created_at=datetime.fromisoformat(row["created_at"]),
|
||||
episode_number=row["episode_number"],
|
||||
)
|
||||
for row in rows
|
||||
]
|
||||
|
||||
def get_latest_episode_number(self) -> int | None:
|
||||
conn = self._connect()
|
||||
row = conn.execute(
|
||||
"SELECT MAX(episode_number) as max_ep FROM shows WHERE episode_number IS NOT NULL"
|
||||
).fetchone()
|
||||
conn.close()
|
||||
return row["max_ep"] if row else None
|
||||
|
||||
def update_show_episode_number(self, show_id: int, episode_number: int) -> None:
|
||||
conn = self._connect()
|
||||
conn.execute(
|
||||
"UPDATE shows SET episode_number = ? WHERE id = ?",
|
||||
(episode_number, show_id),
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def has_track_in_show(self, show_id: int, track_id: int) -> bool:
|
||||
conn = self._connect()
|
||||
row = conn.execute(
|
||||
|
||||
Reference in New Issue
Block a user