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