I'm writing a discord bot using discord.py rewrite, and I want to run a function every day at a certain time. I'm not experienced with async functions at all and I can't figure out how to run one without using "await." This is only a piece of my code which is why some things may not be defined.
async def send_channel():
try:
await active_channel.send('daily text here')
except Exception:
active_channel_id = None
active_channel = None
async def timer():
while True:
schedule.run_pending()
await asyncio.sleep(3)
schedule.every().day.at("21:57").do(await send_channel())
@bot.event
async def on_ready():
print("Logged in as")
print(bot.user.name)
print(bot.user.id)
print("------")
bot.loop.create_task(timer())
Using the schedule.every().day.at("00:00").do()
function, I get this error when I put await send_channel()
in the paramaters of .do()
:
self.job_func = functools.partial(job_func, *args, **kwargs) TypeError: the first argument must be callable
But when I don't use await, and I just have send_channel()
as parameters, I get this error:
RuntimeWarning: coroutine 'send_channel' was never awaited
I'm not super good at programming so if someone could try to dumb it down for me that would be awesome.
Thanks
The built-in solution to this in discord.py is to use the discord.ext.tasks
extension. This lets you register a task to be called repeatedly at a specific interval. When the bots start, we'll delay the start of the loop until the target time, then run the task every 24 hours:
import asyncio
from discord.ext import commands, tasks
from datetime import datetime, timedelta
bot = commands.Bot("!")
@tasks.loop(hours=24)
async def my_task():
...
@my_task.before_loop
async def before_my_task():
hour = 21
minute = 57
await bot.wait_until_ready()
now = datetime.now()
future = datetime.datetime(now.year, now.month, now.day, hour, minute)
if now.hour >= hour and now.minute > minute:
future += timedelta(days=1)
await asyncio.sleep((future-now).seconds)
my_task.start()