8904ec6ae75061ad8c0710ee983b80269c69e255
[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.gvoice 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         logging.debug(
123                 "Missed: %s, Voicemail: %s, SMS: %s" % (notifyOnMissed, notifyOnVoicemail, notifyOnSms)
124         )
125
126         notifySources = []
127         if notifyOnMissed:
128                 notifySources.append(("missed", get_missed))
129         if notifyOnVoicemail:
130                 notifySources.append(("voicemail", get_voicemail))
131         if notifyOnSms:
132                 notifySources.append(("sms", get_sms))
133
134         notifyUser = False
135         for type, get_material in notifySources:
136                 if is_type_changed(backend, type, get_material):
137                         notifyUser = True
138         return notifyUser
139
140
141 def notify_on_change():
142         config = ConfigParser.SafeConfigParser()
143         config.read(constants._user_settings_)
144         backend = create_backend(config)
145         notifyUser = is_changed(config, backend)
146
147         if notifyUser:
148                 logging.info("Changed")
149                 import led_handler
150                 led = led_handler.LedHandler()
151                 led.on()
152         else:
153                 logging.info("No Change")
154
155
156 if __name__ == "__main__":
157         logging.basicConfig(level=logging.WARNING, filename=constants._notifier_logpath_)
158         logging.info("Notifier %s-%s" % (constants.__version__, constants.__build__))
159         logging.info("OS: %s" % (os.uname()[0], ))
160         logging.info("Kernel: %s (%s) for %s" % os.uname()[2:])
161         logging.info("Hostname: %s" % os.uname()[1])
162         try:
163                 notify_on_change()
164         except:
165                 logging.exception("Error")
166                 raise