如何在discord.py事件循环中添加函数?

时间:2018-08-04 20:21:37

标签: python bots discord

我正在将Python与discord.py一起使用。文档 here

我有一个在Discord服务器上运行的机器人,该机器人将服务器与subreddit链接在一起。用户具有各种命令,可以执行诸如获取最高提交,获取最新提交等操作。

我想向机器人添加一些功能,其中之一是关键字通知程序。机器人应该在subreddit中搜索标题中的关键字,然后通知用户列表中是否包含该关键字。我知道如何做到这一点,我已经做了很多次,但是我不知道如何使用Discord机器人来做到这一点。我没有使用asynchio或任何类型的异步编程的经验。

我尝试执行此操作的方式有效,但它非常简陋,绝对不好。在on message()函数的顶部,我只添加了对search_submissions()函数的调用,这样,只要有人放置在服务器上发送新消息,该漫游器就会扫描Reddit提交。服务器很忙,可以正常工作,但是我真的想以“适当”的方式来做。

我不知道如何在不将search_submissions()放入on_message()内的情况下调用它。


编辑其他代码:

import discord

TOKEN = "redacted"
client = discord.Client()

@client.event
async def reddit_search():
    print("Searching")

@client.event
async def on_message(message):
    if message.content.startswith("reddit!hot"):
        # Get hot
    # Do other things.

@client.event
async def on_ready():
    print("Connected to Discord as {}.".format(client.user.name))

client.run(TOKEN)

3 个答案:

答案 0 :(得分:2)

您可以使用Client.loop.create_task(search_submissions())向bot事件循环添加一个函数,如下所示:

async def search_submissions():
    pass

client = discord.Client()

client.loop.create_task(search_submissions())
client.run(TOKEN)


更新

如果您希望函数继续运行,可以将其置于while循环中,并在它们之间进行一些睡眠:

async def search_submissions():
    while(true):
        # do your stuff
        await asyncio.sleep(1)

答案 1 :(得分:1)

此处的其他答案未考虑discord.py有用的tasks.loop装饰器。

要使事件每5秒发生一次,您可以使用

from discord.ext import tasks, commands

class MyCog(commands.Cog):
    def __init__(self):
        self.foo.start()

    def cog_unload(self):
        self.printer.cancel()

    @tasks.loop(seconds=5.0)
    async def foo(self):
        print('bar')

更多信息可以在这里找到:https://discordpy.readthedocs.io/en/latest/ext/tasks/

答案 2 :(得分:0)

您希望search_submissions()函数是 async ,因此您的漫游器的其他功能仍然可以调用,并且漫游器保持响应状态。将其定义为def async并使用aiohttp将异步HTTP请求发送到reddit -这样做是发送请求,将控制放到事件循环中,然后在结果获得后再收回控制被传送回来。如果您在此处使用标准的HTTP库,则整个机器人将被阻止,直到结果返回为止。当然,只有当任务主要是受I / O约束而较少受CPU约束时,这才有意义。

然后在search_submissions()中调用on_message(message),但是使用result = await search_submissions()异步地 调用它。一旦on_message的结果准备就绪,它将恢复执行search_submissions

如果您确实想在等待search_submissions的同时在同一上下文中执行 (我认为这不太可能),请将其作为task = asyncio.create_task(search_submissions())分发。这将立即启动任务,并允许您在同一函数中执行其他操作。一旦需要结果,就必须result = await task

async def search_submissions():
    async with aiohttp.ClientSession() as session:
        async with session.get(some_reddit_url) as response:
            return await response.read()

@client.event
async def on_message(message):
    if message.content.startswith("reddit!hot"):
        result = await search_submissions()
        await message.channel.send(result)