Re: Modem 56K en filtre d'appels telephone fixe...
Publié : 12 mai 2022, 12:14
Pour ma part, j'ai utilisé doisjerepondre (en °1) qui fonctionne comme tellows via une page web mais sans API (=> nécessaire d'analyser la page de réponse pour en extraire la classification) qui vient désormais en second (même si dans le code ci dessous, c'est en 3, le 2 collant un captcha sur demandes répétées je l'avais supprimé): Bref, j'ai un code fonctionnel pour ces deux là, à adapter à callattendant...adv a écrit : 11 mai 2022, 21:22 Je connais rien en python mais un développeur un peu calé pourrait tout à fait développer un autre plugin, afin d'envoyer le numéro de l'appelant sur un site comme...
Ayant utilisé initialement uniquement doisjerepondre qui donne une classification texte à 3 niveaux j'avais transformé la notation tellows dans ce mode car tout mon code était fait derrière pour traiter les "unknown"/"neutral"/"negative" de doisjerepondre. J'ai ajouté un perso, "not_digit" pour ceux qui bricolent les caller ID avec des caractères sortant de 0-9 par exemple (mon modem donne "P" pour un appel privé, sans envoi de caller ID, qui se retrouvera dans ce cas également)
Extraits de code python (sur les 1300 lignes de mon truc perso, sans compter la partie email/récupération d'infos Domoticz, qui m'envoie les numéros qui m'appellent par mail si je suis absent, s'ils sont des appels légitimes/non filtrés, c'est dans des modules python séparés) ci dessous pour la partie analyse de page réponse automatisée (via le module python beautifulsoup), avec les imports spécifiques (d'autres sans doute nécessaires, genre logger, mais non spécifiques) ; Le code concernant numeroinconnu.fr est là mais commenté, inutilsable cause captcha...
Code : Tout sélectionner
#
# IMPORTS specifiques:
#
from urllib2 import urlopen as urlopen2, Request
from bs4 import BeautifulSoup
# URLs check Caller ID:
CHECK_URL = 'http://www.doisjerepondre.fr/numero-de-telephone/'
#CHECK_URL2 = 'https://www.numeroinconnu.fr/numero/'
CHECK_URL3 = 'https://www.tellows.fr/num/'
#
# Fonctions CHECK CID (2 inactive):
#
def check_cid(caller_id, logger):
# Input: Caller ID as a string like '0367079816' (ranked 'neutral') or '0367077296' ('negative')...
#
# May return hereunder "score xxx" substring from http response:
# [<div class="scoreContainer">\n<div class="score unknown"></div>\n</div>]
# [<div class="scoreContainer">\n<div class="score neutral"></div>\n</div>]
# [<div class="scoreContainer">\n<div class="score negative"></div>\n</div>]
# Immediately default to 'not_digit' pseudo-score if CID string
# is not digit only (private call with no filled CID?)
if not caller_id.isdigit():
return 'not_digit'
# Otherwise defaults to 'unknown'...
ret = 'unknown'
try:
#check_page = urlopen1(CHECK_URL+caller_id)
r = Request(CHECK_URL+caller_id, headers={'User-Agent': 'Mozilla/5.0'})
check_page = urlopen2(r).read()
except: # pylint: disable=bare-except
logger.log(logging.INFO, "Connection failed : "+CHECK_URL)
return ret
check_soup = BeautifulSoup(check_page, "lxml")
#print check_soup # DEBUG (very verbose...).
try:
score_raw = check_soup.find("div", attrs={'class':u'scoreContainer'})
logger.log(logging.DEBUG, score_raw)
score = score_raw.div.get('class')
if score[0] == 'score':
ret = score[1]
else:
logger.log(logging.INFO, "Can't decode score result from "+CHECK_URL+caller_id)
logger.log(logging.INFO, "%s scored %s", caller_id , ret)
except: # pylint: disable=bare-except
logger.log(logging.INFO, "CID check exception (page structure) for "+CHECK_URL+caller_id)
return ret
"""
def check_cid2(caller_id, logger):
# Input: Caller ID as a string like '0367079816' or '0367077296'...
#
# Should return "danger level" progress-bar value percentage from http response (here 69%):
# <div id="progress-bar-wrapper"><div class="progress-bar-rank4" id="progress-bar-inner">69</div><div id="progress-bar-over"></div></div>
# Immediately default to 'not_digit' pseudo-score if CID string
# is not digit only (private call with no filled CID?)
if not caller_id.isdigit():
return 'not_digit'
# Otherwise defaults to 'unknown'...
ret = 'unknown'
try:
r = Request(CHECK_URL2+caller_id, headers={'User-Agent': 'Mozilla/5.0'})
check_page = urlopen2(r).read()
except: # pylint: disable=bare-except
logger.log(logging.INFO, "Connection failed : "+CHECK_URL2)
return ret
check_soup = BeautifulSoup(check_page, "lxml")
#print check_soup # DEBUG (very verbose...).
try:
scoreVal_raw = check_soup.find("div", attrs={'id':u'progress-bar-wrapper'})
logger.log(logging.DEBUG, scoreVal_raw)
scoreVal = int(scoreVal_raw.contents[0].text.split()[0])
if 0 <= scoreVal <= 100:
if scoreVal < 35:
ret = 'unknown'
elif 35 <= scoreVal <= 65:
ret = 'neutral'
else:
ret = 'negative'
logger.log(logging.INFO, "%s scored %d:%s", caller_id , scoreVal, ret)
except: # pylint: disable=bare-except
logger.log(logging.INFO, "CID check exception (page structure) for "+CHECK_URL2+caller_id)
return ret
"""
def check_cid3(caller_id, logger):
# Input: Caller ID as a string like '0367079816' (ranked 'neutral') or '0367077296' ('negative')...
#
# May return hereunder "score" value from http response:
# <div class="scorepic">
# <a style="line-height:0em;" href="https://blog.tellows.fr/tellows_score/" target="_blank">
# <img width="100" height="108" style="width: 100px;" class="scoreimage" src="/images/score/s8.jpg" alt="tellows Note pour 0516440080 : Score 8" />
# </a>
# </div>
# Immediately default to 'not_digit' pseudo-score if CID string
# is not digit only (private call with no filled CID?)
if not caller_id.isdigit():
return 'not_digit'
# Otherwise defaults to 'unknown'...
ret = 'unknown'
try:
r = Request(CHECK_URL3+caller_id, headers={'User-Agent': 'Mozilla/5.0'})
check_page = urlopen2(r).read()
except: # pylint: disable=bare-except
logger.log(logging.INFO, "Connection failed : "+CHECK_URL3)
return ret
check_soup = BeautifulSoup(check_page, "lxml")
#print check_soup # DEBUG (very verbose...).
try:
scoreVal_raw = check_soup.find('img', attrs={'class':u'scoreimage', 'alt':True})['alt'].split()
scoreVal = int(scoreVal_raw[-1])
logger.log(logging.DEBUG, 'Score figure (1/9): %d', scoreVal)
if 1 <= scoreVal <= 9:
if scoreVal < 4:
ret = 'unknown'
elif 4 <= scoreVal <= 6:
ret = 'neutral'
else:
ret = 'negative'
logger.log(logging.INFO, "%s scored %d:%s", caller_id , scoreVal, ret)
except: # pylint: disable=bare-except
logger.log(logging.INFO, "CID check exception (page structure) for "+CHECK_URL3+caller_id)
return ret
#
# USAGE : Verif en cascade, extrait de la fonction de filtragevenant en étape finale
# après les blacklist locales (ID opérateur ou préfixes numéro isolés),
# => Si doisjrepondre réponds "unknown", on utilise tellows...
#
(...)
score = check_cid(caller_id, logger)
# Double check if unknown for 1st online checker
if score == 'unknown':
score = check_cid3(caller_id, logger)
if (score == 'negative') or (score == 'not_digit'):
filterThisCall = True
updateCfgBlackList(call_record, logger)
# Filter call if nmbr blacklisted or scored negative
if filterThisCall:
logger.log(logging.INFO, "CID : " + caller_id + " (score = " + score + ") => Filter call !")
modem_hold_on_off(logger)
else:
logger.log(logging.DEBUG, "CID : " + caller_id + " ; score = " + score)
(...)
C'est pas directement réutilisable et tout n'y est pas: L'appel a modem_hold_on_off() est par exemple laissé: C'est l'endroit ou le décroché/raccroché est fait afin de filtrer l'appel. Cela peut aider à localiser ou greffer tout ceci dans callattendant...