new media player functionality
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
+41
-1
@@ -11,6 +11,45 @@ from app.user_models import User
|
||||
from app.api import events, auth, station_config, history, team, community, shows, storage, underwriters
|
||||
|
||||
|
||||
def _migrate_add_missing_columns(sync_conn):
|
||||
"""Add missing columns to existing tables (startup migration — no Alembic).
|
||||
|
||||
Handles both SQLite and PostgreSQL. Idempotent: skips columns that already exist.
|
||||
Receives a sync SQLAlchemy Connection from engine.run_sync().
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
|
||||
# Column definitions: (table, name, type, default)
|
||||
pending = [
|
||||
("station_config", "stream_url", sa.String(500), ""),
|
||||
("station_config", "stream_metadata_url", sa.String(500), ""),
|
||||
]
|
||||
|
||||
# Determine dialect
|
||||
dialect = sync_conn.dialect.name # "sqlite" | "postgresql"
|
||||
|
||||
inspector = sa.inspect(sync_conn)
|
||||
|
||||
for table_name, col_name, col_type, default in pending:
|
||||
# Check if column already exists
|
||||
existing = inspector.get_columns(table_name)
|
||||
if any(c["name"] == col_name for c in existing):
|
||||
continue
|
||||
|
||||
print(f" → Migrating: adding column {table_name}.{col_name}")
|
||||
|
||||
if dialect == "sqlite":
|
||||
sync_conn.execute(
|
||||
sa.text(f'ALTER TABLE {table_name} ADD COLUMN "{col_name}" TEXT NOT NULL DEFAULT "{default}"')
|
||||
)
|
||||
else:
|
||||
sync_conn.execute(
|
||||
sa.text(f'ALTER TABLE {table_name} ADD COLUMN "{col_name}" VARCHAR(500) NOT NULL DEFAULT "{default}"')
|
||||
)
|
||||
|
||||
print(f" ✓ Added {table_name}.{col_name}")
|
||||
|
||||
|
||||
async def _ensure_station_config(session):
|
||||
"""Ensure the singleton station config row exists (idempotent)."""
|
||||
result = await session.execute(
|
||||
@@ -28,9 +67,10 @@ async def _ensure_station_config(session):
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
# Create tables on startup
|
||||
# Create tables on startup, then patch any missing columns
|
||||
async with engine.begin() as conn:
|
||||
await conn.run_sync(Base.metadata.create_all)
|
||||
await conn.run_sync(_migrate_add_missing_columns)
|
||||
|
||||
# Auto-seed if database is empty
|
||||
async with async_session() as session:
|
||||
|
||||
@@ -94,6 +94,10 @@ class StationConfig(Base):
|
||||
# Donation
|
||||
donation_url = Column(String(500), nullable=False, default="")
|
||||
|
||||
# Stream
|
||||
stream_url = Column(String(500), nullable=False, default="")
|
||||
stream_metadata_url = Column(String(500), nullable=False, default="")
|
||||
|
||||
|
||||
class HistoryEntry(Base):
|
||||
__tablename__ = "history_entries"
|
||||
|
||||
@@ -73,6 +73,8 @@ class StationConfigResponse(BaseModel):
|
||||
email: str
|
||||
website: str
|
||||
donation_url: str
|
||||
stream_url: str
|
||||
stream_metadata_url: str
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
@@ -95,6 +97,8 @@ class StationConfigUpdate(BaseModel):
|
||||
email: Optional[str] = None
|
||||
website: Optional[str] = None
|
||||
donation_url: Optional[str] = None
|
||||
stream_url: Optional[str] = None
|
||||
stream_metadata_url: Optional[str] = None
|
||||
|
||||
|
||||
# ── HistoryEntry ──────────────────────────────────────────
|
||||
|
||||
@@ -212,6 +212,8 @@ STATION_CONFIG: dict = {
|
||||
"email": "hello@kmountainflower.org",
|
||||
"website": "kmountainflower.org",
|
||||
"donation_url": "",
|
||||
"stream_url": "",
|
||||
"stream_metadata_url": "",
|
||||
}
|
||||
|
||||
HISTORY_ENTRIES: list[dict] = [
|
||||
|
||||
Reference in New Issue
Block a user