-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnotifier.py
More file actions
224 lines (183 loc) · 6.73 KB
/
notifier.py
File metadata and controls
224 lines (183 loc) · 6.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
"""Notification system using Apprise."""
import logging
from typing import List, Optional
from datetime import datetime, timedelta
from session_parser import Session
logger = logging.getLogger(__name__)
class Notifier:
"""Notification handler using Apprise."""
def __init__(
self,
apprise_urls: List[str],
enabled: bool = True,
upcoming_hours: int = 1,
notify_start: bool = True,
notify_end: bool = True
):
"""
Initialize notifier.
Args:
apprise_urls: List of Apprise notification URLs
enabled: Whether notifications are enabled
upcoming_hours: Hours before session to send upcoming notification
notify_start: Whether to notify when session starts
notify_end: Whether to notify when session ends
"""
self.apprise_urls = apprise_urls
self.enabled = enabled
self.upcoming_hours = upcoming_hours
self.notify_start = notify_start
self.notify_end = notify_end
self.apprise = None
if self.enabled and self.apprise_urls:
self._initialize_apprise()
def _initialize_apprise(self) -> None:
"""Initialize Apprise instance."""
try:
import apprise
self.apprise = apprise.Apprise()
# Add all URLs
for url in self.apprise_urls:
if url:
self.apprise.add(url)
logger.info(f"Initialized Apprise with {len(self.apprise_urls)} service(s)")
except ImportError:
logger.error(
"Apprise not installed. Install it with: pip install apprise"
)
self.enabled = False
except Exception as e:
logger.error(f"Failed to initialize Apprise: {e}")
self.enabled = False
def send_notification(self, title: str, body: str) -> bool:
"""
Send a notification.
Args:
title: Notification title
body: Notification body
Returns:
True if sent successfully, False otherwise
"""
if not self.enabled:
logger.debug("Notifications disabled, skipping")
return False
if not self.apprise:
logger.warning("Apprise not initialized, cannot send notification")
return False
try:
self.apprise.notify(
title=title,
body=body
)
logger.info(f"Sent notification: {title}")
return True
except Exception as e:
logger.error(f"Failed to send notification: {e}")
return False
def notify_new_session(self, session: Session) -> bool:
"""
Notify about a new session being scheduled.
Args:
session: Session object
Returns:
True if sent successfully
"""
title = "⚡ New Free Electricity Session Scheduled"
body = (
f"Session: {session.session_str}\n"
f"Start: {session.start_time.strftime('%A, %d %B %Y at %I:%M %p')}\n"
f"End: {session.end_time.strftime('%I:%M %p')}\n"
f"Duration: {session.duration}"
)
return self.send_notification(title, body)
def notify_upcoming_session(self, session: Session, hours: int) -> bool:
"""
Notify about an upcoming session.
Args:
session: Session object
hours: Hours until session starts
Returns:
True if sent successfully
"""
title = f"⏰ Free Electricity in {hours} hour{'s' if hours != 1 else ''}"
body = (
f"Session: {session.session_str}\n"
f"Starts: {session.start_time.strftime('%A, %d %B %Y at %I:%M %p')}\n"
f"Ends: {session.end_time.strftime('%I:%M %p')}\n"
f"Get ready to use electricity!"
)
return self.send_notification(title, body)
def notify_session_starting(self, session: Session) -> bool:
"""
Notify that a session is starting now.
Args:
session: Session object
Returns:
True if sent successfully
"""
title = "🎉 Free Electricity Starting NOW!"
body = (
f"Session: {session.session_str}\n"
f"Ends: {session.end_time.strftime('%I:%M %p')}\n"
f"Duration: {session.duration}\n"
f"Start using electricity now!"
)
return self.send_notification(title, body)
def notify_session_ending(self, session: Session) -> bool:
"""
Notify that a session is ending now.
Args:
session: Session object
Returns:
True if sent successfully
"""
title = "⏱️ Free Electricity Ending NOW"
body = (
f"Session: {session.session_str}\n"
f"The free electricity period is ending.\n"
f"Reduce your electricity usage."
)
return self.send_notification(title, body)
def should_notify_upcoming(self, session: Session) -> bool:
"""
Check if we should send upcoming notification for this session.
Args:
session: Session object
Returns:
True if notification should be sent
"""
if not self.enabled:
return False
now = datetime.now()
notification_time = session.start_time - timedelta(hours=self.upcoming_hours)
# Check if we're within the notification window (5 minute tolerance)
time_diff = abs((now - notification_time).total_seconds())
return time_diff < 300 # 5 minutes in seconds
def should_notify_start(self, session: Session) -> bool:
"""
Check if we should send start notification for this session.
Args:
session: Session object
Returns:
True if notification should be sent
"""
if not self.enabled or not self.notify_start:
return False
now = datetime.now()
# Check if we're within 5 minutes of start time
time_diff = abs((now - session.start_time).total_seconds())
return time_diff < 300 # 5 minutes in seconds
def should_notify_end(self, session: Session) -> bool:
"""
Check if we should send end notification for this session.
Args:
session: Session object
Returns:
True if notification should be sent
"""
if not self.enabled or not self.notify_end:
return False
now = datetime.now()
# Check if we're within 5 minutes of end time
time_diff = abs((now - session.end_time).total_seconds())
return time_diff < 300 # 5 minutes in seconds