Files
mtgonline/backend/setup_db.py
T

224 lines
8.2 KiB
Python

"""
Database initialization script for MTG Online backend.
Creates all necessary tables matching the SQLAlchemy ORM models
for both databases.
"""
import asyncio
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy import text
from app.core.settings import get_settings
async def setup_mtg_online_database():
"""Create tables for the mtgonline database."""
settings = get_settings()
engine = create_async_engine(settings.MTGO_DATABASE_URL)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async with async_session() as session:
# Create tables
tables = [
"""
CREATE TABLE IF NOT EXISTS mtgonline_users (
id SERIAL PRIMARY KEY,
username VARCHAR(64) UNIQUE NOT NULL,
password_hash VARCHAR(128) NOT NULL,
salt VARCHAR(128) NOT NULL,
email VARCHAR(255),
country VARCHAR(2),
real_name VARCHAR(128),
avatar_bmp TEXT,
privlevel VARCHAR(50) DEFAULT 'User',
is_active BOOLEAN DEFAULT TRUE,
is_banned BOOLEAN DEFAULT FALSE,
ban_reason TEXT,
ban_ends TIMESTAMP,
vip_status INTEGER DEFAULT 0,
vip_expiry TIMESTAMP,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login TIMESTAMP
)
""",
"""
CREATE TABLE IF NOT EXISTS mtgonline_decklist_folders (
id SERIAL PRIMARY KEY,
owner_id INTEGER REFERENCES mtgonline_users(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
parent_id INTEGER REFERENCES mtgonline_decklist_folders(id) ON DELETE CASCADE,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""",
"""
CREATE TABLE IF NOT EXISTS mtgonline_decklist_files (
id SERIAL PRIMARY KEY,
folder_id INTEGER REFERENCES mtgonline_decklist_folders(id) ON DELETE CASCADE,
owner_id INTEGER REFERENCES mtgonline_users(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
format VARCHAR(50) DEFAULT 'native',
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""",
"""
CREATE TABLE IF NOT EXISTS mtgonline_rooms (
id SERIAL PRIMARY KEY,
name VARCHAR(100) UNIQUE NOT NULL,
description TEXT,
is_password_protected BOOLEAN DEFAULT FALSE,
password_hash VARCHAR(128),
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""",
"""
CREATE TABLE IF NOT EXISTS mtgonline_rooms_gametypes (
id SERIAL PRIMARY KEY,
room_id INTEGER REFERENCES mtgonline_rooms(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
description TEXT
)
""",
"""
CREATE TABLE IF NOT EXISTS mtgonline_bans (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES mtgonline_users(id) ON DELETE CASCADE,
server_id INTEGER,
reason TEXT NOT NULL,
moderators VARCHAR(255),
ip_address VARCHAR(45),
expiration_time TIMESTAMP,
active BOOLEAN DEFAULT TRUE,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""",
"""
CREATE TABLE IF NOT EXISTS mtgonline_log (
id SERIAL PRIMARY KEY,
room_id INTEGER REFERENCES mtgonline_rooms(id) ON DELETE CASCADE,
player_id INTEGER REFERENCES mtgonline_users(id) ON DELETE CASCADE,
message TEXT NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""",
"""
CREATE TABLE IF NOT EXISTS mtgonline_audit (
id SERIAL PRIMARY KEY,
admin_id INTEGER REFERENCES mtgonline_users(id) ON DELETE SET NULL,
action_type VARCHAR(50) NOT NULL,
target_user_id INTEGER REFERENCES mtgonline_users(id) ON DELETE SET NULL,
details TEXT,
ip_address VARCHAR(45),
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""",
]
for table_sql in tables:
await session.execute(text(table_sql))
# Create indexes
indexes = [
"CREATE INDEX IF NOT EXISTS idx_decks_owner ON mtgonline_decklist_files(owner_id);",
"CREATE INDEX IF NOT EXISTS idx_decks_folder ON mtgonline_decklist_files(folder_id);",
"CREATE INDEX IF NOT EXISTS idx_bans_active ON mtgonline_bans(active);",
"CREATE INDEX IF NOT EXISTS idx_log_timestamp ON mtgonline_log(timestamp);",
]
for idx_sql in indexes:
await session.execute(text(idx_sql))
print("✓ All mtgonline tables created")
await engine.dispose()
async def setup_mtg_data_database():
"""Create tables for the mtgdata database."""
settings = get_settings()
engine = create_async_engine(settings.MTG_DATABASE_URL)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async with async_session() as session:
# Create tables
tables = [
"""
CREATE TABLE IF NOT EXISTS mtg_sets (
id SERIAL PRIMARY KEY,
code VARCHAR(10) UNIQUE NOT NULL,
name VARCHAR(255),
type VARCHAR(100),
release_date DATE,
base_set_size INTEGER,
total_size INTEGER,
is_foil_only BOOLEAN,
is_non_foil_only BOOLEAN,
digital BOOLEAN,
icon_svg_url TEXT,
parent_code VARCHAR(10),
mtgo_code VARCHAR(10),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""",
"""
CREATE TABLE IF NOT EXISTS mtg_cards (
id SERIAL PRIMARY KEY,
set_id INTEGER REFERENCES mtg_sets(id) ON DELETE CASCADE,
name VARCHAR(255),
mana_cost VARCHAR(255),
type_line VARCHAR(255),
oracle_text TEXT,
power VARCHAR(50),
toughness VARCHAR(50),
rarity VARCHAR(50),
layout VARCHAR(50),
artist VARCHAR(255),
flavor_text TEXT,
numbers VARCHAR(100),
identifiers TEXT,
images TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""",
]
for table_sql in tables:
await session.execute(text(table_sql))
# Create indexes
indexes = [
"CREATE INDEX IF NOT EXISTS idx_mtg_cards_name ON mtg_cards(name);",
"CREATE INDEX IF NOT EXISTS idx_mtg_cards_type ON mtg_cards(type_line);",
"CREATE INDEX IF NOT EXISTS idx_mtg_cards_rarity ON mtg_cards(rarity);",
"CREATE INDEX IF NOT EXISTS idx_mtg_cards_set_id ON mtg_cards(set_id);",
]
for idx_sql in indexes:
await session.execute(text(idx_sql))
print("✓ All mtgdata tables created")
await engine.dispose()
async def main():
"""Main initialization function."""
print("MTG Online Database Initialization")
print("=" * 50)
# Setup mtgonline database
print("\nSetting up mtgonline database...")
await setup_mtg_online_database()
# Setup mtgdata database
print("\nSetting up mtgdata database...")
await setup_mtg_data_database()
print("\n✓ Database initialization complete!")
if __name__ == "__main__":
asyncio.run(main())