transport.js 4.62 KB
"use strict";

const request = require('request');
const uuidv4 = require('uuid/v4');
const moment = require('moment');

const config = require('komodo-sdk/config');
const logger = require('komodo-sdk/logger');

const modems = require('./modems');
const partnerLastSeen = require('./partner-last-seen');
const history = require('./history');

async function _getApproriateHandlerByLastSeen(partnerNumber) {
    logger.verbose('Looking for last seen on for partner number ' + partnerNumber);
    const lastSeenFrom = await partnerLastSeen.get(partnerNumber);
    return lastSeenFrom;
}

function _getApproriateHandlerByForced() {
    if (!config.sending_handler || !config.sending_handler.length) return;

    const sendingHandlerCount = config.sending_handler.length;
    const idx = Math.floor(Math.random() * sendingHandlerCount);
    return config.sending_handler[idx];
}

async function _getApproriateHandler(partnerNumber, origin) {
    let handlerToUse;

    if (config.handler_chooser_algorithm === 'FORCED') {
        handlerToUse = _getApproriateHandlerByForced();
        logger.verbose('Config file mentioned to using FORCED handler chooser algorithm', { handler_to_use: handlerToUse});
    }
    else {
        handlerToUse = await _getApproriateHandlerByLastSeen(partnerNumber);
        logger.verbose('Config file mentioned to using LAST-SEEN handler chooser algorithm', { handler_to_use: handlerToUse});
    }

    if (!modems.getModemConfig(handlerToUse, config.modems)) {
        const handlerWithSameOrigin = modems.getModemConfig(origin, config.modems);
        if (handlerWithSameOrigin) {
            logger.verbose('Invalid approriate handler, using handler from the same ORIGIN request by CORE to send sms')
            handlerToUse = origin;
        }
        else {
            logger.verbose('Invalid approriate handler, using default handler to send sms')
            handlerToUse = config.default_modem;
        }
    }

    return handlerToUse;
}

function _send(destinationNumber, msg, handlerName) {

    /*
    if (msg.length > 160 && !config.do_not_trim_long_sms) {
        logger.verbose('Message trim to 160 chars');
        msg = msg.slice(0, 156) + ' ...';
    }
    */

    if (msg.length > 160) {
        const newMsg = msg.slice(0, 160);
        const remainingMsg = msg.slice(160);

        _send(destinationNumber, newMsg, handlerName);
        setTimeout(() => {
            _send(destinationNumber, remainingMsg, handlerName);
        }, 2000);

        return;
    }

    const modem = modems.getModemConfig(handlerName, config.modems);
    if (!modem) {
        logger.warn('Not knowing modem to use. Ignoring message', { destination_number: destinationNumber, msg: msg, handler_name: handlerName });
        return;
    }

    if (!modem.url || !modem.apikey) {
        logger.warn('Invalid modem configuration', { config: modem, handler_name: handlerName });
        return;
    }

    const reqId = uuidv4();

    history.push({
        ts: moment().format('YYYY-MM-DD HH:mm:ss'), 
        modem: {
            name: handlerName,
        },
        direction: 'OUTGOING',
        partner: destinationNumber,
        message: msg,
    });


    const requestOptions = {
        url: modem.url,
        qs: {
            msg: msg,
            number: destinationNumber,
            reqid: reqId,
            apikey: modem.apikey
        }
    }

    logger.info('Sending message to modem handler', { req_id: reqId, destination_number: destinationNumber, msg: msg, msg_length: msg.length, handler_name: handlerName });
    request(requestOptions, function(err, res, body) {
        if (err) {
            logger.warn('Error requesting to modem handler. ' + err.toString(), { req_id: reqId, handler_name: handlerName });
            
        }
        else if (res.statusCode != 200) {
            logger.warn('Modem handler not responding with HTTP status code 200.', { http_status_code: res.statusCode, req_id: reqId, handler_name: handlerName });
        }
        else {
            logger.verbose('Message sent to handler', { req_id: reqId, handler_name: handlerName, response_body: body });
        }
    })

}

async function send(partner, msg, origin) {
    if (!partner) return;

    if (typeof msg !== 'string') {
        logger.warn('Message to send is not a string, ignoring message');
        return;
    }

    msg = msg.trim();
    if (!msg) return;

    const destinationNumber = modems.removeSuffixFromNumber(partner, config);

    logger.verbose('Choosing handler name', { partner: partner, msg: msg, origin: origin });
    let handlerName = ( await _getApproriateHandler(destinationNumber) );

    _send(destinationNumber, msg, handlerName);
}

exports.send = send;