Skip to content

Commit

Permalink
🔀 Merge pull request #1711 from TF2Autobot/development
Browse files Browse the repository at this point in the history
v5.11.1
  • Loading branch information
idinium96 authored Apr 6, 2024
2 parents cf3d1d4 + 41b4b4c commit 617debe
Show file tree
Hide file tree
Showing 11 changed files with 1,147 additions and 990 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"editor.formatOnPaste": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.eslint": "explicit"
},
"editor.tabSize": 4,
"editor.insertSpaces": true,
Expand Down
1,952 changes: 1,060 additions & 892 deletions package-lock.json

Large diffs are not rendered by default.

76 changes: 38 additions & 38 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@
"updateMessage": "",
"homepage": "https://github.com/TF2Autobot/tf2autobot#readme",
"dependencies": {
"@tf2autobot/bptf-listings": "^5.7.6",
"@tf2autobot/bptf-login": "^2.3.6",
"@tf2autobot/filter-axios-error": "^1.5.2",
"@tf2autobot/bptf-listings": "^5.7.7",
"@tf2autobot/bptf-login": "^2.3.7",
"@tf2autobot/filter-axios-error": "^1.5.3",
"@tf2autobot/jsonlint": "^1.0.0",
"@tf2autobot/steamcommunity": "^3.47.2",
"@tf2autobot/tf2": "^1.3.5",
"@tf2autobot/steamcommunity": "^3.48.1",
"@tf2autobot/tf2": "^1.3.6",
"@tf2autobot/tf2-currencies": "^2.0.1",
"@tf2autobot/tf2-schema": "^4.3.1",
"@tf2autobot/tf2-schema": "^4.4.1",
"@tf2autobot/tf2-sku": "^2.0.4",
"@tf2autobot/tradeoffer-manager": "^2.15.2",
"@tf2autobot/tradeoffer-manager": "^2.17.5",
"async": "^3.2.5",
"axios": "^1.6.1",
"axios": "^1.6.8",
"bluebird": "^3.7.2",
"bluebird-global": "^1.0.1",
"body-parser": "^1.20.2",
Expand All @@ -46,10 +46,10 @@
"cheerio": "^1.0.0-rc.12",
"dayjs": "^1.11.10",
"death": "^1.1.0",
"discord.js": "^14.12.1",
"discord.js": "^14.14.1",
"dot-prop": "^6.0.1",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"isobject": "^4.0.0",
"js-levenshtein": "^1.1.6",
"jsonschema": "^1.4.1",
Expand All @@ -61,49 +61,49 @@
"pretty-ms": "^7.0.1",
"reconnecting-websocket": "^4.4.0",
"retry": "^0.13.1",
"semver": "^7.5.4",
"socket.io-client": "^4.7.2",
"semver": "^7.6.0",
"socket.io-client": "^4.7.5",
"steam-totp": "^2.1.2",
"steam-user": "^5.0.4",
"steam-user": "^5.0.8",
"steamid": "^2.0.0",
"url": "^0.11.3",
"valid-url": "^1.0.9",
"winston": "^3.11.0",
"winston": "^3.13.0",
"winston-daily-rotate-file": "^4.7.1",
"write-file-atomic": "^5.0.0",
"ws": "^7.5.9"
},
"devDependencies": {
"@babel/preset-typescript": "^7.22.5",
"@types/async": "^3.2.18",
"@types/bluebird-global": "^3.5.13",
"@types/cheerio": "^0.22.31",
"@types/death": "^1.1.2",
"@types/express": "^4.17.17",
"@types/graceful-fs": "^4.1.6",
"@types/jest": "^29.5.3",
"@types/jsonwebtoken": "^9.0.1",
"@types/node": "^18.17.1",
"@types/pluralize": "0.0.29",
"@types/request": "^2.48.8",
"@types/retry": "^0.12.2",
"@types/semver": "^7.3.13",
"@types/valid-url": "^1.0.4",
"@types/write-file-atomic": "^4.0.0",
"@types/ws": "^8.5.5",
"@babel/preset-typescript": "^7.24.1",
"@types/async": "^3.2.24",
"@types/bluebird-global": "^3.5.18",
"@types/cheerio": "^0.22.35",
"@types/death": "^1.1.5",
"@types/express": "^4.17.21",
"@types/graceful-fs": "^4.1.9",
"@types/jest": "^29.5.12",
"@types/jsonwebtoken": "^9.0.6",
"@types/node": "^20.12.5",
"@types/pluralize": "^0.0.33",
"@types/request": "^2.48.12",
"@types/retry": "^0.12.5",
"@types/semver": "^7.5.8",
"@types/valid-url": "^1.0.7",
"@types/write-file-atomic": "^4.0.3",
"@types/ws": "^8.5.10",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"eslint": "^8.46.0",
"eslint-config-prettier": "^8.9.0",
"eslint-plugin-jest": "^27.2.3",
"eslint": "^8.57.0",
"eslint-config-prettier": "^8.10.0",
"eslint-plugin-jest": "^27.9.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-tsdoc": "^0.2.17",
"global-agent": "^3.0.0",
"jest": "^29.6.2",
"jest": "^29.7.0",
"prettier": "^2.8.7",
"socket.io-mock": "^1.3.2",
"ts-jest": "^29.1.1",
"typescript": "^5.1.6"
"ts-jest": "^29.1.2",
"typescript": "^5.4.4"
},
"private": true,
"_moduleAliases": {
Expand Down
4 changes: 4 additions & 0 deletions src/classes/Bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ export default class Bot {
this.manager = new TradeOfferManager({
steam: this.client,
community: this.community,
// useAccessToken: false, // https://github.com/DoctorMcKay/node-steam-tradeoffer-manager/wiki/Access-Tokens
language: 'en',
pollInterval: -1,
cancelTime: 15 * 60 * 1000,
Expand Down Expand Up @@ -1612,6 +1613,9 @@ export default class Bot {
if (err.eresult === EResult.LoggedInElsewhere) {
log.warn('Signed in elsewhere, stopping the bot...');
this.botManager.stop(err, false, true);
} else if (err.eresult === EResult.AccessDenied) {
// Access denied during login
await this.deleteRefreshToken();
} else if (err.eresult === EResult.LogonSessionReplaced) {
this.sessionReplaceCount++;

Expand Down
4 changes: 2 additions & 2 deletions src/classes/Carts/UserCart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ export default class UserCart extends Cart {
let findByPartialSku = false;
let elevatedStrange = false;
const item_object = SKU.fromString(sku);
if (item_object.quality == 5 && !item_object.effect) {
if (item_object.quality == 5 && !item_object.effect && item_object.craftable) {
log.debug('Generic Unusual in their cart, finding by partial sku');
findByPartialSku = true;
if (item_object.quality2 == 11) {
Expand Down Expand Up @@ -767,7 +767,7 @@ export default class UserCart extends Cart {
const item_object = SKU.fromString(sku);
let findByPartialSku = false;
let elevatedStrange = false;
if (item_object.quality == 5 && !item_object.effect) {
if (item_object.quality == 5 && !item_object.effect && item_object.craftable) {
findByPartialSku = true;
if (item_object.quality2 == 11) {
elevatedStrange = true;
Expand Down
2 changes: 1 addition & 1 deletion src/classes/Commands/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ export default class Commands {
this.buyBPTFPremiumCommand(steamID, message);
} else if (command === 'refreshschema' && isAdmin) {
this.manager.refreshSchema(steamID);
} else if (command === 'crafttoken' && isAdmin) {
} else if (['crafttoken', 'ct'].includes(command) && isAdmin) {
this.crafting.craftTokenCommand(steamID, message);
} else {
const custom = this.bot.options.customMessage.commandNotFound;
Expand Down
62 changes: 29 additions & 33 deletions src/classes/Commands/sub-classes/Crafting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import {

const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);

const classes = ['scout', 'soldier', 'pyro', 'demoman', 'heavy', 'engineer', 'medic', 'sniper', 'spy'];
const slotType = ['primary', 'secondary', 'melee', 'pda2'];
const combineToken = classes.concat(slotType);

export default class CraftingCommands {
private craftWeaponsBySlot: CraftWeaponsBySlot;

Expand Down Expand Up @@ -47,56 +51,47 @@ export default class CraftingCommands {
return this.getCraftTokenInfo(steamID);
}

if (parts.length < 3) {
if (parts.length < 2) {
return this.bot.sendMessage(
steamID,
'❌ Wrong syntax. Correct syntax: !craftToken <tokenType> <subTokenType> <amount>' +
'\n - tokenType: "class" or "slot"' +
'\n - subTokenType: one of the 9 TF2 class characters if TokenType is class, or "primary"/"secondary"/"melee"/"pda2" if TokenType is slot' +
'❌ Wrong syntax. Correct syntax: !craftToken <tokenName> <amount>' +
'\n - TokenName: one of the 9 TF2 class characters, or "primary"/"secondary"/"melee"/"pda2" slot' +
'\n - amount: Must be an integer, or "max"'
);
}

const tokenType = parts[0];
const subTokenType = parts[1];
const amount: number | 'max' = parts[2] === 'max' ? 'max' : parseInt(parts[2]);
const tokenName = parts[0];
const amount: number | 'max' = parts[1] === 'max' ? 'max' : parseInt(parts[1]);

if (amount !== 'max') {
if (isNaN(amount)) {
return this.bot.sendMessage(steamID, '❌ Amount must be type integer!');
}
}

if (!['class', 'slot'].includes(tokenType)) {
return this.bot.sendMessage(steamID, '❌ tokenType must only be either "class" or "slot"!');
}

const classes = ['scout', 'soldier', 'pyro', 'demoman', 'heavy', 'engineer', 'medic', 'sniper', 'spy'];
const slotType = ['primary', 'secondary', 'melee', 'pda2'];

if (tokenType === 'class' && !classes.includes(subTokenType)) {
if (!combineToken.includes(tokenName)) {
return this.bot.sendMessage(
steamID,
'❌ subTokenType must be one of 9 TF2 class character since your tokenType is "class"!'
);
} else if (tokenType === 'slot' && !slotType.includes(subTokenType)) {
return this.bot.sendMessage(
steamID,
'❌ subTokenType must only be either "primary", "secondary", "melee", or "pda2" since your tokenType is "slot"!'
'❌ Invalid token name!' +
'\n• Slot: primary/secondary/melee/pda2' +
'\n• Classes: scout/soldier/pyro/demoman/heavy/engineer/medic/sniper/spy'
);
}

if (tokenType === 'slot') {
let isSlotToken = false;

if (slotType.includes(tokenName)) {
// only load on demand
isSlotToken = true;
this.defineCraftWeaponsBySlots();
}

const assetids: string[] = [];

const craftableItems = this.bot.inventoryManager.getInventory.getCurrencies(
tokenType === 'class'
? this.bot.craftWeaponsByClass[subTokenType as ClassesForCraftableWeapons]
: this.craftWeaponsBySlot[subTokenType as SlotsForCraftableWeapons],
!isSlotToken
? this.bot.craftWeaponsByClass[tokenName as ClassesForCraftableWeapons]
: this.craftWeaponsBySlot[tokenName as SlotsForCraftableWeapons],
false
);

Expand All @@ -115,21 +110,22 @@ export default class CraftingCommands {

const availableAmount = assetids.length;
const amountCanCraft = Math.floor(availableAmount / 3);
const capTokenName = tokenName === 'pda2' ? 'PDA2' : capitalize(tokenName);
const tokenType = isSlotToken ? 'slot' : 'class';
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.`
`❌ Unable to craft ${capTokenType} Token - ${capTokenName} since I only have ${availableAmount} of ${capTokenName} ${capTokenType} 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 ` +
`have ${availableAmount} of ${capSubTokenType} ${tokenType} items.`
`❌ I can only craft ${amountCanCraft} ${capTokenType} Token - ${capTokenName} at the moment, since I only ` +
`have ${availableAmount} of ${capTokenName} ${capTokenType} items.`
);
}

Expand All @@ -141,10 +137,10 @@ export default class CraftingCommands {
const amountToCraft = amount === 'max' ? amountCanCraft : amount;
for (let i = 0; i < amountToCraft; i++) {
const assetidsToCraft = assetids.splice(0, 3);
this.bot.tf2gc.craftToken(assetidsToCraft, tokenType as TokenType, subTokenType as SubTokenType, err => {
this.bot.tf2gc.craftToken(assetidsToCraft, tokenType as TokenType, tokenName as SubTokenType, err => {
if (err) {
log.debug(
`Error crafting ${assetidsToCraft.join(', ')} for ${capTokenType} Token - ${capSubTokenType}`
`Error crafting ${assetidsToCraft.join(', ')} for ${capTokenType} Token - ${capTokenName}`
);
crafted--;
}
Expand All @@ -163,13 +159,13 @@ export default class CraftingCommands {
if (crafted < amountToCraft) {
return this.bot.sendMessage(
steamID,
`✅ Successfully crafted ${crafted} ${capTokenType} Token - ${capSubTokenType} (there were some error while crafting).`
`✅ Successfully crafted ${crafted} ${capTokenType} Token - ${capTokenName} (there were some error while crafting).`
);
}

return this.bot.sendMessage(
steamID,
`✅ Successfully crafted ${crafted} ${capTokenType} Token - ${capSubTokenType}!`
`✅ Successfully crafted ${crafted} ${capTokenType} Token - ${capTokenName}!`
);
}
});
Expand Down
4 changes: 2 additions & 2 deletions src/classes/Commands/sub-classes/Help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default class HelpCommands {
`sku <Full Item Name|Item's sku> - Get the sku of an item.`,
`owner - Get the owner's Steam profile and Backpack.tf links.`,
`discord - Get a link to join TF2Autobot and/or the owner's discord server.`,
`$more - Show more available commands list.`
`more - Show more available commands list.`
].join(`\n- ${prefix}`)
);
}
Expand Down Expand Up @@ -131,7 +131,7 @@ export default class HelpCommands {
'.\n✨=== Crafting ===✨\n- ' +
[
`${prefix}craftToken <info|check> - Check the availability to craft tokens ℹ️🔨`,
`${prefix}craftToken <tokenType> <subTokenType> <amount> - Craft Class or Slot Tokens 🔨`
`${prefix}craftToken <tokenName> <amount> - Craft Class or Slot Tokens 🔨`
].join('\n- ')
);

Expand Down
8 changes: 0 additions & 8 deletions src/classes/Handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,6 @@ export default abstract class Handler {
// empty function
}

/**
* Called when a login attempt has failed
* @param err - Error object
*/
onLoginError(err: CustomError): void {
// empty function
}

/**
* Called when a friend message has been sent to the bot
* @param steamID - SteamID object of the sender
Expand Down
12 changes: 1 addition & 11 deletions src/classes/MyHandler/MyHandler.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import SKU from '@tf2autobot/tf2-sku';
import axios, { AxiosError } from 'axios';
import { EClanRelationship, EFriendRelationship, EPersonaState, EResult } from 'steam-user';
import { EClanRelationship, EFriendRelationship, EPersonaState } from 'steam-user';
import TradeOfferManager, {
TradeOffer,
PollData,
CustomError,
ItemsDict,
Meta,
WrongAboutOffer,
Expand Down Expand Up @@ -501,15 +500,6 @@ export default class MyHandler extends Handler {
});
}

onLoginError(err: CustomError): void {
if (err.eresult === EResult.AccessDenied) {
// Access denied during login
files.deleteFile(this.paths.files.refreshToken).catch(err => {
log.warn('Failed to delete refresh token file: ', err);
});
}
}

onLoginAttempts(attempts: number[]): void {
files.writeFile(this.paths.files.loginAttempts, attempts, true).catch(err => {
log.warn('Failed to save login attempts: ', err);
Expand Down
11 changes: 9 additions & 2 deletions src/types/modules/@tf2autobot/steamcommunity/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,15 @@ declare module '@tf2autobot/steamcommunity' {

getSessionID(): string;

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
getWebAPIKey(domain: string, callback: (err?: Error, key?: string) => void);
getWebApiKey(callback: (err?: Error, key?: string) => void);

createWebApiKey(
options: { domain: string; identitySecret?: string; requestID?: string },
callback: (
err?: Error,
result?: { confirmationRequired: boolean; apiKey: string; finalizeOptions: Record<string, any> }
) => void
);

setCookies(cookies: string[]): void;

Expand Down

0 comments on commit 617debe

Please sign in to comment.