You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
7.7 KiB
202 lines
7.7 KiB
#! /usr/bin/python
|
|
# -*- encoding: utf-8 -*-
|
|
# (c) 2010-2015 Alexis de Lattre <alexis.delattre@akretion.com>
|
|
# (c) 2016 credativ Ltd (<http://credativ.co.uk>).
|
|
# (c) 2016 Trever L. Adams
|
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
|
# flake8: noqa: E501
|
|
|
|
"""
|
|
Log a call and recording within Asterisk
|
|
|
|
This is intended to be called by a hangup handler:
|
|
|
|
Please, note the start is seconds since EPOCH in UTC, it must be UTC.
|
|
|
|
Example:
|
|
[from-pstn-custom]
|
|
...
|
|
exten => _X!,n,Set(CHANNEL(hangup_handler_push)=from-pstn-hdlr,s,1(args))
|
|
|
|
[from-pstn-hdlr]
|
|
exten => s,1,Verbose(0, from-pstn-hdlr called)
|
|
same => n,Set(odoo_type=incoming)
|
|
same => n,Set(odoo_src=${CDR(src)})
|
|
same => n,Set(odoo_dst=${CDR(dst)})
|
|
same => n,Set(odoo_duration=${CDR(duration)})
|
|
same => n,Set(odoo_start=${CDR(start)})
|
|
same => n,Set(odoo_filename=${CDR(recordingfile)})
|
|
same => n,Set(odoo_uniqueid=${UNIQUEID})
|
|
same => n,AGI(/usr/local/bin/asterisk_logcall.sh,${odoo_type},${odoo_src},${odoo_dst},${odoo_duration},${odoo_start},${odoo_filename},${odoo_uniqueid})
|
|
same => n,Return()
|
|
|
|
To test from the CLI:
|
|
./asterisk_logcall.sh << EOF
|
|
agi_arg_1: outgoing
|
|
agi_arg_2: 875
|
|
agi_arg_3: 01234567890
|
|
agi_arg_4: 345
|
|
agi_arg_5: 1234567890
|
|
agi_arg_6: out-875-unknown-20160216-154438-1455637478.61.wav
|
|
agi_arg_7: 1455637478.61
|
|
agi_arg_8: Description may include things like hangup cause, transfer, automated notes
|
|
EOF
|
|
|
|
"""
|
|
|
|
__author__ = """Craig Gowing <craig.gowing@credativ.co.uk> &
|
|
Alexis de Lattre <alexis.delattre@akretion.com>"""
|
|
__date__ = "February 2016"
|
|
__version__ = "0.2"
|
|
|
|
import xmlrpclib
|
|
import sys
|
|
from optparse import OptionParser
|
|
|
|
# Define command line options
|
|
options = [
|
|
{'names': ('-s', '--server'), 'dest': 'server', 'type': 'string',
|
|
'action': 'store', 'default': False,
|
|
'help': 'DNS or IP address of the OpenERP server. Default = none '
|
|
'(will not try to connect to OpenERP)'},
|
|
{'names': ('-p', '--port'), 'dest': 'port', 'type': 'int',
|
|
'action': 'store', 'default': 8069,
|
|
'help': "Port of OpenERP's XML-RPC interface. Default = 8069"},
|
|
{'names': ('-e', '--ssl'), 'dest': 'ssl',
|
|
'help': "Use SSL connections instead of clear connections. "
|
|
"Default = no, use clear XML-RPC or JSON-RPC",
|
|
'action': 'store_true', 'default': False},
|
|
{'names': ('-j', '--jsonrpc'), 'dest': 'jsonrpc',
|
|
'help': "Use JSON-RPC instead of the default protocol XML-RPC. "
|
|
"Default = no, use XML-RPC",
|
|
'action': 'store_true', 'default': False},
|
|
{'names': ('-d', '--database'), 'dest': 'database', 'type': 'string',
|
|
'action': 'store', 'default': 'openerp',
|
|
'help': "OpenERP database name. Default = 'openerp'"},
|
|
{'names': ('-u', '--user-id'), 'dest': 'userid', 'type': 'int',
|
|
'action': 'store', 'default': 2,
|
|
'help': "OpenERP user ID to use when connecting to OpenERP in "
|
|
"XML-RPC. Default = 2"},
|
|
{'names': ('-t', '--username'), 'dest': 'username', 'type': 'string',
|
|
'action': 'store', 'default': 'demo',
|
|
'help': "OpenERP username to use when connecting to OpenERP in "
|
|
"JSON-RPC. Default = demo"},
|
|
{'names': ('-w', '--password'), 'dest': 'password', 'type': 'string',
|
|
'action': 'store', 'default': 'demo',
|
|
'help': "Password of the OpenERP user. Default = 'demo'"},
|
|
]
|
|
|
|
|
|
def stdout_write(string):
|
|
'''Wrapper on sys.stdout.write'''
|
|
sys.stdout.write(string.encode(sys.stdout.encoding or 'utf-8', 'replace'))
|
|
sys.stdout.flush()
|
|
# When we output a command, we get an answer "200 result=1" on stdin
|
|
# Purge stdin to avoid these Asterisk error messages :
|
|
# utils.c ast_carefulwrite: write() returned error: Broken pipe
|
|
sys.stdin.readline()
|
|
return True
|
|
|
|
|
|
def stderr_write(string):
|
|
'''Wrapper on sys.stderr.write'''
|
|
sys.stderr.write(string.encode(sys.stdout.encoding or 'utf-8', 'replace'))
|
|
sys.stdout.flush()
|
|
return True
|
|
|
|
|
|
def main(options, arguments):
|
|
|
|
# AGI passes parameters to the script on standard input
|
|
stdinput = {}
|
|
while 1:
|
|
input_line = sys.stdin.readline()
|
|
if not input_line:
|
|
break
|
|
line = input_line.strip()
|
|
try:
|
|
variable, value = line.split(':', 1)
|
|
except:
|
|
break
|
|
if variable[:4] != 'agi_': # All AGI parameters start with 'agi_'
|
|
stderr_write("bad stdin variable : %s\n" % variable)
|
|
continue
|
|
variable = variable.strip()
|
|
value = value.strip()
|
|
if variable and value:
|
|
stdinput[variable] = value
|
|
stderr_write("full AGI environnement :\n")
|
|
|
|
for variable in stdinput.keys():
|
|
stderr_write("%s = %s\n" % (variable, stdinput.get(variable)))
|
|
|
|
odoo_type = stdinput.get('agi_arg_1', '')
|
|
odoo_src = stdinput.get('agi_arg_2', '')
|
|
odoo_dst = stdinput.get('agi_arg_3', '')
|
|
odoo_duration = stdinput.get('agi_arg_4', '')
|
|
odoo_start = stdinput.get('agi_arg_5', '')
|
|
odoo_filename = stdinput.get('agi_arg_6', '')
|
|
odoo_uniqueid = stdinput.get('agi_arg_7', '')
|
|
odoo_description = stdinput.get('agi_arg_8', '')
|
|
|
|
method = 'log_call_and_recording'
|
|
|
|
res = False
|
|
# Yes, this script can be used without "-s openerp_server" !
|
|
if options.server and options.jsonrpc:
|
|
import odoorpc
|
|
proto = options.ssl and 'jsonrpc+ssl' or 'jsonrpc'
|
|
stdout_write(
|
|
'VERBOSE "Starting %s request on OpenERP %s:%d database '
|
|
'%s username %s"\n' % (
|
|
proto.upper(), options.server, options.port, options.database,
|
|
options.username))
|
|
try:
|
|
odoo = odoorpc.ODOO(options.server, proto, options.port)
|
|
odoo.login(options.database, options.username, options.password)
|
|
res = odoo.execute(
|
|
'phone.common', 'log_call_and_recording', odoo_type, odoo_src,
|
|
odoo_dst, odoo_duration, odoo_start, odoo_filename,
|
|
odoo_uniqueid, odoo_description)
|
|
stdout_write('VERBOSE "Called method %s, returned %s"\n' %
|
|
(method, res))
|
|
except:
|
|
stdout_write(
|
|
'VERBOSE "Could not connect to OpenERP in JSON-RPC"\n')
|
|
elif options.server:
|
|
proto = options.ssl and 'https' or 'http'
|
|
stdout_write(
|
|
'VERBOSE "Starting %s XML-RPC request on OpenERP %s:%d '
|
|
'database %s user ID %d"\n' % (
|
|
proto, options.server, options.port, options.database,
|
|
options.userid))
|
|
sock = xmlrpclib.ServerProxy(
|
|
'%s://%s:%d/xmlrpc/object'
|
|
% (proto, options.server, options.port))
|
|
try:
|
|
res = sock.execute(
|
|
options.database, options.userid, options.password,
|
|
'phone.common', 'log_call_and_recording', odoo_type, odoo_src,
|
|
odoo_dst, odoo_duration, odoo_start, odoo_filename,
|
|
odoo_uniqueid, odoo_description)
|
|
stdout_write('VERBOSE "Called method %s, returned %s"\n' %
|
|
(method, res))
|
|
except:
|
|
stdout_write('VERBOSE "Could not connect to OpenERP in XML-RPC"\n')
|
|
|
|
return True
|
|
|
|
|
|
if __name__ == '__main__':
|
|
usage = "Usage: asterisk_logcall.py [options] login1 login2 login3 ..."
|
|
epilog = "Script written by Craig Gowing based on work by Alexis de "
|
|
"Lattre. Published under the GNU AGPL licence."
|
|
description = "This is an AGI script that sends a query to OpenERP. "
|
|
parser = OptionParser(usage=usage, epilog=epilog, description=description)
|
|
for option in options:
|
|
param = option['names']
|
|
del option['names']
|
|
parser.add_option(*param, **option)
|
|
options, arguments = parser.parse_args()
|
|
sys.argv[:] = arguments
|
|
main(options, arguments)
|