""" Migration: Add web authentication support to players table Adds: - username column (unique, nullable for existing Telegram-only accounts) - password_hash column (nullable for Telegram-only accounts) - id auto-increment column for web users (telegram_id becomes nullable) Run this migration before starting the API service. """ import asyncio import os from sqlalchemy.ext.asyncio import create_async_engine from sqlalchemy import text DB_USER = os.getenv("POSTGRES_USER") DB_PASS = os.getenv("POSTGRES_PASSWORD") DB_NAME = os.getenv("POSTGRES_DB") DB_HOST = os.getenv("POSTGRES_HOST", "localhost") DB_PORT = os.getenv("POSTGRES_PORT", "5432") DATABASE_URL = f"postgresql+psycopg://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}" async def migrate(): engine = create_async_engine(DATABASE_URL) async with engine.begin() as conn: print("Starting migration: Add web authentication support...") # Check if columns already exist result = await conn.execute(text(""" SELECT column_name FROM information_schema.columns WHERE table_name='players' AND column_name IN ('id', 'username', 'password_hash') """)) existing_columns = {row[0] for row in result} if 'id' not in existing_columns: print("Adding id column...") await conn.execute(text(""" ALTER TABLE players ADD COLUMN id SERIAL UNIQUE """)) else: print("✓ id column already exists") if 'username' not in existing_columns: print("Adding username column...") await conn.execute(text(""" ALTER TABLE players ADD COLUMN username VARCHAR(50) UNIQUE """)) else: print("✓ username column already exists") if 'password_hash' not in existing_columns: print("Adding password_hash column...") await conn.execute(text(""" ALTER TABLE players ADD COLUMN password_hash VARCHAR(255) """)) else: print("✓ password_hash column already exists") # Note: telegram_id stays as primary key for backwards compatibility # Web users will use the 'id' column instead print("✓ Keeping telegram_id as primary key for Telegram users") # Add constraint: either telegram_id or username must be present print("Adding check constraint...") try: await conn.execute(text(""" ALTER TABLE players ADD CONSTRAINT players_auth_check CHECK (telegram_id IS NOT NULL OR username IS NOT NULL) """)) print("✓ Check constraint added") except Exception as e: if "already exists" in str(e): print("✓ Check constraint already exists") else: raise print("\n✅ Migration completed successfully!") print("\nNote: Telegram users will continue to use telegram_id as primary key") print(" Web users will use the auto-incrementing id column") await engine.dispose() if __name__ == "__main__": asyncio.run(migrate())