python - 如何在 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
解决方案
- 您应该将
on_command
变量重命名为其他名称(discord.py 使用on_command
事件,如果您将来要使用它,您应该重命名它)。 - 变量永远不会真正改变,
on_command
你应该使用global
关键字。 - 您当前的解决方案一次只允许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)
参考:
推荐阅读
- php - 如何从 PHP 中获取今天设置的数据?
- linux - Docker Swarm(现有)安装中的 userns-remap 选项
- java - 连接规范内的表
- c# - 是否可以在特定消息 ID 后收到电子邮件
- python - 编写正则表达式以查找字符串的开头和结尾是否有特殊字符,(忽略空格)
- xamarin.forms - Xamarin Syncfusion 图表不显示来自本地数据库的绑定数据
- node.js - Google Cloud App Engine - req.user 未定义
- python - 无法导入 tensorflow - 无法加载本机 tensorflow 运行时
- c# - SMTP HTML 电子邮件未通过 Gmail 电子邮件客户端呈现 HTML
- json - 在 Python 3.6 JSON 模块中,为什么我必须同时使用加载和加载?