Merge remote-tracking branch 'schwerkraft/master'
[enigma2-plugins.git] / birthdayreminder / src / BirthdayTimer.py
1 #
2 #  Birthday Reminder E2 Plugin
3 #
4 #  $Id: BirthdayTimer.py,v 1.0 2011-08-29 00:00:00 Shaderman Exp $
5 #
6 #  Coded by Shaderman (c) 2011
7 #  Support: www.dreambox-tools.info
8 #
9 #  This plugin is licensed under the Creative Commons 
10 #  Attribution-NonCommercial-ShareAlike 3.0 Unported 
11 #  License. To view a copy of this license, visit
12 #  http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative
13 #  Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
14 #
15 #  Alternatively, this plugin may be distributed and executed on hardware which
16 #  is licensed by Dream Multimedia GmbH.
17
18 #  This plugin is NOT free software. It is open source, you are allowed to
19 #  modify it (if you keep the license), but it may not be commercially 
20 #  distributed other than under the conditions noted above.
21 #
22
23
24 # OWN IMPORTS
25 from BirthdayNetworking import BroadcastProtocol, TransferServerFactory, TransferClientFactory
26 from BirthdayReminder import BirthdayStore, getAge
27
28 # PYTHON IMPORTS
29 from datetime import datetime, date, timedelta, time as dt_time
30 from time import mktime, time, strftime, strptime
31 from timer import Timer, TimerEntry
32 from twisted.internet import reactor
33
34 # ENIGMA IMPORTS
35 from Components.config import config
36 from enigma import eDVBLocalTimeHandler
37 from Screens.MessageBox import MessageBox
38 from Tools import Notifications
39
40 # for localized messages
41 from . import _
42
43
44 class BirthdayTimerEntry(TimerEntry):
45         def __init__(self, begin, end, preremind):
46                 TimerEntry.__init__(self, int(begin), int(end))
47                 self.preremind = preremind
48                 self.state = self.StatePrepared
49                 
50         def getNextActivation(self):
51                 return self.begin
52                 
53         def activate(self):
54                 if self.preremind:
55                         when = config.plugins.birthdayreminder.preremind.getText()
56                         print "[Birthday Reminder] %s will turn %s in %s!" % (self.bDay[0], getAge(self.bDay[1]) + 1, when)
57                         text = _("%s will turn %s in %s!") % (self.bDay[0], getAge(self.bDay[1]) + 1, when)
58                 else:
59                         print "[Birthday Reminder] It's %s's birthday today!" % self.bDay[0]
60                         
61                         if config.plugins.birthdayreminder.dateFormat.value == "mmddyyyy":
62                                 format = "%m/%d/%Y"
63                         else:
64                                 format = "%d.%m.%Y"
65                         birthday = self.bDay[1].strftime(format)
66                         
67                         text = _("Today is %s's birthday!\n\nShe/he was born on %s and is now %s year(s) old.") % (self.bDay[0], birthday, getAge(self.bDay[1]))
68                         
69                 Notifications.AddNotification(MessageBox, text, type = MessageBox.TYPE_INFO)
70                 
71                 # activate the timer for next year
72                 now = date.today()
73                 bDay = self.bDay[1]
74                 
75                 # set timer to feb 28th for birthdays on feb 29th
76                 try:
77                         bDayNextYear = date(now.year + 1, bDay.month, bDay.day)
78                 except ValueError: # raised on feb 29th
79                         bDayNextYear = date(now.year + 1, bDay.month, bDay.day - 1)
80                 
81                 self.begin = int(mktime(bDayNextYear.timetuple()))
82                 self.end = self.begin -1
83                 self.state = self.StatePrepared
84                 
85                 return True
86                                                 
87         def shouldSkip(self):
88                 return False
89                 
90         def timeChanged(self):
91                 self.state = self.StatePrepared
92
93 class BirthdayTimer(Timer, BirthdayStore):
94         def __init__(self):
95                 BirthdayStore.__init__(self)
96                 Timer.__init__(self)
97                 
98                 # this is used to detect settings changes, because we only want to change preremind timers if a different value was saved by the user
99                 config.plugins.birthdayreminder.preremindChanged.addNotifier(self.cbPreremindChanged, initial_call = False)
100                 config.plugins.birthdayreminder.notificationTimeChanged.addNotifier(self.cbNotificationTimeChanged, initial_call = False)
101                 
102                 # let's wait for the system time being up to date before starting the timers. needed when the box was powered off
103                 if not eDVBLocalTimeHandler.getInstance().ready():
104                         self.local_time_handler_conn = eDVBLocalTimeHandler.getInstance().m_timeUpdated.timeout.connect(self.startTimer)
105                 else:
106                         self.start()
107                         self.startNetworking()
108                 self.broadcastPort = None
109                 self.transferServerPort = None
110                 
111         def startTimer(self):
112                 self.local_time_handler_conn = None
113                 self.start()
114                 self.startNetworking()
115                 
116         def start(self):
117                 if not self.getSize():
118                         print "[Birthday Reminder] Got no birthdays, no timers to add."
119                         return
120                         
121                 self.addAllTimers()
122                 
123         def stop(self):
124                 self.stopNetworking()
125                 
126                 print "[Birthday Reminder] stopping timer..."
127                 
128                 self.timer.stop()
129                 self.timer_list = []
130                 self.timer_conn = None
131                 self.timer = None
132                 
133                 config.plugins.birthdayreminder.preremindChanged.notifiers.remove(self.cbPreremindChanged)
134                 config.plugins.birthdayreminder.notificationTimeChanged.notifiers.remove(self.cbNotificationTimeChanged)
135                 
136         def startNetworking(self):
137                 print "[Birthday Reminder] starting network communication..."
138                 
139                 port = config.plugins.birthdayreminder.broadcastPort.value
140                 self.transferServerProtocol = TransferServerFactory(self)
141                 self.broadcastProtocol = BroadcastProtocol(self)
142                 try:
143                         self.transferServerPort = reactor.listenTCP(port, self.transferServerProtocol)
144                         self.broadcastPort = reactor.listenUDP(port, self.broadcastProtocol)
145                 except:
146                         print "[Birthday Reminder] can't listen on port", port
147                         
148         def stopNetworking(self):
149                 print "[Birthday Reminder] stopping network communication..."
150                 self.broadcastPort and self.broadcastPort.stopListening()
151                 self.transferServerPort and self.transferServerPort.stopListening()
152                 
153         def requestBirthdayList(self, addr):
154                 print "[Birthday Reminder] requesting birthday list from", addr[0]
155                 reactor.connectTCP(addr[0], 7374, TransferClientFactory(self, "requestingList"))
156                 
157         def sendPingResponse(self, addr):
158                 print "[Birthday Reminder] sending ping response to", addr[0]
159                 reactor.connectTCP(addr[0], 7374, TransferClientFactory(self, "pong"))
160                 
161         def updateTimer(self, oldBirthday, newBirthday):
162                 print "[Birthday Reminder] updating timer for", oldBirthday[0]
163                 
164                 self.removeTimersForEntry(oldBirthday)
165                 self.addTimer(newBirthday)
166                 
167                 # add a preremind timer also?
168                 if config.plugins.birthdayreminder.preremind.getValue() != "-1":
169                         self.addTimer(newBirthday, preremind = True)
170                         
171         def addTimer(self, entry, preremind = False):
172                 if preremind:
173                         print "[Birthday Reminder] Adding preremind timer for", entry[0]
174                 else:
175                         print "[Birthday Reminder] Adding birthday timer for", entry[0]
176                 
177                 timeList = config.plugins.birthdayreminder.notificationTime.value
178                 notifyTime = dt_time(timeList[0], timeList[1])
179                 now = date.today()
180                 bDay = entry[1]
181                 
182                 if preremind:
183                         numDays = int(config.plugins.birthdayreminder.preremind.getValue())
184                         # set timer to feb 28th for birthdays on feb 29th
185                         try:
186                                 dateThisYear = date(now.year, bDay.month, bDay.day) - timedelta(numDays)
187                         except ValueError: # raised on feb 29th
188                                 dateThisYear = date(now.year, bDay.month, bDay.day -1) - timedelta(numDays)
189                 else:
190                         # set timer to feb 28th for birthdays on feb 29th
191                         try:
192                                 dateThisYear = date(now.year, bDay.month, bDay.day)
193                         except ValueError: # raised on feb 29th
194                                 dateThisYear = date(now.year, bDay.month, bDay.day -1)
195                         
196                 dateTimeThisYear = datetime.combine(dateThisYear, notifyTime)
197                 
198                 if dateThisYear >= now: # check if the birthday is in this year
199                         begin = int(mktime(dateTimeThisYear.timetuple()))
200                 else: # birthday is in the past, we need a timer for the next year
201                         # set timer to feb 28th for birthdays on feb 29th
202                         try:
203                                 bDayNextYear = dateTimeThisYear.replace(year = dateThisYear.year +1)
204                         except ValueError: # raised on feb 29th
205                                 bDayNextYear = dateTimeThisYear.replace(year = dateThisYear.year +1, day = dateThisYear.day -1)
206                                 
207                         begin = int(mktime(bDayNextYear.timetuple()))
208                         
209                 end = begin -1
210                 timerEntry = BirthdayTimerEntry(begin, end, preremind)
211                 timerEntry.bDay = entry
212                 self.addTimerEntry(timerEntry)
213                 
214         def removeTimersForEntry(self, entry):
215                 for timer in self.timer_list[:]:
216                         if timer.bDay == entry:
217                                 if timer.preremind:
218                                         print "[Birthday Reminder] Removing preremind timer for", entry[0]
219                                 else:
220                                         print "[Birthday Reminder] Removing birthday timer for", entry[0]
221                                 self.timer_list.remove(timer)
222                                 
223                 self.calcNextActivation()
224                 
225         def removePreremindTimers(self):
226                 print "[Birthday Reminder] Removing all preremind timers..."
227                 for timer in self.timer_list[:]:
228                         if timer.preremind:
229                                 self.timer_list.remove(timer)
230                                 
231                 self.calcNextActivation()
232                         
233         def addAllTimers(self):
234                 print "[Birthday Reminder] Adding timers for all birthdays..."
235                 bDayList = self.getBirthdayList()
236                 for entry in bDayList:
237                         self.addTimer(entry)
238                         
239                         # add a preremind timer also?
240                         if config.plugins.birthdayreminder.preremind.getValue() != "-1":
241                                 self.addTimer(entry, preremind = True)
242                                 
243         def showReceivedMessage(self, numReceived, peer):
244                 text = _("Birthday Reminder received %s birthdays from %s.") % (numReceived, peer)
245                 Notifications.AddNotification(MessageBox, text, type = MessageBox.TYPE_INFO)
246                 
247         def cbPreremindChanged(self, configElement = None):
248                 if config.plugins.birthdayreminder.preremind.value == "-1": # remove all preremind timers
249                         self.removePreremindTimers()
250                 else: # we need to add or change timers
251                         if config.plugins.birthdayreminder.preremindChanged.value: # there are no preremind timers, add new timers
252                                 print "[Birthday Reminder] Adding new preremind timers..."
253                                 for timer in self.timer_list[:]:
254                                         self.addTimer(timer.bDay, preremind = True)
255                         else: # change existing preremind timers
256                                 print "[Birthday Reminder] Changing date of preremind timers..."
257                                 self.removePreremindTimers()
258                                 
259                                 for timer in self.timer_list[:]:
260                                         self.addTimer(timer.bDay, preremind = True)
261                                         
262         def cbNotificationTimeChanged(self, configElement = None):
263                 print "[Birthday Reminder] Changing timer times..."
264                 
265                 timeList = config.plugins.birthdayreminder.notificationTime.value
266                 notifyTime = dt_time(timeList[0], timeList[1])
267                 
268                 for timer in self.timer_list:
269                         day = date.fromtimestamp(timer.begin)
270                         newDateTime = datetime.combine(day, notifyTime)
271                         timer.begin = int(mktime(newDateTime.timetuple()))
272                         timer.end = timer.begin -1
273                         
274                 self.calcNextActivation()
275