Merge branch 'master' of git+ssh://aholst@scm.schwerkraft.elitedvb.net/scmrepos/git...
[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                         eDVBLocalTimeHandler.getInstance().m_timeUpdated.get().append(self.startTimer)
105                 else:
106                         self.start()
107                         self.startNetworking()
108                         
109         def startTimer(self):
110                 eDVBLocalTimeHandler.getInstance().m_timeUpdated.get().remove(self.startTimer)
111                 self.start()
112                 self.startNetworking()
113                 
114         def start(self):
115                 if not self.getSize():
116                         print "[Birthday Reminder] Got no birthdays, no timers to add."
117                         return
118                         
119                 self.addAllTimers()
120                 
121         def stop(self):
122                 self.stopNetworking()
123                 
124                 print "[Birthday Reminder] stopping timer..."
125                 
126                 self.timer.stop()
127                 self.timer_list = []
128                 self.timer.callback.remove(self.calcNextActivation)
129                 self.timer = None
130                 
131                 config.plugins.birthdayreminder.preremindChanged.notifiers.remove(self.cbPreremindChanged)
132                 config.plugins.birthdayreminder.notificationTimeChanged.notifiers.remove(self.cbNotificationTimeChanged)
133                 
134         def startNetworking(self):
135                 print "[Birthday Reminder] starting network communication..."
136                 
137                 port = config.plugins.birthdayreminder.broadcastPort.value
138                 self.transferServerProtocol = TransferServerFactory(self)
139                 self.broadcastProtocol = BroadcastProtocol(self)
140                 try:
141                         self.transferServerPort = reactor.listenTCP(port, self.transferServerProtocol)
142                         self.broadcastPort = reactor.listenUDP(port, self.broadcastProtocol)
143                 except:
144                         print "[Birthday Reminder] can't listen on port", port
145                         
146         def stopNetworking(self):
147                 print "[Birthday Reminder] stopping network communication..."
148                 
149                 self.broadcastPort.stopListening()
150                 self.transferServerPort.stopListening()
151                 
152         def requestBirthdayList(self, addr):
153                 print "[Birthday Reminder] requesting birthday list from", addr[0]
154                 reactor.connectTCP(addr[0], 7374, TransferClientFactory(self, "requestingList"))
155                 
156         def sendPingResponse(self, addr):
157                 print "[Birthday Reminder] sending ping response to", addr[0]
158                 reactor.connectTCP(addr[0], 7374, TransferClientFactory(self, "pong"))
159                 
160         def updateTimer(self, oldBirthday, newBirthday):
161                 print "[Birthday Reminder] updating timer for", oldBirthday[0]
162                 
163                 self.removeTimersForEntry(oldBirthday)
164                 self.addTimer(newBirthday)
165                 
166                 # add a preremind timer also?
167                 if config.plugins.birthdayreminder.preremind.getValue() != "-1":
168                         self.addTimer(newBirthday, preremind = True)
169                         
170         def addTimer(self, entry, preremind = False):
171                 if preremind:
172                         print "[Birthday Reminder] Adding preremind timer for", entry[0]
173                 else:
174                         print "[Birthday Reminder] Adding birthday timer for", entry[0]
175                 
176                 timeList = config.plugins.birthdayreminder.notificationTime.value
177                 notifyTime = dt_time(timeList[0], timeList[1])
178                 now = date.today()
179                 bDay = entry[1]
180                 
181                 if preremind:
182                         numDays = int(config.plugins.birthdayreminder.preremind.getValue())
183                         # set timer to feb 28th for birthdays on feb 29th
184                         try:
185                                 dateThisYear = date(now.year, bDay.month, bDay.day) - timedelta(numDays)
186                         except ValueError: # raised on feb 29th
187                                 dateThisYear = date(now.year, bDay.month, bDay.day -1) - timedelta(numDays)
188                 else:
189                         # set timer to feb 28th for birthdays on feb 29th
190                         try:
191                                 dateThisYear = date(now.year, bDay.month, bDay.day)
192                         except ValueError: # raised on feb 29th
193                                 dateThisYear = date(now.year, bDay.month, bDay.day -1)
194                         
195                 dateTimeThisYear = datetime.combine(dateThisYear, notifyTime)
196                 
197                 if dateThisYear >= now: # check if the birthday is in this year
198                         begin = int(mktime(dateTimeThisYear.timetuple()))
199                 else: # birthday is in the past, we need a timer for the next year
200                         # set timer to feb 28th for birthdays on feb 29th
201                         try:
202                                 bDayNextYear = dateTimeThisYear.replace(year = dateThisYear.year +1)
203                         except ValueError: # raised on feb 29th
204                                 bDayNextYear = dateTimeThisYear.replace(year = dateThisYear.year +1, day = dateThisYear.day -1)
205                                 
206                         begin = int(mktime(bDayNextYear.timetuple()))
207                         
208                 end = begin -1
209                 timerEntry = BirthdayTimerEntry(begin, end, preremind)
210                 timerEntry.bDay = entry
211                 self.addTimerEntry(timerEntry)
212                 
213         def removeTimersForEntry(self, entry):
214                 for timer in self.timer_list[:]:
215                         if timer.bDay == entry:
216                                 if timer.preremind:
217                                         print "[Birthday Reminder] Removing preremind timer for", entry[0]
218                                 else:
219                                         print "[Birthday Reminder] Removing birthday timer for", entry[0]
220                                 self.timer_list.remove(timer)
221                                 
222                 self.calcNextActivation()
223                 
224         def removePreremindTimers(self):
225                 print "[Birthday Reminder] Removing all preremind timers..."
226                 for timer in self.timer_list[:]:
227                         if timer.preremind:
228                                 self.timer_list.remove(timer)
229                                 
230                 self.calcNextActivation()
231                         
232         def addAllTimers(self):
233                 print "[Birthday Reminder] Adding timers for all birthdays..."
234                 bDayList = self.getBirthdayList()
235                 for entry in bDayList:
236                         self.addTimer(entry)
237                         
238                         # add a preremind timer also?
239                         if config.plugins.birthdayreminder.preremind.getValue() != "-1":
240                                 self.addTimer(entry, preremind = True)
241                                 
242         def showReceivedMessage(self, numReceived, peer):
243                 text = _("Birthday Reminder received %s birthdays from %s.") % (numReceived, peer)
244                 Notifications.AddNotification(MessageBox, text, type = MessageBox.TYPE_INFO)
245                 
246         def cbPreremindChanged(self, configElement = None):
247                 if config.plugins.birthdayreminder.preremind.value == "-1": # remove all preremind timers
248                         self.removePreremindTimers()
249                 else: # we need to add or change timers
250                         if config.plugins.birthdayreminder.preremindChanged.value: # there are no preremind timers, add new timers
251                                 print "[Birthday Reminder] Adding new preremind timers..."
252                                 for timer in self.timer_list[:]:
253                                         self.addTimer(timer.bDay, preremind = True)
254                         else: # change existing preremind timers
255                                 print "[Birthday Reminder] Changing date of preremind timers..."
256                                 self.removePreremindTimers()
257                                 
258                                 for timer in self.timer_list[:]:
259                                         self.addTimer(timer.bDay, preremind = True)
260                                         
261         def cbNotificationTimeChanged(self, configElement = None):
262                 print "[Birthday Reminder] Changing timer times..."
263                 
264                 timeList = config.plugins.birthdayreminder.notificationTime.value
265                 notifyTime = dt_time(timeList[0], timeList[1])
266                 
267                 for timer in self.timer_list:
268                         day = date.fromtimestamp(timer.begin)
269                         newDateTime = datetime.combine(day, notifyTime)
270                         timer.begin = int(mktime(newDateTime.timetuple()))
271                         timer.end = timer.begin -1
272                         
273                 self.calcNextActivation()
274