如何在 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
- 您应该将
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)
参考:
我正在尝试解决一个问题,我的 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
- 您应该将
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)