简体   繁体   中英

Discord.py Bot run function at specific time every day

I'm using discord.py to create a discord bot, and I need to execute certain actions every day at a specific time. I saw this answer: How to make a loop in discord.py rewrite? and I've been using it so far.

The problem started when I hosted my bot on the heroku free plan. The server on Heroku resets at least once a day, which messes up the timer as shown in that post.

I also saw the schedule library. The problem with this is that it seems like it uses an infinite loop. Wouldn't that prevent me from running anything else during the 24 hours? The bot needs to be able to respond to commands at all times, in addition to sending out the message every 24 hours.

How can I execute an action every day at a specific time even if the server resets? Thank you in advance!

You can write a function to run periodically on a different thread and check if it's the right time to send your message like this example:

from datetime import datetime
import threading


def checkTime():
    # This function runs periodically every 1 second
    threading.Timer(1, checkTime).start()

    now = datetime.now()

    current_time = now.strftime("%H:%M:%S")
    print("Current Time =", current_time)

    if(current_time == '02:11:00'):  # check if matches with the desired time
        print('sending message')


checkTime()

The heroku free plan is Linux. Therefore cron will let you run things at a specific time and /etc/init.d/ will let you run things at start up. It's a good thing to know your OS.

Have you considered using multithreading to run your program? You could have one thread waiting for the time of day you want, and another that is running the rest of your program. Here's some documentation to help you get started: Intro to Python Threading , Threading Documentation

I know I am late, but this may be helpful for future users.
There is a library called APScheduler which can be used to run functions by setting a cron job (there are other ways too instead of cron. Read more ).

A small example will be like:

import discord
from discord.ext import commands

from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger

class Scheduler(commands.Cog):
    """Schedule commands."""
    def __init__(self, bot):
        self.bot = bot

        # Initialize session
        self.session = aiohttp.ClientSession()
    
    # Scheduled events
    async def schedule_func(self):

    def schedule(self):
        # Initialize scheduler
        schedule_log = logging.getLogger("apscheduler")
        schedule_log.setLevel(logging.WARNING)

        job_defaults = {
            "coalesce": True,
            "max_instances": 5,
            "misfire_grace_time": 15,
            "replace_existing": True,
        }

        scheduler = AsyncIOScheduler(job_defaults = job_defaults, 
                          logger = schedule_log)

        # Add jobs to scheduler
        scheduler.add_job(self.schedule_func, CronTrigger.from_crontab("0 * * * *")) 
        # Every hour

And in our main.py file add this (after importing the schedule_jobs.py file obviously):

# Start scheduled commands
scheduler = schedule_jobs.Scheduler(bot).schedule()
scheduler.start()

You can have an infinite loop and use the asyncio.sleep() function. This allows you to process commands from anywhere in the script and still wait the time. Here's a little example:

import asyncio

while True:
    await asyncio.sleep(60)
    print(1)

@client.command()
async def command(ctx):
    pass

Every minute the script will print 1 and anytime somebody does the command it will execute.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM