Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (function(scope, document, $) {
- 'use strict';
- // Constantes
- var MAX_RETRIES = 5;
- var $cometd = scope.$cometd || $.cometd,
- _handlers = {},
- _state = {
- endpoint: '',
- restService: '',
- cometdService: '',
- connected: false,
- wasConnected: true,
- allowManualHandshake: true,
- retries: 0,
- auth: {
- extension: '',
- siteid: '',
- linkType: '',
- password: '',
- username: '',
- teamid: null
- /*campaignid: null*/
- /*reason: null*/
- }
- },
- ACCESS_TOKEN = '',
- EXPIRES_IN = ''
- /**
- * Funciones públicas del módulo
- */
- /**
- * Inicializa la conexión a CometD
- **
- * @author jmartinezpisson
- * @date 24/09/2017
- */
- function init(settings) {
- console.log('Initializing CometD client');
- // 1 - Inicializamos y registramos los handlers
- settings = settings || {};
- settings.events = settings.events || {};
- _state.endpoint = settings.endpoint.base || '';
- _state.restService = settings.endpoint.restService || '';
- _state.cometdService = settings.endpoint.cometdService || '';
- _state.auth.extension = settings.extension || '';
- _state.auth.siteid = settings.siteId || '';
- _state.auth.linkType = settings.linkType || '';
- _state.auth.username = settings.username || '';
- _state.auth.password = settings.password || '';
- // Función de obtención de credenciales OAuth
- if(typeof(settings.getOAuthCredentials) === 'function') {
- getOAuthCredentials = settings.getOAuthCredentials;
- }
- for (var event in settings.events) {
- if (settings.events.hasOwnProperty(event)) {
- addHook(event, settings.events[event]);
- }
- }
- // 2 - Se revisa que los eventos del sistema tienen handler asociado y se lanza un error en caso contrario
- if (!_handlers.onConnectionEstablished || !_handlers.onConnectionRetry ||
- !_handlers.onConnectionBroken || !_handlers.onConnectionClosed ||
- !_handlers.onHandshakeSuccess || !_handlers.onHandshakeError ||
- !_handlers.onDisconnection || !_handlers.onRetryError) {
- throw new Error('Fatal Error. No callback registered for softphone system events. Please check the initialization config.');
- }
- // 3 - Se añaden los listeners a los canales de CometD:
- $cometd.addListener("/meta/handshake", _metaHandshake);
- $cometd.addListener("/meta/connect", _metaConnect);
- $cometd.addListener('/meta/disconnect', _metaDisconnect);
- // 4 - Se añade gestión de excepciones
- $cometd.onListenerException = function(exception, subscriptionHandle, isListener, message) {
- console.log(exception);
- console.log(message);
- };
- console.log('CometD client reporting for duty!');
- // 5 - Get Access Token
- // getToken();
- }
- /**
- * Registra un hook para ejecutar un callback ante un evento de BIG/CometD
- **
- * @author jmartinezpisson
- * @date 24/09/2017
- */
- function addHook(event, handler) {
- _handlers[event] = handler;
- _handlers[event.charAt(0).toUpperCase() + event.slice(1)] = handler;
- }
- /**
- * Elimina un hook para un evento determinado
- **
- * @author jmartinezpisson
- * @date 24/09/2017
- */
- function removeHook(event, handler) {
- var capitalizedEvent = event.charAt(0).toUpperCase() + event.slice(1);
- if (_handlers[event]) {
- delete _handlers[event];
- }
- if (_handlers[capitalizedEvent]) {
- delete _handlers[capitalizedEvent];
- }
- }
- /**
- * Inicializa la comunicación CometD
- **
- * @author jmartinezpisson
- * @date 28/09/2017
- */
- function start(settings) {
- if (settings) {
- _state.auth.extension = (settings.extension || settings.extension === '')? settings.extension:_state.auth.extension;
- _state.auth.username = (settings.username || settings.username === '')? settings.username:_state.auth.username;
- _state.auth.password = (settings.password || settings.password === '')? settings.password:_state.auth.password;
- _state.auth.siteid = settings.siteId || _state.auth.siteid;
- _state.auth.linkType = settings.linkType || _state.auth.linkType;
- _state.auth.teamid = settings.teamId || _state.auth.teamid;
- //_state.auth.campaignid = settings.campaignid || _state.auth.campaignid; // Comentado con miedo por axel
- _state.allowManualHandshake = settings.isRestart? !settings.isRestart:true;
- }
- $cometd.configure({
- url: _state.cometdService
- });
- var additional = {
- extension: _state.auth.extension,
- apptype: 'desktop',
- siteid: _state.auth.siteid,
- linktype: _state.auth.linkType,
- agentname: _state.auth.username
- };
- getToken().then(function() {
- console.log('Resolve on getToken');
- $cometd.handshake(additional);
- }).catch(function(error) {
- console.log('Reject on getToken: ' + error);
- _handlers.onHandshakeError(_state.allowManualHandshake, settings.isRestart);
- });
- }
- /**
- * Actualiza los parametros internos de las peticiones
- */
- function updateAuth(settings) {
- if (settings) {
- _state.auth = Object.assign(_state.auth, settings);
- }
- }
- /**
- * Detiene la comunicación CometD
- **
- * @author jmartinezpisson
- * @date 28/09/2017
- */
- function stop() {
- $cometd.disconnect(function() {
- _state.allowManualHandshake = true;
- _handlers.onDisconnection();
- });
- }
- /**
- * Funciones privadas del módulo
- */
- /**
- * Util Functions
- */
- function _logCometd(channel, message) {
- console.log(' >> ' + channel + 'Subscribe </br>');
- console.log(' >> Evento: ' + message.data.name + '</br>');
- if (message.data.name === "OnAgentStateChanged") {
- console.log('· Estado Agente[' + message.data.username + ']: ' + message.data.status + ' - ReasonCode: ' + message.data.reason + '</br>');
- } else {
- _createLog(message.data);
- }
- }
- function _createLog(data) {
- var props = [];
- var knownProps = {
- name: '<span style="background-color: #FFEB3B; color: #00BCD4;"> >>> New Event[' + new Date().toJSON() + ']: ' + data.name + '</span>',
- extension: ' - Extension: ' + data.extension,
- provider: '- Provider: ' + data.provider,
- username: '- Username: ' + data.username
- };
- for (var prop in data) {
- if (data.hasOwnProperty(prop) && !knownProps.hasOwnProperty(prop)) {
- props.push(' - ' + prop.charAt(0).toUpperCase() + prop.slice(1) + ': ' + data[prop]);
- }
- }
- console.log('<div>' +
- knownProps.name +
- '<br>' + knownProps.extension +
- '<br>' + knownProps.provider +
- '<br>' + knownProps.username +
- '<br>' + props.join('<br>') +
- '</div>'
- );
- }
- function _keysToCamelCase(target) {
- var stringToCamelCase = function(s) {
- return s.replace(/-([a-z])/g, function(g) {
- return g[1].toUpperCase();
- });
- }
- var i = 0;
- for (var key in target) {
- if (typeof target[key] !== 'undefined') {
- if (typeof target[key] === 'object' && !(target[key] instanceof Array)) {
- _keysToCamelCase(target[key]);
- }
- if (target[key] instanceof Array) {
- for (var i = 0; i < target[key].length; i++) {
- _keysToCamelCase(target[key][i]);
- }
- }
- if (~key.indexOf('_') || ~key.indexOf('-')) {
- var oldKey = key;
- key = key.replace(/_/g, '-');
- key = stringToCamelCase(key);
- target[key] = target[oldKey];
- delete target[oldKey];
- }
- }
- i = ++i;
- }
- return target;
- }
- /**
- * CometD - Hard Reset. Fuerza la desconexión y un nuevo handshake.
- **
- * @author jmartinezpisson
- * @date 24/09/2017
- */
- function _hardReset(handshake) {
- $cometd.disconnect(function() {
- start();
- });
- }
- /**
- * CometD - Handshake handler. Gestiona el handshake de CometD
- **
- * @author jmartinezpisson
- * @date 24/09/2017
- */
- function _metaHandshake(handshake) {
- var isManualHandshake = _state.allowManualHandshake;
- console.log('Handshake: ' + handshake.successful);
- console.log(handshake);
- // 1 - Gestión del success
- if (handshake.successful) {
- if ($cometd.getAdvice() && $cometd.getAdvice().reconnect === 'handshake') {
- console.log('CometD: Received advice: handshake during a succesful handshake. Resetting...');
- return start();
- }
- console.log('CometD: successful handshake');
- // 1.1 - Se ejecuta un callback para la gestión de un handshake exitoso, identificando si el handshake ha sido manual y bloqueando la ejecución de futuros
- _state.allowManualHandshake = false;
- _handlers.onHandshakeSuccess(isManualHandshake);
- // 1.2 - En algunas centralitas se realiza una gestión posterior del token para realizar la monitorización
- if (_handlers.onHandshakeTokenReceived) {
- // Datos que necesitamos de BIG (Token de acceso que necesitamos para la monitorizacion)
- if (handshake.ext && handshake.ext.token) {
- _handlers.onHandshakeTokenReceived(handshake.ext.token, isManualHandshake);
- } else {
- // No se ha recibido correctamente el Token; si no, es un error en el handshake
- if (handshake.ext) {
- _handlers.onHandshakeError(isManualHandshake);
- } else {
- alert('Error, el handshake no ha sido correcto');
- }
- }
- }
- // 1.3 - Se (re)suscribe a los eventos de BIG
- _suscribeChannels(handshake);
- } else { // 2 - Gestión de errores en callbacks
- // 2.1 - Se lanza el callback de gestión de errores en handshake
- _handlers.onHandshakeError(isManualHandshake);
- // 2.2 - Si el handshake es manual y falla no se reintenta la conexión.
- console.log($cometd.isDisconnected());
- if (_state.allowManualHandshake) {
- return $cometd.disconnect();
- }
- // 2.3 - Se evita un reintento en fallos graves de conexión
- if ((handshake.error && handshake.error.indexOf("403") === 0) || (handshake.failure && handshake.failure.reason.indexOf("Extra Connection") === 0)) {
- _state.tryReconnecting = false;
- }
- }
- }
- /**
- * CometD - Handshake handling. Función auxiliar para escuchar los canales y eventos de BIG
- **
- * @author jmartinezpisson
- * @date 24/09/2017
- */
- function _suscribeChannels(handshake) {
- var bigChannelSubscribe = '/cti/' + _state.extension + '/*';
- if (handshake.ext && handshake.ext.bigchannel) {
- bigChannelSubscribe = handshake.ext.bigchannel;
- }
- $cometd.batch(function() {
- $cometd.subscribe(bigChannelSubscribe, function(message) {
- _logCometd('BigChannelSubscribe', message);
- if (_handlers[message.data.name]) {
- _handlers[message.data.name](message.data);
- } else {
- console.log('No CometD Handler Registered for ' + message.data.name);
- }
- });
- });
- }
- /**
- * Gestiona el estado de la conexión al servidor Bayeux
- **
- * @author jmartinezpisson
- * @date 24/09/2017
- * @change 04/10/2017 jmartienzpisson Cambiada la gestión de reintentos para hacerla más robusta
- */
- function _metaConnect(message) {
- console.log('>> MetaConnect - ID: ' + message.id + ' – Date: ' + new Date().toJSON());
- // 1 - Si CometD, se encuentra desconectado, se obvia el LongPolling. Para gestionar una desconexión completa, se usa el canal metadisconnect
- if ($cometd.isDisconnected()) {
- console.log('CometD: Metaconnect - Desconexión CometD');
- return;
- }
- // 2 - Se almacena el estado anterior de conexión y se verifica si la conexión es correcta
- _state.wasConnected = _state.connected;
- _state.connected = (message.successful === true);
- // 3 -Se actua en caso de (re)conexión, desconexión parcial (gestionada automáticamente por CometD)
- // y reintentos fallidos
- // 3.1 - Si se ha producido una conexión
- if (!_state.wasConnected && _state.connected) {
- console.log('CometD: Metaconnect - Conexión establecida');
- console.log(message);
- _handlers.onConnectionEstablished(_state.retries);
- _state.retries = 0;
- // 3.2 - Si se ha producido una desconexión
- } else if (_state.wasConnected && !_state.connected) {
- console.log('CometD: Metaconnect - Conexión rota');
- console.log(message);
- _handlers.onConnectionBroken();
- // 3.3 - Si se ha producido un reintento
- } else if (!_state.wasConnected && !_state.connected) {
- console.log('CometD: Metaconnect - Intento de reconexión erróneo');
- console.log(message);
- _state.retries++;
- if (_state.retries > MAX_RETRIES) {
- _handlers.onConnectionRetry(_state.retries);
- } else {
- _handlers.onRetryError();
- scope.setTimeout(function() {
- stop();
- }, 2000);
- }
- }
- }
- function _metaDisconnect(message) {
- console.log('Disconnection');
- console.log(message);
- // Independientemente de si la desconexión se produce en servidor, la libería CometD borra su estado interno, por lo que se considera una desconexión
- _state.connected = false;
- _state.wasConnected = false;
- _state.retries = 0;
- _handlers.onConnectionClosed();
- }
- /**
- * BIG REST
- **/
- <!--[if gte IE 9]><!-->
- $.ajaxSetup({
- cache: false
- });
- <!--<![endif]-->
- //Funciones de OAuth2
- function getToken() {
- return new Promise(function(resolve, reject) {
- console.log(' #### getToken Request #### ');
- getOAuthCredentials().then(function(oAuthCredentials) {
- var credentials = Object.assign({
- grant_type: 'password'
- }, oAuthCredentials);
- $.ajax({
- url: _state.endpoint + "/api/token",
- type: "POST",
- dataType: "json",
- data: credentials,
- success: function(json) {
- ACCESS_TOKEN = json.access_token;
- EXPIRES_IN = json.expires_in;
- console.log('Token received: ' + ACCESS_TOKEN + ' - Expires in ' + EXPIRES_IN + ' seconds');
- window.setTimeout(function() {
- refreshToken();
- }, EXPIRES_IN * 1000);
- resolve();
- },
- error: function(error) {
- console.log(error);
- reject(error)
- //tokenError('Error retreiving the token');
- },
- });
- })
- });
- }
- function refreshToken() {
- console.log(' #### refreshToken Request #### ');
- console.log('Parameters: ' + _state.endpoint + _state.restService);
- if (ACCESS_TOKEN) {
- $.ajax({
- url: _state.endpoint + _state.restService + "/api/token",
- type: "POST",
- dataType: "json",
- headers: {
- 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
- 'Pragma': 'no-cache'
- },
- data: {
- grant_type: "refresh_token",
- refresh_token: ACCESS_TOKEN,
- client_secret: "oauth2clientsecret",
- client_id: "oauth2test"
- },
- success: function(json) {
- ACCESS_TOKEN = json.access_token;
- EXPIRES_IN = json.expires_in;
- window.setTimeout(function() {
- refreshToken();
- }, EXPIRES_IN * 1000);
- },
- error: function() {
- console.log('Error with token request');
- },
- })
- }
- }
- //Funcion que devuelve una promesa con las credenciales del oAuth
- function getOAuthCredentials() {
- return new Promise(function(resolve, reject) {
- //Se simula que se obtienen las credenciales.
- //Esto HAY QUE MODIFICARLO PARA OBTENERLAS DE FUERA?
- var obj = {
- username: '',
- password: '',
- client_secret: '',
- client_id: ''
- }
- resolve(obj);
- });
- }
- function debug(name, args) {
- var debug = '';
- for (var key in args) {
- debug += key + ': ' + args[key] + '<br />';
- }
- console.log('#### ' + name + ' Request #### ' + new Date().toJSON());
- console.log('Parameters:<br/>' + debug);
- }
- // Name. def.name
- // ReturnValue: def.returnValueAttribute
- // Error: def.errorAttribute
- // useCredentials: true/false
- // useAccessToken: true/false
- function promisify(def) {
- return function(args, keepHyphens) {
- // 0 - Tratamiento parámetros
- args = args || {};
- if (def.useCredentials !== false) {
- args = Object.assign(args, _state.auth);
- }
- if (def.useAccessToken !== false) {
- args.access_token = ACCESS_TOKEN;
- }
- // 1 - Debug
- debug(def.name, args);
- // 2 - Llamada
- return new Promise(function(resolve, reject) {
- $.ajax({
- url: _state.restService + '/' + def.name,
- type: 'GET',
- async: false,
- contentType: "application/json",
- dataType: 'jsonp',
- headers: {
- 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
- 'Pragma': 'no-cache'
- },
- data: formatParams(args),
- error: function(xhr, status, error) {
- console.log(def.name);
- console.log('URL Disconnect - Reconnection. - Error: ' + error);
- reject(error);
- },
- success: function(json) {
- console.log(def.name);
- if (json.response === 'OK') {
- console.log('Response: Success');
- if (!keepHyphens) {
- json = _keysToCamelCase(json);
- }
- if (typeof(def.returnValue) === 'function') {
- resolve(def.returnValue(json));
- } else {
- resolve(def.returnValue ?
- json[def.returnValue] :
- true
- );
- }
- } else {
- console.log('Response: Failure - ' + (def.errorAttribute ? json[def.errorAttribute] : json.failureDescription));
- reject(def.errorAttribute ?
- json[def.errorAttribute] :
- (json.failureDescription? json.failureDescription: json.failuredescription)
- );
- }
- },
- });
- });
- }
- }
- function formatParams(args) {
- var params = [];
- for (var key in args) {
- if (args[key] || args[key] === '') {
- params.push(key + '=' + args[key]);
- }
- }
- return params.join('&');
- }
- var restDefinitions = {
- login: promisify({
- name: 'login',
- useCredentials: true,
- useAccessToken: true,
- returnValue: function (response) {
- return response;
- }
- }),
- logout: promisify({
- name: 'logout',
- useCredentials: true,
- useAccessToken: true
- }),
- extension: promisify({
- name: 'extension',
- useCredentials: true,
- useAccessToken: true
- }),
- getStatusCalls: promisify({
- name: 'getstatuscalls',
- useCredentials: true,
- useAccessToken: true,
- returnValue: function(response) {
- return {
- extension: _state.auth.extension,
- calls: response.calls
- }
- }
- }),
- getState: promisify({
- name: 'getstate',
- useCredentials: true,
- useAccessToken: true,
- returnValue: function(response) {
- return {
- state: response.state,
- workMode: response.workmode,
- reason: response.reason,
- pendingState: response.pendingstate,
- pendingReason: response.pendingreason
- };
- }
- }),
- getSessionInfo: promisify({
- name: 'getsessioninfo',
- useCredentials: true,
- useAccessToken: true,
- returnValue: function(response) {
- return {
- services: {
- campaigns: response.sessionInfoList.serviceInfoList
- },
- session: {
- agentName: response.sessionInfoList.agentName
- }
- }
- }
- }),
- setReady: promisify({
- name: 'setready',
- useCredentials: true,
- useAccessToken: true
- }),
- setNotReady: promisify({
- name: 'setnotready',
- useCredentials: true,
- useAccessToken: true
- }),
- makeCall: promisify({
- name: 'makecall',
- useCredentials: true,
- useAccessToken: true,
- returnValue: function (response) {
- if(response.hasOwnProperty('sessionid')){
- return response.sessionid;
- }
- else{
- return response.cid;
- }
- }
- }),
- consultationCall: promisify({
- name: 'consultation',
- useCredentials: true,
- useAccessToken: true,
- returnValue: 'cid'
- }),
- blindTransferCall: promisify({
- name: 'blindtransfer',
- useCredentials: true,
- useAccessToken: true,
- returnValue: 'cid'
- }),
- transferCall: promisify({
- name: 'transfer',
- useCredentials: true,
- useAccessToken: true,
- returnValue: 'cid'
- }),
- answerCall: promisify({
- name: 'answer',
- useCredentials: true,
- useAccessToken: true
- }),
- clearCall: promisify({
- name: 'clearcall',
- useCredentials: true,
- useAccessToken: true
- }),
- clearAllCalls: promisify({
- name: 'clearallcalls',
- useCredentials: true,
- useAccessToken: true
- }),
- retrieveCall: promisify({
- name: 'retrieve',
- useCredentials: true,
- useAccessToken: true
- }),
- holdCall: promisify({
- name: 'hold',
- useCredentials: true,
- useAccessToken: true
- }),
- sendDtmf: promisify({
- name: 'senddtmf',
- useCredentials: true,
- useAccessToken: true
- }),
- // Presence/Altitude
- site: promisify({
- name: 'site',
- useCredentials: true,
- useAccessToken: true
- }),
- getStatus: promisify({
- name: 'getstatus',
- useCredentials: true,
- useAccessToken: true,
- returnValue: function (response) {
- return {
- campaigns: response.campaigns,
- status: response.status,
- sessions: response.sessions
- };
- }
- }),
- getQCode: promisify({
- name: 'getqcode',
- useCredentials: true,
- useAccessToken: true,
- returnValue: 'listqcode'
- }),
- setQCode: promisify({
- name: 'setqcode',
- useCredentials: true,
- useAccessToken: true
- }),
- startSession: promisify({
- name: 'startsession',
- useCredentials: true,
- useAccessToken: true
- }),
- stopSession: promisify({
- name: 'stopsession',
- useCredentials: true,
- useAccessToken: true
- }),
- getLogoutReasons: promisify({
- name: 'getLogoutCode',
- useCredentials: true,
- useAccessToken: true,
- returnValue: 'reasons'
- }),
- closeContact: promisify({
- name: 'closecontact',
- useCredentials: true,
- useAccessToken: true
- }),
- reschedule: promisify({
- name: 'reschedule',
- useCredentials: true,
- useAccessToken: true
- }),
- rescheduleContact: promisify({
- name: 'reschedulecall',
- useCredentials: true,
- useAccessToken: true
- }),
- getNotReadyCode: promisify({
- name: 'getNotReadyCode',
- useCredentials: true,
- useAccessToken: true
- }),
- makeContactCall: promisify({
- name: 'makecontactcall',
- useCredentials: true,
- useAccessToken: true
- }),
- requestOutboundACDCall: promisify({
- name: 'requestoutboundacdcall',
- useCredentials: true,
- useAccessToken: true
- }),
- campaignOpen: promisify({
- name: 'campaignopen',
- useCredentials: true,
- useAccessToken: true
- }),
- campaignClose: promisify({
- name: 'campaignclose',
- useCredentials: true,
- useAccessToken: true
- }),
- campaignSignOn: promisify({
- name: 'campaignsignon',
- useCredentials: true,
- useAccessToken: true
- }),
- campaignSignOff: promisify({
- name: 'campaignsignoff',
- useCredentials: true,
- useAccessToken: true
- }),
- campaignReady: promisify({
- name: 'campaignready',
- useCredentials: true,
- useAccessToken: true
- }),
- campaignNotReady: promisify({
- name: 'campaignnotready',
- useCredentials: true,
- useAccessToken: true
- }),
- // Finesse
- getReasonsCodes: promisify({
- name: 'getreasonscodes',
- useCredentials: true,
- useAccessToken: true,
- returnValue: 'codes'
- }),
- getWrapupReasons: promisify({
- name: 'getwrapupreasons',
- useCredentials: true,
- useAccessToken: true,
- returnValue: 'reasons'
- }),
- setWrapup: promisify({
- name: 'setwrapup',
- useCredentials: true,
- useAccessToken: true,
- returnValue: 'cid'
- }),
- getNotReadyReasons: promisify({
- name: 'getNotReadyCode',
- useCredentials: true,
- useAccessToken: true,
- returnValue: 'reasons'
- }),
- getRecordingSessionId: promisify({
- name: 'getrecordingsessionid',
- useCredentials: true,
- useAccessToken: true,
- returnValue: 'sessionid'
- })
- };
- // Se expone las funciones públicas del módulo
- scope.thc = scope.thc || {};
- scope.thc.big = {
- init: init,
- start: start,
- update: updateAuth,
- stop: stop,
- addHook: addHook,
- removeHook: removeHook,
- rest: restDefinitions
- };
- })(window, document, window.jQuery);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement