Python开发Discord机器人:服务器内创建的自定义命令无法触发问题求助
Python开发Discord机器人:服务器内创建的自定义命令无法触发问题求助
我正在用Python开发一个Discord机器人,想要实现服务器内创建自定义命令的功能——也就是通过机器人自带的命令来生成新的自定义指令,指令触发后机器人会回复预设内容。根据查到的资料,我需要用字典来存储这些自定义命令的映射关系,于是参考了一份旧教程写出了下面的代码(感谢原作者Furas):
import discord from discord.ext import commands new_dict = {} bot = commands.Bot(command_prefix='>', intents=discord.Intents.all()) @bot.command('create') async def create(ctx, *args): print("Hey it works") print('[create] ctx:', ctx) print('[create] args:', args) if len(args) >= 2: key = '!' + args[0] val = args[1] new_dict[key] = val async def on_message(msg, *args): if msg.author.bot: return cmd, *args = msg.content.split(' ') if cmd in new_dict: answer = new_dict[cmd] await msg.reply(answer) else: # send to other commands await bot.process_commands(msg) cmd, *args = msg.content.split(' ') if cmd in new_dict: answer = new_dict[cmd] await msg.reply(answer) else: # send to other commands - like `!create` await bot.process_commands(msg) bot.run('THE TOKEN')
预期功能
当我输入>create并跟上参数时,希望机器人生成一个自定义命令:第一个参数作为命令名,第二个参数(或后续所有内容)作为机器人的回复内容。
举个例子:
输入:
>create cat meow
期望效果:之后输入>cat,机器人回复meow
目前遇到的问题
执行>create命令时,终端能打印出Hey it works和参数内容,说明create命令本身能被触发,但自定义命令创建完成后,输入触发词会提示CommandNotFound错误,完全无法触发预设的回复。机器人已经正常上线,消息意图也已开启,终端日志如下:
2025-03-18 23:21:38 INFO discord.client logging in using static token 2025-03-18 23:21:39 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: 996c857e3c3c141b35d24977f6a9e025). Hey it works [create] ctx: <discord.ext.commands.context.Context object at 0x000001B2BDA1F6E0> [create] args: () Hey it works [create] ctx: <discord.ext.commands.context.Context object at 0x000001B2BC4DBB30> [create] args: ('cat', 'meow') 2025-03-18 23:22:01 ERROR discord.ext.commands.bot Ignoring exception in command None discord.ext.commands.errors.CommandNotFound: Command "cat" is not found
问题分析与修复方案
你的代码里有几个关键问题导致自定义命令无法正常触发,我来逐一说明并给出修复后的完整代码:
on_message未注册为事件监听器:你定义了on_message函数,但没有用@bot.event装饰器标记,机器人根本不会执行这个函数里的逻辑!- 自定义命令的键名前缀错误:你在
create命令里把键设为! + args[0],但机器人默认前缀是>,这导致字典里存的是!cat,但你实际输入的是>cat,自然匹配不到。 on_message存在重复逻辑:你写了两遍完全一样的命令匹配代码,不仅冗余还可能引发逻辑冲突。- 回复内容只能支持单单词:原始代码仅取第二个参数作为回复,无法处理多单词的回复内容。
修复后的完整代码
import discord from discord.ext import commands # 存储自定义命令:键是完整触发命令(比如">cat"),值是回复内容 custom_commands = {} # 初始化机器人,前缀为">",开启所有必要意图 bot = commands.Bot(command_prefix='>', intents=discord.Intents.all()) @bot.command(name='create') async def create_custom_command(ctx, cmd_name: str, *, response: str): """创建自定义命令:用法 >create 命令名 回复内容(回复内容支持多单词)""" print(f"[create] 收到创建请求:命令名={cmd_name},回复内容={response}") # 拼接完整的命令触发词(带上机器人的前缀) full_cmd = f"{bot.command_prefix}{cmd_name}" custom_commands[full_cmd] = response await ctx.reply(f"自定义命令`{full_cmd}`已创建完成!触发后我会回复:{response}") @bot.event async def on_message(msg): # 忽略机器人自己的消息,避免循环 if msg.author.bot: return # 先提取完整的触发命令(比如">cat") full_cmd = msg.content.split(' ')[0] # 检查是否是自定义命令 if full_cmd in custom_commands: await msg.reply(custom_commands[full_cmd]) else: # 交给机器人处理自带命令(比如>create) await bot.process_commands(msg) # 运行机器人 bot.run('你的机器人TOKEN')
改动说明
- 注册事件监听器:给
on_message加上@bot.event装饰器,确保机器人执行该逻辑。 - 修正命令前缀:用
bot.command_prefix拼接命令名,保证存储的键和实际输入的触发命令完全一致。 - 支持多单词回复:用
*, response: str作为参数,能接收命令名之后的所有内容作为回复(比如>create greet 欢迎来到服务器!)。 - 简化逻辑:删除重复的命令匹配代码,让逻辑更清晰。
- 语义化命名:把
new_dict改成custom_commands,提升代码可读性。
测试效果
- 输入
>create cat meow,机器人会回复确认消息; - 之后输入
>cat,机器人会立刻回复meow; - 还能创建多单词回复的命令,比如
>create greet 欢迎来到服务器!有问题随时找管理~,输入>greet就能收到完整回复。
备注:内容来源于stack exchange,提问作者Soopah
相关产品推荐
相关产品推荐

