""" web/routes/config_routes.py — Keyword groups and channel list management. GET /config/keywords → render groups editor PUT /config/keywords → validate + save groups, reload scorer GET /config/channels → render channel list PUT /config/channels → save channels, signal bot to re-watch """ import re from fastapi import APIRouter, Depends, HTTPException, Request, status from fastapi.responses import RedirectResponse import config import utils.scorer as scorer from tui import events as bus from web.dependencies import require_role from web.models import ChannelsPayload, KeywordGroupsPayload router = APIRouter() def _templates(request: Request): return request.app.state.templates @router.get("/config/keywords") async def keywords_page(request: Request, user=Depends(require_role("admin"))): return _templates(request).TemplateResponse( request, "config.html", { "user": dict(user), "groups": config.KEYWORD_GROUPS, "channels": config.WATCHED_CHANNELS, "active_tab": "keywords", }, ) @router.put("/config/keywords") async def update_keywords(payload: KeywordGroupsPayload, _user=Depends(require_role("admin"))): groups = [g.model_dump() for g in payload.groups] config.save_runtime_config(groups, config.WATCHED_CHANNELS) scorer.reload_from_config() return {"status": "ok", "groups": len(groups)} @router.get("/config/channels") async def channels_page(request: Request, user=Depends(require_role("admin"))): return _templates(request).TemplateResponse( request, "config.html", { "user": dict(user), "groups": config.KEYWORD_GROUPS, "channels": config.WATCHED_CHANNELS, "active_tab": "channels", }, ) @router.put("/config/channels") async def update_channels(payload: ChannelsPayload, _user=Depends(require_role("admin"))): config.save_runtime_config(config.KEYWORD_GROUPS, payload.channels) bus.signal_channel_changed() return {"status": "ok", "channels": len(payload.channels)}