Auto merge dev → main (#1353)
* feat(gateway): hashed key store with grant + hot reload Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(gateway): channel registry + aiohttp app (keyed auth, whoami, per-channel ws/proxy) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(gateway): manage_keys CLI (add/list/revoke) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(gateway): retire srebot_external, run relay-gateway under PM2 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(gateway): point ecosystem + README at relay-gateway Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(tss): replay outbox producer for relay gateway Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(tss): forward processed games to relay outbox Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(tss-api): db helpers, app skeleton, info endpoint, fixtures Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(tss-api): player, games, history, search endpoints Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(tss-api): live, match, scoreboard, matches-search, maps Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(tss-api): filter-required leaderboards (players/vehicles/stats) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(tss-api): tournament list/detail/standings/matches Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: wire tss upstream through gateway + tssbot-api PM2 app Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sqlite3
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import aiosqlite
|
||||
|
||||
# Make TSSBOT root importable for BOT.storage defaults.
|
||||
_TSSBOT_ROOT = Path(__file__).resolve().parents[2]
|
||||
if str(_TSSBOT_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(_TSSBOT_ROOT))
|
||||
|
||||
|
||||
def battles_path() -> Path:
|
||||
override = os.getenv("TSS_API_BATTLES_DB", "").strip()
|
||||
if override:
|
||||
return Path(override)
|
||||
from BOT.storage import TSS_BATTLES_DB_PATH
|
||||
return TSS_BATTLES_DB_PATH
|
||||
|
||||
|
||||
def tournaments_path() -> Path:
|
||||
override = os.getenv("TSS_API_TOURNAMENTS_DB", "").strip()
|
||||
if override:
|
||||
return Path(override)
|
||||
from BOT.storage import STORAGE_DIR
|
||||
return STORAGE_DIR / "tss_tournaments.db"
|
||||
|
||||
|
||||
def _ro_uri(path: Path) -> str:
|
||||
return f"file:{path}?mode=ro"
|
||||
|
||||
|
||||
async def query(path: Path, sql: str, params: tuple[Any, ...] = ()) -> list[dict]:
|
||||
async with aiosqlite.connect(_ro_uri(path), uri=True) as conn:
|
||||
conn.row_factory = sqlite3.Row
|
||||
async with conn.execute(sql, params) as cur:
|
||||
rows = await cur.fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
|
||||
async def query_one(path: Path, sql: str, params: tuple[Any, ...] = ()) -> dict | None:
|
||||
rows = await query(path, sql, params)
|
||||
return rows[0] if rows else None
|
||||
Reference in New Issue
Block a user