UNPKG

help-fem

Version:

A Browserify/Node.js client module for the Help.com team's FEM.

1,569 lines (1,519 loc) 47.7 kB
;(function() { 'use strict'; // ## Required Modules // ### underscore.js // Underscore.js is used for utility, mainly to allow the client to be extended // *a la* Backbone / Ampersand style. var _ = require('underscore'); // ### uuid // UUID is used to generate the v4 UUIDs for the socket messages. var uuid = require('uuid'); // ### femio-client // The main driver for this client module, the femio-client provides an easy // interface for talking to a FEMIO server. var io = require('femio-client'); var clientLog = require('debug')('help-fem:client'); var serverLog = require('debug')('help-fem:server'); // ## HelpFem // `HelpFem` is really just a synonym for `module.exports`. var HelpFem = {}; function defaultHandler(type, error, response) { if (error) { throw error; } console.log('Successful ' + type + ': ' + JSON.stringify(response)); } // ## HelpFem.Client // ### HelpFem.Client.constructor // The constructor for `HelpFem.Client` takes an object of options for flexibility. // The current supported options are: // 1. `uri` :: `String` - The URI for the FEM (or really any websocket server). // Defaults to either `localhost:8080` or reads the `FEM` environment variable. // 2. `organizationId` || `namespace` :: `String` - The namespace you would like to // connect to in your FEMIO server. The option is aliased to `organizationId` // because Help.com namespaces are organization IDs. // 3. `user` :: `Boolean` - Whether or not the client is a user or a customer. // Defaults to `false`. HelpFem.Client = function(options) { // Test to see if we are in the browser or running as a backend microservice. this.inBrowser = typeof window !== 'undefined'; // Set the `uri`. If it's set in `options`, use that value. Otherwise, defer to // localhost if in the browser, or the FEM environment variable otherwise. this.uri = typeof options.uri === 'string' ? options.uri : (this.inBrowser ? 'http://127.0.0.1:8080' : process.env.FEM); // Set the `organizationId` and `namespace`. var org = options.organizationId || options.namespace; if (org === 'start') { org = undefined; } this.organizationId = this.namespace = org; // Set the `role` of the client, defaulting to `'customer'`. this.role = options.user ? 'user' : 'customer'; // Ensure that any objects with methods have access to the client object. // This will allow us to call functions with the desired context. this.chat.parent = this; this.session.parent = this; // Application Context this.context = options.context; // Information to be stored about this specific client. this.info = {}; /* istanbul ignore next */ if (this.inBrowser) { var transports = window.WebSocket && window.WebSocket.CLOSING === 2 ? ['websocket', 'polling'] : ['polling']; } else { var transports = options.transports || ['websocket', 'polling']; } // Connect to the FEMIO server and store the socket information. this.socket = io(this.uri, { transports: transports, orgId: this.organizationId, clientId: options.clientId || undefined }); this.socket.on('error', function(err) { console.error('socket err', err); }); // Reply callback map for this client. this.replyCallbacks = {}; // #### Extending Events // Extending events is done exactly like in Ampersand or Backbone, except with // added functionality to have types within an event. The event callback passes // an error as the first argument followed by the JSON response object. // // ```js // { // events: { // 'event with no sub types': 'regularCallback' // 'server eventGroup event': { // 'type one': 'typeOneCallback', // 'type two': 'typeTwoCallback' // }, // regularCallback: function(error, response) { // console.log('# Raw response: ' + JSON.stringify(response)); // }, // typeOneCallback: function(error, response) { // console.log('# Raw response: ' + JSON.stringify(response)); // } // } // } // ``` // // In order to be able to extend the events without completely overriding all // the default actions, we need to split up socket events from our internal // event types. var events = {}; var eventsWithTypes = {}; // Run through the `events` property and dive into events that have sub types. // This overwrites any default callbacks with explicitly declared ones. var self = this; _.each(self.events, function(event, index) { if (typeof self._events[index] === 'object') { eventsWithTypes[index] = {}; _.extend(eventsWithTypes[index], self._events[index], event); } }); // Create a full list of all events, deferring any default callbacks with // explicitly declared ones. _.extend(events, self._events, self.events, eventsWithTypes); // `generateCallback` is a helper function to properly generate a callback // that works with femio-client. function generateCallback(event) { var getRegisteredCallback; // ##### Basic Top Level Events // If the event does not handle any subtypes, just register the callback. if (typeof events[event] === 'string') { getRegisteredCallback = function() { return self[events[event]]; }; // ##### Events with Subtypes // If the event does involve subtypes, register a callback that handles // those subtypes. } else { getRegisteredCallback = function(meta) { if (_.has(events[event], meta.type)) { return self[events[event][meta.type]]; } }; } return function callback() { var args = Array.prototype.slice.call(arguments); var response = args[0]; var meta = _.has(response, 'meta') ? response.meta : {}; self.log(event, response); var next = [getRegisteredCallback(meta)]; if (_.has(self.replyCallbacks, meta.replyTo)) { next.push(self.replyCallbacks[meta.replyTo]); delete self.replyCallbacks[meta.replyTo]; } // If no callbacks are registered, warn about an unhandled event. if (next.length === 1 && next[0] === undefined) { args.splice(2, 0, event); // Use an overriding unhandled event if specified. var unhandled = typeof self.unhandled === 'function' ? self.unhandled : self._unhandled; next.push(unhandled); } // Prepend the error to the arguments list. var error = _.has(meta, 'result') && meta.result !== 'SUCCESS' ? new Error(meta.reason) : null; args.unshift(error); // Call the callbacks with a client context and the arguments. _.invoke(_.filter(next), 'apply', self, args); }; } // Register all the femio-client callbacks. for (var event in events) { self.socket.on(event, generateCallback(event)); } // Call initialize function if not turned off if (options.init !== false) { this.initialize.apply(this, arguments); } }; // ### HelpFem.Client.prototype _.extend(HelpFem.Client.prototype, { // Logger log: function log(event, payload) { var meta = _.result(payload, 'meta', {}); if (event.indexOf('server') > -1) { serverLog('%s: %o', meta.type, payload); } else { clientLog('%s: %o', meta.type, payload); } }, // Default events. _events: { 'connect': '_connect', 'disconnect': '_disconnect', 'server session event': { 'start': '_sessionStart', 'end': '_sessionEnd', 'login': '_sessionLogin', 'logout': '_sessionLogout' }, 'server chat event': { 'start': '_chatStart', 'join': '_chatJoin', 'leave': '_chatLeave' } }, // ### Default Callbacks // Default `unhandled` callback. _unhandled: function(error, response, event) { console.warn('Unhandled Event', { event: event, command: response.meta.type, error: error, response: response }); }, // Default `connect` callback. _connect: function() { console.log('Connected to FEM.'); }, _disconnect: function() { console.log('Disconnected from FEM.'); }, // Default `server session event start` callback. _sessionStart: _.partial(defaultHandler, 'session start'), // Default `server session event end` callback. _sessionEnd: _.partial(defaultHandler, 'session end'), // Default `server session event login` callback. _sessionLogin: function(error, response) { defaultHandler('session login', error, response); // Update with new Client ID. this.info.clientId = response.data.clientId; }, // Default `server session event logout` callback. _sessionLogout: _.partial(defaultHandler, 'session logout'), // Default `server chat event start` callback. _chatStart: _.partial(defaultHandler, 'chat start'), // Default `server chat event join` callback. _chatJoin: _.partial(defaultHandler, 'chat join'), // Default `server chat event leave` callback. _chatLeave: _.partial(defaultHandler, 'chat leave'), // ### Built-In Actions // #### Initialization initialize: function() { return this; }, // #### Session session: { resetState: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'reset client state'}, data, callback ); }, // Request metadata cache. getCacheMetadata: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'get cache metadata'}, data, callback ); }, // Start a session. start: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'start'}, data, callback ); }, // End a session. end: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'end'}, data, callback ); }, // Login to a session. login: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'login'}, data, callback ); }, // Logout of a session. logout: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'logout'}, data, callback ); }, //send request for reset password token resetPassword: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'reset password'}, data, callback ); }, updatePassword: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'update password'}, data, callback ); }, // Actual password reset request updateCurrentUser: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/user', method: 'PUT'}, data, callback ); }, initializeState: function(data) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'initialize state'}, data ); }, customerSonarPing: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'customer sonar ping'}, data, callback ); }, userSonarPing: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'user sonar ping'}, data, callback ); }, doormanAssignChat: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'doorman assign chat'}, data, callback ); }, doormanMonitorChat: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'doorman monitor chat'}, data, callback ); }, // Send a chat status update. chatStatus: function(data) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'chat status'}, data ); }, // Set rep availability. updateAvailability: function(availability, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'update availability'}, {availability: availability}, callback ); }, suggestion: function(data) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'suggestion'}, data ); }, postchat: function(data) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'postchat'}, data ); }, getSurvey: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'postchat'}, {uri: '/survey', method: 'GET'}, data, callback ); }, postChatResponse: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'postchat'}, {uri: '/response', method: 'GET'}, data, callback ); }, getPostChatQuestion: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'postchat'}, {uri: '/question', method: 'GET'}, data, callback ); }, updatePostChatQuestion: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'postchat'}, {uri: '/question', method: 'PUT'}, data, callback ); }, createPostChatQuestion: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'postchat'}, {uri: '/question', method: 'POST'}, data, callback ); }, deletePostChatQuestion: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'postchat'}, {uri: '/question', method: 'DELETE'}, data, callback ); }, createPostChatQuestionOption: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'postchat'}, {uri: '/option', method: 'POST'}, data, callback ); }, updatePostChatQuestionOption: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'postchat'}, {uri: '/option', method: 'PUT'}, data, callback ); }, deletePostChatQuestionOption: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'postchat'}, {uri: '/option', method: 'DELETE'}, data, callback ); }, getOrganizationSettings: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'get organization settings'}, data, callback ); }, updateOrganizationSettings: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'update organization settings'}, data, callback ); }, deleteOrganizationSettings: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'delete organization settings'}, data, callback ); }, getOrganizationChatSettings: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'get organization chat settings'}, data, callback ); }, updateUser: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/users', method: 'PUT'}, data, callback ); }, createUser: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/users', method: 'POST'}, data, callback ); }, deleteUser: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/user', method: 'DELETE'}, data, callback ); }, getDepartments: function (data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/departments', method: 'GET'}, data, callback ); }, updateAnalyticsSession: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'update analytics'}, data, callback ); }, getAnalyticsSession: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'get analytics session'}, data, callback ); }, sendOfflineMessage: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'sendOfflineMessage'}, {uri: '/sendEmail', method: 'POST'}, data, callback ); }, getHistory: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'chatHistory'}, {uri: '/listChats', method: 'GET'}, data, callback ); }, getEventsForChat: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'chatHistory'}, {uri: '/eventsForChat', method: 'GET'}, data, callback ); }, getReportRollup: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingEvents', method: 'GET'}, data, callback ); }, getReportRaw: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingEventsRaw', method: 'GET'}, data, callback ); }, getNps: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingPostChat'}, {uri: '/nps', method: 'GET'}, data, callback ); }, getReportResponseLag: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingResponseLag', method: 'GET'}, data, callback ); }, getReportWordCounts: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingWordCounts', method: 'GET'}, data, callback ); }, getReportStarted: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingStarted', method: 'GET'}, data, callback ); }, getReportStartedByDayOfWeek: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingStartedByDayOfWeek', method: 'GET'}, data, callback ); }, getReportCompleted: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingCompleted', method: 'GET'}, data, callback ); }, getReportOfflineMessages: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingOfflineMessages', method: 'GET'}, data, callback ); }, getReportBusiestUsers: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingBusiestUsers', method: 'GET'}, data, callback ); }, getReportBusiestGroups: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingBusiestGroups', method: 'GET'}, data, callback ); }, getReportBusiestDepartments: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingBusiestDepartments', method: 'GET'}, data, callback ); }, getReportCompletedDOW: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingCompletedDOW', method: 'GET'}, data, callback ); }, getReportUnanswered: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingUnanswered', method: 'GET'}, data, callback ); }, getReportAbandoned: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingAbandoned', method: 'GET'}, data, callback ); }, getReportTotalChatTime: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingTotalChatTime', method: 'GET'}, data, callback ); }, getReportFirstResponse: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingFirstResponse', method: 'GET'}, data, callback ); }, getReportQueueTime: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingQueueTime', method: 'GET'}, data, callback ); }, getReportNpsResponseCounts: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingNpsResponseCounts', method: 'GET'}, data, callback ); }, getReportNpsHistorical: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingNpsHistorical', method: 'GET'}, data, callback ); }, getReportNpsByUser: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingNpsByUser', method: 'GET'}, data, callback ); }, getReportNpsByGroup: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingNpsByGroup', method: 'GET'}, data, callback ); }, getReportNpsByDepartment: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'reportingEvents'}, {uri: '/reportingNpsByDepartment', method: 'GET'}, data, callback ); }, getUsers: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/users', method: 'GET'}, data, callback ); }, getGroups: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/groups', method: 'GET'}, data, callback ); }, getGroupUsers: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/groupusers', method: 'GET'}, data, callback ); }, createGroupUserTie: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/groupusers', method: 'POST'}, data, callback ); }, deleteGroupUserTie: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/groupusers', method: 'DELETE'}, data, callback ); }, getDepartmentGroups: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/departmentgroups', method: 'GET'}, data, callback ); }, createDepartmentGroupTie: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/departmentgroups', method: 'POST'}, data, callback ); }, deleteDepartmentGroupTie: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/departmentgroups', method: 'DELETE'}, data, callback ); }, createDepartment: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/departments', method: 'POST'}, data, callback ); }, updateDepartment: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/departments', method: 'PUT'}, data, callback ); }, createGroup: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/groups', method: 'POST'}, data, callback ); }, updateGroup: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'organizationManager'}, {uri: '/groups', method: 'PUT'}, data, callback ); }, chatStartRep: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'chat start rep'}, data, callback ); }, chatInvitationSend: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'chat invitation send'}, data, callback ); }, chatInvitationAccept: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'chat invitation accept'}, data, callback ); }, chatInvitationReject: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'chat invitation reject'}, data, callback ); }, getChatNotes: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'noteManager'}, {uri: '/note', method: 'GET'}, data, callback ); }, postChatNotes: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'noteManager'}, {uri: '/note', method: 'POST'}, data, callback ); }, postChatTag: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'tagManager'}, {uri: '/chats', method: 'POST'}, data, callback ); }, removeChatTag: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'tagManager'}, {uri: '/chats', method: 'DELETE'}, data, callback ); }, getTagsForChat: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'tagManager'}, {uri: '/tagsForChat', method: 'GET'}, data, callback ); }, getTagReport: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'tagManager'}, {uri: '/report', method: 'GET'}, data, callback ); }, getOrganizationChatTags: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'tagManager'}, {uri: '/tags', method: 'GET'}, data, callback ); }, postOrganizationChatTag: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'tagManager'}, {uri: '/tags', method: 'POST'}, data, callback ); }, removeOrganizationChatTag: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'tagManager'}, {uri: '/tags', method: 'DELETE'}, data, callback ); }, getBannedIps: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'banned'}, {uri: '/banned', method: 'GET'}, data, callback ); }, postBannedIp: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'banned'}, {uri: '/banned', method: 'POST'}, data, callback ); }, removeBannedIp: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'banned'}, {uri: '/banned', method: 'DELETE'}, data, callback ); }, emailCustomerTranscript: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'email customer transcript'}, data, callback ); }, setCredentialsSalesforceApi: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'salesforceGet'}, {uri: '/credentials', method: 'POST'}, data, callback ); }, getCredentialsSalesforceApi: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'salesforceGet'}, {uri: '/credentials', method: 'GET'}, data, callback ); }, getSalesforceMetaData: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'salesforceGet'}, {uri: '/salesforceMetaData', method: 'GET'}, data, callback ); }, getSalesforcePicklist: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'salesforceGet'}, {uri: '/picklist', method: 'GET'}, data, callback ); }, setSalesforcePicklist: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'salesforceGet'}, {uri: '/picklist', method: 'POST'}, data, callback ); }, getSalesforceData: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'salesforceGet'}, {uri: '/salesforce', method: 'GET'}, data, callback ); }, getSalesforceAuthRequestURL: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'salesforcePush'}, {uri: '/requestURL', method: 'GET'}, data, callback ); }, getSalesforceConnectedApp: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'salesforcePush'}, {uri: '/connectedApp', method: 'GET'}, data, callback ); }, getSalesforceHasAccessToken: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'salesforcePush'}, {uri: '/hasAccessToken', method: 'GET'}, data, callback ); }, refreshSalesforceToken: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'salesforcePush'}, {uri: '/refreshToken', method: 'POST'}, data, callback ); }, createSalesforceObject: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'salesforcePush'}, {uri: '/createObject', method: 'POST'}, data, callback ); }, contactSupport: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'contact support'}, data, callback ); }, addOrganizationChatResponse: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'add organization chat response'}, data, callback ); }, updateOrganizationChatResponse: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'update organization chat response'}, data, callback ); }, getOrganizationChatResponses: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'get organization chat responses'}, data, callback ); }, deleteOrganizationChatResponse: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'delete organization chat response'}, data, callback ); }, addUserChatResponse: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'add user chat response'}, data, callback ); }, updateUserChatResponse: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'update user chat response'}, data, callback ); }, getUserChatResponses: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'get user chat responses'}, data, callback ); }, deleteUserChatResponse: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'delete user chat response'}, data, callback ); }, getAllChatResponses: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'get all chat responses'}, data, callback ); }, postChatResponseToRoom: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'post chat response room'}, data, callback ); }, zendeskGetAuthUrl: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'zendesk get auth url'}, data, callback ); }, zendeskGetTickets: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'zendesk get tickets'}, data, callback ); }, zendeskCreateTicket: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'zendesk create ticket'}, data, callback ); }, fireTrigger: function(data) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'proactive chat fire trigger'}, data ); }, fireTriggers: function(data) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'proactive chat fire triggers'}, data ); }, getProactiveGreetings: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'proactive chat get greetings'}, data, callback ); }, upsertProactiveGreeting: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'proactive chat upsert greeting'}, data, callback ); }, deleteProactiveGreeting: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'proactive chat delete greeting'}, data, callback ); }, // Request to transfer chat. requestTransfer: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'transfer request'}, data, callback ); }, // Respond to transfer chat. respondToTransfer: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'transfer response'}, data, callback ); }, getVisitors: function(data, callback) { this.parent._doHyperJSONEmit( this.parent._emitSessionEvent, {type: 'list visitors'}, {}, data, callback ); }, forceUserLogout: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'force logout user'}, data, callback ); }, getMissionControlVersion: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'mission control get version'}, data, callback ); }, dumpState: function(callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'dumpState'}, {}, callback ); }, chatAndAvailabilityDetails: function(callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'chat-and-availability-details'}, {}, callback ); }, renameCustomer: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'rename-customer'}, data, callback ); } }, // #### Chat chat: { // Start a chat. start: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitChatEvent, {type: 'start'}, data, callback ); }, // End a chat. end: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitChatEvent, {type: 'end'}, data, callback ); }, // Join a chat room. join: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitChatEvent, {type: 'join'}, data, callback ); }, // Leave a chat. leave: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'leave'}, data, callback ); }, // Send a chat message. message: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitChatEvent, {type: 'message'}, data, callback ); }, // Request the latest chat cache. cache: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitChatEvent, {type: 'cache'}, data, callback ); }, // Request message cache. getCacheMessages: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitChatEvent, {type: 'get cache messages'}, data, callback ); }, // Request metadata cache. getCacheMetadata: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitChatEvent, {type: 'get cache metadata'}, data, callback ); }, requestRepAvailability: function(data, callback) { this.parent._doSimpleEmit( this.parent._emitSessionEvent, {type: 'get rep availability'}, data, callback ); } }, // #### Generic Emit // This method can be called to send any kind of message through femio-client without // having to directly invoke the socket object. emit: function(type, payload) { this.log(type, payload); this.socket.send(type, payload); }, // #### Generate Meta // This method generates a meta for your payload. You can pass any properties and it // will automatically take care of the `id` property for you. It will also // add any information in stored in the client's `info` property. // Properties passed into the function take precedent. generateMeta: function(properties) { return _.extend({id: uuid.v4()}, this.info, properties); }, _doSimpleEmit: function(emitter, metaProperties, data, callback) { if (typeof data === 'function' && typeof callback === 'undefined') { callback = data; data = {}; } var _data = _.extend({}, data, this.info); emitter.call(this, metaProperties, _data, callback); }, _doHyperJSONEmit: function(emitter, metaProperties, hyperJSON, data, callback) { if (typeof data === 'function' && typeof callback === 'undefined') { callback = data; data = {}; } var _data = _.extend({}, hyperJSON, {body: data}, this.info); emitter.call(this, metaProperties, _data, callback); }, _emitChatEvent: function(metaProperties, data, callback) { return this._emitEvent('client chat event', metaProperties, data, callback); }, _emitSessionEvent: function(metaProperties, data, callback) { return this._emitEvent('client session event', metaProperties, data, callback); }, _emitEvent: function(event, metaProperties, data, callback) { var payload = {meta: this.generateMeta(metaProperties), data: data}; this.emit(event, payload); if (typeof callback === 'function') { this.replyCallbacks[payload.meta.id] = callback; } } }); // ### HelpFem.Client.extend // Modeled after Ampersand and Backbone's `extend` functionality, this method creates // a new `HelpFem.Client` with any additional prototypical or private methods and // properties. HelpFem.Client.extend = function(prototypes, privates) { var parent = this; var child; if (typeof prototypes === 'object' && prototypes.hasOwnProperty('constructor')) { child = prototypes.constructor; } else { child = function() { return parent.apply(this, arguments); }; } _.extend(child, parent, privates); var Surrogate = function() { this.constructor = child; }; Surrogate.prototype = parent.prototype; child.prototype = new Surrogate(); if (typeof prototypes === 'object') { _.extend(child.prototype, parent.prototype, prototypes); } return child; }; // Export the module. module.exports = HelpFem; })();