ann.py: Further improvements.
[utils.git] / cidnotify
... / ...
CommitLineData
1#!/usr/bin/python
2
3import os, sys, signal
4from time import time
5import socket, select
6import pynotify
7
8if len(sys.argv) < 2:
9 sys.stderr.write("usage: cidnotify SERVER\n")
10 sys.exit(1)
11server = sys.argv[1]
12
13pynotify.init("cidnotify")
14
15sk = None
16notif = None
17curnum = None
18lastring = None
19t2n = None
20buf = ""
21namebuf = ""
22name = None
23actab = []
24
25signal.signal(signal.SIGCHLD, signal.SIG_IGN)
26
27try:
28 acfile = open(os.getenv("HOME") + "/phone/actab")
29except IOError:
30 pass
31else:
32 for line in acfile:
33 pos = line.find(" ")
34 if pos < 0: continue
35 actab += [(line[:pos], line[pos + 1:].strip())]
36 acfile.close()
37
38for family, socktype, proto, canonname, sockaddr in socket.getaddrinfo(server, 5001, 0, socket.SOCK_STREAM):
39 try:
40 sk = socket.socket(family, socktype, proto)
41 sk.connect(sockaddr)
42 except socket.error:
43 sk = None
44 continue
45 else:
46 break
47
48if sk is None:
49 sys.stderr.write("cidnotify: could not connect to " + server + "\n");
50 sys.exit(1)
51
52def popen(*cmd):
53 rfd, wfd = os.pipe()
54 pid = os.fork()
55 if pid == 0:
56 os.dup2(wfd, 1)
57 os.close(rfd)
58 os.close(wfd)
59 os.execvp(cmd[0], cmd)
60 sys.exit(127)
61 os.close(wfd)
62 return pid, rfd
63
64def closet2n():
65 global t2n
66 if t2n is not None:
67 try:
68 os.kill(t2n[0], signal.SIGINT)
69 except:
70 pass
71 os.close(t2n[1])
72 t2n = None
73
74def close():
75 global notif, curnum, lastring, name
76 closet2n()
77 if notif is not None:
78 notif.close()
79 notif = None
80 curnum = None
81 lastring = None
82 name = None
83
84def findac(num):
85 for ac, acn in actab:
86 if num[:len(ac)] == ac:
87 return acn
88 return None
89
90def notiftext():
91 if curnum == "B10":
92 return "<i>Undisclosed number</i>"
93 text = "<b>Number</b>: " + curnum + "\n"
94 acn = findac(curnum)
95 if acn is not None:
96 text += "<b>Area code</b>: " + acn + "\n"
97 else:
98 text += "<b>Area code</b>: <i>Unknown</i>\n"
99 if name is None:
100 text += "<b>Name</b>: <i>Looking up...</i>\n"
101 elif name == "":
102 text += "<b>Name</b>: <i>No hits</i>\n"
103 else:
104 text += "<b>Name</b>: " + name + "\n"
105 return text.strip()
106
107def newnum(num):
108 global curnum, t2n, notif, lastring
109 close()
110 curnum = num
111 notif = pynotify.Notification("Phone call", notiftext())
112 notif.set_timeout(0)
113 notif.show()
114 lastring = time()
115 if curnum.isdigit():
116 t2n = popen("tel2name", num)
117
118try:
119 while True:
120 fds = [sk.fileno()]
121 if t2n is not None:
122 fds += [t2n[1]]
123 if lastring is not None:
124 timeout = lastring + 10 - time()
125 else:
126 timeout = None
127 fds = reduce(lambda s, l: s | set(l),
128 select.select(fds, [], fds, timeout),
129 set())
130
131 if sk.fileno() in fds:
132 ret = sk.recv(100)
133 if ret == "": sys.exit(0)
134 buf += ret
135 lines = buf.split("\n")
136 buf = lines[-1]
137 for line in lines[:-1]:
138 if line[0] == "N":
139 newnum(line[1:])
140 elif line[0] == "R":
141 if lastring is not None:
142 lastring = time()
143
144 if t2n is not None and t2n[1] in fds:
145 ret = os.read(t2n[1], 100)
146 namebuf += ret
147 if ret == "":
148 closet2n()
149 name = namebuf.strip()
150 namebuf = ""
151 if notif is not None:
152 notif.update("Phone call", notiftext())
153 notif.show()
154
155 if lastring is not None and lastring + 10 < time():
156 close()
157
158except KeyboardInterrupt:
159 pass