feat: Introduce core bot components, on-chain wallet watchers, Telegram notifications, and configuration management.
This commit is contained in:
+34
-24
@@ -6,6 +6,7 @@ from typing import Any
|
||||
from loguru import logger
|
||||
|
||||
from src.bot.io_layer import BotIOLayer
|
||||
from src.utils.telegram_chat_ids import get_telegram_chat_ids_from_env, parse_telegram_chat_ids
|
||||
|
||||
|
||||
class CommandGuard:
|
||||
@@ -15,7 +16,10 @@ class CommandGuard:
|
||||
|
||||
def __init__(self, io_layer: BotIOLayer, group_chat_id: str | None = None):
|
||||
self.io_layer = io_layer
|
||||
self.group_chat_id = str(group_chat_id or os.getenv("TELEGRAM_CHAT_ID") or "").strip()
|
||||
if group_chat_id is None:
|
||||
self.group_chat_ids = get_telegram_chat_ids_from_env()
|
||||
else:
|
||||
self.group_chat_ids = parse_telegram_chat_ids(group_chat_id)
|
||||
self.group_invite_url = str(os.getenv("POLYWEATHER_BOT_GROUP_INVITE_URL") or "").strip()
|
||||
|
||||
def _reply_group_required(self, message: Any) -> None:
|
||||
@@ -30,42 +34,48 @@ class CommandGuard:
|
||||
if user_id is None:
|
||||
return False
|
||||
|
||||
if not self.group_chat_id:
|
||||
if not self.group_chat_ids:
|
||||
logger.error(
|
||||
"group member blocked command={} user_id={} reason=missing_TELEGRAM_CHAT_ID",
|
||||
"group member blocked command={} user_id={} reason=missing_TELEGRAM_CHAT_IDS",
|
||||
command_label,
|
||||
user_id,
|
||||
)
|
||||
self.io_layer.bot.reply_to(
|
||||
message,
|
||||
"⚠️ 机器人未配置群组准入(TELEGRAM_CHAT_ID),请联系管理员。",
|
||||
"⚠️ 机器人未配置群组准入(TELEGRAM_CHAT_IDS / TELEGRAM_CHAT_ID),请联系管理员。",
|
||||
)
|
||||
return False
|
||||
|
||||
try:
|
||||
member = self.io_layer.bot.get_chat_member(self.group_chat_id, int(user_id))
|
||||
status = str(getattr(member, "status", "") or "").strip().lower()
|
||||
except Exception as exc:
|
||||
blocked_statuses: list[str] = []
|
||||
lookup_failures: list[str] = []
|
||||
for chat_id in self.group_chat_ids:
|
||||
try:
|
||||
member = self.io_layer.bot.get_chat_member(chat_id, int(user_id))
|
||||
status = str(getattr(member, "status", "") or "").strip().lower()
|
||||
except Exception as exc:
|
||||
lookup_failures.append(f"{chat_id}:{type(exc).__name__}")
|
||||
continue
|
||||
|
||||
if status in self._ALLOWED_MEMBER_STATUSES:
|
||||
return True
|
||||
blocked_statuses.append(f"{chat_id}:{status or 'unknown'}")
|
||||
|
||||
if blocked_statuses:
|
||||
logger.info(
|
||||
"group member blocked command={} user_id={} chat_id={} reason=lookup_failed error={}",
|
||||
"group member blocked command={} user_id={} chat_ids={} statuses={}",
|
||||
command_label,
|
||||
user_id,
|
||||
self.group_chat_id,
|
||||
exc,
|
||||
",".join(self.group_chat_ids),
|
||||
"|".join(blocked_statuses),
|
||||
)
|
||||
else:
|
||||
logger.info(
|
||||
"group member blocked command={} user_id={} chat_ids={} reason=lookup_failed_all errors={}",
|
||||
command_label,
|
||||
user_id,
|
||||
",".join(self.group_chat_ids),
|
||||
"|".join(lookup_failures) or "unknown",
|
||||
)
|
||||
self._reply_group_required(message)
|
||||
return False
|
||||
|
||||
if status in self._ALLOWED_MEMBER_STATUSES:
|
||||
return True
|
||||
|
||||
logger.info(
|
||||
"group member blocked command={} user_id={} chat_id={} status={}",
|
||||
command_label,
|
||||
user_id,
|
||||
self.group_chat_id,
|
||||
status or "unknown",
|
||||
)
|
||||
self._reply_group_required(message)
|
||||
return False
|
||||
|
||||
|
||||
Reference in New Issue
Block a user