I need help with a Discord Hikari bot that writes a message every day. I can't get the loop to work. I tried to do it with apscheduler (AsyncIOScheduler) but when I run it it doesn't do anything and when I run the async loop, it executes, but everything after it doesn't run, so the bot doesn't start.
import hikari
import lightbulb
import asyncio
import bot
from datetime import datetime
from lightbulb import commands, context
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
daily_plugin = lightbulb.Plugin("Daily")
sched = AsyncIOScheduler()
sched.start()
@sched.scheduled_job(CronTrigger(hour=2, minute=0))
async def msg1():
await bot.bot.rest.create_message(783996883080708096, "Morning Message")
print("Message")
#asyncio.get_event_loop().run_forever()
def load(bot: lightbulb.BotApp) -> None:
bot.add_plugin(daily_plugin)
(This is inside a Lightbulb plugin)
The problem here is strictly the asyncio.get_event_loop().run_forever()
call. This is fully blocking and prevents the lightbulb BotApp from starting.
The remaining code you have works, I have tested it with a 1 minute interval as follows:
# main.py
import os
import hikari
import lightbulb
from dotenv import load_dotenv
load_dotenv()
bot = lightbulb.BotApp(
token=os.environ["TOKEN"],
prefix="$",
intents=hikari.Intents.ALL,
ignore_bots=True,
)
bot.load_extensions("daily")
if __name__ == "__main__":
bot.run()
# daily.py
import lightbulb
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
daily_plugin = lightbulb.Plugin("Daily")
sched = AsyncIOScheduler()
sched.start()
@sched.scheduled_job(CronTrigger(minute="*/1"))
async def msg1() -> None:
await daily_plugin.app.rest.create_message(783996883080708096, "Morning Message")
def load(bot: lightbulb.BotApp) -> None:
bot.add_plugin(daily_plugin)
You could also consider using the hikari lifetime events and a lightbulb Plugin listener decorator to start the scheduler to prevent cluttering your namespace. If you have other places you may need to use the scheduler outside this extension, you could even store it inside the BotApp
's datastore for easy access anywhere you have the BotApp
.
# main.py
import os
import hikari
import lightbulb
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from dotenv import load_dotenv
load_dotenv()
bot = lightbulb.BotApp(
token=os.environ["TOKEN"],
prefix="$",
intents=hikari.Intents.ALL,
ignore_bots=True,
)
@bot.listen(hikari.StartingEvent)
async def on_starting(_: hikari.StartingEvent) -> None:
# This event fires once, while the BotApp is starting.
bot.d.sched = AsyncIOScheduler()
bot.d.sched.start()
bot.load_extensions("daily")
if __name__ == "__main__":
bot.run()
# daily.py
import hikari
import lightbulb
from apscheduler.triggers.cron import CronTrigger
daily_plugin = lightbulb.Plugin("Daily")
async def msg1() -> None:
await daily_plugin.app.rest.create_message(783996883080708096, "Morning Message")
@daily_plugin.listener(hikari.StartedEvent)
async def on_started(_: hikari.StartedEvent) -> None:
# This event fires once, when the BotApp is fully started.
daily_plugin.app.d.sched.add_job(msg1, CronTrigger(minute="*/1"))
def load(bot: lightbulb.BotApp) -> None:
bot.add_plugin(daily_plugin)