diff --git a/core_functions/athkar/athkar_scheduler.py b/core_functions/athkar/athkar_scheduler.py index 4af55ed..4e5fcc0 100644 --- a/core_functions/athkar/athkar_scheduler.py +++ b/core_functions/athkar/athkar_scheduler.py @@ -6,11 +6,13 @@ from random import choice from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.triggers.cron import CronTrigger -from sqlalchemy.exc import IntegrityError +from sqlalchemy.exc import IntegrityError from .athkar_db_manager import AthkarDBManager from .athkar_refresher import AthkarRefresher from utils.audio_player import AthkarPlayer from utils.const import Globals +from utils.logger import Logger +from exceptions.base import ErrorMessage class AthkarScheduler: def __init__(self, athkar_db_folder: Union[Path, str], default_category_path: Optional[Union[Path, str]] = None, text_athkar_path: Optional[Union[Path, str]] = None, default_category_settings: Optional[Dict[str, int]] = None) -> None: @@ -19,11 +21,10 @@ def __init__(self, athkar_db_folder: Union[Path, str], default_category_path: Op self.default_category_settings = default_category_settings if default_category_settings is not None else {} self.categories = None self.db_manager = AthkarDBManager(athkar_db_folder) - self.scheduler = BackgroundScheduler() + self.scheduler = BackgroundScheduler() self.setup() def setup(self) -> None: - if self.default_category_path: self.default_category_path.mkdir(parents=True, exist_ok=True) try: @@ -31,7 +32,7 @@ def setup(self) -> None: if self.text_athkar_path and self.text_athkar_path.exists(): with open(self.text_athkar_path, encoding="UTF-8") as f: self.db_manager.add_text_athkar(json.load(f), category_id) - except IntegrityError as e: + except IntegrityError: pass self.categories = self.db_manager.get_all_categories() @@ -46,38 +47,62 @@ def audio_athkar_job(self, category_id: int, audio_path: str) -> None: def text_athkar_job(self, category_id: int) -> None: random_text_athkar = choice(self.db_manager.get_text_athkar(category_id)) text = random_text_athkar.text - + if len(text) > 256: - # Extract the first 5 words for the title title = " ".join(text.split()[:10]) description = " ".join(text.split()[10:]) else: title = "البيان" description = text - + Globals.TRAY_ICON.showMessage(title, description, msecs=5000) @staticmethod def _parse_time(time_str: str) -> time: - time_ob = datetime.strptime(time_str, "%H:%M") - return time_ob + return datetime.strptime(time_str, "%H:%M").time() - def start(self,) -> None: + def _create_triggers(self, from_time: time, to_time: time, play_interval: int): + minute = "0" if play_interval == 60 else f"*/{play_interval}" + + if from_time < to_time: + return [CronTrigger(minute=minute, hour=f"{from_time.hour}-{to_time.hour}")] + else: + return [ + CronTrigger(minute=minute, hour=f"{from_time.hour}-23"), + CronTrigger(minute=minute, hour=f"0-{to_time.hour}") + ] + + def _add_jobs(self, category, trigger): + if category.audio_athkar_enabled: + self.scheduler.add_job( + self.audio_athkar_job, + trigger, + args=[category.id, category.audio_path], + id=f"audio_athkar_{category.id}_{trigger}" + ) + if category.text_athkar_enabled: + self.scheduler.add_job( + self.text_athkar_job, + trigger, + args=[category.id], + id=f"text_athkar_{category.id}_{trigger}" + ) + + def start(self) -> None: for category in self.categories: - from_time = self._parse_time(category.from_time) - to_time = self._parse_time(category.to_time) - minute = "0" if category.play_interval == 60 else f"*/{category.play_interval}" - trigger = CronTrigger(minute=minute, hour=f"{from_time.hour}-{to_time.hour}") - if category.audio_athkar_enabled : - self.scheduler.add_job(self.audio_athkar_job, trigger, args=[category.id, category.audio_path]) - if category.text_athkar_enabled: - self.scheduler.add_job(self.text_athkar_job, trigger, args=[category.id]) + try: + from_time = self._parse_time(category.from_time) + to_time = self._parse_time(category.to_time) + triggers = self._create_triggers(from_time, to_time, category.play_interval) + for trigger in triggers: + self._add_jobs(category, trigger) + except Exception as e: + Logger.error(ErrorMessage(e)) if not self.scheduler.running: self.scheduler.start() def refresh(self) -> None: - if self.scheduler is not None: self.scheduler.remove_all_jobs()