如何让机器人休眠并停止响应命令(或 on_messages)
Posted
技术标签:
【中文标题】如何让机器人休眠并停止响应命令(或 on_messages)【英文标题】:How to make bot sleep and stop responding to commands (or on_messages) 【发布时间】:2019-07-16 20:55:10 【问题描述】:我正在尝试制作一个使机器人基本上处于睡眠模式的命令,这旨在使机器人停止响应命令(或 on_messages,如果可能的话)
尝试使用 client.pause (Boolean)
并没有给出错误我不知道它到底做了什么但没有任何反应
以下是我目前的位置。
@client.command(pass_context=True)
async def sleep(ctx):
client.pause = True
@client.command(pass_context=True)
async def awake(ctx):
client.pause = False
【问题讨论】:
您是否使用任何类型的数据库后端,您可以在其中保存变量,例如is_asleep
?
不,我没有使用它
没关系,这将是一个实例变量,尽管我会建议一些持久化变量的方法。
【参考方案1】:
您可以使用on_message
来覆盖机器人自动调用命令,然后构建一些逻辑让您决定它不想再接受任何命令(又名睡眠)。但请确保您作为 bot 所有者可以选择唤醒它,否则您是 SOL,需要重新启动。
类似下面的东西应该可以工作。
我的代码中假设您正在使用返工和 f 字符串是可以接受的,但是逻辑在这里并且几乎不需要更改我认为它与 @ 兼容987654325@ 版本。
基本控制流程:
bot.py
from discord.ext import commands
class MyBot(commands.bot):
def __init__(self, command_prefix = '!', description=None):
super().__init__(command_prefix, description)
#you could just say False here but if you
#want to start the bot asleep here's a decent way to do it.
self.asleep = kwargs.get('asleep', False)
async def is_owner(obj):
owner = self.application_info().owner
return obj.author == owner
async def on_message(self, message):
ctx = await self.get_context(message)
is_owner = client.is_owner(ctx):
if is_owner or not self.asleep:
self.invoke(ctx)
...
owner.py - 或您保存“仅限机器人所有者”命令的任何位置。
from discord.ext import commands
...
@commands.command()
async def sleep(self, ctx):
self.bot.asleep = True
await ctx.say(f"I am now asleep, I will only respond to ctx.author")
@commands.command()
async def awaken(self, ctx):
self.bot.asleep = False
await ctx.say("Ahhh, just woke up! Ready to take commands!")
...
launcher.py
import MyBot
...
bot = MyBot(...)
bot.load_extension("path/to/owner_py_file")
...
我是根据RDanny bot 在调用命令之前将它的数据库分配给每个上下文的方式提出的。这是一个写得很好的机器人,它的所有者为了教育目的公开了源代码。
编辑
以适应您当前的构建
对于您的情况,我假设您只是使用 client = commands.bot(...)
之类的东西创建一个机器人,这又是一个非常简单的做法,并且不允许您利用从子类化 bot
中获得的任何功能,但是您可以只需实现以下并获得与上述相同的功能:
client = commands.bot(...)
client.asleep = False
然后对于您在问题中显示的命令:
@client.command(pass_context=True)
async def sleep(ctx):
client.sleep = True
@client.command(pass_context=True)
async def awake(ctx):
client.asleep = False
然后是 on_message
覆盖。 请参考: this answer 以帮助解释为什么会这样。 甚至docs。提示提示
async def _is_owner(obj):
owner = self.application_info().owner
return obj.author == owner
@client.event()
async def on_message(message):
ctx = await self.get_context(message)
is_owner = _is_owner(ctx):
if is_owner or not self.asleep:
client.invoke(ctx)
如果上述实现对您不起作用,那么您可以给出我在上面链接的答案中描述的方法:
@client.event
async def on_message(message):
is_owner = _is_owner(ctx):
if is_owner or not client.asleep:
await bot.process_commands(message)
请注意我不知道你的模块是如何构成的,但如果这是在一个类中完成的,并且你在那个类中定义了_is_owner(...)
,你将需要使用is_owner = self._is_owner(...)
,尽管这可以在别处定义。
【讨论】:
说 kwargs 没有定义,我也没有使用 cogs,所以我在从 cogs 转换时可能在某个地方搞砸了 您不使用 cogs 有什么原因吗?另外,如果不是,那么而不是self.invoke
只是返回,然后将所有其他“命令”逻辑放在后面。
嗯。这确实可以解决问题,我没有使用 cogs,因为我已经开始编写我的机器人脚本并且没有使用 cogs,而且脚本太多了,所以将它们变成 cogs 需要一段时间
从长远来看,你会让事情变得更加困难。此外,“这并不能完全解决问题”并没有给我任何信息来帮助你。
它并不能修复未定义kwargs的错误,有没有什么办法可以在没有cogs的情况下重新制作scripot?【参考方案2】:
您可以使用 get_prefix 函数来更改 bot 命令,使其不会响应任何公共前缀。
backup_prefixes=['.','!','s.','k!']
prefixes = ['.','!','s.','k!']
def get_prefix(bot, msg):
return commands.when_mentioned_or(*prefixes)(bot, msg)
bot = commands.Bot(command_prefix=get_prefix)
@bot.event
async def on_ready():
print(bot.user.name)
@bot.command(pass_context=True)
async def resume(con):
for i in backup_prefixes:
prefixes.append(i)
@bot.command(pass_context=True)
async def pause(con):
prefixes.clear()
# prefixes.append("an unknow prefix so it can't be invoked") #Ex: aslkdjflkj2k4lkj21312kj
prefixes.append(',')
您还可以添加更多 if 语句,以确保只有某些用户可以使用该命令将机器人静音,使其不会响应其他用户。
【讨论】:
以上是关于如何让机器人休眠并停止响应命令(或 on_messages)的主要内容,如果未能解决你的问题,请参考以下文章
Discord.js - Discord 机器人停止响应命令