Add offline Twitch chat test mode

This commit is contained in:
2026-05-12 18:57:49 -05:00
parent b249f82631
commit 5c920fa309
3 changed files with 27 additions and 1 deletions

View File

@@ -50,6 +50,7 @@ class Settings(BaseSettings):
TWITCH_CHAT_ENABLED: bool = True TWITCH_CHAT_ENABLED: bool = True
TWITCH_REQUIRE_LIVE_STREAM: bool = True TWITCH_REQUIRE_LIVE_STREAM: bool = True
TWITCH_LIVE_STATUS_CACHE_SECONDS: int = 60 TWITCH_LIVE_STATUS_CACHE_SECONDS: int = 60
TWITCH_OFFLINE_CHAT_TEST_MODE: bool = False
# LLM # LLM
LLM_PROVIDER: Optional[str] = None # "openai", "ollama", "lm_studio", or None LLM_PROVIDER: Optional[str] = None # "openai", "ollama", "lm_studio", or None

View File

@@ -47,6 +47,7 @@ twitch_chat_client: TwitchIRCClient | None = None
twitch_chat_task: asyncio.Task | None = None twitch_chat_task: asyncio.Task | None = None
twitch_session_id: str | None = None twitch_session_id: str | None = None
twitch_live_status: TwitchLiveStatusService | None = None twitch_live_status: TwitchLiveStatusService | None = None
offline_chat_test_mode: bool = settings.TWITCH_OFFLINE_CHAT_TEST_MODE
async def require_admin( async def require_admin(
@@ -92,6 +93,8 @@ def twitch_configured() -> bool:
async def channel_is_live_for_chat(channel_name: str) -> bool: async def channel_is_live_for_chat(channel_name: str) -> bool:
"""Return whether the agent may interact with chat for a channel.""" """Return whether the agent may interact with chat for a channel."""
if offline_chat_test_mode:
return True
if not settings.TWITCH_REQUIRE_LIVE_STREAM: if not settings.TWITCH_REQUIRE_LIVE_STREAM:
return True return True
if not twitch_live_status: if not twitch_live_status:
@@ -496,6 +499,7 @@ async def get_twitch_status() -> dict:
"configured": configured, "configured": configured,
"running": bool(twitch_chat_task and not twitch_chat_task.done()), "running": bool(twitch_chat_task and not twitch_chat_task.done()),
"require_live_stream": settings.TWITCH_REQUIRE_LIVE_STREAM, "require_live_stream": settings.TWITCH_REQUIRE_LIVE_STREAM,
"offline_chat_test_mode": offline_chat_test_mode,
"live_status": live_status, "live_status": live_status,
"session_id": twitch_session_id, "session_id": twitch_session_id,
**client_status, **client_status,
@@ -503,6 +507,24 @@ async def get_twitch_status() -> dict:
} }
@app.post("/admin/twitch/offline-test-mode", dependencies=[Depends(require_admin)])
async def set_offline_chat_test_mode(enabled: bool = Form(...)) -> dict:
"""Allow or block Twitch chat posting while the stream is offline."""
global offline_chat_test_mode
offline_chat_test_mode = enabled
return {
"status": "offline_chat_test_mode_updated",
"offline_chat_test_mode": offline_chat_test_mode,
"warning": (
"Agent may post to Twitch chat while the stream is offline"
if offline_chat_test_mode
else None
),
"timestamp": datetime.utcnow().isoformat(),
}
@app.get("/admin/stream/status", dependencies=[Depends(require_admin)]) @app.get("/admin/stream/status", dependencies=[Depends(require_admin)])
async def get_current_stream_status() -> dict: async def get_current_stream_status() -> dict:
"""Get one operator view of the current Twitch stream runtime state.""" """Get one operator view of the current Twitch stream runtime state."""
@@ -538,7 +560,8 @@ async def get_current_stream_status() -> dict:
await twitch_live_status.get_status(session_info["channel_name"]) await twitch_live_status.get_status(session_info["channel_name"])
).to_dict() ).to_dict()
chat_interaction_allowed = ( chat_interaction_allowed = (
not settings.TWITCH_REQUIRE_LIVE_STREAM offline_chat_test_mode
or not settings.TWITCH_REQUIRE_LIVE_STREAM
or bool(live_status and live_status["is_live"]) or bool(live_status and live_status["is_live"])
) )
@@ -557,6 +580,7 @@ async def get_current_stream_status() -> dict:
"configured": twitch_configured(), "configured": twitch_configured(),
"running": bool(twitch_chat_task and not twitch_chat_task.done()), "running": bool(twitch_chat_task and not twitch_chat_task.done()),
"require_live_stream": settings.TWITCH_REQUIRE_LIVE_STREAM, "require_live_stream": settings.TWITCH_REQUIRE_LIVE_STREAM,
"offline_chat_test_mode": offline_chat_test_mode,
"live_status": live_status, "live_status": live_status,
"session_id": twitch_session_id, "session_id": twitch_session_id,
**twitch_status, **twitch_status,

View File

@@ -42,6 +42,7 @@ services:
TWITCH_CHAT_ENABLED: ${TWITCH_CHAT_ENABLED:-true} TWITCH_CHAT_ENABLED: ${TWITCH_CHAT_ENABLED:-true}
TWITCH_REQUIRE_LIVE_STREAM: ${TWITCH_REQUIRE_LIVE_STREAM:-true} TWITCH_REQUIRE_LIVE_STREAM: ${TWITCH_REQUIRE_LIVE_STREAM:-true}
TWITCH_LIVE_STATUS_CACHE_SECONDS: ${TWITCH_LIVE_STATUS_CACHE_SECONDS:-60} TWITCH_LIVE_STATUS_CACHE_SECONDS: ${TWITCH_LIVE_STATUS_CACHE_SECONDS:-60}
TWITCH_OFFLINE_CHAT_TEST_MODE: ${TWITCH_OFFLINE_CHAT_TEST_MODE:-false}
LLM_PROVIDER: ${LLM_PROVIDER:-} LLM_PROVIDER: ${LLM_PROVIDER:-}
LLM_BASE_URL: ${LLM_BASE_URL:-} LLM_BASE_URL: ${LLM_BASE_URL:-}
LLM_API_KEY: ${LLM_API_KEY:-} LLM_API_KEY: ${LLM_API_KEY:-}