Browse Source

Encore fine tuning.

Jean-Francois Burdet 6 years ago
parent
commit
96cbfff709
4 changed files with 119 additions and 65 deletions
  1. 0 4
      config.ini
  2. 9 0
      config.yml
  3. 109 61
      lenny.py
  4. 1 0
      requirements.txt

+ 0 - 4
config.ini

@@ -1,4 +0,0 @@
-[connection_1]
-domain: 192.168.1.1
-username: 621
-password: toto

+ 9 - 0
config.yml

@@ -0,0 +1,9 @@
+- connection:
+  domain: "192.168.1.1"
+  username: "621"
+  password: "toto"
+  mailer:
+    from: "lenny@burdet.ch"
+    to: "jf@burdet.ch"
+    smtp_host: "orion"
+    log_all_call: true

+ 109 - 61
lenny.py

@@ -8,6 +8,7 @@ import glob
 import io
 import os
 import signal
+import smtplib
 import string
 import subprocess
 import sys
@@ -19,6 +20,7 @@ import wave
 from datetime import datetime
 
 import linphone
+import yaml
 from enum import Enum
 
 VOLUME_THRESHOLD = 100
@@ -64,51 +66,6 @@ replies_generic.sort()
 
 THREADS_MUST_QUIT = False
 
-KTIP_LOOKUP_URL = "https://www.ktipp.ch/service/warnlisten/detail/?warnliste_id=7&ajax=ajax-search-form&keyword={" \
-                  "$number$}"
-
-SHOULDIANSWER_LOOKUP_URL = "https://ch.shouldianswer.net/telefonnummer/{$number$}"
-
-
-def is_in_blacklists(a_number):
-    return is_in_local_blacklist(a_number) or is_in_ktipp_blacklist(a_number) or is_in_shiansw_blacklist(a_number)
-
-
-def is_in_local_blacklist(a_number):
-    black_list = current_dir + "/blacklist.txt"
-    if os.path.isfile(black_list):
-        return a_number in open(current_dir + "/blacklist.txt").read()
-
-
-def is_in_ktipp_blacklist(a_number):
-    # On peut interroger le site ktipp:
-    # https://www.ktipp.ch/service/warnlisten/detail/?warnliste_id=7&ajax=ajax-search-form&keyword=0445510503
-    # Si argument keyword pas trouvé, ca donne ca dans la réponse :
-    # 0 Einträge
-
-    the_number = a_number.lstrip("0")
-    the_number = the_number.replace("+", "")
-
-    url = KTIP_LOOKUP_URL.replace("{$number$}", the_number)
-    response = ""
-    try:
-        response = urllib2.urlopen(url).read()
-    except urllib2.HTTPError:
-        pass
-
-    return "0 Eintr" not in response
-
-
-def is_in_shiansw_blacklist(a_number):
-    url = SHOULDIANSWER_LOOKUP_URL.replace("{$number$}", a_number)
-    response = ""
-    try:
-        response = urllib2.urlopen(url).read()
-    except urllib2.HTTPError:
-        pass
-
-    return '<div class="review_score negative"></div>' in response
-
 
 def get_wav_duration(fname):
     with contextlib.closing(wave.open(fname, 'r')) as f:
@@ -123,11 +80,23 @@ def sleep(duration):
 
 
 class SipConnection(object):
+    class MailType(Enum):
+        Notify_Incoming_Call = 1
+        Notify_Incoming_Telemarketer_Call = 2
+
     def log(self, msg):
         to_show = str(self) + ": " + msg
         print(to_show)
         syslog.syslog(to_show)
 
+    def mail(self, mail_cfg, text):
+        try:
+            server = smtplib.SMTP(mail_cfg["smtp_host"])
+            server.sendmail(mail_cfg["from"], mail_cfg["to"], text)
+            server.quit()
+        except smtplib.SMTPException as e:
+            self.log("Error sending email " + e.message)
+
     def say(self, core):
         if self._conversation.status is not ConversationStatus.IMTALKING:
             self._conversation.status = ConversationStatus.IMTALKING
@@ -211,13 +180,18 @@ class SipConnection(object):
         if state == linphone.CallState.IncomingReceived:
             self.log("Incoming call : {}".format(call.remote_address.username))
 
+            self.mail_if_needed(call.remote_address.username, self.MailType.Notify_Incoming_Call)
+
             self._replies_pos = 0
 
-            if is_in_blacklists(call.remote_address.username):
+            if self.is_in_blacklists(call.remote_address.username):
                 self.log("telemarketer calling : " + call.remote_address.username)
+                self.mail_if_needed(call.remote_address.username, self.MailType.Notify_Incoming_Telemarketer_Call)
 
                 call_params = core.create_call_params(call)
-                os.makedirs(current_dir + "/out", exist_ok=True)
+                if not os.path.isdir(current_dir + "/out"):
+                    os.makedirs(current_dir + "/out")
+
                 a_file = current_dir + "/out/call_from_" + slugify(call.remote_address.username) + \
                          "_" + datetime.now().strftime(
                     '%Y-%m-%d_%Hh%Mmn%Ss') + ".wav"
@@ -252,11 +226,13 @@ class SipConnection(object):
         self._core.record_file = self._incoming_stream_file
 
         proxy_cfg = self._core.create_proxy_config()
-        proxy_cfg.identity_address = self._core.create_address('sip:' + self._username + '@' + self._domain + ':5060')
-        proxy_cfg.server_addr = 'sip:' + self._domain + ':5060'
+        proxy_cfg.identity_address = self._core.create_address('sip:' + self._config_info["username"] +
+                                                               '@' + self._config_info["domain"] + ':5060')
+        proxy_cfg.server_addr = 'sip:' + self._config_info["domain"] + ':5060'
         proxy_cfg.register_enabled = True
         self._core.add_proxy_config(proxy_cfg)
-        auth_info = self._core.create_auth_info(self._username, None, self._password, None, None, self._domain)
+        auth_info = self._core.create_auth_info(self._config_info["username"], None, self._config_info["password"],
+                                                None, None, self._config_info["domain"])
         self._core.add_auth_info(auth_info)
 
         while not self._is_quitting:
@@ -268,19 +244,18 @@ class SipConnection(object):
         self.__exit__(None, None, None)
 
     def __str__(self):
-        return self._username + "@" + self._domain
+        return self._config_info["username"] + "@" + str(self._config_info["domain"])
 
-    def __init__(self, domain, username, password):
+    def __init__(self, config_info):
 
         callbacks = {
             'call_state_changed': self.call_state_changed,
             'registration_state_changed': self.registration_state_changed,
         }
 
+        self._config_info = config_info
+
         self._core = linphone.Core.new(callbacks, None, None)
-        self._domain = domain
-        self._username = username
-        self._password = password
         self._is_quitting = False
 
         self._registration_previous_message = ""
@@ -291,22 +266,96 @@ class SipConnection(object):
         self._incoming_stream_file = tempfile.NamedTemporaryFile(delete=False).name
         self._core.iterate()
 
+    def mail_if_needed(self, number, type):
+        if "mailer" in self._config_info:
+            mail_cfg = self._config_info["mailer"]
+            if type == self.MailType.Notify_Incoming_Call:
+                if mail_cfg["log_all_call"]:
+                    self.mail(mail_cfg, "Appel entrant : " + number)
+
+            if type == self.MailType.Notify_Incoming_Telemarketer_Call:
+                self.mail(mail_cfg, "Appel télémarketeur entrant : " + number)
+
+    def is_in_blacklists(self, a_number):
+        return self.is_in_local_blacklist(a_number) or self.is_in_directory_ch_blacklist(
+            a_number) or self.is_in_ktipp_blacklist(a_number) \
+               or self.is_in_shiansw_blacklist(a_number)
+
+    def is_in_local_blacklist(self, a_number):
+        black_list = current_dir + "/blacklist.txt"
+        if os.path.isfile(black_list):
+            res = a_number in open(current_dir + "/blacklist.txt").read()
+            if res:
+                self.log(a_number + " Found in localblacklist")
+            return res
+
+    def is_in_ktipp_blacklist(self, a_number):
+        # On peut interroger le site ktipp:
+        # https://www.ktipp.ch/service/warnlisten/detail/?warnliste_id=7&ajax=ajax-search-form&keyword=0445510503
+        # Si argument keyword pas trouvé, ca donne ca dans la réponse :
+        # 0 Einträge
+
+        base_url = "https://www.ktipp.ch/service/warnlisten/detail/?warnliste_id=7&ajax=ajax-search-form&keyword={" \
+                   "$number$}"
+
+        the_number = a_number.lstrip("0")
+        the_number = the_number.replace("+", "")
+
+        url = base_url.replace("{$number$}", the_number)
+        response = ""
+        try:
+            response = urllib2.urlopen(url).read()
+        except urllib2.HTTPError:
+            pass
+
+        res = "0 Eintr" not in response
+        if res:
+            self.log(a_number + " found in ktipp blacklist")
+        return res
+
+    def is_in_shiansw_blacklist(self, a_number):
+        base_url = "https://ch.shouldianswer.net/telefonnummer/{$number$}"
+        url = base_url.replace("{$number$}", a_number)
+        response = ""
+        try:
+            response = urllib2.urlopen(url).read()
+        except urllib2.HTTPError:
+            pass
+
+        res = '<div class="review_score negative"></div>' in response
+        if res:
+            self.log("Found in ch.shouldianswer.net blacklist")
+        return res
+
+    def is_in_directory_ch_blacklist(self, a_number):
+        base_url = "https://tel.local.ch/fr/{$number$}"
+        url = base_url.replace("{$number$}", a_number)
+        response = ""
+        try:
+            response = urllib2.urlopen(url).read()
+        except urllib2.HTTPError:
+            pass
+
+        res = 'https://tel.local.ch/fr/spamnumber/' in response
+
+        if res:
+            self.log(a_number + " found in directories.ch blacklist")
+        return res
+
 
 if __name__ == "__main__":
 
     cfg = ConfigParser.SafeConfigParser()
 
-    cfg_path = current_dir + "/config.ini"
+    cfg_path = current_dir + "/config.yml"
 
     if len(sys.argv) == 2:
         cfg_path = sys.argv[1]
 
     connections = []
 
-    cfg.read(cfg_path)
-
-    for c in cfg.sections():
-        connections.append(SipConnection(cfg.get(c, "domain"), cfg.get(c, "username"), cfg.get(c, "password")))
+    for connection_cfg in yaml.load(file(cfg_path)):
+        connections.append(SipConnection(connection_cfg))
 
     for sip_c in connections:
         threading.Thread(target=sip_c.start).start()
@@ -315,7 +364,6 @@ if __name__ == "__main__":
     # Ensuring clean quit and ressource releasing
     # when receiving ctrl-c from console or SIGTERM
     # from daemon manager.
-
     def signal_handler(sig, frame):
         print('External stop request!')
         for conn in connections:

+ 1 - 0
requirements.txt

@@ -3,3 +3,4 @@
 linphone
 lxml
 enum34
+pyaml