global: 'Dream Multimedia' -> 'Dream Property'
[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 Property 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 class BirthdayTimerEntry(TimerEntry):
41         def __init__(self, begin, end, preremind):
42                 TimerEntry.__init__(self, int(begin), int(end))
43                 self.preremind = preremind
44                 self.state = self.StatePrepared
45                 
46         def getNextActivation(self):
47                 return self.begin
48                 
49         def activate(self):
50                 if self.preremind:
51                         when = config.plugins.birthdayreminder.preremind.getText()
52                         print "[Birthday Reminder] %s will turn %s in %s!" % (self.bDay[0], getAge(self.bDay[1]) + 1, when)
53                         text = _("%s will turn %s in %s!") % (self.bDay[0], getAge(self.bDay[1]) + 1, when)
54                 else:
55                         print "[Birthday Reminder] It's %s's birthday today!" % self.bDay[0]
56                         
57                         if config.plugins.birthdayreminder.dateFormat.value == "mmddyyyy":
58                                 format = "%m/%d/%Y"
59                         else:
60                                 format = "%d.%m.%Y"
61                         birthday = self.bDay[1].strftime(format)
62                         
63                         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]))
64                         
65                 Notifications.AddNotification(MessageBox, text, type = MessageBox.TYPE_INFO)
66                 
67                 # activate the timer for next year
68                 now = date.today()
69                 bDay = self.bDay[1]
70                 
71                 # set timer to feb 28th for birthdays on feb 29th
72                 try:
73                         bDayNextYear = date(now.year + 1, bDay.month, bDay.day)
74                 except ValueError: # raised on feb 29th
75                         bDayNextYear = date(now.year + 1, bDay.month, bDay.day - 1)
76                 
77                 self.begin = int(mktime(bDayNextYear.timetuple()))
78                 self.end = self.begin -1
79                 self.state = self.StatePrepared
80                 
81                 return True
82                                                 
83         def shouldSkip(self):
84                 return False
85                 
86         def timeChanged(self):
87                 self.state = self.StatePrepared
88
89 class BirthdayTimer(Timer, BirthdayStore):
90         def __init__(self):
91                 BirthdayStore.__init__(self)
92                 Timer.__init__(self)
93                 
94                 # this is used to detect settings changes, because we only want to change preremind timers if a different value was saved by the user
95                 config.plugins.birthdayreminder.preremindChanged.addNotifier(self.cbPreremindChanged, initial_call = False)
96                 config.plugins.birthdayreminder.notificationTimeChanged.addNotifier(self.cbNotificationTimeChanged, initial_call = False)
97                 
98                 # let's wait for the system time being up to date before starting the timers. needed when the box was powered off
99                 if not eDVBLocalTimeHandler.getInstance().ready():
100                         self.local_time_handler_conn = eDVBLocalTimeHandler.getInstance().m_timeUpdated.connect(self.startTimer)
101                 else:
102                         self.start()
103                         self.startNetworking()
104                 self.broadcastPort = None
105                 self.transferServerPort = None
106                 
107         def startTimer(self):
108                 self.local_time_handler_conn = None
109                 self.start()
110                 self.startNetworking()
111                 
112         def start(self):
113                 if not self.getSize():
114                         print "[Birthday Reminder] Got no birthdays, no timers to add."
115                         return
116                         
117                 self.addAllTimers()
118                 
119         def stop(self):
120                 self.stopNetworking()
121                 
122                 print "[Birthday Reminder] stopping timer..."
123                 
124                 self.timer.stop()
125                 self.timer_list = []
126                 self.timer_conn = None
127                 self.timer = None
128                 
129                 config.plugins.birthdayreminder.preremindChanged.notifiers.remove(self.cbPreremindChanged)
130                 config.plugins.birthdayreminder.notificationTimeChanged.notifiers.remove(self.cbNotificationTimeChanged)
131                 
132         def startNetworking(self):
133                 print "[Birthday Reminder] starting network communication..."
134                 
135                 port = config.plugins.birthdayreminder.broadcastPort.value
136                 self.transferServerProtocol = TransferServerFactory(self)
137                 self.broadcastProtocol = BroadcastProtocol(self)
138                 try:
139                         self.transferServerPort = reactor.listenTCP(port, self.transferServerProtocol)
140                         self.broadcastPort = reactor.listenUDP(port, self.broadcastProtocol)
141                 except:
142                         print "[Birthday Reminder] can't listen on port", port
143                         
144         def stopNetworking(self):
145                 print "[Birthday Reminder] stopping network communication..."
146                 self.broadcastPort and self.broadcastPort.stopListening()
147                 self.transferServerPort and self.transferServerPort.stopListening()
148                 
149         def requestBirthdayList(self, addr):
150                 print "[Birthday Reminder] requesting birthday list from", addr[0]
151                 reactor.connectTCP(addr[0], 7374, TransferClientFactory(self, "requestingList"))
152                 
153         def sendPingResponse(self, addr):
154                 print "[Birthday Reminder] sending ping response to", addr[0]
155                 reactor.connectTCP(addr[0], 7374, TransferClientFactory(self, "pong"))
156                 
157         def updateTimer(self, oldBirthday, newBirthday):
158                 print "[Birthday Reminder] updating timer for", oldBirthday[0]
159                 
160                 self.removeTimersForEntry(oldBirthday)
161                 self.addTimer(newBirthday)
162                 
163                 # add a preremind timer also?
164                 if config.plugins.birthdayreminder.preremind.getValue() != "-1":
165                         self.addTimer(newBirthday, preremind = True)
166                         
167         def addTimer(self, entry, preremind = False):
168                 if preremind:
169                         print "[Birthday Reminder] Adding preremind timer for", entry[0]
170                 else:
171                         print "[Birthday Reminder] Adding birthday timer for", entry[0]
172                 
173                 timeList = config.plugins.birthdayreminder.notificationTime.value
174                 notifyTime = dt_time(timeList[0], timeList[1])
175                 now = date.today()
176                 bDay = entry[1]
177                 
178                 if preremind:
179                         numDays = int(config.plugins.birthdayreminder.preremind.getValue())
180                         # set timer to feb 28th for birthdays on feb 29th
181                         try:
182                                 dateThisYear = date(now.year, bDay.month, bDay.day) - timedelta(numDays)
183                         except ValueError: # raised on feb 29th
184                                 dateThisYear = date(now.year, bDay.month, bDay.day -1) - timedelta(numDays)
185                 else:
186                         # set timer to feb 28th for birthdays on feb 29th
187                         try:
188                                 dateThisYear = date(now.year, bDay.month, bDay.day)
189                         except ValueError: # raised on feb 29th
190                                 dateThisYear = date(now.year, bDay.month, bDay.day -1)
191                         
192                 dateTimeThisYear = datetime.combine(dateThisYear, notifyTime)
193                 
194                 if dateThisYear >= now: # check if the birthday is in this year
195                         begin = int(mktime(dateTimeThisYear.timetuple()))
196                 else: # birthday is in the past, we need a timer for the next year
197                         # set timer to feb 28th for birthdays on feb 29th
198                         try:
199                                 bDayNextYear = dateTimeThisYear.replace(year = dateThisYear.year +1)
200                         except ValueError: # raised on feb 29th
201                                 bDayNextYear = dateTimeThisYear.replace(year = dateThisYear.year +1, day = dateThisYear.day -1)
202                                 
203                         begin = int(mktime(bDayNextYear.timetuple()))
204                         
205                 end = begin -1
206                 timerEntry = BirthdayTimerEntry(begin, end, preremind)
207                 timerEntry.bDay = entry
208                 self.addTimerEntry(timerEntry)
209                 
210         def removeTimersForEntry(self, entry):
211                 for timer in self.timer_list[:]:
212                         if timer.bDay == entry:
213                                 if timer.preremind:
214                                         print "[Birthday Reminder] Removing preremind timer for", entry[0]
215                                 else:
216                                         print "[Birthday Reminder] Removing birthday timer for", entry[0]
217                                 self.timer_list.remove(timer)
218                                 
219                 self.calcNextActivation()
220                 
221         def removePreremindTimers(self):
222                 print "[Birthday Reminder] Removing all preremind timers..."
223                 for timer in self.timer_list[:]:
224                         if timer.preremind:
225                                 self.timer_list.remove(timer)
226                                 
227                 self.calcNextActivation()
228                         
229         def addAllTimers(self):
230                 print "[Birthday Reminder] Adding timers for all birthdays..."
231                 bDayList = self.getBirthdayList()
232                 for entry in bDayList:
233                         self.addTimer(entry)
234                         
235                         # add a preremind timer also?
236                         if config.plugins.birthdayreminder.preremind.getValue() != "-1":
237                                 self.addTimer(entry, preremind = True)
238                                 
239         def showReceivedMessage(self, numReceived, peer):
240                 text = _("Birthday Reminder received %s birthdays from %s.") % (numReceived, peer)
241                 Notifications.AddNotification(MessageBox, text, type = MessageBox.TYPE_INFO)
242                 
243         def cbPreremindChanged(self, configElement = None):
244                 if config.plugins.birthdayreminder.preremind.value == "-1": # remove all preremind timers
245                         self.removePreremindTimers()
246                 else: # we need to add or change timers
247                         if config.plugins.birthdayreminder.preremindChanged.value: # there are no preremind timers, add new timers
248                                 print "[Birthday Reminder] Adding new preremind timers..."
249                                 for timer in self.timer_list[:]:
250                                         self.addTimer(timer.bDay, preremind = True)
251                         else: # change existing preremind timers
252                                 print "[Birthday Reminder] Changing date of preremind timers..."
253                                 self.removePreremindTimers()
254                                 
255                                 for timer in self.timer_list[:]:
256                                         self.addTimer(timer.bDay, preremind = True)
257                                         
258         def cbNotificationTimeChanged(self, configElement = None):
259                 print "[Birthday Reminder] Changing timer times..."
260                 
261                 timeList = config.plugins.birthdayreminder.notificationTime.value
262                 notifyTime = dt_time(timeList[0], timeList[1])
263                 
264                 for timer in self.timer_list:
265                         day = date.fromtimestamp(timer.begin)
266                         newDateTime = datetime.combine(day, notifyTime)
267                         timer.begin = int(mktime(newDateTime.timetuple()))
268                         timer.end = timer.begin -1
269                         
270                 self.calcNextActivation()
271