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

Viewed 80

I am trying to write a discord bot that posts yeterday's Wordle solutions but I cannot seem to figure out how to get a task to be invoked by a message and then have that task loop. I tried to use a while loop but then the bot would only work for one server. Trying to use a looping task does not work either. Here is the code

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

Either the bot gets stuck at setup, or the the task doesn't loop in 10 seconds, or the bot only works for one server. I use the setup command to prevent needing to hardcode the channel id into the code.

1 Answers

I have solved the issue by wrapping the code in a client class and allowing the storage of multiple channel ids. The new code is shown here.

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

Related