ym.js 7.3 KB
var YahooMessenger = require("yahoomessenger");
var striptags = require('striptags');
var sleep = require('sleep');
var db = require('./db.js');

var oldMessages = [];

var config;
var logger;

function insertMessages(db_connection, logger_id, direction, partner, message, sentdate) {

    db_connection.query(
        'INSERT INTO messages SET ?',
        {
            transport: 'YAHOO',
            logger: logger_id,
            direction: direction,
            partner: partner,
            message: message,
            sentdate: sentdate,
        },

        function(err) {
            if (err != null) {
                logger.error("Error on inserting messages to DB, error: " + err);
            }
        }
    );
}

function pm(destination, message) {
    logger.info("Sending to " + destination + ": " + message);

    try {
        YahooMessenger.sendPM(destination, message);
    }
    catch (err) {
        logger.info("Error sending message: " + err.message);
        relogin();
    }
}


function broadcast(destinations, message, exclude) {
    var destinations = destinations.split(',');
    var destinationCount = destinations.length;

    for (var i=0; i < destinationCount; i++) {
        destination = destinations[i];
        if (destination == exclude) {
            continue;
        }

        pm(destination, message);
    }
}

var keepAliveTimer;

var _keepAliveLoop = function() {
    logger.info('Keep alive loop');

    try {
        YahooMessenger.keepAlive();
        keepAliveLoop();
    }
    catch (err) {
        logger.info("Error when sending keepalive: " + err.message);
        relogin();
    }
}

function isAdmin(user) {
  var admins = config.yahoomessenger.admin.split(',');

  return (admins.indexOf(user) >= 0);
}

function keepAliveLoop() {
    keepAliveTimer = setTimeout(_keepAliveLoop, config.yahoomessenger.keepalive_interval * 1000);
}

function login(){
    logger.info("Login to YM as " + config.yahoomessenger.username + '(' + config.yahoomessenger.password + ')')
    YahooMessenger.login(config.yahoomessenger.username, config.yahoomessenger.password);
}

function logout() {
    logger.info("Logout from YM");

    clearTimeout(keepAliveTimer);

    try {
        YahooMessenger.logout();
    }
    catch(err) {
        logger.info("Error on logout: " + err.message);
    }
}

function relogin() {
    logger.info("Going to relogin");
    logout();

    logger.info("Sleeping 5 seconds before login");
    sleep.sleep(5);

    YahooMessenger.newInstance();
}

function start(_config, _logger) {
    config = _config;
    logger = _logger;

    function onReady() {
        login();
    }

    function onLoginSuccesful(data) {
        logger.info('Online on YM as ' + data.user_id + ' (' + data.firstname + ' ' + data.lastname + ')');

        if (config.yahoomessenger.status) {
            logger.info('Set status to: ' + config.yahoomessenger.status);
            YahooMessenger.setCustomAwayStatus(config.yahoomessenger.status);
        };

        broadcast(config.yahoomessenger.report_to, config.yahoomessenger.report_message);
        keepAliveLoop();
    }

    function onLoginError(data) {
        logger.error('Login error: ' + data.errorCode + ' ' + data.message);
    }

    function onBuddyAddRequest(data) {
        logger.info("Got request to add buddy from " + data.username);
        YahooMessenger.acceptAddBuddy(data.username);
    }

    function onPM(data) {
        var direction = 'IN';
        var direction_symbol = '=>';

        if (config.globals.debug == 1) {
          console.log(data);
        }

        // check duplicate message
        if (oldMessages.indexOf(data.message_id) >= 0) {
            return;
        }

        oldMessages.unshift(data.message_id);
        if (oldMessages.length > 30) {
            oldMessages = oldMessages.slice(0, 10);
        }

        partner = data.sender;
        if (partner == data.user_id) {
            partner = data.target_user;
            direction = 'OUT';
            direction_symbol = '<=';
        }

        var message = striptags(data.message).trim();

        logger.info('New ' + direction + ' message from ' + data.sender + ' to ' +  data.target_user + ': ' + message);

        if (isAdmin(data.sender)) {
            logger.info('Sender (' + data.sender + ') is an admin');
        }

        var sentdate = Date.parse(data.time);
        var strftime = require('strftime');
        sentdate = strftime('%Y-%m-%d %H:%M:%S', sentdate);

        insertMessages(
            db_connection,
            data.user_id,
            direction,
            partner,
            message,
            sentdate
        );

        broadcast(config.yahoomessenger.report_to, '@' + data.partner + ' ' +  direction_symbol + ' ' + message, partner);

        if ((direction == 'IN') && (isAdmin(partner))) {

            if (message.charAt(0) == '@') {

                target = message.split(' ', 1).join();
                target = target.slice(1);

                var messageToForward = message.replace('@' + target, '').trim();
                if (messageToForward == '') {
                    return;
                }

                logger.info('Forward to ' + target + ': ' + messageToForward);
                pm(target, '@' + partner + ': ' + messageToForward);

            }
            else if (message.charAt(0) == '+') {

                target = message.split(' ', 1).join();
                target = target.slice(1);

                var messageToForward = message.replace('+' + target, '').trim();
                if (messageToForward == '') {
                    return;
                }

                logger.info('Clean forward to ' + target + ': ' + messageToForward);
                pm(target, messageToForward);

            }
            else if (message.indexOf('!relogin') == 0) {

                broadcast(config.yahoomessenger.report_to, 'relogin requested by ' + data.sender);
                logger.info('Relogin request by pm');
                relogin();

            }
            else if (message.indexOf('!setstatus ') == 0) {

                logger.info('Set status request by pm');

                var newStatus = message.replace('!setstatus').trim();

                broadcast(config.yahoomessenger.report_to, 'Set new status requested by ' + data.sender + ': ' + newStatus);
                config.yahoomessenger.status = newStatus;
                YahooMessenger.setCustomAwayStatus(config.yahoomessenger.status);

            }
            else if (message.indexOf('!ping') == 0) {

                logger.info("Ping request by pm");
                pm(partner, 'PONG');

            }
            else if (message.indexOf('!terminate') == 0) {

                logger.info("Terminate request by pm");
                logout();
                sleep.sleep(12);

                process.exit(code=0);

            }
        }
    }

    db_connection = db.start(config.db.host, config.db.username, config.db.password, config.db.name, logger);


    YahooMessenger.newInstance();
    YahooMessenger.on('ready', onReady);
    YahooMessenger.on('loginSuccessful', onLoginSuccesful);
    YahooMessenger.on('loginError', onLoginError);
    YahooMessenger.on('buddyAddRequest', onBuddyAddRequest);
    YahooMessenger.on('pm', onPM);

    return YahooMessenger;
}

exports.start = start;
exports.broadcast = broadcast;
exports.pm = pm;
exports.logout = logout;
exports.relogin = relogin;