fix: danmaku template now uses event rules; rules apply instantly on save
- _on_danmaku renders via event_text(rules, 'danmaku', ...) like all other
events; hardcoded {uname}说、 {msg} format removed
- Drop message_format param from DanmakuHandler/DanmakuClient/server/main
- api_rules_post mutates the shared rules dict in place (clear+update)
instead of rebinding, so running handlers pick up new templates
immediately without restarting TTS
- UI save toast: '规则已保存并即时生效'
- Verified: custom template 卧槽!、是{uname}!、他说、 {msg} works;
save-then-next-danmaku uses new template without restart
This commit is contained in:
+8
-13
@@ -20,8 +20,6 @@ from event_rules import (
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
DANMAKU_FORMAT = "{uname}\u8bf4\u3001 {msg}"
|
|
||||||
|
|
||||||
INTERACT_TYPE_NAMES = {
|
INTERACT_TYPE_NAMES = {
|
||||||
3: "\u5206\u4eab", 4: "\u7279\u522b\u5173\u6ce8", 5: "\u4e92\u7c89",
|
3: "\u5206\u4eab", 4: "\u7279\u522b\u5173\u6ce8", 5: "\u4e92\u7c89",
|
||||||
}
|
}
|
||||||
@@ -32,12 +30,10 @@ class DanmakuHandler(blivedm.BaseHandler):
|
|||||||
|
|
||||||
_CMD_CALLBACK_DICT = blivedm.BaseHandler._CMD_CALLBACK_DICT.copy()
|
_CMD_CALLBACK_DICT = blivedm.BaseHandler._CMD_CALLBACK_DICT.copy()
|
||||||
|
|
||||||
def __init__(self, queue: asyncio.Queue, rules: dict | None = None,
|
def __init__(self, queue: asyncio.Queue, rules: dict | None = None):
|
||||||
message_format: str = DANMAKU_FORMAT):
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._queue = queue
|
self._queue = queue
|
||||||
self._rules = rules or dict(DEFAULT_RULES)
|
self._rules = rules or dict(DEFAULT_RULES)
|
||||||
self._message_format = message_format
|
|
||||||
self._count = 0
|
self._count = 0
|
||||||
|
|
||||||
# ── custom SEND_GIFT callback to capture blind-gift info ──────────
|
# ── custom SEND_GIFT callback to capture blind-gift info ──────────
|
||||||
@@ -62,11 +58,12 @@ class DanmakuHandler(blivedm.BaseHandler):
|
|||||||
def _on_danmaku(self, client: blivedm.BLiveClient, message: DanmakuMessage) -> None:
|
def _on_danmaku(self, client: blivedm.BLiveClient, message: DanmakuMessage) -> None:
|
||||||
if not message.msg.strip():
|
if not message.msg.strip():
|
||||||
return
|
return
|
||||||
text = self._message_format.format(
|
text = event_text(self._rules, "danmaku",
|
||||||
uname=message.uname,
|
uname=message.uname,
|
||||||
msg=message.msg,
|
msg=message.msg,
|
||||||
uid=message.uid,
|
uid=message.uid)
|
||||||
)
|
if not text:
|
||||||
|
return
|
||||||
self._count += 1
|
self._count += 1
|
||||||
if self._count % 20 == 1:
|
if self._count % 20 == 1:
|
||||||
logger.info("Danmaku #%d: %s", self._count, text)
|
logger.info("Danmaku #%d: %s", self._count, text)
|
||||||
@@ -173,13 +170,11 @@ class DanmakuClient:
|
|||||||
queue: asyncio.Queue,
|
queue: asyncio.Queue,
|
||||||
cookies: Optional[dict[str, str]] = None,
|
cookies: Optional[dict[str, str]] = None,
|
||||||
rules: dict | None = None,
|
rules: dict | None = None,
|
||||||
message_format: str = DANMAKU_FORMAT,
|
|
||||||
):
|
):
|
||||||
self._room_id = room_id
|
self._room_id = room_id
|
||||||
self._queue = queue
|
self._queue = queue
|
||||||
self._cookies = cookies
|
self._cookies = cookies
|
||||||
self._rules = rules or dict(DEFAULT_RULES)
|
self._rules = rules or dict(DEFAULT_RULES)
|
||||||
self._message_format = message_format
|
|
||||||
self._client: Optional[blivedm.BLiveClient] = None
|
self._client: Optional[blivedm.BLiveClient] = None
|
||||||
self._session: Optional["aiohttp.ClientSession"] = None
|
self._session: Optional["aiohttp.ClientSession"] = None
|
||||||
|
|
||||||
@@ -187,7 +182,7 @@ class DanmakuClient:
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
self._session = await build_danmaku_session(self._cookies)
|
self._session = await build_danmaku_session(self._cookies)
|
||||||
self._client = blivedm.BLiveClient(self._room_id, session=self._session)
|
self._client = blivedm.BLiveClient(self._room_id, session=self._session)
|
||||||
handler = DanmakuHandler(self._queue, self._rules, self._message_format)
|
handler = DanmakuHandler(self._queue, self._rules)
|
||||||
self._client.set_handler(handler)
|
self._client.set_handler(handler)
|
||||||
self._client.start()
|
self._client.start()
|
||||||
logger.info("Connected to room %d", self._room_id)
|
logger.info("Connected to room %d", self._room_id)
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ def parse_args() -> argparse.Namespace:
|
|||||||
choices=["f1", "f2", "m1", "m2", "dvd", "imd1", "jgr", "r1"])
|
choices=["f1", "f2", "m1", "m2", "dvd", "imd1", "jgr", "r1"])
|
||||||
parser.add_argument("--speed", "-s", type=int, default=DEFAULT_SPEED)
|
parser.add_argument("--speed", "-s", type=int, default=DEFAULT_SPEED)
|
||||||
parser.add_argument("--sessdata", type=str, default="")
|
parser.add_argument("--sessdata", type=str, default="")
|
||||||
parser.add_argument("--format", "-f", type=str,
|
|
||||||
default="{uname}\u8bf4\u3001 {msg}")
|
|
||||||
parser.add_argument("--no-numbers", action="store_true")
|
parser.add_argument("--no-numbers", action="store_true")
|
||||||
parser.add_argument("--list-devices", action="store_true")
|
parser.add_argument("--list-devices", action="store_true")
|
||||||
parser.add_argument("--debug", "-d", action="store_true")
|
parser.add_argument("--debug", "-d", action="store_true")
|
||||||
@@ -77,7 +75,6 @@ async def main_async(args: argparse.Namespace) -> int:
|
|||||||
room_id=args.room_id, queue=queue,
|
room_id=args.room_id, queue=queue,
|
||||||
cookies={"SESSDATA": args.sessdata} if args.sessdata else None,
|
cookies={"SESSDATA": args.sessdata} if args.sessdata else None,
|
||||||
rules=rules,
|
rules=rules,
|
||||||
message_format=args.format,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
async def handle_signal():
|
async def handle_signal():
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ class TTSService:
|
|||||||
voice = config.get("voice", "f1")
|
voice = config.get("voice", "f1")
|
||||||
speed = config.get("speed", 100)
|
speed = config.get("speed", 100)
|
||||||
self._volume = config.get("volume", 100)
|
self._volume = config.get("volume", 100)
|
||||||
message_format = config.get("format", "{uname}\u8bf4\u3001 {msg}")
|
|
||||||
convert_numbers = config.get("convert_numbers", True)
|
convert_numbers = config.get("convert_numbers", True)
|
||||||
self.current_config = config
|
self.current_config = config
|
||||||
self.recent_messages = []
|
self.recent_messages = []
|
||||||
@@ -71,7 +70,6 @@ class TTSService:
|
|||||||
self._danmaku_client = DanmakuClient(
|
self._danmaku_client = DanmakuClient(
|
||||||
room_id=room_id, queue=self._queue,
|
room_id=room_id, queue=self._queue,
|
||||||
cookies=self._cookies, rules=event_rules,
|
cookies=self._cookies, rules=event_rules,
|
||||||
message_format=message_format,
|
|
||||||
)
|
)
|
||||||
await self._danmaku_client.start()
|
await self._danmaku_client.start()
|
||||||
self.running = True
|
self.running = True
|
||||||
@@ -169,7 +167,6 @@ async def api_start(request: web.Request) -> web.Response:
|
|||||||
config.setdefault("voice", "f1")
|
config.setdefault("voice", "f1")
|
||||||
config.setdefault("speed", 100)
|
config.setdefault("speed", 100)
|
||||||
config.setdefault("volume", 100)
|
config.setdefault("volume", 100)
|
||||||
config.setdefault("format", "{uname}\u8bf4\u3001 {msg}")
|
|
||||||
config.setdefault("convert_numbers", True)
|
config.setdefault("convert_numbers", True)
|
||||||
if tts_service.running:
|
if tts_service.running:
|
||||||
try:
|
try:
|
||||||
@@ -248,7 +245,6 @@ async def api_rules_get(request: web.Request) -> web.Response:
|
|||||||
|
|
||||||
|
|
||||||
async def api_rules_post(request: web.Request) -> web.Response:
|
async def api_rules_post(request: web.Request) -> web.Response:
|
||||||
global event_rules
|
|
||||||
try:
|
try:
|
||||||
new_rules = await request.json()
|
new_rules = await request.json()
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -275,7 +271,11 @@ async def api_rules_post(request: web.Request) -> web.Response:
|
|||||||
save_rules(merged)
|
save_rules(merged)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
return web.json_response({"error": f"Failed to save rules: {e}"}, status=500)
|
return web.json_response({"error": f"Failed to save rules: {e}"}, status=500)
|
||||||
event_rules = merged
|
|
||||||
|
# Mutate in place so running handlers (which hold the same dict reference)
|
||||||
|
# pick up the new rules immediately without restarting TTS.
|
||||||
|
event_rules.clear()
|
||||||
|
event_rules.update(merged)
|
||||||
return web.json_response({"status": "saved", "rules": event_rules})
|
return web.json_response({"status": "saved", "rules": event_rules})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -634,7 +634,7 @@ async function saveRules() {
|
|||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
if (data.error) { alert('保存失败: ' + data.error); return; }
|
if (data.error) { alert('保存失败: ' + data.error); return; }
|
||||||
renderRules(data.rules);
|
renderRules(data.rules);
|
||||||
alert('规则已保存。重启TTS后生效。');
|
alert('规则已保存并即时生效。');
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
alert('保存失败: ' + e.message);
|
alert('保存失败: ' + e.message);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user