Files
Steam-Panel/app/database.py
T
2026-04-17 22:22:40 +03:00

201 lines
7.2 KiB
Python

import aiosqlite
from loguru import logger
from app.config import settings
import asyncio
_db: aiosqlite.Connection | None = None
_db_lock = asyncio.Lock()
SQL_CREATE_ACCOUNTS = """
CREATE TABLE IF NOT EXISTS accounts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
login TEXT NOT NULL,
password TEXT NOT NULL,
steam_id TEXT UNIQUE,
email TEXT,
email_password TEXT,
phone TEXT,
mafile_path TEXT,
shared_secret TEXT,
identity_secret TEXT,
proxy TEXT,
status TEXT NOT NULL DEFAULT 'unknown',
notes TEXT,
nickname TEXT,
avatar_url TEXT,
steam_level INTEGER,
auto_accept INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
"""
SQL_CREATE_PROXIES = """
CREATE TABLE IF NOT EXISTS proxies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
address TEXT NOT NULL UNIQUE,
protocol TEXT NOT NULL DEFAULT 'http',
is_alive INTEGER NOT NULL DEFAULT 1,
last_checked TEXT,
fail_count INTEGER NOT NULL DEFAULT 0
);
"""
SQL_CREATE_TASKS = """
CREATE TABLE IF NOT EXISTS tasks (
id TEXT PRIMARY KEY,
type TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
progress INTEGER NOT NULL DEFAULT 0,
total INTEGER NOT NULL DEFAULT 0,
result TEXT,
error TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
"""
SQL_CREATE_LOGPASS_ACCOUNTS = """
CREATE TABLE IF NOT EXISTS logpass_accounts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
login TEXT NOT NULL UNIQUE,
password TEXT NOT NULL,
steam_id TEXT,
proxy TEXT,
status TEXT NOT NULL DEFAULT 'unknown',
ban_status TEXT,
nickname TEXT,
steam_level INTEGER,
prime TEXT,
trophy TEXT,
behavior TEXT,
license TEXT,
notes TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
"""
SQL_CREATE_TOKEN_ACCOUNTS = """
CREATE TABLE IF NOT EXISTS token_accounts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
login TEXT,
token TEXT NOT NULL,
steam_id TEXT,
status TEXT NOT NULL DEFAULT 'unknown',
notes TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
"""
async def get_db() -> aiosqlite.Connection:
global _db
async with _db_lock:
if _db is None:
settings.data_dir.mkdir(parents=True, exist_ok=True)
_db = await aiosqlite.connect(str(settings.db_path))
_db.row_factory = aiosqlite.Row
await _db.execute("PRAGMA journal_mode=WAL")
await _db.execute("PRAGMA foreign_keys=ON")
await _init_tables(_db)
logger.info(f"Database connected: {settings.db_path}")
return _db
async def _init_tables(db: aiosqlite.Connection) -> None:
await db.execute(SQL_CREATE_ACCOUNTS)
await db.execute(SQL_CREATE_PROXIES)
await db.execute(SQL_CREATE_TASKS)
await db.execute(SQL_CREATE_LOGPASS_ACCOUNTS)
await db.execute(SQL_CREATE_TOKEN_ACCOUNTS)
await _migrate(db)
await db.commit()
async def _migrate(db: aiosqlite.Connection) -> None:
"""Add columns that may not exist in older DBs."""
cursor = await db.execute("PRAGMA table_info(accounts)")
cols = {row[1] for row in await cursor.fetchall()}
migrations = [
("nickname", "ALTER TABLE accounts ADD COLUMN nickname TEXT"),
("avatar_url", "ALTER TABLE accounts ADD COLUMN avatar_url TEXT"),
("steam_level", "ALTER TABLE accounts ADD COLUMN steam_level INTEGER"),
("auto_accept", "ALTER TABLE accounts ADD COLUMN auto_accept INTEGER NOT NULL DEFAULT 0"),
("ban_status", "ALTER TABLE accounts ADD COLUMN ban_status TEXT"),
("session_cookies", "ALTER TABLE accounts ADD COLUMN session_cookies TEXT"),
("last_online", "ALTER TABLE accounts ADD COLUMN last_online TEXT"),
]
for col, sql in migrations:
if col not in cols:
await db.execute(sql)
logger.info(f"Migration: added column '{col}' to accounts")
cursor = await db.execute("PRAGMA table_info(tasks)")
task_cols = {row[1] for row in await cursor.fetchall()}
task_migrations = [
("account_ids", "ALTER TABLE tasks ADD COLUMN account_ids TEXT"),
("account_results", "ALTER TABLE tasks ADD COLUMN account_results TEXT"),
]
for col, sql in task_migrations:
if col not in task_cols:
await db.execute(sql)
logger.info(f"Migration: added column '{col}' to tasks")
# Logpass accounts migrations
cursor = await db.execute("PRAGMA table_info(logpass_accounts)")
lp_cols = {row[1] for row in await cursor.fetchall()}
lp_migrations = [
("prime", "ALTER TABLE logpass_accounts ADD COLUMN prime TEXT"),
("trophy", "ALTER TABLE logpass_accounts ADD COLUMN trophy TEXT"),
("behavior", "ALTER TABLE logpass_accounts ADD COLUMN behavior TEXT"),
("license", "ALTER TABLE logpass_accounts ADD COLUMN license TEXT"),
("session_cookies", "ALTER TABLE logpass_accounts ADD COLUMN session_cookies TEXT"),
("steam_level", "ALTER TABLE logpass_accounts ADD COLUMN steam_level INTEGER"),
("avatar_url", "ALTER TABLE logpass_accounts ADD COLUMN avatar_url TEXT"),
("last_online", "ALTER TABLE logpass_accounts ADD COLUMN last_online TEXT"),
]
for col, sql in lp_migrations:
if col not in lp_cols:
await db.execute(sql)
logger.info(f"Migration: added column '{col}' to logpass_accounts")
# Token accounts migrations
cursor = await db.execute("PRAGMA table_info(token_accounts)")
tk_cols = {row[1] for row in await cursor.fetchall()}
tk_migrations = [
("proxy", "ALTER TABLE token_accounts ADD COLUMN proxy TEXT"),
("session_cookies", "ALTER TABLE token_accounts ADD COLUMN session_cookies TEXT"),
("ban_status", "ALTER TABLE token_accounts ADD COLUMN ban_status TEXT"),
("nickname", "ALTER TABLE token_accounts ADD COLUMN nickname TEXT"),
("steam_level", "ALTER TABLE token_accounts ADD COLUMN steam_level INTEGER"),
("avatar_url", "ALTER TABLE token_accounts ADD COLUMN avatar_url TEXT"),
("last_online", "ALTER TABLE token_accounts ADD COLUMN last_online TEXT"),
]
for col, sql in tk_migrations:
if col not in tk_cols:
await db.execute(sql)
logger.info(f"Migration: added column '{col}' to token_accounts")
# Add UNIQUE index on login if missing
cursor = await db.execute("PRAGMA index_list(logpass_accounts)")
idx_rows = await cursor.fetchall()
idx_names = {row[1] for row in idx_rows}
if "uq_logpass_login" not in idx_names:
try:
await db.execute("CREATE UNIQUE INDEX uq_logpass_login ON logpass_accounts(login)")
logger.info("Migration: added unique index on logpass_accounts.login")
except Exception:
logger.warning("Could not create unique index on logpass_accounts.login (duplicates may exist)")
async def close_db() -> None:
global _db
if _db is not None:
await _db.close()
_db = None
logger.info("Database connection closed")