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

Discord Bot异常:!decklist内on_message干扰!boh命令执行

Discord Bot 命令冲突问题解决

我的Discord Bot目前能正常执行!decklist命令,但触发if not message.attachments分支后,执行!boh命令时,机器人既会回复该分支的提示内容,又会执行!boh命令。需要解决的问题是:如何正确退出!decklist命令,避免使用其他命令时触发该分支。

原问题代码

import discord
from discord.ext import commands
from io import BytesIO

TOKEN = 'disc_token'

def run():
    intents = discord.Intents.default()
    intents.message_content = True
    intents.members = True
    bot = commands.Bot(command_prefix="!", intents = intents)
    
    #ON_READY
    @bot.event
    async def on_ready():
        #SERVER = bot.get_guild(int(1156534000890953748))
        bot_name = await bot.fetch_user(int(1155959555876991098))
        await bot.tree.sync()
        print(f'{bot_name}si è connesso a Discord')

    #SENDS USER EMBED TO RESPOND WITH IMAGE.
    @bot.command()
    async def decklist (ctx):
        """Riceve l'immagine della Decklist e la invia per la conferma"""
        embed = discord.Embed(
        colour = discord.Colour.dark_magenta(),
        title = ("Dreamborn"),
        url = ("https://dreamborn.ink/")
        )
        embed.set_image(url="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKCp5PneGn0VgoP-Hncj4AxiN-Ql2tqaKd6w&usqp=CAU")
        await ctx.send(f"Mandami l'immagine della Decklist esportata da **Dreamborn!**", ephemeral=True)
        await ctx.send(embed=embed)
        @bot.event
        async def on_message(message):
            await bot.process_commands(message)
            if message.author == bot.user:
                return
            if message.author.bot:
                return
            if not message.attachments:
                #ignore (message=bot.command())
                await message.author.send('Ciao! La tua lista non è **idonea**.
Mandami una **immagine!**')
                pass
            image_file = message.attachments[0]
            image_bytes = await image_file.read()
            liste = bot.get_channel(int(1156534533907288064))
            istruzioni = bot.get_channel(int(1156626680794845234))
            await liste.send('**' + message.author.display_name + '**')
            await liste.send(file=discord.File(fp=BytesIO(image_bytes), filename=image_file.filename))
            await message.author.send('Oki doki, Decklist inviata! 
Metti la reazione al messaggio su' + istruzioni.mention + 'per essere Confermato! 
Se invece avevi già messo la reazione a Confermati, ignora!')
            await bot.process_commands(message)

    #REPLY WITH "HELLO"
    @bot.command()
    async def boh(ctx):
        await ctx.send(f"ciao!")

    bot.run(TOKEN)
run()

问题根源

你在!decklist命令内部嵌套定义了全局的on_message事件监听器,每次调用!decklist都会新增一个监听器。后续所有消息(包括其他命令)都会被这个额外的监听器处理,导致命令冲突。

修正方案

移除命令内部的on_message事件,改用wait_for来监听用户的后续回复,这是Discord.py处理命令交互的标准方式,仅在当前命令上下文内生效,不会干扰其他命令。

修正后的完整代码

import discord
from discord.ext import commands
from io import BytesIO

TOKEN = 'disc_token'

def run():
    intents = discord.Intents.default()
    intents.message_content = True
    intents.members = True
    bot = commands.Bot(command_prefix="!", intents=intents)
    
    # ON_READY
    @bot.event
    async def on_ready():
        bot_name = await bot.fetch_user(int(1155959555876991098))
        await bot.tree.sync()
        print(f'{bot_name} si è connesso a Discord')

    # SENDS USER EMBED TO RESPOND WITH IMAGE.
    @bot.command()
    async def decklist(ctx):
        """Riceve l'immagine della Decklist e la invia per la conferma"""
        embed = discord.Embed(
            colour=discord.Colour.dark_magenta(),
            title="Dreamborn",
            url="https://dreamborn.ink/"
        )
        embed.set_image(url="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKCp5PneGn0VgoP-Hncj4AxiN-Ql2tqaKd6w&usqp=CAU")
        await ctx.send(f"Mandami l'immagine della Decklist esportata da **Dreamborn!**", ephemeral=True)
        await ctx.send(embed=embed)

        # 仅监听当前命令发起者在同一频道的消息
        def check(message):
            return message.author == ctx.author and message.channel == ctx.channel

        try:
            # 设置60秒超时,避免命令一直挂起
            message = await bot.wait_for('message', check=check, timeout=60.0)
        except TimeoutError:
            await ctx.author.send("Timeout! Non hai inviato l'immagine in tempo.")
            return

        if not message.attachments:
            await message.author.send('Ciao! La tua lista non è **idonea**. Mandami una **immagine!**')
            return

        image_file = message.attachments[0]
        image_bytes = await image_file.read()
        liste = bot.get_channel(int(1156534533907288064))
        istruzioni = bot.get_channel(int(1156626680794845234))
        await liste.send(f'**{message.author.display_name}**')
        await liste.send(file=discord.File(fp=BytesIO(image_bytes), filename=image_file.filename))
        await message.author.send(f'Oki doki, Decklist inviata! \nMetti la reazione al messaggio su {istruzioni.mention} per essere Confermato! \nSe invece avevi già messo la reazione a Confermati, ignora!')

    # REPLY WITH "HELLO"
    @bot.command()
    async def boh(ctx):
        await ctx.send(f"ciao!")

    bot.run(TOKEN)
run()

关键改进点

  • 使用wait_for替代全局on_message,仅在!decklist命令的上下文内监听用户回复,不会影响其他命令。
  • check函数确保只处理当前命令发起者的消息,避免误处理其他人的输入。
  • 添加超时机制,防止命令无限等待用户输入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 20:50:53