feat: add bot I/O layer for message routing and point management, updating .env.example with topic map configuration.

This commit is contained in:
2569718930@qq.com
2026-03-14 11:51:14 +08:00
parent 4bd531bbc9
commit d1f4a8b236
2 changed files with 47 additions and 6 deletions
+4
View File
@@ -8,6 +8,10 @@ TELEGRAM_CHAT_IDS=
# If TELEGRAM_QUERY_TOPIC_CHAT_ID is empty, fallback to command source chat. # If TELEGRAM_QUERY_TOPIC_CHAT_ID is empty, fallback to command source chat.
TELEGRAM_QUERY_TOPIC_CHAT_ID= TELEGRAM_QUERY_TOPIC_CHAT_ID=
TELEGRAM_QUERY_TOPIC_ID= TELEGRAM_QUERY_TOPIC_ID=
# Optional per-group topic routing (higher priority than fixed topic above):
# format: chat_id:topic_id,chat_id:topic_id
# Example: TELEGRAM_QUERY_TOPIC_MAP=-1003586303099:25513,-1003539418691:25514
TELEGRAM_QUERY_TOPIC_MAP=
TELEGRAM_ALERT_PUSH_ENABLED=true TELEGRAM_ALERT_PUSH_ENABLED=true
TELEGRAM_ALERT_PUSH_INTERVAL_SEC=300 TELEGRAM_ALERT_PUSH_INTERVAL_SEC=300
TELEGRAM_ALERT_PUSH_COOLDOWN_SEC=1800 TELEGRAM_ALERT_PUSH_COOLDOWN_SEC=1800
+43 -6
View File
@@ -2,7 +2,7 @@ from __future__ import annotations
import os import os
from datetime import datetime from datetime import datetime
from typing import Any from typing import Any, Dict, Optional, Tuple
from loguru import logger from loguru import logger
@@ -23,6 +23,9 @@ class BotIOLayer:
def __init__(self, bot: Any, db: DBManager): def __init__(self, bot: Any, db: DBManager):
self.bot = bot self.bot = bot
self.db = db self.db = db
self.query_topic_map = self._parse_topic_map(
os.getenv("TELEGRAM_QUERY_TOPIC_MAP")
)
self.query_topic_chat_id = str( self.query_topic_chat_id = str(
os.getenv("TELEGRAM_QUERY_TOPIC_CHAT_ID") or "" os.getenv("TELEGRAM_QUERY_TOPIC_CHAT_ID") or ""
).strip() ).strip()
@@ -42,6 +45,39 @@ class BotIOLayer:
except Exception: except Exception:
return default return default
@staticmethod
def _parse_topic_map(raw: Optional[str]) -> Dict[str, int]:
"""
Parse TELEGRAM_QUERY_TOPIC_MAP:
- "-1003586303099:25513,-1003539418691:25514"
- Supports comma/semicolon/newline separators.
"""
out: Dict[str, int] = {}
if not raw:
return out
normalized = str(raw).replace("\r", ",").replace("\n", ",").replace(";", ",")
for part in normalized.split(","):
row = part.strip()
if not row or ":" not in row:
continue
chat_id, topic_raw = row.split(":", 1)
chat_id = str(chat_id or "").strip()
topic_id = BotIOLayer._safe_int(topic_raw, default=0)
if chat_id and topic_id > 0:
out[chat_id] = topic_id
return out
def _resolve_query_target(
self,
source_chat_id: Any,
) -> Tuple[Optional[str], int]:
src = str(source_chat_id).strip() if source_chat_id is not None else ""
if src and src in self.query_topic_map:
return src, self.query_topic_map[src]
if self.query_topic_chat_id:
return self.query_topic_chat_id, self.query_topic_id
return src or None, self.query_topic_id
def send_query_message( def send_query_message(
self, self,
message: Any, message: Any,
@@ -51,7 +87,7 @@ class BotIOLayer:
) -> None: ) -> None:
chat = getattr(message, "chat", None) chat = getattr(message, "chat", None)
fallback_chat_id = getattr(chat, "id", None) fallback_chat_id = getattr(chat, "id", None)
target_chat_id = self.query_topic_chat_id or fallback_chat_id target_chat_id, target_topic_id = self._resolve_query_target(fallback_chat_id)
if target_chat_id is None: if target_chat_id is None:
self.bot.send_message(message.chat.id, text, parse_mode=parse_mode) self.bot.send_message(message.chat.id, text, parse_mode=parse_mode)
return return
@@ -59,17 +95,18 @@ class BotIOLayer:
kwargs = {} kwargs = {}
if parse_mode: if parse_mode:
kwargs["parse_mode"] = parse_mode kwargs["parse_mode"] = parse_mode
if self.query_topic_id > 0: if target_topic_id > 0:
kwargs["message_thread_id"] = self.query_topic_id kwargs["message_thread_id"] = target_topic_id
try: try:
self.bot.send_message(target_chat_id, text, **kwargs) self.bot.send_message(target_chat_id, text, **kwargs)
return return
except Exception as exc: except Exception as exc:
logger.warning( logger.warning(
"query topic send failed chat_id={} topic_id={} error={}", "query topic send failed chat_id={} topic_id={} source_chat_id={} error={}",
target_chat_id, target_chat_id,
self.query_topic_id, target_topic_id,
fallback_chat_id,
exc, exc,
) )