modem-chooser.js 3.34 KB
'use strict';

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

function filterOutCandidates(candidates) {
    const logger = global.KOMODO_LOGGER;

    if (!Array.isArray(candidates)) {
        return [];
    }

    if (!candidates.length) return [];

    const filtered = candidates.filter((item) => {
        if (typeof item === 'number') {
            item = item.toString();
        }

        if (typeof item !== 'string') {
            if (logger) logger.warn(`MODEM-CHOOSER: typeof item is ${ typeof item }, not a string or a number`);
            return false;
        }

        if (item.indexOf('#') >= 0) {
            if (logger) logger.warn('MODEM-CHOOSER: candidate has #, ignoring');
            return false;
        }

        const modem = modems.get('imsi', item);
        if (!modem) {
            if (logger) logger.verbose(`MODEM-CHOOSER: No modem with IMSI ${item} found, removing from candidates`);
            return false;
        }

        return true;
    });

    if (logger) logger.verbose('MODEM-CHOOSER: Senders candidates reduced', { candidates, filtered });
    return filtered;
}

exports.chooser = async function chooser(destination, config) {
    const logger = global.KOMODO_LOGGER;

    let prefixName = await prefixes.lookup(destination);
    if (typeof prefixName === 'string') {
        prefixName = prefixName.toUpperCase();
    }

    if (logger) logger.verbose('MODEM-CHOOSER: Choosing suitable senders', { destination, prefixName });

    let sendersImsi = [];
    if (config.senders_imsi && prefixName && config.senders_imsi.prefix_names && config.senders_imsi.prefix_names[prefixName]) {
        sendersImsi = filterOutCandidates(config.senders_imsi.prefix_names[prefixName]);
        if (logger) logger.verbose('MODEM-CHOOSER: Try to use imsi senders by prefix name', { destination, prefixName, sendersImsi, candidates: config.senders_imsi.prefix_names[prefixName] });
    }

    if (!sendersImsi.length && config.senders_imsi && config.senders_imsi.unknown_prefix) {
        sendersImsi = filterOutCandidates(config.senders_imsi.unknown_prefix);
        if (logger) logger.verbose('MODEM-CHOOSER: Try to use senders for unknown prefix', { destination, prefixName, sendersImsi, candidates: config.senders_imsi.unknown_prefix });
    }

    if (!sendersImsi.length) {
        sendersImsi = filterOutCandidates([ await partnerLastSeen.get(destination) ]);
        if (logger) logger.verbose('MODEM-CHOOSER: Try to use sender by last seen', { destination, prefixName, sendersImsi });
    }

    if (!sendersImsi.length && config.senders_imsi && config.senders_imsi.default) {
        sendersImsi = filterOutCandidates(config.senders_imsi.default);
        if (logger) logger.verbose('MODEM-CHOOSER: Try to use default senders', { destination, prefixName, sendersImsi, candidates: config.senders_imsi.default });
    }

    if (!sendersImsi.length) {
        if (logger) logger.warn('MODEM-CHOOSER: No suitable sender found', { destination, prefixName });
        return;
    }

    const count = sendersImsi.length;
    const idx = Math.round(Math.random() * (count - 1));
    const imsiChoosed = sendersImsi[idx];

    if (logger) logger.verbose(`MODEM-CHOOSER: gonna use modem with IMSI ${imsiChoosed}`, { destination, prefixName, imsiSenders: sendersImsi });

    return imsiChoosed;
}