【问题标题】:How to make to be able to run only one command or event at a time in discord.py bot如何在 discord.py bot 中一次只能运行一个命令或事件
【发布时间】:2021-04-24 04:08:34
【问题描述】:

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


    【解决方案1】:
    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)
    

    参考:

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 感谢您的帮助,discord.py 中是否有一些功能会在命令或事件在一段时间内未完成时自动停止运行?
      • 遗憾的是没有@garadosix
      猜你喜欢
      • 2021-04-09
      • 1970-01-01
      • 1970-01-01
      • 2021-04-16
      • 1970-01-01
      • 1970-01-01
      • 2021-03-29
      • 1970-01-01
      • 2020-11-02
      相关资源
      最近更新 更多