|
@@ -14,10 +14,14 @@ import concurrent.futures
|
|
|
from http.server import BaseHTTPRequestHandler
|
|
|
from http.server import HTTPServer
|
|
|
import src.core.callcenter.utils.call_cache_util as CacheUtil
|
|
|
-from src.core.callcenter.constant.constant import AT, CO, SK, saasId
|
|
|
-from src.core.callcenter.constant.esl_constant import SIP_HEADER, SPLIT, SOFIA, ORIGINATE, PARK
|
|
|
+from src.core.callcenter.constant.constant import AT, CO, SK, saasId, EMPTY
|
|
|
+from src.core.callcenter.constant.esl_constant import BRIDGE_VARIABLES, BRIDGE, HANGUP, NORMAL_CLEARING, SIP_HEADER, SPACE, SPLIT, SOFIA, \
|
|
|
+ ORIGINATE, PARK, SET, EAVESDROP, SMF_ALEG, EXECUTE, PLAYBACK, PAUSE, TRANSFER, UUID_TRANSFER, UUID_BROADCAST, UUID_BREAK, UUID_HOLD, \
|
|
|
+ UUID_RECORD, UUID_SETVAR, UUID_GETVAR
|
|
|
import src.core.callcenter.utils.esl_event_util as EslEventUtil
|
|
|
import src.core.callcenter.handler as event_handler
|
|
|
+from src.core.callcenter.constant.sip_header_constant import sipHeaderHoldMusic
|
|
|
+from src.core.callcenter.enumeration import CallCauseEnum
|
|
|
from src.core.callcenter.handler.default_esl_event_handler import DefaultEslEventHandler
|
|
|
|
|
|
|
|
@@ -145,7 +149,7 @@ class InboundClient:
|
|
|
"{return_ring_ready=true,",
|
|
|
f"sip_contact_user={display},",
|
|
|
"ring_asr=true,",
|
|
|
- "absolute_codec_string=codecs,", # Assuming codecs is defined somewhere
|
|
|
+ "absolute_codec_string=^^:PCMU:PCMA,", # Assuming codecs is defined somewhere
|
|
|
f"origination_caller_id_number={display},",
|
|
|
f"origination_caller_id_name={display},",
|
|
|
f"origination_uuid={device_id},",
|
|
@@ -169,70 +173,180 @@ class InboundClient:
|
|
|
|
|
|
def send_args(self, device_id, name, arg):
|
|
|
msg = ESL.ESLevent("sendmsg", device_id)
|
|
|
- msg.addHeader("call-command", "execute")
|
|
|
+ msg.addHeader("call-command", EXECUTE)
|
|
|
msg.addHeader("execute-app-name", name)
|
|
|
msg.addHeader("execute-app-arg", arg)
|
|
|
self.con.sendEvent(msg)
|
|
|
|
|
|
def bridge_call(self, call_id, device_id1, device_id2):
|
|
|
"""桥接电话"""
|
|
|
- pass
|
|
|
+ self.multi_set_var(device_id1, BRIDGE_VARIABLES)
|
|
|
+ self.multi_set_var(device_id2, BRIDGE_VARIABLES)
|
|
|
+ self.con.bgapi(BRIDGE, device_id1 + SPACE + device_id2)
|
|
|
|
|
|
def transfer_call(self, _from, _to):
|
|
|
"""转接"""
|
|
|
- pass
|
|
|
+ builder = [
|
|
|
+ _from,
|
|
|
+ " -both 'set:hangup_after_bridge=false,set:park_after_bridge=true,park:' inline "
|
|
|
+ ]
|
|
|
+ arg = ''.join(builder)
|
|
|
+ self.con.bgapi(TRANSFER, arg)
|
|
|
|
|
|
def answer(self, device_id):
|
|
|
"""应答"""
|
|
|
- pass
|
|
|
+ self.con.bgapi('uuid_phone_event', device_id + ' talk')
|
|
|
|
|
|
- def hangup_call(self, call_id, device_id):
|
|
|
+ def hangup_call(self, call_id, device_id, case_enum=CallCauseEnum.DEFAULT):
|
|
|
"""挂机"""
|
|
|
- pass
|
|
|
-
|
|
|
- def play_file(self, call_id, device_id, file):
|
|
|
- """放音"""
|
|
|
- pass
|
|
|
+ msg = ESL.ESLevent("sendmsg", device_id)
|
|
|
+ msg.addHeader("call-command", EXECUTE)
|
|
|
+ msg.addHeader("execute-app-name", HANGUP)
|
|
|
+ msg.addHeader("execute-app-arg", NORMAL_CLEARING)
|
|
|
+ # log.info("hangupCall挂机 hangup media:{} call: {}, device: {}, ctiCauseEnum:{}", media,callId, deviceId, ctiCauseEnum);
|
|
|
+ self.send_args(device_id, SET, EslEventUtil.SIP_H_P_WDH_HANGUP_CAUSE + "=" + case_enum.description)
|
|
|
+ self.con.sendEvent(msg)
|
|
|
|
|
|
def broadcast(self, uuid, path, smf):
|
|
|
- pass
|
|
|
+ builder = [
|
|
|
+ UUID_BROADCAST,
|
|
|
+ uuid,
|
|
|
+ path,
|
|
|
+ smf
|
|
|
+ ]
|
|
|
+ command = ' '.join(builder)
|
|
|
+ self.con.bgapi(command, EMPTY)
|
|
|
|
|
|
- def break0(self, uuid, all, sync):
|
|
|
- pass
|
|
|
+ def break0(self, uuid, all=False, sync=True):
|
|
|
+ builder = [
|
|
|
+ UUID_BREAK,
|
|
|
+ uuid
|
|
|
+ ]
|
|
|
+ if all:
|
|
|
+ builder.append("all")
|
|
|
+ command = ' '.join(builder)
|
|
|
+ if sync:
|
|
|
+ self.con.api(command, EMPTY)
|
|
|
+ else:
|
|
|
+ self.con.bgapi(command, EMPTY)
|
|
|
|
|
|
def hold(self, smf, uuid, display):
|
|
|
- pass
|
|
|
+ builder = [
|
|
|
+ UUID_HOLD,
|
|
|
+ smf,
|
|
|
+ uuid,
|
|
|
+ display
|
|
|
+ ]
|
|
|
+ if display:
|
|
|
+ builder.append("all")
|
|
|
+ else:
|
|
|
+ builder.append(EMPTY)
|
|
|
+ command = ' '.join(builder)
|
|
|
+ self.con.bgapi(command, EMPTY)
|
|
|
|
|
|
def get_var(self, uuid, var):
|
|
|
- pass
|
|
|
+ builder = [
|
|
|
+ UUID_GETVAR,
|
|
|
+ uuid,
|
|
|
+ var
|
|
|
+ ]
|
|
|
+ command = ' '.join(builder)
|
|
|
+ self.con.bgapi(command, EMPTY)
|
|
|
|
|
|
def set_var(self, uuid, var, val):
|
|
|
- pass
|
|
|
+ builder = [
|
|
|
+ UUID_SETVAR,
|
|
|
+ uuid,
|
|
|
+ var,
|
|
|
+ val
|
|
|
+ ]
|
|
|
+ command = ' '.join(builder)
|
|
|
+ self.con.bgapi(command, EMPTY)
|
|
|
|
|
|
def multi_set_var(self, uuid, params):
|
|
|
- pass
|
|
|
+ builder = [
|
|
|
+ "uuid_setvar_multi " + uuid + " "
|
|
|
+ ]
|
|
|
+ builder1 = []
|
|
|
+ for k, v in params.items():
|
|
|
+ builder1.append(k + "="+v)
|
|
|
+ builder.append(';'.join(builder1))
|
|
|
+ command = ''.join(builder)
|
|
|
+ self.con.bgapi(command, EMPTY)
|
|
|
|
|
|
def record(self, uuid, action, path, limit):
|
|
|
- pass
|
|
|
+ builder = [
|
|
|
+ UUID_TRANSFER,
|
|
|
+ uuid,
|
|
|
+ action,
|
|
|
+ path,
|
|
|
+ str(limit)
|
|
|
+ ]
|
|
|
+ command = ' '.join(builder)
|
|
|
+ self.con.bgapi(command, EMPTY)
|
|
|
|
|
|
def transfer(self, uuid, smf, dest, dialplan, context):
|
|
|
- pass
|
|
|
+ builder = [
|
|
|
+ UUID_TRANSFER,
|
|
|
+ uuid,
|
|
|
+ smf,
|
|
|
+ dest,
|
|
|
+ dialplan,
|
|
|
+ context
|
|
|
+ ]
|
|
|
+ command = ' '.join(builder)
|
|
|
+ self.con.bgapi(command, EMPTY)
|
|
|
|
|
|
def insert(self, device_id):
|
|
|
"""强插"""
|
|
|
- pass
|
|
|
+ builder = [
|
|
|
+ device_id,
|
|
|
+ " -both 'set:hangup_after_bridge=false,set:park_after_bridge=true,park:' inline "
|
|
|
+ ]
|
|
|
+ arg = ''.join(builder)
|
|
|
+ self.con.api(TRANSFER, arg)
|
|
|
|
|
|
def bridge_break(self, device_id):
|
|
|
"""拆线"""
|
|
|
- pass
|
|
|
+ builder = [
|
|
|
+ device_id,
|
|
|
+ " -both 'set:hangup_after_bridge=false,set:park_after_bridge=true,set:" + SIP_HEADER + sipHeaderHoldMusic + "=true,park:' inline "
|
|
|
+ ]
|
|
|
+ arg = ''.join(builder)
|
|
|
+ self.con.api(TRANSFER, arg)
|
|
|
+
|
|
|
+ def play_file(self, call_id, device_id, file, sync):
|
|
|
+ """放音"""
|
|
|
+ if sync:
|
|
|
+ return self.hold_play(device_id, file)
|
|
|
+ else:
|
|
|
+ msg = ESL.ESLevent("sendmsg", device_id)
|
|
|
+ msg.addHeader("call-command", EXECUTE)
|
|
|
+ msg.addHeader("execute-app-name", PLAYBACK)
|
|
|
+ msg.addHeader("execute-app-arg", file)
|
|
|
+ msg.addHeader("async", "true")
|
|
|
+ self.con.sendEvent(msg)
|
|
|
|
|
|
def stop_play(self, device_id):
|
|
|
"""关闭播放音乐"""
|
|
|
- pass
|
|
|
+ builder = [
|
|
|
+ device_id,
|
|
|
+ " on"
|
|
|
+ ]
|
|
|
+ arg = "".join(builder)
|
|
|
+ return self.con.api(PAUSE, arg)
|
|
|
|
|
|
def hold_play(self, device_id, play):
|
|
|
"""向a-leg插播tts音乐(无限播放)"""
|
|
|
- pass
|
|
|
+ builder = [
|
|
|
+ device_id,
|
|
|
+ " playback::",
|
|
|
+ play,
|
|
|
+ " ",
|
|
|
+ SMF_ALEG
|
|
|
+ ]
|
|
|
+ arg = "".join(builder)
|
|
|
+ return self.con.api(UUID_BROADCAST, arg)
|
|
|
|
|
|
def play_timeout(self, call_id, timeout):
|
|
|
"""播放超时主动挂机"""
|
|
@@ -240,7 +354,15 @@ class InboundClient:
|
|
|
|
|
|
def listen(self, device_id1, device_id2, aleg, bleg):
|
|
|
"""监听"""
|
|
|
- pass
|
|
|
+ if aleg:
|
|
|
+ self.send_args(device_id1, SET, "eavesdrop_bridge_aleg=true")
|
|
|
+ if bleg:
|
|
|
+ self.send_args(device_id1, SET, "eavesdrop_bridge_bleg=true")
|
|
|
+ self.send_args(device_id1, EAVESDROP, device_id2)
|
|
|
+
|
|
|
+ def show_channel(self, device_id):
|
|
|
+ msg = self.con.api("show", " channels like " + device_id + " as json")
|
|
|
+ print('show_channel::', msg)
|
|
|
|
|
|
def expression(self, template, params):
|
|
|
for key, value in params.items():
|