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('.*', 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) ]