matrix-util.js 4.96 KB
'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.isAFriend = function(jid) {
    if (!jid) { return; }

    jid = _cleanPartnerId(jid);

    let matrix = this.matrix;

    if (!matrix) { return false; };
    if (!matrix.buddies) { return false; }
    if (!matrix.buddies[jid]) { return false; }

    return true;
}

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;
    logger.verbose('Response time in ' + delta + ' seconds');
    matrix.buddies[partner]['last_response_time_in_secs'] = Math.round(delta * 100) / 100;
}

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');
}