首页 > 解决方案 > 如何在 discord.py bot 中一次只能运行一个命令或事件

问题描述

我正在尝试解决一个问题,我的 discord 机器人(迷你游戏)中有许多命令和事件,我希望用户一次只能使用一个命令,所以如果有一个迷你游戏已经在运行,其他命令或事件不能使用。所以我创建了on_command变量,在每个命令和事件的开头,变量变为 1,在每个命令和事件结束时,变量变回 0。因此,如果有人尝试使用某个命令或事件并且变量为 1 ,机器人只是向他发送他现在无法使用该命令。但由于某种原因,它不起作用,我收到下一个错误:

discord.ext.commands.errors.CommandInvokeError: Command raised an exception: UnboundLocalError: local variable 'on_command' referenced before assignment

我的代码:

on_command = 0

@bot.command()
@commands.cooldown(1, 180.0, commands.BucketType.guild)
async def question(msg):
    if msg.channel.id != channel:
        return
    if on_command == 1:
        await msg.send("Another command or event is running")
        return
    on_command = 1
    ....
    ....
    ....
    on_command = 0

标签: pythonpycharmdiscord.pydiscord.py-rewrite

解决方案


  1. 您应该将on_command变量重命名为其他名称(discord.py 使用on_command事件,如果您将来要使用它,您应该重命名它)。
  2. 变量永远不会真正改变,on_command你应该使用global关键字。
  3. 您当前的解决方案一次只允许1 个用户使用该机器人(如果其他人想使用它,他将无法使用)

一种解决方案是创建一个名为current_users(或其他)的机器人变量,在任何命令之前进行全局检查,并检查用户是否可以玩,当命令完成时将他从变量中删除

bot.current_users = set() # Empty set

@bot.check
async def is_user_playing(ctx):
    if not ctx.author in bot.current_users:
        # The user can play a game, add him to the set
        bot.current_users.add(ctx.author)
        return True

    return False


@bot.command()
async def test(ctx):
    """Command for testing"""
    await ctx.send("Starting game...")
    await asyncio.sleep(100)
    await ctx.send("Finishing game... You can play other games now")


@bot.event
async def on_command_completion(ctx):
    # Removing the user when he finishes playing a game
    bot.current_users.remove(ctx.author)


@bot.event
async def on_command_error(ctx, error):
    if isinstance(error, commands.CheckFailure):
        # The user can't play games, send the message here
        await ctx.send("You can't play more games, please finish your current game")

注意:事件的工作方式不同,您需要手动完成

@bot.event # Example event
async def on_message(message):
    if message.author in bot.current_users:
        return await message.channel.send("You can't play games...")

    bot.current_users.add(message.author)
    # ...
    bot.current_users.remove(message.author)


# Another example event
@bot.event
async def on_reaction_add(reaction, user):
    if user in bot.current_users:
        return await reaction.message.channel.send("...")

    bot.current_users.add(user)
    # ...
    bot.current_users.remove(user)

参考:


推荐阅读