diff --git a/package-lock.json b/package-lock.json index 18fd5ccc9..67993a210 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,10 +18,7 @@ "@tf2autobot/tf2-schema": "^3.2.0", "@tf2autobot/tf2-sku": "^2.0.3", "@tf2autobot/tradeoffer-manager": "^2.14.0", - "async": "^3.2.4", "axios": "^0.27.2", - "bluebird": "^3.7.2", - "bluebird-global": "^1.0.1", "body-parser": "^1.20.0", "callback-queue": "^3.0.0", "change-case": "^4.1.2", @@ -41,7 +38,6 @@ "pretty-ms": "^7.0.1", "reconnecting-websocket": "^4.4.0", "retry": "^0.13.1", - "sleep-async": "^1.0.5", "socket.io-client": "^4.5.1", "steam-totp": "^2.1.2", "steam-user": "^4.24.3", @@ -56,13 +52,12 @@ }, "devDependencies": { "@babel/preset-typescript": "^7.17.12", - "@types/async": "^3.2.13", - "@types/bluebird-global": "^3.5.13", "@types/cheerio": "^0.22.31", "@types/death": "^1.1.2", "@types/express": "^4.17.13", "@types/graceful-fs": "^4.1.5", "@types/jest": "^28.1.3", + "@types/node": "^17.0.41", "@types/pluralize": "0.0.29", "@types/request": "^2.48.8", "@types/retry": "^0.12.2", @@ -2109,12 +2104,6 @@ "node": ">= 6" } }, - "node_modules/@types/async": { - "version": "3.2.13", - "resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.13.tgz", - "integrity": "sha512-7Q3awrhnvm89OzfsmqeqRQh8mh+8Pxfgq1UvSAn2nWQ5y/F3+NrbIF0RbkWq8+5dY99ozgap2b3DNBNwjLVOxw==", - "dev": true - }, "node_modules/@types/babel__core": { "version": "7.1.19", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", @@ -2156,21 +2145,6 @@ "@babel/types": "^7.3.0" } }, - "node_modules/@types/bluebird": { - "version": "3.5.36", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz", - "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", - "dev": true - }, - "node_modules/@types/bluebird-global": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bluebird-global/-/bluebird-global-3.5.13.tgz", - "integrity": "sha512-jmq47VdRYy8KPjXDlJ6zO5Ie+l5j0X2fGdSbfCS3mGdM93MTy50dh/EfltIv/QD15hCYTY+0lm/C0Bou1tPYnQ==", - "dev": true, - "dependencies": { - "@types/bluebird": "*" - } - }, "node_modules/@types/body-parser": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", @@ -2295,10 +2269,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "10.14.22", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.22.tgz", - "integrity": "sha512-9taxKC944BqoTVjE+UT3pQH0nHZlTvITwfsOZqyc+R3sfJuxaTtxWjfn1K2UlxyPcKHf0rnaXcVFrS9F9vf0bw==", - "dev": true + "version": "17.0.42", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.42.tgz", + "integrity": "sha512-Q5BPGyGKcvQgAMbsr7qEGN/kIPN6zZecYYABeTDBizOsau+2NMdSVTar9UQw21A2+JyA2KRNDYaYrPB0Rpk2oQ==" }, "node_modules/@types/pluralize": { "version": "0.0.29", @@ -3107,19 +3080,6 @@ "node": ">= 0.8.0" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/bluebird-global": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bluebird-global/-/bluebird-global-1.0.1.tgz", - "integrity": "sha512-llTREi0V3EUM150DKdMLlXN/X2QsQ/hWJDiaGnivqeDwE32I0dmivYLU9/VvhotTzvvbv7OiM6zjVXYJ2dCmKQ==", - "peerDependencies": { - "bluebird": "*" - } - }, "node_modules/bodec": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz", @@ -8993,11 +8953,6 @@ "pbts": "bin/pbts" } }, - "node_modules/protobufjs/node_modules/@types/node": { - "version": "16.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz", - "integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==" - }, "node_modules/protobufjs/node_modules/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", @@ -9578,11 +9533,6 @@ "node": ">=8" } }, - "node_modules/sleep-async": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sleep-async/-/sleep-async-1.0.5.tgz", - "integrity": "sha512-G2B+GBBshG+gSKZZeCTX5ONnF7XVUVpYP0O4QYWmXH6XIpEUfcFbWWwQKleZixg68PWEArvVEi23159F7ohlUQ==" - }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -12390,12 +12340,6 @@ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" }, - "@types/async": { - "version": "3.2.13", - "resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.13.tgz", - "integrity": "sha512-7Q3awrhnvm89OzfsmqeqRQh8mh+8Pxfgq1UvSAn2nWQ5y/F3+NrbIF0RbkWq8+5dY99ozgap2b3DNBNwjLVOxw==", - "dev": true - }, "@types/babel__core": { "version": "7.1.19", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", @@ -12437,21 +12381,6 @@ "@babel/types": "^7.3.0" } }, - "@types/bluebird": { - "version": "3.5.36", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz", - "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", - "dev": true - }, - "@types/bluebird-global": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bluebird-global/-/bluebird-global-3.5.13.tgz", - "integrity": "sha512-jmq47VdRYy8KPjXDlJ6zO5Ie+l5j0X2fGdSbfCS3mGdM93MTy50dh/EfltIv/QD15hCYTY+0lm/C0Bou1tPYnQ==", - "dev": true, - "requires": { - "@types/bluebird": "*" - } - }, "@types/body-parser": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", @@ -12576,10 +12505,9 @@ "dev": true }, "@types/node": { - "version": "10.14.22", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.22.tgz", - "integrity": "sha512-9taxKC944BqoTVjE+UT3pQH0nHZlTvITwfsOZqyc+R3sfJuxaTtxWjfn1K2UlxyPcKHf0rnaXcVFrS9F9vf0bw==", - "dev": true + "version": "17.0.42", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.42.tgz", + "integrity": "sha512-Q5BPGyGKcvQgAMbsr7qEGN/kIPN6zZecYYABeTDBizOsau+2NMdSVTar9UQw21A2+JyA2KRNDYaYrPB0Rpk2oQ==" }, "@types/pluralize": { "version": "0.0.29", @@ -13181,17 +13109,6 @@ "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", "integrity": "sha1-+WLWh+wsNpVwrnGvhDJW5tDKESk=" }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "bluebird-global": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bluebird-global/-/bluebird-global-1.0.1.tgz", - "integrity": "sha512-llTREi0V3EUM150DKdMLlXN/X2QsQ/hWJDiaGnivqeDwE32I0dmivYLU9/VvhotTzvvbv7OiM6zjVXYJ2dCmKQ==", - "requires": {} - }, "bodec": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz", @@ -17606,11 +17523,6 @@ "long": "^4.0.0" }, "dependencies": { - "@types/node": { - "version": "16.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz", - "integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==" - }, "long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", @@ -18061,11 +17973,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, - "sleep-async": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sleep-async/-/sleep-async-1.0.5.tgz", - "integrity": "sha512-G2B+GBBshG+gSKZZeCTX5ONnF7XVUVpYP0O4QYWmXH6XIpEUfcFbWWwQKleZixg68PWEArvVEi23159F7ohlUQ==" - }, "smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", diff --git a/package.json b/package.json index de91a0ec7..278ea351c 100644 --- a/package.json +++ b/package.json @@ -35,10 +35,7 @@ "@tf2autobot/tf2-schema": "^3.2.0", "@tf2autobot/tf2-sku": "^2.0.3", "@tf2autobot/tradeoffer-manager": "^2.14.0", - "async": "^3.2.4", "axios": "^0.27.2", - "bluebird": "^3.7.2", - "bluebird-global": "^1.0.1", "body-parser": "^1.20.0", "callback-queue": "^3.0.0", "change-case": "^4.1.2", @@ -58,7 +55,6 @@ "pretty-ms": "^7.0.1", "reconnecting-websocket": "^4.4.0", "retry": "^0.13.1", - "sleep-async": "^1.0.5", "socket.io-client": "^4.5.1", "steam-totp": "^2.1.2", "steam-user": "^4.24.3", @@ -73,13 +69,12 @@ }, "devDependencies": { "@babel/preset-typescript": "^7.17.12", - "@types/async": "^3.2.13", - "@types/bluebird-global": "^3.5.13", "@types/cheerio": "^0.22.31", "@types/death": "^1.1.2", "@types/express": "^4.17.13", "@types/graceful-fs": "^4.1.5", "@types/jest": "^28.1.3", + "@types/node": "^17.0.41", "@types/pluralize": "0.0.29", "@types/request": "^2.48.8", "@types/retry": "^0.12.2", diff --git a/src/app.ts b/src/app.ts index 7fcb608ef..b88bdf376 100644 --- a/src/app.ts +++ b/src/app.ts @@ -24,8 +24,6 @@ if (process.env.BOT_VERSION !== pjson.version) { process.exit(1); } -import 'bluebird-global'; - import dotenv from 'dotenv'; dotenv.config({ path: path.join(__dirname, '../.env') }); @@ -143,20 +141,17 @@ process.on('message', message => { } }); -void botManager.start(options).asCallback(err => { - if (err) { - throw err; - } - - if (options.enableHttpApi) { - void import('./classes/HttpManager').then(({ default: HttpManager }) => { +botManager + .start(options) + .then(async () => { + if (options.enableHttpApi) { + const { default: HttpManager } = await import('./classes/HttpManager'); const httpManager = new HttpManager(options); - - void httpManager.start().asCallback(err => { - if (err) { - throw err; - } - }); - }); - } -}); + await httpManager.start(); + } + }) + .catch(err => { + if (err) { + throw err; + } + }); diff --git a/src/classes/Bot.ts b/src/classes/Bot.ts index b61544c99..7e1683ed0 100644 --- a/src/classes/Bot.ts +++ b/src/classes/Bot.ts @@ -9,11 +9,11 @@ import SchemaManager, { Effect, StrangeParts } from '@tf2autobot/tf2-schema'; import BptfLogin from '@tf2autobot/bptf-login'; import TF2 from '@tf2autobot/tf2'; import dayjs, { Dayjs } from 'dayjs'; -import async from 'async'; import semver from 'semver'; import axios, { AxiosError } from 'axios'; import pluralize from 'pluralize'; -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; +import { promisify } from 'util'; import fs from 'fs'; import path from 'path'; @@ -311,22 +311,18 @@ export default class Bot { this.client.setPersona(EPersonaState.Snooze); log.debug('Removing all listings due to halt mode turned on'); - await this.listings.removeAll().asCallback(err => { - if (err) { - log.warn('Failed to remove all listings on enabling halt mode: ', err); - } - }); + await this.listings + .removeAll() + .catch((err: Error) => log.warn('Failed to remove all listings on enabling halt mode: ', err)); } async unhalt(): Promise { this.halted = false; log.debug('Recreating all listings due to halt mode turned off'); - await this.listings.redoListings().asCallback(err => { - if (err) { - log.warn('Failed to recreate all listings on disabling halt mode: ', err); - } - }); + await this.listings + .redoListings() + .catch((err: Error) => log.warn('Failed to recreate all listings on disabling halt mode: ', err)); log.debug('Setting status in Steam to "Online"'); this.client.setPersona(EPersonaState.Online); @@ -399,7 +395,7 @@ export default class Bot { [] ); - await sleepasync().Promise.sleep(1000); + await timersPromises.setTimeout(1000); if (this.isCloned() && process.env.pm_id !== undefined && canUpdateRepo) { this.messageAdmins( @@ -436,7 +432,7 @@ export default class Bot { } for (const message of messages) { - await sleepasync().Promise.sleep(1000); + await timersPromises.setTimeout(1000); this.messageAdmins('version', message, []); } } @@ -705,7 +701,7 @@ export default class Bot { }); } - start(): Promise { + async start(): Promise { let data: { loginAttempts?: number[]; pricelist?: PricesDataObject; @@ -723,10 +719,10 @@ export default class Bot { this.addListener(this.client, 'webSession', this.onWebSession.bind(this), false); this.addListener(this.client, 'steamGuard', this.onSteamGuard.bind(this), false); this.addListener(this.client, 'loginKey', this.handler.onLoginKey.bind(this.handler), false); - this.addListener(this.client, 'error', this.onError.bind(this), false); + this.addAsyncListener(this.client, 'error', this.onError.bind(this), false); this.addListener(this.community, 'sessionExpired', this.onSessionExpired.bind(this), false); - this.addListener(this.community, 'confKeyNeeded', this.onConfKeyNeeded.bind(this), false); + this.addAsyncListener(this.community, 'confKeyNeeded', this.onConfKeyNeeded.bind(this), false); this.addListener(this.manager, 'pollData', this.handler.onPollData.bind(this.handler), false); this.addListener(this.manager, 'newOffer', this.trades.onNewOffer.bind(this.trades), true); @@ -734,318 +730,246 @@ export default class Bot { this.addListener(this.manager, 'receivedOfferChanged', this.trades.onOfferChanged.bind(this.trades), true); this.addListener(this.manager, 'offerList', this.trades.onOfferList.bind(this.trades), true); - return new Promise((resolve, reject) => { - async.eachSeries( - [ - (callback): void => { - log.debug('Calling onRun'); - void this.handler.onRun().asCallback((err, v) => { - if (err) { - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(err); - } + const promisesChain = [ + async () => { + log.debug('Calling onRun'); - data = v; + data = await this.handler.onRun(); - if (data.pollData) { - log.debug('Setting poll data'); - this.manager.pollData = data.pollData; - } + if (data.pollData) { + log.debug('Setting poll data'); + this.manager.pollData = data.pollData; + } - if (data.loginAttempts) { - log.debug('Setting login attempts'); - this.setLoginAttempts = data.loginAttempts; - } + if (data.loginAttempts) { + log.debug('Setting login attempts'); + this.setLoginAttempts = data.loginAttempts; + } - if (data.blockedList) { - log.debug('Loading blocked list data'); - this.blockedList = data.blockedList; - } + if (data.blockedList) { + log.debug('Loading blocked list data'); + this.blockedList = data.blockedList; + } + }, + async () => { + log.info('Signing in to Steam...'); - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(null); - }); - }, - (callback): void => { - log.info('Signing in to Steam...'); - - let lastLoginFailed = false; - const loginResponse = (err: CustomError): void => { - if (err) { - this.handler.onLoginError(err); - if (!lastLoginFailed && err.eresult === EResult.InvalidPassword) { - lastLoginFailed = true; - // Try and sign in without login key - log.warn('Failed to sign in to Steam, retrying without login key...'); - void this.login(null).asCallback(loginResponse); - return; - } else { - log.warn('Failed to sign in to Steam: ', err); - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(err); - } - } + let lastLoginFailed = false; - log.info('Signed in to Steam!'); + const successResponse = () => { + log.info('Signed in to Steam!'); + }; - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(null); - }; + const failResponse = (err: CustomError) => { + this.handler.onLoginError(err); + log.warn('Failed to sign in to Steam: ', err); + throw err; + }; - void this.login(data.loginKey || null).asCallback(loginResponse); - }, - (callback): void => { - log.debug('Waiting for web session'); - void this.getWebSession().asCallback((err, v) => { - if (err) { - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(err); - } + await this.login(data.loginKey || null) + .then(successResponse) + .catch(async (err: CustomError) => { + if (!lastLoginFailed && err.eresult === EResult.InvalidPassword) { + this.handler.onLoginError(err); + lastLoginFailed = true; + // Try and sign in without login key + log.warn('Failed to sign in to Steam, retrying without login key...'); + await this.login(null).then(successResponse).catch(failResponse); + } else { + failResponse(err); + } + }); + }, + async () => { + log.debug('Waiting for web session'); + cookies = await this.getWebSession(); + this.bptf.setCookies(cookies); + }, + async () => { + if (this.options.bptfApiKey && this.options.bptfAccessToken) return; - cookies = v; - this.bptf.setCookies(cookies); + log.warn('You have not included the backpack.tf API key or access token in the environment variables'); - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(null); - }); - }, - (callback): void => { - if (this.options.bptfApiKey && this.options.bptfAccessToken) { - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(null); - } + await this.getBptfAPICredentials; + }, + async () => { + log.info('Getting Steam API key...'); + await this.setCookies(cookies); + }, + async () => { + const banned = await this.checkAdminBanned(); + if (banned) throw new Error('Not allowed'); - log.warn( - 'You have not included the backpack.tf API key or access token in the environment variables' - ); - void this.getBptfAPICredentials.asCallback(err => { - if (err) { - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(err); - } + this.periodicCheck(); + }, + async () => { + this.schemaManager = new SchemaManager({ + apiKey: this.manager.apiKey, + updateTime: 24 * 60 * 60 * 1000 + }); - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(null); - }); - }, - (callback): void => { - log.info('Getting Steam API key...'); - void this.setCookies(cookies).asCallback(callback); - }, - (callback): void => { - void this.checkAdminBanned() - .then(banned => { - if (banned) { - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(new Error('Not allowed')); - } + log.info('Getting TF2 schema...'); + await this.initializeSchema(); + }, + () => { + log.info('Setting pricelist and inventory...'); - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(null); - }) - .catch(err => { - if (err) { - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(err); - } - }); + this.pricelist = new Pricelist(this.priceSource, this.schema, this.options, this); + this.pricelist.init(); - this.periodicCheck(); - }, - (callback): void => { - this.schemaManager = new SchemaManager({ - apiKey: this.manager.apiKey, - updateTime: 24 * 60 * 60 * 1000 - }); + this.addListener( + this.pricelist, + 'pricelist', + // eslint-disable-next-line @typescript-eslint/no-misused-promises + this.handler.onPricelist.bind(this.handler), + false + ); + this.addListener(this.pricelist, 'price', this.handler.onPriceChange.bind(this.handler), true); - log.info('Getting TF2 schema...'); - void this.initializeSchema().asCallback(callback); - }, - (callback): void => { - log.info('Setting properties, inventory, etc...'); - this.pricelist = new Pricelist(this.priceSource, this.schema, this.options, this); - this.pricelist.init(); - this.inventoryManager = new InventoryManager(this.pricelist); - this.userID = this.bptf._getUserID(); - - this.listingManager = new ListingManager({ - token: this.options.bptfAccessToken, - userID: this.userID, - userAgent: - 'TF2Autobot' + - (this.options.useragentHeaderCustom !== '' - ? ` - ${this.options.useragentHeaderCustom}` - : ' - Run your own bot for free'), - schema: this.schema - }); + this.setProperties(); + }, + async () => { + log.debug('Initializing inventory...'); + this.inventoryManager = new InventoryManager(this.pricelist); + + // only call this here, and in Commands/Options + Inventory.setOptions(this.schema.paints, this.strangeParts, this.options.highValue); + + this.inventoryManager.setInventory = new Inventory( + this.client.steamID, + this.manager, + this.schema, + this.options, + this.strangeParts, + 'our' + ); + await this.inventoryManager.getInventory.fetch(); + }, + async () => { + log.debug('Initializing bptf-listings...'); + + this.userID = this.bptf._getUserID(); + + this.listingManager = new ListingManager({ + token: this.options.bptfAccessToken, + userID: this.userID, + userAgent: + 'TF2Autobot' + + (this.options.useragentHeaderCustom !== '' + ? ` - ${this.options.useragentHeaderCustom}` + : ' - Run your own bot for free'), + schema: this.schema, + steamid: this.client.steamID.getSteamID64() + }); - this.addListener(this.listingManager, 'pulse', this.handler.onUserAgent.bind(this), true); - this.addListener( - this.listingManager, - 'createListingsSuccessful', - this.handler.onCreateListingsSuccessful.bind(this), - true - ); - this.addListener( - this.listingManager, - 'updateListingsSuccessful', - this.handler.onUpdateListingsSuccessful.bind(this), - true - ); - this.addListener( - this.listingManager, - 'deleteListingsSuccessful', - this.handler.onDeleteListingsSuccessful.bind(this), - true - ); - this.addListener( - this.listingManager, - 'deleteArchivedListingSuccessful', - this.handler.onDeleteArchivedListingSuccessful.bind(this), - true - ); - this.addListener( - this.listingManager, - 'createListingsError', - this.handler.onCreateListingsError.bind(this), - true - ); - this.addListener( - this.listingManager, - 'updateListingsError', - this.handler.onUpdateListingsError.bind(this), - true - ); - this.addListener( - this.listingManager, - 'deleteListingsError', - this.handler.onDeleteListingsError.bind(this), - true - ); - this.addListener( - this.listingManager, - 'deleteArchivedListingError', - this.handler.onDeleteArchivedListingError.bind(this), - true - ); + this.addListener(this.listingManager, 'pulse', this.handler.onUserAgent.bind(this), true); + this.addListener( + this.listingManager, + 'createListingsSuccessful', + this.handler.onCreateListingsSuccessful.bind(this), + true + ); + this.addListener( + this.listingManager, + 'updateListingsSuccessful', + this.handler.onUpdateListingsSuccessful.bind(this), + true + ); + this.addListener( + this.listingManager, + 'deleteListingsSuccessful', + this.handler.onDeleteListingsSuccessful.bind(this), + true + ); + this.addListener( + this.listingManager, + 'deleteArchivedListingSuccessful', + this.handler.onDeleteArchivedListingSuccessful.bind(this), + true + ); + this.addListener( + this.listingManager, + 'createListingsError', + this.handler.onCreateListingsError.bind(this), + true + ); + this.addListener( + this.listingManager, + 'updateListingsError', + this.handler.onUpdateListingsError.bind(this), + true + ); + this.addListener( + this.listingManager, + 'deleteListingsError', + this.handler.onDeleteListingsError.bind(this), + true + ); + this.addListener( + this.listingManager, + 'deleteArchivedListingError', + this.handler.onDeleteArchivedListingError.bind(this), + true + ); + await promisify(this.listingManager.init.bind(this.listingManager))(); + }, + async () => { + if (this.options.skipUpdateProfileSettings) return; - this.addListener( - this.pricelist, - 'pricelist', - // eslint-disable-next-line @typescript-eslint/no-misused-promises - this.handler.onPricelist.bind(this.handler), - false - ); - this.addListener(this.pricelist, 'price', this.handler.onPriceChange.bind(this.handler), true); + log.debug('Updating profile settings...'); - this.setProperties(); + await promisify(this.community.profileSettings.bind(this.community))({ + profile: 3, + inventory: 3, + inventoryGifts: false + }); + }, + async () => { + log.info('Setting up pricelist...'); - // only call this here, and in Commands/Options - Inventory.setOptions(this.schema.paints, this.strangeParts, this.options.highValue); + const pricelist = Array.isArray(data.pricelist) + ? (data.pricelist.reduce((buff: Record, e: EntryData) => { + buff[e.sku] = e; + return buff; + }, {}) as PricesDataObject) + : data.pricelist || {}; - this.inventoryManager.setInventory = new Inventory( - this.client.steamID, - this.manager, - this.schema, - this.options, - this.strangeParts, - 'our' - ); + await this.pricelist.setPricelist(pricelist, this); + }, + async () => { + log.debug('Getting max friends...'); + await this.friends.getMaxFriends; + }, + async () => { + log.debug('Creating listings...'); + await this.listings.redoListings(); + } + ]; - /* eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ - return callback(null); - }, - (callback): void => { - log.info('Initializing inventory, bptf-listings, and profile settings'); - async.parallel( - [ - (callback): void => { - log.debug('Getting inventory...'); - void this.inventoryManager.getInventory.fetch().asCallback(callback); - }, - (callback): void => { - log.debug('Initializing bptf-listings...'); - this.listingManager.token = this.options.bptfAccessToken; - this.listingManager.steamid = this.client.steamID; - - this.listingManager.init(callback); - }, - (callback): void => { - if (this.options.skipUpdateProfileSettings) { - return callback(null); - } - - log.debug('Updating profile settings...'); - - this.community.profileSettings( - { - profile: 3, - inventory: 3, - inventoryGifts: false - }, - callback - ); - } - ], - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - callback - ); - }, - (callback: (err?) => void): void => { - log.info('Setting up pricelist...'); - - const pricelist = Array.isArray(data.pricelist) - ? (data.pricelist.reduce((buff: Record, e: EntryData) => { - buff[e.sku] = e; - return buff; - }, {}) as PricesDataObject) - : data.pricelist || {}; - - this.pricelist - .setPricelist(pricelist, this) - .then(() => { - callback(null); - }) - .catch(err => { - callback(err); - }); - }, - (callback): void => { - log.debug('Getting max friends...'); - void this.friends.getMaxFriends.asCallback(callback); - }, - (callback): void => { - log.debug('Creating listings...'); - void this.listings.redoListings().asCallback(callback); - } - ], - (item, callback) => { - if (this.botManager.isStopping) { - // Shutdown is requested, break out of the startup process - return resolve(); - } + let promise = Promise.resolve(); - item(callback); - }, - err => { - if (err) { - return reject(err); - } + return new Promise((resolve, reject) => { + const checkIfStopping = () => { + if (this.botManager.isStopping) return reject(); + }; - if (this.botManager.isStopping) { - // Shutdown is requested, break out of the startup process - return resolve(); - } + for (const promiseToChain of promisesChain) { + promise = promise.then(promiseToChain).then(checkIfStopping); + } + promise + .then(() => { this.manager.pollInterval = 60 * 1000; this.setReady = true; this.handler.onReady(); this.manager.doPoll(); this.startVersionChecker(); - return resolve(); - } - ); + resolve(); + }) + .catch(err => { + reject(err); + }); }); } @@ -1076,7 +1000,7 @@ export default class Bot { }, 24 * 60 * 60 * 1000); } - setCookies(cookies: string[]): Promise { + async setCookies(cookies: string[]): Promise { this.community.setCookies(cookies); if (this.isReady) { @@ -1085,15 +1009,7 @@ export default class Bot { this.listingManager.setUserID(this.userID); } - return new Promise((resolve, reject) => { - this.manager.setCookies(cookies, err => { - if (err) { - return reject(err); - } - - resolve(); - }); - }); + await promisify(this.manager.setCookies.bind(this.manager))(cookies); } getWebSession(eventOnly = false): Promise { @@ -1358,15 +1274,17 @@ export default class Bot { if (this.client.steamID) this.client.webLogOn(); } - private onConfKeyNeeded(tag: string, callback: (err: Error | null, time: number, confKey: string) => void): void { + private async onConfKeyNeeded( + tag: string, + callback: (err: Error | null, time: number, confKey: string) => void + ): Promise { log.debug('Conf key needed'); - void this.getTimeOffset.asCallback((err, offset) => { - const time = SteamTotp.time(offset); - const confKey = SteamTotp.getConfirmationKey(this.options.steamIdentitySecret, time, tag); + const offset = await this.getTimeOffset; + const time = SteamTotp.time(offset); + const confKey = SteamTotp.getConfirmationKey(this.options.steamIdentitySecret, time, tag); - return callback(null, time, confKey); - }); + callback(null, time, confKey); } private onSteamGuard(domain: string, callback: (authCode: string) => void, lastCodeWrong: boolean): void { @@ -1388,7 +1306,8 @@ export default class Bot { this.handler.onLoginThrottle(wait); } - void Promise.delay(wait) + void timersPromises + .setTimeout(wait) .then(this.generateAuthCode.bind(this)) .then(authCode => { this.newLoginAttempt(); @@ -1397,7 +1316,7 @@ export default class Bot { }); } - private onError(err: CustomError): void { + private async onError(err: CustomError): Promise { if (err.eresult === EResult.LoggedInElsewhere) { log.warn('Signed in elsewhere, stopping the bot...'); this.botManager.stop(err, false, true); @@ -1412,11 +1331,7 @@ export default class Bot { log.warn('Login session replaced, relogging...'); - void this.login().asCallback(err => { - if (err) { - throw err; - } - }); + await this.login(); } else { throw err; } diff --git a/src/classes/BotManager.ts b/src/classes/BotManager.ts index ac9d57414..7f84b33f9 100644 --- a/src/classes/BotManager.ts +++ b/src/classes/BotManager.ts @@ -1,4 +1,3 @@ -import async from 'async'; import SchemaManager from '@tf2autobot/tf2-schema'; import pm2 from 'pm2'; import Bot from './Bot'; @@ -54,54 +53,35 @@ export default class BotManager { return this.bot !== null && this.bot.isReady; } - start(options: Options): Promise { - return new Promise((resolve, reject) => { - REQUIRED_OPTS.forEach(optName => { - if (!process.env[optName] && !options[camelCase(optName)]) { - return reject(new Error(`Missing required environment variable "${optName}"`)); - } - }); - - async.eachSeries( - [ - (callback): void => { - log.debug('Connecting to PM2...'); - void this.connectToPM2().asCallback(callback); - }, - (callback): void => { - log.info('Starting bot...'); - this.pricer.init(options.enableSocket); - this.bot = new Bot(this, options, this.pricer); - - void this.bot.start().asCallback(callback); - } - ], - (item, callback) => { - if (this.isStopping) { - // Shutdown is requested, stop the bot - return this.stop(null, false, false); - } - - item(callback); - }, - err => { - if (err) { - return reject(err); - } - - if (this.isStopping) { - // Shutdown is requested, stop the bot - return this.stop(null, false, false); - } - - this.pricer.connect(this.bot?.options.enableSocket); - - this.schemaManager = this.bot.schemaManager; - - return resolve(); - } - ); + async start(options: Options): Promise { + REQUIRED_OPTS.forEach(optName => { + if (!process.env[optName] && !options[camelCase(optName)]) { + throw new Error(`Missing required environment variable "${optName}"`); + } }); + + try { + log.debug('Connecting to PM2...'); + await this.connectToPM2(); + + log.info('Starting bot...'); + this.pricer.init(options.enableSocket); + this.bot = new Bot(this, options, this.pricer); + + await this.bot.start(); + + this.pricer.connect(this.bot?.options.enableSocket); + + this.schemaManager = this.bot.schemaManager; + } catch (err) { + if (this.isStopping) { + return Promise.resolve(this.stop(null, false, false)); + } + + if (err) { + throw err; + } + } } stop(err: Error | null, checkIfReady = true, rudely = false): void { diff --git a/src/classes/Carts/AdminCart.ts b/src/classes/Carts/AdminCart.ts index 638e597ec..c359d4605 100644 --- a/src/classes/Carts/AdminCart.ts +++ b/src/classes/Carts/AdminCart.ts @@ -122,74 +122,76 @@ export default class AdminCart extends Cart { 'admin' ); - void theirInventory.fetch().asCallback(err => { - if (err) { - log.error(`Failed to load admin inventories (${this.partner.getSteamID64()}): `, err); - return reject( - 'Failed to load your inventory, Steam might be down. ' + - 'Please try again later. If you have your profile/inventory set to private, please set it to public and try again.' - ); - } - - // Add their items + void theirInventory + .fetch() + .then(() => { + // Add their items + + for (const sku in this.their) { + if (!Object.prototype.hasOwnProperty.call(this.their, sku)) { + continue; + } - for (const sku in this.their) { - if (!Object.prototype.hasOwnProperty.call(this.their, sku)) { - continue; - } + let amount = this.getTheirCount(sku); + const theirAssetids = theirInventory.findBySKU(sku, true); + const theirAssetidsCount = theirAssetids.length; + + if (amount > theirAssetidsCount) { + amount = theirAssetidsCount; + // Remove the item from the cart + this.removeTheirItem(sku); + + if (theirAssetidsCount === 0) { + alteredMessages.push( + "you don't have any " + + pluralize(this.bot.schema.getName(SKU.fromString(sku), false)) + ); + } else { + alteredMessages.push( + 'you only have ' + + pluralize( + this.bot.schema.getName(SKU.fromString(sku), false), + theirAssetidsCount, + true + ) + ); + + // Add the max amount to the offer substract current added amount + this.addTheirItem( + sku, + this.their[sku] ? theirAssetidsCount - this.their[sku] : theirAssetidsCount + ); + } + } - let amount = this.getTheirCount(sku); - const theirAssetids = theirInventory.findBySKU(sku, true); - const theirAssetidsCount = theirAssetids.length; - - if (amount > theirAssetidsCount) { - amount = theirAssetidsCount; - // Remove the item from the cart - this.removeTheirItem(sku); - - if (theirAssetidsCount === 0) { - alteredMessages.push( - "you don't have any " + pluralize(this.bot.schema.getName(SKU.fromString(sku), false)) - ); - } else { - alteredMessages.push( - 'you only have ' + - pluralize( - this.bot.schema.getName(SKU.fromString(sku), false), - theirAssetidsCount, - true - ) - ); - - // Add the max amount to the offer substract current added amount - this.addTheirItem( - sku, - this.their[sku] ? theirAssetidsCount - this.their[sku] : theirAssetidsCount - ); + for (let i = 0; i < amount; i++) { + offer.addTheirItem({ + appid: 440, + contextid: '2', + assetid: theirAssetids[i] + }); } } - for (let i = 0; i < amount; i++) { - offer.addTheirItem({ - appid: 440, - contextid: '2', - assetid: theirAssetids[i] - }); - } - } + offer.data('dict', { our: this.our, their: this.their }); - offer.data('dict', { our: this.our, their: this.their }); - - this.offer = offer; + this.offer = offer; - theirInventory.clearFetch(); + theirInventory.clearFetch(); - const timeTaken = Date.now() - start; - offer.data('constructOfferTime', timeTaken); - log.debug(`Constructing offer took ${timeTaken} ms`); + const timeTaken = Date.now() - start; + offer.data('constructOfferTime', timeTaken); + log.debug(`Constructing offer took ${timeTaken} ms`); - return resolve(alteredMessages.length === 0 ? undefined : alteredMessages.join(', ')); - }); + return resolve(alteredMessages.length === 0 ? undefined : alteredMessages.join(', ')); + }) + .catch((err: Error) => { + log.error(`Failed to load admin inventories (${this.partner.getSteamID64()}): `, err); + return reject( + 'Failed to load your inventory, Steam might be down. ' + + 'Please try again later. If you have your profile/inventory set to private, please set it to public and try again.' + ); + }); }); } } diff --git a/src/classes/Carts/CartQueue.ts b/src/classes/Carts/CartQueue.ts index 1e0d7c83c..f3abfdb88 100644 --- a/src/classes/Carts/CartQueue.ts +++ b/src/classes/Carts/CartQueue.ts @@ -240,7 +240,7 @@ export default class CartQueue { log.debug('Sending offer...'); return cart.sendOffer(); }) - .then(status => { + .then(async status => { log.debug('Sent offer'); if (status === 'pending') { const sendNotification = isDonating @@ -260,7 +260,10 @@ export default class CartQueue { log.debug('Accepting mobile confirmation...'); // Wait for confirmation to be accepted - return this.bot.trades.acceptConfirmation(cart.getOffer).reflect(); + await this.bot.trades.acceptConfirmation(cart.getOffer).catch(() => { + return; + }); + return; } }) .catch(err => { diff --git a/src/classes/Carts/UserCart.ts b/src/classes/Carts/UserCart.ts index 751c74ad5..57efce730 100644 --- a/src/classes/Carts/UserCart.ts +++ b/src/classes/Carts/UserCart.ts @@ -1,7 +1,6 @@ import pluralize from 'pluralize'; import SKU from '@tf2autobot/tf2-sku'; import Currencies from '@tf2autobot/tf2-currencies'; -import async from 'async'; import { ItemsDict, OurTheirItemsDict, Prices } from '@tf2autobot/tradeoffer-manager'; import Cart from './Cart'; import Inventory, { getSkuAmountCanTrade, DictItem } from '../Inventory'; @@ -78,20 +77,15 @@ export default class UserCart extends Cart { if (this.bot.handler.dupeCheckEnabled && assetidsToCheck.length > 0) { const inventory = new TF2Inventory(this.partner, this.bot.manager); - const requests = assetidsToCheck.map(assetid => { - return (callback: (err: Error | null, result: boolean | null) => void): void => { - log.debug(`Dupe checking ${assetid}...`); - void Promise.resolve(inventory.isDuped(assetid, this.bot.userID)).asCallback((err, result) => { - log.debug(`Dupe check for ${assetid} done`); - callback(err as Error, result); - }); - }; + const requests = assetidsToCheck.map(async (assetid): Promise => { + log.debug(`Dupe checking ${assetid}...`); + const result = await inventory.isDuped(assetid, this.bot.userID); + log.debug(`Dupe check for ${assetid} done`); + return result; }); try { - const result: (boolean | null)[] = await Promise.fromCallback(callback => { - async.series(requests, callback); - }); + const result: (boolean | null)[] = await Promise.all(requests); log.info(`Got result from dupe checks on ${assetidsToCheck.join(', ')}`, { result: result }); diff --git a/src/classes/Commands/Commands.ts b/src/classes/Commands/Commands.ts index 26292bed2..9b5117960 100644 --- a/src/classes/Commands/Commands.ts +++ b/src/classes/Commands/Commands.ts @@ -3,6 +3,7 @@ import SKU from '@tf2autobot/tf2-sku'; import pluralize from 'pluralize'; import Currencies from '@tf2autobot/tf2-currencies'; import dayjs from 'dayjs'; +import { promisify } from 'util'; import * as c from './sub-classes/export'; import { removeLinkProtocol, getItemFromParams, getItemAndAmount } from './functions/utils'; @@ -722,37 +723,38 @@ export default class Commands { ); } - void this.bot.trades.getOffer(activeOffer).asCallback((err, offer) => { - if (err || !offer) { + void this.bot.trades + .getOffer(activeOffer) + .then(offer => { + if (!offer) throw new Error('Offer might already be canceled'); + offer.data('canceledByUser', true); + + void promisify(offer.cancel.bind(offer))() + .then(() => { + this.bot.sendMessage( + steamID, + `✅ Offer sent (${offer.id}) has been successfully cancelled.` + ); + }) + .catch((err: Error) => { + // Only react to error, if the offer is canceled then the user + // will get an alert from the onTradeOfferChanged handler + + log.warn('Error while trying to cancel an offer: ', err); + return this.bot.sendMessage( + steamID, + `❌ Ohh nooooes! Something went wrong while trying to cancel the offer: ${err.message}` + ); + }); + }) + .catch((err: Error) => { const errStringify = JSON.stringify(err); - const errMessage = errStringify === '' ? (err as Error)?.message : errStringify; + const errMessage = errStringify === '' ? err?.message : errStringify; return this.bot.sendMessage( steamID, - `❌ Ohh nooooes! Something went wrong while trying to get the offer: ${errMessage}` + - (!offer ? ` (or the offer might already be canceled)` : '') - ); - } - - offer.data('canceledByUser', true); - - offer.cancel(err => { - // Only react to error, if the offer is canceled then the user - // will get an alert from the onTradeOfferChanged handler - - if (err) { - log.warn('Error while trying to cancel an offer: ', err); - return this.bot.sendMessage( - steamID, - `❌ Ohh nooooes! Something went wrong while trying to cancel the offer: ${err.message}` - ); - } - - return this.bot.sendMessage( - steamID, - `✅ Offer sent (${offer.id}) has been successfully cancelled.` + `❌ Ohh nooooes! Something went wrong while trying to get the offer: ${errMessage}` ); }); - }); } } diff --git a/src/classes/Commands/sub-classes/Help.ts b/src/classes/Commands/sub-classes/Help.ts index 2fe6ec249..b293f9def 100644 --- a/src/classes/Commands/sub-classes/Help.ts +++ b/src/classes/Commands/sub-classes/Help.ts @@ -1,5 +1,5 @@ import SteamID from 'steamid'; -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; import Bot from '../../Bot'; export default class HelpCommands { @@ -48,7 +48,7 @@ export default class HelpCommands { ); if (isAdmin) { - await sleepasync().Promise.sleep(2000); + await timersPromises.setTimeout(2000); this.bot.sendMessage( steamID, '.\n✨=== Pricelist manager ===✨\n- ' + @@ -71,7 +71,7 @@ export default class HelpCommands { ].join('\n- ') ); - await sleepasync().Promise.sleep(2000); + await timersPromises.setTimeout(2000); this.bot.sendMessage( steamID, '.\n✨=== Bot manager ===✨\n- ' + @@ -103,7 +103,7 @@ export default class HelpCommands { ].join('\n- ') ); - await sleepasync().Promise.sleep(2000); + await timersPromises.setTimeout(2000); this.bot.sendMessage( steamID, '.\n✨=== Crafting ===✨\n- ' + @@ -113,7 +113,7 @@ export default class HelpCommands { ].join('\n- ') ); - await sleepasync().Promise.sleep(2000); + await timersPromises.setTimeout(2000); this.bot.sendMessage( steamID, '.\n✨=== Bot status ===✨\n- ' + @@ -126,7 +126,7 @@ export default class HelpCommands { ].join('\n- ') ); - await sleepasync().Promise.sleep(2000); + await timersPromises.setTimeout(2000); this.bot.sendMessage( steamID, '.\n✨=== Manual review ===✨\n- ' + @@ -141,7 +141,7 @@ export default class HelpCommands { ].join('\n- ') ); - await sleepasync().Promise.sleep(2000); + await timersPromises.setTimeout(2000); this.bot.sendMessage( steamID, '.\n✨=== Request ===✨\n- ' + @@ -158,7 +158,7 @@ export default class HelpCommands { ].join('\n- ') ); - await sleepasync().Promise.sleep(2000); + await timersPromises.setTimeout(2000); this.bot.sendMessage( steamID, '.\n✨=== Configuration manager (options.json) ===✨\n- ' + @@ -169,7 +169,7 @@ export default class HelpCommands { ].join('\n- ') ); - await sleepasync().Promise.sleep(2000); + await timersPromises.setTimeout(2000); this.bot.sendMessage( steamID, '.\n✨=== Misc ===✨\n- ' + diff --git a/src/classes/Commands/sub-classes/Manager.ts b/src/classes/Commands/sub-classes/Manager.ts index d3c4c9915..86ad516b5 100644 --- a/src/classes/Commands/sub-classes/Manager.ts +++ b/src/classes/Commands/sub-classes/Manager.ts @@ -4,9 +4,9 @@ import pluralize from 'pluralize'; import Currencies from '@tf2autobot/tf2-currencies'; import { Listing } from '@tf2autobot/bptf-listings'; import validUrl from 'valid-url'; +import * as timersPromises from 'timers/promises'; import path from 'path'; import child from 'child_process'; -import sleepasync from 'sleep-async'; import dayjs from 'dayjs'; import { EPersonaState } from 'steam-user'; import { EFriendRelationship } from 'steam-user'; @@ -311,7 +311,7 @@ export default class ManagerCommands { this.bot.sendMessage(steamID, toSend.slice(i * limit, last ? toSendCount : (i + 1) * limit).join('\n')); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); } this.isSendingBlockedList = false; @@ -417,7 +417,7 @@ export default class ManagerCommands { this.bot.client.removeFriend(steamid); // Prevent Steam from detecting the bot as spamming - await sleepasync().Promise.sleep(5000); + await timersPromises.setTimeout(5000); } this.isClearingFriends = false; diff --git a/src/classes/Commands/sub-classes/Misc.ts b/src/classes/Commands/sub-classes/Misc.ts index a3418ef36..ec34e3288 100644 --- a/src/classes/Commands/sub-classes/Misc.ts +++ b/src/classes/Commands/sub-classes/Misc.ts @@ -1,7 +1,7 @@ import SteamID from 'steamid'; import SKU from '@tf2autobot/tf2-sku'; import pluralize from 'pluralize'; -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; import { removeLinkProtocol } from '../functions/utils'; import CommandParser from '../../CommandParser'; import Bot from '../../Bot'; @@ -244,7 +244,7 @@ export default class MiscCommands { this.bot.sendMessage(steamID, weaponStock.slice(i15, last ? firstOrLast : (i + 1) * 15).join('\n')); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); } return; diff --git a/src/classes/Commands/sub-classes/Options.ts b/src/classes/Commands/sub-classes/Options.ts index 9a6d98d2d..2bdcc9d40 100644 --- a/src/classes/Commands/sub-classes/Options.ts +++ b/src/classes/Commands/sub-classes/Options.ts @@ -1,6 +1,6 @@ import SteamID from 'steamid'; import { promises as fsp } from 'fs'; -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; import { removeLinkProtocol } from '../functions/utils'; import Bot from '../../Bot'; import Inventory from '../../Inventory'; @@ -93,7 +93,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); const ct = webhook.customText; this.bot.sendMessage( steamID, @@ -112,7 +112,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -129,7 +129,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -148,7 +148,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -184,7 +184,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -199,7 +199,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -214,7 +214,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -248,7 +248,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -264,7 +264,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -281,7 +281,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -307,7 +307,7 @@ export default class OptionsCommands { obj[webhookKeys[j]] = webhook[webhookKeys[j] as DiscordWebhookKeys]; this.bot.sendMessage(steamID, `/code ${JSON.stringify({ discordWebhook: obj }, null, 2)}`); - await sleepasync().Promise.sleep(2000); + await timersPromises.setTimeout(2000); } */ @@ -328,7 +328,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -342,7 +342,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -357,7 +357,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -372,7 +372,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -405,7 +405,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -419,7 +419,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -433,7 +433,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -467,7 +467,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -482,7 +482,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -497,7 +497,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -512,7 +512,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -526,7 +526,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -540,7 +540,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -554,7 +554,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -568,7 +568,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -583,7 +583,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -598,7 +598,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -613,7 +613,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -628,7 +628,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -643,7 +643,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -673,7 +673,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -687,7 +687,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage( steamID, `/code ${JSON.stringify( @@ -701,7 +701,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); const paints = webhook.painted; const paintedKeys = Object.keys(paints); const paintedKeysCount = paintedKeys.length; @@ -737,7 +737,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); } } @@ -776,7 +776,7 @@ export default class OptionsCommands { )}` ); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); } } } else { diff --git a/src/classes/Commands/sub-classes/PricelistManager.ts b/src/classes/Commands/sub-classes/PricelistManager.ts index e9c37dafa..645f1eea9 100644 --- a/src/classes/Commands/sub-classes/PricelistManager.ts +++ b/src/classes/Commands/sub-classes/PricelistManager.ts @@ -6,7 +6,7 @@ import SKU from '@tf2autobot/tf2-sku'; import Currencies from '@tf2autobot/tf2-currencies'; import pluralize from 'pluralize'; import dayjs from 'dayjs'; -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; import { UnknownDictionary, UnknownDictionaryKnownValues } from '../../../types/common'; import { removeLinkProtocol, getItemFromParams } from '../functions/utils'; import Bot from '../../Bot'; @@ -400,7 +400,7 @@ export default class PricelistManagerCommands { bot.sendMessage(steamID, errorMessage.slice(i10, last ? firstOrLast : (i + 1) * limit).join('\n')); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); } } @@ -1405,7 +1405,7 @@ export default class PricelistManagerCommands { bot.sendMessage(steamID, errorMessage.slice(i10, last ? firstOrLast : (i + 1) * limit).join('\n')); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); } } @@ -1607,7 +1607,7 @@ export default class PricelistManagerCommands { if (params.withgroup || params.withoutgroup) { try { - await this.bot.pricelist.setNewPricelist(newPricelist); + this.bot.pricelist.setNewPricelist(newPricelist); this.bot.sendMessage(steamID, `✅ Removed ${removeCount} items from pricelist.`); return await this.bot.listings.redoListings(); } catch (err) { @@ -1618,7 +1618,7 @@ export default class PricelistManagerCommands { } } else { try { - await this.bot.pricelist.removeAll(); + this.bot.pricelist.removeAll(); return this.bot.sendMessage(steamID, '✅ Cleared pricelist!'); } catch (err) { return this.bot.sendMessage(steamID, `❌ Failed to clear pricelist: ${(err as Error).message}`); @@ -1781,7 +1781,7 @@ export default class PricelistManagerCommands { bot.sendMessage(steamID, errorMessage.slice(i10, last ? firstOrLast : (i + 1) * limit).join('\n')); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); } } @@ -1958,7 +1958,7 @@ export default class PricelistManagerCommands { this.bot.sendMessage(steamID, list.slice(i15, last ? firstOrLast : (i + 1) * 15).join('\n')); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); } PricelistManagerCommands.isSending = false; @@ -2047,7 +2047,7 @@ export default class PricelistManagerCommands { this.bot.sendMessage(steamID, list.slice(i15, last ? firstOrLast : (i + 1) * 15).join('\n')); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); } PricelistManagerCommands.isSending = false; @@ -2236,7 +2236,7 @@ export default class PricelistManagerCommands { this.bot.sendMessage(steamID, list.slice(i15, last ? firstOrLast : (i + 1) * 15).join('\n')); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); } PricelistManagerCommands.isSending = false; @@ -2297,7 +2297,7 @@ class AutoAddQueue { return this.bot.sendMessage(this.steamID, '----------\n🛑 Stopped auto-add items'); } - await sleepasync().Promise.sleep(2000); + await timersPromises.setTimeout(2000); this.params.sku = this.sku; diff --git a/src/classes/Commands/sub-classes/Request.ts b/src/classes/Commands/sub-classes/Request.ts index 075dcebe2..d314df206 100644 --- a/src/classes/Commands/sub-classes/Request.ts +++ b/src/classes/Commands/sub-classes/Request.ts @@ -1,7 +1,7 @@ import SteamID from 'steamid'; import SKU from '@tf2autobot/tf2-sku'; import pluralize from 'pluralize'; -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; import Currencies from '@tf2autobot/tf2-currencies'; import { removeLinkProtocol, getItemFromParams } from '../functions/utils'; import Bot from '../../Bot'; @@ -167,7 +167,7 @@ class Pricecheck { } async executeCheck(): Promise { - await sleepasync().Promise.sleep(2000); + await timersPromises.setTimeout(2000); void Pricecheck.requestCheck(this.sku) .then(() => { diff --git a/src/classes/Commands/sub-classes/Status.ts b/src/classes/Commands/sub-classes/Status.ts index d57de7b5e..3a852be1f 100644 --- a/src/classes/Commands/sub-classes/Status.ts +++ b/src/classes/Commands/sub-classes/Status.ts @@ -2,7 +2,7 @@ import SteamID from 'steamid'; import pluralize from 'pluralize'; import Currencies from '@tf2autobot/tf2-currencies'; import SKU from '@tf2autobot/tf2-sku'; -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; import Bot from '../../Bot'; import CommandParser from '../../CommandParser'; import { stats, profit, itemStats, testSKU } from '../../../lib/tools/export'; @@ -351,13 +351,13 @@ export default class StatusCommands { if (isSendSeparately) { this.bot.sendMessage(steamID, reply); - await sleepasync().Promise.sleep(1000); + await timersPromises.setTimeout(1000); this.bot.sendMessage(steamID, boughtMessage); - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage(steamID, soldMessage); if (adminOnlyMessage) { - await sleepasync().Promise.sleep(3000); + await timersPromises.setTimeout(3000); this.bot.sendMessage(steamID, adminOnlyMessage); } } else this.bot.sendMessage(steamID, reply); @@ -380,7 +380,7 @@ export default class StatusCommands { `\n\n📰 Release note: https://github.com/TF2Autobot/tf2autobot/releases` + (updateMessage ? `\n\n💬 Update message: ${updateMessage}` : '') ); - await sleepasync().Promise.sleep(1000); + await timersPromises.setTimeout(1000); if (this.bot.isCloned() && process.env.pm_id !== undefined && canUpdateRepo) { return this.bot.sendMessage( @@ -415,7 +415,7 @@ export default class StatusCommands { } for (const message of messages) { - await sleepasync().Promise.sleep(1000); + await timersPromises.setTimeout(1000); this.bot.sendMessage(steamID, message); } } diff --git a/src/classes/Listings.ts b/src/classes/Listings.ts index c9acf7b02..ec5fb4547 100644 --- a/src/classes/Listings.ts +++ b/src/classes/Listings.ts @@ -2,7 +2,7 @@ import callbackQueue from 'callback-queue'; import pluralize from 'pluralize'; import dayjs from 'dayjs'; import Currencies from '@tf2autobot/tf2-currencies'; -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; import Bot from './Bot'; import { Entry, PricesObject } from './Pricelist'; import log from '../lib/logger'; @@ -263,7 +263,7 @@ export default class Listings { log.debug('Checking listings for ' + pluralize('item', skus.length, true) + '...'); - void this.recursiveCheckPricelist(skus, pricelist).asCallback(() => { + void this.recursiveCheckPricelist(skus, pricelist).finally(() => { log.debug('Done checking all'); // Done checking all listings this.checkingAllListings = false; @@ -300,7 +300,7 @@ export default class Listings { if (withDelay) { this.checkBySKU(skus[index], pricelist[skus[index]], false, showLogs); index++; - await sleepasync().Promise.sleep(time ? time : 200); + await timersPromises.setTimeout(time ? time : 200); void iteration(); } else { setImmediate(() => { @@ -337,7 +337,7 @@ export default class Listings { return; } - void this.removeAllListings().asCallback(next); + void this.removeAllListings().finally(next); }); } diff --git a/src/classes/MyHandler/MyHandler.ts b/src/classes/MyHandler/MyHandler.ts index 2910277ab..189effc58 100644 --- a/src/classes/MyHandler/MyHandler.ts +++ b/src/classes/MyHandler/MyHandler.ts @@ -15,7 +15,6 @@ import TradeOfferManager, { import pluralize from 'pluralize'; import SteamID from 'steamid'; import Currencies from '@tf2autobot/tf2-currencies'; -import async from 'async'; import { UnknownDictionary } from '../../types/common'; import { accepted, declined, cancelled, acceptEscrow, invalid } from './offer/notify/export-notify'; @@ -411,13 +410,12 @@ export default class MyHandler extends Handler { return resolve(); } - void this.bot.listings.removeAll().asCallback(err => { - if (err) { - log.warn('Failed to remove all listings on shutdown (autokeys was enabled): ', err); - } - - resolve(); - }); + void this.bot.listings + .removeAll() + .catch((err: Error) => + log.warn('Failed to remove all listings on shutdown (autokeys was enabled): ', err) + ) + .finally(() => resolve()); }); } else { if (this.bot.listingManager.ready !== true) { @@ -425,13 +423,10 @@ export default class MyHandler extends Handler { return resolve(); } - void this.bot.listings.removeAll().asCallback(err => { - if (err) { - log.warn('Failed to remove all listings on shutdown: ', err); - } - - resolve(); - }); + void this.bot.listings + .removeAll() + .catch((err: Error) => log.warn('Failed to remove all listings on shutdown: ', err)) + .finally(() => resolve()); } }); } @@ -1216,7 +1211,7 @@ export default class MyHandler extends Handler { let itemSuggestedValue = 'No price'; if (!isNonTF2Items) { - // await sleepasync().Promise.sleep(1 * 1000); + // await timersPromises.setTimeout(1 * 1000); const price = await this.bot.pricelist.getItemPrices(sku); const item = SKU.fromString(sku); @@ -1455,21 +1450,16 @@ export default class MyHandler extends Handler { offer.log('info', 'checking ' + pluralize('item', assetidsToCheckCount, true) + ' for dupes...'); const inventory = new TF2Inventory(offer.partner, this.bot.manager); - const requests = assetidsToCheck.map(assetid => { - return (callback: (err: Error | null, result: boolean | null) => void): void => { - log.debug('Dupe checking ' + assetid + '...'); - void Promise.resolve(inventory.isDuped(assetid, this.bot.userID)).asCallback((err, result) => { - log.debug('Dupe check for ' + assetid + ' done'); - callback(err as Error, result); - }); - }; + const requests = assetidsToCheck.map(async (assetid): Promise => { + log.debug(`Dupe checking ${assetid}...`); + const result = await inventory.isDuped(assetid, this.bot.userID); + log.debug(`Dupe check for ${assetid}... done`); + return result; }); try { - const result: (boolean | null)[] = await Promise.fromCallback(callback => { - async.series(requests, callback); - }); - log.info('Got result from dupe checks on ' + assetidsToCheck.join(', '), { result: result }); + const result: (boolean | null)[] = await Promise.all(requests); + log.info(`Got result from dupe checks on ${assetidsToCheck.join(', ')}`, { result: result }); const resultCount = result.length; diff --git a/src/classes/MyHandler/offer/accepted/processAccepted.ts b/src/classes/MyHandler/offer/accepted/processAccepted.ts index 6ef714d8e..6a55dfd6a 100644 --- a/src/classes/MyHandler/offer/accepted/processAccepted.ts +++ b/src/classes/MyHandler/offer/accepted/processAccepted.ts @@ -1,6 +1,6 @@ import * as i from '@tf2autobot/tradeoffer-manager'; import SKU from '@tf2autobot/tf2-sku'; -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; import Bot from '../../../Bot'; import { KeyPrices } from '../../../Pricelist'; import log from '../../../../lib/logger'; @@ -297,13 +297,13 @@ export async function sendToAdmin( log.debug('Sending message 1'); bot.messageAdmins('trade', message1, []); - await sleepasync().Promise.sleep(1500); // bruh + await timersPromises.setTimeout(1500); // bruh log.debug('Sending message 2'); bot.messageAdmins('trade', message2, []); - await sleepasync().Promise.sleep(1500); + await timersPromises.setTimeout(1500); log.debug('Sending message 3'); bot.messageAdmins('trade', message3, []); - await sleepasync().Promise.sleep(1000); + await timersPromises.setTimeout(1000); log.debug('Sending message 4'); return bot.messageAdmins('trade', message4, []); } diff --git a/src/classes/MyHandler/offer/accepted/requestPriceCheck.ts b/src/classes/MyHandler/offer/accepted/requestPriceCheck.ts index 90558fa29..73d450dec 100644 --- a/src/classes/MyHandler/offer/accepted/requestPriceCheck.ts +++ b/src/classes/MyHandler/offer/accepted/requestPriceCheck.ts @@ -1,4 +1,4 @@ -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; import { RequestCheckFn, RequestCheckResponse } from '../../../IPricer'; import Bot from '../../../Bot'; import log from '../../../../lib/logger'; @@ -48,7 +48,7 @@ export default class PriceCheckQueue { this.isProcessing = true; - await sleepasync().Promise.sleep(2000); + await timersPromises.setTimeout(2000); // Update listings (exclude weapons/pure) this.bot.listings.checkBySKU(sku, null, false, true); diff --git a/src/classes/MyHandler/offer/review/send-review.ts b/src/classes/MyHandler/offer/review/send-review.ts index cd8455685..08bbc962f 100644 --- a/src/classes/MyHandler/offer/review/send-review.ts +++ b/src/classes/MyHandler/offer/review/send-review.ts @@ -1,6 +1,6 @@ import { TradeOffer, Meta } from '@tf2autobot/tradeoffer-manager'; import processReview from './process-review'; -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; import Bot from '../../../Bot'; import log from '../../../../lib/logger'; import { sendOfferReview } from '../../../../lib/DiscordWebhook/export'; @@ -139,7 +139,7 @@ export default async function sendReview( const list = t.listItems(offer, bot, items, true); // add delay here because Steam said RateLimitExceeded - if (isNotifyTradePartner) await sleepasync().Promise.sleep(2000); + if (isNotifyTradePartner) await timersPromises.setTimeout(2000); void sendToAdmin(bot, offer, reasons, content.value, keyPrices, list, links); } } @@ -201,16 +201,16 @@ export async function sendToAdmin( log.debug('Sending message 1'); bot.messageAdmins(message1, []); - await sleepasync().Promise.sleep(1500); // bruh + await timersPromises.setTimeout(1500); // bruh log.debug('Sending message 2'); bot.messageAdmins(message2, []); - await sleepasync().Promise.sleep(1500); + await timersPromises.setTimeout(1500); log.debug('Sending message 3'); bot.messageAdmins(message3, []); - await sleepasync().Promise.sleep(1000); + await timersPromises.setTimeout(1000); log.debug('Sending message 4'); return bot.messageAdmins(message4, []); } - await sleepasync().Promise.sleep(1500); + await timersPromises.setTimeout(1500); bot.messageAdmins(message, []); } diff --git a/src/classes/Pricelist.ts b/src/classes/Pricelist.ts index cdae37830..3753c25dd 100644 --- a/src/classes/Pricelist.ts +++ b/src/classes/Pricelist.ts @@ -566,24 +566,16 @@ export default class Pricelist extends EventEmitter { return entry; } - setNewPricelist(newEntry: PricesObject): Promise { - return new Promise(resolve => { - this.prices = newEntry; - this.emit('pricelist', newEntry); - - return resolve(); - }); + setNewPricelist(newEntry: PricesObject): void { + this.prices = newEntry; + this.emit('pricelist', newEntry); } - removeAll(): Promise { - return new Promise(resolve => { - if (this.getLength !== 0) { - this.prices = {}; - this.emit('pricelist', []); - } - - return resolve(); - }); + removeAll(): void { + if (this.getLength !== 0) { + this.prices = {}; + this.emit('pricelist', []); + } } removePrice(sku: string, emitChange: boolean): Promise { diff --git a/src/classes/TF2GC.ts b/src/classes/TF2GC.ts index 8deeedca1..4d947d9f7 100644 --- a/src/classes/TF2GC.ts +++ b/src/classes/TF2GC.ts @@ -187,34 +187,34 @@ export default class TF2GC { // Ensuring TF2 GC connection... - void this.connectToGC().asCallback(err => { - if (err) { - return this.finishedProcessingJob(err as Error); - } - - let func; - - if (job.type === 'combineWeapon') { - func = this.handleCraftJobWeapon.bind(this, job); - } else if (job.type === 'combineClassWeapon') { - func = this.handleCraftJobClassWeapon.bind(this, job); - } else if (['smelt', 'combine'].includes(job.type)) { - func = this.handleCraftJob.bind(this, job); - } else if (['use', 'delete', 'removeAttributes'].includes(job.type)) { - func = this.handleUseOrDeleteOrRemoveAttributesJob.bind(this, job); - } else if (job.type === 'sort') { - func = this.handleSortJob.bind(this, job); - } else if (job.type === 'craftToken') { - func = this.handleCraftTokenJob.bind(this, job); - } + void this.connectToGC() + .then(() => { + let func; + + if (job.type === 'combineWeapon') { + func = this.handleCraftJobWeapon.bind(this, job); + } else if (job.type === 'combineClassWeapon') { + func = this.handleCraftJobClassWeapon.bind(this, job); + } else if (['smelt', 'combine'].includes(job.type)) { + func = this.handleCraftJob.bind(this, job); + } else if (['use', 'delete', 'removeAttributes'].includes(job.type)) { + func = this.handleUseOrDeleteOrRemoveAttributesJob.bind(this, job); + } else if (job.type === 'sort') { + func = this.handleSortJob.bind(this, job); + } else if (job.type === 'craftToken') { + func = this.handleCraftTokenJob.bind(this, job); + } - if (func) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - func(); - } else { - this.finishedProcessingJob(new Error('Unknown job type')); - } - }); + if (func) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + func(); + } else { + this.finishedProcessingJob(new Error('Unknown job type')); + } + }) + .catch((err: Error) => { + this.finishedProcessingJob(err); + }); } private handleCraftJob(job: Job): void { diff --git a/src/classes/Trades.ts b/src/classes/Trades.ts index c102a66e5..35c8c5417 100644 --- a/src/classes/Trades.ts +++ b/src/classes/Trades.ts @@ -13,6 +13,7 @@ import pluralize from 'pluralize'; import retry from 'retry'; import SteamID from 'steamid'; import Currencies from '@tf2autobot/tf2-currencies'; +import timersPromises from 'timers/promises'; import { UnknownDictionaryKnownValues, UnknownDictionary } from '../types/common'; import Bot from './Bot'; @@ -528,8 +529,19 @@ export default class Trades { log.verbose(`Handling offer #${offerId}...`); - void this.getOffer(offerId).asCallback((err, offer) => { - if (err) { + void this.getOffer(offerId) + .then(offer => { + if (!offer) { + log.debug('Failed to get offer'); + // Failed to get the offer + this.finishProcessingOffer(offerId); + } else { + log.debug('Got offer, handling it'); + // Got the offer, give it to the handler + this.handlerProcessOffer(offer); + } + }) + .catch((err: Error) => { log.warn(`Failed to get offer #${offerId}: `, err); // After many retries we could not get the offer data @@ -537,18 +549,7 @@ export default class Trades { // Remove the offer from the queue and add it to the back of the queue this.receivedOffers.push(offerId); } - } - - if (!offer) { - log.debug('Failed to get offer'); - // Failed to get the offer - this.finishProcessingOffer(offerId); - } else { - log.debug('Got offer, handling it'); - // Got the offer, give it to the handler - this.handlerProcessOffer(offer); - } - }); + }); } getOffer(offerId: string, attempts = 0): Promise { @@ -568,17 +569,20 @@ export default class Trades { if (err.message !== 'Not Logged In') { // We got an error getting the offer, retry after some time - return void Promise.delay(exponentialBackoff(attempts)).then(() => { + return void timersPromises.setTimeout(exponentialBackoff(attempts)).then(() => { resolve(this.getOffer(offerId, attempts)); }); } - return void this.bot.getWebSession(true).asCallback(err => { - // If there is no error when waiting for web session, then attempt to fetch the offer right away - void Promise.delay(err !== null ? 0 : exponentialBackoff(attempts)).then(() => { - resolve(this.getOffer(offerId, attempts)); + return void this.bot + .getWebSession(true) + .catch((err: Error) => err) + .then(err => { + // If there is no error when waiting for web session, then attempt to fetch the offer right away + void timersPromises.setTimeout(err !== null ? 0 : exponentialBackoff(attempts)).then(() => { + resolve(this.getOffer(offerId, attempts)); + }); }); - }); } if (offer.state !== TradeOfferManager.ETradeOfferState['Active']) { @@ -597,113 +601,115 @@ export default class Trades { const start = dayjs().valueOf(); offer.data('actionTimestamp', start); - void this.acceptOfferRetry(offer).asCallback((err, status) => { - const actionTime = dayjs().valueOf() - start; - log.debug('actionTime', actionTime); + void this.acceptOfferRetry(offer) + .then(status => { + offer.log( + 'trade', + 'successfully accepted' + (status === 'pending' ? '; confirmation required' : '') + ); - if (err) { - return reject(err); - } + if (status === 'pending') { + // Maybe wait for confirmation to be accepted and then resolve? + this.acceptConfirmation(offer).catch(err => { + log.warn(`Error while trying to accept mobile confirmation on offer #${offer.id}: `, err); + + const isNotIgnoredError = + !(err as CustomError).message?.includes('Could not act on confirmation') && + !(err as CustomError).message?.includes('Could not find confirmation for object'); + + if (isNotIgnoredError) { + // Only notify if error is not "Could not act on confirmation" or not "Could not find confirmation for object" + const opt = this.bot.options; + + if (opt.sendAlert.enable && opt.sendAlert.failedAccept) { + const keyPrices = this.bot.pricelist.getKeyPrices; + const value = t.valueDiff(offer, keyPrices, false); + + if ( + opt.discordWebhook.sendAlert.enable && + opt.discordWebhook.sendAlert.url.main !== '' + ) { + const summary = t.summarizeToChat( + offer, + this.bot, + 'summary-accepting', + true, + value, + keyPrices, + false, + false + ); + sendAlert( + `error-accept`, + this.bot, + `Error while trying to accept mobile confirmation on offer #${offer.id}` + + summary + + `\n\nThe offer might already get cancelled. You can check if this offer is still active by` + + ` sending "!trade ${offer.id}"`, + null, + err, + [offer.id] + ); + } else { + const summary = t.summarizeToChat( + offer, + this.bot, + 'summary-accepting', + false, + value, + keyPrices, + true, + false + ); + + this.bot.messageAdmins( + `Error while trying to accept mobile confirmation on offer #${offer.id}:` + + summary + + `\n\nThe offer might already get cancelled. You can check if this offer is still active by` + + ` sending "!trade ${offer.id}` + + `\n\nError: ${ + (err as CustomError).eresult + ? `${ + TradeOfferManager.EResult[ + (err as CustomError).eresult + ] as string + } - https://steamerrors.com/${(err as CustomError).eresult}` + : (err as Error).message + }`, + [] + ); + } + } - offer.log('trade', 'successfully accepted' + (status === 'pending' ? '; confirmation required' : '')); - - if (status === 'pending') { - // Maybe wait for confirmation to be accepted and then resolve? - this.acceptConfirmation(offer).catch(err => { - log.warn(`Error while trying to accept mobile confirmation on offer #${offer.id}: `, err); - - const isNotIgnoredError = - !(err as CustomError).message?.includes('Could not act on confirmation') && - !(err as CustomError).message?.includes('Could not find confirmation for object'); - - if (isNotIgnoredError) { - // Only notify if error is not "Could not act on confirmation" or not "Could not find confirmation for object" - const opt = this.bot.options; - - if (opt.sendAlert.enable && opt.sendAlert.failedAccept) { - const keyPrices = this.bot.pricelist.getKeyPrices; - const value = t.valueDiff(offer, keyPrices, false); - - if ( - opt.discordWebhook.sendAlert.enable && - opt.discordWebhook.sendAlert.url.main !== '' - ) { - const summary = t.summarizeToChat( - offer, - this.bot, - 'summary-accepting', - true, - value, - keyPrices, - false, - false - ); - sendAlert( - `error-accept`, - this.bot, - `Error while trying to accept mobile confirmation on offer #${offer.id}` + - summary + - `\n\nThe offer might already get cancelled. You can check if this offer is still active by` + - ` sending "!trade ${offer.id}"`, - null, - err, - [offer.id] - ); - } else { - const summary = t.summarizeToChat( - offer, - this.bot, - 'summary-accepting', - false, - value, - keyPrices, - true, - false - ); + if (!this.retryAcceptOffer[offer.id]) { + // Only retry once + clearTimeout(this.resetRetryAcceptOfferTimeout); + this.retryAcceptOffer[offer.id] = true; - this.bot.messageAdmins( - `Error while trying to accept mobile confirmation on offer #${offer.id}:` + - summary + - `\n\nThe offer might already get cancelled. You can check if this offer is still active by` + - ` sending "!trade ${offer.id}` + - `\n\nError: ${ - (err as CustomError).eresult - ? `${ - TradeOfferManager.EResult[ - (err as CustomError).eresult - ] as string - } - https://steamerrors.com/${(err as CustomError).eresult}` - : (err as Error).message - }`, - [] - ); + setTimeout(() => { + // Auto-retry after 30 seconds + void this.retryActionAfterFailure(offer.id, 'accept'); + }, 30 * 1000); } - } - if (!this.retryAcceptOffer[offer.id]) { - // Only retry once - clearTimeout(this.resetRetryAcceptOfferTimeout); - this.retryAcceptOffer[offer.id] = true; - - setTimeout(() => { - // Auto-retry after 30 seconds - void this.retryActionAfterFailure(offer.id, 'accept'); - }, 30 * 1000); + this.resetRetryAcceptOfferTimeout = setTimeout(() => { + this.retryAcceptOffer = {}; + }, 2 * 60 * 1000); } + }); + } - this.resetRetryAcceptOfferTimeout = setTimeout(() => { - this.retryAcceptOffer = {}; - }, 2 * 60 * 1000); - } - }); - } - - return resolve(status); - }); + return resolve(status); + }) + .catch((err: Error) => { + const actionTime = dayjs().valueOf() - start; + log.debug('actionTime', actionTime); + return reject(err); + }); }); } - private counterOffer(offer: TradeOffer, meta: Meta): Promise { + private counterOffer(offer: TradeOffer, meta: Meta): Promise { return new Promise((resolve, reject) => { const start = dayjs().valueOf(); @@ -721,460 +727,477 @@ export default class Trades { const ourInventoryItems = this.bot.inventoryManager.getInventory.getItems; log.debug('Fetching their inventory...'); - void theirInventory.fetch().asCallback(err => { - if (err) { - log.error(`Failed to load inventories (${offer.partner.getSteamID64()}): `, err); - return reject( - new Error( - `Failed to load your inventories (Steam might down). Please try again later.` + - ` If your profile/inventory is set to private, please set it to public and try again.` - ) + void theirInventory + .fetch() + .then(() => { + const ourItems = Inventory.fromItems( + this.bot.client.steamID || this.bot.community.steamID, + offer.itemsToGive, + this.bot.manager, + this.bot.schema, + opt, + this.bot.strangeParts, + 'our' + ).getItems; + + const theirItems = Inventory.fromItems( + offer.partner, + offer.itemsToReceive, + this.bot.manager, + this.bot.schema, + opt, + this.bot.strangeParts, + 'their' + ).getItems; + + const theirInventoryItems = theirInventory.getItems; + + log.debug('Set counteroffer...'); + const counter = offer.counter(); + + const showOnlyMetal = opt.miscSettings.showOnlyMetal.enable; + // To the person who thinks about changing it. I have a gun keep out ( う-´)づ︻╦̵̵̿╤── \(˚☐˚”)/ + // Extensive tutorial if you want to update this function https://www.youtube.com/watch?v=dQw4w9WgXcQ. + + log.debug('Set counteroffer message...'); + const customMessage = opt.customMessage.counterOffer; + counter.setMessage( + customMessage + ? customMessage + : "Your offer contains wrong value. You've probably made a few mistakes, here's the correct offer." ); - } - - const ourItems = Inventory.fromItems( - this.bot.client.steamID || this.bot.community.steamID, - offer.itemsToGive, - this.bot.manager, - this.bot.schema, - opt, - this.bot.strangeParts, - 'our' - ).getItems; - - const theirItems = Inventory.fromItems( - offer.partner, - offer.itemsToReceive, - this.bot.manager, - this.bot.schema, - opt, - this.bot.strangeParts, - 'their' - ).getItems; - - const theirInventoryItems = theirInventory.getItems; - - log.debug('Set counteroffer...'); - const counter = offer.counter(); - - const showOnlyMetal = opt.miscSettings.showOnlyMetal.enable; - // To the person who thinks about changing it. I have a gun keep out ( う-´)づ︻╦̵̵̿╤── \(˚☐˚”)/ - // Extensive tutorial if you want to update this function https://www.youtube.com/watch?v=dQw4w9WgXcQ. - - log.debug('Set counteroffer message...'); - const customMessage = opt.customMessage.counterOffer; - counter.setMessage( - customMessage - ? customMessage - : "Your offer contains wrong value. You've probably made a few mistakes, here's the correct offer." - ); - function getPureValue(sku: PureSKU) { - if (sku === '5021;6') return keyPriceScrap; - const pures: PureSKU[] = ['5000;6', '5001;6', '5002;6']; - const index = pures.indexOf(sku); - return index === -1 ? 0 : Math.pow(3, index); - } + function getPureValue(sku: PureSKU) { + if (sku === '5021;6') return keyPriceScrap; + const pures: PureSKU[] = ['5000;6', '5001;6', '5002;6']; + const index = pures.indexOf(sku); + return index === -1 ? 0 : Math.pow(3, index); + } - let lockKeys = false; - function calculate(sku: PureSKU, side: Dict | number, increaseDifference: boolean, overpay?: boolean) { - const value = getPureValue(sku); - if (!value) return 0; - if (possibleKeyTrade && sku == '5021;6') { - const ret = increaseDifference === keyDifference > 0 && !lockKeys ? Math.abs(keyDifference) : 0; - lockKeys = !!ret; - return ret; + let lockKeys = false; + function calculate( + sku: PureSKU, + side: Dict | number, + increaseDifference: boolean, + overpay?: boolean + ) { + const value = getPureValue(sku); + if (!value) return 0; + if (possibleKeyTrade && sku == '5021;6') { + const ret = + increaseDifference === keyDifference > 0 && !lockKeys ? Math.abs(keyDifference) : 0; + lockKeys = !!ret; + return ret; + } + const floorCeil = Math[overpay ? 'ceil' : 'floor']; + const length = typeof side === 'number' ? side : side[sku]?.length || 0; + const amount = + Math.min( + length, + Math.max(floorCeil((NonPureWorth * (increaseDifference ? -1 : 1)) / value), 0) + ) || 0; + + NonPureWorth += amount * value * (increaseDifference ? 1 : -1); + return amount; } - const floorCeil = Math[overpay ? 'ceil' : 'floor']; - const length = typeof side === 'number' ? side : side[sku]?.length || 0; - const amount = - Math.min( - length, - Math.max(floorCeil((NonPureWorth * (increaseDifference ? -1 : 1)) / value), 0) - ) || 0; - - NonPureWorth += amount * value * (increaseDifference ? 1 : -1); - return amount; - } - // + for add - for remove - function changeItems(side: 'My' | 'Their', dict: Dict, amount: number, sku: PureSKU) { - if (!amount) return; - const intent = amount >= 0 ? 'add' : 'remove'; - const tradeAmount = Math.abs(amount); - const arr = dict[sku]; - const whichSide = side == 'My' ? 'our' : 'their'; - const changedAmount = counter[(intent + side + 'Items') as AddOrRemoveMyOrTheirItems]( - arr.splice(0, tradeAmount).map(item => { - return { - appid: 440, - contextid: '2', - assetid: item.id - }; - }) - ); + // + for add - for remove + function changeItems(side: 'My' | 'Their', dict: Dict, amount: number, sku: PureSKU) { + if (!amount) return; + const intent = amount >= 0 ? 'add' : 'remove'; + const tradeAmount = Math.abs(amount); + const arr = dict[sku]; + const whichSide = side == 'My' ? 'our' : 'their'; + const changedAmount = counter[(intent + side + 'Items') as AddOrRemoveMyOrTheirItems]( + arr.splice(0, tradeAmount).map(item => { + return { + appid: 440, + contextid: '2', + assetid: item.id + }; + }) + ); - if (changedAmount !== tradeAmount) { - return reject(new Error(`Couldn't ${intent} ${whichSide} ${tradeAmount} ${sku}'s to Trade`)); - } + if (changedAmount !== tradeAmount) { + return reject( + new Error(`Couldn't ${intent} ${whichSide} ${tradeAmount} ${sku}'s to Trade`) + ); + } - if (!showOnlyMetal && !possibleKeyTrade && sku === '5021;6') { - tradeValues[whichSide].keys += amount; - } else { - tradeValues[whichSide].scrap += - amount * - (possibleKeyTrade && sku == '5021;6' && side == 'Their' - ? Currencies.toScrap(prices['5021;6'].buy.metal) - : getPureValue(sku)); - } + if (!showOnlyMetal && !possibleKeyTrade && sku === '5021;6') { + tradeValues[whichSide].keys += amount; + } else { + tradeValues[whichSide].scrap += + amount * + (possibleKeyTrade && sku == '5021;6' && side == 'Their' + ? Currencies.toScrap(prices['5021;6'].buy.metal) + : getPureValue(sku)); + } - dataDict[whichSide][sku] ??= 0; - dataDict[whichSide][sku] += amount; + dataDict[whichSide][sku] ??= 0; + dataDict[whichSide][sku] += amount; - // For removing 0's from the dict - if (dataDict[whichSide][sku] === 0) { - delete dataDict[whichSide][sku]; + // For removing 0's from the dict + if (dataDict[whichSide][sku] === 0) { + delete dataDict[whichSide][sku]; + } } - } - const setOfferDataAndSend = () => { - // Backup it should never make it to here as an error - log.debug('Checking final mismatch...'); - if ( - tradeValues.our.keys * keyPriceScrap + tradeValues.our.scrap !== - tradeValues.their.keys * keyPriceScrap + tradeValues.their.scrap - ) { - return reject( - new Error( - `Couldn't counter an offer - value mismatch:\n${JSON.stringify({ - value: NonPureWorth, - needToTakeWeapon, - ourTradesValue: tradeValues.our, - ourItems: dataDict.our, - theirTradesValue: tradeValues.their, - theirItems: dataDict.their - })}` - ) - ); - // Maybe add some info that they can provide us so we can fix it if it happens again? - } + const setOfferDataAndSend = () => { + // Backup it should never make it to here as an error + log.debug('Checking final mismatch...'); + if ( + tradeValues.our.keys * keyPriceScrap + tradeValues.our.scrap !== + tradeValues.their.keys * keyPriceScrap + tradeValues.their.scrap + ) { + return reject( + new Error( + `Couldn't counter an offer - value mismatch:\n${JSON.stringify({ + value: NonPureWorth, + needToTakeWeapon, + ourTradesValue: tradeValues.our, + ourItems: dataDict.our, + theirTradesValue: tradeValues.their, + theirItems: dataDict.their + })}` + ) + ); + // Maybe add some info that they can provide us so we can fix it if it happens again? + } - // Set polldata datas - log.debug('Setting counter polldata...'); - const handleTimestamp = offer.data('handleTimestamp') as number; - counter.data('handleTimestamp', handleTimestamp); - counter.data('notify', true); + // Set polldata datas + log.debug('Setting counter polldata...'); + const handleTimestamp = offer.data('handleTimestamp') as number; + counter.data('handleTimestamp', handleTimestamp); + counter.data('notify', true); + + counter.data('value', { + our: { + total: tradeValues.our.keys * keyPriceScrap + tradeValues.our.scrap, + keys: tradeValues.our.keys, + metal: Currencies.toRefined(tradeValues.our.scrap) + }, + their: { + total: tradeValues.their.keys * keyPriceScrap + tradeValues.their.scrap, + keys: tradeValues.their.keys, + metal: Currencies.toRefined(tradeValues.their.scrap) + }, + rate: values.rate + }); - counter.data('value', { - our: { - total: tradeValues.our.keys * keyPriceScrap + tradeValues.our.scrap, - keys: tradeValues.our.keys, - metal: Currencies.toRefined(tradeValues.our.scrap) - }, - their: { - total: tradeValues.their.keys * keyPriceScrap + tradeValues.their.scrap, - keys: tradeValues.their.keys, - metal: Currencies.toRefined(tradeValues.their.scrap) - }, - rate: values.rate - }); + counter.data('dict', dataDict); - counter.data('dict', dataDict); + counter.data('prices', prices); - counter.data('prices', prices); + counter.data('action', { + action: 'counter', + reason: 'COUNTERED' + } as Action); - counter.data('action', { - action: 'counter', - reason: 'COUNTERED' - } as Action); + counter.data('meta', meta); - counter.data('meta', meta); + if (meta.highValue) { + counter.data('highValue', meta.highValue); + } - if (meta.highValue) { - counter.data('highValue', meta.highValue); - } + const processTime = offer.data('processOfferTime') as number; + counter.data('processOfferTime', processTime); + const processCounterTime = dayjs().valueOf() - start; + counter.data('processCounterTime', processCounterTime); + + // Send countered offer + log.debug('Sending countered offer...'); + void this.sendOffer(counter) + .then(status => { + log.debug('Countered offer sent.'); + if (status === 'pending') { + log.debug('Accepting mobile confirmation...'); + void this.acceptConfirmation(counter); + } - const processTime = offer.data('processOfferTime') as number; - counter.data('processOfferTime', processTime); - const processCounterTime = dayjs().valueOf() - start; - counter.data('processCounterTime', processCounterTime); - - // Send countered offer - log.debug('Sending countered offer...'); - void this.sendOffer(counter) - .then(status => { - log.debug('Countered offer sent.'); - if (status === 'pending') { - log.debug('Accepting mobile confirmation...'); - void this.acceptConfirmation(counter).reflect(); - } + log.debug(`Done counteroffer for offer #${offer.id}`); + return resolve(); + }) + .catch(err => { + const errStringify = JSON.stringify(err); + const errMessage = errStringify === '' ? (err as Error)?.message : errStringify; + reject(new Error(`Something wrong while sending countered offer: ${errMessage}`)); + }); + }; - log.debug(`Done counteroffer for offer #${offer.id}`); - return resolve(); - }) - .catch(err => { - const errStringify = JSON.stringify(err); - const errMessage = errStringify === '' ? (err as Error)?.message : errStringify; - reject(new Error(`Something wrong while sending countered offer: ${errMessage}`)); - }); - }; - - const values = offer.data('value') as ItemsValue; - const dataDict = offer.data('dict') as ItemsDict; - const prices = offer.data('prices') as Prices; - - const keyPriceScrap = Currencies.toScrap(values.rate); - const tradeValues = { - our: { - scrap: values.our.total - values.our.keys * keyPriceScrap, - keys: values.our.keys - }, - their: { - scrap: values.their.total - values.their.keys * keyPriceScrap, - keys: values.their.keys - } - }; - - const isWACEnabled = opt.miscSettings.weaponsAsCurrency.enable; - const isUncraftEnabled = opt.miscSettings.weaponsAsCurrency.withUncraft; - const weapons = isUncraftEnabled - ? this.bot.craftWeapons.concat(this.bot.uncraftWeapons) - : this.bot.craftWeapons; - - // Bigger than 0 ? they have to pay : we have to pay - const puresWithKeys = ['5000;6', '5001;6', '5002;6', '5021;6']; - let hasMissingPrices = false; - - let possibleKeyTrade = true; - let keyDifference = 0; - - let NonPureWorth = (['our', 'their'] as ['our', 'their']) - .map((side, index) => { - const buySell = index ? 'buy' : 'sell'; - return ( - Object.keys(dataDict[side]) - .map(sku => { - if (prices[sku] === undefined && !puresWithKeys.includes(sku)) { - hasMissingPrices = true; - return 0; - } + const values = offer.data('value') as ItemsValue; + const dataDict = offer.data('dict') as ItemsDict; + const prices = offer.data('prices') as Prices; - if (sku == '5021;6') - keyDifference += dataDict[side][sku] * (side == 'our' ? 1 : -1); - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - if (!dataDict[side][sku] || getPureValue(sku as any) !== 0) return 0; + const keyPriceScrap = Currencies.toScrap(values.rate); + const tradeValues = { + our: { + scrap: values.our.total - values.our.keys * keyPriceScrap, + keys: values.our.keys + }, + their: { + scrap: values.their.total - values.their.keys * keyPriceScrap, + keys: values.their.keys + } + }; - possibleKeyTrade = false; //Offer contains something other than pures + const isWACEnabled = opt.miscSettings.weaponsAsCurrency.enable; + const isUncraftEnabled = opt.miscSettings.weaponsAsCurrency.withUncraft; + const weapons = isUncraftEnabled + ? this.bot.craftWeapons.concat(this.bot.uncraftWeapons) + : this.bot.craftWeapons; - if (isWACEnabled && weapons.includes(sku)) return 0.5 * dataDict[side][sku]; + // Bigger than 0 ? they have to pay : we have to pay + const puresWithKeys = ['5000;6', '5001;6', '5002;6', '5021;6']; + let hasMissingPrices = false; + + let possibleKeyTrade = true; + let keyDifference = 0; + + let NonPureWorth = (['our', 'their'] as ['our', 'their']) + .map((side, index) => { + const buySell = index ? 'buy' : 'sell'; + return ( + Object.keys(dataDict[side]) + .map(sku => { + if (prices[sku] === undefined && !puresWithKeys.includes(sku)) { + hasMissingPrices = true; + return 0; + } + + if (sku == '5021;6') + keyDifference += dataDict[side][sku] * (side == 'our' ? 1 : -1); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + if (!dataDict[side][sku] || getPureValue(sku as any) !== 0) return 0; + + possibleKeyTrade = false; //Offer contains something other than pures + + if (isWACEnabled && weapons.includes(sku)) return 0.5 * dataDict[side][sku]; + + return ( + dataDict[side][sku] * + (prices[sku][buySell].keys * keyPriceScrap + + Currencies.toScrap(prices[sku][buySell].metal)) + ); + }) + .reduce((a, b) => a + b, 0) * (side == 'their' ? -1 : 1) + ); + }) + .reduce((a, b) => b + a, 0); - return ( - dataDict[side][sku] * - (prices[sku][buySell].keys * keyPriceScrap + - Currencies.toScrap(prices[sku][buySell].metal)) - ); - }) - .reduce((a, b) => a + b, 0) * (side == 'their' ? -1 : 1) + if (hasMissingPrices) { + return reject( + new Error( + `Failed to counter offer #${ + offer.id + } - offer data was not properly saved: ${JSON.stringify({ values, dataDict, prices })}` + ) ); - }) - .reduce((a, b) => b + a, 0); + } + if (possibleKeyTrade) { + NonPureWorth += + keyDifference * + Currencies.toScrap(prices['5021;6'][keyDifference > 0 ? 'sell' : 'buy'].metal); + } + // Determine if we need to take a weapon from them + const needToTakeWeapon = NonPureWorth - Math.trunc(NonPureWorth) !== 0; - if (hasMissingPrices) { - return reject( - new Error( - `Failed to counter offer #${offer.id} - offer data was not properly saved: ${JSON.stringify( - { values, dataDict, prices } - )}` - ) - ); - } - if (possibleKeyTrade) { - NonPureWorth += - keyDifference * Currencies.toScrap(prices['5021;6'][keyDifference > 0 ? 'sell' : 'buy'].metal); - } - // Determine if we need to take a weapon from them - const needToTakeWeapon = NonPureWorth - Math.trunc(NonPureWorth) !== 0; + if (needToTakeWeapon) { + log.debug('needToTakeWeapon:', needToTakeWeapon); + const allWeapons = this.bot.handler.isWeaponsAsCurrency.withUncraft + ? this.bot.craftWeapons.concat(this.bot.uncraftWeapons) + : this.bot.craftWeapons; - if (needToTakeWeapon) { - log.debug('needToTakeWeapon:', needToTakeWeapon); - const allWeapons = this.bot.handler.isWeaponsAsCurrency.withUncraft - ? this.bot.craftWeapons.concat(this.bot.uncraftWeapons) - : this.bot.craftWeapons; + const skusFromPricelist = Object.keys(this.bot.pricelist.getPrices); - const skusFromPricelist = Object.keys(this.bot.pricelist.getPrices); + // return filtered weapons + let filtered = allWeapons.filter(sku => !skusFromPricelist.includes(sku)); - // return filtered weapons - let filtered = allWeapons.filter(sku => !skusFromPricelist.includes(sku)); + if (filtered.length === 0) { + // but if nothing left, then just use all + filtered = allWeapons; + } + + const chosenOne = filtered + .filter(sku => theirItems[sku] === undefined) // filter weapons that are not in their offer + .find(sku => theirInventoryItems[sku]); // find one that is in their inventory - if (filtered.length === 0) { - // but if nothing left, then just use all - filtered = allWeapons; + log.debug('weaponOfChoice:', chosenOne); + + const item = theirInventoryItems[chosenOne]; + log.debug('item:', item); + if (item) { + const isAdded = counter.addTheirItem({ + appid: 440, + contextid: '2', + assetid: item[0].id + }); + if (isAdded) { + NonPureWorth -= 0.5; + tradeValues['their'].scrap += 0.5; + dataDict['their'][chosenOne] ??= 0; + dataDict['their'][chosenOne] += 1; + + const isInPricelist = this.bot.pricelist.getPrice(chosenOne, false); + + if (isInPricelist !== null) { + prices[chosenOne] = { + buy: isInPricelist.buy, + sell: isInPricelist.sell + }; + } + } + } } - const chosenOne = filtered - .filter(sku => theirItems[sku] === undefined) // filter weapons that are not in their offer - .find(sku => theirInventoryItems[sku]); // find one that is in their inventory + const ourBestWay: Record = { + '5021;6': calculate('5021;6', ourInventoryItems, true), + '5002;6': calculate('5002;6', ourInventoryItems, true), + '5001;6': calculate('5001;6', ourInventoryItems, true), + '5000;6': calculate('5000;6', ourInventoryItems, true) + }; + if (NonPureWorth < 0) { + log.debug('NonPureWorth < 0 - ourBestWay before', { + ourBestWay + }); - log.debug('weaponOfChoice:', chosenOne); + ourBestWay['5002;6'] += calculate( + '5002;6', + (ourInventoryItems['5002;6']?.length || 0) - ourBestWay['5002;6'], + true, + true + ); + ourBestWay['5001;6'] += calculate( + '5001;6', + (ourInventoryItems['5001;6']?.length || 0) - ourBestWay['5001;6'], + true, + true + ); + ourBestWay['5021;6'] += calculate( + '5021;6', + (ourInventoryItems['5021;6']?.length || 0) - ourBestWay['5021;6'], + true, + true + ); + + ourBestWay['5002;6'] -= calculate('5002;6', ourBestWay['5002;6'], false); + ourBestWay['5001;6'] -= calculate('5001;6', ourBestWay['5001;6'], false); + ourBestWay['5000;6'] -= calculate('5000;6', ourBestWay['5000;6'], false); - const item = theirInventoryItems[chosenOne]; - log.debug('item:', item); - if (item) { - const isAdded = counter.addTheirItem({ - appid: 440, - contextid: '2', - assetid: item[0].id + log.debug('NonPureWorth < 0 - ourBestWay after', { + ourBestWay }); - if (isAdded) { - NonPureWorth -= 0.5; - tradeValues['their'].scrap += 0.5; - dataDict['their'][chosenOne] ??= 0; - dataDict['their'][chosenOne] += 1; - - const isInPricelist = this.bot.pricelist.getPrice(chosenOne, false); - - if (isInPricelist !== null) { - prices[chosenOne] = { - buy: isInPricelist.buy, - sell: isInPricelist.sell - }; - } - } } - } - const ourBestWay: Record = { - '5021;6': calculate('5021;6', ourInventoryItems, true), - '5002;6': calculate('5002;6', ourInventoryItems, true), - '5001;6': calculate('5001;6', ourInventoryItems, true), - '5000;6': calculate('5000;6', ourInventoryItems, true) - }; - if (NonPureWorth < 0) { - log.debug('NonPureWorth < 0 - ourBestWay before', { - ourBestWay - }); + const theirBestWay: Record = { + '5021;6': calculate('5021;6', theirInventoryItems, false), + '5002;6': calculate('5002;6', theirInventoryItems, false), + '5001;6': calculate('5001;6', theirInventoryItems, false), + '5000;6': calculate('5000;6', theirInventoryItems, false) + }; + if (NonPureWorth > 0) { + log.debug('NonPureWorth > 0 - theirBestWay before', { + theirBestWay + }); + theirBestWay['5002;6'] += calculate( + '5002;6', + (theirInventoryItems['5002;6']?.length || 0) - theirBestWay['5002;6'], + false, + true + ); + theirBestWay['5001;6'] += calculate( + '5001;6', + (theirInventoryItems['5001;6']?.length || 0) - theirBestWay['5001;6'], + false, + true + ); + theirBestWay['5021;6'] += calculate( + '5021;6', + (theirInventoryItems['5021;6']?.length || 0) - theirBestWay['5021;6'], + false, + true + ); - ourBestWay['5002;6'] += calculate( - '5002;6', - (ourInventoryItems['5002;6']?.length || 0) - ourBestWay['5002;6'], - true, - true - ); - ourBestWay['5001;6'] += calculate( - '5001;6', - (ourInventoryItems['5001;6']?.length || 0) - ourBestWay['5001;6'], - true, - true - ); - ourBestWay['5021;6'] += calculate( - '5021;6', - (ourInventoryItems['5021;6']?.length || 0) - ourBestWay['5021;6'], - true, - true - ); + theirBestWay['5002;6'] -= calculate('5002;6', theirBestWay['5002;6'], true); + theirBestWay['5001;6'] -= calculate('5001;6', theirBestWay['5001;6'], true); + theirBestWay['5000;6'] -= calculate('5000;6', theirBestWay['5000;6'], true); - ourBestWay['5002;6'] -= calculate('5002;6', ourBestWay['5002;6'], false); - ourBestWay['5001;6'] -= calculate('5001;6', ourBestWay['5001;6'], false); - ourBestWay['5000;6'] -= calculate('5000;6', ourBestWay['5000;6'], false); + log.debug('NonPureWorth > 0 - theirBestWay after', { + theirBestWay + }); - log.debug('NonPureWorth < 0 - ourBestWay after', { - ourBestWay - }); - } + log.debug('Add some of our items if they are still overpaying - before', { + ourBestWay + }); + // Add some of our items if they are still overpaying + ourBestWay['5002;6'] += calculate( + '5002;6', + (ourInventoryItems['5002;6']?.length || 0) - ourBestWay['5002;6'], + true + ); + ourBestWay['5001;6'] += calculate( + '5001;6', + (ourInventoryItems['5001;6']?.length || 0) - ourBestWay['5001;6'], + true + ); + ourBestWay['5000;6'] += calculate( + '5000;6', + (ourInventoryItems['5000;6']?.length || 0) - ourBestWay['5000;6'], + true + ); - const theirBestWay: Record = { - '5021;6': calculate('5021;6', theirInventoryItems, false), - '5002;6': calculate('5002;6', theirInventoryItems, false), - '5001;6': calculate('5001;6', theirInventoryItems, false), - '5000;6': calculate('5000;6', theirInventoryItems, false) - }; - if (NonPureWorth > 0) { - log.debug('NonPureWorth > 0 - theirBestWay before', { - theirBestWay - }); - theirBestWay['5002;6'] += calculate( - '5002;6', - (theirInventoryItems['5002;6']?.length || 0) - theirBestWay['5002;6'], - false, - true - ); - theirBestWay['5001;6'] += calculate( - '5001;6', - (theirInventoryItems['5001;6']?.length || 0) - theirBestWay['5001;6'], - false, - true - ); - theirBestWay['5021;6'] += calculate( - '5021;6', - (theirInventoryItems['5021;6']?.length || 0) - theirBestWay['5021;6'], - false, - true - ); + log.debug('Add some of our items if they are still overpaying - after', { + ourBestWay + }); + } - theirBestWay['5002;6'] -= calculate('5002;6', theirBestWay['5002;6'], true); - theirBestWay['5001;6'] -= calculate('5001;6', theirBestWay['5001;6'], true); - theirBestWay['5000;6'] -= calculate('5000;6', theirBestWay['5000;6'], true); + if (NonPureWorth !== 0) { + return reject(new Error(`Couldn't counter an offer value mismatch: ${NonPureWorth}`)); + } - log.debug('NonPureWorth > 0 - theirBestWay after', { - theirBestWay + // Filter out trade items from inventories + // Now try to match this on the trade offer + Object.keys(theirItems).forEach(sku => { + theirInventoryItems[sku] = theirInventoryItems[sku]?.filter( + i => !theirItems[sku]?.find(i2 => i2.id === i.id) + ); }); - log.debug('Add some of our items if they are still overpaying - before', { - ourBestWay + Object.keys(ourItems).forEach(sku => { + ourInventoryItems[sku] = ourInventoryItems[sku]?.filter( + i => !ourItems[sku]?.find(i2 => i2.id === i.id) + ); }); - // Add some of our items if they are still overpaying - ourBestWay['5002;6'] += calculate( - '5002;6', - (ourInventoryItems['5002;6']?.length || 0) - ourBestWay['5002;6'], - true - ); - ourBestWay['5001;6'] += calculate( - '5001;6', - (ourInventoryItems['5001;6']?.length || 0) - ourBestWay['5001;6'], - true - ); - ourBestWay['5000;6'] += calculate( - '5000;6', - (ourInventoryItems['5000;6']?.length || 0) - ourBestWay['5000;6'], - true - ); - log.debug('Add some of our items if they are still overpaying - after', { - ourBestWay + [theirBestWay, ourBestWay].forEach((side, index) => { + const [sideText, inventory, tradeInventory] = + index === 0 + ? ['Their', theirInventoryItems, theirItems] + : ['My', ourInventoryItems, ourItems]; + + (Object.keys(side) as PureSKU[]).forEach(sku => { + const amount = side[sku] - (tradeInventory[sku]?.length || 0); + changeItems( + sideText as 'Their' | 'My', + amount > 0 ? inventory : tradeInventory, + amount, + sku + ); + }); }); - } - - if (NonPureWorth !== 0) { - return reject(new Error(`Couldn't counter an offer value mismatch: ${NonPureWorth}`)); - } - // Filter out trade items from inventories - // Now try to match this on the trade offer - Object.keys(theirItems).forEach(sku => { - theirInventoryItems[sku] = theirInventoryItems[sku]?.filter( - i => !theirItems[sku]?.find(i2 => i2.id === i.id) - ); - }); - - Object.keys(ourItems).forEach(sku => { - ourInventoryItems[sku] = ourInventoryItems[sku]?.filter( - i => !ourItems[sku]?.find(i2 => i2.id === i.id) + log.debug('Set counteroffer and sending...'); + setOfferDataAndSend(); + }) + .catch((err: Error) => { + log.error(`Failed to load inventories (${offer.partner.getSteamID64()}): `, err); + return reject( + new Error( + `Failed to load your inventories (Steam might down). Please try again later.` + + ` If your profile/inventory is set to private, please set it to public and try again.` + ) ); }); - - [theirBestWay, ourBestWay].forEach((side, index) => { - const [sideText, inventory, tradeInventory] = - index === 0 ? ['Their', theirInventoryItems, theirItems] : ['My', ourInventoryItems, ourItems]; - - (Object.keys(side) as PureSKU[]).forEach(sku => { - const amount = side[sku] - (tradeInventory[sku]?.length || 0); - changeItems(sideText as 'Their' | 'My', amount > 0 ? inventory : tradeInventory, amount, sku); - }); - }); - - log.debug('Set counteroffer and sending...'); - setOfferDataAndSend(); - }); }); } @@ -1212,17 +1235,20 @@ export default class Trades { if (err.message !== 'Not Logged In') { // We got an error getting the offer, retry after some time - return void Promise.delay(exponentialBackoff(attempts)).then(() => { + return void timersPromises.setTimeout(exponentialBackoff(attempts)).then(() => { resolve(this.acceptOfferRetry(offer, attempts)); }); } - return void this.bot.getWebSession(true).asCallback(err => { - // If there is no error when waiting for web session, then attempt to fetch the offer right away - void Promise.delay(err !== null ? 0 : exponentialBackoff(attempts)).then(() => { - resolve(this.acceptOfferRetry(offer, attempts)); + return void this.bot + .getWebSession(true) + .catch((err: Error) => err) + .then(err => { + // If there is no error when waiting for web session, then attempt to fetch the offer right away + void timersPromises.setTimeout(err !== null ? 0 : exponentialBackoff(attempts)).then(() => { + resolve(this.acceptOfferRetry(offer, attempts)); + }); }); - }); } return resolve(status); @@ -1268,21 +1294,27 @@ export default class Trades { log.debug('Sending offer...'); - void this.sendOfferRetry(offer, 0).asCallback((err, status) => { - const actionTime = dayjs().valueOf() - start; - offer.data('actionTime', actionTime); + void this.sendOfferRetry(offer, 0) + .then(status => { + const actionTime = dayjs().valueOf() - start; + offer.data('actionTime', actionTime); + + offer.log( + 'trade', + 'successfully created' + (status === 'pending' ? '; confirmation required' : '') + ); + + return resolve(status); + }) + .catch((err: Error) => { + const actionTime = dayjs().valueOf() - start; + offer.data('actionTime', actionTime); - if (err) { offer.itemsToGive.forEach(item => { this.unsetItemInTrade = item.assetid; }); return reject(err); - } - - offer.log('trade', 'successfully created' + (status === 'pending' ? '; confirmation required' : '')); - - return resolve(status); - }); + }); }); } @@ -1307,53 +1339,50 @@ export default class Trades { if (err.eresult === TradeOfferManager.EResult['Revoked']) { // One or more of the items does not exist in the inventories, refresh our inventory and return the error - return void this.bot.inventoryManager.getInventory.fetch().asCallback(() => { + return void this.bot.inventoryManager.getInventory.fetch().finally(() => { reject(err); }); } else if (err.eresult === TradeOfferManager.EResult['Timeout']) { // The offer may or may not have been made, will wait some time and check if if we can find a matching offer - return void Promise.delay(exponentialBackoff(attempts, 4000)).then(() => { + return void timersPromises.setTimeout(exponentialBackoff(attempts, 4000)).then(() => { // Done waiting, try and find matching offer - void this.findMatchingOffer(offer, true).asCallback((err, match) => { - if (err) { - // Failed to get offers, return error - return reject(err); - } - - if (match === null) { - // Did not find a matching offer, retry sending the offer - return resolve(this.sendOfferRetry(offer, attempts)); - } + void this.findMatchingOffer(offer, true) + .then(match => { + if (match === null) { + // Did not find a matching offer, retry sending the offer + return resolve(this.sendOfferRetry(offer, attempts)); + } - // Update the offer we attempted to send with the properties from the matching offer - offer.id = match.id; - offer.state = match.state; - offer.created = match.created; - offer.updated = match.updated; - offer.expires = match.expires; - offer.confirmationMethod = match.confirmationMethod; - - for (const property in offer._tempData) { - if (Object.prototype.hasOwnProperty.call(offer._tempData, property)) { - offer.manager.pollData.offerData = offer.manager.pollData.offerData || {}; - offer.manager.pollData.offerData[offer.id] = - offer.manager.pollData.offerData[offer.id] || {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - offer.manager.pollData.offerData[offer.id][property] = - offer._tempData[property]; + // Update the offer we attempted to send with the properties from the matching offer + offer.id = match.id; + offer.state = match.state; + offer.created = match.created; + offer.updated = match.updated; + offer.expires = match.expires; + offer.confirmationMethod = match.confirmationMethod; + + for (const property in offer._tempData) { + if (Object.prototype.hasOwnProperty.call(offer._tempData, property)) { + offer.manager.pollData.offerData = offer.manager.pollData.offerData || {}; + offer.manager.pollData.offerData[offer.id] = + offer.manager.pollData.offerData[offer.id] || {}; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + offer.manager.pollData.offerData[offer.id][property] = + offer._tempData[property]; + } } - } - delete offer._tempData; + delete offer._tempData; - offer.manager.emit('pollData', offer.manager.pollData); + offer.manager.emit('pollData', offer.manager.pollData); - return resolve( - offer.state === TradeOfferManager.ETradeOfferState['CreatedNeedsConfirmation'] - ? 'pending' - : 'sent' - ); - }); + return resolve( + offer.state === TradeOfferManager.ETradeOfferState['CreatedNeedsConfirmation'] + ? 'pending' + : 'sent' + ); + }) + .catch((err: Error) => reject(err)); }); } else if (err.eresult !== undefined) { return reject(err); @@ -1361,17 +1390,20 @@ export default class Trades { if (err.message !== 'Not Logged In') { // We got an error getting the offer, retry after some time - return void Promise.delay(exponentialBackoff(attempts)).then(() => { + return void timersPromises.setTimeout(exponentialBackoff(attempts)).then(() => { resolve(this.sendOfferRetry(offer, attempts)); }); } - return void this.bot.getWebSession(true).asCallback(err => { - // If there is no error when waiting for web session, then attempt to fetch the offer right away - void Promise.delay(err !== null ? 0 : exponentialBackoff(attempts)).then(() => { - resolve(this.sendOfferRetry(offer, attempts)); + return void this.bot + .getWebSession(true) + .catch((err: Error) => err) + .then(err => { + // If there is no error when waiting for web session, then attempt to fetch the offer right away + void timersPromises.setTimeout(err !== null ? 0 : exponentialBackoff(attempts)).then(() => { + resolve(this.sendOfferRetry(offer, attempts)); + }); }); - }); } resolve(status); @@ -1425,7 +1457,7 @@ export default class Trades { operation.reset(); // Wait for bot to sign in to retry - void this.bot.getWebSession(true).asCallback(() => { + void this.bot.getWebSession(true).finally(() => { // Callback was called, ignore error from callback and retry operation.retry(err); }); @@ -1634,16 +1666,17 @@ export default class Trades { this.bot.client.gamesPlayed([]); // Canceled offer, declined countered offer => new item assetid - void this.bot.inventoryManager.getInventory.fetch().asCallback(err => { - if (err) { + void this.bot.inventoryManager.getInventory + .fetch() + .catch(err => { log.warn('Error fetching inventory: ', err); log.debug('Retrying to fetch inventory in 30 seconds...'); clearTimeout(this.retryFetchInventoryTimeout); this.retryFetchInventory(); - } - - this.bot.handler.onTradeOfferChanged(offer, oldState, timeTakenToComplete); - }); + }) + .finally(() => { + this.bot.handler.onTradeOfferChanged(offer, oldState, timeTakenToComplete); + }); } private retryFetchInventory(): void { diff --git a/src/lib/DiscordWebhook/pricelistUpdate.ts b/src/lib/DiscordWebhook/pricelistUpdate.ts index 3cb199988..34017ff82 100644 --- a/src/lib/DiscordWebhook/pricelistUpdate.ts +++ b/src/lib/DiscordWebhook/pricelistUpdate.ts @@ -1,7 +1,7 @@ import SKU from '@tf2autobot/tf2-sku'; import SchemaManager from '@tf2autobot/tf2-schema'; import Currencies from '@tf2autobot/tf2-currencies'; -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; import { UnknownDictionary } from '../../types/common'; import { Webhook, sendWebhook } from './export'; @@ -1972,7 +1972,7 @@ class PriceUpdateQueue { this.isProcessing = true; - await sleepasync().Promise.sleep(this.sleepTime); + await timersPromises.setTimeout(this.sleepTime); if (this.isRateLimited) { this.sleepTime = 1000; diff --git a/src/lib/DiscordWebhook/pricelistUpdateFailed.ts b/src/lib/DiscordWebhook/pricelistUpdateFailed.ts index b4fb9d385..2bf395b17 100644 --- a/src/lib/DiscordWebhook/pricelistUpdateFailed.ts +++ b/src/lib/DiscordWebhook/pricelistUpdateFailed.ts @@ -2,7 +2,7 @@ import { sendWebhook } from './utils'; import { Webhook } from './interfaces'; import log from '../logger'; import { GetItemPriceResponse } from '../../classes/IPricer'; -import sleepasync from 'sleep-async'; +import * as timersPromises from 'timers/promises'; import { UnknownDictionary } from '../../types/common'; import Options from '../../classes/Options'; @@ -79,7 +79,7 @@ class PriceUpdateFailedQueue { this.isProcessing = true; if (this.size() >= 5) { - await sleepasync().Promise.sleep(500); + await timersPromises.setTimeout(500); } sendWebhook(this.url, this.priceUpdate[sku], 'pricelist-update') diff --git a/src/lib/files.ts b/src/lib/files.ts index 0ab2b483e..3b898b0b5 100644 --- a/src/lib/files.ts +++ b/src/lib/files.ts @@ -1,6 +1,7 @@ import fs from 'fs'; import writeFileAtomic from 'write-file-atomic'; import path from 'path'; +import timersPromises from 'timers/promises'; import { exponentialBackoff } from './helpers'; @@ -108,7 +109,7 @@ export function waitForWriting(checks = 0): Promise { } return new Promise(resolve => { - void Promise.delay(exponentialBackoff(checks, 100)).then(() => { + void timersPromises.setTimeout(exponentialBackoff(checks, 100)).then(() => { resolve(waitForWriting(checks + 1)); }); }); diff --git a/src/lib/pricer/pricestf/prices-tf-pricer.ts b/src/lib/pricer/pricestf/prices-tf-pricer.ts index 508a73f2c..121ce13a0 100644 --- a/src/lib/pricer/pricestf/prices-tf-pricer.ts +++ b/src/lib/pricer/pricestf/prices-tf-pricer.ts @@ -1,3 +1,4 @@ +import timersPromises from 'timers/promises'; import Currencies from '@tf2autobot/tf2-currencies'; import PricesTfSocketManager from './prices-tf-socket-manager'; import IPricer, { @@ -50,7 +51,7 @@ export default class PricesTfPricer implements IPricer { const minDelay = 200; do { - await Promise.delay(delay); + await timersPromises.setTimeout(delay); const start = new Date().getTime(); log.debug('Requesting pricelist pages...'); const response = await this.api.getPricelistPage(currentPage);