如何在 discord.py bot 中一次仅运行一个命令或事件

时间:2021-01-19 19:57:10

标签: python pycharm discord.py discord.py-rewrite

我正在尝试解决一个问题,我的 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

2 个答案:

答案 0 :(得分:2)

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

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

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)

参考:

答案 1 :(得分:1)

使用 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