node-agent-sdk
Version:
Liveperson Agent Messaging SDK for NodeJS
144 lines (120 loc) • 3.58 kB
JavaScript
'use strict';
/**
* domain : domain,
* token: token,
* apiVersion: 1/2
* @param config
* @constructor
*/
const WebSocket = require('ws');
const Events = require('events');
const SDKError = require('./error/SDKError');
const { SERVICES } = require('./Const');
const INTEGRATION_ID = 'na-sdk-js';
const INTEGRATION_VERSION = require('../package.json').version;
const defaults = {
apiVersion: 2.1,
appId: 'unknown'
};
const WS_EVENTS = {
OPEN: 'open',
CLOSE: 'close',
ERROR: 'error',
MESSAGE: 'message'
};
class Transport extends Events {
constructor(config) {
super();
this.pingInterval = 60000;
this.configuration = Object.assign({}, defaults, config);
this._connect();
}
_generateWebsocketUrl(data) {
const domain = data.domain;
const accountId = data.accountId;
const token = data.token;
const apiVersion = data.apiVersion;
const appId = data.appId;
return `wss://${domain}/ws_api/account/${accountId}/messaging/brand/${token}?v=${apiVersion}&intid=${INTEGRATION_ID}&intvn=${INTEGRATION_VERSION}&appId=${appId}`;
}
_connect() {
const url = this._generateWebsocketUrl(this.configuration);
this.ws = new WebSocket(
url,
this.configuration
);
this._bindWsEvents();
}
_bindWsEvents() {
this.ws.on(WS_EVENTS.OPEN, this._onOpen.bind(this));
this.ws.on(WS_EVENTS.CLOSE, this._onClose.bind(this));
this.ws.on(WS_EVENTS.ERROR, this._onError.bind(this));
this.ws.on(WS_EVENTS.MESSAGE, this._onMessage.bind(this));
}
_unbindWsEvents() {
this.ws.removeListener(WS_EVENTS.OPEN, this._onOpen);
this.ws.removeListener(WS_EVENTS.CLOSE, this._onClose);
this.ws.removeListener(WS_EVENTS.ERROR, this._onError);
this.ws.removeListener(WS_EVENTS.MESSAGE, this._onMessage);
}
_onOpen() {
this.emit('open');
this.ping();
}
_onClose(code, reason) {
this.emit('close', code, reason);
clearTimeout(this.timoutId);
}
_extractCode(err) {
if (err.message && err.message.includes('401')) {
return 401;
}
return null;
}
_onError(err) {
const code = this._extractCode(err);
const error = new SDKError(`Error on WS connection: ${err.message}`, code, SERVICES.MESSAGING, err);
this.emit('error', error);
clearTimeout(this.timoutId);
}
_onMessage(data, flags) {
let parsed;
try {
parsed = JSON.parse(data);
} catch (ex) {
// continue regardless of error
}
this.emit('message', parsed || data, flags);
}
ping() {
try {
this.ws.ping();
this.timoutId = setTimeout(() => {
this.ping();
}, this.pingInterval);
}
catch (err) {
const error = new SDKError(`Error on WS ping: ${err.message}`, null, SERVICES.MESSAGING, err);
this.emit('error', error);
}
}
send(message) {
this.ws.send(JSON.stringify(message));
this.emit('message:sent', message);
}
reconnect() {
this.close();
this._connect();
}
close() {
clearTimeout(this.timoutId);
if (!this.ws) {
return;
}
this._unbindWsEvents();
this.ws.terminate();
this.ws = null;
}
}
Transport.WS_EVENTS = WS_EVENTS;
module.exports = Transport;