Files
2026-07-07 13:07:27 +08:00

81 lines
2.7 KiB
Python

"""群管理工具:权限校验、目标用户解析"""
from __future__ import annotations
import logging
from telegram import Update
from telegram.constants import ChatMemberStatus
from telegram.ext import ContextTypes
import config
from db.models import Action, Ban, Message
from services.message_utils import schedule_delete, record_bot_message
logger = logging.getLogger("spam_guard")
ADMIN_STATUSES = {ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER}
async def is_admin(update: Update, context: ContextTypes.DEFAULT_TYPE) -> bool:
"""判断命令发送者是否为群管理员或配置中的超级管理员。"""
user = update.effective_user
chat = update.effective_chat
if not user or not chat:
return False
if user.id in config.ADMIN_USER_IDS:
return True
try:
member = await context.bot.get_chat_member(chat.id, user.id)
return member.status in ADMIN_STATUSES
except Exception as e:
logger.warning(f"管理员校验失败: user={user.id}, chat={chat.id}, err={e}")
return False
async def require_admin(update: Update, context: ContextTypes.DEFAULT_TYPE) -> bool:
"""命令权限守卫。返回 True 表示允许继续。"""
if await is_admin(update, context):
return True
reply = await update.message.reply_text("⛔ 只有群管理员可以使用这个命令")
schedule_delete(update.message)
await record_bot_message(reply)
schedule_delete(reply)
return False
async def resolve_target_user(update: Update, args: list[str]) -> tuple[int | None, str]:
"""解析管理命令目标用户。
支持:
1. 回复某条消息后执行命令
2. /cmd 用户ID
3. /cmd @username,从历史消息/操作/封禁记录中反查 user_id
"""
# 回复消息优先,最准确
if update.message and update.message.reply_to_message and update.message.reply_to_message.from_user:
u = update.message.reply_to_message.from_user
username = u.username or u.first_name or str(u.id)
return u.id, username
if not args:
return None, ""
target = args[0].strip().lstrip("@")
if target.isdigit():
return int(target), target
# Telegram Bot API 不能直接用 username 查群成员,只能从历史记录里反查
msg = await Message.filter(username=target).order_by("-created_at").first()
if msg:
return msg.user_id, target
action = await Action.filter(username=target, user_id__not_isnull=True).order_by("-created_at").first()
if action:
return action.user_id, target
ban = await Ban.filter(username=target).order_by("-created_at").first()
if ban:
return ban.user_id, target
return None, target