Fixing notifiers, improving sound notifiers, and bumping to -4
[gc-dialer] / src / alarm_notify.py
1 #!/usr/bin/env python
2
3 import os
4 import filecmp
5 import ConfigParser
6 import pprint
7 import logging
8
9 import constants
10 from backends import gvoice
11
12
13 def get_missed(backend):
14         missedPage = backend._browser.download(backend._XML_MISSED_URL)
15         missedJson = backend._grab_json(missedPage)
16         return missedJson
17
18
19 def get_voicemail(backend):
20         voicemailPage = backend._browser.download(backend._XML_VOICEMAIL_URL)
21         voicemailJson = backend._grab_json(voicemailPage)
22         return voicemailJson
23
24
25 def get_sms(backend):
26         smsPage = backend._browser.download(backend._XML_SMS_URL)
27         smsJson = backend._grab_json(smsPage)
28         return smsJson
29
30
31 def remove_reltime(data):
32         for messageData in data["messages"].itervalues():
33                 del messageData["relativeStartTime"]
34                 del messageData["labels"]
35                 del messageData["isRead"]
36                 del messageData["isSpam"]
37                 del messageData["isTrash"]
38                 del messageData["star"]
39
40
41 def is_type_changed(backend, type, get_material):
42         jsonMaterial = get_material(backend)
43         unreadCount = jsonMaterial["unreadCounts"][type]
44
45         previousSnapshotPath = os.path.join(constants._data_path_, "snapshot_%s.old.json" % type)
46         currentSnapshotPath = os.path.join(constants._data_path_, "snapshot_%s.json" % type)
47
48         try:
49                 os.remove(previousSnapshotPath)
50         except OSError, e:
51                 # check if failed purely because the old file didn't exist, which is fine
52                 if e.errno != 2:
53                         raise
54         try:
55                 os.rename(currentSnapshotPath, previousSnapshotPath)
56                 previousExists = True
57         except OSError, e:
58                 # check if failed purely because the new old file didn't exist, which is fine
59                 if e.errno != 2:
60                         raise
61                 previousExists = False
62
63         remove_reltime(jsonMaterial)
64         textMaterial = pprint.pformat(jsonMaterial)
65         currentSnapshot = file(currentSnapshotPath, "w")
66         try:
67                 currentSnapshot.write(textMaterial)
68         finally:
69                 currentSnapshot.close()
70
71         if unreadCount == 0 or not previousExists:
72                 return False
73
74         seemEqual = filecmp.cmp(previousSnapshotPath, currentSnapshotPath)
75         return not seemEqual
76
77
78 def create_backend(config):
79         gvCookiePath = os.path.join(constants._data_path_, "gv_cookies.txt")
80         backend = gvoice.GVoiceBackend(gvCookiePath)
81
82         loggedIn = False
83
84         if not loggedIn:
85                 loggedIn = backend.is_authed()
86
87         if not loggedIn:
88                 import base64
89                 try:
90                         blobs = (
91                                 config.get(constants.__pretty_app_name__, "bin_blob_%i" % i)
92                                 for i in xrange(2)
93                         )
94                         creds = (
95                                 base64.b64decode(blob)
96                                 for blob in blobs
97                         )
98                         username, password = tuple(creds)
99                         loggedIn = backend.login(username, password)
100                 except ConfigParser.NoOptionError, e:
101                         pass
102                 except ConfigParser.NoSectionError, e:
103                         pass
104
105         assert loggedIn
106         return backend
107
108
109 def is_changed(config, backend):
110         try:
111                 notifyOnMissed = config.getboolean("2 - Account Info", "notifyOnMissed")
112                 notifyOnVoicemail = config.getboolean("2 - Account Info", "notifyOnVoicemail")
113                 notifyOnSms = config.getboolean("2 - Account Info", "notifyOnSms")
114         except ConfigParser.NoOptionError, e:
115                 notifyOnMissed = False
116                 notifyOnVoicemail = False
117                 notifyOnSms = False
118         except ConfigParser.NoSectionError, e:
119                 notifyOnMissed = False
120                 notifyOnVoicemail = False
121                 notifyOnSms = False
122
123         notifySources = []
124         if notifyOnMissed:
125                 notifySources.append(("missed", get_missed))
126         if notifyOnVoicemail:
127                 notifySources.append(("voicemail", get_voicemail))
128         if notifyOnSms:
129                 notifySources.append(("sms", get_sms))
130
131         notifyUser = False
132         for type, get_material in notifySources:
133                 if is_type_changed(backend, type, get_material):
134                         notifyUser = True
135         return notifyUser
136
137
138 def notify_on_change():
139         config = ConfigParser.SafeConfigParser()
140         config.read(constants._user_settings_)
141         backend = create_backend(config)
142         notifyUser = is_changed(config, backend)
143
144         if notifyUser:
145                 logging.info("Changed")
146                 import led_handler
147                 led = led_handler.LedHandler()
148                 led.on()
149         else:
150                 logging.info("No Change")
151
152
153 if __name__ == "__main__":
154         logging.basicConfig(level=logging.DEBUG, filename=constants._notifier_logpath_)
155         logging.info("Notifier %s-%s" % (constants.__version__, constants.__build__))
156         logging.info("OS: %s" % (os.uname()[0], ))
157         logging.info("Kernel: %s (%s) for %s" % os.uname()[2:])
158         logging.info("Hostname: %s" % os.uname()[1])
159         try:
160                 notify_on_change()
161         except:
162                 logging.exception("Error")
163                 raise