<commit_before>var Datastore = require('nedb'),
    inflection = require('inflection'),
    Settings = require('../settings');

var db = new Datastore({ filename: Settings.storagePath(), autoload: true });

class Bot {
    constructor(slack, logger, settings) {
        this.slack = slack;
        this.logger = logger;
        this.settings = settings;
        this.looping = false;
        this.quietLoop = true;
        this.queue = [];
        this.channels = settings.channels.map(c => c.toLowerCase());
        db.ensureIndex({ fieldName: 'ts', unique: true}, function(err) { });

        logger.info('Bot', `Connected to Slack as @${slack.self.name} on ${slack.team.name}`);
        var slackChannels = Object.keys(slack.channels)
            .map(c => slack.channels[c]);
        slackChannels = slackChannels.concat(Object.keys(slack.groups)
            .map(g => slack.groups[g])
            .map(g => {
                g.is_member = true;
                return g;
            })
        );

        var unwatchableChannels = slackChannels
            .filter(c => settings.channels.indexOf(c.name) > -1)
            .filter(c => !c.is_member)
            .map(c => c.name);
        var forgottenChannels = slackChannels
            .filter(c => c.is_member)
            .filter(c => settings.channels.indexOf(c.name) == -1)
            .map(c => c.name);
        var validChannels = settings.channels
            .filter(c => unwatchableChannels.indexOf(c) == -1 && forgottenChannels.indexOf(c) == -1);

        this.channels = validChannels;

        if(unwatchableChannels.length > 0) {
            logger.warn('Bot', `Whoa! I'm trying to watch ${inflection.inflect('', unwatchableChannels.length, 'a channel', 'channels')}${inflection.inflect('', unwatchableChannels.length, '', ' in')} which I'm not a member of: ${unwatchableChannels.join(', ')}`);
        }

        if(forgottenChannels.length > 0) {
            logger.warn('Bot', `Hey! I belong to ${inflection.inflect('an', forgottenChannels.length, null, 'some')} unwatched ${inflection.inflect('channel', forgottenChannels.length)}: ${forgottenChannels.join(', ')}`);
        }

        if(validChannels.length === 0) {
            logger.error('Bot', 'Hmm. Looks like I have nothing to watch! Nothing to do! Yay! See u later, alligator.');
            process.exit(1);
            return;
        } else {
            logger.info('Bot', `Okay, I will watch ${inflection.inflect('', validChannels.length, 'this', 'these')} ${inflection.inflect('channel', validChannels.length)}: ${validChannels.join(', ')}`);
        }

        slack
            .on('raw_message', msg => this.onRawMessage(msg))
            .on('message', msg => this.enqueue(msg));
    }

    onRawMessage(msg) {
        if(msg.type.startsWith('reaction_') || msg.type === 'group_joined') {
            this.enqueue(msg);
        }
    }

    enqueue(msg) {
        this.queue.push(msg);
        if(!this.looping) {
            this.looping = true;
            this.loop();
        }
    }

    loop() {
        var msg = this.queue.shift();
        if(!msg) {
            if(!this.quietLoop) {
                this.logger.verbose('Loopr', 'Queue is empty. Pfew! Breaking loop.');
            }
            this.looping = false;
            this.quietLoop = true;
            return;
        }
        this.quietLoop = false;
        if(!!msg.subtype) {
            msg.type = msg.subtype;
        }

        var channelCheck = (chn) => {
            if(!chn) {
                this.logger.warning('channelCheck', 'Received empty or false-y chn: ', chn);
                return false;
            }
            var channel = this.slack.getChannelGroupOrDMByID(chn);
            var exists = this.channels.indexOf(channel.name) > -1;
            this.logger.verbose('Loopr', `Checking ${channel.name} against ${this.channels.join(', ')}...`);
            if(!exists) {
                this.quietLoop = true;
            }
            this.logger.verbose('Loopr', `Result: ${exists}`);
            return exists;
        };

        switch(msg.type) {
            case 'reaction_added':
            case 'reaction_removed':
                if(!channelCheck(msg.item.channel)) {
                    break;
                }
                var delta = msg.type === 'reaction_added' ? 1 : -1,
                    reaction = msg.reaction;<commit_msg>Fix bot log level name<commit_after>var Datastore = require('nedb'),
    inflection = require('inflection'),
    Settings = require('../settings');

var db = new Datastore({ filename: Settings.storagePath(), autoload: true });

class Bot {
    constructor(slack, logger, settings) {
        this.slack = slack;
        this.logger = logger;
        this.settings = settings;
        this.looping = false;
        this.quietLoop = true;
        this.queue = [];
        this.channels = settings.channels.map(c => c.toLowerCase());
        db.ensureIndex({ fieldName: 'ts', unique: true}, function(err) { });

        logger.info('Bot', `Connected to Slack as @${slack.self.name} on ${slack.team.name}`);
        var slackChannels = Object.keys(slack.channels)
            .map(c => slack.channels[c]);
        slackChannels = slackChannels.concat(Object.keys(slack.groups)
            .map(g => slack.groups[g])
            .map(g => {
                g.is_member = true;
                return g;
            })
        );

        var unwatchableChannels = slackChannels
            .filter(c => settings.channels.indexOf(c.name) > -1)
            .filter(c => !c.is_member)
            .map(c => c.name);
        var forgottenChannels = slackChannels
            .filter(c => c.is_member)
            .filter(c => settings.channels.indexOf(c.name) == -1)
            .map(c => c.name);
        var validChannels = settings.channels
            .filter(c => unwatchableChannels.indexOf(c) == -1 && forgottenChannels.indexOf(c) == -1);

        this.channels = validChannels;

        if(unwatchableChannels.length > 0) {
            logger.warn('Bot', `Whoa! I'm trying to watch ${inflection.inflect('', unwatchableChannels.length, 'a channel', 'channels')}${inflection.inflect('', unwatchableChannels.length, '', ' in')} which I'm not a member of: ${unwatchableChannels.join(', ')}`);
        }

        if(forgottenChannels.length > 0) {
            logger.warn('Bot', `Hey! I belong to ${inflection.inflect('an', forgottenChannels.length, null, 'some')} unwatched ${inflection.inflect('channel', forgottenChannels.length)}: ${forgottenChannels.join(', ')}`);
        }

        if(validChannels.length === 0) {
            logger.error('Bot', 'Hmm. Looks like I have nothing to watch! Nothing to do! Yay! See u later, alligator.');
            process.exit(1);
            return;
        } else {
            logger.info('Bot', `Okay, I will watch ${inflection.inflect('', validChannels.length, 'this', 'these')} ${inflection.inflect('channel', validChannels.length)}: ${validChannels.join(', ')}`);
        }

        slack
            .on('raw_message', msg => this.onRawMessage(msg))
            .on('message', msg => this.enqueue(msg));
    }

    onRawMessage(msg) {
        if(msg.type.startsWith('reaction_') || msg.type === 'group_joined') {
            this.enqueue(msg);
        }
    }

    enqueue(msg) {
        this.queue.push(msg);
        if(!this.looping) {
            this.looping = true;
            this.loop();
        }
    }

    loop() {
        var msg = this.queue.shift();
        if(!msg) {
            if(!this.quietLoop) {
                this.logger.verbose('Loopr', 'Queue is empty. Pfew! Breaking loop.');
            }
            this.looping = false;
            this.quietLoop = true;
            return;
        }
        this.quietLoop = false;
        if(!!msg.subtype) {
            msg.type = msg.subtype;
        }

        var channelCheck = (chn) => {
            if(!chn) {
                this.logger.warn('channelCheck', 'Received empty or false-y chn: ', chn);
                return false;
            }
            var channel = this.slack.getChannelGroupOrDMByID(chn);
            var exists = this.channels.indexOf(channel.name) > -1;
            this.logger.verbose('Loopr', `Checking ${channel.name} against ${this.channels.join(', ')}...`);
            if(!exists) {
                this.quietLoop = true;
            }
            this.logger.verbose('Loopr', `Result: ${exists}`);
            return exists;
        };

        switch(msg.type) {
            case 'reaction_added':
            case 'reaction_removed':
                if(!channelCheck(msg.item.channel)) {
                    break;
                }
                var delta = msg.type === 'reaction_added' ? 1 : -1,
                    reaction = msg.reaction;
{'fraction_non_alphanumeric': 0.15235709405602368, 'fraction_numerical': 0.002505124117513095, 'mean_word_length': 1.9286428809603202, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 39, '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': '6915965', 'n_tokens_mistral': 2649, 'n_tokens_neox': 2565, 'n_words': 507}