update to handle new structure from spectra, no more gobs (#1266)

This commit is contained in:
NotSoToothless
2026-05-23 17:16:53 -07:00
committed by GitHub
parent 2d5adfcbe0
commit f6f4e33a65
11 changed files with 459 additions and 313 deletions
+12 -42
View File
@@ -23,17 +23,15 @@ import aiofiles
import aiohttp
import aiosqlite
import discord
import pygob
# Local Module Imports
from . import utils
from data_parser import LangTableReader
from .game_api import get_point_diff
from .gob import load_gob_file, render_gob
from .render_replay import load_gob_file, render_gob
from .health import record_game_processed, record_ws_message
from .receiver_bridge import publish_gob_payload, publish_replay_batch
from .receiver_bridge import publish_replay_batch
from .utils import t, lang_from_features
from .lux_apis import _gob_to_dict
from .scoreboard import create_scoreboard
from .utils import (
STORAGE_DIR,
@@ -452,7 +450,7 @@ async def process_ws_replays(replays: list[dict]):
if not hex_id:
continue
# Skip if already processed (check for replay_data.json, not just dir — GOB ws may create the dir first)
# Skip if already processed
replay_dir = replay_session_dir(hex_id)
if (replay_dir / "replay_data.json").exists():
continue
@@ -494,14 +492,14 @@ async def process_ws_replays(replays: list[dict]):
hex_id,
local_data,
received_time=now_ts,
end_time=replay.get('end_ts', now_ts),
end_time=int(replay.get("end_ts") or now_ts),
)
local_data["scoreboard_context"] = scoreboard_context
forwarded_replays.append(local_data)
validated_games.append({
"sessionIdHex": hex_id,
"endTime": replay.get('end_ts', now_ts),
"endTime": int(replay.get("end_ts") or now_ts),
"missionName": local_data.get("map", ""),
"receivedTime": now_ts,
"scoreboard_context": scoreboard_context,
@@ -1296,36 +1294,8 @@ def build_scoreboard_view(guild_id: int, session_id: str, lang: str = "en") -> d
return view
async def handle_gob_message(compressed: bytes, decompressed: bytes) -> None:
"""Save a received GOB replay (zstd-compressed) to disk for on-demand video generation."""
try:
replay = pygob.load(decompressed)
d = _gob_to_dict(replay)
session_id = d.get("SessionID")
if not session_id:
return
hex_id = format(session_id, 'x')
replay_dir = replay_session_dir(hex_id)
replay_dir.mkdir(parents=True, exist_ok=True)
gob_path = replay_dir / "replay.gob"
if not gob_path.exists():
gob_path.write_bytes(compressed)
logging.info(f"[GOB] Saved {hex_id} ({len(compressed)} bytes compressed)")
await record_ws_message("sqb_gob")
try:
await publish_gob_payload({
"session_id": hex_id,
"payload": d,
"compressed_size": len(compressed),
})
except Exception as bridge_error:
logging.warning(f"[BRIDGE] Failed to forward GOB payload for {hex_id}: {bridge_error}")
except Exception as e:
logging.error(f"[GOB] Save error: {e}")
async def handle_view_video(interaction: discord.Interaction, session_id: str):
"""Callback for 'View Video' - renders GOB replay to MP4, sends ephemerally."""
"""Callback for 'View Video' - renders replay JSON to MP4, sends ephemerally."""
try:
try:
await interaction.response.defer(thinking=True, ephemeral=True)
@@ -1336,10 +1306,10 @@ async def handle_view_video(interaction: discord.Interaction, session_id: str):
_lang = lang_from_features(_gf)
replay_dir = replay_session_dir(session_id)
gob_path = replay_dir / "replay.gob"
replay_json_path = replay_dir / "replay_data.json"
video_path = replay_dir / "replay_video.mp4"
if not gob_path.exists():
if not replay_json_path.exists():
await interaction.followup.send(
t(_lang, "autolog.replay_not_available"),
ephemeral=True
@@ -1356,15 +1326,15 @@ async def handle_view_video(interaction: discord.Interaction, session_id: str):
return
try:
def _generate():
d = load_gob_file(gob_path)
d = load_gob_file(replay_json_path)
render_gob(d, video_path)
logging.info(f"GOB ({session_id}) RENDER START")
logging.info(f"REPLAY ({session_id}) RENDER START")
async with _video_render_sem:
await asyncio.get_event_loop().run_in_executor(None, _generate)
logging.info(f"GOB ({session_id}) RENDER END (Success)")
logging.info(f"REPLAY ({session_id}) RENDER END (Success)")
except Exception as e:
logging.info(f"GOB ({session_id}) RENDER END (Fail)")
logging.info(f"REPLAY ({session_id}) RENDER END (Fail)")
# Clean up broken/partial mp4 so it doesn't get cached
if video_path.exists():
video_path.unlink(missing_ok=True)