CoolFace
Apppublic

PixelPiggy/CS_float

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
bot.js261 linesDownload Raw Back to lib
1const winston = require('winston'),2    SteamUser = require('steam-user'),3    GlobalOffensive = require('globaloffensive'),4    SteamTotp = require('steam-totp'),5    EventEmitter = require('events').EventEmitter;6 7class Bot extends EventEmitter {8    /**9     * Sets the ready status and sends a 'ready' or 'unready' event if it has changed10     * @param {*|boolean} val New ready status11     */12    set ready(val) {13        const prev = this.ready;14        this.ready_ = val;15 16        if (val !== prev) {17            this.emit(val ? 'ready' : 'unready');18        }19    }20 21    /**22     * Returns the current ready status23     * @return {*|boolean} Ready status24     */25    get ready() {26        return this.ready_ || false;27    }28 29    constructor(settings) {30        super();31 32        this.settings = settings;33        this.busy = false;34 35        this.steamClient = new SteamUser(Object.assign({36            promptSteamGuardCode: false,37            enablePicsCache: true // Required to check if we own CSGO with ownsApp38        }, this.settings.steam_user));39 40        this.csgoClient = new GlobalOffensive(this.steamClient);41 42        // set up event handlers43        this.bindEventHandlers();44 45        // Variance to apply so that each bot relogins at different times46        const variance = parseInt(Math.random() * 4 * 60 * 1000);47 48        // As of 7/10/2020, GC inspect calls can timeout repeatedly for whatever reason49        setInterval(() => {50            if (this.csgoClient.haveGCSession) {51                this.relogin = true;52                this.steamClient.relog();53            }54        }, 30 * 60 * 1000 + variance);55    }56 57    logIn(username, password, auth) {58        this.ready = false;59 60        // Save these parameters if we login later61        if (arguments.length === 3) {62            this.username = username;63            this.password = password;64            this.auth = auth;65        }66 67        winston.info(`Logging in ${this.username}`);68 69        // If there is a steam client, make sure it is disconnected70        if (this.steamClient) this.steamClient.logOff();71 72        this.loginData = {73            accountName: this.username,74            password: this.password,75            rememberPassword: true,76        };77 78        if (this.auth && this.auth !== '') {79            // Check if it is a shared_secret80            if (this.auth.length <= 5) this.loginData.authCode = this.auth;81            else {82                // Generate the code from the shared_secret83                winston.debug(`${this.username} Generating TOTP Code from shared_secret`);84                this.loginData.twoFactorCode = SteamTotp.getAuthCode(this.auth);85            }86        }87 88        winston.debug(`${this.username} About to connect`);89        this.steamClient.logOn(this.loginData);90    }91 92    bindEventHandlers() {93        this.steamClient.on('error', (err) => {94            winston.error(`Error logging in ${this.username}:`, err);95 96            let login_error_msgs = {97                61: 'Invalid Password',98                63: 'Account login denied due to 2nd factor authentication failure. ' +99                    'If using email auth, an email has been sent.',100                65: 'Account login denied due to auth code being invalid',101                66: 'Account login denied due to 2nd factor auth failure and no mail has been sent'102            };103 104            if (err.eresult && login_error_msgs[err.eresult] !== undefined) {105                winston.error(this.username + ': ' + login_error_msgs[err.eresult]);106            }107 108            // Yes, checking for string errors sucks, but we have no other attributes to check109            // this error against.110            if (err.toString().includes('Proxy connection timed out')) {111                this.logIn();112            }113        });114 115        this.steamClient.on('disconnected', (eresult, msg) => {116            winston.warn(`${this.username} Logged off, reconnecting! (${eresult}, ${msg})`);117        });118 119        this.steamClient.on('loggedOn', (details, parental) => {120            winston.info(`${this.username} Log on OK`);121 122            // Fixes reconnecting to CS:GO GC since node-steam-user still assumes we're playing 730123            // and never sends the appLaunched event to node-globaloffensive124            this.steamClient.gamesPlayed([], true);125 126            if (this.relogin) {127                // Don't check ownership cache since the event isn't always emitted on relogin128                winston.info(`${this.username} Initiating GC Connection, Relogin`);129                this.steamClient.gamesPlayed([730], true);130                return;131            }132 133            // Ensure we own CSGO134            // We have to wait until app ownership is cached to safely check135            this.steamClient.once('ownershipCached', () => {136                if (!this.steamClient.ownsApp(730)) {137                    winston.info(`${this.username} doesn't own CS:GO, retrieving free license`);138 139                    // Request a license for CS:GO140                    this.steamClient.requestFreeLicense([730], (err, grantedPackages, grantedAppIDs) => {141                        winston.debug(`${this.username} Granted Packages`, grantedPackages);142                        winston.debug(`${this.username} Granted App IDs`, grantedAppIDs);143 144                        if (err) {145                            winston.error(`${this.username} Failed to obtain free CS:GO license`);146                        } else {147                            winston.info(`${this.username} Initiating GC Connection`);148                            this.steamClient.gamesPlayed([730], true);149                        }150                    });151                } else {152                    winston.info(`${this.username} Initiating GC Connection`);153                    this.steamClient.gamesPlayed([730], true);154                }155            });156        });157 158        this.csgoClient.on('inspectItemInfo', (itemData) => {159            if (this.resolve && this.currentRequest) {160                itemData = {iteminfo: itemData};161 162                // Ensure the received itemid is the same as what we want163                if (itemData.iteminfo.itemid !== this.currentRequest.a) return;164 165                // Clear any TTL timeout166                if (this.ttlTimeout) {167                    clearTimeout(this.ttlTimeout);168                    this.ttlTimeout = false;169                }170 171                // GC requires a delay between subsequent requests172                // Figure out how long to delay until this bot isn't busy anymore173                let offset = new Date().getTime() - this.currentRequest.time;174                let delay = this.settings.request_delay - offset;175 176                // If we're past the request delay, don't delay177                if (delay < 0) delay = 0;178 179                itemData.delay = delay;180                itemData.iteminfo.s = this.currentRequest.s;181                itemData.iteminfo.a = this.currentRequest.a;182                itemData.iteminfo.d = this.currentRequest.d;183                itemData.iteminfo.m = this.currentRequest.m;184 185                // If the paintseed is 0, the proto returns null, force 0186                itemData.iteminfo.paintseed = itemData.iteminfo.paintseed || 0;187 188                // paintwear -> floatvalue to match previous API version response189                itemData.iteminfo.floatvalue = itemData.iteminfo.paintwear;190                delete itemData.iteminfo.paintwear;191 192                // Backwards compatibility with previous node-globaloffensive versions193                for (const sticker of itemData.iteminfo.stickers) {194                    sticker.stickerId = sticker.sticker_id;195                    delete sticker.sticker_id;196                }197 198                this.resolve(itemData);199                this.resolve = false;200                this.currentRequest = false;201 202                setTimeout(() => {203                    // We're no longer busy (satisfied request delay)204                    this.busy = false;205                }, delay);206            }207        });208 209        this.csgoClient.on('connectedToGC', () => {210            winston.info(`${this.username} CSGO Client Ready!`);211 212            this.ready = true;213        });214 215        this.csgoClient.on('disconnectedFromGC', (reason) => {216            winston.warn(`${this.username} CSGO unready (${reason}), trying to reconnect!`);217            this.ready = false;218 219            // node-globaloffensive will automatically try to reconnect220        });221 222        this.csgoClient.on('connectionStatus', (status) => {223            winston.debug(`${this.username} GC Connection Status Update ${status}`);224        });225 226        this.csgoClient.on('debug', (msg) => {227            winston.debug(msg);228        });229    }230 231    sendFloatRequest(link) {232        return new Promise((resolve, reject) => {233            this.resolve = resolve;234            this.busy = true;235 236            const params = link.getParams();237            winston.debug(`${this.username} Fetching for ${params.a}`);238 239            this.currentRequest = {s: params.s, a: params.a, d: params.d, m: params.m, time: new Date().getTime()};240 241            if (!this.ready) {242                reject('This bot is not ready');243            }244            else {245                // The first param (owner) depends on the type of inspect link246                this.csgoClient.inspectItem(params.s !== '0' ? params.s : params.m, params.a, params.d);247            }248 249            // Set a timeout in case the GC takes too long to respond250            this.ttlTimeout = setTimeout(() => {251                // GC didn't respond in time, reset and reject252                this.busy = false;253                this.currentRequest = false;254                reject('ttl exceeded');255            }, this.settings.request_ttl);256        });257    }258}259 260module.exports = Bot;261