diff --git a/package-lock.json b/package-lock.json index de747191e..427eaede7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@tf2autobot/steamcommunity": "^3.48.2", "@tf2autobot/tf2": "^1.3.6", "@tf2autobot/tf2-currencies": "^2.0.1", - "@tf2autobot/tf2-schema": "^4.4.4", + "@tf2autobot/tf2-schema": "^4.5.0", "@tf2autobot/tf2-sku": "^2.0.4", "@tf2autobot/tradeoffer-manager": "^2.17.6", "async": "^3.2.5", @@ -54,7 +54,7 @@ "winston": "^3.13.0", "winston-daily-rotate-file": "^4.7.1", "write-file-atomic": "^5.0.0", - "ws": "^7.5.9" + "ws": "^7.5.10" }, "devDependencies": { "@babel/preset-typescript": "^7.24.1", @@ -793,20 +793,23 @@ } }, "node_modules/@discordjs/builders": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.7.0.tgz", - "integrity": "sha512-GDtbKMkg433cOZur8Dv6c25EHxduNIBsxeHrsRoIM8+AwmEZ8r0tEpckx/sHwTLwQPOF3e2JWloZh9ofCaMfAw==", - "dependencies": { - "@discordjs/formatters": "^0.3.3", - "@discordjs/util": "^1.0.2", - "@sapphire/shapeshift": "^3.9.3", - "discord-api-types": "0.37.61", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.8.2.tgz", + "integrity": "sha512-6wvG3QaCjtMu0xnle4SoOIeFB4y6fKMN6WZfy3BMKJdQQtPLik8KGzDwBVL/+wTtcE/ZlFjgEk74GublyEVZ7g==", + "dependencies": { + "@discordjs/formatters": "^0.4.0", + "@discordjs/util": "^1.1.0", + "@sapphire/shapeshift": "^3.9.7", + "discord-api-types": "0.37.83", "fast-deep-equal": "^3.1.3", - "ts-mixer": "^6.0.3", + "ts-mixer": "^6.0.4", "tslib": "^2.6.2" }, "engines": { "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/@discordjs/collection": { @@ -818,82 +821,100 @@ } }, "node_modules/@discordjs/formatters": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.3.3.tgz", - "integrity": "sha512-wTcI1Q5cps1eSGhl6+6AzzZkBBlVrBdc9IUhJbijRgVjCNIIIZPgqnUj3ntFODsHrdbGU8BEG9XmDQmgEEYn3w==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.4.0.tgz", + "integrity": "sha512-fJ06TLC1NiruF35470q3Nr1bi95BdvKFAF+T5bNfZJ4bNdqZ3VZ+Ttg6SThqTxm6qumSG3choxLBHMC69WXNXQ==", "dependencies": { - "discord-api-types": "0.37.61" + "discord-api-types": "0.37.83" }, "engines": { "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/@discordjs/rest": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.2.0.tgz", - "integrity": "sha512-nXm9wT8oqrYFRMEqTXQx9DUTeEtXUDMmnUKIhZn6O2EeDY9VCdwj23XCPq7fkqMPKdF7ldAfeVKyxxFdbZl59A==", - "dependencies": { - "@discordjs/collection": "^2.0.0", - "@discordjs/util": "^1.0.2", - "@sapphire/async-queue": "^1.5.0", - "@sapphire/snowflake": "^3.5.1", - "@vladfrangu/async_event_emitter": "^2.2.2", - "discord-api-types": "0.37.61", - "magic-bytes.js": "^1.5.0", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.3.0.tgz", + "integrity": "sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg==", + "dependencies": { + "@discordjs/collection": "^2.1.0", + "@discordjs/util": "^1.1.0", + "@sapphire/async-queue": "^1.5.2", + "@sapphire/snowflake": "^3.5.3", + "@vladfrangu/async_event_emitter": "^2.2.4", + "discord-api-types": "0.37.83", + "magic-bytes.js": "^1.10.0", "tslib": "^2.6.2", - "undici": "5.27.2" + "undici": "6.13.0" }, "engines": { "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/@discordjs/rest/node_modules/@discordjs/collection": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.0.0.tgz", - "integrity": "sha512-YTWIXLrf5FsrLMycpMM9Q6vnZoR/lN2AWX23/Cuo8uOOtS8eHB2dyQaaGnaF8aZPYnttf2bkLMcXn/j6JUOi3w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz", + "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==", "engines": { "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/@discordjs/util": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.2.tgz", - "integrity": "sha512-IRNbimrmfb75GMNEjyznqM1tkI7HrZOf14njX7tCAAUetyZM1Pr8hX/EK2lxBCOgWDRmigbp24fD1hdMfQK5lw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.0.tgz", + "integrity": "sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg==", "engines": { "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/@discordjs/ws": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.0.2.tgz", - "integrity": "sha512-+XI82Rm2hKnFwAySXEep4A7Kfoowt6weO6381jgW+wVdTpMS/56qCvoXyFRY0slcv7c/U8My2PwIB2/wEaAh7Q==", - "dependencies": { - "@discordjs/collection": "^2.0.0", - "@discordjs/rest": "^2.1.0", - "@discordjs/util": "^1.0.2", - "@sapphire/async-queue": "^1.5.0", - "@types/ws": "^8.5.9", - "@vladfrangu/async_event_emitter": "^2.2.2", - "discord-api-types": "0.37.61", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.1.1.tgz", + "integrity": "sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==", + "dependencies": { + "@discordjs/collection": "^2.1.0", + "@discordjs/rest": "^2.3.0", + "@discordjs/util": "^1.1.0", + "@sapphire/async-queue": "^1.5.2", + "@types/ws": "^8.5.10", + "@vladfrangu/async_event_emitter": "^2.2.4", + "discord-api-types": "0.37.83", "tslib": "^2.6.2", - "ws": "^8.14.2" + "ws": "^8.16.0" }, "engines": { "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/@discordjs/ws/node_modules/@discordjs/collection": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.0.0.tgz", - "integrity": "sha512-YTWIXLrf5FsrLMycpMM9Q6vnZoR/lN2AWX23/Cuo8uOOtS8eHB2dyQaaGnaF8aZPYnttf2bkLMcXn/j6JUOi3w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz", + "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==", "engines": { "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/@discordjs/ws/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "engines": { "node": ">=10.0.0" }, @@ -1011,14 +1032,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "engines": { - "node": ">=14" - } - }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -1983,9 +1996,9 @@ } }, "node_modules/@pm2/agent": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.3.tgz", - "integrity": "sha512-xkqqCoTf5VsciMqN0vb9jthW7olVAi4KRFNddCc7ZkeJZ3i8QwZANr4NSH2H5DvseRFHq7MiPspRY/EWAFWWTg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.4.tgz", + "integrity": "sha512-n7WYvvTJhHLS2oBb1PjOtgLpMhgImOq8sXkPBw6smeg9LJBWZjiEgPKOpR8mn9UJZsB5P3W4V/MyvNnp31LKeA==", "dependencies": { "async": "~3.2.0", "chalk": "~3.0.0", @@ -1999,7 +2012,7 @@ "pm2-axon-rpc": "~0.7.0", "proxy-agent": "~6.3.0", "semver": "~7.5.0", - "ws": "~7.4.0" + "ws": "~7.5.10" } }, "node_modules/@pm2/agent/node_modules/ansi-styles": { @@ -2093,26 +2106,6 @@ "node": ">=8" } }, - "node_modules/@pm2/agent/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/@pm2/agent/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -2298,9 +2291,9 @@ } }, "node_modules/@sapphire/snowflake": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz", - "integrity": "sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz", + "integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" @@ -2477,9 +2470,9 @@ } }, "node_modules/@tf2autobot/tf2-schema": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/@tf2autobot/tf2-schema/-/tf2-schema-4.4.4.tgz", - "integrity": "sha512-sIANOTGdbzLPLyMCJIGDosbX9wSXDIwvGXB2nMtvBSn7uLPRIyof2npNYz9Igh5Sz07j131vAuwEfL4+8OJnkg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@tf2autobot/tf2-schema/-/tf2-schema-4.5.0.tgz", + "integrity": "sha512-Wvt7mPfU0s+dHT3maBo5Dm3gtRfiwlrbLKm58DkxN5IxTwDefzPr2OjJ7a6reH0yIpfC3bE7jPahyjPiJffdaw==", "dependencies": { "@tf2autobot/tf2-sku": "^2.0.4", "async": "^3.2.5", @@ -3035,9 +3028,9 @@ "dev": true }, "node_modules/@vladfrangu/async_event_emitter": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.4.tgz", - "integrity": "sha512-ButUPz9E9cXMLgvAW8aLAKKJJsPu1dY1/l/E8xzLFuysowXygs6GBcyunK9rnGC4zTsnIc2mQo71rGw9U+Ykug==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.4.tgz", + "integrity": "sha512-ZL62PFXEIeGUI8btfJ5S8Flc286eU1ZUSjwyFQtIGXfRUDPZKO+CDJMYb1R71LjGWRZ4n202O+a6FGjsgTw58g==", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" @@ -3598,11 +3591,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -4469,60 +4462,33 @@ } }, "node_modules/discord-api-types": { - "version": "0.37.61", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.61.tgz", - "integrity": "sha512-o/dXNFfhBpYHpQFdT6FWzeO7pKc838QeeZ9d91CfVAtpr5XLK4B/zYxQbYgPdoMiTDvJfzcsLW5naXgmHGDNXw==" + "version": "0.37.83", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.83.tgz", + "integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==" }, "node_modules/discord.js": { - "version": "14.14.1", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.14.1.tgz", - "integrity": "sha512-/hUVzkIerxKHyRKopJy5xejp4MYKDPTszAnpYxzVVv4qJYf+Tkt+jnT2N29PIPschicaEEpXwF2ARrTYHYwQ5w==", + "version": "14.15.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.15.3.tgz", + "integrity": "sha512-/UJDQO10VuU6wQPglA4kz2bw2ngeeSbogiIPx/TsnctfzV/tNf+q+i1HlgtX1OGpeOBpJH9erZQNO5oRM2uAtQ==", "dependencies": { - "@discordjs/builders": "^1.7.0", + "@discordjs/builders": "^1.8.2", "@discordjs/collection": "1.5.3", - "@discordjs/formatters": "^0.3.3", - "@discordjs/rest": "^2.1.0", - "@discordjs/util": "^1.0.2", - "@discordjs/ws": "^1.0.2", - "@sapphire/snowflake": "3.5.1", - "@types/ws": "8.5.9", - "discord-api-types": "0.37.61", + "@discordjs/formatters": "^0.4.0", + "@discordjs/rest": "^2.3.0", + "@discordjs/util": "^1.1.0", + "@discordjs/ws": "^1.1.1", + "@sapphire/snowflake": "3.5.3", + "discord-api-types": "0.37.83", "fast-deep-equal": "3.1.3", "lodash.snakecase": "4.1.1", "tslib": "2.6.2", - "undici": "5.27.2", - "ws": "8.14.2" + "undici": "6.13.0" }, "engines": { "node": ">=16.11.0" - } - }, - "node_modules/discord.js/node_modules/@types/ws": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.9.tgz", - "integrity": "sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/discord.js/node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/doctrine": { @@ -4690,27 +4656,27 @@ } }, "node_modules/engine.io-client": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", - "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz", + "integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.11.0", + "ws": "~8.17.1", "xmlhttprequest-ssl": "~2.0.0" } }, "node_modules/engine.io-client/node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -5446,9 +5412,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -10950,14 +10916,11 @@ "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" }, "node_modules/undici": { - "version": "5.27.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz", - "integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.13.0.tgz", + "integrity": "sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==", "engines": { - "node": ">=14.0" + "node": ">=18.0" } }, "node_modules/undici-types": { @@ -11429,9 +11392,9 @@ } }, "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "engines": { "node": ">=8.3.0" }, diff --git a/package.json b/package.json index 97095fd9e..0872746c6 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@tf2autobot/steamcommunity": "^3.48.2", "@tf2autobot/tf2": "^1.3.6", "@tf2autobot/tf2-currencies": "^2.0.1", - "@tf2autobot/tf2-schema": "^4.4.4", + "@tf2autobot/tf2-schema": "^4.5.0", "@tf2autobot/tf2-sku": "^2.0.4", "@tf2autobot/tradeoffer-manager": "^2.17.6", "async": "^3.2.5", @@ -71,7 +71,7 @@ "winston": "^3.13.0", "winston-daily-rotate-file": "^4.7.1", "write-file-atomic": "^5.0.0", - "ws": "^7.5.9" + "ws": "^7.5.10" }, "devDependencies": { "@babel/preset-typescript": "^7.24.1", diff --git a/src/app.ts b/src/app.ts index bdcfdc1c8..017e4d29b 100644 --- a/src/app.ts +++ b/src/app.ts @@ -64,14 +64,12 @@ import { apiRequest } from './lib/apiRequest'; /*eslint-disable */ SchemaManager.prototype.getSchema = function (callback): void { - apiRequest('GET', 'https://schema.autobot.tf/schema') + apiRequest({ method: 'GET', url: 'https://schema.autobot.tf/schema' }) .then(schema => { this.setSchema(schema, true); callback(null, this.schema); }) - .catch(err => { - callback(err); - }); + .catch(err => callback(err)); }; /*eslint-enable */ @@ -86,9 +84,7 @@ const botManager = new BotManager( import ON_DEATH from 'death'; import * as inspect from 'util'; import { Webhook } from './classes/DiscordWebhook/interfaces'; -import axios, { AxiosError } from 'axios'; import { uptime } from './lib/tools/time'; -import filterAxiosError from '@tf2autobot/filter-axios-error'; ON_DEATH({ uncaughtException: true })((signalOrErr, origin: string | Error) => { const crashed = !['SIGINT', 'SIGTERM'].includes(signalOrErr as 'SIGINT' | 'SIGTERM' | 'SIGQUIT'); @@ -143,13 +139,9 @@ ON_DEATH({ uncaughtException: true })((signalOrErr, origin: string | Error) => { ] }; - void axios({ - method: 'POST', - url: optDW.sendAlert.url.main, - data: sendAlertWebhook // axios should automatically set Content-Type header to application/json - }).catch((err: AxiosError) => { - log.error('Error sending webhook on crash', filterAxiosError(err)); - }); + apiRequest({ method: 'POST', url: optDW.sendAlert.url.main, data: sendAlertWebhook }).catch(err => + log.error('Error sending webhook on crash', err) + ); } if (botReady) { diff --git a/src/classes/Autokeys/Autokeys.ts b/src/classes/Autokeys/Autokeys.ts index 60f7b2595..16b843425 100644 --- a/src/classes/Autokeys/Autokeys.ts +++ b/src/classes/Autokeys/Autokeys.ts @@ -124,9 +124,7 @@ export default class Autokeys { check(): void { log.debug(`checking autokeys (Enabled: ${String(this.isEnabled)})`); - if (this.isEnabled === false) { - return; - } + if (this.isEnabled === false) return; const userPure = this.userPure; @@ -319,7 +317,6 @@ export default class Autokeys { if (setMaxKeys === currKeys) { setMaxKeys += 1; } - if (currKeys >= setMaxKeys) { setMaxKeys = currKeys + 1; } @@ -354,152 +351,107 @@ export default class Autokeys { rKeysCanSell !== this.oldAmount.keysCanSell || currKeys !== this.oldAmount.ofKeys); - if (this.isActive) { - // if Autokeys already running + const alertLowPure = () => { + const msg = 'I am now low on both keys and refs.'; + if (opt.sendAlert.enable && opt.sendAlert.autokeys.lowPure) { + if (opt.discordWebhook.sendAlert.enable && opt.discordWebhook.sendAlert.url.main !== '') + sendAlert('lowPure', this.bot, msg); + else this.bot.messageAdmins(msg, []); + } + }; + + const common1 = () => { + this.setOverallStatus = [false, true, false, true, false, false]; + this.setOldAmount = [0, 0, rKeysCanBankMin, rKeysCanBankMax, currKeys]; + this.setActiveStatus = true; + }; + + const common2 = () => { + this.setOverallStatus = [true, false, false, false, true, false]; + this.setOldAmount = [0, rKeysCanBankMax, 0, 0, currKeys]; + this.setActiveStatus = true; + }; + + const common3 = () => { + this.setOverallStatus = [true, false, false, false, true, false]; + this.setOldAmount = [0, rKeysCanBuy, 0, 0, currKeys]; + this.setActiveStatus = true; + }; + + const common4 = () => { + this.setOverallStatus = [false, false, false, false, false, true]; + this.setOldAmount = [rKeysCanSell, 0, 0, 0, currKeys]; + this.setActiveStatus = true; + }; + + const common5 = () => { + this.setOverallStatus = [false, false, true, false, false, false]; + this.setActiveStatus = false; + alertLowPure(); + }; + + const isNotInPricelist = this.bot.pricelist.getPrice({ priceKey: '5021;6', onlyEnabled: false }) === null; + + if (this.isActive || (!this.isActive && !isNotInPricelist)) { + // if Autokeys already running OR Not running and exist in pricelist if (isBanking) { // enable keys banking - if banking conditions to enable banking matched and banking is enabled - this.setOverallStatus = [false, true, false, true, false, false]; - this.setOldAmount = [0, 0, rKeysCanBankMin, rKeysCanBankMax, currKeys]; - this.setActiveStatus = true; + common1(); this.updateToBank(setMinKeys, setMaxKeys, currKeyPrice); // } else if (isTooManyRefWhileBanking) { // enable keys banking - if refs > minRefs but Keys < minKeys, will buy keys. - this.setOverallStatus = [true, false, false, false, true, false]; - this.setOldAmount = [0, rKeysCanBankMax, 0, 0, currKeys]; - this.setActiveStatus = true; + common2(); this.update(setMinKeys, setMaxKeys, currKeyPrice, 'buy'); // } else if (buyKeys) { // enable Autokeys - Buying - if buying keys conditions matched - this.setOverallStatus = [true, false, false, false, true, false]; - this.setOldAmount = [0, rKeysCanBuy, 0, 0, currKeys]; - this.setActiveStatus = true; + common3(); this.update(setMinKeys, setMaxKeys, currKeyPrice, 'buy'); // } else if (sellKeys) { // enable Autokeys - Selling - if selling keys conditions matched - this.setOverallStatus = [false, false, false, false, false, true]; - this.setOldAmount = [rKeysCanSell, 0, 0, 0, currKeys]; - this.setActiveStatus = true; + common4(); this.update(setMinKeys, setMaxKeys, currKeyPrice, 'sell'); // - } else if (isRemoveBankingKeys && isEnableKeyBanking) { + } else if ( + this.isActive && + ((isRemoveBankingKeys && isEnableKeyBanking) || (isRemoveAutoKeys && !isEnableKeyBanking)) + ) { // disable keys banking - if to conditions to disable banking matched and banking is enabled this.setOverallStatus = [false, false, false, false, false, false]; this.setActiveStatus = false; void this.disable(currKeyPrice); // - } else if (isRemoveAutoKeys && !isEnableKeyBanking) { - // disable Autokeys when conditions to disable Autokeys matched - this.setOverallStatus = [false, false, false, false, false, false]; - this.setActiveStatus = false; - void this.disable(currKeyPrice); - // } else if (isAlertAdmins && !this.status.checkAlertOnLowPure) { // alert admins when low pure - this.setOverallStatus = [false, false, true, false, false, false]; - this.setActiveStatus = false; - - const msg = 'I am now low on both keys and refs.'; - if (opt.sendAlert.enable && opt.sendAlert.autokeys.lowPure) { - if (opt.discordWebhook.sendAlert.enable && opt.discordWebhook.sendAlert.url.main !== '') { - sendAlert('lowPure', this.bot, msg); - } else { - this.bot.messageAdmins(msg, []); - } - } + common5(); } - } else { - // if Autokeys is not running/disabled - if (this.bot.pricelist.getPrice({ priceKey: '5021;6', onlyEnabled: false }) === null) { - // if Mann Co. Supply Crate Key entry does not exist in the pricelist.json - if (isBankingKeys && isEnableKeyBanking) { - //create new Key entry and enable keys banking - if banking conditions to enable banking matched and banking is enabled - this.setOverallStatus = [false, true, false, true, false, false]; - this.setOldAmount = [0, 0, rKeysCanBankMin, rKeysCanBankMax, currKeys]; - this.setActiveStatus = true; - this.createToBank(setMinKeys, setMaxKeys, currKeyPrice); - // - } else if (isBankingBuyKeysWithEnoughRefs && isEnableKeyBanking) { - // enable keys banking - if refs > minRefs but Keys < minKeys, will buy keys. - this.setOverallStatus = [true, false, false, false, true, false]; - this.setOldAmount = [0, rKeysCanBankMax, 0, 0, currKeys]; - this.setActiveStatus = true; - this.create(setMinKeys, setMaxKeys, currKeyPrice, 'buy'); - // - } else if (isBuyingKeys) { - // create new Key entry and enable Autokeys - Buying - if buying keys conditions matched - this.setOverallStatus = [true, false, false, false, true, false]; - this.setOldAmount = [0, rKeysCanBuy, 0, 0, currKeys]; - this.setActiveStatus = true; - this.create(setMinKeys, setMaxKeys, currKeyPrice, 'buy'); - // - } else if (isSellingKeys) { - // create new Key entry and enable Autokeys - Selling - if selling keys conditions matched - this.setOverallStatus = [false, false, false, false, false, true]; - this.setOldAmount = [rKeysCanSell, 0, 0, 0, currKeys]; - this.setActiveStatus = true; - this.create(setMinKeys, setMaxKeys, currKeyPrice, 'sell'); - // - } else if (isAlertAdmins && !this.status.checkAlertOnLowPure) { - // alert admins when low pure - this.setOverallStatus = [false, false, true, false, false, false]; - this.setActiveStatus = false; - - const msg = 'I am now low on both keys and refs.'; - if (opt.sendAlert.enable && opt.sendAlert.autokeys.lowPure) { - if (opt.discordWebhook.sendAlert.enable && opt.discordWebhook.sendAlert.url.main !== '') { - sendAlert('lowPure', this.bot, msg); - } else { - this.bot.messageAdmins(msg, []); - } - } - } - } else { - // if Mann Co. Supply Crate Key entry already in the pricelist.json - if (isBanking) { - // enable keys banking - if banking conditions to enable banking matched and banking is enabled - this.setOverallStatus = [false, true, false, true, false, false]; - this.setOldAmount = [0, 0, rKeysCanBankMin, rKeysCanBankMax, currKeys]; - this.setActiveStatus = true; - this.updateToBank(setMinKeys, setMaxKeys, currKeyPrice); - // - } else if (isTooManyRefWhileBanking) { - // enable keys banking - if refs > minRefs but Keys < minKeys, will buy keys. - this.setOverallStatus = [true, false, false, false, true, false]; - this.setOldAmount = [0, rKeysCanBankMax, 0, 0, currKeys]; - this.setActiveStatus = true; - this.update(setMinKeys, setMaxKeys, currKeyPrice, 'buy'); - // - } else if (buyKeys) { - // enable Autokeys - Buying - if buying keys conditions matched - this.setOverallStatus = [true, false, false, false, true, false]; - this.setOldAmount = [0, rKeysCanBuy, 0, 0, currKeys]; - this.setActiveStatus = true; - this.update(setMinKeys, setMaxKeys, currKeyPrice, 'buy'); - // - } else if (sellKeys) { - // enable Autokeys - Selling - if selling keys conditions matched - this.setOverallStatus = [false, false, false, false, false, true]; - this.setOldAmount = [rKeysCanSell, 0, 0, 0, currKeys]; - this.setActiveStatus = true; - this.update(setMinKeys, setMaxKeys, currKeyPrice, 'sell'); - // - } else if (isAlertAdmins && !this.status.checkAlertOnLowPure) { - // alert admins when low pure - this.setOverallStatus = [false, false, true, false, false, false]; - this.setActiveStatus = false; - - const msg = 'I am now low on both keys and refs.'; - if (opt.sendAlert.enable && opt.sendAlert.autokeys.lowPure) { - if (opt.discordWebhook.sendAlert.enable && opt.discordWebhook.sendAlert.url.main !== '') { - sendAlert('lowPure', this.bot, msg); - } else { - this.bot.messageAdmins(msg, []); - } - } - } + } else if (isNotInPricelist) { + // if Autokeys is not running/disabled AND not exist in pricelist + if (isBankingKeys && isEnableKeyBanking) { + //create new Key entry and enable keys banking - if banking conditions to enable banking matched and banking is enabled + common1(); + this.createToBank(setMinKeys, setMaxKeys, currKeyPrice); + // + } else if (isBankingBuyKeysWithEnoughRefs && isEnableKeyBanking) { + // enable keys banking - if refs > minRefs but Keys < minKeys, will buy keys. + common2(); + this.create(setMinKeys, setMaxKeys, currKeyPrice, 'buy'); + // + } else if (isBuyingKeys) { + // create new Key entry and enable Autokeys - Buying - if buying keys conditions matched + common3(); + this.create(setMinKeys, setMaxKeys, currKeyPrice, 'buy'); + // + } else if (isSellingKeys) { + // create new Key entry and enable Autokeys - Selling - if selling keys conditions matched + common4(); + this.create(setMinKeys, setMaxKeys, currKeyPrice, 'sell'); + // + } else if (isAlertAdmins && !this.status.checkAlertOnLowPure) { + // alert admins when low pure + common5(); } } log.debug( @@ -689,11 +641,7 @@ export default class Autokeys { disable(keyPrices: KeyPrices): Promise { return new Promise((resolve, reject) => { const match = this.bot.pricelist.getPrice({ priceKey: '5021;6', onlyEnabled: false }); - if (match === null) { - return resolve(); - } - - if (!match.enabled) { + if (match === null || !match.enabled) { return resolve(); } diff --git a/src/classes/Bot.ts b/src/classes/Bot.ts index 89b7707f0..0861428c2 100644 --- a/src/classes/Bot.ts +++ b/src/classes/Bot.ts @@ -11,7 +11,7 @@ import TF2 from '@tf2autobot/tf2'; import dayjs, { Dayjs } from 'dayjs'; import async from 'async'; import semver from 'semver'; -import axios, { AxiosError } from 'axios'; +import { AxiosError } from 'axios'; import pluralize from 'pluralize'; import * as timersPromises from 'timers/promises'; import fs from 'fs'; @@ -44,6 +44,7 @@ import { EventEmitter } from 'events'; import { Blocked } from './MyHandler/interfaces'; import filterAxiosError from '@tf2autobot/filter-axios-error'; import { axiosAbortSignal } from '../lib/helpers'; +import { apiRequest } from '../lib/apiRequest'; export interface SteamTokens { refreshToken: string; @@ -312,13 +313,12 @@ export default class Bot { private getLocalizationFile(attempt: 'first' | 'retry' = 'first'): Promise { return new Promise((resolve, reject) => { - axios({ - method: 'get', + apiRequest({ + method: 'GET', url: `https://raw.githubusercontent.com/SteamDatabase/GameTracking-TF2/master/tf/resource/tf_${this.options.tf2Language}.txt`, signal: axiosAbortSignal(60000) }) - .then(response => { - const content = response.data as string; + .then(content => { this.tf2.setLang(content); return resolve(); }) @@ -548,26 +548,23 @@ export default class Bot { attempt: 'first' | 'retry' = 'first' ): Promise<{ version: string; canUpdateRepo: boolean; updateMessage: string }> { return new Promise((resolve, reject) => { - void axios({ + apiRequest({ method: 'GET', url: 'https://raw.githubusercontent.com/TF2Autobot/tf2autobot/master/package.json', signal: axiosAbortSignal(60000) }) - .then(response => { - /*eslint-disable */ - const data = response.data; + .then(data => { return resolve({ version: data.version, canUpdateRepo: data.updaterepo, updateMessage: data.updateMessage }); - /*eslint-enable */ }) - .catch((err: AxiosError) => { + .catch(err => { if (err instanceof AbortSignal && attempt !== 'retry') { return this.getLatestVersion('retry'); } - reject(filterAxiosError(err)); + reject(err); }); }); } @@ -1729,3 +1726,9 @@ export default class Bot { return fs.existsSync(path.resolve(__dirname, '..', '..', '.git')); } } + +interface GithubPackageJson { + version: string; + updaterepo: boolean; + updateMessage: string; +} diff --git a/src/classes/Carts/Cart.ts b/src/classes/Carts/Cart.ts index 343eb95bd..86f06ce5f 100644 --- a/src/classes/Carts/Cart.ts +++ b/src/classes/Carts/Cart.ts @@ -3,14 +3,13 @@ import dayjs from 'dayjs'; import SKU from '@tf2autobot/tf2-sku'; import TradeOfferManager, { OurTheirItemsDict, TradeOffer } from '@tf2autobot/tradeoffer-manager'; import pluralize from 'pluralize'; -import axios, { AxiosError } from 'axios'; import { UnknownDictionary } from '../../types/common'; import Bot from '../Bot'; import Pricelist from '../Pricelist'; import { BPTFGetUserInfo } from '../MyHandler/interfaces'; import log from '../../lib/logger'; import { sendAlert } from '../DiscordWebhook/export'; -import filterAxiosError from '@tf2autobot/filter-axios-error'; +import { apiRequest } from '../../lib/apiRequest'; /** * An abstract class used for sending offers @@ -569,9 +568,9 @@ export default abstract class Cart { private async getTotalBackpackSlots(steamID64: string): Promise { return new Promise(resolve => { - void axios({ - url: 'https://api.backpack.tf/api/users/info/v1', + apiRequest({ method: 'GET', + url: 'https://api.backpack.tf/api/users/info/v1', headers: { 'User-Agent': 'TF2Autobot@' + process.env.BOT_VERSION, Cookie: 'user-id=' + this.bot.userID @@ -581,19 +580,15 @@ export default abstract class Cart { steamids: steamID64 } }) - .then(response => { - const thisBody = response.data as BPTFGetUserInfo; - - const user = thisBody.users[steamID64]; + .then(body => { + const user = body.users[steamID64]; const totalBackpackSlots = user.inventory ? user.inventory['440'].slots.total : 0; return resolve(totalBackpackSlots); }) - .catch((err: AxiosError) => { - if (err) { - log.error('Failed requesting user info from backpack.tf: ', filterAxiosError(err)); - return resolve(0); - } + .catch(err => { + log.error('Failed requesting user info from backpack.tf: ', err); + return resolve(0); }); }); } diff --git a/src/classes/Carts/CartQueue.ts b/src/classes/Carts/CartQueue.ts index 00cc10800..ea3acbea5 100644 --- a/src/classes/Carts/CartQueue.ts +++ b/src/classes/Carts/CartQueue.ts @@ -67,7 +67,7 @@ export default class CartQueue { // determine whether it's good time to restart or not try { // test if backpack.tf is alive by performing bptf banned check request - await isBptfBanned(steamID, this.bot.options.bptfApiKey, this.bot.userID); + await isBptfBanned({ steamID, bptfApiKey: this.bot.options.bptfApiKey, userID: this.bot.userID }); } catch (err) { // do not restart, try again after 3 minutes clearTimeout(this.queuePositionCheck); diff --git a/src/classes/Commands/Commands.ts b/src/classes/Commands/Commands.ts index d4a689996..696777091 100644 --- a/src/classes/Commands/Commands.ts +++ b/src/classes/Commands/Commands.ts @@ -21,8 +21,7 @@ import { fixItem } from '../../lib/items'; import { UnknownDictionary } from '../../types/common'; import log from '../../lib/logger'; import { testPriceKey } from '../../lib/tools/export'; -import axios, { AxiosError } from 'axios'; -import filterAxiosError from '@tf2autobot/filter-axios-error'; +import { apiRequest } from '../../lib/apiRequest'; type Instant = 'buy' | 'b' | 'sell' | 's'; type CraftUncraft = 'craftweapon' | 'uncraftweapon'; @@ -1465,7 +1464,7 @@ const paintCanDefindexes = [ function getMptfDashboardItems(mptfApiKey: string, ignorePainted = false): Promise { return new Promise((resolve, reject) => { - void axios({ + apiRequest({ method: 'GET', url: 'https://marketplace.tf/api/Seller/GetDashboardItems/v2', headers: { @@ -1475,9 +1474,7 @@ function getMptfDashboardItems(mptfApiKey: string, ignorePainted = false): Promi key: mptfApiKey } }) - .then(response => { - const body = response.data as GetMptfDashboardItems; - + .then(body => { if (body.success === false) { return reject(body); } @@ -1508,9 +1505,7 @@ function getMptfDashboardItems(mptfApiKey: string, ignorePainted = false): Promi return resolve(toReturn); }) - .catch((err: AxiosError) => { - reject(filterAxiosError(err)); - }); + .catch(err => reject(err)); }); } diff --git a/src/classes/Commands/sub-classes/Help.ts b/src/classes/Commands/sub-classes/Help.ts index 728773257..415b78339 100644 --- a/src/classes/Commands/sub-classes/Help.ts +++ b/src/classes/Commands/sub-classes/Help.ts @@ -87,7 +87,6 @@ export default class HelpCommands { `find =[&limit=] - Get the list of filtered items detail based on the parameters 🔍`, `ppu [limit=] - Get a list of items that is currently has Partial Price Update enabled`, `getSlots or ${prefix}listings - Get current used listings slot per cap count.`, - `getSlots or !listings - Get current used listings slot per cap count.`, `groups - Get a list of groups in your pricelist 📜` ].join(`\n- ${prefix}`) ); diff --git a/src/classes/DiscordBot.ts b/src/classes/DiscordBot.ts index 68c9fd92e..ddd96ac41 100644 --- a/src/classes/DiscordBot.ts +++ b/src/classes/DiscordBot.ts @@ -33,8 +33,10 @@ export default class DiscordBot { }); // 'ready' binding should be executed BEFORE the login() is complete + /* eslint-disable */ this.client.on('ready', this.onClientReady.bind(this)); this.client.on('messageCreate', async message => this.onMessage(message)); + /* eslint-enable */ this.prefix = this.bot.options.miscSettings?.prefixes?.discord ?? this.prefix; } @@ -49,6 +51,7 @@ export default class DiscordBot { } ]); + /* eslint-disable */ this.client.on('interactionCreate', async interaction => { if (!interaction.isChatInputCommand()) return; @@ -56,6 +59,7 @@ export default class DiscordBot { await interaction.reply({ content: uptime() }); } }); + /* eslint-enable */ } catch (err) { const error = err as DiscordAPIError; @@ -174,8 +178,8 @@ export default class DiscordBot { .send(message) // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - .then(() => log.info(`Message sent to ${origMessage.author.tag} (${origMessage.author.id}): ${message}`)) - .catch(err => log.error('Failed to send message to Discord:', err)); + .then(() => log.info(`Message sent to ${origMessage.author.tag} (${origMessage.author.id}): ${message}`)); + // .catch((err: any) => log.error('Failed to send message to Discord:', err)); } private async onClientReady() { @@ -206,6 +210,7 @@ export default class DiscordBot { setPresence(type: 'online' | 'halt'): void { const opt = this.bot.options.discordChat[type]; + /* eslint-disable */ this.client?.user?.setPresence({ activities: [ { @@ -218,6 +223,7 @@ export default class DiscordBot { ], status: opt.status }); + /* eslint-enable */ } halt(): void { diff --git a/src/classes/DiscordWebhook/utils.ts b/src/classes/DiscordWebhook/utils.ts index f7ca43444..823ad1def 100644 --- a/src/classes/DiscordWebhook/utils.ts +++ b/src/classes/DiscordWebhook/utils.ts @@ -1,9 +1,10 @@ import TradeOfferManager, { TradeOffer } from '@tf2autobot/tradeoffer-manager'; -import axios, { AxiosError } from 'axios'; import { Webhook } from './interfaces'; import Bot from '../Bot'; import log from '../../lib/logger'; -import filterAxiosError, { ErrorFiltered } from '@tf2autobot/filter-axios-error'; +import { AxiosError } from 'axios'; +import { ErrorFiltered } from '@tf2autobot/filter-axios-error'; +import { apiRequest } from '../../lib/apiRequest'; export function getPartnerDetails(offer: TradeOffer, bot: Bot): Promise<{ personaName: string; avatarFull: any }> { return new Promise(resolve => { @@ -58,17 +59,9 @@ export function sendWebhook(url: string, webhook: Webhook, event: string, i?: nu }); } - void axios({ - method: 'POST', - url: url, - data: webhook - }) - .then(() => { - resolve(); - }) - .catch((err: AxiosError) => { - reject({ err: filterAxiosError(err), webhook }); - }); + apiRequest({ method: 'POST', url, data: webhook }) + .then(() => resolve()) + .catch((err: AxiosError) => reject({ err, webhook })); }); } diff --git a/src/classes/Friends.ts b/src/classes/Friends.ts index b0e968345..7d56c8cf7 100644 --- a/src/classes/Friends.ts +++ b/src/classes/Friends.ts @@ -1,8 +1,8 @@ import { EFriendRelationship } from 'steam-user'; import SteamID from 'steamid'; -import axios, { AxiosError } from 'axios'; import Bot from './Bot'; -import filterAxiosError from '@tf2autobot/filter-axios-error'; +import { SteamRequestParams } from '../types/common'; +import { apiRequest } from '../lib/apiRequest'; export default class Friends { maxFriends: number | undefined; @@ -43,45 +43,30 @@ export default class Friends { get getMaxFriends(): Promise { return new Promise((resolve, reject) => { - const params: { - steamid: string; - key?: string; - access_token?: string; - } = { + const params: SteamRequestParams = { steamid: (this.bot.client.steamID === null ? this.bot.handler.getBotInfo.steamID : this.bot.client.steamID ).getSteamID64() }; - if (this.bot.manager.apiKey) { - params.key = this.bot.manager.apiKey; - } else { - params.access_token = this.bot.manager.accessToken; - } - void axios({ - url: 'https://api.steampowered.com/IPlayerService/GetBadges/v1/', + if (this.bot.manager.apiKey) params.key = this.bot.manager.apiKey; + else params.access_token = this.bot.manager.accessToken; + + apiRequest({ method: 'GET', + url: 'https://api.steampowered.com/IPlayerService/GetBadges/v1/', params }) - .then(response => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - const result = response.data.response; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + .then(body => { + const result = body.response; const level = result.player_level; - const base = 250; const multiplier = 5; - this.maxFriends = base + level * multiplier; - resolve(this.maxFriends); }) - .catch((err: AxiosError) => { - if (err) { - return reject(filterAxiosError(err)); - } - }); + .catch(err => reject(err)); }); } } @@ -97,3 +82,23 @@ interface Friend { avatar_url_medium: string; avatar_url_full: string; } + +interface GetBadges { + response: ResponseGetBadges; +} + +interface ResponseGetBadges { + badges: BadgesGetBadges[]; + player_xp: number; + player_level: number; + player_xp_needed_to_level_up: number; + player_xp_needed_current_level: number; +} + +interface BadgesGetBadges { + badgeid: number; + level: number; + completion_time: number; + xp: number; + scarcity: number; +} diff --git a/src/classes/InventoryApis/InventoryApi.ts b/src/classes/InventoryApis/InventoryApi.ts index 0c9388582..5e09cc0b9 100644 --- a/src/classes/InventoryApis/InventoryApi.ts +++ b/src/classes/InventoryApis/InventoryApi.ts @@ -4,7 +4,6 @@ import { UnknownDictionary, UnknownDictionaryKnownValues } from 'src/types/commo import SteamID from 'steamid'; import CEconItem from '@tf2autobot/steamcommunity/classes/CEconItem'; import { EconItem } from '@tf2autobot/tradeoffer-manager'; - import Bot from '../Bot'; export default class InventoryApi { @@ -52,9 +51,9 @@ export default class InventoryApi { const userSteamID64 = typeof userID === 'string' ? userID : userID.getSteamID64(); - const [apiCallURL, apiCallParams] = this.getURLAndParams(userSteamID64, appID, contextID); + const [apiCallUrl, apiCallParams] = this.getURLAndParams(userSteamID64, appID, contextID); - if (apiCallURL === '') { + if (apiCallUrl === '') { callback(new Error('Improper usage of InventoryAPI; descendant class should define getURLAndParams')); return; } @@ -63,8 +62,8 @@ export default class InventoryApi { get([], []); function get(inventory: EconItem[], currency: EconItem[], start?: string) { - void axios({ - url: apiCallURL, + axios({ + url: apiCallUrl, params: { ...apiCallParams, start_assetid: start diff --git a/src/classes/MyHandler/MyHandler.ts b/src/classes/MyHandler/MyHandler.ts index fd897afa5..ab2d7634b 100644 --- a/src/classes/MyHandler/MyHandler.ts +++ b/src/classes/MyHandler/MyHandler.ts @@ -1,5 +1,4 @@ import SKU from '@tf2autobot/tf2-sku'; -import axios, { AxiosError } from 'axios'; import { EClanRelationship, EFriendRelationship, EPersonaState } from 'steam-user'; import TradeOfferManager, { TradeOffer, @@ -51,6 +50,7 @@ import filterAxiosError from '@tf2autobot/filter-axios-error'; import sendTf2SystemMessage from '../DiscordWebhook/sendTf2SystemMessage'; import sendTf2DisplayNotification from '../DiscordWebhook/sendTf2DisplayNotification'; import sendTf2ItemBroadcast from '../DiscordWebhook/sendTf2ItemBroadcast'; +import { apiRequest } from '../../lib/apiRequest'; const filterReasons = (reasons: string[]) => { const filtered = new Set(reasons); @@ -2050,7 +2050,7 @@ export default class MyHandler extends Handler { `accepting. Summary:\n${JSON.stringify(summarize(offer, this.bot, 'summary-accepting', false), null, 4)}` ); - if (opt.offerReceived.sendPreAcceptMessage.enable) { + if (opt.offerReceived.sendPreAcceptMessage.enable && this.bot.friends.isFriend(offer.partner)) { const preAcceptMessage = opt.customMessage.accepted.automatic; MyHandler.sendPreAcceptedMessage( @@ -2498,7 +2498,7 @@ export default class MyHandler extends Handler { return new Promise((resolve, reject) => { const steamID64 = this.bot.manager.steamID.getSteamID64(); - void axios({ + apiRequest({ url: 'https://api.backpack.tf/api/users/info/v1', method: 'GET', headers: { @@ -2510,30 +2510,23 @@ export default class MyHandler extends Handler { steamids: steamID64 } }) - .then(response => { - const body = response.data as BPTFGetUserInfo; - + .then(body => { const user = body.users[steamID64]; this.botName = user.name; this.botAvatarURL = user.avatar; this.isPremium = user.premium ? user.premium === 1 : false; return resolve(); }) - .catch((err: AxiosError) => { - if (err) { - log.error( - 'Failed requesting bot info from backpack.tf, retrying in 5 minutes: ', - filterAxiosError(err) - ); - clearTimeout(this.retryRequest); + .catch(err => { + log.error('Failed requesting bot info from backpack.tf, retrying in 5 minutes: ', err); + clearTimeout(this.retryRequest); - this.retryRequest = setTimeout(() => { - this.getBPTFAccountInfo().catch(() => { - // ignore error - }); - }, 5 * 60 * 1000); - return reject(); - } + this.retryRequest = setTimeout(() => { + this.getBPTFAccountInfo().catch(() => { + // ignore error + }); + }, 5 * 60 * 1000); + return reject(); }); }); } diff --git a/src/classes/TF2Inventory.ts b/src/classes/TF2Inventory.ts index 7c1fcf9f7..ddee37c38 100644 --- a/src/classes/TF2Inventory.ts +++ b/src/classes/TF2Inventory.ts @@ -1,8 +1,8 @@ import SteamID from 'steamid'; import TradeOfferManager from '@tf2autobot/tradeoffer-manager'; -import axios, { AxiosError } from 'axios'; import cheerio from 'cheerio'; -import filterAxiosError from '@tf2autobot/filter-axios-error'; +import { SteamRequestParams } from '../types/common'; +import { apiRequest } from '../lib/apiRequest'; // import { uid } from 'rand-token'; type TF2Attribute = { @@ -99,42 +99,27 @@ export default class TF2Inventory { private fetch(): Promise { return new Promise((resolve, reject) => { - const params: { - steamid: string; - key?: string; - access_token?: string; - } = { steamid: this.getSteamID.toString() }; - - if (this.manager.apiKey) { - params.key = this.manager.apiKey; - } else { - params.access_token = this.manager.accessToken; - } - - void axios({ - url: 'https://api.steampowered.com/IEconItems_440/GetPlayerItems/v0001/', + const params: SteamRequestParams = { steamid: this.getSteamID.toString() }; + + if (this.manager.apiKey) params.key = this.manager.apiKey; + else params.access_token = this.manager.accessToken; + + apiRequest({ method: 'GET', + url: 'https://api.steampowered.com/IEconItems_440/GetPlayerItems/v0001/', params }) - .then(response => { - const body = response.data as GetPlayerItems; - + .then(body => { if (body.result.status != 1) { const err = new Error(body.result.statusDetail); err['status'] = body.result.status; return reject(err); } - this.slots = body.result.num_backpack_slots; this.items = body.result.items; - return resolve(); }) - .catch((err: AxiosError) => { - if (err) { - return reject(filterAxiosError(err)); - } - }); + .catch(err => reject(err)); }); } @@ -147,17 +132,15 @@ export default class TF2Inventory { history?: []; }> { return new Promise((resolve, reject) => { - void axios({ - url: 'https://old.backpack.tf/item/' + assetid, + apiRequest({ method: 'GET', + url: 'https://backpack.tf/item/' + assetid, headers: { 'User-Agent': 'TF2Autobot@' + process.env.BOT_VERSION, Cookie: 'user-id=' + userID // uid(12) } }) - .then(response => { - const body = response.data as string; - + .then(body => { const $ = cheerio.load(body); if ($('table').length !== 1) { @@ -176,11 +159,7 @@ export default class TF2Inventory { history: [] }); }) - .catch((err: AxiosError) => { - if (err) { - return reject(filterAxiosError(err)); - } - }); + .catch(err => reject(err)); }); } } diff --git a/src/classes/Trades.ts b/src/classes/Trades.ts index ec96333dc..14f3059b7 100644 --- a/src/classes/Trades.ts +++ b/src/classes/Trades.ts @@ -1467,7 +1467,7 @@ export default class Trades { // determine whether it's good time to restart or not try { // test if backpack.tf is alive by performing bptf banned check request - await isBptfBanned(steamID, this.bot.options.bptfApiKey, this.bot.userID); + await isBptfBanned({ steamID, bptfApiKey: this.bot.options.bptfApiKey, userID: this.bot.userID }); } catch (err) { // do not restart, try again after 3 minutes clearTimeout(this.restartOnEscrowCheckFailed); diff --git a/src/lib/apiRequest.ts b/src/lib/apiRequest.ts index 9d1e39b7f..542553da1 100644 --- a/src/lib/apiRequest.ts +++ b/src/lib/apiRequest.ts @@ -1,19 +1,28 @@ import axios, { AxiosRequestConfig, Method, AxiosError } from 'axios'; import filterAxiosError from '@tf2autobot/filter-axios-error'; -export async function apiRequest( - httpMethod: string, - url: string, - params?: Record, - data?: Record, - headers?: Record -): Promise { +export async function apiRequest({ + method, + url, + params, + data, + headers, + apiToken +}: { + method: Method; + url: string; + params?: Record; + data?: Record; + headers?: Record; + signal?: AbortSignal; + apiToken?: string; +}): Promise { if (!headers) { headers = {}; } const options: AxiosRequestConfig = { - method: httpMethod as Method, + method, url, headers: { 'User-Agent': 'TF2Autobot@' + process.env.BOT_VERSION, @@ -30,16 +39,13 @@ export async function apiRequest( options.data = data; } + if (apiToken) { + options.headers['Authorization'] = `Token ${apiToken}`; + } + return new Promise((resolve, reject) => { - void axios(options) - .then(response => { - const body = response.data as B; - resolve(body); - }) - .catch((err: AxiosError) => { - if (err) { - reject(filterAxiosError(err)); - } - }); + axios(options) + .then(response => resolve(response.data as B)) + .catch((err: AxiosError) => reject(filterAxiosError(err))); }); } diff --git a/src/lib/bans.ts b/src/lib/bans.ts index f4ad96313..e7b6432cf 100644 --- a/src/lib/bans.ts +++ b/src/lib/bans.ts @@ -1,11 +1,10 @@ -import axios, { AxiosError } from 'axios'; import { BPTFGetUserInfo } from '../classes/MyHandler/interfaces'; import log from '../lib/logger'; -import filterAxiosError from '@tf2autobot/filter-axios-error'; import Bot from '../classes/Bot'; import { ReputationCheck } from '../classes/Options'; import { LeveledLogMethod } from 'winston'; import { axiosAbortSignal } from './helpers'; +import { apiRequest } from './apiRequest'; export type Contents = { [website: string]: string }; export interface IsBanned { @@ -18,6 +17,10 @@ interface SiteResult { content?: string; } +interface SiteResultBptf extends SiteResult { + isSteamRepBanned: boolean; +} + interface BansEntry { bot: Bot; userID?: string; @@ -192,19 +195,15 @@ export default class Bans { private resultsFromAutobot(): Promise { return new Promise((resolve, reject) => { - axios({ + apiRequest({ method: 'GET', url: `https://rep.autobot.tf/json/${this.steamID}`, params: { checkMptf: this.repOpt.checkMptfBanned } }) - .then(res => { - return resolve(res.data as RepAutobotTf); - }) - .catch(err => { - return reject(err); - }); + .then(body => resolve(body)) + .catch(err => reject(err)); }); } @@ -212,70 +211,51 @@ export default class Bans { if (!this.bot.options.bptfApiKey) { return; } + return new Promise(resolve => { - void axios({ - url: 'https://api.backpack.tf/api/users/info/v1', - headers: { - 'User-Agent': 'TF2Autobot@' + process.env.BOT_VERSION, - Cookie: 'user-id=' + this.userID - }, - params: { - key: this.bot.options.bptfApiKey, - steamids: this.steamID - } + isBptfBanned({ + steamID: this.steamID, + bptfApiKey: this.bot.options.bptfApiKey, + userID: this.userID, + showLog: true }) - .then(response => { - const user = (response.data as BPTFGetUserInfo).users[this.steamID]; - const isBptfBanned = - user.bans && (user.bans.all !== undefined || user.bans['all features'] !== undefined); - - const banReason = user.bans ? user.bans.all?.reason ?? user.bans['all features']?.reason ?? '' : ''; + .then(result => { + this._isBptfBanned = result.isBanned; + this._isBptfSteamRepBanned = result.isSteamRepBanned; - this._isBptfBanned = isBptfBanned; - this._isBptfSteamRepBanned = user.bans ? user.bans.steamrep_scammer === 1 : false; - - return resolve({ isBanned: isBptfBanned, content: banReason }); + return resolve({ isBanned: this._isBptfBanned, content: result.content }); }) - .catch((err: AxiosError) => { - if (err) { - if (this.showLog) { - log.warn('Failed to get data from backpack.tf'); - log.debug(filterAxiosError(err)); - } - return resolve(undefined); - } + .catch(err => { + log.warn('Failed to get data from backpack.tf'); + log.debug(err); + return resolve(undefined); }); }); } private isSteamRepMarked(): Promise { return new Promise(resolve => { - void axios({ + apiRequest({ + method: 'GET', url: 'https://steamrep.com/api/beta4/reputation/' + this.steamID, params: { json: 1 } }) - .then(response => { - const isSteamRepBanned = - (response.data as SteamRep).steamrep.reputation?.summary.toLowerCase().indexOf('scammer') !== - -1; - const fullRepInfo = (response.data as SteamRep).steamrep.reputation?.full ?? ''; + .then(body => { + const isSteamRepBanned = body.steamrep.reputation?.summary.toLowerCase().indexOf('scammer') !== -1; + const fullRepInfo = body.steamrep.reputation?.full ?? ''; this._isSteamRepBanned = isSteamRepBanned; return resolve({ isBanned: isSteamRepBanned, content: fullRepInfo }); }) - .catch((err: AxiosError) => { - if (err) { - if (this.showLog) { - log.warn('Failed to get data from SteamRep'); - log.debug(filterAxiosError(err)); - } - if (this._isBptfSteamRepBanned !== null) { - return resolve({ isBanned: this._isBptfSteamRepBanned }); - } - return resolve(undefined); + .catch(err => { + log.warn('Failed to get data from SteamRep'); + log.debug(err); + if (this._isBptfSteamRepBanned !== null) { + return resolve({ isBanned: this._isBptfSteamRepBanned }); } + return resolve(undefined); }); }); } @@ -290,7 +270,7 @@ export default class Bans { return reject(new Error('Marketplace.tf API key was not set.')); } - void axios({ + apiRequest({ method: 'POST', url: 'https://marketplace.tf/api/Bans/GetUserBan/v2', headers: { @@ -301,8 +281,8 @@ export default class Bans { steamid: this.steamID } }) - .then(response => { - const results = (response.data as MptfGetUserBan)?.results; + .then(body => { + const results = body?.results; if (!Array.isArray(results)) { log.debug('Marketplace.tf returned invalid data', results); @@ -323,24 +303,22 @@ export default class Bans { return resolve({ isBanned: false }); }) - .catch((err: AxiosError) => { - if (err) { - if (this.showLog) log.warn('Failed to get data from Marketplace.tf', err); - return resolve(undefined); - } + .catch(err => { + log.warn('Failed to get data from Marketplace.tf', err); + return resolve(undefined); }); }); } private isListedUntrusted(attempt: 'first' | 'retry' = 'first'): Promise { return new Promise(resolve => { - void axios({ + apiRequest({ method: 'GET', url: 'https://raw.githubusercontent.com/TF2Autobot/untrusted-steam-ids/master/untrusted.min.json', signal: axiosAbortSignal(60000) }) - .then(response => { - const results = (response.data as UntrustedJson).steamids[this.steamID]; + .then(body => { + const results = body.steamids[this.steamID]; if (results === undefined) { return resolve({ isBanned: false }); @@ -352,25 +330,32 @@ export default class Bans { content: `Reason: ${results.reason} - Source: ${results.source}` }); }) - .catch((err: AxiosError) => { + .catch(err => { if (err instanceof AbortSignal && attempt !== 'retry') { return this.isListedUntrusted('retry'); } - if (err) { - if (this.showLog) { - log.warn('Failed to get data from Github'); - log.debug(err instanceof AxiosError ? filterAxiosError(err) : err); - } - } + log.warn('Failed to get data from Github'); + log.debug(err); resolve(undefined); }); }); } } -export function isBptfBanned(steamID: string, bptfApiKey: string, userID: string, showLog = true): Promise { +export function isBptfBanned({ + steamID, + bptfApiKey, + userID, + showLog = true +}: { + steamID: string; + bptfApiKey: string; + userID: string; + showLog?: boolean; +}): Promise { return new Promise((resolve, reject) => { - void axios({ + apiRequest({ + method: 'GET', url: 'https://api.backpack.tf/api/users/info/v1', headers: { 'User-Agent': 'TF2Autobot@' + process.env.BOT_VERSION, @@ -381,19 +366,19 @@ export function isBptfBanned(steamID: string, bptfApiKey: string, userID: string steamids: steamID } }) - .then(response => { - const user = (response.data as BPTFGetUserInfo).users[steamID]; + .then(body => { + const user = body.users[steamID]; const isBptfBanned = user.bans && (user.bans.all !== undefined || user.bans['all features'] !== undefined); - + const isSteamRepBanned = user.bans ? user.bans.steamrep_scammer === 1 : false; const banReason = user.bans ? user.bans.all?.reason ?? user.bans['all features']?.reason ?? '' : ''; - return resolve({ isBanned: isBptfBanned, content: banReason }); + return resolve({ isBanned: isBptfBanned, content: banReason, isSteamRepBanned }); }) - .catch((err: AxiosError) => { + .catch(err => { if (err) { if (showLog) log.warn('Failed to get data from backpack.tf'); - return reject(filterAxiosError(err)); + return reject(err); } }); }); diff --git a/src/lib/pricer/custom/custom-pricer-api.ts b/src/lib/pricer/custom/custom-pricer-api.ts index 6bf46062b..ec42d82fa 100644 --- a/src/lib/pricer/custom/custom-pricer-api.ts +++ b/src/lib/pricer/custom/custom-pricer-api.ts @@ -88,7 +88,7 @@ export default class CustomPricerApi { }; if (this.apiToken) { - options.headers = { Authorization: `Token ${this.apiToken}` }; + options.headers['Authorization'] = `Token ${this.apiToken}`; } if (params) { @@ -100,16 +100,10 @@ export default class CustomPricerApi { } return new Promise((resolve, reject) => { - void axios(options) - .then(response => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - resolve(response.data); - }) - .catch((err: AxiosError) => { - if (err) { - reject(filterAxiosError(err)); - } - }); + axios(options) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + .then(response => resolve(response.data)) + .catch((err: AxiosError) => reject(filterAxiosError(err))); }); } diff --git a/src/lib/pricer/pricestf/prices-tf-api.ts b/src/lib/pricer/pricestf/prices-tf-api.ts index e6391d5be..d615b2a10 100644 --- a/src/lib/pricer/pricestf/prices-tf-api.ts +++ b/src/lib/pricer/pricestf/prices-tf-api.ts @@ -105,7 +105,7 @@ export default class PricesTfApi { } return new Promise((resolve, reject) => { - void axios(options) + axios(options) .then(response => { const body = response.data as B; resolve(body); diff --git a/src/types/common.d.ts b/src/types/common.d.ts index c0ca18a45..fe123dc8a 100644 --- a/src/types/common.d.ts +++ b/src/types/common.d.ts @@ -3,3 +3,9 @@ export interface UnknownDictionary { } type UnknownDictionaryKnownValues = UnknownDictionary; + +export interface SteamRequestParams { + steamid: string; + key?: string; + access_token?: string; +}