如何在 discord.py 机器人中一次只能 运行 一个命令或事件

How to make to be able to run only one command or event at a time in 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

使用python的global

on_command = 0

@bot.command()
@commands.cooldown(1, 180.0, commands.BucketType.guild)
async def question(msg):
    global on_command 
    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
  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)

参考: