""" Migration: Add Steam support and remove Telegram - Remove telegram_id column - Add steam_id column - Add email column (required for web users) - Add premium_expires_at column (NULL = premium forever, timestamp = expires at that time) - Add account_type ENUM ('web', 'steam') """ import asyncio import sys import os # Add parent directory to path sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from api.database import engine, metadata from sqlalchemy import text async def migrate(): """Run migration""" print("šŸ”„ Starting Steam support migration...") async with engine.begin() as conn: # 1. Add new columns print("šŸ“ Adding new columns...") try: await conn.execute(text(""" ALTER TABLE players ADD COLUMN steam_id VARCHAR(255) UNIQUE, ADD COLUMN email VARCHAR(255), ADD COLUMN premium_expires_at TIMESTAMP, ADD COLUMN account_type VARCHAR(20) DEFAULT 'web' """)) print(" āœ… Added: steam_id, email, premium_expires_at, account_type") except Exception as e: if "already exists" in str(e).lower(): print(" āš ļø Columns already exist, skipping...") else: raise # 2. Create index on steam_id for fast lookups print("šŸ“ Creating indexes...") try: await conn.execute(text(""" CREATE INDEX IF NOT EXISTS idx_players_steam_id ON players(steam_id) """)) await conn.execute(text(""" CREATE INDEX IF NOT EXISTS idx_players_email ON players(email) """)) print(" āœ… Created indexes on steam_id and email") except Exception as e: print(f" āš ļø Index creation warning: {e}") # 3. Set account_type for existing users print("šŸ“ Setting account_type for existing users...") result = await conn.execute(text(""" UPDATE players SET account_type = CASE WHEN telegram_id IS NOT NULL THEN 'telegram' ELSE 'web' END WHERE account_type IS NULL OR account_type = 'web' """)) print(f" āœ… Updated {result.rowcount} existing users") # 4. Check if telegram_id column exists before trying to drop it print("šŸ“ Checking for telegram_id column...") result = await conn.execute(text(""" SELECT column_name FROM information_schema.columns WHERE table_name = 'players' AND column_name = 'telegram_id' """)) has_telegram = result.fetchone() is not None if has_telegram: # Count how many telegram users we have result = await conn.execute(text(""" SELECT COUNT(*) FROM players WHERE telegram_id IS NOT NULL """)) telegram_count = result.fetchone()[0] if telegram_count > 0: print(f" āš ļø Found {telegram_count} Telegram users") print(f" āš ļø Telegram support is deprecated, but keeping data for now") print(f" ā„¹ļø To fully remove: DROP COLUMN telegram_id (manual step)") else: print(" āœ… No Telegram users found") # Safely drop the column if no users try: await conn.execute(text("ALTER TABLE players DROP COLUMN telegram_id")) print(" āœ… Dropped telegram_id column") except Exception as e: print(f" āš ļø Could not drop telegram_id: {e}") else: print(" āœ… telegram_id column already removed") # 5. Add CHECK constraint for account_type print("šŸ“ Adding constraints...") try: await conn.execute(text(""" ALTER TABLE players ADD CONSTRAINT check_account_type CHECK (account_type IN ('web', 'steam', 'telegram')) """)) print(" āœ… Added account_type constraint") except Exception as e: if "already exists" in str(e).lower(): print(" āš ļø Constraint already exists") else: print(f" āš ļø Could not add constraint: {e}") # 6. Make email required for web users (but allow NULL for steam/legacy) # This is a soft requirement - we'll enforce it in the application layer print("āœ… Migration completed successfully!") print("\nšŸ“‹ Summary:") print(" - Added steam_id column (unique, indexed)") print(" - Added email column (required for web registration)") print(" - Added premium_expires_at (NULL = premium, timestamp = free trial)") print(" - Added account_type ('web', 'steam', 'telegram')") print(" - Kept telegram_id for existing users (deprecated)") print("\nšŸ’” Next steps:") print(" 1. Update registration endpoint to require email") print(" 2. Implement Steam authentication flow") print(" 3. Add premium tier restrictions") print(" 4. Migrate telegram users or archive their data") if __name__ == "__main__": asyncio.run(migrate())