如何制作在 Python 中发布消息时调用的循环 Discord Bot 任务

How to Make a Looping Discord Bot Task that is Invoked When a Message is Posted in Python

我正在尝试编写一个发布昨天的 Wordle 解决方案的 discord 机器人,但我似乎无法弄清楚如何让消息调用任务,然后让该任务循环。我尝试使用 while 循环,但该机器人只能在一台服务器上工作。尝试使用循环任务也不起作用。这是代码

import imp
import json
import requests
import discord
import os
import time
from datetime import date, timedelta
from discord.ext import tasks


client = discord.Client()
#channel_id_exists = False
#channel_id = 0


@client.event
async def on_ready():
    print('We have logged in as {0.user}'.format(client))


@client.event
async def on_message(message):
    if message.author == client.user:
        return

    if message.content.startswith('!wordle_setup'):
        await message.delete()
        await message.channel.send("Setting up...")
        channel_id = message.channel.id
        await wordle_guess(channel_id).start()


@tasks.loop(seconds=10)
async def wordle_guess(channel_id):

    message_channel = client.get_channel(channel_id)
    yesterday = date.today() - timedelta(days=1)

    year = yesterday.year
    month = yesterday.month
    day = yesterday.day

    word_guess = json.loads(requests.get(
        "https://najemi.cz/wordle_answers/api/?day={0}&month={1}&year={2}".format(day, month, year)).text)["word"]
    await message_channel.send("Word guess for " + yesterday.isoformat() + " : " + word_guess + '\nhttps://www.merriam-webster.com/dictionary/' + word_guess)

client.run("TOKEN")

机器人在设置时卡住,或者任务没有在 10 秒内循环,或者机器人只适用于一台服务器。我使用设置命令来防止需要将频道 ID 硬编码到代码中。

我已通过将代码包装在客户端 class 中并允许存储多个频道 ID 解决了这个问题。新代码显示在这里。

import asyncio
import imp
import json
import requests
import discord
import os
import time
from datetime import date, timedelta
from discord.ext import tasks
import threading

print("test!")


class MyClient(discord.Client):
    channel_id = []
    channel_id_exists = False

    async def on_ready(self):
        print('We have logged in as {0.user}'.format(self))

    async def on_message(self, message):
        if message.author == self.user:
            return

        if message.content.startswith('!wordle_setup'):
            await message.delete()
            await message.channel.send("Setting up...")
            self.channel_id.append(message.channel.id)
            self.channel_id_exists = True

    @tasks.loop(seconds=3600*24)
    async def wordle_guess(self):
        if self.channel_id_exists:

            yesterday = date.today() - timedelta(days=1)

            year = yesterday.year
            month = yesterday.month
            day = yesterday.day

            for channel_id_iter in self.channel_id:
                message_channel = self.get_channel(channel_id_iter)
                word_guess = json.loads(requests.get(
                    "https://najemi.cz/wordle_answers/api/?day={0}&month={1}&year={2}".format(day, month, year)).text)["word"]
                await message_channel.send("Wordle guess for " + yesterday.isoformat() + " : " + word_guess + '\nhttps://www.merriam-webster.com/dictionary/' + word_guess)


client = MyClient()
client.wordle_guess.start()
client.run("TOKEN")