feat: support reply-based admin actions

This commit is contained in:
ngfchl
2026-07-07 09:18:11 +08:00
parent 3ee9b1174e
commit 84fee7e287
+47 -22
View File
@@ -38,6 +38,25 @@ async def mark_reply_message_deleted(reply_msg, reason: str = "command_ban_reply
await rec.save()
async def delete_replied_message(update: Update, reason: str) -> None:
"""删除管理命令引用的目标消息,并同步标记本地消息记录。"""
reply_msg = update.message.reply_to_message if update.message else None
if not reply_msg:
return
try:
await reply_msg.delete()
await mark_reply_message_deleted(reply_msg, reason=reason)
except Exception as e:
logger.debug(f"删除引用消息失败: {type(e).__name__}: {e}")
async def delete_command_message(update: Update) -> None:
"""尽量删除管理员命令消息,失败不影响主流程。"""
try:
await update.message.delete()
except Exception as e:
logger.debug(f"删除命令消息失败: {type(e).__name__}: {e}")
async def cmd_stats(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""今日统计"""
@@ -80,19 +99,12 @@ async def cmd_ban(update: Update, context: ContextTypes.DEFAULT_TYPE):
method="reply_command" if update.message.reply_to_message else "command",
)
if update.message.reply_to_message:
try:
await update.message.reply_to_message.delete()
await mark_reply_message_deleted(update.message.reply_to_message)
except Exception:
pass
try:
await update.message.delete()
except Exception:
pass
await delete_replied_message(update, reason="command_ban_reply")
await delete_command_message(update)
reply = await update.effective_chat.send_message(f"🔨 已封禁 {target} ({user_id}) {config.BAN_DURATION_MINUTES} 分钟")
except Exception as e:
logger.error(f"手动封禁失败: {type(e).__name__}: {e}")
reply = await update.message.reply_text(f"❌ 封禁失败: {e}")
reply = await update.message.reply_text("❌ 封禁失败,请检查 Bot 权限或目标用户状态")
asyncio.create_task(auto_delete(reply))
@@ -115,7 +127,7 @@ async def cmd_unban(update: Update, context: ContextTypes.DEFAULT_TYPE):
reply = await update.message.reply_text(f"🔓 已解封用户 {target} ({user_id})")
except Exception as e:
logger.error(f"手动解封失败: {type(e).__name__}: {e}")
reply = await update.message.reply_text(f"❌ 解封失败: {e}")
reply = await update.message.reply_text("❌ 解封失败,请检查 Bot 权限或目标用户状态")
asyncio.create_task(auto_delete(reply))
@@ -137,14 +149,22 @@ async def cmd_warn(update: Update, context: ContextTypes.DEFAULT_TYPE):
else:
reason = " ".join(context.args[1:]) if len(context.args) > 1 else "未说明原因"
warn_count = await Warning.filter(user_id=user_id).count() + 1
await Warning.create(user_id=user_id, username=target, reason=reason, operator_id=update.effective_user.id)
await Action.create(action="WARN", user_id=user_id, username=target, operator_id=update.effective_user.id, details={"reason": reason})
try:
warn_count = await Warning.filter(user_id=user_id).count() + 1
await Warning.create(user_id=user_id, username=target, reason=reason, operator_id=update.effective_user.id)
await Action.create(action="WARN", user_id=user_id, username=target, operator_id=update.effective_user.id, details={"reason": reason})
if update.message.reply_to_message:
await delete_replied_message(update, reason="command_warn_reply")
await delete_command_message(update)
reply = await update.effective_chat.send_message(f"⚠️ 已警告 {target} ({user_id})\n原因: {reason}\n累计警告: {warn_count}")
else:
reply = await update.message.reply_text(f"⚠️ 已警告 {target} ({user_id})\n原因: {reason}\n累计警告: {warn_count}")
except Exception as e:
logger.error(f"警告失败: {type(e).__name__}: {e}")
reply = await update.message.reply_text("❌ 警告失败,请检查 Bot 权限或数据库状态")
reply = await update.message.reply_text(f"⚠️ 已警告 {target} ({user_id})\n原因: {reason}\n累计警告: {warn_count}")
asyncio.create_task(auto_delete(reply))
async def cmd_mute(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""禁言用户"""
if not await require_admin(update, context):
@@ -171,10 +191,15 @@ async def cmd_mute(update: Update, context: ContextTypes.DEFAULT_TYPE):
until_date=until_date,
)
await Action.create(action="MUTE", user_id=user_id, username=target, operator_id=update.effective_user.id, details={"minutes": minutes})
reply = await update.message.reply_text(f"🔇 已禁言 {target} ({user_id}) {minutes} 分钟")
if update.message.reply_to_message:
await delete_replied_message(update, reason="command_mute_reply")
await delete_command_message(update)
reply = await update.effective_chat.send_message(f"🔇 已禁言 {target} ({user_id}) {minutes} 分钟")
else:
reply = await update.message.reply_text(f"🔇 已禁言 {target} ({user_id}) {minutes} 分钟")
except Exception as e:
logger.error(f"禁言失败: {type(e).__name__}: {e}")
reply = await update.message.reply_text(f"❌ 禁言失败: {e}")
reply = await update.message.reply_text("❌ 禁言失败,请检查 Bot 权限或目标用户状态")
asyncio.create_task(auto_delete(reply))
@@ -228,10 +253,10 @@ async def cmd_help(update: Update, context: ContextTypes.DEFAULT_TYPE):
"🔗 /bind - 绑定账号\n"
"🌙 /night on/off - 夜间模式(管理员)\n\n"
"管理命令(管理员):\n"
"🔨 回复消息 /ban 或 /ban 用户ID\n"
"🔓 /unban 用户ID\n"
"⚠️ 回复消息 /warn [原因]\n"
"🔇 回复消息 /mute [分钟]\n"
"🔨 /ban 用户ID/@历史用户名,或回复消息 /ban(删除原消息并封禁)\n"
"🔇 /mute 用户ID/@历史用户名 [分钟],或回复消息 /mute [分钟](禁言并删除原消息)\n"
"⚠️ /warn 用户ID/@历史用户名 [原因],或回复消息 /warn [原因](警告并删除原消息)\n"
"🔓 /unban 用户ID/@历史用户名\n"
"🧹 回复消息 /purge 数量\n"
)
reply = await update.message.reply_text(text)