fediversion/backend/alembic/versions/65c515b4722a_add_slugs.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

213 lines
11 KiB
Python

"""Add slugs
Revision ID: 65c515b4722a
Revises: e50a60c5d343
Create Date: 2025-12-21 20:24:07.968495
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import sqlmodel
# revision identifiers, used by Alembic.
revision: str = '65c515b4722a'
down_revision: Union[str, Sequence[str], None] = 'e50a60c5d343'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
# op.create_table('reaction',
# sa.Column('id', sa.Integer(), nullable=False),
# sa.Column('user_id', sa.Integer(), nullable=False),
# sa.Column('entity_type', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
# sa.Column('entity_id', sa.Integer(), nullable=False),
# sa.Column('emoji', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
# sa.Column('created_at', sa.DateTime(), nullable=False),
# sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
# sa.PrimaryKeyConstraint('id')
# )
# with op.batch_alter_table('reaction', schema=None) as batch_op:
# batch_op.create_index(batch_op.f('ix_reaction_entity_id'), ['entity_id'], unique=False)
# batch_op.create_index(batch_op.f('ix_reaction_entity_type'), ['entity_type'], unique=False)
# op.create_table('chasesong',
# sa.Column('id', sa.Integer(), nullable=False),
# sa.Column('user_id', sa.Integer(), nullable=False),
# sa.Column('song_id', sa.Integer(), nullable=False),
# sa.Column('priority', sa.Integer(), nullable=False),
# sa.Column('notes', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
# sa.Column('created_at', sa.DateTime(), nullable=False),
# sa.Column('caught_at', sa.DateTime(), nullable=True),
# sa.Column('caught_show_id', sa.Integer(), nullable=True),
# sa.ForeignKeyConstraint(['caught_show_id'], ['show.id'], ),
# sa.ForeignKeyConstraint(['song_id'], ['song.id'], ),
# sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
# sa.PrimaryKeyConstraint('id')
# )
# with op.batch_alter_table('chasesong', schema=None) as batch_op:
# batch_op.create_index(batch_op.f('ix_chasesong_song_id'), ['song_id'], unique=False)
# batch_op.create_index(batch_op.f('ix_chasesong_user_id'), ['user_id'], unique=False)
# with op.batch_alter_table('badge', schema=None) as batch_op:
# batch_op.add_column(sa.Column('tier', sqlmodel.sql.sqltypes.AutoString(), nullable=False))
# batch_op.add_column(sa.Column('category', sqlmodel.sql.sqltypes.AutoString(), nullable=False))
# batch_op.add_column(sa.Column('xp_reward', sa.Integer(), nullable=False))
with op.batch_alter_table('comment', schema=None) as batch_op:
batch_op.add_column(sa.Column('parent_id', sa.Integer(), nullable=True))
batch_op.create_foreign_key('fk_comment_parent_id', 'comment', ['parent_id'], ['id'])
with op.batch_alter_table('performance', schema=None) as batch_op:
batch_op.add_column(sa.Column('slug', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.add_column(sa.Column('track_url', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.add_column(sa.Column('youtube_link', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.create_index(batch_op.f('ix_performance_slug'), ['slug'], unique=True)
with op.batch_alter_table('rating', schema=None) as batch_op:
batch_op.add_column(sa.Column('performance_id', sa.Integer(), nullable=True))
batch_op.add_column(sa.Column('venue_id', sa.Integer(), nullable=True))
batch_op.add_column(sa.Column('tour_id', sa.Integer(), nullable=True))
batch_op.alter_column('score',
existing_type=sa.INTEGER(),
type_=sa.Float(),
existing_nullable=False)
batch_op.create_foreign_key('fk_rating_tour_id', 'tour', ['tour_id'], ['id'])
batch_op.create_foreign_key('fk_rating_performance_id', 'performance', ['performance_id'], ['id'])
batch_op.create_foreign_key('fk_rating_venue_id', 'venue', ['venue_id'], ['id'])
with op.batch_alter_table('review', schema=None) as batch_op:
batch_op.alter_column('score',
existing_type=sa.INTEGER(),
type_=sa.Float(),
existing_nullable=False)
with op.batch_alter_table('show', schema=None) as batch_op:
batch_op.add_column(sa.Column('slug', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.add_column(sa.Column('bandcamp_link', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.add_column(sa.Column('nugs_link', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.add_column(sa.Column('youtube_link', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.create_index(batch_op.f('ix_show_slug'), ['slug'], unique=True)
with op.batch_alter_table('song', schema=None) as batch_op:
batch_op.add_column(sa.Column('slug', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.add_column(sa.Column('youtube_link', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.create_index(batch_op.f('ix_song_slug'), ['slug'], unique=True)
with op.batch_alter_table('tour', schema=None) as batch_op:
batch_op.add_column(sa.Column('slug', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.create_index(batch_op.f('ix_tour_slug'), ['slug'], unique=True)
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.add_column(sa.Column('xp', sa.Integer(), nullable=False, server_default="0"))
batch_op.add_column(sa.Column('level', sa.Integer(), nullable=False, server_default="1"))
batch_op.add_column(sa.Column('streak_days', sa.Integer(), nullable=False, server_default="0"))
batch_op.add_column(sa.Column('last_activity', sa.DateTime(), nullable=True))
batch_op.add_column(sa.Column('custom_title', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.add_column(sa.Column('title_color', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.add_column(sa.Column('flair', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.add_column(sa.Column('is_early_adopter', sa.Boolean(), nullable=False, server_default="0"))
batch_op.add_column(sa.Column('is_supporter', sa.Boolean(), nullable=False, server_default="0"))
batch_op.add_column(sa.Column('joined_at', sa.DateTime(), nullable=False, server_default=sa.func.now()))
batch_op.add_column(sa.Column('email_verified', sa.Boolean(), nullable=False, server_default="0"))
batch_op.add_column(sa.Column('verification_token', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.add_column(sa.Column('verification_token_expires', sa.DateTime(), nullable=True))
batch_op.add_column(sa.Column('reset_token', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.add_column(sa.Column('reset_token_expires', sa.DateTime(), nullable=True))
with op.batch_alter_table('venue', schema=None) as batch_op:
batch_op.add_column(sa.Column('slug', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
batch_op.create_index(batch_op.f('ix_venue_slug'), ['slug'], unique=True)
# ### end Alembic commands ###
def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('venue', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_venue_slug'))
batch_op.drop_column('slug')
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.drop_column('reset_token_expires')
batch_op.drop_column('reset_token')
batch_op.drop_column('verification_token_expires')
batch_op.drop_column('verification_token')
batch_op.drop_column('email_verified')
batch_op.drop_column('joined_at')
batch_op.drop_column('is_supporter')
batch_op.drop_column('is_early_adopter')
batch_op.drop_column('flair')
batch_op.drop_column('title_color')
batch_op.drop_column('custom_title')
batch_op.drop_column('last_activity')
batch_op.drop_column('streak_days')
batch_op.drop_column('level')
batch_op.drop_column('xp')
with op.batch_alter_table('tour', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_tour_slug'))
batch_op.drop_column('slug')
with op.batch_alter_table('song', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_song_slug'))
batch_op.drop_column('youtube_link')
batch_op.drop_column('slug')
with op.batch_alter_table('show', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_show_slug'))
batch_op.drop_column('youtube_link')
batch_op.drop_column('nugs_link')
batch_op.drop_column('bandcamp_link')
batch_op.drop_column('slug')
with op.batch_alter_table('review', schema=None) as batch_op:
batch_op.alter_column('score',
existing_type=sa.Float(),
type_=sa.INTEGER(),
existing_nullable=False)
with op.batch_alter_table('rating', schema=None) as batch_op:
batch_op.drop_constraint(None, type_='foreignkey')
batch_op.drop_constraint(None, type_='foreignkey')
batch_op.drop_constraint(None, type_='foreignkey')
batch_op.alter_column('score',
existing_type=sa.Float(),
type_=sa.INTEGER(),
existing_nullable=False)
batch_op.drop_column('tour_id')
batch_op.drop_column('venue_id')
batch_op.drop_column('performance_id')
with op.batch_alter_table('performance', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_performance_slug'))
batch_op.drop_column('youtube_link')
batch_op.drop_column('track_url')
batch_op.drop_column('slug')
with op.batch_alter_table('comment', schema=None) as batch_op:
batch_op.drop_constraint(None, type_='foreignkey')
batch_op.drop_column('parent_id')
with op.batch_alter_table('badge', schema=None) as batch_op:
batch_op.drop_column('xp_reward')
batch_op.drop_column('category')
batch_op.drop_column('tier')
with op.batch_alter_table('chasesong', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_chasesong_user_id'))
batch_op.drop_index(batch_op.f('ix_chasesong_song_id'))
op.drop_table('chasesong')
with op.batch_alter_table('reaction', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_reaction_entity_type'))
batch_op.drop_index(batch_op.f('ix_reaction_entity_id'))
op.drop_table('reaction')
# ### end Alembic commands ###