kreendurron / BRC-Bot

A Discord Bot for The Bible Reading Challenge
1 stars 1 forks source link

Add Automatic Post Feature for Daily Reading Plan #7

Open kreendurron opened 2 years ago

kreendurron commented 2 years ago

Currently the !day command must be used manually in a channel.

Add ability for bot to display the daily reading plan automatically each day.

Options

Add option for admin to specify what time the bot will post daily.

Add option to toggle automatic posting on/off

https://github.com/kreendurron/BRC-Bot/blob/8c56c4467af6088e5a98cbb975e47ab5981928af/cogs/plan.py#L34

kreendurron commented 2 years ago

Here's an implementation:

from discord.ext import commands
from datetime import datetime, time, timedelta
import asyncio

bot = commands.Bot(command_prefix="$")
WHEN = time(18, 0, 0)  # 6:00 PM
channel_id = 1 # Put your channel id here

async def called_once_a_day():  # Fired every day
    await bot.wait_until_ready()  # Make sure your guild cache is ready so the channel can be found via get_channel
    channel = bot.get_channel(channel_id) # Note: It's more efficient to do bot.get_guild(guild_id).get_channel(channel_id) as there's less looping involved, but just get_channel still works fine
    await channel.send("your message here")

async def background_task():
    now = datetime.utcnow()
    if now.time() > WHEN:  # Make sure loop doesn't start after {WHEN} as then it will send immediately the first time as negative seconds will make the sleep yield instantly
        tomorrow = datetime.combine(now.date() + timedelta(days=1), time(0))
        seconds = (tomorrow - now).total_seconds()  # Seconds until tomorrow (midnight)
        await asyncio.sleep(seconds)   # Sleep until tomorrow and then the loop will start 
    while True:
        now = datetime.utcnow() # You can do now() or a specific timezone if that matters, but I'll leave it with utcnow
        target_time = datetime.combine(now.date(), WHEN)  # 6:00 PM today (In UTC)
        seconds_until_target = (target_time - now).total_seconds()
        await asyncio.sleep(seconds_until_target)  # Sleep until we hit the target time
        await called_once_a_day()  # Call the helper function that sends the message
        tomorrow = datetime.combine(now.date() + timedelta(days=1), time(0))
        seconds = (tomorrow - now).total_seconds()  # Seconds until tomorrow (midnight)
        await asyncio.sleep(seconds)   # Sleep until tomorrow and then the loop will start a new iteration

if __name__ == "__main__":
    bot.loop.create_task(background_task())
    bot.run('token')