forked from seveas/hacks
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathp2000
executable file
·238 lines (214 loc) · 8.08 KB
/
p2000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
#!/usr/bin/python
#
# Watch p2000 alarms and notify for new alarms
#
# This program displays p2000 pager messages. p2000 is the pager system for the
# dutch emergency services. Messages are downloaded from p2000-online.net every
# so often (default: 60 seconds). This website also has a delay of about 90
# seconds, making the total delay approximately 2.5 minutes.
#
# Requirements:
# - A linux desktop
# - pynotify and gtk to display notifications
# - beautifulsoup for parsing html
# - libcanberra to play a sound when new alarms arrive (optional)
#
# (c)2011 Dennis Kaarsemaker
# License: gpl 3+
from BeautifulSoup import BeautifulSoup as soup
import ctypes
import os
import glib
import gtk
import pynotify
import sys
import time
import urllib
# These are the region names as used by p2000-online.net
regions = (
"Amsterdam-Amstelland",
"Brabant Noord",
"Brabant ZuidOost",
"Drenthe",
"Flevoland",
"Friesland",
"Gelderland-Midden",
"Gelderland-Zuid",
"Gooi en Vechtstreek",
"Groningen",
"Haaglanden",
"Hollands Midden",
"IJsselland",
"Kennemerland",
"Limburg Noord",
"Limburg Zuid",
"Midden en West Brabant",
"Noord- en Oost Gelderland",
"Noord-Holland Noord",
"Rotterdam Rijnmond",
"Twente",
"Utrecht",
"Zaanstreek-Waterland",
"Zeeland",
"Zuid Holland Zuid",
)
def _escape(data):
return data.replace('&','&').replace('<','<').replace('>','>')
class I(dict):
def __getitem__(self, item):
return 'http://alarmeringen.nl/static/images/icon_%s.png' % dict.__getitem__(self, item)
class Alert(object):
"""Representation of a single message"""
icons = I({
'brandweer': 'fire',
'politie': 'police',
'ambulance': 'ambu',
'lifeliner': 'heli',
'knrm': 'boat',
})
def __init__(self, date, time, who, region, text, recipients = None):
self.time = '%s %s' % (date, time)
self.who = who
self.region = region
self.text = text
self.recipients = recipients or []
if self.is_lifeliner():
self.who = 'LifeLiner'
def is_lifeliner(self):
return 'lifeliner' in (''.join(self.recipients)).lower()
def show(self, timeout):
"""Display a notification for this alarm"""
title = "%s %s" % (self.who, self.region)
text = "%s %s" % (self.time, self.text)
mod = self.__module__
if mod == '__main__':
path = sys.argv[0]
else:
path = sys.modules[mod].__file__
path = os.path.abspath(os.path.dirname(path))
img = self.icons[self.who.lower()]
imgc = os.path.join(os.path.expanduser('~'), '.cache', os.path.basename(imgl))
if not os.path.exists(imgc):
with open(imgc, 'w') as fd:
req = urllib.urlopen(img)
if req.code == 404:
raise IOError
fd.write(req.read())
notification = pynotify.Notification(title, _escape(text), 'file://' + imgc)
notification.set_urgency(pynotify.URGENCY_CRITICAL)
caps = pynotify.get_server_caps()
if self.recipients and 'actions' in caps:
notification.add_action("details", "Details", self.details)
# If the notification is deleted, the callback will not be called
_alerts.append(notification)
notification.set_timeout(timeout * 1000)
notification.show()
def prnt(self):
"""Output this alarm on stdout"""
print "%s %s %s %s" % (time.ctime(), self.time, self.who, self.region)
print "%s %s %s" % (time.ctime(), ' ' * len(self.time), self.text)
for r in self.recipients:
print "%s %s %s" % (time.ctime(), ' ' * len(self.time), r)
def details(self, notification, action):
message = '<b>%s</b>\n%s\n<span foreground="gray">%s</span>' % (self.text, self.time, '\n'.join(self.recipients))
dialog = gtk.MessageDialog(type=gtk.MESSAGE_INFO, buttons=gtk.BUTTONS_CLOSE)
dialog.set_markup(message)
dialog.set_title('%s %s' % (self.who, self.region))
dialog.connect("response", lambda *args: dialog.destroy())
dialog.show()
dialog.set_keep_above(True)
_alerts.remove(notification)
_alerts = []
class P2000Interface(object):
def __init__(self, opts):
self.regions = opts.regions
self.verbose = opts.verbose
self.last_alert = None
self.quiet = opts.quiet
if not self.quiet:
try:
self.canberra = ctypes.CDLL('libcanberra.so.0')
self.ctx = ctypes.c_void_p()
self.canberra.ca_context_create(ctypes.byref(self.ctx))
except OSError:
# Can't find libcanberra
self.quiet = True
pynotify.init("p2000 meldingen")
def get_alerts(self):
"""Fetch all alerts for these regions"""
url = 'http://www.p2000-online.net/p2000.php?%s&nofilterform=1'
url = url % '&'.join(['%s=1' % x for x in self.regions])
if self.verbose:
print time.ctime(), url
try:
data = urllib.urlopen(url).read()
except IOError:
if self.verbose:
import traceback
traceback.print_exc()
return []
doc = soup(data)
alerts = []
table = doc.body('table', {'style': 'align:center'})[0]
for tr in table('tr'):
if tr.td.get('class', None) == 'DT':
alerts.append(Alert(*[x.text for x in tr('td')]))
else:
recipient = tr('td')[-1].text
if recipient != ' ':
alerts[-1].recipients.append(recipient)
return alerts
def alert_iteration(self, first_iteration = False):
global _alerts
_alerts = []
if self.verbose:
print time.ctime(), "Fetching alerts..."
alerts = self.get_alerts()
if self.verbose:
print time.ctime(), "Received %d alerts" % len(alerts)
play_sound = True
alerts = [x for x in alerts[:5] if x.time > self.last_alert]
alerts.reverse()
timeout = min(10,3*len(alerts))
if self.verbose:
print "Timeout: %d" % timeout
for alert in alerts:
if play_sound:
self.canberra.ca_context_play(self.ctx, 1, "event.id", "message-new-instant", None)
play_sound = False
if self.verbose:
alert.prnt()
alert.show(timeout)
self.last_alert = alert.time
return not first_iteration
def main():
import optparse
usage = """%prog [options]
This tool autimatically downloads and displays p2000 alerts for the regions you
specify (Default: Noord-Holland Noord and Flevoland). It can display images and
play sounds too."""
p = optparse.OptionParser(usage = usage)
default_regions = ("Flevoland","Noord-HollandNoord")
p.add_option('-a', '--all', dest='all_regions', action='store_true', default=False,
help="Show alerts for all regions")
for r in regions:
opt_r = '--%s' % r.lower().replace('-','').replace(' ','')
p.add_option(opt_r, dest='regions', action='append_const', const=r.replace(' ',''),
help="Show alerts for region %s" % r)
p.add_option('-d', '--delay', dest='delay', type='int', default=60, metavar='SECS',
help="Delay between updates (default: 60)")
p.add_option('-v', '--verbose', dest='verbose', action='store_true', default=False,
help="Verbose output")
p.add_option('-q', '--quiet', dest='quiet', action='store_true', default=False,
help="Don't play sounds when new alarms arrive")
opts, args = p.parse_args()
if not opts.regions:
opts.regions = default_regions
if opts.all_regions:
opts.regions = [x.replace(' ','') for x in regions]
ui = P2000Interface(opts)
glib.timeout_add_seconds(0, ui.alert_iteration, True)
glib.timeout_add_seconds(opts.delay, ui.alert_iteration)
gtk.main()
if __name__ == '__main__':
main()