'use strict'; var moment = require('moment'); var momentFormat = 'YYYY-MM-DD HH:mm:ss'; module.exports = MatrixUtil; function _cleanPartnerId(partnerId) { let cleaned = partnerId; try { cleaned = cleaned.toLocaleString(); cleaned = cleaned.trim().toLowerCase(); } catch(e) { return partnerId; } return cleaned; } function MatrixUtil(options) { if (!options) { console.trace('Undefined options'); process.exit(1); } this.matrix = options.matrix; if (!this.matrix) { console.trace("Matrix not set"); process.exit(1); } this.logger = options.logger; if (!this.logger) { console.trace("Logger not set"); process.exit(1); } } MatrixUtil.prototype.updateBuddyState = function(jid, state, statusText, resource) { if (!jid) {return; } if (jid == 'undefined') {return; } jid = _cleanPartnerId(jid); if (!resource) { resource = 'undefined'; } let logger = this.logger; let matrix = this.matrix; logger.verbose('Buddy state change', {jid: jid, state: state, statusText: statusText, resource: resource}); if (!matrix) { return; } if (!matrix.buddies) { matrix.buddies = {}; } if (!matrix.buddies[jid]) { matrix.buddies[jid] = {resources: {}}; } try { matrix.buddies[jid]['resources'][resource] = { state: state, statusText: statusText, last_update: moment().format(momentFormat) } } catch(e) { logger.warn('MatrixUtil: Exception on update resources on matrix', {jid: jid, state: state, statusText: statusText, resource: resource}); } if (resource != 'undefined' && matrix.buddies[jid].resources['undefined']) { try { delete matrix.buddies[jid].resources['undefined']; } catch(e) {}; } } MatrixUtil.prototype.isPartnerOffline = function(partner) { if (!partner) { return; } partner = _cleanPartnerId(partner); let matrix = this.matrix; let logger = this.logger; if (!matrix) { return false; } if (!matrix.buddies[partner]) { return false; } if (!matrix.buddies[partner].resources) { return false; }; let resources = matrix.buddies[partner].resources; for (let key in resources) { if (resources.hasOwnProperty(key)) { let resource = resources[key]; if (resources[key].state == 'online') { return false; } } } logger.verbose('Offline partner detected: ' + partner); return true; } MatrixUtil.prototype._updateLastResponseTime = function(partner) { let matrix = this.matrix; let logger = this.logger; if (!matrix.buddies[partner]['last_outgoing']) { logger.verbose('No outgoing yet, skip updateLastResponseTime'); return; } if (!matrix.buddies[partner]['last_outgoing']['last_update_ts']) { logger.verbose('No outgoing timestamp yet, skip updateLastResponseTime'); return; } if ( matrix.buddies[partner]['last_incoming'] && (Number(matrix.buddies[partner]['last_incoming']['last_update_ts']) > Number(matrix.buddies[partner]['last_outgoing']['last_update_ts'])) ) { return; } let delta = Date.now() - Number(matrix.buddies[partner]['last_outgoing']['last_update_ts']); delta = (delta / 1000).toFixed(2); logger.verbose('MatrixUtil: Response time in ' + delta + ' seconds', {partner: partner}); matrix.buddies[partner]['last_response_time_in_secs'] = delta; } MatrixUtil.prototype._updateLastMessage = function(partner, msg, direction) { if (!partner) { return; } partner = _cleanPartnerId(partner); let matrix = this.matrix; let logger = this.logger; if (!matrix) { return; } if (!matrix.buddies) { matrix.buddies = {}; } if (!matrix.buddies[partner]) { matrix.buddies[partner] = {}; } if (direction == 'incoming') { try { this._updateLastResponseTime(partner); } catch(e) { logger.warn('Exception when updateLastResponseTime', {err: e}); } } matrix.buddies[partner]['waiting_for_response'] = (direction == 'outgoing'); matrix.buddies[partner]['last_' + direction] = { msg: msg, last_update: moment().format(momentFormat), last_update_ts: Date.now() } if (direction == 'outgoing') { return; } } MatrixUtil.prototype.updateLastIncoming = function(partner, msg) { this._updateLastMessage(partner, msg, 'incoming'); } MatrixUtil.prototype.updateLastOutgoing = function(partner, msg) { this._updateLastMessage(partner, msg, 'outgoing'); }