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:
NotSoToothless
2026-06-28 03:38:20 -07:00
committed by GitHub
parent f2a1a33c28
commit 24335a2677
18 changed files with 777 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
from __future__ import annotations
from fastapi import APIRouter, FastAPI, Request
from fastapi.responses import JSONResponse
from starlette.exceptions import HTTPException as StarletteHTTPException
from web.api import db
ENDPOINTS = [
"/api/tss/info", "/api/tss/live", "/api/tss/player/{uid}",
"/api/tss/player/{uid}/games", "/api/tss/player/{uid}/history",
"/api/tss/search/{nick}", "/api/tss/match/{session_id}",
"/api/tss/match/{session_id}/scoreboard", "/api/tss/matches/search",
"/api/tss/maps", "/api/tss/leaderboard/players",
"/api/tss/leaderboard/vehicles", "/api/tss/leaderboard/stats",
"/api/tss/tournaments", "/api/tss/tournament/{id}",
"/api/tss/tournament/{id}/standings", "/api/tss/tournament/{id}/matches",
]
info_router = APIRouter()
@info_router.get("/api/tss/info")
async def info() -> dict:
matches = await db.query_one(db.battles_path(), "SELECT COUNT(*) c FROM match_summary")
pg = await db.query_one(db.battles_path(), "SELECT COUNT(*) c FROM player_games_hist")
tn = await db.query_one(db.tournaments_path(), "SELECT COUNT(*) c FROM tournaments")
return {
"service": "tss",
"counts": {
"matches": matches["c"] if matches else 0,
"player_games": pg["c"] if pg else 0,
"tournaments": tn["c"] if tn else 0,
},
"endpoints": ENDPOINTS,
}
def create_app() -> FastAPI:
app = FastAPI(title="TSS HTTP API", version="1.0.0")
@app.exception_handler(StarletteHTTPException)
async def _err(_: Request, exc: StarletteHTTPException) -> JSONResponse:
detail = exc.detail
body = detail if isinstance(detail, dict) else {"error": str(detail)}
return JSONResponse(status_code=exc.status_code, content=body)
app.include_router(info_router)
from web.api.routes_players import router as players_router
from web.api.routes_matches import router as matches_router
from web.api.routes_leaderboard import router as lb_router
from web.api.routes_tournaments import router as tour_router
app.include_router(players_router)
app.include_router(matches_router)
app.include_router(lb_router)
app.include_router(tour_router)
return app
app = create_app()