66from random import choice
77from apscheduler .schedulers .background import BackgroundScheduler
88from apscheduler .triggers .cron import CronTrigger
9- from sqlalchemy .exc import IntegrityError
9+ from sqlalchemy .exc import IntegrityError
1010from .athkar_db_manager import AthkarDBManager
1111from .athkar_refresher import AthkarRefresher
1212from utils .audio_player import AthkarPlayer
1313from utils .const import Globals
14+ from utils .logger import Logger
15+ from exceptions .base import ErrorMessage
1416
1517class AthkarScheduler :
1618 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,19 +21,18 @@ def __init__(self, athkar_db_folder: Union[Path, str], default_category_path: Op
1921 self .default_category_settings = default_category_settings if default_category_settings is not None else {}
2022 self .categories = None
2123 self .db_manager = AthkarDBManager (athkar_db_folder )
22- self .scheduler = BackgroundScheduler ()
24+ self .scheduler = BackgroundScheduler ()
2325 self .setup ()
2426
2527 def setup (self ) -> None :
26-
2728 if self .default_category_path :
2829 self .default_category_path .mkdir (parents = True , exist_ok = True )
2930 try :
3031 category_id = self .db_manager .create_category ("default" , str (self .default_category_path ), ** self .default_category_settings )
3132 if self .text_athkar_path and self .text_athkar_path .exists ():
3233 with open (self .text_athkar_path , encoding = "UTF-8" ) as f :
3334 self .db_manager .add_text_athkar (json .load (f ), category_id )
34- except IntegrityError as e :
35+ except IntegrityError :
3536 pass
3637
3738 self .categories = self .db_manager .get_all_categories ()
@@ -46,38 +47,62 @@ def audio_athkar_job(self, category_id: int, audio_path: str) -> None:
4647 def text_athkar_job (self , category_id : int ) -> None :
4748 random_text_athkar = choice (self .db_manager .get_text_athkar (category_id ))
4849 text = random_text_athkar .text
49-
50+
5051 if len (text ) > 256 :
51- # Extract the first 5 words for the title
5252 title = " " .join (text .split ()[:10 ])
5353 description = " " .join (text .split ()[10 :])
5454 else :
5555 title = "البيان"
5656 description = text
57-
57+
5858 Globals .TRAY_ICON .showMessage (title , description , msecs = 5000 )
5959
6060 @staticmethod
6161 def _parse_time (time_str : str ) -> time :
62- time_ob = datetime .strptime (time_str , "%H:%M" )
63- return time_ob
62+ return datetime .strptime (time_str , "%H:%M" ).time ()
6463
65- def start (self ,) -> None :
64+ def _create_triggers (self , from_time : time , to_time : time , play_interval : int ):
65+ minute = "0" if play_interval == 60 else f"*/{ play_interval } "
66+
67+ if from_time < to_time :
68+ return [CronTrigger (minute = minute , hour = f"{ from_time .hour } -{ to_time .hour } " )]
69+ else :
70+ return [
71+ CronTrigger (minute = minute , hour = f"{ from_time .hour } -23" ),
72+ CronTrigger (minute = minute , hour = f"0-{ to_time .hour } " )
73+ ]
74+
75+ def _add_jobs (self , category , trigger ):
76+ if category .audio_athkar_enabled :
77+ self .scheduler .add_job (
78+ self .audio_athkar_job ,
79+ trigger ,
80+ args = [category .id , category .audio_path ],
81+ id = f"audio_athkar_{ category .id } _{ trigger } "
82+ )
83+ if category .text_athkar_enabled :
84+ self .scheduler .add_job (
85+ self .text_athkar_job ,
86+ trigger ,
87+ args = [category .id ],
88+ id = f"text_athkar_{ category .id } _{ trigger } "
89+ )
90+
91+ def start (self ) -> None :
6692 for category in self .categories :
67- from_time = self . _parse_time ( category . from_time )
68- to_time = self ._parse_time (category .to_time )
69- minute = "0" if category . play_interval == 60 else f"*/ { category .play_interval } "
70- trigger = CronTrigger ( minute = minute , hour = f" { from_time . hour } - { to_time . hour } " )
71- if category . audio_athkar_enabled :
72- self .scheduler . add_job ( self . audio_athkar_job , trigger , args = [ category . id , category . audio_path ] )
73- if category . text_athkar_enabled :
74- self . scheduler . add_job ( self . text_athkar_job , trigger , args = [ category . id ] )
93+ try :
94+ from_time = self ._parse_time (category .from_time )
95+ to_time = self . _parse_time ( category .to_time )
96+ triggers = self . _create_triggers ( from_time , to_time , category . play_interval )
97+ for trigger in triggers :
98+ self ._add_jobs ( category , trigger )
99+ except Exception as e :
100+ Logger . error ( ErrorMessage ( e ) )
75101
76102 if not self .scheduler .running :
77103 self .scheduler .start ()
78104
79105 def refresh (self ) -> None :
80-
81106 if self .scheduler is not None :
82107 self .scheduler .remove_all_jobs ()
83108
0 commit comments