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
相关产品推荐
相关产品推荐

