Skip to content

Commit

Permalink
🔀 Merge pull request #1270 from TF2Autobot/development
Browse files Browse the repository at this point in the history
v5.3.0
  • Loading branch information
idinium96 authored Aug 1, 2022
2 parents 5e08146 + da1a91b commit 4489d31
Show file tree
Hide file tree
Showing 19 changed files with 486 additions and 312 deletions.
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.git/**/*
.example/**/*
.github/**/*
.idea/**/*
.vscode/**
dist/**/*
node_modules/**/*
.env
npm-debug.log
package-lock.json
yarn.lock
448 changes: 292 additions & 156 deletions package-lock.json

Large diffs are not rendered by default.

19 changes: 9 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@
"updateMessage": "",
"homepage": "https://github.com/TF2Autobot/tf2autobot#readme",
"dependencies": {
"@tf2autobot/bptf-listings": "^5.6.2",
"@tf2autobot/bptf-listings": "^5.6.5",
"@tf2autobot/bptf-login": "^2.3.4",
"@tf2autobot/filter-axios-error": "^1.3.1",
"@tf2autobot/filter-axios-error": "^1.4.0",
"@tf2autobot/jsonlint": "^1.0.0",
"@tf2autobot/steamcommunity": "^3.45.4",
"@tf2autobot/tf2": "^1.2.1",
"@tf2autobot/tf2-currencies": "^2.0.1",
"@tf2autobot/tf2-schema": "^4.0.0",
"@tf2autobot/tf2-schema": "^4.2.1",
"@tf2autobot/tf2-sku": "^2.0.3",
"@tf2autobot/tradeoffer-manager": "^2.14.1",
"axios": "^0.27.2",
Expand All @@ -59,11 +59,10 @@
"retry": "^0.13.1",
"socket.io-client": "^4.5.1",
"steam-totp": "^2.1.2",
"steam-user": "^4.24.5",
"steam-user": "^4.24.6",
"steamid": "^2.0.0",
"url": "^0.11.0",
"valid-url": "^1.0.9",
"websocket-extensions": "^0.1.4",
"winston": "^3.8.1",
"winston-daily-rotate-file": "^4.7.1",
"write-file-atomic": "^4.0.1",
Expand All @@ -76,19 +75,19 @@
"@types/express": "^4.17.13",
"@types/graceful-fs": "^4.1.5",
"@types/jest": "^28.1.6",
"@types/node": "^18.0.6",
"@types/node": "^18.6.3",
"@types/pluralize": "0.0.29",
"@types/request": "^2.48.8",
"@types/retry": "^0.12.2",
"@types/semver": "^7.3.10",
"@types/valid-url": "^1.0.3",
"@types/write-file-atomic": "^4.0.0",
"@types/ws": "^8.5.3",
"@typescript-eslint/eslint-plugin": "^5.30.7",
"@typescript-eslint/parser": "^5.30.7",
"eslint": "^8.20.0",
"@typescript-eslint/eslint-plugin": "^5.32.0",
"@typescript-eslint/parser": "^5.32.0",
"eslint": "^8.21.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-jest": "^26.6.0",
"eslint-plugin-jest": "^26.7.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-tsdoc": "^0.2.16",
"jest": "^28.1.3",
Expand Down
26 changes: 18 additions & 8 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,23 +155,33 @@ botManager
if (err) {
// https://stackoverflow.com/questions/30715367/why-can-i-not-throw-inside-a-promise-catch-handler
setTimeout(() => {
if (err instanceof AxiosError) {
/*eslint-disable */
if (err.response || err.name === 'AxiosError') {
// if it's Axios error, filter the error

const e = new Error(err.message);
e['status'] = err.response?.status;

if (typeof err.response?.data === 'string' && err.response?.data.includes('<html>')) {
throw e;
e['code'] = err.code;
e['status'] = err.response?.status ?? err.status;
e['method'] = err.config?.method ?? err.method;
e['url'] = err.config?.url?.replace(/\?.+/, '') ?? err.baseURL?.replace(/\?.+/, ''); // Ignore parameters

if (typeof err.response?.data === 'string' && err.response?.data?.includes('<html>')) {
return throwErr(e);
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
e['data'] = err.response?.data;

throw e;
return throwErr(e);
}
/*eslint-enable */

throw err;
});
return throwErr(err);
}, 10);
}
});

function throwErr(err): void {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
process.emit('uncaughtException', err);
}
101 changes: 59 additions & 42 deletions src/classes/Bot.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import SteamID from 'steamid';
import SteamUser, { EResult } from 'steam-user'; // { EResult, EPersonaState } gives me crash
import { EPersonaState } from 'steam-user';
import SteamUser from 'steam-user';
import { EResult, EPersonaState } from 'steam-user';
import TradeOfferManager, { CustomError } from '@tf2autobot/tradeoffer-manager';
import SteamCommunity from '@tf2autobot/steamcommunity';
import SteamTotp from 'steam-totp';
Expand Down Expand Up @@ -793,7 +793,7 @@ 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);

const promisesChain = [
const firstTwoChain = [
async () => {
log.debug('Calling onRun');

Expand All @@ -817,32 +817,11 @@ export default class Bot {
async () => {
log.info('Signing in to Steam...');

let lastLoginFailed = false;

const successResponse = () => {
log.info('Signed in to Steam!');
};

const failResponse = (err: CustomError) => {
this.handler.onLoginError(err);
log.warn('Failed to sign in to Steam: ', err);
throw err;
};
return await this.login(data.loginKey || null);
}
];

await this.login(data.loginKey || null)
.then(successResponse)
.catch(async (err: CustomError) => {
if (!lastLoginFailed && err.eresult === 5) {
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);
}
});
},
const promisesChain = [
async () => {
log.debug('Waiting for web session');
cookies = await this.getWebSession();
Expand Down Expand Up @@ -1017,31 +996,69 @@ export default class Bot {
}
];

let promiseFirstTwo = Promise.resolve();
let promise = Promise.resolve();

return new Promise((resolve, reject) => {
const checkIfStopping = () => {
if (this.botManager.isStopping) return reject();
};

for (const promiseToChain of promisesChain) {
promise = promise.then(promiseToChain).then(checkIfStopping);
for (const promiseToChainFirstTwo of firstTwoChain) {
promiseFirstTwo = promiseFirstTwo.then(promiseToChainFirstTwo).then(checkIfStopping);
}

void promise.then(() => {
if (this.options.discordBotToken) {
this.discordBot.setPresence('online');
}
let lastLoginFailed = false;

this.manager.pollInterval = 5 * 1000;
this.setReady = true;
this.handler.onReady();
this.manager.doPoll();
this.startVersionChecker();
this.initResetCacheInterval();
const successResponse = () => {
log.info('Signed in to Steam!');
};

resolve();
});
const failResponse = (err: CustomError) => {
this.handler.onLoginError(err);
log.warn('Failed to sign in to Steam: ', err);
return reject(err);
};

promiseFirstTwo
.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);
}
})
.finally(() => {
for (const promiseToChain of promisesChain) {
promise = promise.then(promiseToChain).then(checkIfStopping);
}

promise
.then(() => {
if (this.options.discordBotToken) {
this.discordBot.setPresence('online');
}

this.manager.pollInterval = 5 * 1000;
this.setReady = true;
this.handler.onReady();
this.manager.doPoll();
this.startVersionChecker();
this.initResetCacheInterval();

resolve();
})
.catch(err => {
return reject(err);
});
});
});
}

Expand Down
9 changes: 8 additions & 1 deletion src/classes/Commands/sub-classes/Crafting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,17 @@ export default class CraftingCommands {
const capTokenType = capitalize(tokenType);
const capSubTokenType = subTokenType === 'pda2' ? 'PDA2' : capitalize(subTokenType);

if (amount === 'max' && amountCanCraft === 0) {
return this.bot.sendMessage(
steamID,
`❌ Unable to craft ${capTokenType} Token - ${capSubTokenType} since I only have of ${capSubTokenType} ${tokenType} items.`
);
}

if (amount !== 'max' && amount > amountCanCraft) {
return this.bot.sendMessage(
steamID,
`❌ I can only craft ${amountCanCraft} ${capTokenType} Token - ${capSubTokenType} at the moment, since I only ` +
`❌ I can only craft ${amountCanCraft} ${capTokenType} Token - ${capSubTokenType} at the moment, since I only ` +
`have ${availableAmount} of ${capSubTokenType} ${tokenType} items.`
);
}
Expand Down
6 changes: 5 additions & 1 deletion src/classes/Commands/sub-classes/Manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,11 @@ export default class ManagerCommands {
);

this.bot.sendMessage(steamID, '⌛ Installing packages...');
await exec(`npm install${process.env.RUN_ON_ANDROID === 'true' ? ' --no-bin-links --force' : ''}`);
await exec(
`npm install${
process.env.RUN_ON_ANDROID === 'true' ? ' --no-bin-links --force' : ''
} --omit=dev`
);

this.bot.sendMessage(steamID, '⌛ Compiling TypeScript codes into JavaScript...');
await exec('npm run build');
Expand Down
15 changes: 1 addition & 14 deletions src/classes/Commands/sub-classes/Misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import CommandParser from '../../CommandParser';
import Bot from '../../Bot';
import { Discord, Stock } from '../../Options';
import { pure, timeNow, uptime, testPriceKey } from '../../../lib/tools/export';
import { killstreakersData, sheensData, spellsData } from '../../../lib/data';
import { Paints, StrangeParts } from '@tf2autobot/tf2-schema';
import getAttachmentName from '../../../lib/tools/getAttachmentName';

type Misc = 'time' | 'uptime' | 'pure' | 'rate' | 'owner' | 'discord' | 'stock';
type CraftUncraft = 'craftweapon' | 'uncraftweapon';
Expand Down Expand Up @@ -374,15 +373,3 @@ export default class MiscCommands {
return stock;
}
}

function getKeyByValue(object: { [key: string]: any }, value: any): string {
return Object.keys(object).find(key => object[key] === value);
}

function getAttachmentName(attachment: string, pSku: string, paints: Paints, parts: StrangeParts): string {
if (attachment === 's') return getKeyByValue(spellsData, pSku);
else if (attachment === 'sp') return getKeyByValue(parts, pSku);
else if (attachment === 'ke') return getKeyByValue(killstreakersData, pSku);
else if (attachment === 'ks') return getKeyByValue(sheensData, pSku);
else if (attachment === 'p') return getKeyByValue(paints, parseInt(pSku.replace('p', '')));
}
5 changes: 3 additions & 2 deletions src/classes/Commands/sub-classes/PricelistManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2273,14 +2273,15 @@ export default class PricelistManagerCommands {
const isPremium = this.bot.handler.getBotInfo.premium;

const list = filter.map((entry, i) => {
const priceKey = entry.id ? entry.id : entry.sku;
const name = entry.name;
const stock = this.bot.inventoryManager.getInventory.getAmount({
priceKey: entry.sku,
priceKey,
includeNonNormalized: false,
tradableOnly: true
});

return `${i + 1}. ${entry.sku} - ${name}${name.length > 40 ? '\n' : ' '}(${stock}, ${entry.min}, ${
return `${i + 1}. ${priceKey} - ${name}${name.length > 40 ? '\n' : ' '}(${stock}, ${entry.min}, ${
entry.max
}, ${entry.intent === 2 ? 'bank' : entry.intent === 1 ? 'sell' : 'buy'}, ${
entry.enabled ? '✅' : '❌'
Expand Down
5 changes: 4 additions & 1 deletion src/classes/Commands/sub-classes/Request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { fixItem } from '../../../lib/items';
import { testPriceKey } from '../../../lib/tools/export';
import { UnknownDictionary } from '../../../types/common';
import IPricer, { RequestCheckFn, RequestCheckResponse } from '../../IPricer';
import Pricelist from '../../Pricelist';

export default class RequestCommands {
constructor(private readonly bot: Bot, private priceSource: IPricer) {
Expand Down Expand Up @@ -70,7 +71,9 @@ export default class RequestCommands {
}

const pricelist = this.bot.pricelist.getPrices;
const skus = Object.keys(pricelist).filter(sku => sku !== '5021;6');
const skus = Object.keys(pricelist).filter(
sku => sku !== '5021;6' && !Pricelist.isAssetId(sku) && !/;[p][0-9]+/.test(sku)
);

const total = skus.length;
const totalTime = total * 2 * 1000;
Expand Down
5 changes: 3 additions & 2 deletions src/classes/Inventory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,12 @@ export default class Inventory {
}
}

return accAmount - amountToDeduct;
return accAmount === 1 && amountToDeduct === 1 ? 1 : accAmount - amountToDeduct;
}

// else just return amount
return this.findBySKU(sku, tradableOnly).length - amountToDeduct;
const amount = this.findBySKU(sku, tradableOnly).length;
return amount === 1 && amountToDeduct === 1 ? 1 : amount - amountToDeduct;
}

getAmountOfGenerics({
Expand Down
16 changes: 2 additions & 14 deletions src/classes/Listings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import Bot from './Bot';
import Pricelist, { Entry, PricesObject } from './Pricelist';
import log from '../lib/logger';
import { exponentialBackoff } from '../lib/helpers';
import { noiseMakers, spellsData, killstreakersData, sheensData } from '../lib/data';
import { noiseMakers } from '../lib/data';
import { DictItem } from './Inventory';
import { PaintedNames } from './Options';
import { Paints, StrangeParts } from '@tf2autobot/tf2-schema';
import ListingManager from '@tf2autobot/bptf-listings';
import getAttachmentName from '../lib/tools/getAttachmentName';

export default class Listings {
private checkingAllListings = false;
Expand Down Expand Up @@ -717,18 +717,6 @@ export default class Listings {

type Attachment = 's' | 'sp' | 'ke' | 'ks' | 'p';

function getKeyByValue(object: { [key: string]: any }, value: any): string {
return Object.keys(object).find(key => object[key] === value);
}

function getAttachmentName(attachment: string, pSKU: string, paints: Paints, parts: StrangeParts): string {
if (attachment === 's') return getKeyByValue(spellsData, pSKU);
else if (attachment === 'sp') return getKeyByValue(parts, pSKU);
else if (attachment === 'ke') return getKeyByValue(killstreakersData, pSKU);
else if (attachment === 'ks') return getKeyByValue(sheensData, pSKU);
else if (attachment === 'p') return getKeyByValue(paints, parseInt(pSKU.replace('p', '')));
}

function boldDetails(str: string, style: number): string {
// https://lingojam.com/BoldTextGenerator

Expand Down
Loading

0 comments on commit 4489d31

Please sign in to comment.