Browse Source

Add support for geolocalisation via the phonenumbers lib in the get_cid_name.py script. If you add --geoloc, the numbers that are not found in OpenERP will be geolocalized.

Thanks to Ludovic Gasc for making me discover this great "phonenumbers" lib.
pull/26/head
Alexis de Lattre 12 years ago
parent
commit
d907ba2e72
  1. 84
      asterisk_click2dial/scripts/get_cid_name.py
  2. 11
      asterisk_click2dial/scripts/get_cid_name_timeout.sh

84
asterisk_click2dial/scripts/get_cid_name.py

@ -7,15 +7,16 @@
OpenERP's partner addresses, and, if it finds the phone number, it will get the
corresponding name of the person and use this name as CallerID name for the incoming call.
Requires the "asterisk_click2dial" module (available in the extra-addons)
on OpenERP version >= 5
Requires the "asterisk_click2dial" module
available from https://code.launchpad.net/openerp-asterisk-connector
for OpenERP version >= 5.0
This script is designed to be used as an AGI on an Asterisk IPBX...
BUT I advise you to use a wrapper around this script to control the
execution time. Why ? Because if the script takes too much time to
execute or get stucks (in the XML-RPC request for example), then the
incoming phone call will also get stucks and you will miss a call !
The most simple solution I found is to use the "timeout" shell command to
The simplest solution I found is to use the "timeout" shell command to
call this script, for example :
# timeout 1s get_cid_name.py <OPTIONS>
@ -34,11 +35,14 @@
It's probably a good idea to create a user in OpenERP dedicated to this task.
This user only needs to be part of the group "Asterisk CallerID", which has
read access on the 'res.partner.address' object, nothing more.
Note that this script can be used without OpenERP, with just the geolocalisation
feature : for that, don't use option --server ; only use --geoloc
"""
__author__ = "Alexis de Lattre <alexis.delattre@akretion.com>"
__date__ = "December 2010"
__version__ = "0.1"
__version__ = "0.2"
# Copyright (C) 2010-2012 Alexis de Lattre <alexis.delattre@akretion.com>
#
@ -61,18 +65,23 @@ from optparse import OptionParser
# CID Name that will be displayed if there is no match in res.partner.address
# and no geolocalisation
default_cid_name = "Not in OpenERP"
# Define command line options
option_server = {'names': ('-s', '--server'), 'dest': 'server', 'type': 'string', 'help': 'DNS or IP address of the OpenERP server. Default = localhost', 'action': 'store', 'default':'localhost'}
option_server = {'names': ('-s', '--server'), 'dest': 'server', 'type': 'string', 'help': 'DNS or IP address of the OpenERP server. Default = none (will not try to connect to OpenERP)', 'action': 'store', 'default': False}
option_port = {'names': ('-p', '--port'), 'dest': 'port', 'type': 'int', 'help': "Port of OpenERP's XML-RPC interface. Default = 8069", 'action': 'store', 'default': 8069}
option_ssl = {'names': ('-e', '--ssl'), 'dest': 'ssl', 'help': "Use XML-RPC secure i.e. with SSL instead of clear XML-RPC. Default = no, use clear XML-RPC.", 'action': 'store_true', 'default': False}
option_database = {'names': ('-d', '--database'), 'dest': 'database', 'type': 'string', 'help': "OpenERP database name. Default = openerp", 'action': 'store', 'default': 'openerp'}
option_ssl = {'names': ('-e', '--ssl'), 'dest': 'ssl', 'help': "Use XML-RPC secure i.e. with SSL instead of clear XML-RPC. Default = no, use clear XML-RPC", 'action': 'store_true', 'default': False}
option_database = {'names': ('-d', '--database'), 'dest': 'database', 'type': 'string', 'help': "OpenERP database name. Default = 'openerp'", 'action': 'store', 'default': 'openerp'}
option_user = {'names': ('-u', '--user-id'), 'dest': 'user', 'type': 'int', 'help': "OpenERP user ID to use when connecting to OpenERP. Default = 2", 'action': 'store', 'default': 2}
option_password = {'names': ('-w', '--password'), 'dest': 'password', 'type': 'string', 'help': "Password of the OpenERP user. Default = demo", 'action': 'store', 'default': 'demo'}
option_password = {'names': ('-w', '--password'), 'dest': 'password', 'type': 'string', 'help': "Password of the OpenERP user. Default = 'demo'", 'action': 'store', 'default': 'demo'}
option_ascii = {'names': ('-a', '--ascii'), 'dest': 'ascii', 'help': "Convert name from UTF-8 to ASCII. Default = no, keep UTF-8", 'action': 'store_true', 'default': False}
option_geoloc = {'names': ('-g', '--geoloc'), 'dest': 'geoloc', 'help': "Try to geolocate phone numbers unknown to OpenERP. This features requires the 'phonenumbers' Python lib. To install it, run 'sudo pip install phonenumbers' Default = no", 'action': 'store_true', 'default': False}
option_geoloc_lang = {'names': ('-l', '--geoloc-lang'), 'dest': 'lang', 'help': "Language in which the name of the country and city name will be displayed by the geolocalisation database. Use the 2 letters ISO code of the language. Default = 'en'", 'action': 'store', 'default': "en"}
option_geoloc_country = {'names': ('-c', '--geoloc-country'), 'dest': 'country', 'help': "2 letters ISO code for your country e.g. 'FR' for France. This will be used by the geolocalisation system to parse the phone number of the calling party. Default = 'FR'", 'action': 'store', 'default': "FR"}
option_geoloc_cityonly = {'names': ('-t', '--geoloc-city-only'), 'dest': 'cityonly', 'help': "Only display the city name, instead of displaying both the country and the city. Default = no", 'action': 'store_true', 'default': False}
options = [option_server, option_port, option_ssl, option_database, option_user, option_password, option_ascii]
options = [option_server, option_port, option_ssl, option_database, option_user, option_password, option_ascii, option_geoloc, option_geoloc_lang, option_geoloc_country, option_geoloc_cityonly]
def stdout_write(string):
'''Wrapper on sys.stdout.write'''
@ -90,6 +99,21 @@ def stderr_write(string):
sys.stdout.flush()
return True
def geolocate_phone_number(number, country_code, lang):
import phonenumbers
import phonenumbers.geocoder
res = ''
phonenum = phonenumbers.parse(number, country_code.upper())
city = phonenumbers.area_description_for_number(phonenum, lang.lower())
if not options.cityonly:
country = phonenumbers.country_name_for_number(phonenum, lang.lower())
if country and city:
res = country + ' ' + city
elif country and not city:
res = country
elif city:
res = city
return res
def reformat_phone_number_before_query_openerp(number):
'''We match only on the end of the phone number'''
@ -150,30 +174,42 @@ def main(options, arguments):
exit(0)
stdout_write('VERBOSE "CallerID number = %s"\n' % input_cid_number)
query_number = reformat_phone_number_before_query_openerp(input_cid_number)
stderr_write("phone number sent to OpenERP = %s\n" % query_number)
if options.ssl:
stdout_write('VERBOSE "Starting XML-RPC secure request on OpenERP %s:%s"\n' % (options.server, str(options.port)))
protocol = 'https'
else:
stdout_write('VERBOSE "Starting clear XML-RPC request on OpenERP %s:%s"\n' % (options.server, str(options.port)))
protocol = 'http'
sock = xmlrpclib.ServerProxy('%s://%s:%s/xmlrpc/object' % (protocol, options.server, str(options.port)))
res = False
if options.server: # Yes, this script can be used without "-s openerp_server" !
query_number = reformat_phone_number_before_query_openerp(input_cid_number)
stderr_write("phone number sent to OpenERP = %s\n" % query_number)
if options.ssl:
stdout_write('VERBOSE "Starting XML-RPC secure request on OpenERP %s:%s"\n' % (options.server, str(options.port)))
protocol = 'https'
else:
stdout_write('VERBOSE "Starting clear XML-RPC request on OpenERP %s:%s"\n' % (options.server, str(options.port)))
protocol = 'http'
res = sock.execute(options.database, options.user, options.password, 'res.partner.address', 'get_name_from_phone_number', query_number)
# To simulate a long execution of the XML-RPC request
#import time
#time.sleep(5)
sock = xmlrpclib.ServerProxy('%s://%s:%s/xmlrpc/object' % (protocol, options.server, str(options.port)))
stdout_write('VERBOSE "End of XML-RPC request on OpenERP"\n')
try:
res = sock.execute(options.database, options.user, options.password, 'res.partner.address', 'get_name_from_phone_number', query_number)
stdout_write('VERBOSE "End of XML-RPC request on OpenERP"\n')
if not res:
stdout_write('VERBOSE "Phone number not found in OpenERP"\n')
except:
stdout_write('VERBOSE "Could not connect to OpenERP"\n')
res = False
# To simulate a long execution of the XML-RPC request
#import time
#time.sleep(5)
# Function to limit the size of the CID name to 40 chars
if res:
if len(res) > 40:
res = res[0:40]
elif options.geoloc:
# if the number is not found in OpenERP, we try to geolocate
stdout_write('VERBOSE "Trying to geolocate with country %s and lang %s"\n' % (options.country, options.lang))
res = geolocate_phone_number(input_cid_number, options.country, options.lang)
else:
# if the number is not found in OpenERP, we put 'default_cid_name' as CID Name
# if the number is not found in OpenERP and geoloc is off, we put 'default_cid_name' as CID Name
res = default_cid_name
# All SIP phones should support UTF-8... but in case you have analog phones over TDM

11
asterisk_click2dial/scripts/get_cid_name_timeout.sh

@ -14,5 +14,12 @@
# in the "coreutils" package
# The first argument of the "timeout" command is the maximum execution time
# In this example, we chose 1 second
timeout 1s /usr/local/bin/get_cid_name.py -s openerp.mycompany.com -d erp_prod -u 12 -w "mypasswd"
# In this example, we chose 2 seconds. Note that geolocalisation takes about
# 1 second on an small machine ; so if you enable the --geoloc option,
# don't put a 1 sec timeout !
# To test this script manually (i.e. outside of Asterisk), run :
# echo "agi_callerid:0141981242"|get_cid_name_timeout.sh
# where 0141981242 is a phone number that could be presented by the calling party
timeout 2s /usr/local/bin/get_cid_name.py --server openerp.mycompany.com --database erp_prod --user-id 12 --password "thepasswd" --geoloc --geoloc-country "FR" --geoloc-lang "fr"
Loading…
Cancel
Save