Source: plugins/outbound/telegram/base.js

process.env.NTBA_FIX_319 = 1;

const EventEmitter = require('events');
const TelegramBot = require('node-telegram-bot-api');
const Basedata = require('../../../models/basedata');
const Assets = require('../../../models/assets');
const moment = require("moment");

class telegram extends EventEmitter {
    constructor() {
        super();
        global.plgManager.logger.info('-------- PLUGIN TELEGRAM -----------');
        //this.plgManager = global.plgManager;
        this.registerForEvents();
        this.serviceProcId = null;
        this.loadConfig((success) => {

        });
        this.bot = null;
        this.basedata = new Basedata(global.plgManager.logger);
        this.assets = new Assets(global.plgManager.logger);
    }

    /**
     * Registration of Events at the plugin manager (hook in to events provided by the plugin manager)
     */
    registerForEvents() {
        global.plgManager.logger.info('PLUGIN | TELEGRAM | Registering events')

        global.plgManager.on('event_pluginConfig_refreshed', (namespace) => {
            if (namespace === 'telegram') {
                // plugins config has changed --> refresh
                this.loadConfig((success) => {
                    if (success) {
                        global.plgManager.logger.info('PLUGIN | TELEGRAM | successfully reloaded plugin configuration');
                    } else {
                        global.plgManager.logger.error('PLUGIN | TELEGRAM | could not reload plugin config!');
                    }
                });
            }
        })

        global.plgManager.on('event_new_admin_notification', function (notification) {
            if (this.getConfigValue('adminChatActive') == "true"){
                try {
                    this.sendAdminMessage(notification);
                }      
                catch (error){
                    console.error("PLUGIN | TELEGRAM | Error caught while sending admin notification: " + error.message);
                    global.plgManager.logger.error('PLUGIN | TELEGRAM | Error caught while sending admin notification: ' + error.message);
                }
            }
        }.bind(this));

        global.plgManager.on('event_new_feedback_received', (operationUUID, basedataUUID, stateId) => {
            if (this.getConfigValue('telegramFeedbackActive') == "true"){
                try {
                    this.sendFeedbackMessage(operationUUID, basedataUUID, stateId);
                }      
                catch (error){
                    console.error("PLUGIN | TELEGRAM | Error caught while sending feedback: " + error.message);
                    global.plgManager.logger.error('PLUGIN | TELEGRAM | Error caught while sending feedback: ' + error.message);
                }
            }
        });

        global.plgManager.on('event_new_alarm', function (alarmInfo) {   
            if (this.getConfigValue('telegramAlarmActive') == "true"){  
                try {
                    this.sendAlarm(alarmInfo);
                }      
                catch (error){
                    console.error("PLUGIN | TELEGRAM | Error caught while sending alarm: " + error.message);
                    global.plgManager.logger.error('PLUGIN | TELEGRAM | Error caught while sending alarm: ' + error.message);
                }
            }
        }.bind(this));

        global.plgManager.on('event_new_state', function (stateInfo) {
            if (this.getConfigValue('telegramStateActive') == "true"){
                try {
                    this.sendState(stateInfo);
                }      
                catch (error){
                    console.error("PLUGIN | TELEGRAM | Error caught while sending state: " + error.message);
                    global.plgManager.logger.error('PLUGIN | TELEGRAM | Error caught while sending state: ' + error.message);
                }
            }
        }.bind(this));

    }


    /**
     * Plugin-specific Getters and Setters
     * 
    */
    set chatId(chatId) {
        this._chatId = chatId;
    }
    get chatId() {
        return this._chatId;
    }

    set message(message) {
        this._message = message;
    }
    get message() {
        return this._message;
    }

    /**
     * Plugin-specific implementation
     */

    /**
     * Setup TelegramBot object with API-token from config store 
     * 
     */
    setupBot() {
        global.plgManager.logger.debug('PLUGIN | TELEGRAM | Setup Telegram Bot');
        const botToken = this.getConfigValue('botToken');
        this.bot = new TelegramBot(botToken, {polling: false});
    }

    /**
     * returns user chatIds as array from configStore 
     * 
     */
    getUserArray(){
        var userArrayString = this.getConfigValue('chatIds');
        var userArray = [];

        // check if string is empty
        if (userArrayString){
            userArray = userArrayString.split(",").map(x => x.trim()).filter(x => x); // filter removes empty results
        }
        return userArray;
    }
    
    /**
     * returns admin chatIds as array from configStore 
     * 
     */
    getAdminArray(){
        var adminArrayString = this.getConfigValue('adminChatIds');
        var adminArray = [];

        // check if string is empty
        if (adminArrayString){
            adminArray = adminArrayString.split(",").map(x => x.trim()).filter(x => x); // filter removes empty results
        }
        return adminArray;
    }

    getStateArray(){
        var stateArrayString = this.getConfigValue('stateChatIds');
        var stateArray = [];

        // check if string is empty
        if (stateArrayString){
            stateArray = stateArrayString.split(",").map(x => x.trim()).filter(x => x); // filter removes empty results
        }
        return stateArray;
    }

    /**
     * returns feedback chatIds as array from configStore 
     * 
     */
    getFeedbackArray(){
        var feedbackArrayString = this.getConfigValue('feedbackChatIds');
        var feedbackArray = [];

        // check if string is empty
        if (feedbackArrayString){
            feedbackArray = feedbackArrayString.split(",").map(x => x.trim()).filter(x => x); // filter removes empty results
        }
        return feedbackArray;
    }

     /**
     * Send a message to each chatId in chatIds array
     * @param {array} chatIds 
     * @param {string} message 
     */
    sendMessages(chatIds, message) {
        global.plgManager.logger.debug('PLUGIN | TELEGRAM | Sending '+ chatIds.length +' Telegram messages');
        chatIds.forEach(chatId => {
            try {

                this.bot.sendMessage(chatId, message, { parse_mode: 'HTML', disable_web_page_preview: true })
                .then((info) => {

                    global.plgManager.logger.info('PLUGIN | TELEGRAM | Message to ' + JSON.stringify(info.chat) +' sent successfully');
                    console.log('PLUGIN | TELEGRAM | Message to ' + JSON.stringify(info.chat) +' sent successfully');
                   },

                   (error) => {

                    global.plgManager.logger.error('PLUGIN | TELEGRAM | Error sending message: ' + error);
                    console.error(error);
                 });
            }
            catch(error) {
                console.error("PLUGIN | TELEGRAM | Error caught while sending message: " + error);
                global.plgManager.logger.error('PLUGIN | TELEGRAM | Error caught while sending message: ' + error);
            }

            
        });
    }

    /**
     * Sends message to admins
     * @param {string} notification 
     */
    sendAdminMessage(notification){
        var chatIds = this.getAdminArray();
        
        this.setupBot();
        this.sendMessages(chatIds, this.encodeStringForHTML(notification));
    }

    /**
     * Sends message to admins
     * @param {string} operationUUID 
     * @param {string} basedataUUID 
     * @param {integer} stateId 
     */
    sendFeedbackMessage(operationUUID, basedataUUID, stateId){
        var chatIds = this.getFeedbackArray();
        
        var stateLabel = ""
        switch (stateId) {
            case 0:
                stateLabel = "KEINE RÜCKMELDUNG";
                break;
            case 1:
                stateLabel = "KOMME";
                break;
            case 2:
                stateLabel = "KOMME NICHT";
                break;
            default:
                stateLabel = "Status nicht definiert!";
                break; 
        }
        this.setupBot();

        this.basedata.getBaseDataForUUID(basedataUUID, (basedataRows) => {
            if (basedataRows != null){
                basedataRows.forEach((entry)=> {

                    var message = "Rückmeldung \'" + stateLabel + "\' erhalten von "+ entry.lastname + " " + entry.firstname;
                    this.sendMessages(chatIds, this.encodeStringForHTML(message));
               })
           }
       }); 
    }

    /**
     * Creates message for a alarm object and sends message to users
     * @param {object} alarmInfo 
     */
    sendAlarm(alarmInfo){
        var chatIds = this.getUserArray();

        var alarmMessage= "";
        alarmMessage+="\uD83D\uDEA8 EINSATZ \uD83D\uDEA8";
        alarmMessage += "\n\ud83d\udcdf " + this.encodeStringForHTML(alarmInfo.subject.value) + " - " + this.encodeStringForHTML(alarmInfo.keywordCategory.value) + " - " + this.encodeStringForHTML(alarmInfo.keywordName.value);
        alarmMessage+="\n\n";
        alarmMessage+="## BEMERKUNG ##";
        alarmMessage += "\n\ud83d\udcc4 " + this.encodeStringForHTML(alarmInfo.message.value);
        alarmMessage+="\n\n";
        alarmMessage+="## EINSATZSTELLE ##";
        alarmMessage += "\n\uD83D\uDCCD ORT: " + this.encodeStringForHTML(alarmInfo.location.value);
        alarmMessage += "\n\uD83D\uDEE3\uFE0F STRASSE: " + this.encodeStringForHTML(alarmInfo.street.value);
        alarmMessage += "\n\uD83C\uDFE2 ETAGE: " + this.encodeStringForHTML(alarmInfo.floor.value);
        alarmMessage += "\n\uD83C\uDFE0 OBJEKT: " + this.encodeStringForHTML(alarmInfo.object.value);
        alarmMessage += "\n\uD83D\uDEA7 ABSCHNITT: " + this.encodeStringForHTML(alarmInfo.section.value);
        alarmMessage += "\n\uD83C\uDF0D MAPS: <a href='https://www.google.com/maps/search/?api=1&query=" + alarmInfo.lat.value + "," + alarmInfo.lon.value +"'>Google Maps</a> | ";
        alarmMessage += "<a href='http://openfiremap.org/?zoom=17&lat=" + alarmInfo.lat.value + "&lon=" + alarmInfo.lon.value +"'>Openfiremap</a>";
        alarmMessage+="\n\n";
        alarmMessage += "\uD83D\uDE92 EINSATZMITTEL:\n" + this.encodeStringForHTML(alarmInfo.gear.value);
        alarmMessage+="\n\n";
        alarmMessage+="## SONSTIGES ##";
        alarmMessage += "\n\uD83D\uDCE1 LEITSTELLE: " + this.encodeStringForHTML(alarmInfo.ils.value);
        alarmMessage += "\n\u23f0 ALARMZEIT: " + this.encodeStringForHTML(alarmInfo.alarmdate.value) + " " + this.encodeStringForHTML(alarmInfo.alarmtime.value);
        alarmMessage += "\n\uD83D\uDCF3 VERSENDET: "+moment().format("DD.MM.YYYY, HH:mm:ss");
        this.setupBot();
        this.sendMessages(chatIds, alarmMessage);
    }

    /**
     * Creates message for a state object and sends message to users
     * @param {object} stateInfo 
     */
    sendState(stateInfo){
        var chatIds = this.getStateArray();

        this.setupBot();

        this.assets.getAssetForISSI(stateInfo.issi, (assetsRows) => {
            if (assetsRows != null) {
                if (assetsRows.length > 0){
                    assetsRows.forEach((entry)=> {
                        var stateMessage= entry.gearname +" Status: " + stateInfo.radioStatusShort + " - " + stateInfo.radioStatusHumanReadable;
                        this.sendMessages(chatIds, this.encodeStringForHTML(stateMessage))
                   })
                }
                else {
                    var stateMessage= "ISSI: "+stateInfo.issi +" Status: " + stateInfo.radioStatusShort + " - " + stateInfo.radioStatusHumanReadable;
                    this.sendMessages(chatIds, this.encodeStringForHTML(stateMessage))
                }
            }
       }); 



        //this.sendMessages(chatIds, this.encodeStringForHTML(stateMessage));
    }

    /**
     * Creates message for a state object and sends message to users
     * @param {string} message 
     */
    encodeStringForHTML(message){
        if (message != null && message != undefined){
            message = message.replace(/&/gm,"&amp;");
            message = message.replace(/</gm,"&lt;");
            message = message.replace(/>/gm,"&gt;");
            message = message.replace(/\"/gm,"&quot;");
        }
        else {
            message = "";
        }
      
        return message;
    }

    /**
     * Loads configuration for Telegram plugin
     * TBD: Needs to be pulled from plugin config store
     */
    loadConfig(callback) {
        global.plgManager.loadConfigFromStore('telegram', (configRows) => {
            if (configRows !== null) {
                this.config = configRows[0];
                this.config = JSON.parse(this.config.configstore);
                callback(true);
            }
            global.plgManager.logger.info('PLUGIN | TELEGRAM | Configuration reloaded from core database');
        })
    }

    /**
     * returns config parameter for given fieldname
     * @param {string} fieldname 
     */
    getConfigValue(fieldname) {
        var retVal = null;
        this.config.fields.forEach((field) => {
            if (field.fieldname === fieldname) {
                retVal = field.value;
            } 
        });
        return retVal;
    }

}

module.exports = telegram;