PAYATHON 2026

discord.py 角色白名单检查后没有响应,应该如何排查?

数据小陈

角色 ID 列表缺少逗号,需要先修正。如果贴出的缩进与实际文件一致,缩进也需要调整。这两类语法问题都会阻止相关代码正常加载,无法单独解释“已经打印 admin,随后没有响应”的现象,还需要结合实际运行的代码继续排查。

先修正角色 ID 列表

admin 中从第二个 ID 开始缺少分隔逗号。多个整数直接连续排列会产生 SyntaxError,不会自动组成有效列表。

将 utils/variables.py 改为:

admin = [
    1408442799925235794,
    1445017368123277460,
    1079504634772738078,
    1272691594591473695,
    1379137477192843264,
]

如果执行命令时确实能打印 admin,说明当前执行的代码与贴出的内容存在差异,或者运行进程仍在使用修改前已加载的内容。保存修改后,重启机器人进程,确保重新导入配置。

白名单不匹配时,也应该执行 else

这段代码检查命令调用者是否至少拥有一个 ID 在 admin 中的角色:

any(r.id in admin for r in ctx.author.roles)

这里检查的是 ctx.author,即执行命令的人。参数 member 是角色登记的目标成员,不参与当前权限判断。

如果没有匹配的角色,结果为 False,程序应执行 else 并发送拒绝消息。“没有收到消息”不能证明程序没有进行检查,也可能是在获取角色、写入数据库或发送消息时发生了异常。

修正缩进,并添加执行位置日志

贴出的代码没有保留类、方法和条件分支所需的缩进。如果实际文件也是这样,Python 无法正常加载。可以按下面的结构整理,再通过日志确认执行停在哪一步:

import discord
from discord.ext import commands
from utils.databases import roles_db
from utils.variables import admin


class Roles(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.hybrid_group()
    async def custom(self, ctx: commands.Context):
        return

    @custom.command(
        name="register",
        description="Registers a custom role to a user",
    )
    async def register(
        self,
        ctx: commands.Context,
        role: discord.Role,
        member: discord.Member,
    ):
        print("admin:", admin)

        if ctx.guild is None:
            await ctx.send("Please use this command in a server.")
            return

        author_role_ids = [r.id for r in ctx.author.roles]
        print("author role IDs:", author_role_ids)

        allowed = any(role_id in admin for role_id in author_role_ids)
        print("allowed:", allowed)

        if not allowed:
            print("sending permission denial")
            await ctx.send(":x: You do not have the required role.")
            print("permission denial sent")
            return

        print("before insert_one")
        roles_db.insert_one({"user_id": member.id, "role_id": role.id})
        print("after insert_one")

        await ctx.send(":white_check_mark: Role registered!")
        print("success message sent")


async def setup(bot):
    await bot.add_cog(Roles(bot))

示例保留了原代码中同步调用 insert_one 的方式。由于没有提供 roles_db 的初始化代码,无法判断数据库客户端是同步还是异步。如果实际使用的是异步客户端,应根据其接口要求使用 await。同步数据库调用也可能在等待数据库响应时阻塞当前执行。

根据最后一条日志继续排查

  • 只有 admin:查看紧随其后的异常堆栈,确认执行是否在服务器上下文中,以及角色属性访问是否失败。
  • 输出 allowed: False:比较调用者角色 ID 与白名单,确认白名单填写的是角色 ID,且类型与 r.id 一致。这里的 r.id 是整数。
  • 输出 before insert_one,没有 after insert_one:检查数据库调用是否报错或仍在等待返回。
  • 输出 after insert_one,没有 success message sent:检查 ctx.send 的异常,以及机器人是否有在当前频道发送消息所需的权限。
  • 输出 sending permission denial,没有 permission denial sent:检查消息发送环节。

同时查看运行终端和已有的命令错误处理器。如果错误处理器吞掉了异常,应让它记录完整堆栈。找到停止位置和实际异常后,再决定修改哪一部分;仅凭没有回复,无法确定是白名单判断出了问题。

备注:内容仅供参考。