<commit_before>const fs = require('fs'),
    crypto = require('crypto'),
    Long = require('long'),
    SteamTotp = require('steam-totp'),
    EventEmitter = require('events').EventEmitter;

class Bot extends EventEmitter {
    constructor(settings, servers) {
        super();

        this.settings = settings;
        this.steamReady = false;
        this.clientReady = false;
        this.busy = false;
        this.currentRequest = false;
        this.ttlTimeout = false;
        this.loggingIn = false;
        this.servers = servers;
    }

    logIn(username, password, auth, show_in_game) {
        if (this.loggingIn) return;

        this.emit('unready');
        this.loggingIn = true;
        this.steamReady = false;
        this.clientReady = false;

        if (arguments.length === 4) {
            this.username = username;
            this.password = password;
            this.auth = auth;
            this.show_in_game = show_in_game;
        }

        console.log(`Logging in ${this.username}`);

        // Prevent lingering values across login sessions by importing here
        this.Steam = require('steam');
        this.csgo = require('csgo');

        // If there is a server list, use it
        if (this.servers) this.Steam.servers = this.servers;

        // If there is a steam client, make sure it is disconnected
        if (this.steamClient) this.steamClient.disconnect();

        this.steamClient = new this.Steam.SteamClient();
        this.steamUser = new this.Steam.SteamUser(this.steamClient);
        this.steamFriends = new this.Steam.SteamFriends(this.steamClient);
        this.steamGC = new this.Steam.SteamGameCoordinator(this.steamClient, 730);
        this.csgoClient = new this.csgo.CSGOClient(this.steamUser, this.steamGC, false);

        // set up event handlers
        this.bindEventHandlers();

        this.sentryPath = `sentry/${this.username}.sentry`;

        this.loginData = {
            account_name: this.username,
            password: this.password
        };

        if (this.auth && this.auth !== '') {
            // Check if it is a shared_secret
            if (this.auth.length <= 5) this.loginData.auth_code = this.auth;
            else {
                // Generate the code from the shared_secret
                console.log(`${this.username} Generating TOTP Code from shared_secret`);
                this.loginData.two_factor_code = SteamTotp.getAuthCode(this.auth);
            }
        }

        let sentry = null;

        if (fs.existsSync(this.sentryPath)) {
            sentry = fs.readFileSync(this.sentryPath);
        }

        if (sentry && sentry.length) {
            this.loginData.sha_sentryfile = crypto.createHash('sha1').update(sentry).digest();
        }

        console.log(`${this.username} About to connect`);
        this.steamClient.connect();
    }

    bindEventHandlers() {
        this.steamClient.once('connected', () => {
            this.steamReady = true;

            console.log(`${this.username} Connected`);
            this.steamUser.logOn(this.loginData);
        });

        this.steamClient.once('error', (err) => {
            console.log(err);

            this.logIn();
        });

        this.steamClient.once('loggedOff', () => {
            console.log(`${this.username} Logged off, reconnecting!`);

            this.logIn();
        });

        this.steamClient.once('servers', (servers) => {
            console.log(`${this.username} Received servers.`);
            fs.writeFileSync('servers.json', JSON.stringify(servers, null, 2));
        });

        this.steamClient.once('sentry', (sentry) => {
            console.log(`${this.username} Received sentry.`);
            fs.writeFileSync(this.sentryPath, sentry);
        });

        this.steamUser.on('updateMachineAuth', (sentry, callback) => {
            fs.writeFileSync(this.sentryPath, sentry.bytes);

            let sha_file = crypto.createHash('sha1').update(sentry.bytes).digest();

            callback({ sha_file: sha_file });
        });

        this.steamClient.once('logOnResponse', (response) => {
            if (response.eresult == this.Steam.EResult.OK) {
                console.log(`${this.username} Log on OK`);

                if (this.show_in_game === undefined || this.show_in_game === true) {
                    this.steamFriends.setPersonaState(this.Steam.EPersonaState.Busy);
                }

                this.csgoClient.launch();
            }
            else {
                console.log(`Error logging in ${this.username}:`, response);

                let login_error_msgs = {
                    61: 'Invalid Password',
                    63: 'Account login denied due to 2nd factor authentication failure. If using email auth, an email has been sent.',
                    65: 'Account login denied due to auth code being invalid',
                    66: 'Account login denied due to 2nd factor auth failure and no mail has been sent'
                };

                if (response.eresult && login_error_msgs[response.eresult] != undefined) {
                    console.log(this.username + ': ' + login_error_msgs[response.eresult]);
                }   
            }
        });

        this.csgoClient.on('itemData', (itemData) => {
            if (this.resolve && this.currentRequest) {
                // Ensure the received itemid is the same as what we want
                let itemid = itemData.iteminfo.itemid;
                itemData.iteminfo.itemid_int = new Long(itemid.low, itemid.high, itemid.unsigned).toNumber();

                if (itemData.iteminfo.itemid != parseInt(this.currentRequest.a)) return;

                // Clear any TTL timeout
                if (this.ttlTimeout) {
                    clearInterval(this.ttlTimeout);
                    this.ttlTimeout = false;
                }

                // Figure out how long to delay until this bot isn't busy anymore
                let offset = new Date().getTime() - this.currentRequest.time;
                let delay = this.settings.request_delay - offset;

                // If we're past the request delay, don't delay
                if (delay < 0) delay = 0;

                itemData.delay = delay;
                itemData.iteminfo.s = this.currentRequest.s;
                itemData.iteminfo.a = this.currentRequest.a;
                itemData.iteminfo.d = this.currentRequest.d;
                itemData.iteminfo.m = this.currentRequest.m;

                this.resolve(itemData);
                this.resolve = false;
                this.currentRequest = false;

                setTimeout(() => {
                    // We're no longer busy (satisfied request delay)
                    this.busy = false;
                }, delay);
            }
        });
<commit_msg>MAJOR: Fixes TTL Timeout Clearing<commit_after>const fs = require('fs'),
    crypto = require('crypto'),
    Long = require('long'),
    SteamTotp = require('steam-totp'),
    EventEmitter = require('events').EventEmitter;

class Bot extends EventEmitter {
    constructor(settings, servers) {
        super();

        this.settings = settings;
        this.steamReady = false;
        this.clientReady = false;
        this.busy = false;
        this.currentRequest = false;
        this.ttlTimeout = false;
        this.loggingIn = false;
        this.servers = servers;
    }

    logIn(username, password, auth, show_in_game) {
        if (this.loggingIn) return;

        this.emit('unready');
        this.loggingIn = true;
        this.steamReady = false;
        this.clientReady = false;

        if (arguments.length === 4) {
            this.username = username;
            this.password = password;
            this.auth = auth;
            this.show_in_game = show_in_game;
        }

        console.log(`Logging in ${this.username}`);

        // Prevent lingering values across login sessions by importing here
        this.Steam = require('steam');
        this.csgo = require('csgo');

        // If there is a server list, use it
        if (this.servers) this.Steam.servers = this.servers;

        // If there is a steam client, make sure it is disconnected
        if (this.steamClient) this.steamClient.disconnect();

        this.steamClient = new this.Steam.SteamClient();
        this.steamUser = new this.Steam.SteamUser(this.steamClient);
        this.steamFriends = new this.Steam.SteamFriends(this.steamClient);
        this.steamGC = new this.Steam.SteamGameCoordinator(this.steamClient, 730);
        this.csgoClient = new this.csgo.CSGOClient(this.steamUser, this.steamGC, false);

        // set up event handlers
        this.bindEventHandlers();

        this.sentryPath = `sentry/${this.username}.sentry`;

        this.loginData = {
            account_name: this.username,
            password: <PASSWORD>
        };

        if (this.auth && this.auth !== '') {
            // Check if it is a shared_secret
            if (this.auth.length <= 5) this.loginData.auth_code = this.auth;
            else {
                // Generate the code from the shared_secret
                console.log(`${this.username} Generating TOTP Code from shared_secret`);
                this.loginData.two_factor_code = SteamTotp.getAuthCode(this.auth);
            }
        }

        let sentry = null;

        if (fs.existsSync(this.sentryPath)) {
            sentry = fs.readFileSync(this.sentryPath);
        }

        if (sentry && sentry.length) {
            this.loginData.sha_sentryfile = crypto.createHash('sha1').update(sentry).digest();
        }

        console.log(`${this.username} About to connect`);
        this.steamClient.connect();
    }

    bindEventHandlers() {
        this.steamClient.once('connected', () => {
            this.steamReady = true;

            console.log(`${this.username} Connected`);
            this.steamUser.logOn(this.loginData);
        });

        this.steamClient.once('error', (err) => {
            console.log(err);

            this.logIn();
        });

        this.steamClient.once('loggedOff', () => {
            console.log(`${this.username} Logged off, reconnecting!`);

            this.logIn();
        });

        this.steamClient.once('servers', (servers) => {
            console.log(`${this.username} Received servers.`);
            fs.writeFileSync('servers.json', JSON.stringify(servers, null, 2));
        });

        this.steamClient.once('sentry', (sentry) => {
            console.log(`${this.username} Received sentry.`);
            fs.writeFileSync(this.sentryPath, sentry);
        });

        this.steamUser.on('updateMachineAuth', (sentry, callback) => {
            fs.writeFileSync(this.sentryPath, sentry.bytes);

            let sha_file = crypto.createHash('sha1').update(sentry.bytes).digest();

            callback({ sha_file: sha_file });
        });

        this.steamClient.once('logOnResponse', (response) => {
            if (response.eresult == this.Steam.EResult.OK) {
                console.log(`${this.username} Log on OK`);

                if (this.show_in_game === undefined || this.show_in_game === true) {
                    this.steamFriends.setPersonaState(this.Steam.EPersonaState.Busy);
                }

                this.csgoClient.launch();
            }
            else {
                console.log(`Error logging in ${this.username}:`, response);

                let login_error_msgs = {
                    61: 'Invalid Password',
                    63: 'Account login denied due to 2nd factor authentication failure. If using email auth, an email has been sent.',
                    65: 'Account login denied due to auth code being invalid',
                    66: 'Account login denied due to 2nd factor auth failure and no mail has been sent'
                };

                if (response.eresult && login_error_msgs[response.eresult] != undefined) {
                    console.log(this.username + ': ' + login_error_msgs[response.eresult]);
                }   
            }
        });

        this.csgoClient.on('itemData', (itemData) => {
            if (this.resolve && this.currentRequest) {
                // Ensure the received itemid is the same as what we want
                let itemid = itemData.iteminfo.itemid;
                itemData.iteminfo.itemid_int = new Long(itemid.low, itemid.high, itemid.unsigned).toNumber();

                if (itemData.iteminfo.itemid != parseInt(this.currentRequest.a)) return;

                // Clear any TTL timeout
                if (this.ttlTimeout) {
                    clearTimeout(this.ttlTimeout);
                    this.ttlTimeout = false;
                }

                // Figure out how long to delay until this bot isn't busy anymore
                let offset = new Date().getTime() - this.currentRequest.time;
                let delay = this.settings.request_delay - offset;

                // If we're past the request delay, don't delay
                if (delay < 0) delay = 0;

                itemData.delay = delay;
                itemData.iteminfo.s = this.currentRequest.s;
                itemData.iteminfo.a = this.currentRequest.a;
                itemData.iteminfo.d = this.currentRequest.d;
                itemData.iteminfo.m = this.currentRequest.m;

                this.resolve(itemData);
                this.resolve = false;
                this.currentRequest = false;

                setTimeout(() => {
                    // We're no longer busy (satisfied request delay)
                    this.busy = false;
                }, delay);
            }
        });

{'fraction_non_alphanumeric': 0.11796600234466588, 'fraction_numerical': 0.0029308323563892145, 'mean_word_length': 1.7889252145484267, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 22, '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': '2514974', 'n_tokens_mistral': 3907, 'n_tokens_neox': 3724, 'n_words': 796}