如何让机器人休眠并停止响应命令(或 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)的主要内容,如果未能解决你的问题,请参考以下文章

Linux休眠,挂起,待机,关机的区别及相关命令

如何让我的机器人消息响应特定频道中的命令

Discord.js - Discord 机器人停止响应命令

你如何让 Discord 机器人响应 DM 中的命令? (Python)

如何让我的脚本不断检查变量?

Discord.py 机器人:如何让我的不和谐机器人向我发送对用户在 DM 中使用的命令的响应,例如进行调查?