One_Piece_Bounty_Bot / src /service /timer_service.py
github-actions[bot]
Automated sync from GitHub
71e71e8
Raw
History Blame Contribute Delete
5.56 kB
import logging
from datetime import datetime
import asyncprawcore.exceptions
from apscheduler.triggers.cron import CronTrigger
from src.tg_compat.ext import ContextTypes, Application, Job
import src.model.enums.Timer as Timer
from src.chat.manage_message import init, end
from src.model.DailyReward import DailyReward
from src.service.bounty_loan_service import set_expired_bounty_loans
from src.service.bounty_poster_service import reset_bounty_poster_limit
from src.service.devil_fruit_service import schedule_devil_fruit_release, respawn_devil_fruit
from src.service.fight_plunder_service import decrease_scout_count
from src.service.game_service import end_inactive_games
from src.service.generic_service import run_minute_tasks
from src.service.group_service import deactivate_inactive_group_chats
from src.service.leaderboard_service import send_leaderboard
from src.service.location_service import reset_can_change_region
from src.service.prediction_service import (
send_scheduled_predictions,
close_scheduled_predictions,
send_prediction_status_change_message_or_refresh_dispatch,
)
from src.service.reddit_service import manage as send_reddit_post
from src.service.user_service import sync_admin_users
from src.utils.download_utils import cleanup_temp_dir
def add_to_queue(application: Application, timer: Timer.Timer) -> Job:
"""
Add a job to the context
:param application: The application
:param timer: The timer
:return: The job
"""
cron_expression_len = len(timer.cron_expression.split())
if cron_expression_len not in [1, 5]:
raise ValueError(
f"Invalid cron expression for timer {timer.name}: {timer.cron_expression}"
)
if cron_expression_len == 1: # Every X seconds
job = application.job_queue.run_repeating(
callback=run,
interval=int(timer.cron_expression),
first=datetime.min,
name=timer.name,
data=timer,
)
else:
job = application.job_queue.run_custom(
callback=run,
job_kwargs={"trigger": CronTrigger.from_crontab(timer.cron_expression)},
name=timer.name,
data=timer,
)
logging.info(f'Next run of "{timer.name}" is {job.next_t}')
return job
async def set_timers(application: Application) -> None:
"""
Set the timers
:param application: The application
:return: None
"""
for timer in Timer.TIMERS:
if not timer.is_enabled:
logging.info(f"Timer {timer.name} is disabled")
continue
job = add_to_queue(application, timer)
if timer.should_run_on_startup:
await job.run(application)
async def run(context: ContextTypes.DEFAULT_TYPE) -> None:
"""
Run the timers
:param context: The context
:return: None
"""
job = context.job
if not isinstance(job.data, Timer.Timer):
logging.error(f"Job {job.name} context is not a Timer")
return
timer: Timer.Timer = job.data
db = init()
if timer.should_log:
logging.info(f"Running timer {job.name}")
match timer:
case Timer.REDDIT_POST_ONE_PIECE | Timer.REDDIT_POST_MEME_PIECE:
try:
await send_reddit_post(context, timer.info)
except asyncprawcore.exceptions.AsyncPrawcoreException as e:
# Reddit's own API/servers had a problem (a transient 5xx,
# rate limiting, a connection issue, etc.) - not a bug in
# this codebase to fix, and not worth reporting as an
# "unhandled exception" every time Reddit's API has a
# momentary hiccup. The next scheduled run of this timer
# tries again naturally.
logging.warning(f"Reddit API error running {job.name}: {e}")
case Timer.TEMP_DIR_CLEANUP:
cleanup_temp_dir()
case Timer.TIMER_SEND_LEADERBOARD:
await send_leaderboard(context)
case Timer.RESET_BOUNTY_POSTER_LIMIT:
await reset_bounty_poster_limit()
case Timer.RESET_CAN_CHANGE_REGION:
reset_can_change_region()
case Timer.SEND_SCHEDULED_PREDICTIONS:
await send_scheduled_predictions(context)
case Timer.CLOSE_SCHEDULED_PREDICTIONS:
await close_scheduled_predictions(context)
case Timer.REFRESH_ACTIVE_PREDICTIONS_GROUP_MESSAGE:
await send_prediction_status_change_message_or_refresh_dispatch(
context, should_refresh=True
)
case Timer.SCHEDULE_DEVIL_FRUIT_ZOAN_RELEASE:
await schedule_devil_fruit_release(context)
case Timer.RESPAWN_DEVIL_FRUIT:
await respawn_devil_fruit(context)
case Timer.DEACTIVATE_INACTIVE_GROUP_CHATS:
deactivate_inactive_group_chats()
case Timer.END_INACTIVE_GAMES:
await end_inactive_games(context)
case Timer.SET_EXPIRED_BOUNTY_LOANS:
await set_expired_bounty_loans(context)
case Timer.MINUTE_TASKS:
await run_minute_tasks(context)
case Timer.DAILY_REWARD:
DailyReward.reset()
case Timer.FIGHT_PLUNDER_SCOUT_COUNT_DECREASE:
decrease_scout_count()
case Timer.SYNC_ADMIN_USERS:
sync_admin_users()
case _:
raise ValueError(f"Unknown timer {timer.name}")
if timer.should_log:
logging.info(f"Finished timer {context.job.name}")
end(db)
return