################################################################## # Basic CallerID listener # Coded by Rich-Hard (farside@rogers.com) # # Update to YAC2: now supports YAC, CallerID Sentry and software from Impulse Technology # # ** YAC Server Software: # http://www.sunflowerhead.com/software/yac/ # # ** CID Sentry Server Software: # Windows: http://home.houston.rr.com/jeffkohn/callerid_sentry.htm # Macintosh: http://www.afterten.com/products/cidtracker/index.html # 3Com Audry: http://www.timemocksme.com/acid/ # # ** Impulse Technology Software (there are a number of options using this protocol): # http://www.imptec.com/index.html # # To add thumbnails for incoming calls, add [phonenumber].jpg # into the CallerID subdirectory. The filename must be the same number # of digits as display in the callid, but should contain no extra # characters such as hyphens or spaces. ################################################################## import socket import xbmc, xbmcgui, threading, thread from time import * from string import * MYAREACODE = "519" # SPECIFY YOUR AREA CODE DELAY = 5 # SPECIFY DELAY BEFORE CLOSE IN SECONDS DOLOG = 1 # SPECIFY WHETHER OR NOT TO WRITE TO LOG DOIMAGE = 1 # SPECIFY WHETHER OR NOT TO DISPLAY PICTURE WITH DIALOG SERVERTYPE = "YAC" # SPECIFY EITHER "YAC", "CIDSENTRY" OR "IMPULSE" YACPORT = 10629 # SPECIFY PORT FOR YAC CIDSENTRYPORT = 4550 # SPECIFY PORT FOR CALLER ID SENTRY CIDSENTRYIP = "192.168.0.49" # SPECIFY IP ADDRESS FOR CALLER ID SENTRY SERVER IMPULSEPORT = 42685 # SPECIFY PORT FOR IMPULSE BIGENDIAN = 1 # 0 OR 1, IF ONE DOESN'T WORK, TRY THE OTHER HOST = '' # Symbolic name meaning the local host class packet: def __init__(self, type, param1, param2 = "", param3 = ""): self.type = type self.param1 = param1 self.param2 = param2 self.param3 = param3 def decodepacket(the_string): if not(BIGENDIAN): type = ord(the_string[3]) param1 = (ord(the_string[6]) * 256) + ord(the_string[7]) else: type = ord(the_string[0]) param1 = (ord(the_string[5]) * 256) + ord(the_string[4]) param2 = the_string[8:72] param3 = the_string[72:] for i in range(-63, 0): if ord(param2[-i]) == 0: param2 = param2[:-i] if ord(param3[-i]) == 0: param3 = param3[:-i] return packet(type, param1, param2, param3) def encodepacket(the_packet): r = " " if not(BIGENDIAN): r = r + chr(0) else: r = r + chr(the_packet.type) r = r[1:] r = r + chr(0) r = r + chr(0) if BIGENDIAN: r = r + chr(0) else: r = r + chr(the_packet.type) if not(BIGENDIAN): r = r + chr(the_packet.param1 - ((the_packet.param1 / 256) * 256)) else: r = r + chr(the_packet.param1 - ((the_packet.param1 / 256) * 256)) r = r + chr(the_packet.param1 / 256) r = r + chr(0) r = r + chr(0) r = r + the_packet.param2 for i in range(len(r), 72): r = r + chr(0) r = r + the_packet.param3 for i in range(len(r), 136): r = r + chr(0) return r def formatnumber( n ): if len( n ) == 7: return "(" + MYAREACODE + ") " + n[:3] + "-" + n[3:] if len( n ) == 10: return "(" + n[:3] + ") " + n[3:6] + "-" + n[6:] if len( n ) == 11: return n[0] + " (" + n[1:4] + ") " + n[4:7] + "-" + n[7:] return n def fileExists(f): try: file = open(f) except IOError: exists = 0 else: exists = 1 return exists class caller(xbmcgui.WindowDialog): def __init__(self): w = self.getWidth() h = self.getHeight() self.bg = xbmcgui.ControlImage(w - 282, h - 138, 222, 103, os.getcwd().replace(";","")+"\\CallerID\\dialog.png") self.addControl(self.bg) self.callerid = xbmcgui.ControlLabel(w - 275, h - 95, 151, 64, data, 'font13', '0xff000000') self.addControl(self.callerid) if not DOIMAGE: self.title = xbmcgui.ControlLabel(w - 277, h - 133, 100, 10, 'Caller ID', 'font13', '0xffffffff') self.addControl(self.title) else: self.frame = xbmcgui.ControlImage(w - 359, h - 138, 77, 103, os.getcwd().replace(";","")+"\\CallerID\\frame.png") self.addControl(self.frame) self.title = xbmcgui.ControlLabel(w - 354, h - 133, 100, 10, 'Caller ID', 'font13', '0xffffffff') self.addControl(self.title) filename = replace(number, '(', '') filename = replace(filename, ')', '') filename = replace(filename, ' ', '') filename = replace(filename, '-', '') filename = os.getcwd().replace(";","")+"\\CallerID\\" + filename + '.jpg' if not fileExists(filename): filename = os.getcwd().replace(";","")+"\\CallerID\\default.jpg" self.tn = xbmcgui.ControlImage(w - 359, h - 112, 77, 77, filename) self.addControl(self.tn) self.a = -1 self.shown = 1 subThread = threading.Thread(target=self.SubthreadProc, args=()) subThread.start() def SubthreadProc(self): sleep(DELAY) if self.shown: self.close() def onAction(self, action): if self.a == action: self.shown = 0 self.close() self.a = action if SERVERTYPE == "CIDSENTRY": s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setblocking(1) s.bind((HOST, CIDSENTRYPORT)) req = packet(1, CIDSENTRYPORT) rpack = encodepacket(req) s.sendto(rpack, (CIDSENTRYIP, CIDSENTRYPORT)) elif SERVERTYPE == "IMPULSE": s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setblocking(1) s.bind((HOST, IMPULSEPORT)) req = packet(1, IMPULSEPORT) else: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, YACPORT)) data = "" name = "" number = "" while 1: if SERVERTYPE == "YAC": s.listen(1) conn, addr = s.accept() a = conn.recv(1024) alist = split(a[5:], "~") if len(alist) > 1: name = alist[0] number = alist[1] data = number + "\n" + name else: data = a elif SERVERTYPE == "CIDSENTRY": r = s.recv(1024) p = decodepacket(r) if p.type == 3: name = p.param2 number = formatnumber(p.param3) data = number + "\n" + name elif SERVERTYPE == "IMPULSE": r=s.recv(1024) if r[:4] == "NAME": name = r[5:] elif r[:4] == "NMBR": number = formatnumber(replace(r[5:], "-", "")) if name != "" and number != "": data = number + "\n" + name if data != "": print(data) w = caller() w.doModal() del w if DOLOG == 1: log = open(os.getcwd().replace(";","")+"\\call_log.txt", "a") logentry = asctime(localtime(time())) + ": " + replace(data, "\n", " (") + ")" log.write(logentry + "\n") log.close() if SERVERTYPE == "YAC": conn.close() data = "" name = "" number = ""