Search code examples
pythondiscorddiscord.pybots

why does my discord tasks start at random times?


I built a bot to ping people at certain time in the day (for fun lol) but the bot seems to randomly ping at random times in the day and doesn't print a message to terminal as it should've if it were a usual ping. This has happened twice already and caused a lot of frustration since obviously people don't really like getting pinged for no reason. I'm hosting this bot on Bot-Hosting.

Here's my code:

import discord
from datetime import time, datetime, timezone, timedelta, today
from discord.ext import tasks, commands
from time import sleep


def run():
    time_role = time(16,7,0, tzinfo=timezone(timedelta(hours=a certain timezone)))
    time_person = time(16,7,0, tzinfo=timezone(timedelta(hours=another certain timezone)))
    channel_id = # channel id
    server_id = # server id
    #gives the bot message content intent
    intents = discord.Intents.default()
    intents.message_content = True

    TOKEN = "my token obviously"
    client = discord.Client(intents = intents)

                 
    #pings @role A at time_role
    @tasks.loop(time=time_role)
    async def send_time():
        await client.get_channel(channel_id).send("<@&role A id>")
        await client.get_channel(channel_id).send("get ready guys")
        print("sent role A ping at " + today().strftime('%m-%d %H:%M:%S')) 
    #the above two lines were NOT SENT along with the unexpected pings
    
    #pings @person A at time_person
    @tasks.loop(time=time_person)
    async def send_person(): 
        await client.get_channel(channel_id).send("<@person A id>")
        await client.get_channel(channel_id).send("get ready person A")
        print("sent person A ping at " + today().strftime('%m-%d %H:%M:%S'))
    #the above two lines were NOT SENT along with the unexpected pings


    @client.event
    async def on_ready():
        print(f"{client.user} is now online!\ntime: "today().strftime('%m-%d %H:%M:%S'))
        if not send_time.is_running():
            send_time.start()
            print("started role ping")
        if not send_person.is_running():
            send_person.start()
            print("started person ping")

    client.run(TOKEN)
run()

screenshot of one of the unexpected pings


Solution

  • I think the issue here is that your timezone has some problems with setting the correct one or the time= attribute of @tasks.loop doesn't work as you expect - overall I can't find the cause of your problem.

    But an other issue that your user mentions sometimes does NOT work can be caused because the bot's cache is not ready. If that's the case, you get None for things like client.get_channel - you should wait until the bot's cache is ready with await self.client.wait_until_ready().

    That's why I recommend you switch to an APScheduler with Cron to schedule your user mentions to be sent at a specific time.

    from apscheduler.schedulers.asyncio import AsyncIOScheduler
    from apscheduler.triggers.cron import CronTrigger
    from discord.ext import commands
    import discord
    
    client = discord.Client(intents = intents)
    
    async def send_time():
        # wait until cache is ready
        await self.client.wait_until_ready()
    
        await client.get_channel(channel_id).send("<@&role A id>")
        await client.get_channel(channel_id).send("get ready guys")
        print("sent role A ping at " + today().strftime('%m-%d %H:%M:%S')) 
    
    async def send_person(): 
        # wait until cache is ready
        await self.client.wait_until_ready()
    
        await client.get_channel(channel_id).send("<@person A id>")
        await client.get_channel(channel_id).send("get ready person A")
        print("sent person A ping at " + today().strftime('%m-%d %H:%M:%S'))
    
    @bot.event
    async def on_ready():
        print("Ready")
    
        #initializing scheduler
        scheduler = AsyncIOScheduler()
    
        # add your functions to the scheduler
        scheduler.add_job(send_time, CronTrigger(hour="16", minute="7", second="0"))
        scheduler.add_job(send_person, CronTrigger(hour="16", minute="7", second="0")) 
    
        #starting the scheduler
        scheduler.start()