Python:通过齿轮和后台任务将消息发送到Discord中的特定通道

时间:2020-06-23 00:15:45

标签: python discord discord.py-rewrite

我有一个Discord Python机器人,我在其中尝试运行一个后台任务,该任务将每X秒不断向通道发送一条消息-无需任何命令。目前有5秒钟的任意时间用于测试。

这是有问题的齿轮文件(导入文件和未删除的文件以提高效率)

class TestCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.mytask.start()

    @tasks.loop(seconds=5.0)
    async def mytask(self):
        channel = client.get_channel(my channel id here)
        await channel.send("Test")

def setup(bot):
    bot.add_cog(TestCog(bot))

我感觉这是由于self参数是唯一传递的参数,但是我在阅读API文档中究竟要做什么时有些困惑。

我尝试使用client而不是bot,而是尝试定义discord.Client()(但就我所读的内容而言,我不应该使用一直在努力避免。

在其他使用实际命令的齿轮中,我进行了如下设置:

    @commands.command(name='test')
    async def check(self, ctx):
        if ctx.channel.name == 'channel name':
            await ctx.send("Response message")

这就是让我相信我传递的参数错误的原因。我了解是因为我通过ctx可以获取频道名称,但是我不太确定如何仅使用self来做到这一点。尝试传递ctx参数时,我没有收到任何错误,但是由于明显的原因,消息没有发送。

我在这里到底想念什么?感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

discord.Client对象没有get_channel()方法。您必须改为使用discord.Guild对象:

await client.get_guild(guild_id_here).get_channel(channel_id_here).send("Test")

Read the docs

答案 1 :(得分:0)

您可以使用.loop.create_task(mytask(arguments))将任务添加到asyncio循环中,然后在启动bot之前将其调用。 Read all about asyncio here

您可以像使用async def mytask(argument)那样的普通命令来定义任务,但是请忽略ctx,因为ctx基本上是您通常会获得的用于调用该函数的命令的所有上下文。 取而代之的是,您将要使用频道ID通过channel = bot.get_channel(id)手动获取频道对象,然后可以执行await channel.send("Your message")向该频道发送消息。

要使其循环,只需对while True使用asyncio.sleep(delay)循环来计时。 由于您必须等待消息发送的时间,因此可能导致计时方面的不准确,因此我建议在功能前使用clock = asyncio.create_task(asyncio.sleep(delay))启动计时任务,并在使用功能后使用{{1}捕获计时任务}

现在,如果您希望它在每个间隔的某个时间而不是从启动函数开始的固定间隔运行,您将要延迟函数的启动以匹配您设置的时间。您可以使用await clock来执行此操作,它返回商和时间的余数以及间隔,余数是自上一个间隔开始以来的时间。如果要在间隔开始时启动功能,可以使用divmod(time.time(), interval)使函数进入休眠状态,直到下一个间隔开始。如果要在该时间间隔中设置时间,则需要将其分为两个部分,一个用于设置时间已过,另一个用于尚未设置时间。

await asyncio.sleep(interval-remainder)

现在,如果将所有这些都加到一个函数中,您将得到如下内容(这是我在我的机器人中使用的一段代码:

if remainder < set_time: 
    await asyncio.sleep(set_time - remainder)
else:
    await asyncio.sleep(interval + set_time - remainder)

(我知道这不能100%回答问题,但是正如您所说的,您同时尝试了async def reminder(channel, interval, set_time, message): await bot.wait_until_ready() channel = bot.get_channel(channel) quotient, remainder = divmod(time.time(), interval) if remainder < set_time: await asyncio.sleep(set_time-remainder) else: await asyncio.sleep(set_time + interval - remainder) while True: clock = asyncio.create_task(asyncio.sleep(interval)) await channel.send(message) quotient, remainder = divmod(time.time(), interval) if remainder-set_time > 1: clock.cancel() await asyncio.sleep(interval-1) await clock bot.loop.create_task(reminder(774262090801479740, 3600, 3300, "This is the 55th minute of the hour")) bot.run(TOKEN) bot这个解决方案应该对您有用)