Basically, I am writing a simple discord bot that tells me exactly how many days, hours, minutes and seconds left until a certain date. But while im importing datetime module, because the code would be still running, the starting date and time of the time until the certain date becomes the date and time that I have started the bots script and not up to date. I am somewhat a new python learner and don't know what to do. In conclusion, the think I want (I guess) is to make this code to be repeatedly refresh its data of date and time. Thank you. Mankitsu
I've tried to make it in a loop I have no idea if it would work but either I messed up or it just shouldn't be done like that.
The answer is using tasks
. This allows you to execute some code at repeatable intervals. So let's create a basic task for what you want to do. Let's say we want to countdown until Christmas.
# in a "christmas_task.py" file or similar
import datetime
import discord
from discord.ext import tasks, commands
class ChristmasCountdown(commands.Cog):
def __init__(self, client: discord.Client, channel_id: int, message_id: int = None):
self.client = client
self.channel_id = channel_id
self.message_id = message_id
self.date = datetime.datetime(year=2023, month=12, day=25)
def cog_unload(self):
self.countdown.cancel()
@tasks.loop(minutes=1)
def countdown(self):
now = datetime.datetime.now()
difference = date - now
# convert difference.seconds into hours/minutes/seconds
hours, remainder = divmod(difference.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
message_content = (
"**Countdown to Christmas\n**"
f"`{difference.days}` days, `{hours}` hours, and `{minutes}` minutes!"
)
if not self.message_id:
# send the message as we haven't got one yet
channel = await self.client.fetch_channel(self.channel_id)
message = await channel.send(content=message_content)
self.message_id = message.id
else:
channel = await self.client.fetch_channel(self.channel_id)
message = await channel.fetch_message(self.message_id)
await message.edit(content=message_content)
@countdown.before_loop
async def before_countdown(self):
await self.client.wait_until_ready()
And then in your main file:
# import it somewhere
from christmas_task import ChristmasCountdown
# and just make sure to instantiate it before `client.run`
task = ChristmasCountdown(client, MY_CHRISTMAS_CHANNEL_ID)
# if you already have a message ID here then you can insert it
# task = ChristmasCountdown(client, MY_CHRISTMAS_CHANNEL_ID, MY_MESSAGE_ID)
client.run(TOKEN)
This is a basic example - it'll only work for one guild/channel. But hopefully an idea on how to do it and you can adapt it for your needs.