如何使机器人睡眠并停止响应命令(或on_messages)

5 python python-3.x discord discord.py

我正在尝试制作一个命令,使机器人基本上处于睡眠模式,这是为了让机器人停止响应命令(或如果可能的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
Run Code Online (Sandbox Code Playgroud)

Jab*_*Jab 2

您可以使用on_message自动覆盖机器人调用命令,然后构建一些逻辑来决定它不再接受任何命令(也称为睡眠)。但请确保您作为机器人所有者可以选择唤醒它,否则您将无法正常工作并且需要重新启动。

像下面这样的东西应该有效。

我的代码中的假设是您正在使用返工和 f 字符串是可以接受的,但逻辑就在这里,我认为几乎不需要更改即可与版本兼容async

基本控制流程:

机器人.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)

...
Run Code Online (Sandbox Code Playgroud)

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!")

...
Run Code Online (Sandbox Code Playgroud)

启动器.py

import MyBot

...

bot = MyBot(...)
bot.load_extension("path/to/owner_py_file")

...
Run Code Online (Sandbox Code Playgroud)

我根据RDanny机器人在调用命令之前将其数据库分配给每个上下文的方式想出了这一点。这是一个编写得非常好的机器人,所有者已出于教育目的公开发布了源代码。


编辑

以适应您当前的构建

对于您的情况,我假设您只是使用类似的东西创建一个机器人,client = commands.bot(...)这又很千篇一律,并且不允许您利用从子类化中获得的任何能力bot,但您可以实现以下内容并获得相同的功能如上:

client = commands.bot(...)
client.asleep = False
Run Code Online (Sandbox Code Playgroud)

然后对于您在问题中显示的命令:

@client.command(pass_context=True)
async def sleep(ctx):
    client.sleep = True

@client.command(pass_context=True)
async def awake(ctx):
    client.asleep = False
Run Code Online (Sandbox Code Playgroud)

然后进行on_message覆盖。请参考: 这个答案来帮助解释为什么它有效。甚至文档。提示提示

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)
Run Code Online (Sandbox Code Playgroud)

如果上述实现对您不起作用,那么您可以提供我上面链接的答案中描述的方法:

@client.event
async def on_message(message):
    is_owner = _is_owner(ctx):
    
    if is_owner or not client.asleep:        
        await bot.process_commands(message)
Run Code Online (Sandbox Code Playgroud)

请注意,我不知道您的模块是如何构造的,但如果这是在一个类中完成的,并且您_is_owner(...)在该类中定义,则您将需要使用is_owner = self._is_owner(...),尽管这可以在其他地方定义。