<commit_before>var PlugAPI = require('plugapi');
var fs = require('fs');
path = require('path')
var config = require(path.resolve(__dirname, 'config.json'));
var runCount = 0;

if (config.botinfo.auth != "") {
    console.log("[INIT] Using auth key: " + config.botinfo.auth);
    runBot(false, config.botinfo.auth);
}
else {
    // @todo Set up plug-dj-login handling
}

function runBot(error, auth) {
    if(error) {
        console.log("[INIT] An error occurred: " + err);
        return;
    } 
    
    initializeModules(auth);
    
    bot.connect(config.roomName);

    bot.on('roomJoin', function(data) {

        bot.log('[INIT] Joined room:', data);

        if (config.responses.botConnect !== "") {
            bot.sendChat(config.responses.botConnect);
        }
        if (bot.getMedia() != null && config.wootSongs == 'ALL') {
            bot.woot();
        }

        bot.getUsers().forEach(function(user) { addUserToDb(user); });
        lastRpcMessage = new Date();
    });

    bot.on('chat', function(data) {
        bot.log('[CHAT]', data.from + ': ' + data.message);
        handleCommand(data);
        db.run('UPDATE USERS SET lastActive = CURRENT_TIMESTAMP WHERE userid = ?', [data.fromID]);
    });
    
    bot.on('emote', function(data) {
        bot.log('[EMTE]', data.from + ': ' + data.from + ' ' + data.message);
        handleCommand(data);
        db.run('UPDATE USERS SET lastActive = CURRENT_TIMESTAMP WHERE userid = ?', [data.fromID]);
    });
    
    bot.on('userJoin', function(data) {
        bot.log('[JOIN]', data.username);

        var newUser = false;
        var message = "";

        if (data.username != config.botinfo.botname) {
            getUserFromDb(data, function (dbUser) {

                if (dbUser == undefined) {
                    message = config.responses.welcome.newUser.replace('{username}', data.username);
                    newUser = true;
                }
                else {
                    message = config.responses.welcome.oldUser.replace('{username}', data.username);
                }

                if (newUser && message && (config.welcomeUsers == "NEW" || config.welcomeUsers == "ALL")) {
                    setTimeout(function(){ bot.sendChat(message) }, 5000);
                } else if (config.welcomeUsers == "ALL") {
                    // Don't welcome people repeatedly if they're throttling in and out of the room
                    db.get("SELECT strftime('%s', 'now')-strftime('%s', lastActive) AS 'secondsSinceLastActive', lastActive FROM USERS WHERE userid = ?", [data.id] , function (error, row) {
                        if (row != null) {
                            bot.log('[JOIN] ' + data.username + ' visited '+ row.secondsSinceLastActive + ' seconds ago (' + row.lastActive + ')');
                            if(row.secondsSinceLastActive >= 300 && message) {
                                setTimeout(function(){ bot.sendChat(message) }, 5000);
                                db.run('UPDATE USERS SET lastActive = CURRENT_TIMESTAMP WHERE userid = ?', [data.id]);
                            }
                        }
                    });
                }

                addUserToDb(data);
            });
        }
        else {
            addUserToDb(data);
        }
        
        room.users.push(data);
        
        lastRpcMessage = new Date();
    })
    
    bot.on('userLeave', function(data) {       
        bot.log('[LEAVE]', 'User left: ' + data);
        db.run('UPDATE OR IGNORE USERS SET lastSeen = CURRENT_TIMESTAMP WHERE userid = ?', [data.id]);
        lastRpcMessage = new Date();
    });
    
    bot.on('userUpdate', function(data) {
        bot.log('User update: ', data);
        lastRpcMessage = new Date();
    });
    
    bot.on('curateUpdate', function(data) {
        bot.log('[GRAB]', bot.getUsers().filter(function(user) { return user.id == data.id; })[0].username + ' grabbed this song');
        db.run('UPDATE USERS SET lastActive = CURRENT_TIMESTAMP WHERE userid = ?', [data.id]);
        lastRpcMessage = new Date();
    });
    
    bot.on('djAdvance', function(data) {
        //bot.log('djAdvance: ', JSON.stringify(data, null, 2));
        bot.log('[SONG]', data.media.author + ' - ' + data.media.title);

        // Write previous song data to DB
        // But only if the last song actually existed
        if (data.lastPlay != null) {
            db.run('INSERT OR IGNORE INTO SONGS VALUES (?, ?, ?, ?, ?, ?)', [data.lastPlay.media.id, data.lastPlay.media.title, data.lastPlay.media.format, data.lastPlay.media.author, data.lastPlay.media.cid, data.lastPlay.media.duration]);
                    
            db.run('INSERT INTO PLAYS (userid, songid, upvotes, downvotes, snags, started, listeners) VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?)',
                [data.lastPlay.dj.id,
                data.lastPlay.media.id,
                data.lastPlay.score.positive,
                data.lastPlay.score.negative,
                data.lastPlay.score.curates,
                data.lastPlay.score.listeners]);
        }

        // @todo: Add support for other settings - for now, woot if it's set on ALL
        if (data.media != null && config.wootSongs == 'ALL') {
            bot.woot();
        }

        // DOL Checks: Specific quirky bot messages (feel free to nuke)
        if (data.media.author == 'U2') {
            bot.sendChat(':boom:');
        }
        else if (data.media.author == 'Wing') {
            bot.sendChat('OH MY GOD MY EARS! :hear_no_evil:')
            bot.meh();
        }
        else if (data.media.author == 'Extreme' || data.media.title == 'Winds of Change' || data.media.title == 'Under the Bridge') {
            bot.sendChat('What is this dreck?');
        }

        // Perform automatic song metadata correction
        if (data.media != null && config.autoSuggestCorrections) {
            correctMetadata();
        }

        if (config.activeDJTimeoutMins > 0) {
            var maxIdleTime = config.activeDJTimeoutMins * 60;
            var idleDJs = [];
            var z = 0;

            waitlist = bot.getDJs().splice(1);
            waitlist.forEach(function(dj) {
                db.get("SELECT strftime('%s', 'now')-strftime('%s', lastActive) AS 'secondsSinceLastActive', strftime('%s', lastActive) AS 'lastActive', username FROM USERS WHERE userid = ?", [dj.id] , function (error, row) {
                    z++;
                    if (row != null) {
                        if(row.secondsSinceLastActive >= maxIdleTime) {
                            bot.log('[IDLE] ' + z + '. ' + row.username + ' last active '+ timeSince(row.lastActive) + ' ago');
                            idleDJs.push(row.username);
                        }
                        else {
                            bot.log('[ACTIVE] ' + z + '. ' + row.username + ' last active '+ timeSince(row.lastActive) + ' ago');
                        }
                    }

                    if (z == waitlist.length && idleDJs.length > 0) {
                        var idleDJsList = idleDJs.join(' @');
                        bot.sendChat('@' + idleDJsList + ' ' + config.responses.activeDJReminder);
                    }
                });
            });
        }
        lastRpcMessage = new Date();
    });
    
    bot.on('djUpdate', function(data) {
        //bot.log('DJ update', JSON.stringify(data, null, 2));
        lastRpcMessage = new Date();
    });
    
    bot.on('voteUpdate', function(data) {
        bot.log('[VOTE] ' + _.findWhere(bot.getUsers(), {id: data.id}).username + ' voted ' + data.vote);
        lastRpcMessage = new Date();
    });

    if (config.requireWootInLine || config.activeDJTimeoutMins > 0) {<commit_msg>* Fix bot mention doubling up since emotes now emit both chat and emote events * Fix logging for grabs and votes to use data and not crazy methods<commit_after>var PlugAPI = require('plugapi');
var fs = require('fs');
path = require('path')
var config = require(path.resolve(__dirname, 'config.json'));
var runCount = 0;

if (config.botinfo.auth != "") {
    console.log("[INIT] Using auth key: " + config.botinfo.auth);
    runBot(false, config.botinfo.auth);
}
else {
    // @todo Set up plug-dj-login handling
}

function runBot(error, auth) {
    if(error) {
        console.log("[INIT] An error occurred: " + err);
        return;
    } 
    
    initializeModules(auth);
    
    bot.connect(config.roomName);

    bot.on('roomJoin', function(data) {

        bot.log('[INIT] Joined room:', data);

        if (config.responses.botConnect !== "") {
            bot.sendChat(config.responses.botConnect);
        }
        if (bot.getMedia() != null && config.wootSongs == 'ALL') {
            bot.woot();
        }

        bot.getUsers().forEach(function(user) { addUserToDb(user); });
        lastRpcMessage = new Date();
    });

    bot.on('chat', function(data) {
        bot.log('[CHAT]', data.from + ': ' + data.message);
        handleCommand(data);
        db.run('UPDATE USERS SET lastActive = CURRENT_TIMESTAMP WHERE userid = ?', [data.fromID]);
    });
    
    bot.on('userJoin', function(data) {
        bot.log('[JOIN]', data.username);

        var newUser = false;
        var message = "";

        if (data.username != config.botinfo.botname) {
            getUserFromDb(data, function (dbUser) {

                if (dbUser == undefined) {
                    message = config.responses.welcome.newUser.replace('{username}', data.username);
                    newUser = true;
                }
                else {
                    message = config.responses.welcome.oldUser.replace('{username}', data.username);
                }

                if (newUser && message && (config.welcomeUsers == "NEW" || config.welcomeUsers == "ALL")) {
                    setTimeout(function(){ bot.sendChat(message) }, 5000);
                } else if (config.welcomeUsers == "ALL") {
                    // Don't welcome people repeatedly if they're throttling in and out of the room
                    db.get("SELECT strftime('%s', 'now')-strftime('%s', lastActive) AS 'secondsSinceLastActive', lastActive FROM USERS WHERE userid = ?", [data.id] , function (error, row) {
                        if (row != null) {
                            bot.log('[JOIN] ' + data.username + ' visited '+ row.secondsSinceLastActive + ' seconds ago (' + row.lastActive + ')');
                            if(row.secondsSinceLastActive >= 300 && message) {
                                setTimeout(function(){ bot.sendChat(message) }, 5000);
                                db.run('UPDATE USERS SET lastActive = CURRENT_TIMESTAMP WHERE userid = ?', [data.id]);
                            }
                        }
                    });
                }

                addUserToDb(data);
            });
        }
        else {
            addUserToDb(data);
        }
        
        room.users.push(data);
        
        lastRpcMessage = new Date();
    })
    
    bot.on('userLeave', function(data) {       
        bot.log('[LEAVE]', 'User left: ' + data);
        db.run('UPDATE OR IGNORE USERS SET lastSeen = CURRENT_TIMESTAMP WHERE userid = ?', [data.id]);
        lastRpcMessage = new Date();
    });
    
    bot.on('userUpdate', function(data) {
        bot.log('User update: ', data);
        lastRpcMessage = new Date();
    });
    
    bot.on('curateUpdate', function(data) {
        bot.log('[GRAB]', data + ' grabbed this song');
        db.run('UPDATE USERS SET lastActive = CURRENT_TIMESTAMP WHERE userid = ?', [data.id]);
        lastRpcMessage = new Date();
    });

    bot.on('voteUpdate', function(data) {
        bot.log('[VOTE]', data + ' voted ' + data.vote);
        lastRpcMessage = new Date();
    });
    
    bot.on('djAdvance', function(data) {
        //bot.log('djAdvance: ', JSON.stringify(data, null, 2));
        bot.log('[SONG]', data.media.author + ' - ' + data.media.title);

        // Write previous song data to DB
        // But only if the last song actually existed
        if (data.lastPlay != null) {
            db.run('INSERT OR IGNORE INTO SONGS VALUES (?, ?, ?, ?, ?, ?)', [data.lastPlay.media.id, data.lastPlay.media.title, data.lastPlay.media.format, data.lastPlay.media.author, data.lastPlay.media.cid, data.lastPlay.media.duration]);
                    
            db.run('INSERT INTO PLAYS (userid, songid, upvotes, downvotes, snags, started, listeners) VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?)',
                [data.lastPlay.dj.id,
                data.lastPlay.media.id,
                data.lastPlay.score.positive,
                data.lastPlay.score.negative,
                data.lastPlay.score.curates,
                data.lastPlay.score.listeners]);
        }

        // @todo: Add support for other settings - for now, woot if it's set on ALL
        if (data.media != null && config.wootSongs == 'ALL') {
            bot.woot();
        }

        // DOL Checks: Specific quirky bot messages (feel free to nuke)
        if (data.media.author == 'U2') {
            bot.sendChat(':boom:');
        }
        else if (data.media.author == 'Wing') {
            bot.sendChat('OH MY GOD MY EARS! :hear_no_evil:')
            bot.meh();
        }
        else if (data.media.author == 'Extreme' || data.media.title == 'Winds of Change' || data.media.title == 'Under the Bridge') {
            bot.sendChat('What is this dreck?');
        }

        // Perform automatic song metadata correction
        if (data.media != null && config.autoSuggestCorrections) {
            correctMetadata();
        }

        if (config.activeDJTimeoutMins > 0) {
            var maxIdleTime = config.activeDJTimeoutMins * 60;
            var idleDJs = [];
            var z = 0;

            waitlist = bot.getDJs().splice(1);
            waitlist.forEach(function(dj) {
                db.get("SELECT strftime('%s', 'now')-strftime('%s', lastActive) AS 'secondsSinceLastActive', strftime('%s', lastActive) AS 'lastActive', username FROM USERS WHERE userid = ?", [dj.id] , function (error, row) {
                    z++;
                    if (row != null) {
                        if(row.secondsSinceLastActive >= maxIdleTime) {
                            bot.log('[IDLE] ' + z + '. ' + row.username + ' last active '+ timeSince(row.lastActive) + ' ago');
                            idleDJs.push(row.username);
                        }
                        else {
                            bot.log('[ACTIVE] ' + z + '. ' + row.username + ' last active '+ timeSince(row.lastActive) + ' ago');
                        }
                    }

                    if (z == waitlist.length && idleDJs.length > 0) {
                        var idleDJsList = idleDJs.join(' @');
                        bot.sendChat('@' + idleDJsList + ' ' + config.responses.activeDJReminder);
                    }
                });
            });
        }
        lastRpcMessage = new Date();
    });

    bot.on('djUpdate', function(data) {
        //bot.log('DJ update', JSON.stringify(data, null, 2));
        lastRpcMessage = new Date();
    });

    if (config.requireWootInLine || config.activeDJTimeoutMins > 0) {
{'fraction_non_alphanumeric': 0.14778389719381066, 'fraction_numerical': 0.002950432730133753, 'mean_word_length': 1.7844103687477182, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3767075', 'n_tokens_mistral': 4643, 'n_tokens_neox': 4396, 'n_words': 930}