How to Make Discord Bot Automatically Post Messages at Scheduled Time

I want to build a discord bot that automatically posts weather updates every morning at 8 AM based on the user’s timezone. The bot should send temperature and precipitation data without anyone having to trigger it with a command.

Right now I have some helper functions that get the current time in “HH:MM:SS” format, but I can’t figure out how to make the bot check for the specific time and send messages automatically.

import discord
from discord.ext import commands
from timeUtils import getLocalTime

intents = discord.Intents.all()
bot = commands.Bot(command_prefix="?", intents=intents)
api_token = "your_token_here"

@bot.event
async def on_ready():
    print("Bot is online and ready!")

@bot.command()   
async def about(ctx):
    await ctx.send("Hi! I'm your daily weather bot!")
    await ctx.send("I post weather updates automatically at 8 AM each day.")

# This doesn't work - not sure how to trigger without command
if (getLocalTime() == '08:00:00'):
    async def daily_forecast(ctx):
        await ctx.send("Weather data will go here")
        await ctx.send("This message never appears")

bot.run(api_token)

I’ve tried different approaches but I can’t find a way to make the bot run functions automatically without using commands. The discord.py docs don’t seem to cover scheduled tasks clearly.

you could also throw asyncio.sleep in a while loop. while True: await asyncio.sleep(60) then check your time inside. not as clean as using tasks but it works if u don’t want extra imports. just run it as a background task or it’ll block everything.

Your code only checks the time once when it starts - you need it checking continuously. Use discord.py’s task extension for scheduled tasks. Here’s what you want:

from discord.ext import tasks

@tasks.loop(minutes=1)
async def check_weather_time():
    if getLocalTime() == '08:00:00':
        channel = bot.get_channel(your_channel_id)
        await channel.send("Weather data will go here")

@bot.event
async def on_ready():
    print("Bot is online and ready!")
    check_weather_time.start()

I’ve run similar bots for months - this works great. The loop decorator checks every minute for 8 AM. Just remember to start the task in on_ready or it won’t work. Also, you’ll need to hardcode your channel ID since there’s no ctx in scheduled tasks.

Your conditional check only runs once when the bot starts up, not continuously. Use asyncio.create_task() with the schedule library instead of checking every minute - way more efficient than constant polling.

Here’s a cleaner approach:

import asyncio
import schedule
import threading

def job():
    asyncio.create_task(send_weather())

async def send_weather():
    channel = bot.get_channel(channel_id)
    await channel.send("Your weather data here")

schedule.every().day.at("08:00").do(job)

# Run scheduler in separate thread
def run_scheduler():
    while True:
        schedule.run_pending()
        time.sleep(60)

scheduler_thread = threading.Thread(target=run_scheduler)
scheduler_thread.start()

This schedules exactly at 8 AM instead of checking every minute. I’ve used this pattern for production bots and it handles timezone changes much better.