You need to enable JavaScript to run this app. Discord.py审核Bot开发求助:实现带文件存储的warn/warnings/unwarn指令
优惠活动
大模型
产品
解决方案
定价
更多

Discord.py审核Bot开发求助:实现带文件存储的warn/warnings/unwarn指令

Discord.py 警告类审核指令实现

前置准备

  • 采用本地JSON文件warnings.json存储警告记录,无需额外数据库,适配中小服务器使用场景
  • 记录结构为:{"用户Discord ID(字符串)": [{"reason": "警告原因", "timestamp": "生成时间", "warner_id": "操作管理员ID"}]}
  • 统一通过manage_members权限校验操作门槛,符合要求的权限规则

注意:需要在Discord开发者门户的机器人设置页,开启「Server Members Intent」权限,否则无法正常解析@的用户信息。

工具函数封装

首先导入依赖、初始化机器人,并封装通用的警告记录读写函数:

import discord
from discord.ext import commands
import json
import datetime
import os

# 初始化机器人配置,命令前缀为?
intents = discord.Intents.default()
intents.members = True
bot = commands.Bot(command_prefix="?", intents=intents)

# 警告存储文件路径
WARNING_FILE = "warnings.json"

def load_warnings():
    # 文件不存在时返回空字典结构,避免读取报错
    if not os.path.exists(WARNING_FILE):
        return {}
    with open(WARNING_FILE, "r", encoding="utf-8") as f:
        return json.load(f)

def save_warnings(data):
    with open(WARNING_FILE, "w", encoding="utf-8") as f:
        # 缩进格式化方便手动调试,开启ensure_ascii=False支持中文存储
        json.dump(data, f, indent=2, ensure_ascii=False)

核心指令实现

1. 警告指令 ?warn @user [警告原因]

符合权限的用户执行后将为目标用户新增警告,自动存储到本地文件:

@bot.command(name="warn")
@commands.has_permissions(manage_members=True)
async def warn(ctx, target: discord.Member, *, reason: str = "未提供警告原因"):
    # 防滥用校验逻辑
    if target == ctx.author:
        return await ctx.send("你不能警告你自己")
    if target == ctx.me:
        return await ctx.send("你不能警告机器人")
    # 禁止警告权限高于或等于当前操作者的用户(服务器所有者除外)
    if target.top_role >= ctx.author.top_role and ctx.author != ctx.guild.owner:
        return await ctx.send("你不能警告权限高于或等于你的用户")
    
    warnings = load_warnings()
    user_id = str(target.id)
    # 初始化新用户的警告列表
    if user_id not in warnings:
        warnings[user_id] = []
    
    # 新增警告条目
    new_warning = {
        "reason": reason,
        "timestamp": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "warner_id": str(ctx.author.id)
    }
    warnings[user_id].append(new_warning)
    save_warnings(warnings)
    
    await ctx.send(f"已成功警告 {target.mention},原因:{reason}\n该用户当前累计警告数:{len(warnings[user_id])}")

2. 警告查询指令 ?warnings @user

查询指定用户的全部历史警告记录,以Embed卡片形式格式化展示:

@bot.command(name="warnings", aliases=["warns"])
@commands.has_permissions(manage_members=True)
async def get_warnings(ctx, target: discord.Member):
    warnings = load_warnings()
    user_id = str(target.id)
    user_warnings = warnings.get(user_id, [])
    
    if not user_warnings:
        return await ctx.send(f"{target.mention} 没有任何历史警告记录")
    
    embed = discord.Embed(title=f"{target} 的历史警告记录", color=discord.Color.orange())
    for idx, warn in enumerate(user_warnings, 1):
        warner = await bot.fetch_user(int(warn["warner_id"]))
        embed.add_field(
            name=f"警告 #{idx}",
            value=f"时间:{warn['timestamp']}\n原因:{warn['reason']}\n操作管理员:{warner.mention}",
            inline=False
        )
    await ctx.send(embed=embed)

3. 警告移除指令 ?unwarn @user [可选:警告序号]

支持移除指定用户的警告记录,默认移除最新一条,也可通过序号指定要删除的警告:

@bot.command(name="unwarn")
@commands.has_permissions(manage_members=True)
async def unwarn(ctx, target: discord.Member, warn_index: int = None):
    warnings = load_warnings()
    user_id = str(target.id)
    user_warnings = warnings.get(user_id, [])
    
    if not user_warnings:
        return await ctx.send(f"{target.mention} 没有任何警告记录可以移除")
    
    # 未指定序号时默认移除最新的一条警告
    if warn_index is None:
        removed = user_warnings.pop()
    else:
        # 用户输入的序号从1开始计数,转换为数组索引需减1
        try:
            removed = user_warnings.pop(warn_index - 1)
        except IndexError:
            return await ctx.send(f"无效的警告序号,该用户共有 {len(user_warnings)} 条警告,序号范围为 1-{len(user_warnings)}")
    
    # 清空警告列表时删除该用户的存储条目,减少冗余
    if not user_warnings:
        del warnings[user_id]
    else:
        warnings[user_id] = user_warnings
    save_warnings(warnings)
    
    await ctx.send(f"已成功移除 {target.mention} 的一条警告(原因:{removed['reason']})\n该用户剩余警告数:{len(user_warnings)}")

通用错误处理

统一处理权限不足、参数错误等常见异常,避免用户看到默认的英文报错:

@bot.event
async def on_command_error(ctx, error):
    if isinstance(error, commands.MissingPermissions):
        await ctx.send("你没有「管理成员」权限,无法执行该指令")
    elif isinstance(error, commands.MissingRequiredArgument):
        await ctx.send("指令参数错误,正确用法:\n`?warn @用户 [警告原因]`\n`?warnings @用户`\n`?unwarn @用户 [可选:警告序号]`")

内容的提问来源于stack exchange,提问作者King Zebrus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 12:06:06