You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

discord.py中hybrid命令仅部分注册问题求助

Discord机器人hybrid命令注册异常问题解决

问题现象

使用discord.py开发Discord机器人时,通过commands.hybrid_command同时注册斜杠命令与普通命令,但仅含2个命令的information cog能正常加载命令,包含5个命令的moderation cog未注册任何命令。

相关代码

main.py

import discord
import asyncio
import re
from discord.ext import commands
import os

client = commands.Bot(command_prefix = "!", intents = discord.Intents.all())
#client.remove_command("help")

@client.event
async def on_ready():
    await client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="a movie"))
    print('Logged in as {0.user}'.format(client))    # Lets you know when the bot is online
    try:
        synced = await client.tree.sync()
        print(f"Synced {len(synced)} command(s)")
    except Exception as e:
        print(e)

@client.command(name='load', description='Loads the given cog')
async def load(ctx, extension):
    await client.load_extension(f"cogs.{extension}")
    await ctx.send(f"Loaded {extension}.")
    print(f"Loaded {extension}.py")

@client.command(name='unload', description='Unloads the given cog')
async def unload(ctx, extension):
    await client.unload_extension(f"cogs.{extension}")
    await ctx.send(f"Unloaded {extension}.")
    print(f"Unloaded {extension}.py")

@client.command(name='reload', description='Re-loads the given cog')
async def reload(ctx, extension):
    await client.reload_extension(f"cogs.{extension}")
    await ctx.send(f"Re-loaded {extension}.")
    print(f"Re-loaded {extension}.py")

async def load_extensions():
    for filename in os.listdir("./cogs"):
        if filename.endswith(".py"):
            await client.load_extension(f"cogs.{filename[:-3]}")

async def main():
    async with client:
        await load_extensions()
        await client.start("TOKEN")

asyncio.run(main())

information.py(正常工作的cog)

class Information(commands.Cog):
    def __init__(self, client):
        self.client = client
    
    # Test command
    @commands.hybrid_command(name='test', description='Just a basic test command to see if the commands are working.')
    async def test(self, ctx):
        await ctx.send("Everything is working fine!")

    # Latency command
    @commands.hybrid_command(name='ping', description='Sends the bots letency/response time in ms.')
    async def ping(self, ctx):
        await ctx.send(f"Pong {round(self.client.latency * 1000)}ms")

async def setup(client):
    await client.add_cog(Information(client))

moderation.py(存在问题的cog)

class Moderation(commands.Cog):
    def __init__(self, client):
        self.client = client

        @commands.hybrid_command(name='purge', description='Purges the given amount of messages from the channel.')
        @commands.has_permissions(manage_messages=True)
        async def purge(self, ctx, amount: int):
            await ctx.channel.purge(limit=amount)
            await ctx.send(f"Successfully cleared {amount} messages!")

        @commands.hybrid_command(name='kick', description='Kicks the mentioned user from the guild.')
        @commands.has_permissions(kick_members=True)
        async def kick(self, ctx, member: discord.Member, *, reason=None):
            await discord.Member.kick(member)
            await ctx.send(f"{member} has been kicked.")

        @commands.hybrid_command(name='mute', description='Mutes the mentioned user for the given amount of time.')
        @commands.has_permissions(manage_roles=True)
        async def mute(self, ctx, member:discord.Member, *, time:TimeConverter = None, reason=None):
            """Mutes a member for the specified time- time in 2d 10h 3m 2s format ex:
            &mute @Someone 1d"""
            role = discord.utils.get(ctx.guild.roles, name="Muted")
            memRole = discord.utils.get(ctx.guild.roles, name='Member')
            await member.remove_roles(memRole)
            await member.add_roles(role)
            await ctx.send(("Muted {} for {}s" if time else "Muted {}").format(member, time))
            if time:
                await asyncio.sleep(time)
                await member.add_roles(memRole)
                await member.remove_roles(role)

        @commands.hybrid_command(name='unmute', description='Unmutes the mentioned user.')
        @commands.has_permissions(manage_roles=True)
        async def unmute(self, ctx, member:discord.Member, *, reason=None):
            role = discord.utils.get(ctx.guild.roles, name="Muted")
            memRole = discord.utils.get(ctx.guild.roles, name='Member')
            await member.remove_roles(role)
            await member.add_roles(memRole)
            await ctx.send(f'Unmuted {member}.')

async def setup(client):
    await client.add_cog(Moderation(client))

问题根源

moderation.py的Cog类中,所有hybrid命令错误嵌套在__init__方法内部,discord.py无法识别这种嵌套结构中的命令,因此无法完成注册。

修复后的moderation.py代码

将所有hybrid命令从__init__方法中移出,作为Cog类的直接方法:

import asyncio
import re
import discord
from discord.ext import commands

# 自定义时间转换器实现(若原有代码已定义可忽略)
class TimeConverter(commands.Converter):
    async def convert(self, ctx, argument):
        units = {'d': 86400, 'h': 3600, 'm': 60, 's': 1}
        total = 0
        for match in re.findall(r'(\d+)([dhms])', argument.lower()):
            total += int(match[0]) * units[match[1]]
        return total if total else None

class Moderation(commands.Cog):
    def __init__(self, client):
        self.client = client

    @commands.hybrid_command(name='purge', description='Purges the given amount of messages from the channel.')
    @commands.has_permissions(manage_messages=True)
    async def purge(self, ctx, amount: int):
        await ctx.channel.purge(limit=amount)
        await ctx.send(f"Successfully cleared {amount} messages!")

    @commands.hybrid_command(name='kick', description='Kicks the mentioned user from the guild.')
    @commands.has_permissions(kick_members=True)
    async def kick(self, ctx, member: discord.Member, *, reason=None):
        await member.kick(reason=reason)
        await ctx.send(f"{member} has been kicked.")

    @commands.hybrid_command(name='mute', description='Mutes the mentioned user for the given amount of time.')
    @commands.has_permissions(manage_roles=True)
    async def mute(self, ctx, member:discord.Member, *, time:TimeConverter = None, reason=None):
        """Mutes a member for the specified time- time in 2d 10h 3m 2s format ex:
        &mute @Someone 1d"""
        role = discord.utils.get(ctx.guild.roles, name="Muted")
        memRole = discord.utils.get(ctx.guild.roles, name='Member')
        await member.remove_roles(memRole)
        await member.add_roles(role)
        await ctx.send(("Muted {} for {}s" if time else "Muted {}").format(member, time))
        if time:
            await asyncio.sleep(time)
            await member.add_roles(memRole)
            await member.remove_roles(role)

    @commands.hybrid_command(name='unmute', description='Unmutes the mentioned user.')
    @commands.has_permissions(manage_roles=True)
    async def unmute(self, ctx, member:discord.Member, *, reason=None):
        role = discord.utils.get(ctx.guild.roles, name="Muted")
        memRole = discord.utils.get(ctx.guild.roles, name='Member')
        await member.remove_roles(role)
        await member.add_roles(memRole)
        await ctx.send(f'Unmuted {member}.')

async def setup(client):
    await client.add_cog(Moderation(client))

补充说明

  • 修复时修正了kick方法中不必要的discord.Member.kick(member)调用,直接使用member.kick(reason=reason)更符合discord.py的使用规范。
  • 补充了TimeConverter的示例实现,若原有代码中已定义该转换器可直接替换或删除此部分。

内容的提问来源于stack exchange,提问作者Swift AU

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:44:57