from Screens.Screen import Screen from Screens.MessageBox import MessageBox from Components.ActionMap import ActionMap from Components.Label import Label from Plugins.Plugin import PluginDescriptor from Tools import Notifications from twisted.internet import reactor from twisted.internet.protocol import ReconnectingClientFactory from twisted.protocols.basic import LineReceiver from enigma import eTimer my_global_session = None from Components.config import config, ConfigSubsection, ConfigSelection, ConfigIP, ConfigEnableDisable, getConfigListEntry, ConfigText from Components.ConfigList import ConfigList, ConfigListScreen import os, urllib, re config.FritzCall = ConfigSubsection() config.FritzCall.hostname = ConfigIP(default = [192,168,1,1]) config.FritzCall.enable = ConfigEnableDisable(default = False) config.FritzCall.lookup = ConfigEnableDisable(default = False) config.FritzCall.showOutgoing = ConfigEnableDisable(default = False) config.FritzCall.fritzphonebook = ConfigEnableDisable(default = False) #config.FritzCall.prefix = ConfigText("030") config.FritzCall.phonebook = ConfigEnableDisable(default = False) config.FritzCall.addcallers = ConfigEnableDisable(default = False) config.FritzCall.phonebookLocation = ConfigSelection(choices = [("usb", _("USB Stick")), ("cf", _("CF Drive")), ("hdd", _("Harddisk"))]) PhonebookFile = { "hdd" : "/media/hdd/PhoneBook.txt", "usb" : "/media/usb/PhoneBook.txt", "cf" : "/media/cf/PhoneBook.txt" } # --------------------------------------- # Hier die Vorwahl für ausgehende Telefonate eingeben: Prefix = "030" # # Kennwort für die Weboberfläche der FritzBox (für Telefonbuch-Abfrage) # wenn kein Kennwort eingestellt ist - leer lassen FritzBoxPassword = "" #FritzBoxPassword = "123456" # # --------------------------------------- class FritzCallSetup(ConfigListScreen, Screen): skin = """ """ def __init__(self, session, args = None): from Tools.BoundFunction import boundFunction Screen.__init__(self, session) self.onClose.append(self.abort) # nun erzeugen wir eine liste von elementen fuer die menu liste. self.list = [ ] self.list.append(getConfigListEntry(_("Call monitoring"), config.FritzCall.enable)) self.list.append(getConfigListEntry(_("Fritz!Box FON IP address"), config.FritzCall.hostname)) self.list.append(getConfigListEntry(_("Reverse Lookup Caller ID (DE only)"), config.FritzCall.lookup)) self.list.append(getConfigListEntry(_("Show Outgoing Calls"), config.FritzCall.showOutgoing)) # self.list.append(getConfigListEntry(_("Prefix for Outgoing Calls"), config.FritzCall.prefix)) self.list.append(getConfigListEntry(_("Read PhoneBook from Fritz!Box"), config.FritzCall.fritzphonebook)) self.list.append(getConfigListEntry(_("Use PhoneBook"), config.FritzCall.phonebook)) self.list.append(getConfigListEntry(_("Add new Caller to PhoneBook"), config.FritzCall.addcallers)) self.list.append(getConfigListEntry(_("PhoneBook Location"), config.FritzCall.phonebookLocation)) ConfigListScreen.__init__(self, self.list) # DO NOT ASK. self["setupActions"] = ActionMap(["SetupActions"], { "save": self.save, "cancel": self.cancel, "ok": self.save, }, -2) def abort(self): print "aborting" def save(self): for x in self["config"].list: x[1].save() if fritz_call is not None: fritz_call.connect() if config.FritzCall.phonebook.value: # ggf. Datei mit Dummyeintrag anlegen if not os.path.exists(PhonebookFile[config.FritzCall.phonebookLocation.value]): try: f = open(PhonebookFile[config.FritzCall.phonebookLocation.value],'w') f.write("01234567890#Name, Strasse, Ort (Leerzeichen nach dem Komma beachten!)\n"); f.close() except: Notifications.AddNotification(MessageBox, "Can't create PhoneBook.txt", type=MessageBox.TYPE_INFO, timeout=5) else: fritz_call.loadPhoneBook() fritz_call.loadFritzPhoneBook() self.close() def cancel(self): for x in self["config"].list: x[1].cancel() self.close() class FritzProtocol(LineReceiver): def reverseLookup(self, number): html = urllib.urlopen("http://www3.dasoertliche.de/?form_name=search_inv&ph="+number+"&recFrom=&atfilter=&districtfilter=&bname=&la=de&subnav=map1").read() found = re.match('.*(.*?)', html, re.S) result = '' if found: # TD-Tag gefunden td = found.group(1) # erste geklammerte Gruppe, hier Tag-Inhalt text = re.sub("<.*?>", "", td) # Tags entfernen text = text.replace(" ", " ") # Normale Leerzeichen lines = text.split("\n") # Array auf Zeilen result = lines[2].strip() # Name address = lines[8].strip() # Adresse result = result + ", " + address # Daten zusammensetzen (jeweils mit Komma getrennt) return result def searchPhoneBook(self, number): name = "" if config.FritzCall.phonebook.value: if phonebook.has_key(number): # Treffer ? name = phonebook[number] if name == "": name = "(unbekannt)" return name def addToPhoneBook(self, number, name): if config.FritzCall.phonebook.value: if config.FritzCall.addcallers.value: if os.path.exists(PhonebookFile[config.FritzCall.phonebookLocation.value]): f = open(PhonebookFile[config.FritzCall.phonebookLocation.value],'a') # Nummer + Name an Phonebook anhängen if name == "": name = "\n" string = number +"#"+ name # Trennzeichen zw. Nummer und Name phonebook[number] = name; # Liste updaten f.write(string) # und in Datei schreiben f.close() return def lineReceived(self, line): #15.07.06 00:38:54;CALL;1;4;;; #15.07.06 00:38:58;DISCONNECT;1;0; #15.07.06 00:39:22;RING;0;;; #15.07.06 00:39:27;DISCONNECT;0;0; a = line.split(';') (date, event) = a[0:2] if event == "RING": phone = a[4] number = a[3] timeout = 10 text = "" elif config.FritzCall.showOutgoing.value and event == "CALL": phone = a[4] number = a[5] timeout = 10 text = "Ausgehender " if number[0] != '0': # Ortsvorwahl ergänzen ? number = Prefix + number else: return name = self.searchPhoneBook(number) if name == '': if config.FritzCall.lookup.value: name = self.reverseLookup(number) # Internet - Abfrage if config.FritzCall.addcallers.value and event == "RING": self.addToPhoneBook(number, name) # Nummer in Telefonbuch eintragen if(name != ""): name = name.decode("iso-8859-1") name = name.encode("utf-8") address = name.replace(", ", "\n") # Die Adresse wegen der Optik untereinander text += _("Anruf - %s\n---------------------------------------------\n%s\n(%s)") % (date, address, number) else: text += _("Anruf - %s\n---------------------------------------------\n%s") % (date, number) Notifications.AddNotification(MessageBox, text, type=MessageBox.TYPE_INFO, timeout=timeout) class FritzClientFactory(ReconnectingClientFactory): initialDelay = 20 maxDelay = 500 def __init__(self): self.hangup_ok = False def startedConnecting(self, connector): Notifications.AddNotification(MessageBox, _("Verbinde zu Fritz!Box..."), type=MessageBox.TYPE_INFO, timeout=2) def buildProtocol(self, addr): Notifications.AddNotification(MessageBox, _("Verbunden mit Fritz!Box!"), type=MessageBox.TYPE_INFO, timeout=2) self.resetDelay() return FritzProtocol() def clientConnectionLost(self, connector, reason): if not self.hangup_ok: Notifications.AddNotification(MessageBox, _("Disconnected from\nFritz!Box! (%s)\nretrying...") % reason.getErrorMessage(), type=MessageBox.TYPE_INFO, timeout=4) ReconnectingClientFactory.clientConnectionLost(self, connector, reason) def clientConnectionFailed(self, connector, reason): Notifications.AddNotification(MessageBox, _("Connection to Fritz!Box\nfailed! (%s)\nretrying...") % reason.getErrorMessage(), type=MessageBox.TYPE_INFO, timeout=4) ReconnectingClientFactory.clientConnectionFailed(self, connector, reason) class FritzCall: def __init__(self): self.dialog = None self.d = None self.connect() self.loadPhoneBook() self.loadFritzPhoneBook() def loadPhoneBook(self): phonebook.clear() if os.path.exists(PhonebookFile[config.FritzCall.phonebookLocation.value]): for line in open(PhonebookFile[config.FritzCall.phonebookLocation.value]): # Datei zeilenweise lesen try: nummer, name = line.split("#") # Zeile in Nummer und Name trennen if not phonebook.has_key(nummer): # gleich Nummern ? nur den ersten Eintrag nehmen phonebook[nummer] = name # in Liste einfügen except: pass def loadFritzPhoneBook(self): if config.FritzCall.fritzphonebook: if FritzBoxPassword != "": postdata = urllib.urlencode({"login:command/password":FritzBoxPassword}) html = urllib.urlopen("http://%d.%d.%d.%d/cgi-bin/webcm" % tuple(config.FritzCall.hostname.value), postdata).read() fritz_url = "http://%d.%d.%d.%d/cgi-bin/webcm?getpage=../html/de/menus/menu2.html&var:lang=de&var:pagename=fonbuch&var:menu=fon" % tuple(config.FritzCall.hostname.value) html = urllib.urlopen(fritz_url).read() found = re.match('.*\n(.*?)
', html, re.S) result = '' if found: # Tags gefunden table = found.group(1) # erste geklammerte Gruppe, hier Tag-Inhalt text = re.sub("<.*?>", "", table) # Tags entfernen text = text.split('\n') for line in text: try: if line.index('TrFon'): # In der Zeile ist eine Adresse ? line = line.replace('",', '#') # Trennzeichen erzeugen line = line.replace('"', '') # "-Striche entfernen try: ldfnr, name, nummer, kurzwahl, vanity = line.split("#") #Zeile in Daten auftrennen name = name.replace("ß", "ß").replace("ä","ä").replace("ö","ö").replace("ü","ü").replace("Ä","Ä").replace("Ö","Ö").replace("Ü","Ü") phonebook[nummer.strip()] = name.strip() # in Liste einfügen (Leerzeichen entfernen) except: pass except: pass else: Notifications.AddNotification(MessageBox, _("FritzBox Telefonbuch konnte nicht gelesen werden.") , type=MessageBox.TYPE_INFO, timeout=4) def connect(self): self.abort() if config.FritzCall.enable.value: f = FritzClientFactory() self.d = (f, reactor.connectTCP("%d.%d.%d.%d" % tuple(config.FritzCall.hostname.value), 1012, f)) def shutdown(self): self.abort() def abort(self): if self.d is not None: self.d[0].hangup_ok = True self.d[0].stopTrying() self.d[1].disconnect() self.d = None def main(session): session.open(FritzCallSetup) fritz_call = None phonebook = {} def autostart(reason, **kwargs): global fritz_call global phonebook # ouch, this is a hack if kwargs.has_key("session"): global my_global_session my_global_session = kwargs["session"] return print "autostart" if reason == 0: fritz_call = FritzCall() elif reason == 1: fritz_call.shutdown() fritz_call = None def Plugins(**kwargs): return [ PluginDescriptor(name="FritzCall", description="Display Fritzbox-Fon calls on screen", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main), PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = autostart) ]