transport.js 4.6 KB
"use strict";

const MAX_SMS_LENGTH = 140;

const url = require('url');
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 messagingService = require('komodo-center-messaging-client-lib');

const common = require('./common');
const modems = require('./modems2');
const modemChooser = require('./modem-chooser');
// const partnerLastSeen = require('./partner-last-seen');
const history = require('./history');
const prefixes = require('./prefixes');
const truncate = require('./truncate-paragraph');

function _send(destinationNumber, msg, handlerIMSI) {

    if (msg.length > MAX_SMS_LENGTH) {
        logger.info('Splitting message');

        /*
        const newMsg = msg.slice(0, MAX_SMS_LENGTH);
        const remainingMsg = msg.slice(MAX_SMS_LENGTH);
        */

        const [newMsg, remainingMsg] = truncate(msg, MAX_SMS_LENGTH);
        logger.verbose('TRANSPORT: Truncate long message', {maxLength: MAX_SMS_LENGTH, original: msg, head: newMsg, tail: remainingMsg});

        _send(destinationNumber, newMsg, handlerIMSI);
        setTimeout(() => {
            _send(destinationNumber, remainingMsg, handlerIMSI);
        }, 1000);

        return;
    }

    const modem = modems.get('imsi', handlerIMSI);
    if (!modem) {
        logger.warn('Not knowing modem to use. Ignoring message', { destination_number: destinationNumber, msg: msg, modem_imsi: handlerIMSI });
        return;
    }

    if (!modem.reportIp || !modem.reportPort || !modem.reportApikey) {
        logger.warn('Invalid modem configuration', { modem });
        return;
    }

    const reqId = uuidv4();

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

    logger.verbose('TRANSPORT: saving outgoing message');
    messagingService.onIncomingMessage({
        me: modem.name,
        partner: destinationNumber,
        partner_raw: `+${destinationNumber}`.replace(/^\++/, '+'),
        msg: msg,
        origin_label: modem.imsi || 'UNKNOWN',
        origin_transport: 'SMS',
        origin_partner: destinationNumber,
        do_not_forward_to_core: true,
        is_outgoing: true,
    });

    const requestOptions = {
        url: url.format({
            protocol: 'http',
            hostname: modem.reportIp,
            port: modem.reportPort,
            pathname: modem.reportPathSms || '/sms',
        }),
        qs: {
            msg: msg,
            number: destinationNumber,
            reqid: reqId,
            apikey: modem.reportApikey,
        }
    }

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

}

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

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

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

    const destinationNumber = common.removeSuffixFromNumber(partner, config.number_suffix);
    const prefixName = await prefixes.lookup(destinationNumber);
    logger.verbose('Destination number prefix lookup', {partner: destinationNumber, prefix: prefixName});

    // logger.verbose('Choosing handler name', { partner, destinationNumber, msg, origin });
    // const handlerIMSI = await partnerLastSeen.get(destinationNumber) ;
    const handlerIMSI = await modemChooser.chooser(destinationNumber, config);

    if (!handlerIMSI) {
        logger.warn(`Unknown handler for sending message to partner`, { partner, destinationNumber });
        return;
    }

    _send(destinationNumber, msg, handlerIMSI);
}

exports.send = send;