diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 000000000..119b9dc8e --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,19 @@ +on: + push: + pull_request: + +jobs: + lint: + name: Lint - Node ${{ matrix.node }} + runs-on: ubuntu-latest + strategy: + matrix: + node: [ 14, 16, 18 ] + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node }} + cache: 'npm' + - run: npm install + - run: npm test diff --git a/README.md b/README.md index 173278c04..b8b6db51c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,13 @@ reddit donate on ko-fi -

rustPlusPlus ~~~ Rust+ Discord Bot

+

+ + + +

+ +

rustPlusPlus ~ Rust+ Discord Bot

A NodeJS Discord Bot that uses the [rustplus.js](https://github.com/liamcottle/rustplus.js) library to utilize the power of the [Rust+ Companion App](https://rust.facepunch.com/companion) with additional Quality-of-Life features. @@ -43,7 +49,7 @@ A NodeJS Discord Bot that uses the [rustplus.js](https://github.com/liamcottle/r > To run the bot, simply open the terminal of your choice and run the following from repository root: - $ node . + $ npm start run ## **How to update the repository** diff --git a/docs/commands.md b/docs/commands.md index 58cfec3a7..a35f1107c 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -32,9 +32,7 @@ Subcommand | Options | Description | Required ---------- | ------- | ----------- | -------- `edit` |   | Edit the properties of a Smart Alarm. |     | `id` | The ID of the Smart Alarm. | `True` -  | `name` | Rename the Smart Alarm. | `False` -  | `message` | Set the Smart Alarm notification message. | `False` -  | `image` | Set the image that best represent the Smart Alarm. | `False` +  | `image` | Set the image that best represent the Smart Alarm. | `True` ![Discord Slash Command alarm Image](images/alarms_edit.png) @@ -192,8 +190,6 @@ Subcommand | Options | Description | Required ---------- | ------- | ----------- | -------- `edit_switch` |   | Edit the properties of a Smart Switch. |     | `id` | The ID of the Smart Switch. | `True` -  | `name` | Rename the Smart Switch. | `False` -  | `command` | Set the custom command for the Smart Switch. | `False`   | `image` | Set the image that best represent the Smart Switch. | `False` `create_group` |   | Create a Smart Switch Group. |     | `group_name` | The name of the Group to be created. | `True` diff --git a/docs/discord_bot_setup.md b/docs/discord_bot_setup.md index 92e22cec5..bb287ee77 100644 --- a/docs/discord_bot_setup.md +++ b/docs/discord_bot_setup.md @@ -31,31 +31,35 @@ ![Setup Discord Bot bot token Image](images/bot_token_bot_setup.png) -9. Click on `OAuth2` and then `URL Generator`. +9. Scroll down to `Privileged Gateway Intents` and enable them all. + +![Setup Discord Bot Privileged Gateway Intents Image](images/privileged_gateway_intents_bot_setup.png) + +10. Click on `OAuth2` and then `URL Generator`. ![Setup Discord Bot oauth2 Image](images/oauth2_bot_setup.png) -10. Under `SCOPES` select `bot` and `applications.commands`. +11. Under `SCOPES` select `bot` and `applications.commands`. ![Setup Discord Bot scopes Image](images/scopes_bot_setup.png) -11. Under `BOT PERMISSIONS` select `Administrator`. +12. Under `BOT PERMISSIONS` select `Administrator`. ![Setup Discord Bot bot permissions Image](images/bot_permissions_bot_setup.png) -12. Copy the `GENERATED URL` and paste it into your URL browser. +13. Copy the `GENERATED URL` and paste it into your URL browser. ![Setup Discord Bot generated url Image](images/generated_url_bot_setup.png) -13. Add the bot to desired Discord Server and click `Continue`. +14. Add the bot to desired Discord Server and click `Continue`. ![Setup Discord Bot add bot to server Image](images/add_bot_to_server_bot_setup.png) -14. Click on `Authorise`. +15. Click on `Authorise`. ![Setup Discord Bot authorise Image](images/authorise_bot_setup.png) -15. The Bot should now be visible in your Discord Server. +16. The Bot should now be visible in your Discord Server. ![Setup Discord Bot bot in server Image](images/bot_in_server_bot_setup.png) diff --git a/docs/images/privileged_gateway_intents_bot_setup.png b/docs/images/privileged_gateway_intents_bot_setup.png new file mode 100644 index 000000000..40a379b79 Binary files /dev/null and b/docs/images/privileged_gateway_intents_bot_setup.png differ diff --git a/docs/installation.md b/docs/installation.md index 0f90fa8a3..c4e45c1f7 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -4,7 +4,7 @@ Program | Version | Download | Note ------- | ------- | -------- | ---- -`NodeJS` | >= 16.6 | [**here**](https://nodejs.org/en/download/) | Since discordjs v13 is used, the version needs to be at least 16.6. +`NodeJS` | >= 16.9 | [**here**](https://nodejs.org/en/download/) | Since discordjs v14 is used, the version needs to be at least 16.9. `Git` | Any | [**here**](https://git-scm.com/downloads) |   @@ -14,4 +14,4 @@ Open a terminal (`Git Bash` / `CMD` / `Terminal` / `PowerShell` or similar) and $ git clone https://github.com/alexemanuelol/rustPlusPlus.git $ cd rustPlusPlus - $ npm install \ No newline at end of file + $ npm install diff --git a/docs/pair_and_connect_to_server.md b/docs/pair_and_connect_to_server.md index f871487f0..bde12a354 100644 --- a/docs/pair_and_connect_to_server.md +++ b/docs/pair_and_connect_to_server.md @@ -1,6 +1,6 @@ # Pair and Connect to a Server -1. Make sure that you've setup the FCM Credentials and that the bot is currently running (`node .`). +1. Make sure that you've setup the FCM Credentials and that the bot is currently running (`npm start run`). 2. Login to the Rust server you want to play. 3. Click `ESC` and then on `Rust+`. 4. Click `PAIR WITH SERVER`. diff --git a/index.js b/index.js deleted file mode 100644 index e0246c862..000000000 --- a/index.js +++ /dev/null @@ -1,19 +0,0 @@ -const fs = require('fs'); -const Discord = require('discord.js'); -const DiscordBot = require('./src/structures/DiscordBot'); - -/* If Logs directory does not exist, create it */ -if (!fs.existsSync(`${__dirname}/src/logs`)) { - fs.mkdirSync(`${__dirname}/src/logs`); -} - -const client = new DiscordBot({ - intents: [Discord.GatewayIntentBits.Guilds, Discord.GatewayIntentBits.GuildMessages], - retryLimit: 2, - restRequestTimeout: 60000, - disableEveryone: false -}); - -client.build(); - -exports.client = client; diff --git a/index.ts b/index.ts new file mode 100644 index 000000000..1c469ba07 --- /dev/null +++ b/index.ts @@ -0,0 +1,39 @@ +const Discord = require('discord.js'); +const Fs = require('fs'); + +const DiscordBot = require('./src/structures/DiscordBot'); + +createMissingDirectories(); + +const client = new DiscordBot({ + intents: [ + Discord.GatewayIntentBits.Guilds, + Discord.GatewayIntentBits.GuildMessages, + Discord.GatewayIntentBits.MessageContent, + Discord.GatewayIntentBits.GuildMembers], + retryLimit: 2, + restRequestTimeout: 60000, + disableEveryone: false +}); + +client.build(); + +function createMissingDirectories() { + if (!Fs.existsSync(`${__dirname}/src/logs`)) { + Fs.mkdirSync(`${__dirname}/src/logs`); + } + + if (!Fs.existsSync(`${__dirname}/src/instances`)) { + Fs.mkdirSync(`${__dirname}/src/instances`); + } + + if (!Fs.existsSync(`${__dirname}/src/credentials`)) { + Fs.mkdirSync(`${__dirname}/src/credentials`); + } + + if (!Fs.existsSync(`${__dirname}/src/resources/images/maps`)) { + Fs.mkdirSync(`${__dirname}/src/resources/images/maps`); + } +} + +exports.client = client; diff --git a/join_discord.png b/join_discord.png new file mode 100644 index 000000000..5d8073513 Binary files /dev/null and b/join_discord.png differ diff --git a/package-lock.json b/package-lock.json index 413f786b1..2de78e093 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rustPlusPlus", - "version": "1.0.0", + "version": "1.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "rustPlusPlus", - "version": "1.0.0", + "version": "1.1.0", "hasInstallScript": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { @@ -20,6 +20,8 @@ "push-receiver": "^2.1.1", "rustplus.js": "github:liamcottle/rustplus.js", "translate": "^1.4.1", + "ts-node": "^10.9.1", + "typescript": "^4.8.2", "winston": "^3.3.3" } }, @@ -31,15 +33,6 @@ "node": ">=0.1.90" } }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "peer": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, "node_modules/body-parser/node_modules/qs": { "version": "6.10.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", @@ -207,6 +200,11 @@ "dom-walk": "^0.1.0" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", @@ -226,6 +224,48 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -271,6 +311,14 @@ "node": ">= 0.8" } }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/exif-parser": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", @@ -693,6 +741,11 @@ "follow-redirects": "^1.14.8" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, "node_modules/raw-body": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", @@ -707,17 +760,15 @@ "node": ">= 0.8" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "peer": true, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": ">=6.0.0" + "node": ">=12" } }, "node_modules/@jimp/plugin-color": { @@ -831,11 +882,6 @@ } } }, - "node_modules/jpeg-js": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", - "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -1122,12 +1168,6 @@ "ms": "2.0.0" } }, - "node_modules/convert-source-map/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "peer": true - }, "node_modules/@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", @@ -1372,19 +1412,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, - "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/helper-simple-access": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", @@ -1468,6 +1495,11 @@ "@jimp/custom": ">=0.3.5" } }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, "node_modules/@babel/plugin-proposal-export-namespace-from": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", @@ -1536,6 +1568,14 @@ "uuid": "bin/uuid" } }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/node-releases": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", @@ -1558,6 +1598,18 @@ "node": ">=6" } }, + "node_modules/typescript": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/@babel/plugin-transform-modules-commonjs": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", @@ -1689,6 +1741,15 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -1790,6 +1851,11 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, "node_modules/body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -2068,20 +2134,6 @@ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" }, - "node_modules/@babel/helpers": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", - "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", - "peer": true, - "dependencies": { - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.9", - "@babel/types": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -2220,15 +2272,6 @@ "node": ">=4.0.0" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -2267,6 +2310,7 @@ "name": "@liamcottle/rustplus.js", "version": "2.3.0", "resolved": "git+ssh://git@github.com/liamcottle/rustplus.js.git#a01735ee9305d81084aac6654db03f84b93024c4", + "integrity": "sha512-/xJymjRmTEX822cT5oHPKm2pzOFjrJB+/Kk8UySFh4f2n7LBuWeNznAsBOd1vI0mFptNx3MQhGUhqfa1MjUHQQ==", "license": "MIT", "dependencies": { "axios": "^0.24.0", @@ -2349,6 +2393,11 @@ "node": "*" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, "node_modules/@babel/plugin-transform-member-expression-literals": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", @@ -2555,18 +2604,6 @@ "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==" }, - "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "peer": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@babel/plugin-proposal-dynamic-import": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", @@ -2781,6 +2818,17 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/babel-plugin-dynamic-import-node": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", @@ -3072,6 +3120,11 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, "node_modules/@jimp/tiff": { "version": "0.16.1", "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.1.tgz", @@ -3331,6 +3384,11 @@ "node": ">= 0.8" } }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, "node_modules/request-promise": { "version": "4.2.6", "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", @@ -4079,6 +4137,14 @@ "node": ">=6.0.0" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", @@ -4090,23 +4156,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/core/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "peer": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/typical": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", @@ -4142,6 +4191,11 @@ "node": ">=4" } }, + "node_modules/@jimp/jpeg/node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -4549,36 +4603,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/core": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", - "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", - "peer": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-module-transforms": "^7.18.9", - "@babel/helpers": "^7.18.9", - "@babel/parser": "^7.18.10", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.18.10", - "@babel/types": "^7.18.10", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, "node_modules/@jimp/png": { "version": "0.16.1", "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.1.tgz", @@ -4592,6 +4616,11 @@ "@jimp/custom": ">=0.3.5" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -4815,16 +4844,6 @@ } }, "dependencies": { - "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "peer": true, - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, "@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", @@ -4838,40 +4857,6 @@ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==" }, - "@babel/core": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", - "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", - "peer": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-module-transforms": "^7.18.9", - "@babel/helpers": "^7.18.9", - "@babel/parser": "^7.18.10", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.18.10", - "@babel/types": "^7.18.10", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "peer": true, - "requires": { - "ms": "2.1.2" - } - } - } - }, "@babel/generator": { "version": "7.18.12", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz", @@ -5120,17 +5105,6 @@ "@babel/types": "^7.18.10" } }, - "@babel/helpers": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", - "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", - "peer": true, - "requires": { - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.9", - "@babel/types": "^7.18.9" - } - }, "@babel/highlight": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", @@ -5871,6 +5845,25 @@ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + } + } + }, "@dabh/diagnostics": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", @@ -6261,16 +6254,6 @@ "regenerator-runtime": "^0.13.3" } }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "peer": true, - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, "@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", @@ -6373,6 +6356,26 @@ "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, "@types/long": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", @@ -6400,6 +6403,16 @@ "negotiator": "0.6.3" } }, + "acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==" + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -6424,6 +6437,11 @@ "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, "array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", @@ -6739,23 +6757,6 @@ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "peer": true, - "requires": { - "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "peer": true - } - } - }, "cookie": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", @@ -6787,6 +6788,11 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -6832,6 +6838,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + }, "discord-api-types": { "version": "0.37.2", "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.2.tgz", @@ -7071,12 +7082,6 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "peer": true - }, "get-intrinsic": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", @@ -7284,11 +7289,6 @@ "regenerator-runtime": "^0.13.3" } }, - "jpeg-js": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", - "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7319,12 +7319,6 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" }, - "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "peer": true - }, "jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", @@ -7414,6 +7408,11 @@ "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", "integrity": "sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==" }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, "marky": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", @@ -8110,6 +8109,26 @@ "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz", "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==" }, + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } + }, "tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", @@ -8137,6 +8156,11 @@ "mime-types": "~2.1.24" } }, + "typescript": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==" + }, "typical": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", @@ -8221,6 +8245,11 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -8332,6 +8361,11 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" } } } \ No newline at end of file diff --git a/package.json b/package.json index a9d857127..bb0094900 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "name": "rustPlusPlus", - "version": "1.1.0", + "version": "1.2.0", "description": "A NodeJS Discord Bot that uses the rustplus.js library to utilize the power of the Rust+ Companion App with additional Quality-of-Life features.", - "main": "index.js", + "main": "index.ts", "scripts": { - "run": "node .", - "preinstall": "npx npm-force-resolutions" + "start": "ts-node .", + "preinstall": "npx npm-force-resolutions", + "test": "tsc --noEmit -p ." }, "repository": { "type": "git", @@ -28,7 +29,9 @@ "lodash": "^4.0.0", "axios": "^0.26.1", "jimp": "^0.16.1", - "translate": "^1.4.1" + "translate": "^1.4.1", + "ts-node": "^10.9.1", + "typescript": "^4.8.2" }, "resolutions": { "jpeg-js": "0.4.4" diff --git a/src/commands/alarm.js b/src/commands/alarm.js index 2e2a307ac..7d4956bde 100644 --- a/src/commands/alarm.js +++ b/src/commands/alarm.js @@ -1,151 +1,75 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); -const DiscordTools = require('../discordTools/discordTools.js'); -const { EmbedBuilder } = require('discord.js'); +const Builder = require('@discordjs/builders'); + +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); +const InstanceUtils = require('../util/instanceUtils.js'); module.exports = { - data: new SlashCommandBuilder() + data: new Builder.SlashCommandBuilder() .setName('alarm') .setDescription('Operations on Smart Alarms.') - .addSubcommand(subcommand => - subcommand - .setName('edit') - .setDescription('Edit the properties of a Smart Alarm.') - .addStringOption(option => - option.setName('id') - .setDescription('The ID of the Smart Alarm.') - .setRequired(true)) - .addStringOption(option => - option.setName('name') - .setDescription('Rename the Smart Alarm.') - .setRequired(false)) - .addStringOption(option => - option.setName('message') - .setDescription('Set the Smart Alarm notification message.') - .setRequired(false)) - .addStringOption(option => - option.setName('image') - .setDescription('Set the image that best represent the Smart Alarm.') - .setRequired(false) - .addChoices( - { - name: 'Autoturret', - value: 'autoturret' - }, - { - name: 'Boom Box', - value: 'boombox' - }, - { - name: 'Broadcaster', - value: 'broadcaster' - }, - { - name: 'Ceiling Light', - value: 'ceiling_light' - }, - { - name: 'Discofloor', - value: 'discofloor' - }, - { - name: 'Door Controller', - value: 'door_controller' - }, - { - name: 'Elevator', - value: 'elevator' - }, - { - name: 'HBHF Sensor', - value: 'hbhf_sensor' - }, - { - name: 'Heater', - value: 'heater' - }, - { - name: 'SAM site', - value: 'samsite' - }, - { - name: 'Siren Light', - value: 'siren_light' - }, - { - name: 'Smart Alarm', - value: 'smart_alarm' - }, - { - name: 'Smart Switch', - value: 'smart_switch' - }, - { - name: 'Sprinkler', - value: 'sprinkler' - }, - { - name: 'Storage Monitor', - value: 'storage_monitor' - }, - { - name: 'Christmas Lights', - value: 'xmas_light' - } - ))), + .addSubcommand(subcommand => subcommand + .setName('edit') + .setDescription('Edit the properties of a Smart Alarm.') + .addStringOption(option => option + .setName('id') + .setDescription('The ID of the Smart Alarm.') + .setRequired(true)) + .addStringOption(option => option + .setName('image') + .setDescription('Set the image that best represent the Smart Alarm.') + .setRequired(true) + .addChoices( + { name: 'Autoturret', value: 'autoturret' }, + { name: 'Boom Box', value: 'boombox' }, + { name: 'Broadcaster', value: 'broadcaster' }, + { name: 'Ceiling Light', value: 'ceiling_light' }, + { name: 'Discofloor', value: 'discofloor' }, + { name: 'Door Controller', value: 'door_controller' }, + { name: 'Elevator', value: 'elevator' }, + { name: 'HBHF Sensor', value: 'hbhf_sensor' }, + { name: 'Heater', value: 'heater' }, + { name: 'SAM site', value: 'samsite' }, + { name: 'Siren Light', value: 'siren_light' }, + { name: 'Smart Alarm', value: 'smart_alarm' }, + { name: 'Smart Switch', value: 'smart_switch' }, + { name: 'Sprinkler', value: 'sprinkler' }, + { name: 'Storage Monitor', value: 'storage_monitor' }, + { name: 'Christmas Lights', value: 'xmas_light' }))), async execute(client, interaction) { - let instance = client.readInstanceFile(interaction.guildId); + const instance = client.readInstanceFile(interaction.guildId); + const rustplus = client.rustplusInstances[interaction.guildId]; if (!await client.validatePermissions(interaction)) return; - await interaction.deferReply({ ephemeral: true }); - const id = interaction.options.getString('id'); - const name = interaction.options.getString('name'); - const message = interaction.options.getString('message'); - const image = interaction.options.getString('image'); - - let embedChanged = false; - let filesChanged = false; - switch (interaction.options.getSubcommand()) { case 'edit': { - if (!Object.keys(instance.alarms).includes(id)) { - let str = `Invalid ID: '${id}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const entityId = interaction.options.getString('id'); + const image = interaction.options.getString('image'); + + const device = InstanceUtils.getSmartDevice(interaction.guildId, entityId); + if (device === null) { + let str = `Invalid ID: '${entityId}'.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str, + instance.serverList[device.serverId].title)); client.log('WARNING', str); return; } - if (name !== null) { - instance.alarms[id].name = name; - embedChanged = true; - } - if (message !== null) { - instance.alarms[id].message = message; - embedChanged = true; - } - if (image !== null) { - instance.alarms[id].image = `${image}.png`; - embedChanged = true; - filesChanged = true; - } + const entity = instance.serverList[device.serverId].alarms[entityId]; + + if (image !== null) instance.serverList[device.serverId].alarms[entityId].image = `${image}.png`; client.writeInstanceFile(interaction.guildId, instance); - await DiscordTools.sendSmartAlarmMessage(interaction.guildId, id, embedChanged, false, filesChanged); + if (rustplus && rustplus.serverId === device.serverId) { + await DiscordMessages.sendSmartAlarmMessage(interaction.guildId, device.serverId, entityId); + } - let str = `Successfully edited Smart Alarm '${instance.alarms[id].name}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``)], - ephemeral: true - }); + let str = `Successfully edited Smart Alarm '${entity.name}'.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str, + instance.serverList[device.serverId].title)); client.log('INFO', str); } break; diff --git a/src/commands/credentials.js b/src/commands/credentials.js index 4dbd46697..35d2d6833 100644 --- a/src/commands/credentials.js +++ b/src/commands/credentials.js @@ -1,63 +1,60 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); const _ = require('lodash'); +const Builder = require('@discordjs/builders'); + +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); const DiscordTools = require('../discordTools/discordTools.js'); -const { EmbedBuilder } = require('discord.js'); module.exports = { - data: new SlashCommandBuilder() + data: new Builder.SlashCommandBuilder() .setName('credentials') .setDescription('Set/Clear the FCM Credentials for the user account.') - .addSubcommand(subcommand => - subcommand - .setName('set') - .setDescription('Set the FCM Credentials.') - .addStringOption(option => option - .setName('keys_private_key') - .setDescription('Keys Private Key.') - .setRequired(true)) - .addStringOption(option => option - .setName('keys_public_key') - .setDescription('Keys Public Key.') - .setRequired(true)) - .addStringOption(option => option - .setName('keys_auth_secret') - .setDescription('Keys Auth Secret.') - .setRequired(true)) - .addStringOption(option => option - .setName('fcm_token') - .setDescription('FCM Token.') - .setRequired(true)) - .addStringOption(option => option - .setName('fcm_push_set') - .setDescription('FCM Push Set.') - .setRequired(true)) - .addStringOption(option => option - .setName('gcm_token') - .setDescription('GCM Token.') - .setRequired(true)) - .addStringOption(option => option - .setName('gcm_android_id') - .setDescription('GCM Android ID.') - .setRequired(true)) - .addStringOption(option => option - .setName('gcm_security_token') - .setDescription('GCM Security Token.') - .setRequired(true)) - .addStringOption(option => option - .setName('gcm_app_id') - .setDescription('GCM App ID.') - .setRequired(true))) - .addSubcommand(subcommand => - subcommand - .setName('clear') - .setDescription('Clear the FCM Credentials.')) - .addSubcommand(subcommand => - subcommand - .setName('is_set') - .setDescription('Is the FCM Credentials already set for this Discord Server?')), + .addSubcommand(subcommand => subcommand + .setName('set') + .setDescription('Set the FCM Credentials.') + .addStringOption(option => option + .setName('keys_private_key') + .setDescription('Keys Private Key.') + .setRequired(true)) + .addStringOption(option => option + .setName('keys_public_key') + .setDescription('Keys Public Key.') + .setRequired(true)) + .addStringOption(option => option + .setName('keys_auth_secret') + .setDescription('Keys Auth Secret.') + .setRequired(true)) + .addStringOption(option => option + .setName('fcm_token') + .setDescription('FCM Token.') + .setRequired(true)) + .addStringOption(option => option + .setName('fcm_push_set') + .setDescription('FCM Push Set.') + .setRequired(true)) + .addStringOption(option => option + .setName('gcm_token') + .setDescription('GCM Token.') + .setRequired(true)) + .addStringOption(option => option + .setName('gcm_android_id') + .setDescription('GCM Android ID.') + .setRequired(true)) + .addStringOption(option => option + .setName('gcm_security_token') + .setDescription('GCM Security Token.') + .setRequired(true)) + .addStringOption(option => option + .setName('gcm_app_id') + .setDescription('GCM App ID.') + .setRequired(true))) + .addSubcommand(subcommand => subcommand + .setName('clear') + .setDescription('Clear the FCM Credentials.')) + .addSubcommand(subcommand => subcommand + .setName('is_set') + .setDescription('Is the FCM Credentials already set for this Discord Server?')), async execute(client, interaction) { if (!await client.validatePermissions(interaction)) return; - await interaction.deferReply({ ephemeral: true }); switch (interaction.options.getSubcommand()) { @@ -80,55 +77,45 @@ module.exports = { }; async function setCredentials(client, interaction) { - let credentials = new Object(); - credentials.fcm_credentials = {}; - - credentials.fcm_credentials.keys = {}; - credentials.fcm_credentials.keys.privateKey = interaction.options.getString('keys_private_key'); - credentials.fcm_credentials.keys.publicKey = interaction.options.getString('keys_public_key'); - credentials.fcm_credentials.keys.authSecret = interaction.options.getString('keys_auth_secret'); - - credentials.fcm_credentials.fcm = {}; - credentials.fcm_credentials.fcm.token = interaction.options.getString('fcm_token'); - credentials.fcm_credentials.fcm.pushSet = interaction.options.getString('fcm_push_set'); - - credentials.fcm_credentials.gcm = {}; - credentials.fcm_credentials.gcm.token = interaction.options.getString('gcm_token'); - credentials.fcm_credentials.gcm.androidId = interaction.options.getString('gcm_android_id'); - credentials.fcm_credentials.gcm.securityToken = interaction.options.getString('gcm_security_token'); - credentials.fcm_credentials.gcm.appId = interaction.options.getString('gcm_app_id'); - - credentials.owner = interaction.member.user.id; - - for (let guild of client.guilds.cache) { - let instance = client.readCredentialsFile(guild[0]); - if (_.isEqual(credentials, instance.credentials)) { - let str = 'FCM Credentials are already used for another discord server!'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const newCredentials = new Object(); + newCredentials.fcm_credentials = {}; + + newCredentials.fcm_credentials.keys = {}; + newCredentials.fcm_credentials.keys.privateKey = interaction.options.getString('keys_private_key'); + newCredentials.fcm_credentials.keys.publicKey = interaction.options.getString('keys_public_key'); + newCredentials.fcm_credentials.keys.authSecret = interaction.options.getString('keys_auth_secret'); + + newCredentials.fcm_credentials.fcm = {}; + newCredentials.fcm_credentials.fcm.token = interaction.options.getString('fcm_token'); + newCredentials.fcm_credentials.fcm.pushSet = interaction.options.getString('fcm_push_set'); + + newCredentials.fcm_credentials.gcm = {}; + newCredentials.fcm_credentials.gcm.token = interaction.options.getString('gcm_token'); + newCredentials.fcm_credentials.gcm.androidId = interaction.options.getString('gcm_android_id'); + newCredentials.fcm_credentials.gcm.securityToken = interaction.options.getString('gcm_security_token'); + newCredentials.fcm_credentials.gcm.appId = interaction.options.getString('gcm_app_id'); + + newCredentials.owner = interaction.member.user.id; + + for (const guild of client.guilds.cache) { + const credentials = client.readCredentialsFile(guild[0]); + if (_.isEqual(newCredentials, credentials.credentials)) { + const str = 'FCM Credentials are already used for another discord server!'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); client.log('WARNING', str); return; } } - let instance = client.readCredentialsFile(interaction.guildId); - instance.credentials = credentials; - client.writeCredentialsFile(interaction.guildId, instance); + const credentials = client.readCredentialsFile(interaction.guildId); + credentials.credentials = newCredentials; + client.writeCredentialsFile(interaction.guildId, credentials); /* Start Fcm Listener */ require('../util/FcmListener')(client, DiscordTools.getGuild(interaction.guildId)); - let str = 'FCM Credentials were set successfully!'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``)], - ephemeral: true - }); + const str = 'FCM Credentials were set successfully!'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str)); client.log('INFO', str); } @@ -137,40 +124,20 @@ async function clearCredentials(client, interaction) { client.currentFcmListeners[interaction.guildId].destroy(); } - let instance = client.readCredentialsFile(interaction.guildId); - instance.credentials = null; - client.writeCredentialsFile(interaction.guildId, instance); - - let str = 'FCM Credentials were cleared successfully!'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``)], - ephemeral: true - }); + const credentials = client.readCredentialsFile(interaction.guildId); + credentials.credentials = null; + client.writeCredentialsFile(interaction.guildId, credentials); + + const str = 'FCM Credentials were cleared successfully!'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str)); client.log('INFO', str); } async function isSetCredentials(client, interaction) { - let instance = client.readCredentialsFile(interaction.guildId); - - let embed = new EmbedBuilder() - .setTitle('Is FCM Credentials set?') - .setColor('#ce412b'); - - let str = ''; - if (instance.credentials === null) { - str = 'FCM Credentials are not currently set.'; - embed.setDescription(`\`\`\`diff\n- ${str}\n\`\`\``); - } - else { - str = 'FCM Credentials are set.'; - embed.setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``); - } + const credentials = client.readCredentialsFile(interaction.guildId); - await client.interactionEditReply(interaction, { - embeds: [embed], - ephemeral: true - }); + const str = 'FCM Credentials are ' + ((credentials.credentials === null) ? 'not currently ' : '') + 'set.'; + const isSet = (credentials.credentials === null) ? 1 : 0; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(isSet, str)); client.log('INFO', str); } \ No newline at end of file diff --git a/src/commands/customizetimers.js b/src/commands/customizetimers.js deleted file mode 100644 index 3d8dd5d39..000000000 --- a/src/commands/customizetimers.js +++ /dev/null @@ -1,204 +0,0 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); -const { EmbedBuilder } = require('discord.js'); -const Timer = require('../util/timer'); - -module.exports = { - data: new SlashCommandBuilder() - .setName('customizetimers') - .setDescription('Operations to customize In-Game timers.') - .addSubcommand(subcommand => - subcommand - .setName('cargo_ship_egress_time') - .setDescription( - 'Get/Set time for cargo ship egress stage timer for connected server, default: 50min (3000s).') - .addIntegerOption(option => - option - .setName('seconds') - .setDescription('Seconds before cargo ship enters egress stage.') - .setRequired(false))) - .addSubcommand(subcommand => - subcommand - .setName('bradley_apc_respawn_time') - .setDescription( - 'Get/Set time for Bradley APC respawn timer for connected server, default: 60 min (3600s).') - .addIntegerOption(option => - option - .setName('seconds') - .setDescription('Seconds till Bradley APC respawns.') - .setRequired(false))) - .addSubcommand(subcommand => - subcommand - .setName('crate_despawn_time') - .setDescription( - 'Get/Set time for Locked Crate despawn timer for connected server, default: 120 min (7200s).') - .addIntegerOption(option => - option - .setName('seconds') - .setDescription('Seconds till Locked Crate despawns.') - .setRequired(false))) - .addSubcommand(subcommand => - subcommand - .setName('crate_despawn_warning_time') - .setDescription( - 'Get/Set time for warning before Locked Crate despawns for connected server, default: 20 min (1200s).') - .addIntegerOption(option => - option - .setName('seconds') - .setDescription('Seconds before Locked Crate despawn warning.') - .setRequired(false))) - .addSubcommand(subcommand => - subcommand - .setName('oil_rig_crate_unlock_time') - .setDescription( - 'Get/Set time for Locked Crate on Oil Rig unlocks for connected server, default: 15 min (900s).') - .addIntegerOption(option => - option - .setName('seconds') - .setDescription('Seconds till Locked Crate on Oil Rig unlocks.') - .setRequired(false))), - - async execute(client, interaction) { - let instance = client.readInstanceFile(interaction.guildId); - - if (!await client.validatePermissions(interaction)) return; - - await interaction.deferReply({ ephemeral: true }); - - let rustplus = client.rustplusInstances[interaction.guildId]; - if (!rustplus) { - let str = 'Not currently connected to a rust server.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('WARNING', str); - return; - } - - let seconds = interaction.options.getInteger('seconds'); - - let str = ''; - switch (interaction.options.getSubcommand()) { - case 'cargo_ship_egress_time': { - if (seconds === null) { - let ms = instance.serverList[rustplus.serverId].cargoShipEgressTimeMs; - let sec = parseInt(ms / 1000); - let time = Timer.secondsToFullScale(sec); - str = `Time is currently set to: ${time} (${sec}s).`; - } - else { - let ms = seconds * 1000; - let time = Timer.secondsToFullScale(seconds); - instance.serverList[rustplus.serverId].cargoShipEgressTimeMs = ms; - client.writeInstanceFile(interaction.guildId, instance); - str = `Time was set to: ${time} (${seconds}).`; - } - } break; - - case 'bradley_apc_respawn_time': { - if (seconds === null) { - let ms = instance.serverList[rustplus.serverId].bradleyApcRespawnTimeMs; - let sec = parseInt(ms / 1000); - let time = Timer.secondsToFullScale(sec); - str = `Time is currently set to: ${time} (${sec}s).`; - } - else { - let ms = seconds * 1000; - let time = Timer.secondsToFullScale(seconds); - instance.serverList[rustplus.serverId].bradleyApcRespawnTimeMs = ms; - client.writeInstanceFile(interaction.guildId, instance); - str = `Time was set to: ${time} (${seconds}).`; - } - } break; - - case 'crate_despawn_time': { - if (seconds === null) { - let ms = instance.serverList[rustplus.serverId].lockedCrateDespawnTimeMs; - let sec = parseInt(ms / 1000); - let time = Timer.secondsToFullScale(sec); - str = `Time is currently set to: ${time} (${sec}s).`; - } - else { - let ms = seconds * 1000; - if (ms <= instance.serverList[rustplus.serverId].lockedCrateDespawnWarningTimeMs) { - let sec = instance.serverList[rustplus.serverId].lockedCrateDespawnWarningTimeMs / 1000; - sec = parseInt(sec); - let warning = `Time can not be lower than despawn warning time (${sec}s).`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${warning}\n\`\`\``)], - ephemeral: true - }); - client.log('WARNING', warning); - return; - } - - let time = Timer.secondsToFullScale(seconds); - instance.serverList[rustplus.serverId].lockedCrateDespawnTimeMs = ms; - client.writeInstanceFile(interaction.guildId, instance); - str = `Time was set to: ${time} (${seconds}).`; - } - } break; - - case 'crate_despawn_warning_time': { - if (seconds === null) { - let ms = instance.serverList[rustplus.serverId].lockedCrateDespawnWarningTimeMs; - let sec = parseInt(ms / 1000); - let time = Timer.secondsToFullScale(sec); - str = `Time is currently set to: ${time} (${sec}s).`; - } - else { - let ms = seconds * 1000; - if (ms >= instance.serverList[rustplus.serverId].lockedCrateDespawnTimeMs) { - let sec = instance.serverList[rustplus.serverId].lockedCrateDespawnTimeMs / 1000; - sec = parseInt(sec); - let warning = `Time can not be higher than despawn time (${sec}s).`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${warning}\n\`\`\``)], - ephemeral: true - }); - client.log('WARNING', warning); - return; - } - - let time = Timer.secondsToFullScale(seconds); - instance.serverList[rustplus.serverId].lockedCrateDespawnWarningTimeMs = ms; - client.writeInstanceFile(interaction.guildId, instance); - str = `Time was set to: ${time} (${seconds}).`; - } - } break; - - case 'oil_rig_crate_unlock_time': { - if (seconds === null) { - let ms = instance.serverList[rustplus.serverId].oilRigLockedCrateUnlockTimeMs; - let sec = parseInt(ms / 1000); - let time = Timer.secondsToFullScale(sec); - str = `Time is currently set to: ${time} (${sec}s).`; - } - else { - let ms = seconds * 1000; - let time = Timer.secondsToFullScale(seconds); - instance.serverList[rustplus.serverId].oilRigLockedCrateUnlockTimeMs = ms; - client.writeInstanceFile(interaction.guildId, instance); - str = `Time was set to: ${time} (${seconds}).`; - } - } break; - - default: { - } break; - } - - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('INFO', str); - }, -}; diff --git a/src/commands/help.js b/src/commands/help.js index 751f4ff4f..d7bc892e4 100644 --- a/src/commands/help.js +++ b/src/commands/help.js @@ -1,30 +1,36 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); -const { ButtonBuilder, ActionRowBuilder, ButtonStyle } = require('discord.js'); +const Builder = require('@discordjs/builders'); +const Discord = require('discord.js'); + +const DiscordButtons = require('../discordTools/discordButtons.js'); module.exports = { - data: new SlashCommandBuilder() + data: new Builder.SlashCommandBuilder() .setName('help') .setDescription('Display help message'), async execute(client, interaction) { await client.interactionReply(interaction, { - components: [new ActionRowBuilder() + components: [new Discord.ActionRowBuilder() .addComponents( - new ButtonBuilder() - .setStyle(ButtonStyle.Link) - .setLabel('DEVELOPER') - .setURL('https://github.com/alexemanuelol'), - new ButtonBuilder() - .setStyle(ButtonStyle.Link) - .setLabel('REPOSITORY') - .setURL('https://github.com/alexemanuelol/rustPlusPlus'), - new ButtonBuilder() - .setStyle(ButtonStyle.Link) - .setLabel('DOCUMENTATION') - .setURL('https://github.com/alexemanuelol/rustPlusPlus/blob/master/docs/documentation.md'), - new ButtonBuilder() - .setStyle(ButtonStyle.Link) - .setLabel('CREDENTIALS') - .setURL('https://github.com/alexemanuelol/rustPlusPlus/releases/tag/v1.0.0') + DiscordButtons.getButton({ + style: Discord.ButtonStyle.Link, + label: 'DEVELOPER', + url: 'https://github.com/alexemanuelol' + }), + DiscordButtons.getButton({ + style: Discord.ButtonStyle.Link, + label: 'REPOSITORY', + url: 'https://github.com/alexemanuelol/rustPlusPlus' + }), + DiscordButtons.getButton({ + style: Discord.ButtonStyle.Link, + label: 'DOCUMENTATION', + url: 'https://github.com/alexemanuelol/rustPlusPlus/blob/master/docs/documentation.md' + }), + DiscordButtons.getButton({ + style: Discord.ButtonStyle.Link, + label: 'CREDENTIALS', + url: 'https://github.com/alexemanuelol/rustPlusPlus/releases/tag/v1.0.0' + }) ) ], ephemeral: true diff --git a/src/commands/leader.js b/src/commands/leader.js index a9038f58d..36109d274 100644 --- a/src/commands/leader.js +++ b/src/commands/leader.js @@ -1,67 +1,52 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); -const { EmbedBuilder } = require('discord.js'); +const Builder = require('@discordjs/builders'); + +const DiscordEmbeds = require('../discordTools/discordEmbeds'); module.exports = { - data: new SlashCommandBuilder() + data: new Builder.SlashCommandBuilder() .setName('leader') .setDescription('Give or take the leadership from/to a team member.') - .addStringOption(option => - option.setName('member') - .setDescription('The name of the team member.') - .setRequired(true)), + .addStringOption(option => option + .setName('member') + .setDescription('The name of the team member.') + .setRequired(true)), async execute(client, interaction) { - let instance = client.readInstanceFile(interaction.guildId); + const instance = client.readInstanceFile(interaction.guildId); + const rustplus = client.rustplusInstances[interaction.guildId]; if (!await client.validatePermissions(interaction)) return; - await interaction.deferReply({ ephemeral: true }); const member = interaction.options.getString('member'); - let rustplus = client.rustplusInstances[interaction.guildId]; if (!rustplus || (rustplus && !rustplus.ready)) { - let str = 'Not currently connected to a rust server.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = 'Not currently connected to a rust server.'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); client.log('WARNING', str); return; } if (!rustplus.generalSettings.leaderCommandEnabled) { - let str = 'Leader command is turned OFF in settings.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); + const str = 'Leader command is turned OFF in settings.'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str, + instance.serverList[rustplus.serverId].title)); rustplus.log('WARNING', str); return; } if (rustplus.team.leaderSteamId !== rustplus.playerId) { - let player = rustplus.team.getPlayer(rustplus.playerId); - let str = `Leader command only works if the current leader is ${player.name}.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); + const player = rustplus.team.getPlayer(rustplus.playerId); + const str = `Leader command only works if the current leader is ${player.name}.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str, + instance.serverList[rustplus.serverId].title)); rustplus.log('WARNING', str); return; } let matchedPlayer = null; /* Look for parts of the name */ - for (let player of rustplus.team.players) { + for (const player of rustplus.team.players) { if (player.name.toLowerCase().includes(member.toLowerCase())) { matchedPlayer = player; break; @@ -70,7 +55,7 @@ module.exports = { if (matchedPlayer === null) { /* Find the closest name */ - for (let player of rustplus.team.players) { + for (const player of rustplus.team.players) { if (Str.similarity(member, player.name) >= 0.9) { matchedPlayer = player; break; @@ -79,40 +64,25 @@ module.exports = { } if (matchedPlayer === null) { - let str = `Could not identify team member: ${member}.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); + const str = `Could not identify team member: ${member}.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str, + instance.serverList[rustplus.serverId].title)); rustplus.log('WARNING', str); } else { if (rustplus.team.leaderSteamId === matchedPlayer.steamId) { - let str = `${matchedPlayer.name} is already team leader.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); + const str = `${matchedPlayer.name} is already team leader.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str, + instance.serverList[rustplus.serverId].title)); rustplus.log('WARNING', str); } else { await rustplus.team.changeLeadership(matchedPlayer.steamId); - let str = `Team leadership was transferred to ${matchedPlayer.name}.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); + const str = `Team leadership was transferred to ${matchedPlayer.name}.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str, + instance.serverList[rustplus.serverId].title)); rustplus.log('INFO', str); } } }, -}; +}; \ No newline at end of file diff --git a/src/commands/map.js b/src/commands/map.js index 252486025..191f2b08a 100644 --- a/src/commands/map.js +++ b/src/commands/map.js @@ -1,43 +1,35 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); -const { EmbedBuilder, AttachmentBuilder } = require('discord.js'); +const Builder = require('@discordjs/builders'); +const Discord = require('discord.js'); + +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); module.exports = { - data: new SlashCommandBuilder() + data: new Builder.SlashCommandBuilder() .setName('map') .setDescription('Get the currently connected server map image.') - .addSubcommand(subcommand => - subcommand - .setName('all') - .setDescription('Get the map including both monument names and markers.')) - .addSubcommand(subcommand => - subcommand - .setName('clean') - .setDescription('Get the clean map.')) - .addSubcommand(subcommand => - subcommand - .setName('monuments') - .setDescription('Get the map including monument names.')) - .addSubcommand(subcommand => - subcommand - .setName('markers') - .setDescription('Get the map including markers.')), + .addSubcommand(subcommand => subcommand + .setName('all') + .setDescription('Get the map including both monument names and markers.')) + .addSubcommand(subcommand => subcommand + .setName('clean') + .setDescription('Get the clean map.')) + .addSubcommand(subcommand => subcommand + .setName('monuments') + .setDescription('Get the map including monument names.')) + .addSubcommand(subcommand => subcommand + .setName('markers') + .setDescription('Get the map including markers.')), async execute(client, interaction) { - let instance = client.readInstanceFile(interaction.guildId); + const instance = client.readInstanceFile(interaction.guildId); + const rustplus = client.rustplusInstances[interaction.guildId]; if (!await client.validatePermissions(interaction)) return; - await interaction.deferReply({ ephemeral: true }); - let rustplus = client.rustplusInstances[interaction.guildId]; if (!rustplus || (rustplus && !rustplus.ready)) { - let str = 'Not currently connected to a rust server.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = 'Not currently connected to a rust server.'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); client.log('WARNING', str); return; } @@ -65,21 +57,22 @@ module.exports = { let file = null; if (interaction.options.getSubcommand() === 'clean') { - file = new AttachmentBuilder(`src/resources/images/maps/${interaction.guildId}_map_clean.png`); + file = new Discord.AttachmentBuilder(`src/resources/images/maps/${interaction.guildId}_map_clean.png`); } else { - file = new AttachmentBuilder(`src/resources/images/maps/${interaction.guildId}_map_full.png`); + file = new Discord.AttachmentBuilder(`src/resources/images/maps/${interaction.guildId}_map_full.png`); } - let fileName = (interaction.options.getSubcommand() === 'clean') ? 'clean' : 'full'; + const fileName = (interaction.options.getSubcommand() === 'clean') ? 'clean' : 'full'; await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setImage(`attachment://${interaction.guildId}_map_${fileName}.png`) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], + embeds: [DiscordEmbeds.getEmbed({ + color: '#ce412b', + image: `attachment://${interaction.guildId}_map_${fileName}.png`, + footer: { text: instance.serverList[rustplus.serverId].title } + })], files: [file], ephemeral: true }); rustplus.log('INFO', `Displaying ${fileName} map.`); }, -}; +}; \ No newline at end of file diff --git a/src/commands/market.js b/src/commands/market.js index 1752c99a3..bda92baf6 100644 --- a/src/commands/market.js +++ b/src/commands/market.js @@ -1,83 +1,73 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); -const { EmbedBuilder } = require('discord.js'); +const Builder = require('@discordjs/builders'); + +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); module.exports = { - data: new SlashCommandBuilder() + data: new Builder.SlashCommandBuilder() .setName('market') .setDescription('Operations for In-Game Vending Machines.') - .addSubcommand(subcommand => - subcommand.setName('search') - .setDescription('Search for an item in Vending Machines.') - .addStringOption(option => - option.setName('name') - .setDescription('The name of the item to search for.') - .setRequired(false)) - .addStringOption(option => - option.setName('id') - .setDescription('The ID of the item to search for.') - .setRequired(false))) - .addSubcommand(subcommand => - subcommand.setName('subscribe') - .setDescription('Subscribe to an item in Vending Machines.') - .addStringOption(option => - option.setName('name') - .setDescription('The name of the item to subscribe to.') - .setRequired(false)) - .addStringOption(option => - option.setName('id') - .setDescription('The ID of the item to subscribe to.') - .setRequired(false))) - .addSubcommand(subcommand => - subcommand.setName('unsubscribe') - .setDescription('Unsubscribe to an item in Vending Machines.') - .addStringOption(option => - option.setName('name') - .setDescription('The name of the item to unsubscribe to.') - .setRequired(false)) - .addStringOption(option => - option.setName('id') - .setDescription('The ID of the item to unsubscribe to.') - .setRequired(false))) - .addSubcommand(subcommand => - subcommand.setName('list') - .setDescription('Display the subscription list.')), + .addSubcommand(subcommand => subcommand + .setName('search') + .setDescription('Search for an item in Vending Machines.') + .addStringOption(option => option + .setName('name') + .setDescription('The name of the item to search for.') + .setRequired(false)) + .addStringOption(option => option + .setName('id') + .setDescription('The ID of the item to search for.') + .setRequired(false))) + .addSubcommand(subcommand => subcommand + .setName('subscribe') + .setDescription('Subscribe to an item in Vending Machines.') + .addStringOption(option => option + .setName('name') + .setDescription('The name of the item to subscribe to.') + .setRequired(false)) + .addStringOption(option => option + .setName('id') + .setDescription('The ID of the item to subscribe to.') + .setRequired(false))) + .addSubcommand(subcommand => subcommand + .setName('unsubscribe') + .setDescription('Unsubscribe to an item in Vending Machines.') + .addStringOption(option => option + .setName('name') + .setDescription('The name of the item to unsubscribe to.') + .setRequired(false)) + .addStringOption(option => option + .setName('id') + .setDescription('The ID of the item to unsubscribe to.') + .setRequired(false))) + .addSubcommand(subcommand => subcommand + .setName('list') + .setDescription('Display the subscription list.')), async execute(client, interaction) { - let instance = client.readInstanceFile(interaction.guildId); + const instance = client.readInstanceFile(interaction.guildId); + const rustplus = client.rustplusInstances[interaction.guildId]; if (!await client.validatePermissions(interaction)) return; - await interaction.deferReply({ ephemeral: true }); - let rustplus = client.rustplusInstances[interaction.guildId]; if (!rustplus || (rustplus && !rustplus.ready)) { - let str = 'Not currently connected to a rust server.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = 'Not currently connected to a rust server.'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); client.log('WARNING', str); return; } switch (interaction.options.getSubcommand()) { case 'search': { - let searchItemName = interaction.options.getString('name'); - let searchItemId = interaction.options.getString('id'); + const searchItemName = interaction.options.getString('name'); + const searchItemId = interaction.options.getString('id'); let itemId = null; if (searchItemName !== null) { - let item = rustplus.items.getClosestItemIdByName(searchItemName) + const item = rustplus.items.getClosestItemIdByName(searchItemName) if (item === undefined) { - let str = `No item with name '${searchItemName}' could be found.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = `No item with name '${searchItemName}' could be found.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); rustplus.log('WARNING', str); return; } @@ -90,51 +80,44 @@ module.exports = { itemId = searchItemId; } else { - let str = `No item with id '${searchItemId}' could be found.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = `No item with id '${searchItemId}' could be found.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); rustplus.log('WARNING', str); return; } } else if (searchItemName === null && searchItemId === null) { - let str = `No 'name' or 'id' was given.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = `No 'name' or 'id' was given.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); rustplus.log('WARNING', str); return; } - let itemName = rustplus.items.getName(itemId); + const itemName = rustplus.items.getName(itemId); + let full = false; let foundLines = ''; - for (let vendingMachine of rustplus.mapMarkers.vendingMachines) { + for (const vendingMachine of rustplus.mapMarkers.vendingMachines) { + if (full) break; if (!vendingMachine.hasOwnProperty('sellOrders')) continue; - for (let order of vendingMachine.sellOrders) { + for (const order of vendingMachine.sellOrders) { if (order.amountInStock === 0) continue; - let orderItemId = (Object.keys(rustplus.items.items).includes(order.itemId.toString())) ? + const orderItemId = (Object.keys(rustplus.items.items).includes(order.itemId.toString())) ? order.itemId : null; - let orderQuantity = order.quantity; - let orderCurrencyId = (Object.keys(rustplus.items.items).includes(order.currencyId.toString())) ? - order.currencyId : null; - let orderCostPerItem = order.costPerItem; - let orderAmountInStock = order.amountInStock; - let orderItemIsBlueprint = order.itemIsBlueprint; - let orderCurrencyIsBlueprint = order.currencyIsBlueprint; - - let orderItemName = (orderItemId !== null) ? rustplus.items.getName(orderItemId) : 'Unknown'; - let orderCurrencyName = (orderCurrencyId !== null) ? + const orderQuantity = order.quantity; + const orderCurrencyId = (Object.keys(rustplus.items.items) + .includes(order.currencyId.toString())) ? order.currencyId : null; + const orderCostPerItem = order.costPerItem; + const orderAmountInStock = order.amountInStock; + const orderItemIsBlueprint = order.itemIsBlueprint; + const orderCurrencyIsBlueprint = order.currencyIsBlueprint; + + const orderItemName = (orderItemId !== null) ? rustplus.items.getName(orderItemId) : 'Unknown'; + const orderCurrencyName = (orderCurrencyId !== null) ? rustplus.items.getName(orderCurrencyId) : 'Unknown'; + const prevFoundLines = foundLines; if (orderItemId === parseInt(itemId) || orderCurrencyId === parseInt(itemId)) { if (foundLines === '') { foundLines += '```diff\n'; @@ -146,6 +129,13 @@ module.exports = { foundLines += `${orderCostPerItem}x ${orderCurrencyName}`; foundLines += `${(orderCurrencyIsBlueprint) ? ' (BP)' : ''} `; foundLines += `(${orderAmountInStock} left)\n`; + + if (foundLines.length >= 4000) { + foundLines = prevFoundLines; + foundLines += `...\n`; + full = true; + break; + } } } } @@ -157,31 +147,27 @@ module.exports = { foundLines += '```' } - let embed = new EmbedBuilder() - .setColor('#ce412b') - .setTitle(`Search result for item: **${itemName}**`) - .setDescription(foundLines) - .setFooter({ text: `${instance.serverList[rustplus.serverId].title}` }); + const embed = DiscordEmbeds.getEmbed({ + color: '#ce412b', + title: `Search result for item: **${itemName}**`, + description: foundLines, + footer: { text: `${instance.serverList[rustplus.serverId].title}` } + }); await client.interactionEditReply(interaction, { embeds: [embed] }); rustplus.log('INFO', `Showing the result for item: ${itemName}`); } break; case 'subscribe': { - let subscribeItemName = interaction.options.getString('name'); - let subscribeItemId = interaction.options.getString('id'); + const subscribeItemName = interaction.options.getString('name'); + const subscribeItemId = interaction.options.getString('id'); let itemId = null; if (subscribeItemName !== null) { - let item = rustplus.items.getClosestItemIdByName(subscribeItemName) + const item = rustplus.items.getClosestItemIdByName(subscribeItemName) if (item === undefined) { - let str = `No item with name '${subscribeItemName}' could be found.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = `No item with name '${subscribeItemName}' could be found.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); rustplus.log('WARNING', str); return; } @@ -194,29 +180,19 @@ module.exports = { itemId = subscribeItemId; } else { - let str = `No item with id '${subscribeItemId}' could be found.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = `No item with id '${subscribeItemId}' could be found.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); rustplus.log('WARNING', str); return; } } else if (subscribeItemName === null && subscribeItemId === null) { - let str = `No 'name' or 'id' was given.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = `No 'name' or 'id' was given.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); rustplus.log('WARNING', str); return; } - let itemName = rustplus.items.getName(itemId); + const itemName = rustplus.items.getName(itemId); /* TODO: Set a variable in rustplus to indicate first loop Which means that we should NOT notify all found items at first loop, @@ -226,47 +202,32 @@ module.exports = { from the vending machine, remove it from the object. */ if (instance.marketSubscribeItemIds.includes(itemId)) { - let str = `Already subscribed to item '${itemName}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: `${instance.serverList[rustplus.serverId].title}` })], - ephemeral: true - }); + const str = `Already subscribed to item '${itemName}'.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str, + instance.serverList[rustplus.serverId].title)); rustplus.log('WARNING', str); } else { instance.marketSubscribeItemIds.push(itemId); client.writeInstanceFile(interaction.guildId, instance); - let str = `Just subscribed to item '${itemName}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); + const str = `Just subscribed to item '${itemName}'.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str, + instance.serverList[rustplus.serverId].title)); rustplus.log('INFO', str); } } break; case 'unsubscribe': { - let subscribeItemName = interaction.options.getString('name'); - let subscribeItemId = interaction.options.getString('id'); + const subscribeItemName = interaction.options.getString('name'); + const subscribeItemId = interaction.options.getString('id'); let itemId = null; if (subscribeItemName !== null) { - let item = rustplus.items.getClosestItemIdByName(subscribeItemName) + const item = rustplus.items.getClosestItemIdByName(subscribeItemName) if (item === undefined) { - let str = `No item with name '${subscribeItemName}' could be found.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = `No item with name '${subscribeItemName}' could be found.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); rustplus.log('WARNING', str); return; } @@ -279,29 +240,19 @@ module.exports = { itemId = subscribeItemId; } else { - let str = `No item with id '${subscribeItemId}' could be found.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = `No item with id '${subscribeItemId}' could be found.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); rustplus.log('WARNING', str); return; } } else if (subscribeItemName === null && subscribeItemId === null) { - let str = `No 'name' or 'id' was given.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = `No 'name' or 'id' was given.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); rustplus.log('WARNING', str); return; } - let itemName = rustplus.items.getName(itemId); + const itemName = rustplus.items.getName(itemId); /* TODO: Remove item from object in rustplus */ @@ -309,25 +260,15 @@ module.exports = { instance.marketSubscribeItemIds = instance.marketSubscribeItemIds.filter(e => e !== itemId); client.writeInstanceFile(interaction.guildId, instance); - let str = `Item '${itemName}' have been removed from subscription.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); + const str = `Item '${itemName}' have been removed from subscription.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str, + instance.serverList[rustplus.serverId].title)); rustplus.log('INFO', str); } else { - let str = `Item '${itemName}' does not exist in subscription list.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); + const str = `Item '${itemName}' does not exist in subscription list.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str, + instance.serverList[rustplus.serverId].title)); rustplus.log('WARNING', str); } } break; @@ -340,30 +281,25 @@ module.exports = { ids += `\`${item}\`\n`; } - let content = null; if (names === '' || ids === '') { - content = { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription('```diff\n- Item subcription list is empty.\n```') - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - } + const str = 'Item subscription list is empty.'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str, + instance.serverList[rustplus.serverId].title)); } else { - content = { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setTitle('Subscription list') - .addFields( + await client.interactionEditReply(interaction, { + embeds: [DiscordEmbeds.getEmbed({ + color: '#ce412b', + title: 'Subscription list', + footer: { text: instance.serverList[rustplus.serverId].title }, + fields: [ { name: 'Name', value: names, inline: true }, - { name: 'ID', value: ids, inline: true }) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], + { name: 'ID', value: ids, inline: true }] + })], ephemeral: true - } + }); } - await client.interactionEditReply(interaction, content); rustplus.log('INFO', 'Showing the subscription list.'); } break; diff --git a/src/commands/players.js b/src/commands/players.js index 218c2610a..8fbc75701 100644 --- a/src/commands/players.js +++ b/src/commands/players.js @@ -1,59 +1,43 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); -const { EmbedBuilder } = require('discord.js'); +const Builder = require('@discordjs/builders'); + +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); module.exports = { - data: new SlashCommandBuilder() + data: new Builder.SlashCommandBuilder() .setName('players') .setDescription('Get player/players information based on Battlemetrics.') - .addStringOption(option => - option.setName('name') - .setDescription('The name or part of the name of the player.') - .setRequired(false)), + .addStringOption(option => option + .setName('name') + .setDescription('The name or part of the name of the player.') + .setRequired(false)), async execute(client, interaction) { - let instance = client.readInstanceFile(interaction.guildId); - - const name = interaction.options.getString('name'); + const instance = client.readInstanceFile(interaction.guildId); + const rustplus = client.rustplusInstances[interaction.guildId]; if (!await client.validatePermissions(interaction)) return; - await interaction.deferReply({ ephemeral: true }); - let rustplus = client.rustplusInstances[interaction.guildId]; + const name = interaction.options.getString('name'); + if (!rustplus || (rustplus && !rustplus.ready)) { - let str = 'Not currently connected to a rust server.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = 'Not currently connected to a rust server.'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); client.log('WARNING', str); return; } const battlemetricsId = instance.serverList[rustplus.serverId].battlemetricsId; - if (battlemetricsId === null) { - let str = 'This server is using streamer mode.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = 'This server is using streamer mode.'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); client.log('WARNING', str); return; } if (!Object.keys(client.battlemetricsOnlinePlayers).includes(battlemetricsId)) { - let str = 'Could not find players for this server.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + const str = 'Could not find players for this server.'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); client.log('WARNING', str); return; } @@ -63,19 +47,19 @@ module.exports = { foundPlayers = client.battlemetricsOnlinePlayers[battlemetricsId].slice(); } else { - for (let player of client.battlemetricsOnlinePlayers[battlemetricsId]) { + for (const player of client.battlemetricsOnlinePlayers[battlemetricsId]) { if (player.name.includes(name)) { foundPlayers.push(player); } } } - let allPlayersLength = foundPlayers.length; - let playerColumns = ['', '', '']; + const allPlayersLength = foundPlayers.length; + const playerColumns = ['', '', '']; let playerIndex = 0; let isFull = false; - for (let player of foundPlayers) { - let playerStr = `\`[${player.time}] ${player.name}\`\n`; + for (const player of foundPlayers) { + const playerStr = `\`[${player.time}] ${player.name}\`\n`; if (playerColumns[playerIndex % 3].length + playerStr.length > 1024) { isFull = true; @@ -94,9 +78,10 @@ module.exports = { title = `Online players '${name}'`; } - let embed = new EmbedBuilder() - .setTitle(title) - .setColor('#ce412b'); + const embed = DiscordEmbeds.getEmbed({ + title: title, + color: '#ce412b' + }); let description = ''; if (playerIndex === 0) { diff --git a/src/commands/reset.js b/src/commands/reset.js index 6d3871f4c..3550b7fdf 100644 --- a/src/commands/reset.js +++ b/src/commands/reset.js @@ -1,20 +1,20 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); +const Builder = require('@discordjs/builders'); +const Discord = require('discord.js'); + +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); const DiscordTools = require('../discordTools/discordTools.js'); -const { EmbedBuilder, AttachmentBuilder } = require('discord.js'); module.exports = { - data: new SlashCommandBuilder() + data: new Builder.SlashCommandBuilder() .setName('reset') .setDescription('Reset Discord channels.') - .addSubcommand(subcommand => - subcommand - .setName('discord') - .setDescription('Reset discord channels.')), + .addSubcommand(subcommand => subcommand + .setName('discord') + .setDescription('Reset discord channels.')), async execute(client, interaction) { let instance = client.readInstanceFile(interaction.guildId); if (!await client.validatePermissions(interaction)) return; - await interaction.deferReply({ ephemeral: true }); switch (interaction.options.getSubcommand()) { @@ -24,7 +24,7 @@ module.exports = { instance.firstTime = true; client.writeInstanceFile(interaction.guildId, instance); - let category = await require('../discordTools/SetupGuildCategory')(client, guild); + const category = await require('../discordTools/SetupGuildCategory')(client, guild); await require('../discordTools/SetupGuildChannels')(client, guild, category); await require('../discordTools/SetupServerList')(client, guild); @@ -40,11 +40,11 @@ module.exports = { await DiscordTools.clearTextChannel(guild.id, instance.channelId.information, 100); - let rustplus = client.rustplusInstances[guild.id]; + const rustplus = client.rustplusInstances[guild.id]; if (rustplus && rustplus.ready) { await rustplus.map.writeMap(false, true); - let channel = DiscordTools.getTextChannelById(guild.id, instance.channelId.information); + const channel = DiscordTools.getTextChannelById(guild.id, instance.channelId.information); if (!channel) { client.log('ERROR', 'Invalid guild or channel.', 'error'); @@ -52,20 +52,16 @@ module.exports = { else { instance = client.readInstanceFile(guild.id); - let file = new AttachmentBuilder(`src/resources/images/maps/${guild.id}_map_full.png`); - let msg = await client.messageSend(channel, { files: [file] }); + const file = new Discord.AttachmentBuilder( + `src/resources/images/maps/${guild.id}_map_full.png`); + const msg = await client.messageSend(channel, { files: [file] }); instance.informationMessageId.map = msg.id; client.writeInstanceFile(guild.id, instance); } } - let str = 'Successfully reset Discord.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``)], - ephemeral: true - }); + const str = 'Successfully reset Discord.'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str)); client.log('INFO', str); } break; diff --git a/src/commands/role.js b/src/commands/role.js index 057203d28..a076195b2 100644 --- a/src/commands/role.js +++ b/src/commands/role.js @@ -1,31 +1,30 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); +const Builder = require('@discordjs/builders'); + +const DiscordEmbeds = require('../discordTools/discordEmbeds'); const DiscordTools = require('../discordTools/discordTools'); -const { EmbedBuilder } = require('discord.js'); module.exports = { - data: new SlashCommandBuilder() + data: new Builder.SlashCommandBuilder() .setName('role') .setDescription('Set/Clear a specific role that will be able to see the rustPlusPlus category content.') - .addSubcommand(subcommand => - subcommand.setName('set') - .setDescription('Set the role.') - .addRoleOption(option => - option.setName('role') - .setDescription('The role rustPlusPlus channels will be visible to.') - .setRequired(true))) - .addSubcommand(subcommand => - subcommand.setName('clear') - .setDescription('Clear the role (to allow everyone to see the rustPlusPlus channels).')), + .addSubcommand(subcommand => subcommand + .setName('set') + .setDescription('Set the role.') + .addRoleOption(option => option + .setName('role') + .setDescription('The role rustPlusPlus channels will be visible to.') + .setRequired(true))) + .addSubcommand(subcommand => subcommand + .setName('clear') + .setDescription('Clear the role (to allow everyone to see the rustPlusPlus channels).')), async execute(client, interaction) { - let instance = client.readInstanceFile(interaction.guildId); + const instance = client.readInstanceFile(interaction.guildId); if (!await client.validatePermissions(interaction)) return; - await interaction.deferReply({ ephemeral: true }); let role = null; - switch (interaction.options.getSubcommand()) { case 'set': { role = interaction.options.getRole('role'); @@ -41,34 +40,23 @@ module.exports = { } break; default: { - } break; } const guild = DiscordTools.getGuild(interaction.guildId); if (guild) { - let category = await require('../discordTools/SetupGuildCategory')(client, guild); + const category = await require('../discordTools/SetupGuildCategory')(client, guild); await require('../discordTools/SetupGuildChannels')(client, guild, category); } if (interaction.options.getSubcommand() === 'set') { - let str = `rustPlusPlus role has been set to '${role.name}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``)], - ephemeral: true - }); + const str = `rustPlusPlus role has been set to '${role.name}'.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str)); client.log('INFO', str); } else { - let str = 'rustPlusPlus role has been cleared.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``)], - ephemeral: true - }); + const str = 'rustPlusPlus role has been cleared.'; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str)); client.log('INFO', str); } }, diff --git a/src/commands/storagemonitor.js b/src/commands/storagemonitor.js index 280824cf2..0e3e7ab0c 100644 --- a/src/commands/storagemonitor.js +++ b/src/commands/storagemonitor.js @@ -1,217 +1,67 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); -const DiscordTools = require('../discordTools/discordTools.js'); -const { EmbedBuilder, AttachmentBuilder } = require('discord.js'); -const Recycler = require('../util/recycler.js'); +const Builder = require('@discordjs/builders'); + +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); +const InstanceUtils = require('../util/instanceUtils.js'); module.exports = { - data: new SlashCommandBuilder() + data: new Builder.SlashCommandBuilder() .setName('storagemonitor') .setDescription('Operations on Storage Monitors.') - .addSubcommand(subcommand => - subcommand - .setName('edit') - .setDescription('Edit the properties of a Storage Monitor.') - .addStringOption(option => - option.setName('id') - .setDescription('The ID of the Storage Monitor.') - .setRequired(true)) - .addStringOption(option => - option.setName('name') - .setDescription('Rename the Storage Monitor.') - .setRequired(false)) - .addStringOption(option => - option.setName('image') - .setDescription('Set the image that best represent the Storage Monitor.') - .setRequired(false) - .addChoices( - { - name: 'Storage Monitor', - value: 'storage_monitor' - }, - { - name: 'Tool Cupboard', - value: 'tool_cupboard' - }, - { - name: 'Large Wood Box', - value: 'large_wood_box' - }, - { - name: 'Vending Machine', - value: 'vending_machine' - } - ))) - .addSubcommand(subcommand => - subcommand - .setName('recycle') - .setDescription('Calculate the resources gained from recycling the content of a Storage Monitor.') - .addStringOption(option => - option.setName('id') - .setDescription('The ID of the Storage Monitor.') - .setRequired(true))), + .addSubcommand(subcommand => subcommand + .setName('edit') + .setDescription('Edit the properties of a Storage Monitor.') + .addStringOption(option => option + .setName('id') + .setDescription('The ID of the Storage Monitor.') + .setRequired(true)) + .addStringOption(option => option + .setName('image') + .setDescription('Set the image that best represent the Storage Monitor.') + .setRequired(false) + .addChoices( + { name: 'Storage Monitor', value: 'storage_monitor' }, + { name: 'Tool Cupboard', value: 'tool_cupboard' }, + { name: 'Large Wood Box', value: 'large_wood_box' }, + { name: 'Vending Machine', value: 'vending_machine' } + ))), async execute(client, interaction) { - let instance = client.readInstanceFile(interaction.guildId); + const instance = client.readInstanceFile(interaction.guildId); + const rustplus = client.rustplusInstances[interaction.guildId]; if (!await client.validatePermissions(interaction)) return; - await interaction.deferReply({ ephemeral: true }); - const id = interaction.options.getString('id'); - - let rustplus = client.rustplusInstances[interaction.guildId]; - if (!rustplus || (rustplus && !rustplus.ready)) { - let str = 'Not currently connected to a rust server.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('WARNING', str); - return; - } - switch (interaction.options.getSubcommand()) { case 'edit': { - const name = interaction.options.getString('name'); + const entityId = interaction.options.getString('id'); const image = interaction.options.getString('image'); - let embedChanged = false; - let filesChanged = false; - - if (!Object.keys(instance.storageMonitors).includes(id)) { - let str = `Invalid ID: '${id}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); + const device = InstanceUtils.getSmartDevice(interaction.guildId, entityId); + if (device === null) { + let str = `Invalid ID: '${entityId}'.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str, + instance.serverList[device.serverId].title)); + client.log('WARNING', str); return; } - if (instance.storageMonitors[id].serverId !== rustplus.serverId) { - let str = 'That Storage Monitor is not part of this Rust Server.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } + const entity = instance.serverList[device.serverId].storageMonitors[entityId]; - if (name !== null) { - instance.storageMonitors[id].name = name; - embedChanged = true; - } if (image !== null) { - instance.storageMonitors[id].image = `${image}.png`; - embedChanged = true; - filesChanged = true; + instance.serverList[device.serverId].storageMonitors[entityId].image = `${image}.png`; } client.writeInstanceFile(interaction.guildId, instance); - await DiscordTools.sendStorageMonitorMessage( - interaction.guildId, id, embedChanged, false, filesChanged); - - let str = `Successfully edited Storage Monitor '${instance.storageMonitors[id].name}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('INFO', str); - } break; - - case 'recycle': { - if (!Object.keys(instance.storageMonitors).includes(id)) { - let str = `Invalid ID: '${id}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; + if (rustplus && rustplus.serverId === device.serverId) { + await DiscordMessages.sendStorageMonitorMessage(interaction.guildId, device.serverId, entityId); } - if (instance.storageMonitors[id].serverId !== rustplus.serverId) { - let str = 'That Storage Monitor is not part of this Rust Server.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } - - let entityInfo = await rustplus.getEntityInfoAsync(id); - if (!(await rustplus.isResponseValid(entityInfo))) { - instance.storageMonitors[id].reachable = false; - client.writeInstanceFile(interaction.guildId, instance); - - let str = `Could not get items from Storage Monitor: ${id}`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - - await DiscordTools.sendStorageMonitorMessage(rustplus.guildId, id); - return; - } - instance.storageMonitors[id].reachable = true; - client.writeInstanceFile(interaction.guildId, instance); - - let items = Recycler.calculate(entityInfo.entityInfo.payload.items); - - let itemName = ''; - let itemQuantity = ''; - for (let item of items) { - itemName += `\`${rustplus.items.getName(item.itemId)}\`\n`; - itemQuantity += `\`${item.quantity}\`\n`; - } - - let file = new AttachmentBuilder('src/resources/images/electrics/recycler.png'); - let embed = new EmbedBuilder() - .setTitle('Result of recycling:') - .setColor('#ce412b') - .setThumbnail('attachment://recycler.png') - .setFooter({ text: `${instance.storageMonitors[id].server}` }) - .setDescription(`**Name** \`${instance.storageMonitors[id].name}\`\n**ID** \`${id}\``); - - if (itemName === '' || itemQuantity === '') { - itemName = 'Empty'; - itemQuantity = 'Empty'; - } - - embed.addFields( - { name: 'Item', value: itemName, inline: true }, - { name: 'Quantity', value: itemQuantity, inline: true } - ); - - await client.interactionEditReply(interaction, { - embeds: [embed], - files: [file] - }); - rustplus.log('INFO', - `Showing result of recycling content of storage monitor '${instance.storageMonitors[id].name}'`); + let str = `Successfully edited Storage Monitor '${entity.name}'.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str, + instance.serverList[device.serverId].title)); + client.log('INFO', str); } break; default: { diff --git a/src/commands/switch.js b/src/commands/switch.js index ecf90e2f0..e4bfb54a8 100644 --- a/src/commands/switch.js +++ b/src/commands/switch.js @@ -1,490 +1,79 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); -const DiscordTools = require('../discordTools/discordTools.js'); -const Keywords = require('../util/keywords.js'); +const Builder = require('@discordjs/builders'); + +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); +const InstanceUtils = require('../util/instanceUtils.js'); const SmartSwitchGroupHandler = require('../handlers/smartSwitchGroupHandler.js'); -const { EmbedBuilder } = require('discord.js'); module.exports = { - data: new SlashCommandBuilder() + data: new Builder.SlashCommandBuilder() .setName('switch') .setDescription('Operations on Smart Switches.') - .addSubcommand(subcommand => - subcommand - .setName('edit_switch') - .setDescription('Edit the properties of a Smart Switch.') - .addStringOption(option => - option.setName('id') - .setDescription('The ID of the Smart Switch.') - .setRequired(true)) - .addStringOption(option => - option.setName('name') - .setDescription('Rename the Smart Switch.') - .setRequired(false)) - .addStringOption(option => - option.setName('command') - .setDescription('Set the custom command for the Smart Switch.') - .setRequired(false)) - .addStringOption(option => - option.setName('image') - .setDescription('Set the image that best represent the Smart Switch.') - .setRequired(false) - .addChoices( - { - name: 'Autoturret', - value: 'autoturret' - }, - { - name: 'Boom Box', - value: 'boombox' - }, - { - name: 'Broadcaster', - value: 'broadcaster' - }, - { - name: 'Ceiling Light', - value: 'ceiling_light' - }, - { - name: 'Discofloor', - value: 'discofloor' - }, - { - name: 'Door Controller', - value: 'door_controller' - }, - { - name: 'Elevator', - value: 'elevator' - }, - { - name: 'HBHF Sensor', - value: 'hbhf_sensor' - }, - { - name: 'Heater', - value: 'heater' - }, - { - name: 'SAM site', - value: 'samsite' - }, - { - name: 'Siren Light', - value: 'siren_light' - }, - { - name: 'Smart Alarm', - value: 'smart_alarm' - }, - { - name: 'Smart Switch', - value: 'smart_switch' - }, - { - name: 'Sprinkler', - value: 'sprinkler' - }, - { - name: 'Storage Monitor', - value: 'storage_monitor' - }, - { - name: 'Christmas Lights', - value: 'xmas_light' - }))) - .addSubcommand(subcommand => - subcommand - .setName('create_group') - .setDescription('Create a Smart Switch Group.') - .addStringOption(option => - option - .setName('group_name') - .setDescription('The name of the Group to be created.') - .setRequired(true)) - .addStringOption(option => - option - .setName('command') - .setDescription('Set the custom command for the Group.') - .setRequired(true))) - .addSubcommand(subcommand => - subcommand - .setName('edit_group') - .setDescription('Edit the properties of a Group.') - .addStringOption(option => - option - .setName('group_name') - .setDescription('The name of the Group.') - .setRequired(true)) - .addStringOption(option => - option - .setName('command') - .setDescription('Set the custom command for the Group.') - .setRequired(false))) - .addSubcommand(subcommand => - subcommand - .setName('add_switch') - .setDescription('Add a Smart Switch to a Group.') - .addStringOption(option => - option - .setName('group_name') - .setDescription('The name of the Group.') - .setRequired(true)) - .addStringOption(option => - option - .setName('switch_id') - .setDescription('The Smart Switch ID.') - .setRequired(true))) - .addSubcommand(subcommand => - subcommand - .setName('remove_switch') - .setDescription('Remove a Smart Switch from a Group.') - .addStringOption(option => - option - .setName('group_name') - .setDescription('The name of the Group.') - .setRequired(true)) - .addStringOption(option => - option - .setName('switch_id') - .setDescription('The Smart Switch ID.') - .setRequired(true))), + .addSubcommand(subcommand => subcommand + .setName('edit') + .setDescription('Edit the properties of a Smart Switch.') + .addStringOption(option => option + .setName('id') + .setDescription('The ID of the Smart Switch.') + .setRequired(true)) + .addStringOption(option => option + .setName('image') + .setDescription('Set the image that best represent the Smart Switch.') + .setRequired(true) + .addChoices( + { name: 'Autoturret', value: 'autoturret' }, + { name: 'Boom Box', value: 'boombox' }, + { name: 'Broadcaster', value: 'broadcaster' }, + { name: 'Ceiling Light', value: 'ceiling_light' }, + { name: 'Discofloor', value: 'discofloor' }, + { name: 'Door Controller', value: 'door_controller' }, + { name: 'Elevator', value: 'elevator' }, + { name: 'HBHF Sensor', value: 'hbhf_sensor' }, + { name: 'Heater', value: 'heater' }, + { name: 'SAM site', value: 'samsite' }, + { name: 'Siren Light', value: 'siren_light' }, + { name: 'Smart Alarm', value: 'smart_alarm' }, + { name: 'Smart Switch', value: 'smart_switch' }, + { name: 'Sprinkler', value: 'sprinkler' }, + { name: 'Storage Monitor', value: 'storage_monitor' }, + { name: 'Christmas Lights', value: 'xmas_light' }))), async execute(client, interaction) { - let instance = client.readInstanceFile(interaction.guildId); + const instance = client.readInstanceFile(interaction.guildId); + const rustplus = client.rustplusInstances[interaction.guildId]; if (!await client.validatePermissions(interaction)) return; - await interaction.deferReply({ ephemeral: true }); - let embedChanged = false; - let filesChanged = false; - - let rustplus = client.rustplusInstances[interaction.guildId]; - if (!rustplus || (rustplus && !rustplus.ready)) { - let str = 'Not currently connected to a rust server.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('WARNING', str); - return; - } - switch (interaction.options.getSubcommand()) { - case 'edit_switch': { - const id = interaction.options.getString('id'); - const name = interaction.options.getString('name'); - const command = interaction.options.getString('command'); + case 'edit': { + const entityId = interaction.options.getString('id'); const image = interaction.options.getString('image'); - if (Keywords.getListOfUsedKeywords(client, interaction.guildId, rustplus.serverId).includes(command)) { - let str = `The command '${command}' is already in use, please choose another command.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } - - if (!Object.keys(instance.switches).includes(id)) { - let str = `Invalid ID: '${id}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } - - if (instance.switches[id].serverId !== rustplus.serverId) { - let str = 'The Smart Switch is not part of this Rust Server.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } - - if (name !== null) { - instance.switches[id].name = name; - embedChanged = true; - } - if (command !== null) { - instance.switches[id].command = command; - embedChanged = true; - } - if (image !== null) { - instance.switches[id].image = `${image}.png`; - embedChanged = true; - filesChanged = true; - } - client.writeInstanceFile(interaction.guildId, instance); - - DiscordTools.sendSmartSwitchMessage(interaction.guildId, id, embedChanged, false, filesChanged); - SmartSwitchGroupHandler.updateSwitchGroupIfContainSwitch( - client, interaction.guildId, rustplus.serverId, id); - - let str = `Successfully edited Smart Switch '${instance.switches[id].name}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('INFO', str); - } break; - - case 'create_group': { - const groupName = interaction.options.getString('group_name'); - const command = interaction.options.getString('command'); - - if (!instance.serverList[rustplus.serverId].hasOwnProperty('switchGroups')) { - instance.serverList[rustplus.serverId].switchGroups = {}; - client.writeInstanceFile(interaction.guildId, instance); - } - - if (Object.keys(instance.serverList[rustplus.serverId].switchGroups).includes(groupName)) { - let str = `The Group name '${groupName}' is already in use.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } - - if (Keywords.getListOfUsedKeywords(client, interaction.guildId, rustplus.serverId).includes(command)) { - let str = `The command '${command}' is already in use, please choose another command.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } - - instance.serverList[rustplus.serverId].switchGroups[groupName] = { - serverId: rustplus.serverId, - command: command, - switches: [] - } - client.writeInstanceFile(interaction.guildId, instance); - - await DiscordTools.sendSmartSwitchGroupMessage(interaction.guildId, groupName); - - let str = `Successfully created the Group '${groupName}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('INFO', str); - } break; - - case 'edit_group': { - const groupName = interaction.options.getString('group_name'); - const command = interaction.options.getString('command'); - - if (!Object.keys(instance.serverList[rustplus.serverId].switchGroups).includes(groupName)) { - let str = `The Group name '${groupName}' does not exist.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); + const device = InstanceUtils.getSmartDevice(interaction.guildId, entityId); + if (device === null) { + let str = `Invalid ID: '${entityId}'.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str, + instance.serverList[device.serverId].title)); + client.log('WARNING', str); return; } - if (command === null) { - let str = 'No changes were made.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } - - if (Keywords.getListOfUsedKeywords(client, interaction.guildId, rustplus.serverId).includes(command)) { - let str = `The command '${command}' is already in use, please choose another command.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } + const entity = instance.serverList[device.serverId].switches[entityId]; - if (command !== null) { - instance.serverList[rustplus.serverId].switchGroups[groupName].command = command; - embedChanged = true; - } + if (image !== null) instance.serverList[device.serverId].switches[entityId].image = `${image}.png`; client.writeInstanceFile(interaction.guildId, instance); - await DiscordTools.sendSmartSwitchGroupMessage(interaction.guildId, groupName, true, false, false); - - let str = `Successfully edited the Group '${groupName}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('INFO', str); - } break; - - case 'add_switch': { - const groupName = interaction.options.getString('group_name'); - const switchId = interaction.options.getString('switch_id'); - - if (!Object.keys(instance.serverList[rustplus.serverId].switchGroups).includes(groupName)) { - let str = `The Group name '${groupName}' does not exist.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } - - if (!Object.keys(instance.switches).includes(switchId)) { - let str = `The Switch ID '${switchId}' does not exist.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; + if (rustplus && rustplus.serverId === device.serverId) { + DiscordMessages.sendSmartSwitchMessage(interaction.guildId, device.serverId, entityId); + SmartSwitchGroupHandler.updateSwitchGroupIfContainSwitch( + client, interaction.guildId, device.serverId, entityId); } - if (instance.serverList[rustplus.serverId].switchGroups[groupName].switches.includes(switchId)) { - let str = `The Switch ID '${switchId}' is already part of the Group '${groupName}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } - - let sw = instance.switches[switchId]; - - if (sw.serverId !== rustplus.serverId) { - let str = `The Switch '${switchId}' is not part of this server.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } - - instance.serverList[rustplus.serverId].switchGroups[groupName].switches.push(switchId); - client.writeInstanceFile(interaction.guildId, instance); - - await DiscordTools.sendSmartSwitchGroupMessage(interaction.guildId, groupName, true, false, false); - - let str = `Successfully added '${switchId}' to the Group '${groupName}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('INFO', str); - } break; - - case 'remove_switch': { - const groupName = interaction.options.getString('group_name'); - const switchId = interaction.options.getString('switch_id'); - - if (!Object.keys(instance.serverList[rustplus.serverId].switchGroups).includes(groupName)) { - let str = `The Group name '${groupName}' does not exist.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } - - if (!instance.serverList[rustplus.serverId].switchGroups[groupName].switches.includes(switchId)) { - let str = `The Switch '${switchId}' does not exist in the Group '${groupName}'`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('WARNING', str); - return; - } - - instance.serverList[rustplus.serverId].switchGroups[groupName].switches = - instance.serverList[rustplus.serverId].switchGroups[groupName].switches.filter(e => e !== switchId); - client.writeInstanceFile(interaction.guildId, instance); - - await DiscordTools.sendSmartSwitchGroupMessage(interaction.guildId, groupName, true, false, false); - - let str = `Successfully removed '${switchId}' to the Group '${groupName}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``) - .setFooter({ text: instance.serverList[rustplus.serverId].title })], - ephemeral: true - }); - rustplus.log('INFO', str); + let str = `Successfully edited Smart Switch '${entity.name}'.`; + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str, + instance.serverList[device.serverId].title)); + client.log('INFO', str); } break; default: { diff --git a/src/commands/tracker.js b/src/commands/tracker.js deleted file mode 100644 index 805162ca0..000000000 --- a/src/commands/tracker.js +++ /dev/null @@ -1,193 +0,0 @@ -const { SlashCommandBuilder } = require('@discordjs/builders'); -const DiscordTools = require('../discordTools/discordTools.js'); -const { EmbedBuilder } = require('discord.js'); - -module.exports = { - data: new SlashCommandBuilder() - .setName('tracker') - .setDescription('Operations for Battlemetrics Player Tracker.') - .addSubcommand(subcommand => - subcommand - .setName('edit') - .setDescription('Edit a Battlemetrics Player Tracker.') - .addStringOption(option => - option.setName('tracker_name') - .setDescription('The name of the tracker.') - .setRequired(true)) - .addStringOption(option => - option.setName('new_tracker_name') - .setDescription('The new name for the tracker.') - .setRequired(true))) - .addSubcommand(subcommand => - subcommand - .setName('add_player') - .setDescription('Add a player to the Battlemetrics Player Tracker.') - .addStringOption(option => - option.setName('tracker_name') - .setDescription('The name of the tracker.') - .setRequired(true)) - .addStringOption(option => - option.setName('steam_id') - .setDescription('The steam ID for the player.') - .setRequired(true))) - .addSubcommand(subcommand => - subcommand - .setName('remove_player') - .setDescription('Remove a player from the Battlemetrics Player Tracker.') - .addStringOption(option => - option.setName('tracker_name') - .setDescription('The name of the tracker.') - .setRequired(true)) - .addStringOption(option => - option.setName('steam_id') - .setDescription('The steam ID for the player.') - .setRequired(true))), - - async execute(client, interaction) { - let instance = client.readInstanceFile(interaction.guildId); - - if (!await client.validatePermissions(interaction)) return; - - await interaction.deferReply({ ephemeral: true }); - - const trackerName = interaction.options.getString('tracker_name'); - - switch (interaction.options.getSubcommand()) { - case 'edit': { - if (!Object.keys(instance.trackers).includes(trackerName)) { - let str = `Battlemetrics Player Tracker '${trackerName}' does not exist.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('WARNING', str); - return; - } - - const newTrackerName = interaction.options.getString('new_tracker_name'); - - if (trackerName === newTrackerName) { - let str = 'No changes were made.'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('WARNING', str); - return; - } - - instance.trackers[newTrackerName] = JSON.parse(JSON.stringify(instance.trackers[trackerName])); - delete instance.trackers[trackerName]; - client.writeInstanceFile(interaction.guildId, instance); - - await DiscordTools.sendTrackerMessage(interaction.guildId, newTrackerName); - - let str = `Successfully edited Battlemetrics Player Tracker '${trackerName}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('INFO', str); - } break; - - case 'add_player': { - if (!Object.keys(instance.trackers).includes(trackerName)) { - let str = `Battlemetrics Player Tracker '${trackerName}' does not exist.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('WARNING', str); - return; - } - - const steamId = interaction.options.getString('steam_id'); - - if (instance.trackers[trackerName].players.some(e => e.id === steamId)) { - let str = `The player '${steamId}' already exist in '${trackerName}' tracker.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('WARNING', str); - return; - } - - instance.trackers[trackerName].players.push({ - name: '-', steamId: steamId, playerId: null, status: false, time: null - }); - client.writeInstanceFile(interaction.guildId, instance); - - await DiscordTools.sendTrackerMessage(interaction.guildId, trackerName); - - /* To force search of player name via scrape */ - client.battlemetricsIntervalCounter = 0; - - let str = `Successfully added '${steamId}' to the tracker '${trackerName}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('INFO', str); - } break; - - case 'remove_player': { - if (!Object.keys(instance.trackers).includes(trackerName)) { - let str = `Battlemetrics Player Tracker '${trackerName}' does not exist.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('WARNING', str); - return; - } - - const steamId = interaction.options.getString('steam_id'); - - if (!instance.trackers[trackerName].players.some(e => e.steamId === steamId)) { - let str = `The player '${steamId}' already exist in '${trackerName}' tracker.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('WARNING', str); - return; - } - - instance.trackers[trackerName].players = - instance.trackers[trackerName].players.filter(e => e.steamId !== steamId); - client.writeInstanceFile(interaction.guildId, instance); - - await DiscordTools.sendTrackerMessage(interaction.guildId, trackerName); - - let str = `Successfully removed '${steamId}' from the tracker '${trackerName}'.`; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setDescription(`\`\`\`diff\n+ ${str}\n\`\`\``)], - ephemeral: true - }); - client.log('INFO', str); - } break; - - default: { - } break; - } - }, -}; diff --git a/src/credentialApplication/package-lock.json b/src/credentialApplication/package-lock.json index c346014e8..f16c572bd 100644 --- a/src/credentialApplication/package-lock.json +++ b/src/credentialApplication/package-lock.json @@ -594,9 +594,9 @@ "optional": true }, "node_modules/webpack-dev-server": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz", - "integrity": "sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.10.0.tgz", + "integrity": "sha512-7dezwAs+k6yXVFZ+MaL8VnE+APobiO3zvpp3rBHe/HmWQ+avwh0Q3d0xxacOiBybZZ3syTZw9HXzpa3YNbAZDQ==", "dev": true, "dependencies": { "colorette": "^2.0.10", @@ -1373,9 +1373,9 @@ } }, "node_modules/protobufjs/node_modules/@types/node": { - "version": "18.6.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.4.tgz", - "integrity": "sha512-I4BD3L+6AWiUobfxZ49DlU43gtI+FTHSv9pE2Zekg6KjMpre4ByusaljW3vYSLJrvQ1ck1hUaeVu8HVlY3vzHg==" + "version": "18.7.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.9.tgz", + "integrity": "sha512-0N5Y1XAdcl865nDdjbO0m3T6FdmQ4ijE89/urOHLREyTXbpMWbSafx9y7XIsgWGtwUP2iYTinLyyW3FatAxBLQ==" }, "node_modules/dotenv": { "version": "10.0.0", @@ -1458,9 +1458,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001374", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz", - "integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==", + "version": "1.0.30001381", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001381.tgz", + "integrity": "sha512-fEnkDOKpvp6qc+olg7+NzE1SqyfiyKf4uci7fAU38M3zxs0YOyKOxW/nMZ2l9sJbt7KZHcDIxUnbI0Iime7V4w==", "funding": [ { "type": "opencollective", @@ -1519,9 +1519,9 @@ "dev": true }, "node_modules/colord": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", - "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==", + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true }, "node_modules/postcss/node_modules/picocolors": { @@ -2221,9 +2221,9 @@ } }, "node_modules/portfinder": { - "version": "1.0.29", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.29.tgz", - "integrity": "sha512-Z5+DarHWCKlufshB9Z1pN95oLtANoY5Wn9X3JGELGyQ6VhEcBfT2t+1fGUBq7MwUant6g/mqowH+4HifByPbiQ==", + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", "dev": true, "dependencies": { "async": "^2.6.4", @@ -3299,9 +3299,9 @@ } }, "node_modules/@babel/types": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz", - "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz", + "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.18.10", @@ -3374,9 +3374,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", - "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz", + "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==", "dev": true, "engines": { "node": ">=6.9.0" @@ -3942,14 +3942,14 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.211", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.211.tgz", - "integrity": "sha512-BZSbMpyFQU0KBJ1JG26XGeFI3i4op+qOYGxftmZXFZoHkhLgsSv4DHDJfl8ogII3hIuzGt51PaZ195OVu0yJ9A==" + "version": "1.4.225", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.225.tgz", + "integrity": "sha512-ICHvGaCIQR3P88uK8aRtx8gmejbVJyC6bB4LEC3anzBrIzdzC7aiZHY4iFfXhN4st6I7lMO0x4sgBHf/7kBvRw==" }, "node_modules/@babel/parser": { - "version": "7.18.11", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz", - "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz", + "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -4061,9 +4061,9 @@ } }, "node_modules/bignumber.js": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", - "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.0.tgz", + "integrity": "sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A==", "engines": { "node": "*" } @@ -5474,9 +5474,9 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz", - "integrity": "sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz", + "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.9" @@ -6404,9 +6404,9 @@ } }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -6565,9 +6565,9 @@ } }, "node_modules/@vue/compiler-sfc": { - "version": "2.7.8", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.8.tgz", - "integrity": "sha512-2DK4YWKfgLnW9VDR9gnju1gcYRk3flKj8UNsms7fsRmFcg35slVTZEkqwBtX+wJBXaamFfn6NxSsZh3h12Ix/Q==", + "version": "2.7.9", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.9.tgz", + "integrity": "sha512-TD2FvT0fPUezw5RVP4tfwTZnKHP0QjeEUb39y7tORvOJQTjbOuHJEk4GPHUPsRaTeQ8rjuKjntyrYcEIx+ODxg==", "dependencies": { "@babel/parser": "^7.18.4", "postcss": "^8.4.14", @@ -7605,9 +7605,9 @@ } }, "node_modules/launch-editor": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.5.0.tgz", - "integrity": "sha512-coRiIMBJ3JF7yX8nZE4Fr+xxUy+3WTRsDSwIzHghU28gjXwkAWsvac3BpZrL/jHtbiqQ4TiRAyTJmsgErNk1jQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", + "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", "dev": true, "dependencies": { "picocolors": "^1.0.0", @@ -8184,12 +8184,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.18.12", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz", - "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz", + "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==", "dev": true, "dependencies": { - "@babel/types": "^7.18.10", + "@babel/types": "^7.18.13", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -9297,16 +9297,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz", - "integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.5.tgz", + "integrity": "sha512-AOEDLDxD2zylUGf/wxHxklEkOe2/r+seuyOWujejFrIxHf11brA1/dWQNIgXa1c6/Wkxgu7zvv0JhOWfc2ELEA==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.14", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", - "terser": "^5.7.2" + "terser": "^5.14.1" }, "engines": { "node": ">= 10.13.0" @@ -9598,9 +9598,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", "dev": true }, "node_modules/mime": { @@ -9945,12 +9945,12 @@ "dev": true }, "node_modules/launch-editor-middleware": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.5.0.tgz", - "integrity": "sha512-kv9MMO81pbYjznk9j/DBu0uBGxIpT6uYhGajq6fxdGEPb+DCRBoS96jGkhe3MJumdY3zZFkuS8CFPTZI9DaBNw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.6.0.tgz", + "integrity": "sha512-K2yxgljj5TdCeRN1lBtO3/J26+AIDDDw+04y6VAiZbWcTdBwsYN6RrZBnW5DN/QiSIdKNjKdATLUUluWWFYTIA==", "dev": true, "dependencies": { - "launch-editor": "^2.5.0" + "launch-editor": "^2.6.0" } }, "node_modules/progress-webpack-plugin/node_modules/escape-string-regexp": { @@ -10152,19 +10152,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.18.11", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz", - "integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz", + "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", + "@babel/generator": "^7.18.13", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.18.9", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.11", - "@babel/types": "^7.18.10", + "@babel/parser": "^7.18.13", + "@babel/types": "^7.18.13", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -11087,9 +11087,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.5.tgz", - "integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==", + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz", + "integrity": "sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==", "dev": true, "dependencies": { "@types/estree": "*", @@ -13245,9 +13245,9 @@ } }, "node_modules/vue-template-compiler": { - "version": "2.7.8", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.8.tgz", - "integrity": "sha512-eQqdcUpJKJpBRPDdxCNsqUoT0edNvdt1jFjtVnVS/LPPmr0BU2jWzXlrf6BVMeODtdLewB3j8j3WjNiB+V+giw==", + "version": "2.7.9", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.9.tgz", + "integrity": "sha512-NPJxt6OjVlzmkixYg0SdIN2Lw/rMryQskObY89uAMcM9flS/HrmLK5LaN1ReBTuhBgnYuagZZEkSS6FESATQUQ==", "dev": true, "dependencies": { "de-indent": "^1.0.2", @@ -13457,11 +13457,11 @@ } }, "node_modules/vue": { - "version": "2.7.8", - "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.8.tgz", - "integrity": "sha512-ncwlZx5qOcn754bCu5/tS/IWPhXHopfit79cx+uIlLMyt3vCMGcXai5yCG5y+I6cDmEj4ukRYyZail9FTQh7lQ==", + "version": "2.7.9", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.9.tgz", + "integrity": "sha512-GeWCvAUkjzD5q4A3vgi8ka5r9bM6g8fmNmx/9VnHDKCaEzBcoVw+7UcQktZHrJ2jhlI+Zv8L57pMCIwM4h4MWg==", "dependencies": { - "@vue/compiler-sfc": "2.7.8", + "@vue/compiler-sfc": "2.7.9", "csstype": "^3.1.0" } }, @@ -13939,9 +13939,9 @@ } }, "node_modules/webpack-bundle-analyzer": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz", - "integrity": "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.6.1.tgz", + "integrity": "sha512-oKz9Oz9j3rUciLNfpGFjOb49/jEpXNmWdVH8Ls//zNcnLlQdTGXQQMsBbb/gR7Zl8WNLxVCq+0Hqbx3zv6twBw==", "dev": true, "dependencies": { "acorn": "^8.0.4", @@ -14398,9 +14398,9 @@ } }, "node_modules/cssnano": { - "version": "5.1.12", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.12.tgz", - "integrity": "sha512-TgvArbEZu0lk/dvg2ja+B7kYoD7BBCmn3+k58xD0qjrGHsFzXY/wKTo9M5egcUCabPol05e/PVoIu79s2JN4WQ==", + "version": "5.1.13", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.13.tgz", + "integrity": "sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==", "dev": true, "dependencies": { "cssnano-preset-default": "^5.2.12", @@ -15318,9 +15318,9 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz", - "integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.13.tgz", + "integrity": "sha512-hDvXp+QYxSRL+23mpAlSGxHMDyIGChm0/AwTfTAAK5Ufe40nCsyNdaYCGuK91phn/fVu9kqayImRDkvNAgdrsA==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", @@ -17101,21 +17101,21 @@ "dev": true }, "node_modules/@babel/core": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", - "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz", + "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", + "@babel/generator": "^7.18.13", "@babel/helper-compilation-targets": "^7.18.9", "@babel/helper-module-transforms": "^7.18.9", "@babel/helpers": "^7.18.9", - "@babel/parser": "^7.18.10", + "@babel/parser": "^7.18.13", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.18.10", - "@babel/types": "^7.18.10", + "@babel/traverse": "^7.18.13", + "@babel/types": "^7.18.13", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -17642,9 +17642,9 @@ } }, "node_modules/object.assign": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz", - "integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", @@ -18185,27 +18185,27 @@ } }, "@babel/compat-data": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", - "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz", + "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==", "dev": true }, "@babel/core": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", - "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz", + "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==", "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", + "@babel/generator": "^7.18.13", "@babel/helper-compilation-targets": "^7.18.9", "@babel/helper-module-transforms": "^7.18.9", "@babel/helpers": "^7.18.9", - "@babel/parser": "^7.18.10", + "@babel/parser": "^7.18.13", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.18.10", - "@babel/types": "^7.18.10", + "@babel/traverse": "^7.18.13", + "@babel/types": "^7.18.13", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -18214,12 +18214,12 @@ } }, "@babel/generator": { - "version": "7.18.12", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz", - "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz", + "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==", "dev": true, "requires": { - "@babel/types": "^7.18.10", + "@babel/types": "^7.18.13", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -18269,9 +18269,9 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz", - "integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.13.tgz", + "integrity": "sha512-hDvXp+QYxSRL+23mpAlSGxHMDyIGChm0/AwTfTAAK5Ufe40nCsyNdaYCGuK91phn/fVu9kqayImRDkvNAgdrsA==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", @@ -18544,9 +18544,9 @@ } }, "@babel/parser": { - "version": "7.18.11", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz", - "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==" + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz", + "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.18.6", @@ -18957,9 +18957,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz", - "integrity": "sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz", + "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.9" @@ -19340,27 +19340,27 @@ } }, "@babel/traverse": { - "version": "7.18.11", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz", - "integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz", + "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", + "@babel/generator": "^7.18.13", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.18.9", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.11", - "@babel/types": "^7.18.10", + "@babel/parser": "^7.18.13", + "@babel/types": "^7.18.13", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz", - "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz", + "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.18.10", @@ -19595,9 +19595,9 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", @@ -20011,9 +20011,9 @@ } }, "@types/eslint": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.5.tgz", - "integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==", + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz", + "integrity": "sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==", "dev": true, "requires": { "@types/estree": "*", @@ -20589,9 +20589,9 @@ } }, "@vue/compiler-sfc": { - "version": "2.7.8", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.8.tgz", - "integrity": "sha512-2DK4YWKfgLnW9VDR9gnju1gcYRk3flKj8UNsms7fsRmFcg35slVTZEkqwBtX+wJBXaamFfn6NxSsZh3h12Ix/Q==", + "version": "2.7.9", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.9.tgz", + "integrity": "sha512-TD2FvT0fPUezw5RVP4tfwTZnKHP0QjeEUb39y7tORvOJQTjbOuHJEk4GPHUPsRaTeQ8rjuKjntyrYcEIx+ODxg==", "requires": { "@babel/parser": "^7.18.4", "postcss": "8.4.14", @@ -21541,9 +21541,9 @@ "dev": true }, "bignumber.js": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", - "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==" + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.0.tgz", + "integrity": "sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A==" }, "binary-extensions": { "version": "2.2.0", @@ -22103,9 +22103,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001374", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz", - "integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==" + "version": "1.0.30001381", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001381.tgz", + "integrity": "sha512-fEnkDOKpvp6qc+olg7+NzE1SqyfiyKf4uci7fAU38M3zxs0YOyKOxW/nMZ2l9sJbt7KZHcDIxUnbI0Iime7V4w==" }, "case-sensitive-paths-webpack-plugin": { "version": "2.4.0", @@ -22417,9 +22417,9 @@ } }, "colord": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", - "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==", + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true }, "colorette": { @@ -23039,9 +23039,9 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" }, "cssnano": { - "version": "5.1.12", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.12.tgz", - "integrity": "sha512-TgvArbEZu0lk/dvg2ja+B7kYoD7BBCmn3+k58xD0qjrGHsFzXY/wKTo9M5egcUCabPol05e/PVoIu79s2JN4WQ==", + "version": "5.1.13", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.13.tgz", + "integrity": "sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==", "dev": true, "requires": { "cssnano-preset-default": "^5.2.12", @@ -23785,9 +23785,9 @@ } }, "electron-to-chromium": { - "version": "1.4.211", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.211.tgz", - "integrity": "sha512-BZSbMpyFQU0KBJ1JG26XGeFI3i4op+qOYGxftmZXFZoHkhLgsSv4DHDJfl8ogII3hIuzGt51PaZ195OVu0yJ9A==" + "version": "1.4.225", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.225.tgz", + "integrity": "sha512-ICHvGaCIQR3P88uK8aRtx8gmejbVJyC6bB4LEC3anzBrIzdzC7aiZHY4iFfXhN4st6I7lMO0x4sgBHf/7kBvRw==" }, "elliptic": { "version": "6.5.4", @@ -25751,9 +25751,9 @@ } }, "launch-editor": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.5.0.tgz", - "integrity": "sha512-coRiIMBJ3JF7yX8nZE4Fr+xxUy+3WTRsDSwIzHghU28gjXwkAWsvac3BpZrL/jHtbiqQ4TiRAyTJmsgErNk1jQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", + "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", "dev": true, "requires": { "picocolors": "^1.0.0", @@ -25769,12 +25769,12 @@ } }, "launch-editor-middleware": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.5.0.tgz", - "integrity": "sha512-kv9MMO81pbYjznk9j/DBu0uBGxIpT6uYhGajq6fxdGEPb+DCRBoS96jGkhe3MJumdY3zZFkuS8CFPTZI9DaBNw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.6.0.tgz", + "integrity": "sha512-K2yxgljj5TdCeRN1lBtO3/J26+AIDDDw+04y6VAiZbWcTdBwsYN6RrZBnW5DN/QiSIdKNjKdATLUUluWWFYTIA==", "dev": true, "requires": { - "launch-editor": "^2.5.0" + "launch-editor": "^2.6.0" } }, "lazy-val": { @@ -26772,9 +26772,9 @@ } }, "object.assign": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz", - "integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -27199,9 +27199,9 @@ } }, "portfinder": { - "version": "1.0.29", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.29.tgz", - "integrity": "sha512-Z5+DarHWCKlufshB9Z1pN95oLtANoY5Wn9X3JGELGyQ6VhEcBfT2t+1fGUBq7MwUant6g/mqowH+4HifByPbiQ==", + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", "dev": true, "requires": { "async": "^2.6.4", @@ -27843,9 +27843,9 @@ }, "dependencies": { "@types/node": { - "version": "18.6.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.4.tgz", - "integrity": "sha512-I4BD3L+6AWiUobfxZ49DlU43gtI+FTHSv9pE2Zekg6KjMpre4ByusaljW3vYSLJrvQ1ck1hUaeVu8HVlY3vzHg==" + "version": "18.7.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.9.tgz", + "integrity": "sha512-0N5Y1XAdcl865nDdjbO0m3T6FdmQ4ijE89/urOHLREyTXbpMWbSafx9y7XIsgWGtwUP2iYTinLyyW3FatAxBLQ==" } } }, @@ -29176,9 +29176,9 @@ } }, "spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", "dev": true }, "spdy": { @@ -29661,16 +29661,16 @@ } }, "terser-webpack-plugin": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz", - "integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.5.tgz", + "integrity": "sha512-AOEDLDxD2zylUGf/wxHxklEkOe2/r+seuyOWujejFrIxHf11brA1/dWQNIgXa1c6/Wkxgu7zvv0JhOWfc2ELEA==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.14", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", - "terser": "^5.7.2" + "terser": "^5.14.1" }, "dependencies": { "ajv": { @@ -30368,11 +30368,11 @@ "dev": true }, "vue": { - "version": "2.7.8", - "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.8.tgz", - "integrity": "sha512-ncwlZx5qOcn754bCu5/tS/IWPhXHopfit79cx+uIlLMyt3vCMGcXai5yCG5y+I6cDmEj4ukRYyZail9FTQh7lQ==", + "version": "2.7.9", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.9.tgz", + "integrity": "sha512-GeWCvAUkjzD5q4A3vgi8ka5r9bM6g8fmNmx/9VnHDKCaEzBcoVw+7UcQktZHrJ2jhlI+Zv8L57pMCIwM4h4MWg==", "requires": { - "@vue/compiler-sfc": "2.7.8", + "@vue/compiler-sfc": "2.7.9", "csstype": "^3.1.0" } }, @@ -31596,9 +31596,9 @@ } }, "vue-template-compiler": { - "version": "2.7.8", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.8.tgz", - "integrity": "sha512-eQqdcUpJKJpBRPDdxCNsqUoT0edNvdt1jFjtVnVS/LPPmr0BU2jWzXlrf6BVMeODtdLewB3j8j3WjNiB+V+giw==", + "version": "2.7.9", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.9.tgz", + "integrity": "sha512-NPJxt6OjVlzmkixYg0SdIN2Lw/rMryQskObY89uAMcM9flS/HrmLK5LaN1ReBTuhBgnYuagZZEkSS6FESATQUQ==", "dev": true, "requires": { "de-indent": "^1.0.2", @@ -31958,9 +31958,9 @@ } }, "webpack-bundle-analyzer": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz", - "integrity": "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.6.1.tgz", + "integrity": "sha512-oKz9Oz9j3rUciLNfpGFjOb49/jEpXNmWdVH8Ls//zNcnLlQdTGXQQMsBbb/gR7Zl8WNLxVCq+0Hqbx3zv6twBw==", "dev": true, "requires": { "acorn": "^8.0.4", @@ -32050,9 +32050,9 @@ } }, "webpack-dev-server": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz", - "integrity": "sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.10.0.tgz", + "integrity": "sha512-7dezwAs+k6yXVFZ+MaL8VnE+APobiO3zvpp3rBHe/HmWQ+avwh0Q3d0xxacOiBybZZ3syTZw9HXzpa3YNbAZDQ==", "dev": true, "requires": { "@types/bonjour": "^3.5.9", diff --git a/src/credentialApplication/src/background.js b/src/credentialApplication/src/background.js index 73c0a5ea9..b66ce379f 100644 --- a/src/credentialApplication/src/background.js +++ b/src/credentialApplication/src/background.js @@ -1,14 +1,16 @@ -const electron = require('electron'); import { createProtocol } from 'vue-cli-plugin-electron-builder/lib' -const app = electron.app; -const ipcMain = electron.ipcMain; -const protocol = electron.protocol; -const BrowserWindow = electron.BrowserWindow; +const Electron = require('electron'); const ElectronStore = require('electron-store'); + const ExpoPushTokenManager = require('@/js/ipc/main/ExpoPushTokenManager'); const FCMNotificationManager = require('@/js/ipc/main/FCMNotificationManager'); const RustCompanionManager = require('@/js/ipc/main/RustCompanionManager'); +const app = Electron.app; +const ipcMain = Electron.ipcMain; +const protocol = Electron.protocol; +const BrowserWindow = Electron.BrowserWindow; + /* Scheme must be registered before the app is ready */ protocol.registerSchemesAsPrivileged([{ scheme: 'app', @@ -71,7 +73,7 @@ app.on('ready', () => { /* Open links clicked in main window in external OS browser */ window.webContents.on('new-window', async function (event, url) { event.preventDefault(); - await electron.shell.openExternal(url); + await Electron.shell.openExternal(url); }); if (process.env.WEBPACK_DEV_SERVER_URL) { diff --git a/src/credentialApplication/src/js/ipc/main/ExpoPushTokenManager.js b/src/credentialApplication/src/js/ipc/main/ExpoPushTokenManager.js index 8cfbac3ec..54f86bd6c 100644 --- a/src/credentialApplication/src/js/ipc/main/ExpoPushTokenManager.js +++ b/src/credentialApplication/src/js/ipc/main/ExpoPushTokenManager.js @@ -1,5 +1,5 @@ -const axios = require('axios'); -const https = require('https'); +const Axios = require('axios'); +const Https = require('https'); const { v4: uuidv4 } = require('uuid'); /** @@ -36,7 +36,7 @@ class ExpoPushTokenManager { */ async onRegister(event, data) { /* Register with expo */ - axios.post('https://exp.host/--/api/v2/push/getExpoPushToken', { + Axios.post('https://exp.host/--/api/v2/push/getExpoPushToken', { deviceId: uuidv4(), experienceId: data.experienceId, appId: data.appId, @@ -49,7 +49,7 @@ class ExpoPushTokenManager { * ignores invalid ssl certificates when registering for expo push token * temporary fix for: https://github.com/liamcottle/atlas-for-rust/issues/5 */ - httpsAgent: new https.Agent({ + httpsAgent: new Https.Agent({ rejectUnauthorized: false }) }).then((response) => { diff --git a/src/credentialApplication/src/js/ipc/main/FCMNotificationManager.js b/src/credentialApplication/src/js/ipc/main/FCMNotificationManager.js index 919e27c74..93fa8c10d 100644 --- a/src/credentialApplication/src/js/ipc/main/FCMNotificationManager.js +++ b/src/credentialApplication/src/js/ipc/main/FCMNotificationManager.js @@ -1,4 +1,4 @@ -const { register } = require('push-receiver'); +const PushReceiver = require('push-receiver'); /** * This class is responsible for registering a new android device with fcm @@ -36,7 +36,7 @@ class FCMNotificationManager { async onRegister(event, data) { try { /* Register with gcm/fcm */ - const credentials = await register(data.senderId); + const credentials = await PushReceiver.register(data.senderId); /* Registering was successful */ this.onRegisterSuccess(event, credentials); diff --git a/src/credentialApplication/src/js/ipc/main/RustCompanionManager.js b/src/credentialApplication/src/js/ipc/main/RustCompanionManager.js index 8349c7b1f..89d926123 100644 --- a/src/credentialApplication/src/js/ipc/main/RustCompanionManager.js +++ b/src/credentialApplication/src/js/ipc/main/RustCompanionManager.js @@ -1,4 +1,4 @@ -const axios = require('axios'); +const Axios = require('axios'); /** * This class is responsible for registering with the Rust Companion API. @@ -33,7 +33,7 @@ class RustCompanionManager { */ async onRegister(event, data) { /* Register with rust companion api */ - axios.post('https://companion-rust.facepunch.com:443/api/push/register', { + Axios.post('https://companion-rust.facepunch.com:443/api/push/register', { AuthToken: data.token, DeviceId: data.deviceId, PushKind: 0, diff --git a/src/credentialApplication/src/js/ipc/renderer/ExpoPushTokenReceiver.js b/src/credentialApplication/src/js/ipc/renderer/ExpoPushTokenReceiver.js index a3979a1c8..33d97351d 100644 --- a/src/credentialApplication/src/js/ipc/renderer/ExpoPushTokenReceiver.js +++ b/src/credentialApplication/src/js/ipc/renderer/ExpoPushTokenReceiver.js @@ -1,4 +1,4 @@ -const { EventEmitter } = require('events'); +const Events = require('events'); /** * This class is responsible for communicating with the ExpoPushTokenManager running @@ -7,7 +7,7 @@ const { EventEmitter } = require('events'); * Events are sent from here in the renderer process via ipc to the main process, * and results are then sent back to the renderer process via ipc. */ -class ExpoPushTokenReceiver extends EventEmitter { +class ExpoPushTokenReceiver extends Events.EventEmitter { constructor(ipcRenderer) { super(); diff --git a/src/credentialApplication/src/js/ipc/renderer/FCMNotificationReceiver.js b/src/credentialApplication/src/js/ipc/renderer/FCMNotificationReceiver.js index e60ff6c59..353d12c41 100644 --- a/src/credentialApplication/src/js/ipc/renderer/FCMNotificationReceiver.js +++ b/src/credentialApplication/src/js/ipc/renderer/FCMNotificationReceiver.js @@ -1,4 +1,4 @@ -const { EventEmitter } = require('events'); +const Events = require('events'); /** * This class is responsible for communicating with the FCMNotificationManager running @@ -7,7 +7,7 @@ const { EventEmitter } = require('events'); * Events are sent from here in the renderer process via ipc to the main process, * and results are then sent back to the renderer process via ipc. */ -class FCMNotificationReceiver extends EventEmitter { +class FCMNotificationReceiver extends Events.EventEmitter { constructor(ipcRenderer) { super(); diff --git a/src/credentialApplication/src/js/ipc/renderer/RustCompanionReceiver.js b/src/credentialApplication/src/js/ipc/renderer/RustCompanionReceiver.js index 68a00e3fb..deaf9882c 100644 --- a/src/credentialApplication/src/js/ipc/renderer/RustCompanionReceiver.js +++ b/src/credentialApplication/src/js/ipc/renderer/RustCompanionReceiver.js @@ -1,4 +1,4 @@ -const { EventEmitter } = require('events'); +const Events = require('events'); /** * This class is responsible for communicating with the RustCompanionManager running @@ -7,7 +7,7 @@ const { EventEmitter } = require('events'); * Events are sent from here in the renderer process via ipc to the main process, * and results are then sent back to the renderer process via ipc. */ -class RustCompanionReceiver extends EventEmitter { +class RustCompanionReceiver extends Events.EventEmitter { constructor(ipcRenderer) { super(); diff --git a/src/credentialApplication/src/main.js b/src/credentialApplication/src/main.js index 88815c376..3821ad106 100644 --- a/src/credentialApplication/src/main.js +++ b/src/credentialApplication/src/main.js @@ -1,5 +1,5 @@ -import Vue from 'vue' import App from '@/App.vue' +import Vue from 'vue' /* Add globals */ window.ExpoPushTokenReceiver = require('@/js/ipc/renderer/ExpoPushTokenReceiver'); diff --git a/src/credentialApplication/src/preload.js b/src/credentialApplication/src/preload.js index cea48bb62..0b68c2a9e 100644 --- a/src/credentialApplication/src/preload.js +++ b/src/credentialApplication/src/preload.js @@ -1,7 +1,7 @@ /* Allow browser to use ipc */ -let electron = require('electron'); -window.appversion = electron.remote.app.getVersion(); -window.ipcRenderer = electron.ipcRenderer; +let Electron = require('electron'); +window.appversion = Electron.remote.app.getVersion(); +window.ipcRenderer = Electron.ipcRenderer; /* Add utils */ window.uuidv4 = require('uuid').v4; diff --git a/src/discordEvents/interactionCreate.js b/src/discordEvents/interactionCreate.js index 5948f2c30..976aefc54 100644 --- a/src/discordEvents/interactionCreate.js +++ b/src/discordEvents/interactionCreate.js @@ -1,4 +1,6 @@ -const { EmbedBuilder, InteractionType } = require('discord.js'); +const Discord = require('discord.js'); + +const DiscordEmbeds = require('../discordTools/discordEmbeds'); module.exports = { name: 'interactionCreate', @@ -24,7 +26,7 @@ module.exports = { else if (interaction.isSelectMenu()) { require('../handlers/selectMenuHandler')(client, interaction); } - else if (interaction.type === InteractionType.ApplicationCommand) { + else if (interaction.type === Discord.InteractionType.ApplicationCommand) { const command = interaction.client.commands.get(interaction.commandName); /* If the command doesn't exist, return */ @@ -38,15 +40,13 @@ module.exports = { client.log('ERROR', error, 'error'); let str = 'There was an error while executing this command!'; - await client.interactionEditReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); + await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); client.log('ERROR', str, 'error'); } } + else if (interaction.type === Discord.InteractionType.ModalSubmit) { + require('../handlers/modalHandler')(client, interaction); + } else { client.log('ERROR', 'Unknown Interaction...', 'error') if (interaction.isButton()) { diff --git a/src/discordTools/RegisterSlashCommands.js b/src/discordTools/RegisterSlashCommands.js index 981d96c32..037d983b7 100644 --- a/src/discordTools/RegisterSlashCommands.js +++ b/src/discordTools/RegisterSlashCommands.js @@ -1,21 +1,22 @@ -const fs = require("fs"); -const { REST } = require('@discordjs/rest'); -const { Routes } = require('discord-api-types/v9'); +const Fs = require("fs"); +const Rest = require('@discordjs/rest'); +const Types = require('discord-api-types/v9'); + const Config = require('../../config.json'); module.exports = async (client, guild) => { const commands = []; - const commandFiles = fs.readdirSync(`${__dirname}/../commands`).filter(file => file.endsWith('.js')); + const commandFiles = Fs.readdirSync(`${__dirname}/../commands`).filter(file => file.endsWith('.js')); for (const file of commandFiles) { const command = require(`../commands/${file}`); commands.push(command.data.toJSON()); } - const rest = new REST({ version: '9' }).setToken(Config.discord.token); + const rest = new Rest.REST({ version: '9' }).setToken(Config.discord.token); try { - await rest.put(Routes.applicationGuildCommands(Config.discord.clientId, guild.id), { body: commands }); + await rest.put(Types.Routes.applicationGuildCommands(Config.discord.clientId, guild.id), { body: commands }); } catch (e) { client.log('ERROR', diff --git a/src/discordTools/SetupAlarms.js b/src/discordTools/SetupAlarms.js index 47426e158..1fb525e7a 100644 --- a/src/discordTools/SetupAlarms.js +++ b/src/discordTools/SetupAlarms.js @@ -1,31 +1,29 @@ -const DiscordTools = require('./discordTools.js'); +const DiscordMessages = require('./discordMessages.js'); module.exports = async (client, rustplus) => { let instance = client.readInstanceFile(rustplus.guildId); - for (const [key, value] of Object.entries(instance.alarms)) { - if (rustplus.serverId !== `${value.serverId}`) continue; - + for (const [key, value] of Object.entries(instance.serverList[rustplus.serverId].alarms)) { let info = await rustplus.getEntityInfoAsync(key); instance = client.readInstanceFile(rustplus.guildId); if (!(await rustplus.isResponseValid(info))) { - await DiscordTools.sendSmartAlarmNotFound(rustplus.guildId, key); - instance.alarms[key].reachable = false; + await DiscordMessages.sendSmartAlarmNotFoundMessage(rustplus.guildId, rustplus.serverId, key); + instance.serverList[rustplus.serverId].alarms[key].reachable = false; } else { - instance.alarms[key].reachable = true; + instance.serverList[rustplus.serverId].alarms[key].reachable = true; } client.writeInstanceFile(rustplus.guildId, instance); - if (instance.alarms[key].reachable) { - if (instance.alarms[key].active !== info.entityInfo.payload.value) { - instance.alarms[key].active = info.entityInfo.payload.value; + if (instance.serverList[rustplus.serverId].alarms[key].reachable) { + if (instance.serverList[rustplus.serverId].alarms[key].active !== info.entityInfo.payload.value) { + instance.serverList[rustplus.serverId].alarms[key].active = info.entityInfo.payload.value; client.writeInstanceFile(rustplus.guildId, instance); } } - await DiscordTools.sendSmartAlarmMessage(rustplus.guildId, key); + await DiscordMessages.sendSmartAlarmMessage(rustplus.guildId, rustplus.serverId, key); } }; diff --git a/src/discordTools/SetupGuildCategory.js b/src/discordTools/SetupGuildCategory.js index 7f4f6c340..31abdc370 100644 --- a/src/discordTools/SetupGuildCategory.js +++ b/src/discordTools/SetupGuildCategory.js @@ -1,5 +1,6 @@ +const Discord = require('discord.js'); + const DiscordTools = require('../discordTools/discordTools.js'); -const { PermissionFlagsBits } = require('discord.js'); module.exports = async (client, guild) => { let instance = client.readInstanceFile(guild.id); @@ -20,17 +21,17 @@ module.exports = async (client, guild) => { let roleAllow = []; let roleDeny = []; if (instance.role !== null) { - everyoneDeny.push(PermissionFlagsBits.ViewChannel); - everyoneDeny.push(PermissionFlagsBits.SendMessages); - roleAllow.push(PermissionFlagsBits.ViewChannel); - roleDeny.push(PermissionFlagsBits.SendMessages); + everyoneDeny.push(Discord.PermissionFlagsBits.ViewChannel); + everyoneDeny.push(Discord.PermissionFlagsBits.SendMessages); + roleAllow.push(Discord.PermissionFlagsBits.ViewChannel); + roleDeny.push(Discord.PermissionFlagsBits.SendMessages); perms.push({ id: guild.roles.everyone.id, deny: everyoneDeny }); perms.push({ id: instance.role, allow: roleAllow, deny: roleDeny }); } else { - everyoneAllow.push(PermissionFlagsBits.ViewChannel); - everyoneDeny.push(PermissionFlagsBits.SendMessages); + everyoneAllow.push(Discord.PermissionFlagsBits.ViewChannel); + everyoneDeny.push(Discord.PermissionFlagsBits.SendMessages); perms.push({ id: guild.roles.everyone.id, allow: everyoneAllow, deny: everyoneDeny }); } diff --git a/src/discordTools/SetupGuildChannels.js b/src/discordTools/SetupGuildChannels.js index ebfad55a7..f9da1033a 100644 --- a/src/discordTools/SetupGuildChannels.js +++ b/src/discordTools/SetupGuildChannels.js @@ -1,5 +1,6 @@ +const Discord = require('discord.js'); + const DiscordTools = require('../discordTools/discordTools.js'); -const { PermissionFlagsBits } = require('discord.js'); module.exports = async (client, guild, category) => { await addTextChannel('information', client, guild, category); @@ -50,28 +51,28 @@ async function addTextChannel(name, client, guild, parent, permissionWrite = fal let roleDeny = []; if (instance.role !== null) { if (permissionWrite) { - roleAllow.push(PermissionFlagsBits.SendMessages); + roleAllow.push(Discord.PermissionFlagsBits.SendMessages); } else { - roleDeny.push(PermissionFlagsBits.SendMessages); + roleDeny.push(Discord.PermissionFlagsBits.SendMessages); } - everyoneDeny.push(PermissionFlagsBits.ViewChannel); - everyoneDeny.push(PermissionFlagsBits.SendMessages); - roleAllow.push(PermissionFlagsBits.ViewChannel); + everyoneDeny.push(Discord.PermissionFlagsBits.ViewChannel); + everyoneDeny.push(Discord.PermissionFlagsBits.SendMessages); + roleAllow.push(Discord.PermissionFlagsBits.ViewChannel); perms.push({ id: guild.roles.everyone.id, deny: everyoneDeny }); perms.push({ id: instance.role, allow: roleAllow, deny: roleDeny }); } else { if (permissionWrite) { - everyoneAllow.push(PermissionFlagsBits.SendMessages); + everyoneAllow.push(Discord.PermissionFlagsBits.SendMessages); } else { - everyoneDeny.push(PermissionFlagsBits.SendMessages); + everyoneDeny.push(Discord.PermissionFlagsBits.SendMessages); } - everyoneAllow.push(PermissionFlagsBits.ViewChannel); + everyoneAllow.push(Discord.PermissionFlagsBits.ViewChannel); perms.push({ id: guild.roles.everyone.id, allow: everyoneAllow, deny: everyoneDeny }); } diff --git a/src/discordTools/SetupServerList.js b/src/discordTools/SetupServerList.js index 2a9fb26ae..d506bacfd 100644 --- a/src/discordTools/SetupServerList.js +++ b/src/discordTools/SetupServerList.js @@ -1,3 +1,5 @@ + +const DiscordMessages = require('./discordMessages.js'); const DiscordTools = require('./discordTools.js'); module.exports = async (client, guild) => { @@ -6,6 +8,6 @@ module.exports = async (client, guild) => { await DiscordTools.clearTextChannel(guild.id, instance.channelId.servers, 100); for (const [key, value] of Object.entries(instance.serverList)) { - await DiscordTools.sendServerMessage(guild.id, key); + await DiscordMessages.sendServerMessage(guild.id, key); } }; diff --git a/src/discordTools/SetupSettingsMenu.js b/src/discordTools/SetupSettingsMenu.js index 5a3f76db7..4d0a84b1e 100644 --- a/src/discordTools/SetupSettingsMenu.js +++ b/src/discordTools/SetupSettingsMenu.js @@ -1,4 +1,8 @@ -const { EmbedBuilder, AttachmentBuilder } = require('discord.js'); +const Discord = require('discord.js'); + +const DiscordButtons = require('./discordButtons.js'); +const DiscordEmbeds = require('./discordEmbeds.js'); +const DiscordSelectMenus = require('./discordSelectMenus.js'); const DiscordTools = require('./discordTools.js'); module.exports = async (client, guild) => { @@ -13,7 +17,7 @@ module.exports = async (client, guild) => { if (instance.firstTime) { await DiscordTools.clearTextChannel(guild.id, instance.channelId.settings, 100); - await setupGeneralSettings(client, instance, channel); + await setupGeneralSettings(client, guild.id, instance, channel); await setupNotificationSettings(client, instance, channel); instance.firstTime = false; @@ -22,119 +26,133 @@ module.exports = async (client, guild) => { }; -async function setupGeneralSettings(client, instance, channel) { +async function setupGeneralSettings(client, guildId, instance, channel) { await client.messageSend(channel, { - files: [new AttachmentBuilder('src/resources/images/general_settings_logo.png')] + files: [new Discord.AttachmentBuilder('src/resources/images/general_settings_logo.png')] }); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#861c0c') - .setTitle('Select what in-game command prefix that should be used:') - .setThumbnail(`attachment://settings_logo.png`)], - components: [DiscordTools.getPrefixSelectMenu(instance.generalSettings.prefix)], - files: [new AttachmentBuilder('src/resources/images/settings_logo.png')] + embeds: [DiscordEmbeds.getEmbed({ + color: '#861c0c', + title: 'Select what in-game command prefix that should be used:', + thumbnail: `attachment://settings_logo.png` + })], + components: [DiscordSelectMenus.getPrefixSelectMenu(instance.generalSettings.prefix)], + files: [new Discord.AttachmentBuilder('src/resources/images/settings_logo.png')] }); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#861c0c') - .setTitle(`Select which trademark that should be shown in every in-game message.`) - .setThumbnail(`attachment://settings_logo.png`)], - components: [DiscordTools.getTrademarkSelectMenu(instance.generalSettings.trademark)], - files: [new AttachmentBuilder('src/resources/images/settings_logo.png')] + embeds: [DiscordEmbeds.getEmbed({ + color: '#861c0c', + title: `Select which trademark that should be shown in every in-game message.`, + thumbnail: `attachment://settings_logo.png` + })], + components: [DiscordSelectMenus.getTrademarkSelectMenu(instance.generalSettings.trademark)], + files: [new Discord.AttachmentBuilder('src/resources/images/settings_logo.png')] }); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#861c0c') - .setTitle('Should in-game commands be enabled?') - .setThumbnail(`attachment://settings_logo.png`)], - components: [DiscordTools.getInGameCommandsEnabledButton(instance.generalSettings.inGameCommandsEnabled)], - files: [new AttachmentBuilder('src/resources/images/settings_logo.png')] + embeds: [DiscordEmbeds.getEmbed({ + color: '#861c0c', + title: 'Should in-game commands be enabled?', + thumbnail: `attachment://settings_logo.png` + })], + components: [DiscordButtons.getInGameCommandsEnabledButton(instance.generalSettings.inGameCommandsEnabled)], + files: [new Discord.AttachmentBuilder('src/resources/images/settings_logo.png')] }); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#861c0c') - .setTitle('In-game teammate notifications.') - .setThumbnail(`attachment://settings_logo.png`)], - components: [DiscordTools.getInGameTeammateNotificationsButtons(instance)], - files: [new AttachmentBuilder('src/resources/images/settings_logo.png')] + embeds: [DiscordEmbeds.getEmbed({ + color: '#861c0c', + title: 'In-game teammate notifications.', + thumbnail: `attachment://settings_logo.png` + })], + components: [DiscordButtons.getInGameTeammateNotificationsButtons(guildId)], + files: [new Discord.AttachmentBuilder('src/resources/images/settings_logo.png')] }); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#861c0c') - .setTitle('Should there be a command delay? How long?') - .setThumbnail(`attachment://settings_logo.png`)], - components: [DiscordTools.getCommandDelaySelectMenu(instance.generalSettings.commandDelay)], - files: [new AttachmentBuilder('src/resources/images/settings_logo.png')] + embeds: [DiscordEmbeds.getEmbed({ + color: '#861c0c', + title: 'Should there be a command delay? How long?', + thumbnail: `attachment://settings_logo.png` + })], + components: [DiscordSelectMenus.getCommandDelaySelectMenu(instance.generalSettings.commandDelay)], + files: [new Discord.AttachmentBuilder('src/resources/images/settings_logo.png')] }); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#861c0c') - .setTitle('Should Smart Alarms notify even if they are not setup on the connected rust server?') - .addFields( - { name: 'NOTE', value: '- These Alarm notifications will use the title and message given to the Smart Alarm in-game.\n- These Smart Alarms might not be available in the alarms text channel in discord.', inline: true } - ) - .setThumbnail(`attachment://settings_logo.png`)], + embeds: [DiscordEmbeds.getEmbed({ + color: '#861c0c', + title: 'Should Smart Alarms notify even if they are not setup on the connected rust server?', + thumbnail: `attachment://settings_logo.png`, + fields: [ + { + name: 'NOTE', + value: '- These Alarm notifications will use the title and message given to the Smart Alarm ' + + 'in-game.\n- These Smart Alarms might not be available in the alarms text channel in discord.', + inline: true + }] + })], components: [ - DiscordTools.getFcmAlarmNotificationButtons( + DiscordButtons.getFcmAlarmNotificationButtons( instance.generalSettings.fcmAlarmNotificationEnabled, instance.generalSettings.fcmAlarmNotificationEveryone)], - files: [new AttachmentBuilder('src/resources/images/settings_logo.png')] + files: [new Discord.AttachmentBuilder('src/resources/images/settings_logo.png')] }); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#861c0c') - .setTitle('Should Smart Alarms notify In-Game?') - .setThumbnail(`attachment://settings_logo.png`)], - components: [DiscordTools.getSmartAlarmNotifyInGameButton(instance.generalSettings.smartAlarmNotifyInGame)], - files: [new AttachmentBuilder('src/resources/images/settings_logo.png')] + embeds: [DiscordEmbeds.getEmbed({ + color: '#861c0c', + title: 'Should Smart Alarms notify In-Game?', + thumbnail: `attachment://settings_logo.png`, + })], + components: [DiscordButtons.getSmartAlarmNotifyInGameButton(instance.generalSettings.smartAlarmNotifyInGame)], + files: [new Discord.AttachmentBuilder('src/resources/images/settings_logo.png')] }); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#861c0c') - .setTitle('Should the leader command be enabled?') - .setThumbnail(`attachment://settings_logo.png`)], - components: [DiscordTools.getLeaderCommandEnabledButton(instance.generalSettings.leaderCommandEnabled)], - files: [new AttachmentBuilder('src/resources/images/settings_logo.png')] + embeds: [DiscordEmbeds.getEmbed({ + color: '#861c0c', + title: 'Should the leader command be enabled?', + thumbnail: `attachment://settings_logo.png`, + })], + components: [DiscordButtons.getLeaderCommandEnabledButton(instance.generalSettings.leaderCommandEnabled)], + files: [new Discord.AttachmentBuilder('src/resources/images/settings_logo.png')] }); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#861c0c') - .setTitle('When should the Battlemetrics trackers notify?') - .setThumbnail(`attachment://settings_logo.png`)], - components: [DiscordTools.getTrackerNotifyButtons( + embeds: [DiscordEmbeds.getEmbed({ + color: '#861c0c', + title: 'When should the Battlemetrics trackers notify?', + thumbnail: `attachment://settings_logo.png` + })], + components: [DiscordButtons.getTrackerNotifyButtons( instance.generalSettings.trackerNotifyAllOffline, instance.generalSettings.trackerNotifyAnyOnline)], - files: [new AttachmentBuilder('src/resources/images/settings_logo.png')] + files: [new Discord.AttachmentBuilder('src/resources/images/settings_logo.png')] }); } async function setupNotificationSettings(client, instance, channel) { await client.messageSend(channel, { - files: [new AttachmentBuilder('src/resources/images/notification_settings_logo.png')] + files: [new Discord.AttachmentBuilder('src/resources/images/notification_settings_logo.png')] }); for (let setting in instance.notificationSettings) { await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#861c0c') - .setTitle(instance.notificationSettings[setting].description) - .setThumbnail(`attachment://${instance.notificationSettings[setting].image}`)], + embeds: [DiscordEmbeds.getEmbed({ + color: '#861c0c', + title: instance.notificationSettings[setting].description, + thumbnail: `attachment://${instance.notificationSettings[setting].image}` + })], components: [ - DiscordTools.getNotificationButtons( + DiscordButtons.getNotificationButtons( setting, instance.notificationSettings[setting].discord, instance.notificationSettings[setting].inGame)], files: [ - new AttachmentBuilder(`src/resources/images/events/${instance.notificationSettings[setting].image}`)] + new Discord.AttachmentBuilder(`src/resources/images/events/${instance.notificationSettings[setting].image}`)] }); } } \ No newline at end of file diff --git a/src/discordTools/SetupStorageMonitors.js b/src/discordTools/SetupStorageMonitors.js index a34b11b39..e360000b2 100644 --- a/src/discordTools/SetupStorageMonitors.js +++ b/src/discordTools/SetupStorageMonitors.js @@ -1,29 +1,28 @@ +const DiscordMessages = require('./discordMessages.js'); const DiscordTools = require('./discordTools.js'); -module.exports = async (client, rustplus) => { +module.exports = async (client, rustplus, newConnection = false) => { let instance = client.readInstanceFile(rustplus.guildId); - client.storageMonitorsMessages[rustplus.guildId] = {}; - - await DiscordTools.clearTextChannel(rustplus.guildId, instance.channelId.storageMonitors, 100); - - for (const [key, value] of Object.entries(instance.storageMonitors)) { - if (rustplus.serverId !== `${value.serverId}`) continue; + if (newConnection) { + await DiscordTools.clearTextChannel(rustplus.guildId, instance.channelId.storageMonitors, 100); + } + for (const [key, value] of Object.entries(instance.serverList[rustplus.serverId].storageMonitors)) { let info = await rustplus.getEntityInfoAsync(key); instance = client.readInstanceFile(rustplus.guildId); if (!(await rustplus.isResponseValid(info))) { - await DiscordTools.sendStorageMonitorNotFound(rustplus.guildId, key); - instance.storageMonitors[key].reachable = false; + await DiscordMessages.sendStorageMonitorNotFoundMessage(rustplus.guildId, rustplus.serverId, key); + instance.serverList[rustplus.serverId].storageMonitors[key].reachable = false; } else { - instance.storageMonitors[key].reachable = true; + instance.serverList[rustplus.serverId].storageMonitors[key].reachable = true; } client.writeInstanceFile(rustplus.guildId, instance); - if (instance.storageMonitors[key].reachable) { + if (instance.serverList[rustplus.serverId].storageMonitors[key].reachable) { rustplus.storageMonitors[key] = { items: info.entityInfo.payload.items, expiry: info.entityInfo.payload.protectionExpiry, @@ -33,21 +32,21 @@ module.exports = async (client, rustplus) => { if (info.entityInfo.payload.capacity !== 0) { if (info.entityInfo.payload.capacity === 28) { - instance.storageMonitors[key].type = 'toolcupboard'; + instance.serverList[rustplus.serverId].storageMonitors[key].type = 'toolcupboard'; if (info.entityInfo.payload.protectionExpiry === 0) { - instance.storageMonitors[key].decaying = true; + instance.serverList[rustplus.serverId].storageMonitors[key].decaying = true; } else { - instance.storageMonitors[key].decaying = false; + instance.serverList[rustplus.serverId].storageMonitors[key].decaying = false; } } else { - instance.storageMonitors[key].type = 'container'; + instance.serverList[rustplus.serverId].storageMonitors[key].type = 'container'; } client.writeInstanceFile(rustplus.guildId, instance); } } - await DiscordTools.sendStorageMonitorMessage(rustplus.guildId, key); + await DiscordMessages.sendStorageMonitorMessage(rustplus.guildId, rustplus.serverId, key); } }; diff --git a/src/discordTools/SetupSwitchGroups.js b/src/discordTools/SetupSwitchGroups.js index a04825fe5..039345fe8 100644 --- a/src/discordTools/SetupSwitchGroups.js +++ b/src/discordTools/SetupSwitchGroups.js @@ -1,20 +1,9 @@ -const DiscordTools = require('./discordTools.js'); +const DiscordMessages = require('./discordMessages.js'); module.exports = async (client, rustplus) => { let instance = client.readInstanceFile(rustplus.guildId); - if (!client.switchesMessages.hasOwnProperty(rustplus.guildId)) { - client.switchesMessages[rustplus.guildId] = {}; - } - - if (!instance.serverList[rustplus.serverId].hasOwnProperty('switchGroups')) { - instance.serverList[rustplus.serverId].switchGroups = {}; - client.writeInstanceFile(rustplus.guildId, instance); - } - - for (const [groupName, content] of Object.entries(instance.serverList[rustplus.serverId].switchGroups)) { - if (rustplus.serverId !== `${content.serverId}`) continue; - - await DiscordTools.sendSmartSwitchGroupMessage(rustplus.guildId, groupName); + for (const [groupId, content] of Object.entries(instance.serverList[rustplus.serverId].switchGroups)) { + await DiscordMessages.sendSmartSwitchGroupMessage(rustplus.guildId, rustplus.serverId, groupId); } }; diff --git a/src/discordTools/SetupSwitches.js b/src/discordTools/SetupSwitches.js index 069f4fda1..937222dd3 100644 --- a/src/discordTools/SetupSwitches.js +++ b/src/discordTools/SetupSwitches.js @@ -1,33 +1,32 @@ +const DiscordMessages = require('./discordMessages.js'); const DiscordTools = require('./discordTools.js'); -module.exports = async (client, rustplus) => { +module.exports = async (client, rustplus, newConnection = false) => { let instance = client.readInstanceFile(rustplus.guildId); - client.switchesMessages[rustplus.guildId] = {}; - - await DiscordTools.clearTextChannel(rustplus.guildId, instance.channelId.switches, 100); - - for (const [key, value] of Object.entries(instance.switches)) { - if (rustplus.serverId !== `${value.serverId}`) continue; + if (newConnection) { + await DiscordTools.clearTextChannel(rustplus.guildId, instance.channelId.switches, 100); + } + for (const [key, value] of Object.entries(instance.serverList[rustplus.serverId].switches)) { let info = await rustplus.getEntityInfoAsync(key); instance = client.readInstanceFile(rustplus.guildId); if (!(await rustplus.isResponseValid(info))) { - await DiscordTools.sendSmartSwitchNotFound(rustplus.guildId, key); - instance.switches[key].reachable = false; + await DiscordMessages.sendSmartSwitchNotFoundMessage(rustplus.guildId, rustplus.serverId, key); + instance.serverList[rustplus.serverId].switches[key].reachable = false; } else { - instance.switches[key].reachable = true; + instance.serverList[rustplus.serverId].switches[key].reachable = true; } client.writeInstanceFile(rustplus.guildId, instance); - if (instance.switches[key].reachable) { - instance.switches[key].active = info.entityInfo.payload.value; + if (instance.serverList[rustplus.serverId].switches[key].reachable) { + instance.serverList[rustplus.serverId].switches[key].active = info.entityInfo.payload.value; client.writeInstanceFile(rustplus.guildId, instance); } - await DiscordTools.sendSmartSwitchMessage(rustplus.guildId, key); + await DiscordMessages.sendSmartSwitchMessage(rustplus.guildId, rustplus.serverId, key); } }; diff --git a/src/discordTools/SetupTrackers.js b/src/discordTools/SetupTrackers.js index a27f558b2..1630cfe77 100644 --- a/src/discordTools/SetupTrackers.js +++ b/src/discordTools/SetupTrackers.js @@ -1,3 +1,4 @@ +const DiscordMessages = require('./discordMessages.js'); const DiscordTools = require('./discordTools.js'); module.exports = async (client, guild) => { @@ -6,6 +7,6 @@ module.exports = async (client, guild) => { await DiscordTools.clearTextChannel(guild.id, instance.channelId.trackers, 100); for (const [key, value] of Object.entries(instance.trackers)) { - await DiscordTools.sendTrackerMessage(guild.id, key); + await DiscordMessages.sendTrackerMessage(guild.id, key); } } \ No newline at end of file diff --git a/src/discordTools/discordButtons.js b/src/discordTools/discordButtons.js new file mode 100644 index 000000000..daac02101 --- /dev/null +++ b/src/discordTools/discordButtons.js @@ -0,0 +1,388 @@ +const Discord = require('discord.js'); + +const Constants = require('../util/constants.js'); +const Client = require('../../index.ts'); + +const SUCCESS = Discord.ButtonStyle.Success; +const DANGER = Discord.ButtonStyle.Danger; +const PRIMARY = Discord.ButtonStyle.Primary; +const SECONDARY = Discord.ButtonStyle.Secondary; +const LINK = Discord.ButtonStyle.Link; + +module.exports = { + getButton: function (options = {}) { + const button = new Discord.ButtonBuilder(); + + if (options.customId) button.setCustomId(options.customId); + if (options.label) button.setLabel(options.label); + if (options.style) button.setStyle(options.style); + if (options.url) button.setURL(options.url); + if (options.emoji) button.setEmoji(options.emoji); + if (options.disabled) button.setDisabled(options.disabled); + + return button; + }, + + getServerButtons: function (guildId, serverId, state = null) { + const instance = Client.client.readInstanceFile(guildId); + const server = instance.serverList[serverId]; + const identifier = `{"serverId":"${serverId}"}`; + + if (state === null) state = (instance.serverList[serverId].active) ? 1 : 0; + + let connectionButton = null; + if (state === 0) { + connectionButton = module.exports.getButton({ + customId: `ServerConnect${identifier}`, + label: 'CONNECT', + style: PRIMARY + }); + } + else if (state === 1) { + connectionButton = module.exports.getButton({ + customId: `ServerDisconnect${identifier}`, + label: 'DISCONNECT', + style: DANGER + }); + } + else if (state === 2) { + connectionButton = module.exports.getButton({ + customId: `ServerReconnecting${identifier}`, + label: 'RECONNECTING...', + style: DANGER + }); + } + + const customTimersButton = module.exports.getButton({ + customId: `CustomTimersEdit${identifier}`, + label: 'CUSTOM TIMERS', + style: PRIMARY + }); + const trackerButton = module.exports.getButton({ + customId: `CreateTracker${identifier}`, + label: 'CREATE TRACKER', + style: PRIMARY + }); + const groupButton = module.exports.getButton({ + customId: `CreateGroup${identifier}`, + label: 'CREATE GROUP', + style: PRIMARY + }); + let linkButton = module.exports.getButton({ + label: 'WEBSITE', + style: LINK, + url: server.url + }); + let deleteButton = module.exports.getButton({ + customId: `ServerDelete${identifier}`, + style: SECONDARY, + emoji: '🗑️' + }); + + if (server.battlemetricsId !== null) { + return [ + new Discord.ActionRowBuilder().addComponents( + connectionButton, linkButton, deleteButton + ), + new Discord.ActionRowBuilder().addComponents( + customTimersButton, trackerButton, groupButton + ) + ]; + } + else { + return [ + new Discord.ActionRowBuilder().addComponents( + connectionButton, linkButton, deleteButton + ), + new Discord.ActionRowBuilder().addComponents( + customTimersButton, groupButton + ) + ]; + } + }, + + getSmartSwitchButtons: function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].switches[entityId]; + const identifier = `{"serverId":"${serverId}","entityId":${entityId}}`; + + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: `SmartSwitch${entity.active ? 'Off' : 'On'}${identifier}`, + label: entity.active ? 'TURN OFF' : 'TURN ON', + style: entity.active ? DANGER : SUCCESS + }), + module.exports.getButton({ + customId: `SmartSwitchEdit${identifier}`, + label: 'EDIT', + style: PRIMARY + }), + module.exports.getButton({ + customId: `SmartSwitchDelete${identifier}`, + style: SECONDARY, + emoji: '🗑️' + })); + }, + + getSmartSwitchGroupButtons: function (serverId, groupId) { + const identifier = `{"serverId":"${serverId}","groupId":${groupId}}`; + + return [ + new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: `GroupTurnOn${identifier}`, + label: 'TURN ON', + style: PRIMARY + }), + module.exports.getButton({ + customId: `GroupTurnOff${identifier}`, + label: 'TURN OFF', + style: PRIMARY + }), + module.exports.getButton({ + customId: `GroupEdit${identifier}`, + label: 'EDIT', + style: PRIMARY + }), + module.exports.getButton({ + customId: `GroupDelete${identifier}`, + style: SECONDARY, + emoji: '🗑️' + })), + new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: `GroupAddSwitch${identifier}`, + label: 'ADD SWITCH', + style: SUCCESS + }), + module.exports.getButton({ + customId: `GroupRemoveSwitch${identifier}`, + label: 'REMOVE SWITCH', + style: DANGER + })) + ]; + }, + + getSmartAlarmButtons: function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].alarms[entityId]; + const identifier = `{"serverId":"${serverId}","entityId":${entityId}}`; + + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: `SmartAlarmEveryone${identifier}`, + label: '@everyone', + style: entity.everyone ? SUCCESS : DANGER + }), + module.exports.getButton({ + customId: `SmartAlarmEdit${identifier}`, + label: 'EDIT', + style: PRIMARY + }), + module.exports.getButton({ + customId: `SmartAlarmDelete${identifier}`, + style: SECONDARY, + emoji: '🗑️' + })); + }, + + getStorageMonitorToolCupboardButtons: function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].storageMonitors[entityId]; + const identifier = `{"serverId":"${serverId}","entityId":${entityId}}`; + + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: `StorageMonitorToolCupboardEveryone${identifier}`, + label: '@everyone', + style: entity.everyone ? SUCCESS : DANGER + }), + module.exports.getButton({ + customId: `StorageMonitorToolCupboardInGame${identifier}`, + label: 'IN-GAME', + style: entity.inGame ? SUCCESS : DANGER + }), + module.exports.getButton({ + customId: `StorageMonitorEdit${identifier}`, + label: 'EDIT', + style: PRIMARY, + }), + module.exports.getButton({ + customId: `StorageMonitorToolCupboardDelete${identifier}`, + style: SECONDARY, + emoji: '🗑️' + })); + }, + + getStorageMonitorContainerButton: function (serverId, entityId) { + const identifier = `{"serverId":"${serverId}","entityId":${entityId}}`; + + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: `StorageMonitorEdit${identifier}`, + label: 'EDIT', + style: PRIMARY, + }), + module.exports.getButton({ + customId: `StorageMonitorRecycle${identifier}`, + label: 'RECYCLE', + style: PRIMARY, + }), + module.exports.getButton({ + customId: `StorageMonitorContainerDelete${identifier}`, + style: SECONDARY, + emoji: '🗑️' + })); + }, + + getRecycleDeleteButton: function () { + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: 'RecycleDelete', + style: SECONDARY, + emoji: '🗑️' + })); + }, + + getNotificationButtons: function (setting, discordActive, inGameActive) { + const identifier = `{"setting":"${setting}"}`; + + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: `DiscordNotification${identifier}`, + label: 'DISCORD', + style: discordActive ? SUCCESS : DANGER + }), + module.exports.getButton({ + customId: `InGameNotification${identifier}`, + label: 'IN-GAME', + style: inGameActive ? SUCCESS : DANGER + })); + }, + + getInGameCommandsEnabledButton: function (enabled) { + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: 'AllowInGameCommands', + label: enabled ? 'ENABLED' : 'DISABLED', + style: enabled ? SUCCESS : DANGER + })); + }, + + getInGameTeammateNotificationsButtons: function (guildId) { + const instance = Client.client.readInstanceFile(guildId); + + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: 'InGameTeammateConnection', + label: 'CONNECTIONS', + style: instance.generalSettings.connectionNotify ? SUCCESS : DANGER + }), + module.exports.getButton({ + customId: 'InGameTeammateAfk', + label: 'AFK', + style: instance.generalSettings.afkNotify ? SUCCESS : DANGER + }), + module.exports.getButton({ + customId: 'InGameTeammateDeath', + label: 'DEATH', + style: instance.generalSettings.deathNotify ? SUCCESS : DANGER + })); + }, + + getFcmAlarmNotificationButtons: function (enabled, everyone) { + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: 'FcmAlarmNotification', + label: enabled ? 'ENABLED' : 'DISABLED', + style: enabled ? SUCCESS : DANGER + }), + module.exports.getButton({ + customId: 'FcmAlarmNotificationEveryone', + label: '@everyone', + style: everyone ? SUCCESS : DANGER + })); + }, + + getSmartAlarmNotifyInGameButton: function (enabled) { + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: 'SmartAlarmNotifyInGame', + label: enabled ? 'ENABLED' : 'DISABLED', + style: enabled ? SUCCESS : DANGER + })); + }, + + getLeaderCommandEnabledButton: function (enabled) { + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: 'LeaderCommandEnabled', + label: enabled ? 'ENABLED' : 'DISABLED', + style: enabled ? SUCCESS : DANGER + })); + }, + + getTrackerButtons: function (guildId, trackerId) { + const instance = Client.client.readInstanceFile(guildId); + const tracker = instance.trackers[trackerId]; + const identifier = `{"trackerId":${trackerId}}`; + + return [ + new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: `TrackerActive${identifier}`, + label: tracker.active ? 'ACTIVE' : 'INACTIVE', + style: tracker.active ? SUCCESS : DANGER + }), + module.exports.getButton({ + customId: `TrackerEveryone${identifier}`, + label: '@everyone', + style: tracker.everyone ? SUCCESS : DANGER + }), + module.exports.getButton({ + customId: `TrackerEdit${identifier}`, + label: 'EDIT', + style: PRIMARY + }), + module.exports.getButton({ + customId: `TrackerDelete${identifier}`, + style: SECONDARY, + emoji: '🗑️' + })), + new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: `TrackerAddPlayer${identifier}`, + label: 'ADD PLAYER', + style: SUCCESS + }), + module.exports.getButton({ + customId: `TrackerRemovePlayer${identifier}`, + label: 'REMOVE PLAYER', + style: DANGER + })) + ]; + }, + + getTrackerNotifyButtons: function (allOffline, anyOnline) { + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + customId: 'TrackerNotifyAllOffline', + label: 'ALL OFFLINE', + style: allOffline ? SUCCESS : DANGER + }), + module.exports.getButton({ + customId: 'TrackerNotifyAnyOnline', + label: 'ANY ONLINE', + style: anyOnline ? SUCCESS : DANGER + })); + }, + + getNewsButton: function (body, validURL) { + return new Discord.ActionRowBuilder().addComponents( + module.exports.getButton({ + style: LINK, + label: 'LINK', + url: validURL ? body.url : Constants.DEFAULT_SERVER_URL + })); + }, +} \ No newline at end of file diff --git a/src/discordTools/discordEmbeds.js b/src/discordTools/discordEmbeds.js new file mode 100644 index 000000000..91ef402c5 --- /dev/null +++ b/src/discordTools/discordEmbeds.js @@ -0,0 +1,469 @@ +const Discord = require('discord.js'); + +const Client = require('../../index.ts'); +const Constants = require('../util/constants.js'); +const Timer = require('../util/timer'); +const DiscordTools = require('./discordTools.js'); + +module.exports = { + getEmbed: function (options = {}) { + const embed = new Discord.EmbedBuilder(); + + if (options.title) embed.setTitle(options.title); + if (options.color) embed.setColor(options.color); + if (options.description) embed.setDescription(options.description); + if (options.thumbnail) embed.setThumbnail(options.thumbnail); + if (options.image) embed.setImage(options.image); + if (options.url) embed.setURL(options.url); + if (options.author) embed.setAuthor(options.author); + if (options.footer) embed.setFooter(options.footer); + if (options.timestamp) embed.setTimestamp(); + if (options.fields) embed.setFields(...options.fields); + + return embed; + }, + + getSmartSwitchEmbed: function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].switches[entityId]; + + return module.exports.getEmbed({ + title: `${entity.name}`, + color: entity.active ? '#00ff40' : '#ff0040', + description: `**ID**: \`${entityId}\``, + thumbnail: `attachment://${entity.image}`, + footer: { text: `${entity.server}` }, + fields: [{ + name: 'Custom Command', + value: `\`${instance.generalSettings.prefix}${entity.command}\``, + inline: true + }] + }); + }, + + getServerEmbed: function (guildId, serverId) { + const instance = Client.client.readInstanceFile(guildId); + const server = instance.serverList[serverId]; + + return module.exports.getEmbed({ + title: `${server.title}`, + color: '#ce412b', + description: `${server.description}`, + thumbnail: `${server.img}`, + fields: [{ + name: 'Connect', + value: `\`${server.connect === null ? 'Unavailable' : server.connect}\``, + inline: true + }] + }); + }, + + getTrackerEmbed: function (guildId, trackerId) { + const instance = Client.client.readInstanceFile(guildId); + const tracker = instance.trackers[trackerId]; + const serverStatus = tracker.status ? Constants.ONLINE_EMOJI : Constants.OFFLINE_EMOJI; + + let playerName = '', playerSteamId = '', playerStatus = ''; + for (const player of tracker.players) { + playerName += `${player.name}\n`; + if (tracker.players.length < 12) { + playerSteamId += `[${player.steamId}](${Constants.STEAM_PROFILES_URL}${player.steamId})\n`; + } + else { + playerSteamId += `${player.steamId}\n`; + } + playerStatus += `${(player.status === true) ? + `${Constants.ONLINE_EMOJI} [${player.time}]` : `${Constants.OFFLINE_EMOJI}`}\n`; + } + + if (playerName === '') playerName = 'Empty'; + if (playerSteamId === '') playerSteamId = 'Empty'; + if (playerStatus === '') playerStatus = 'Empty'; + + return module.exports.getEmbed({ + title: `${tracker.name}`, + color: '#ce412b', + description: `**Battlemetrics ID:** \`${tracker.battlemetricsId}\`\n**Server Status:** ${serverStatus}`, + thumbnail: `${tracker.img}`, + fields: [ + { name: 'Name', value: playerName, inline: true }, + { name: 'SteamID', value: playerSteamId, inline: true }, + { name: 'Status', value: playerStatus, inline: true }] + }); + }, + + getSmartAlarmEmbed: function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].alarms[entityId]; + + return module.exports.getEmbed({ + title: `${entity.name}`, + color: entity.active ? '#00ff40' : '#ce412b', + description: `**ID**: \`${entityId}\``, + thumbnail: `attachment://${entity.image}`, + footer: { text: `${entity.server}` }, + fields: [{ + name: 'Message', + value: `\`${entity.message}\``, + inline: true + }] + }); + }, + + getStorageMonitorEmbed: function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].storageMonitors[entityId]; + const rustplus = Client.client.rustplusInstances[guildId]; + + let description = `**ID** \`${entityId}\``; + + if (!rustplus) { + return module.exports.getEmbed({ + title: `${entity.name}`, + color: '#ce412b', + description: `${description}\n**STATUS** \`NOT CONNECTED TO SERVER!\``, + thumbnail: `attachment://${entity.image}`, + footer: { text: `${entity.server}` } + }); + } + + if (rustplus && rustplus.storageMonitors[entityId].capacity === 0) { + return module.exports.getEmbed({ + title: `${entity.name}`, + color: '#ce412b', + description: `${description}\n**STATUS** \`NOT ELECTRICALLY CONNECTED!\``, + thumbnail: `attachment://${entity.image}`, + footer: { text: `${entity.server}` } + }); + } + + description += `\n**Type** \`${(entity.type === 'toolcupboard') ? 'Tool Cupboard' : 'Container'}\``; + + const items = rustplus.storageMonitors[entityId].items; + const expiry = rustplus.storageMonitors[entityId].expiry; + + if (entity.type === 'toolcupboard') { + let seconds = 0; + if (expiry !== 0) { + seconds = (new Date(expiry * 1000) - new Date()) / 1000; + } + + let upkeep = null; + if (seconds === 0) { + upkeep = ':warning:\`DECAYING\`:warning:'; + instance.serverList[serverId].storageMonitors[entityId].upkeep = 'DECAYING'; + } + else { + let upkeepTime = Timer.secondsToFullScale(seconds); + upkeep = `\`${upkeepTime}\``; + instance.serverList[serverId].storageMonitors[entityId].upkeep = `${upkeepTime}`; + } + description += `\n**Upkeep** ${upkeep}`; + Client.client.writeInstanceFile(guildId, instance); + } + + let itemName = '', itemQuantity = '', storageItems = new Object(); + for (const item of items) { + if (storageItems.hasOwnProperty(item.itemId)) { + storageItems[item.itemId] += item.quantity; + } + else { + storageItems[item.itemId] = item.quantity; + } + } + + for (const [id, quantity] of Object.entries(storageItems)) { + itemName += `\`${Client.client.items.getName(id)}\`\n`; + itemQuantity += `\`${quantity}\`\n`; + } + + if (itemName === '') itemName = 'Empty'; + if (itemQuantity === '') itemQuantity = 'Empty'; + + return module.exports.getEmbed({ + title: `${entity.name}`, + color: '#ce412b', + description: description, + thumbnail: `attachment://${entity.image}`, + footer: { text: `${entity.server}` }, + fields: [ + { name: 'Item', value: itemName, inline: true }, + { name: 'Quantity', value: itemQuantity, inline: true } + ] + }); + }, + + getSmartSwitchGroupEmbed: function (guildId, serverId, groupId) { + const instance = Client.client.readInstanceFile(guildId); + const group = instance.serverList[serverId].switchGroups[groupId]; + + let switchName = '', switchId = '', switchActive = ''; + for (const groupSwitchId of group.switches) { + if (instance.serverList[serverId].switches.hasOwnProperty(groupSwitchId)) { + const active = instance.serverList[serverId].switches[groupSwitchId].active; + switchName += `${instance.serverList[serverId].switches[groupSwitchId].name}\n`; + switchId += `${groupSwitchId}\n`; + if (instance.serverList[serverId].switches[groupSwitchId].reachable) { + switchActive += `${(active) ? Constants.ONLINE_EMOJI : Constants.OFFLINE_EMOJI}\n`; + } + else { + switchActive += `${Constants.NOT_FOUND_EMOJI}\n`; + } + } + else { + instance.serverList[serverId].switchGroups[groupId].switches = + instance.serverList[serverId].switchGroups[groupId].switches.filter(e => e !== groupSwitchId); + } + } + Client.client.writeInstanceFile(guildId, instance); + + if (switchName === '') switchName = 'None'; + if (switchId === '') switchId = 'None'; + if (switchActive === '') switchActive = 'None'; + + return module.exports.getEmbed({ + title: group.name, + color: '#ce412b', + thumbnail: 'attachment://smart_switch.png', + footer: { text: `${instance.serverList[serverId].title}` }, + fields: [ + { + name: 'Custom Command', + value: `\`${instance.generalSettings.prefix}${group.command}\``, + inline: false + }, + { name: 'Switches', value: switchName, inline: true }, + { name: 'ID', value: switchId, inline: true }, + { name: 'Active', value: switchActive, inline: true } + ] + }); + }, + + getNotFoundSmartDeviceEmbed: function (guildId, serverId, entityId, type) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId][type][entityId]; + + return module.exports.getEmbed({ + title: `${entity.name}`, + color: '#ff0040', + description: `**ID**: \`${entityId}\`\n**STATUS**: NOT FOUND ${Constants.NOT_FOUND_EMOJI}`, + thumbnail: `attachment://${entity.image}`, + footer: { text: `${entity.server}` } + }); + }, + + getStorageMonitorRecycleEmbed: function (guildId, serverId, entityId, items) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].storageMonitors[entityId]; + const rustplus = Client.client.rustplusInstances[guildId]; + + let itemName = '', itemQuantity = ''; + for (const item of items) { + itemName += `\`${rustplus.items.getName(item.itemId)}\`\n`; + itemQuantity += `\`${item.quantity}\`\n`; + } + + const embed = module.exports.getEmbed({ + title: 'Result of recycling:', + color: '#ce412b', + thumbnail: 'attachment://recycler.png', + footer: { text: `${entity.server} | This message will be deleted in 30 seconds.` }, + description: `**Name** \`${entity.name}\`\n**ID** \`${entityId}\`` + }); + + if (itemName === '') itemName = 'Empty'; + if (itemQuantity === '') itemQuantity = 'Empty'; + + embed.addFields( + { name: 'Item', value: itemName, inline: true }, + { name: 'Quantity', value: itemQuantity, inline: true } + ); + + return embed; + }, + + getDecayingNotificationEmbed: function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].storageMonitors[entityId]; + + return module.exports.getEmbed({ + title: `${entity.name} is decaying!`, + color: '#ff0040', + description: `**ID** \`${entityId}\``, + thumbnail: `attachment://${entity.image}`, + footer: { text: `${entity.server}` }, + timestamp: true + }); + }, + + getStorageMonitorDisconnectNotificationEmbed: function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].storageMonitors[entityId]; + + return module.exports.getEmbed({ + title: `${entity.name}` + + ` is no longer electrically connected!`, + color: '#ff0040', + description: `**ID** \`${entityId}\``, + thumbnail: `attachment://${entity.image}`, + footer: { text: `${entity.server}` }, + timestamp: true + }); + }, + + getStorageMonitorNotFoundEmbed: async function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].storageMonitors[entityId]; + const credentials = Client.client.readCredentialsFile(guildId); + const user = await DiscordTools.getUserById(guildId, credentials.credentials.owner); + + return module.exports.getEmbed({ + title: `${entity.name} could not be found! Either it have been destroyed or ` + + `${user.user.username} have lost tool cupboard access.`, + color: '#ff0040', + description: `**ID** \`${entityId}\``, + thumbnail: `attachment://${entity.image}`, + footer: { text: `${entity.server}` }, + timestamp: true + }); + }, + + getSmartSwitchNotFoundEmbed: async function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].switches[entityId]; + const credentials = Client.client.readCredentialsFile(guildId); + const user = await DiscordTools.getUserById(guildId, credentials.credentials.owner); + + return module.exports.getEmbed({ + title: `${entity.name} could not be found! Either it have been destroyed or ` + + `${user.user.username} have lost tool cupboard access.`, + color: '#ff0040', + description: `**ID** \`${entityId}\``, + thumbnail: `attachment://${entity.image}`, + footer: { text: `${entity.server}` }, + timestamp: true + }); + }, + + getSmartAlarmNotFoundEmbed: async function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].alarms[entityId]; + const credentials = Client.client.readCredentialsFile(guildId); + const user = await DiscordTools.getUserById(guildId, credentials.credentials.owner); + + return module.exports.getEmbed({ + title: `${entity.name} could not be found! Either it have been destroyed or ` + + `${user.user.username} have lost tool cupboard access.`, + color: '#ff0040', + description: `**ID** \`${entityId}\``, + thumbnail: `attachment://${entity.image}`, + footer: { text: `${entity.server}` }, + timestamp: true + }); + }, + + getTrackerAllOfflineEmbed: function (guildId, trackerId) { + const instance = Client.client.readInstanceFile(guildId); + const tracker = instance.trackers[trackerId]; + + return module.exports.getEmbed({ + title: `Everyone from the tracker \`${tracker.name}\` just went offline.`, + color: '#ff0040', + thumbnail: `${instance.serverList[tracker.serverId].img}`, + footer: { text: `${instance.serverList[tracker.serverId].title}` }, + timestamp: true + }); + }, + + getTrackerAnyOnlineEmbed: function (guildId, trackerId) { + const instance = Client.client.readInstanceFile(guildId); + const tracker = instance.trackers[trackerId]; + + return module.exports.getEmbed({ + title: `Someone from the tracker \`${tracker.name}\` just went online.`, + color: '#00ff40', + thumbnail: `${instance.serverList[tracker.serverId].img}`, + footer: { text: `${instance.serverList[tracker.serverId].title}` }, + timestamp: true + }); + }, + + getNewsEmbed: function (data) { + return module.exports.getEmbed({ + title: `NEWS: ${data.title}`, + color: '#ce412b', + description: `${data.message}`, + thumbnail: Constants.DEFAULT_SERVER_IMG, + timestamp: true + }); + }, + + getTeamLoginEmbed: function (body, png) { + return module.exports.getEmbed({ + color: '#00ff40', + timestamp: true, + footer: { text: body.name }, + author: { + name: `${body.targetName} just connected.`, + iconURL: (png !== null) ? png : Constants.DEFAULT_SERVER_IMG, + url: `${Constants.STEAM_PROFILES_URL}${body.targetId}` + } + }); + }, + + getPlayerDeathEmbed: function (data, body, png) { + return module.exports.getEmbed({ + color: '#ff0040', + thumbnail: png, + title: data.title, + timestamp: true, + footer: { text: body.name }, + url: body.targetId !== '' ? `${Constants.STEAM_PROFILES_URL}${body.targetId}` : '' + }); + }, + + getAlarmRaidAlarmEmbed: function (data, body) { + return module.exports.getEmbed({ + color: '#00ff40', + timestamp: true, + footer: { text: body.name }, + title: data.title, + description: data.message, + thumbnail: body.img + }); + }, + + getAlarmEmbed: function (data, body) { + return module.exports.getEmbed({ + color: '#ce412b', + thumbnail: 'attachment://smart_alarm.png', + title: data.title, + footer: { text: body.name }, + timestamp: true, + fields: [{ name: 'Message', value: `\`${data.message}\``, inline: true }] + }); + }, + + getEventEmbed: function (guildId, rustplus, text, image) { + const instance = Client.client.readInstanceFile(guildId); + + return module.exports.getEmbed({ + color: '#ce412b', + thumbnail: `attachment://${image}`, + title: text, + footer: { text: instance.serverList[rustplus.serverId].title }, + timestamp: true + }); + }, + + getActionInfoEmbed: function (color, str, footer = null, ephemeral = true) { + return { + embeds: [module.exports.getEmbed({ + color: color === 0 ? '#ce412b' : '#ff0040', + description: `\`\`\`diff\n${(color === 0) ? '+' : '-'} ${str}\n\`\`\``, + footer: footer !== null ? { text: footer } : null, + ephemeral: ephemeral + })] + }; + }, +} \ No newline at end of file diff --git a/src/discordTools/discordMessages.js b/src/discordTools/discordMessages.js new file mode 100644 index 000000000..6f1032e1d --- /dev/null +++ b/src/discordTools/discordMessages.js @@ -0,0 +1,261 @@ +const Discord = require('discord.js'); + +const Client = require('../../index.ts'); +const DiscordButtons = require('./discordButtons.js'); +const DiscordEmbeds = require('./discordEmbeds.js'); +const DiscordSelectMenus = require('./discordSelectMenus.js'); +const DiscordTools = require('./discordTools.js'); + +module.exports = { + sendMessage: async function (guildId, content, messageId, channelId, interaction = null) { + if (interaction) { + await Client.client.interactionUpdate(interaction, content); + return; + } + + let message = messageId !== null ? + await DiscordTools.getMessageById(guildId, channelId, messageId) : undefined; + + if (message !== undefined) { + return await Client.client.messageEdit(message, content); + } + else { + const channel = DiscordTools.getTextChannelById(guildId, channelId); + + if (!channel) { + Client.client.log('ERROR', `Could not get channel with id: ${channelId}.`, 'error'); + return; + } + + return await Client.client.messageSend(channel, content); + } + }, + + sendServerMessage: async function (guildId, serverId, state = null, interaction = null) { + const instance = Client.client.readInstanceFile(guildId); + const server = instance.serverList[serverId]; + + const content = { + embeds: [DiscordEmbeds.getServerEmbed(guildId, serverId)], + components: DiscordButtons.getServerButtons(guildId, serverId, state) + } + + const message = await module.exports.sendMessage(guildId, content, server.messageId, + instance.channelId.servers, interaction); + + if (!interaction) { + instance.serverList[serverId].messageId = message.id; + Client.client.writeInstanceFile(guildId, instance); + } + }, + + sendTrackerMessage: async function (guildId, trackerId, interaction = null) { + const instance = Client.client.readInstanceFile(guildId); + const tracker = instance.trackers[trackerId]; + + const content = { + embeds: [DiscordEmbeds.getTrackerEmbed(guildId, trackerId)], + components: DiscordButtons.getTrackerButtons(guildId, trackerId) + } + + const message = await module.exports.sendMessage(guildId, content, tracker.messageId, + instance.channelId.trackers, interaction); + + if (!interaction) { + instance.trackers[trackerId].messageId = message.id; + Client.client.writeInstanceFile(guildId, instance); + } + }, + + sendSmartSwitchMessage: async function (guildId, serverId, entityId, interaction = null) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].switches[entityId]; + + const content = { + embeds: [entity.reachable ? + DiscordEmbeds.getSmartSwitchEmbed(guildId, serverId, entityId) : + DiscordEmbeds.getNotFoundSmartDeviceEmbed(guildId, serverId, entityId, 'switches')], + components: [ + DiscordSelectMenus.getSmartSwitchSelectMenu(guildId, serverId, entityId), + DiscordButtons.getSmartSwitchButtons(guildId, serverId, entityId) + ], + files: [ + new Discord.AttachmentBuilder(`src/resources/images/electrics/${entity.image}`) + ] + } + + const message = await module.exports.sendMessage(guildId, content, entity.messageId, + instance.channelId.switches, interaction); + + if (!interaction) { + instance.serverList[serverId].switches[entityId].messageId = message.id; + Client.client.writeInstanceFile(guildId, instance); + } + }, + + sendSmartAlarmMessage: async function (guildId, serverId, entityId, interaction = null) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].alarms[entityId]; + + const content = { + embeds: [entity.reachable ? + DiscordEmbeds.getSmartAlarmEmbed(guildId, serverId, entityId) : + DiscordEmbeds.getNotFoundSmartDeviceEmbed(guildId, serverId, entityId, 'alarms')], + components: [DiscordButtons.getSmartAlarmButtons(guildId, serverId, entityId)], + files: [new Discord.AttachmentBuilder(`src/resources/images/electrics/${entity.image}`)] + } + + const message = await module.exports.sendMessage(guildId, content, entity.messageId, + instance.channelId.alarms, interaction); + + if (!interaction) { + instance.serverList[serverId].alarms[entityId].messageId = message.id; + Client.client.writeInstanceFile(guildId, instance); + } + }, + + sendStorageMonitorMessage: async function (guildId, serverId, entityId, interaction = null) { + let instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].storageMonitors[entityId]; + + const content = { + embeds: [entity.reachable ? + DiscordEmbeds.getStorageMonitorEmbed(guildId, serverId, entityId) : + DiscordEmbeds.getNotFoundSmartDeviceEmbed(guildId, serverId, entityId, 'storageMonitors')], + components: [entity.type === 'toolcupboard' ? + DiscordButtons.getStorageMonitorToolCupboardButtons(guildId, serverId, entityId) : + DiscordButtons.getStorageMonitorContainerButton(serverId, entityId)], + files: [ + new Discord.AttachmentBuilder(`src/resources/images/electrics/${entity.image}`)] + } + + instance = Client.client.readInstanceFile(guildId); + + const message = await module.exports.sendMessage(guildId, content, entity.messageId, + instance.channelId.storageMonitors, interaction); + + if (!interaction) { + instance.serverList[serverId].storageMonitors[entityId].messageId = message.id; + Client.client.writeInstanceFile(guildId, instance); + } + }, + + sendSmartSwitchGroupMessage: async function (guildId, serverId, groupId, interaction = null) { + const instance = Client.client.readInstanceFile(guildId); + const group = instance.serverList[serverId].switchGroups[groupId]; + + const content = { + embeds: [DiscordEmbeds.getSmartSwitchGroupEmbed(guildId, serverId, groupId)], + components: DiscordButtons.getSmartSwitchGroupButtons(serverId, groupId), + files: [new Discord.AttachmentBuilder('src/resources/images/electrics/smart_switch.png')] + } + + const message = await module.exports.sendMessage(guildId, content, group.messageId, + instance.channelId.switches, interaction); + + if (!interaction) { + instance.serverList[serverId].switchGroups[groupId].messageId = message.id; + Client.client.writeInstanceFile(guildId, instance); + } + }, + + sendStorageMonitorRecycleMessage: async function (guildId, serverId, entityId, items) { + const instance = Client.client.readInstanceFile(guildId); + + const content = { + embeds: [DiscordEmbeds.getStorageMonitorRecycleEmbed(guildId, serverId, entityId, items)], + components: [DiscordButtons.getRecycleDeleteButton()], + files: [new Discord.AttachmentBuilder('src/resources/images/electrics/recycler.png')] + } + + return await module.exports.sendMessage(guildId, content, null, instance.channelId.storageMonitors); + }, + + sendDecayingNotificationMessage: async function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].storageMonitors[entityId]; + + const content = { + embeds: [DiscordEmbeds.getDecayingNotificationEmbed(guildId, serverId, entityId)], + files: [new Discord.AttachmentBuilder(`src/resources/images/electrics/${entity.image}`)], + content: entity.everyone ? '@everyone' : '' + } + + await module.exports.sendMessage(guildId, content, null, instance.channelId.activity); + }, + + sendStorageMonitorDisconnectNotificationMessage: async function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].storageMonitors[entityId]; + + const content = { + embeds: [DiscordEmbeds.getStorageMonitorDisconnectNotificationEmbed(guildId, serverId, entityId)], + files: [new Discord.AttachmentBuilder(`src/resources/images/electrics/${entity.image}`)], + content: entity.everyone ? '@everyone' : '' + } + + await module.exports.sendMessage(guildId, content, null, instance.channelId.activity); + }, + + sendStorageMonitorNotFoundMessage: async function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].storageMonitors[entityId]; + + const content = { + embeds: [await DiscordEmbeds.getStorageMonitorNotFoundEmbed(guildId, serverId, entityId)], + files: [new Discord.AttachmentBuilder(`src/resources/images/electrics/${entity.image}`)], + content: entity.everyone ? '@everyone' : '' + } + + await module.exports.sendMessage(guildId, content, null, instance.channelId.activity); + }, + + sendSmartSwitchNotFoundMessage: async function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].switches[entityId]; + + const content = { + embeds: [await DiscordEmbeds.getSmartSwitchNotFoundEmbed(guildId, serverId, entityId)], + files: [new Discord.AttachmentBuilder(`src/resources/images/electrics/${entity.image}`)] + } + + await module.exports.sendMessage(guildId, content, null, instance.channelId.activity); + }, + + sendSmartAlarmNotFoundMessage: async function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].alarms[entityId]; + + const content = { + embeds: [await DiscordEmbeds.getSmartAlarmNotFoundEmbed(guildId, serverId, entityId)], + files: [new Discord.AttachmentBuilder(`src/resources/images/electrics/${entity.image}`)], + content: entity.everyone ? '@everyone' : '' + } + + await module.exports.sendMessage(guildId, content, null, instance.channelId.activity); + }, + + sendTrackerAllOfflineMessage: async function (guildId, trackerId) { + const instance = Client.client.readInstanceFile(guildId); + const tracker = instance.trackers[trackerId]; + + const content = { + embeds: [DiscordEmbeds.getTrackerAllOfflineEmbed(guildId, trackerId)], + content: tracker.everyone ? '@everyone' : '' + } + + await module.exports.sendMessage(guildId, content, null, instance.channelId.activity); + }, + + sendTrackerAnyOnlineMessage: async function (guildId, trackerId) { + const instance = Client.client.readInstanceFile(guildId); + const tracker = instance.trackers[trackerId]; + + const content = { + embeds: [DiscordEmbeds.getTrackerAnyOnlineEmbed(guildId, trackerId)], + content: tracker.everyone ? '@everyone' : '' + } + + await module.exports.sendMessage(guildId, content, null, instance.channelId.activity); + }, +} \ No newline at end of file diff --git a/src/discordTools/discordModals.js b/src/discordTools/discordModals.js new file mode 100644 index 000000000..5f3640e9b --- /dev/null +++ b/src/discordTools/discordModals.js @@ -0,0 +1,279 @@ +const Discord = require('discord.js'); + +const Client = require('../../index.ts'); +const TextInput = require('./discordTextInputs.js'); + +module.exports = { + getModal: function (options = {}) { + const modal = new Discord.ModalBuilder(); + + if (options.customId) modal.setCustomId(options.customId); + if (options.title) modal.setTitle(options.title); + + return modal; + }, + + getCustomTimersEditModal(guildId, serverId) { + const instance = Client.client.readInstanceFile(guildId); + const server = instance.serverList[serverId]; + const identifier = `{"serverId":"${serverId}"}`; + + const modal = module.exports.getModal({ + customId: `CustomTimersEdit${identifier}`, + title: 'Editing of Custom Timers' + }); + + modal.addComponents( + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'CargoShipEgressTime', + label: 'Cargoship egress time (seconds):', + value: `${server.cargoShipEgressTimeMs / 1000}`, + style: Discord.TextInputStyle.Short + })), + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'BradleyApcRespawnTime', + label: 'Bradley APC respawn time (seconds):', + value: `${server.bradleyApcRespawnTimeMs / 1000}`, + style: Discord.TextInputStyle.Short + })), + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'CrateDespawnTime', + label: 'Locked Crate despawn time (seconds):', + value: `${server.lockedCrateDespawnTimeMs / 1000}`, + style: Discord.TextInputStyle.Short + })), + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'CrateDespawnWarningTime', + label: 'Locked Crate despawn warning time (seconds):', + value: `${server.lockedCrateDespawnWarningTimeMs / 1000}`, + style: Discord.TextInputStyle.Short + })), + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'OilRigCrateUnlockTime', + label: 'OilRig Locked Crate unlock time (seconds):', + value: `${server.oilRigLockedCrateUnlockTimeMs / 1000}`, + style: Discord.TextInputStyle.Short + })) + ); + + return modal; + + }, + + getSmartSwitchEditModal(guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].switches[entityId]; + const identifier = `{"serverId":"${serverId}","entityId":${entityId}}`; + + const modal = module.exports.getModal({ + customId: `SmartSwitchEdit${identifier}`, + title: `Editing of ${entity.name}` + }); + + modal.addComponents( + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'SmartSwitchName', + label: 'The name of the Smart Switch:', + value: entity.name, + style: Discord.TextInputStyle.Short + })), + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'SmartSwitchCommand', + label: 'The custom command for the Smart Switch:', + value: entity.command, + style: Discord.TextInputStyle.Short + })) + ); + + return modal; + }, + + getGroupEditModal(guildId, serverId, groupId) { + const instance = Client.client.readInstanceFile(guildId); + const group = instance.serverList[serverId].switchGroups[groupId]; + const identifier = `{"serverId":"${serverId}","groupId":${groupId}}`; + + const modal = module.exports.getModal({ + customId: `GroupEdit${identifier}`, + title: `Editing of ${group.name}` + }); + + modal.addComponents( + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'GroupName', + label: 'The name of the Group:', + value: group.name, + style: Discord.TextInputStyle.Short + })), + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'GroupCommand', + label: 'The custom command for the Group:', + value: group.command, + style: Discord.TextInputStyle.Short + })) + ); + + return modal; + }, + + getGroupAddSwitchModal(guildId, serverId, groupId) { + const instance = Client.client.readInstanceFile(guildId); + const group = instance.serverList[serverId].switchGroups[groupId]; + const identifier = `{"serverId":"${serverId}","groupId":${groupId}}`; + + const modal = module.exports.getModal({ + customId: `GroupAddSwitch${identifier}`, + title: `Add Switch to ${group.name}` + }); + + modal.addComponents( + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'GroupAddSwitchId', + label: 'The Entity ID of the switch to add:', + value: '', + style: Discord.TextInputStyle.Short + })) + ); + + return modal; + }, + + getGroupRemoveSwitchModal(guildId, serverId, groupId) { + const instance = Client.client.readInstanceFile(guildId); + const group = instance.serverList[serverId].switchGroups[groupId]; + const identifier = `{"serverId":"${serverId}","groupId":${groupId}}`; + + const modal = module.exports.getModal({ + customId: `GroupRemoveSwitch${identifier}`, + title: `Add Switch to ${group.name}` + }); + + modal.addComponents( + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'GroupRemoveSwitchId', + label: 'The Entity ID of the switch to remove:', + value: '', + style: Discord.TextInputStyle.Short + })) + ); + + return modal; + }, + + getSmartAlarmEditModal(guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].alarms[entityId]; + const identifier = `{"serverId":"${serverId}","entityId":${entityId}}`; + + const modal = module.exports.getModal({ + customId: `SmartAlarmEdit${identifier}`, + title: `Editing of ${entity.name}` + }); + + modal.addComponents( + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'SmartAlarmName', + label: 'The name of the Smart Alarm:', + value: entity.name, + style: Discord.TextInputStyle.Short + })), + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'SmartAlarmMessage', + label: 'The message for the Smart Alarm:', + value: entity.message, + style: Discord.TextInputStyle.Short + })) + ); + + return modal; + }, + + getStorageMonitorEditModal(guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].storageMonitors[entityId]; + const identifier = `{"serverId":"${serverId}","entityId":${entityId}}`; + + const modal = module.exports.getModal({ + customId: `StorageMonitorEdit${identifier}`, + title: `Editing of ${entity.name}` + }); + + modal.addComponents( + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'StorageMonitorName', + label: 'The name of the Storage Monitor:', + value: entity.name, + style: Discord.TextInputStyle.Short + })) + ); + + return modal; + }, + + getTrackerEditModal(guildId, trackerId) { + const instance = Client.client.readInstanceFile(guildId); + const tracker = instance.trackers[trackerId]; + const identifier = `{"trackerId":${trackerId}}`; + + const modal = module.exports.getModal({ + customId: `TrackerEdit${identifier}`, + title: `Editing of ${tracker.name}` + }); + + modal.addComponents( + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'TrackerName', + label: 'The name of the Tracker:', + value: tracker.name, + style: Discord.TextInputStyle.Short + })) + ); + + return modal; + }, + + getTrackerAddPlayerModal(guildId, trackerId) { + const instance = Client.client.readInstanceFile(guildId); + const tracker = instance.trackers[trackerId]; + const identifier = `{"trackerId":${trackerId}}`; + + const modal = module.exports.getModal({ + customId: `TrackerAddPlayer${identifier}`, + title: `Add Player to ${tracker.name}` + }); + + + modal.addComponents( + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'TrackerAddPlayerSteamId', + label: 'The SteamID of the player to add:', + value: '', + style: Discord.TextInputStyle.Short + })) + ); + + return modal; + }, + + getTrackerRemovePlayerModal(guildId, trackerId) { + const instance = Client.client.readInstanceFile(guildId); + const tracker = instance.trackers[trackerId]; + const identifier = `{"trackerId":${trackerId}}`; + + const modal = module.exports.getModal({ + customId: `TrackerRemovePlayer${identifier}`, + title: `Remove Player from ${tracker.name}` + }); + + modal.addComponents( + new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({ + customId: 'TrackerRemovePlayerSteamId', + label: 'The SteamID of the player to remove:', + value: '', + style: Discord.TextInputStyle.Short + })) + ); + + return modal; + }, +} \ No newline at end of file diff --git a/src/discordTools/discordSelectMenus.js b/src/discordTools/discordSelectMenus.js new file mode 100644 index 000000000..8ea7e2ceb --- /dev/null +++ b/src/discordTools/discordSelectMenus.js @@ -0,0 +1,103 @@ +const Discord = require('discord.js'); + +const Client = require('../../index.ts'); + +module.exports = { + getSelectMenu: function (options = {}) { + const selectMenu = new Discord.SelectMenuBuilder(); + + if (options.customId) selectMenu.setCustomId(options.customId); + if (options.placeholder) selectMenu.setPlaceholder(options.placeholder); + if (options.options) selectMenu.setOptions(options.options); + if (options.disabled) selectMenu.setDisabled(options.disabled); + + return selectMenu; + }, + + getPrefixSelectMenu: function (prefix) { + return new Discord.ActionRowBuilder().addComponents( + module.exports.getSelectMenu({ + customId: 'Prefix', + placeholder: `Current Prefix: ${prefix}`, + options: [ + { label: '!', description: 'Exlamation Mark', value: '!' }, + { label: '/', description: 'Slash', value: '/' }, + { label: '.', description: 'Dot', value: '.' }] + })); + }, + + getTrademarkSelectMenu: function (trademark) { + return new Discord.ActionRowBuilder().addComponents( + module.exports.getSelectMenu({ + customId: 'Trademark', + placeholder: `${trademark}`, + options: [ + { + label: 'rustPlusPlus', + description: `rustPlusPlus will be shown before messages.`, + value: 'rustPlusPlus' + }, + { + label: 'Rust++', + description: `Rust++ will be shown before messages.`, + value: 'Rust++' + }, + { + label: 'NOT SHOWING', + description: 'Hide trademark.', + value: 'NOT SHOWING' + }] + })); + }, + + getCommandDelaySelectMenu: function (delay) { + return new Discord.ActionRowBuilder().addComponents( + module.exports.getSelectMenu({ + customId: 'CommandDelay', + placeholder: `Current Command Delay: ${delay} seconds.`, + options: [ + { label: 'NO DELAY', description: 'No command delay.', value: '0' }, + { label: '1 second', description: 'One second command delay.', value: '1' }, + { label: '2 seconds', description: 'Two seconds command delay.', value: '2' }, + { label: '3 seconds', description: 'Three seconds command delay.', value: '3' }, + { label: '4 seconds', description: 'Four seconds command delay.', value: '4' }, + { label: '5 seconds', description: 'Five seconds command delay.', value: '5' }, + { label: '6 seconds', description: 'Six seconds command delay.', value: '6' }, + { label: '7 seconds', description: 'Seven seconds command delay.', value: '7' }, + { label: '8 seconds', description: 'Eight seconds command delay.', value: '8' }] + })); + }, + + getSmartSwitchSelectMenu: function (guildId, serverId, entityId) { + const instance = Client.client.readInstanceFile(guildId); + const entity = instance.serverList[serverId].switches[entityId]; + const identifier = `{"serverId":"${serverId}","entityId":${entityId}}`; + + let autoDayNightString = 'AUTO SETTING: '; + if (entity.autoDayNight === 0) autoDayNightString += 'OFF'; + else if (entity.autoDayNight === 1) autoDayNightString += 'AUTO-DAY'; + else if (entity.autoDayNight === 2) autoDayNightString += 'AUTO-NIGHT'; + + return new Discord.ActionRowBuilder().addComponents( + module.exports.getSelectMenu({ + customId: `AutoDayNight${identifier}`, + placeholder: `${autoDayNightString}`, + options: [ + { + label: 'OFF', + description: 'Smart Switch work as normal.', + value: '0' + }, + { + label: 'AUTO-DAY', + description: `Smart Switch Will be active only during the day.`, + value: '1' + }, + { + label: 'AUTO-NIGHT', + description: `Smart Switch Will be active only during the night.`, + value: '2' + }] + })); + }, +} \ No newline at end of file diff --git a/src/discordTools/discordTextInputs.js b/src/discordTools/discordTextInputs.js new file mode 100644 index 000000000..8ee8b9340 --- /dev/null +++ b/src/discordTools/discordTextInputs.js @@ -0,0 +1,16 @@ +const Discord = require('discord.js'); + +module.exports = { + getTextInput: function (options = {}) { + const textInput = new Discord.TextInputBuilder(); + + if (options.customId) textInput.setCustomId(options.customId); + if (options.label) textInput.setLabel(options.label); + if (options.value) textInput.setValue(options.value); + if (options.style) textInput.setStyle(options.style); + if (options.placeholder) textInput.setPlaceholder(options.placeholder); + if (options.required) textInput.setRequired(options.required); + + return textInput; + }, +} \ No newline at end of file diff --git a/src/discordTools/discordTools.js b/src/discordTools/discordTools.js index 7f7d0de6c..f2112d9e7 100644 --- a/src/discordTools/discordTools.js +++ b/src/discordTools/discordTools.js @@ -1,7 +1,6 @@ -const { ActionRowBuilder, ButtonBuilder, SelectMenuBuilder, EmbedBuilder, ChannelType, PermissionFlagsBits, AttachmentBuilder, ButtonStyle, Embed } = require('discord.js'); -const Client = require('../../index.js'); -const Timer = require('../util/timer'); -const Constants = require('../util/constants.js'); +const Discord = require('discord.js'); + +const Client = require('../../index.ts'); module.exports = { getGuild: function (guildId) { @@ -28,6 +27,22 @@ module.exports = { return undefined; }, + getUserById: async function (guildId, userId) { + let guild = module.exports.getGuild(guildId); + + if (guild) { + try { + const user = await guild.members.fetch(userId); + if (user instanceof Map) return await user.get(userId); + return user; + } + catch (e) { + Client.client.log('ERROR', `Could not find user: ${userId}`, 'error'); + } + } + return undefined; + }, + getTextChannelById: function (guildId, channelId) { const guild = module.exports.getGuild(guildId); @@ -40,7 +55,7 @@ module.exports = { Client.client.log('ERROR', `Could not find channel: ${channelId}`, 'error'); } - if (channel && channel.type === ChannelType.GuildText) { + if (channel && channel.type === Discord.ChannelType.GuildText) { return channel; } } @@ -59,7 +74,7 @@ module.exports = { Client.client.log('ERROR', `Could not find channel: ${name}`, 'error'); } - if (channel && channel.type === ChannelType.GuildText) { + if (channel && channel.type === Discord.ChannelType.GuildText) { return channel; } } @@ -78,7 +93,7 @@ module.exports = { Client.client.log('ERROR', `Could not find category: ${categoryId}`, 'error'); } - if (category && category.type === ChannelType.GuildCategory) { + if (category && category.type === Discord.ChannelType.GuildCategory) { return category; } } @@ -97,7 +112,7 @@ module.exports = { Client.client.log('ERROR', `Could not find category: ${name}`, 'error'); } - if (category && category.type === ChannelType.GuildCategory) { + if (category && category.type === Discord.ChannelType.GuildCategory) { return category; } } @@ -112,7 +127,9 @@ module.exports = { if (channel) { try { - return await channel.messages.fetch(messageId); + const message = await channel.messages.fetch(messageId); + if (message instanceof Map) return await message.get(messageId); + return message; } catch (e) { Client.client.log('ERROR', `Could not find message: ${messageId}`, 'error'); @@ -122,21 +139,15 @@ module.exports = { return undefined; }, - getMemberById: async function (guildId, memberId) { - const guild = module.exports.getGuild(guildId); + deleteMessageById: async function (guildId, channelId, messageId) { + const message = await module.exports.getMessageById(guildId, channelId, messageId); - if (guild) { - let member = undefined; - try { - member = await Client.client.users.fetch(memberId); - } - catch (e) { - Client.client.log('ERROR', `Could not find member: ${memberId}`, 'error'); - } + try { + await message.delete(); + } + catch (e) { + Client.client.log('ERROR', `Could not delete message: ${messageId}`, 'error'); - if (member) { - return member; - } } return undefined; }, @@ -148,10 +159,10 @@ module.exports = { try { return await guild.channels.create({ name: name, - type: ChannelType.GuildCategory, + type: Discord.ChannelType.GuildCategory, permissionOverwrites: [{ id: guild.roles.everyone.id, - deny: [PermissionFlagsBits.SendMessages] + deny: [Discord.PermissionFlagsBits.SendMessages] }] }); } @@ -169,10 +180,10 @@ module.exports = { try { return await guild.channels.create({ name: name, - type: ChannelType.GuildText, + type: Discord.ChannelType.GuildText, permissionOverwrites: [{ id: guild.roles.everyone.id, - deny: [PermissionFlagsBits.SendMessages] + deny: [Discord.PermissionFlagsBits.SendMessages] }], }); } @@ -229,1069 +240,4 @@ module.exports = { } } }, - - getNotificationButtons: function (setting, discordActive, inGameActive) { - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId(`${setting}DiscordNotification`) - .setLabel('DISCORD') - .setStyle((discordActive) ? ButtonStyle.Success : ButtonStyle.Danger), - new ButtonBuilder() - .setCustomId(`${setting}InGameNotification`) - .setLabel('IN-GAME') - .setStyle((inGameActive) ? ButtonStyle.Success : ButtonStyle.Danger)) - }, - - getInGameCommandsEnabledButton: function (enabled) { - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId('allowInGameCommands') - .setLabel((enabled) ? 'ENABLED' : 'DISABLED') - .setStyle((enabled) ? ButtonStyle.Success : ButtonStyle.Danger)) - }, - - getInGameTeammateNotificationsButtons: function (instance) { - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId('inGameTeammateConnection') - .setLabel('CONNECTIONS') - .setStyle((instance.generalSettings.connectionNotify) ? ButtonStyle.Success : ButtonStyle.Danger), - new ButtonBuilder() - .setCustomId('inGameTeammateAfk') - .setLabel('AFK') - .setStyle((instance.generalSettings.afkNotify) ? ButtonStyle.Success : ButtonStyle.Danger), - new ButtonBuilder() - .setCustomId('inGameTeammateDeath') - .setLabel('DEATH') - .setStyle((instance.generalSettings.deathNotify) ? ButtonStyle.Success : ButtonStyle.Danger)) - }, - - getFcmAlarmNotificationButtons: function (enabled, everyone) { - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId('fcmAlarmNotification') - .setLabel((enabled) ? 'ENABLED' : 'DISABLED') - .setStyle((enabled) ? ButtonStyle.Success : ButtonStyle.Danger), - new ButtonBuilder() - .setCustomId('fcmAlarmNotificationEveryone') - .setLabel('@everyone') - .setStyle((everyone) ? ButtonStyle.Success : ButtonStyle.Danger)); - }, - - getSmartAlarmNotifyInGameButton: function (enabled) { - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId('smartAlarmNotifyInGame') - .setLabel((enabled) ? 'ENABLED' : 'DISABLED') - .setStyle((enabled) ? ButtonStyle.Success : ButtonStyle.Danger)) - }, - - getLeaderCommandEnabledButton: function (enabled) { - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId('leaderCommandEnabled') - .setLabel((enabled) ? 'ENABLED' : 'DISABLED') - .setStyle((enabled) ? ButtonStyle.Success : ButtonStyle.Danger)) - }, - - getTrackerNotifyButtons: function (allOffline, anyOnline) { - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId('trackerNotifyAllOffline') - .setLabel('ALL OFFLINE') - .setStyle((allOffline) ? ButtonStyle.Success : ButtonStyle.Danger), - new ButtonBuilder() - .setCustomId('trackerNotifyAnyOnline') - .setLabel('ANY ONLINE') - .setStyle((anyOnline) ? ButtonStyle.Success : ButtonStyle.Danger)); - }, - - getPrefixSelectMenu: function (currentPrefix) { - return new ActionRowBuilder() - .addComponents( - new SelectMenuBuilder() - .setCustomId('prefix') - .setPlaceholder(`Current Prefix: ${currentPrefix}`) - .addOptions([ - { - label: '!', - description: 'Exclamation Mark', - value: '!', - }, - { - label: '/', - description: 'Slash', - value: '/', - }, - { - label: '.', - description: 'Dot', - value: '.', - }, - ]) - ); - }, - - getTrademarkSelectMenu: function (currentTrademark) { - return new ActionRowBuilder() - .addComponents( - new SelectMenuBuilder() - .setCustomId('trademark') - .setPlaceholder(`${currentTrademark}`) - .addOptions([ - { - label: 'rustPlusPlus', - description: 'rustPlusPlus will be shown before messages.', - value: 'rustPlusPlus', - }, - { - label: 'Rust++', - description: 'Rust++ will be shown before messages.', - value: 'Rust++', - }, - { - label: 'NOT SHOWING', - description: 'Not showing any trademark before messages.', - value: 'NOT SHOWING', - }, - ]) - ); - }, - - getCommandDelaySelectMenu: function (currentDelay) { - return new ActionRowBuilder() - .addComponents( - new SelectMenuBuilder() - .setCustomId('commandDelay') - .setPlaceholder(`Current Command Delay: ${currentDelay} seconds`) - .addOptions([ - { - label: 'NO DELAY', - description: 'No command delay.', - value: '0', - }, - { - label: '1 second', - description: 'One second command delay.', - value: '1', - }, - { - label: '2 seconds', - description: 'Two seconds command delay.', - value: '2', - }, - { - label: '3 seconds', - description: 'Three seconds command delay.', - value: '3', - }, - { - label: '4 seconds', - description: 'Four seconds command delay.', - value: '4', - }, - { - label: '5 seconds', - description: 'Five seconds command delay.', - value: '5', - }, - { - label: '6 seconds', - description: 'Six seconds command delay.', - value: '6', - }, - { - label: '7 seconds', - description: 'Seven seconds command delay.', - value: '7', - }, - { - label: '8 seconds', - description: 'Eight seconds command delay.', - value: '8', - } - ]) - ); - }, - - getServerEmbed: function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - - let embed = new EmbedBuilder() - .setTitle(`${instance.serverList[id].title}`) - .setColor('#ce412b') - .setDescription(`${instance.serverList[id].description}`) - .setThumbnail(`${instance.serverList[id].img}`); - - if (instance.serverList[id].connect !== null) { - embed.addFields({ - name: 'Connect', - value: `\`${instance.serverList[id].connect}\``, - inline: true - }); - } - - return embed; - }, - - getServerButtons: function (guildId, id, state = null) { - const instance = Client.client.readInstanceFile(guildId); - - if (state === null) { - state = (instance.serverList[id].active) ? 1 : 0; - } - - let customId = null; - let label = null; - let style = null; - - switch (state) { - case 0: { /* CONNECT */ - customId = `${id}ServerConnect`; - label = 'CONNECT'; - style = ButtonStyle.Primary; - } break; - - case 1: { /* DISCONNECT */ - customId = `${id}ServerDisconnect`; - label = 'DISCONNECT'; - style = ButtonStyle.Danger; - } break; - - case 2: { /* RECONNECTING */ - customId = `${id}ServerReconnecting`; - label = 'RECONNECTING...'; - style = ButtonStyle.Danger; - } break; - - default: { - } break; - } - - let trackerAvailable = (instance.serverList[id].battlemetricsId !== null) ? true : false; - - let connectionButton = new ButtonBuilder() - .setCustomId(customId) - .setLabel(label) - .setStyle(style); - let trackerButton = new ButtonBuilder() - .setCustomId(`${id}CreateTracker`) - .setLabel('CREATE TRACKER') - .setStyle(ButtonStyle.Primary); - let linkButton = new ButtonBuilder() - .setStyle(ButtonStyle.Link) - .setLabel('WEBSITE') - .setURL(instance.serverList[id].url); - let deleteButton = new ButtonBuilder() - .setCustomId(`${id}ServerDelete`) - .setEmoji('🗑️') - .setStyle(ButtonStyle.Secondary); - - if (trackerAvailable) { - return new ActionRowBuilder() - .addComponents( - connectionButton, - trackerButton, - linkButton, - deleteButton); - } - else { - return new ActionRowBuilder() - .addComponents( - connectionButton, - linkButton, - deleteButton); - } - }, - - sendServerMessage: async function (guildId, id, state = null, e = true, c = true, interaction = null) { - const instance = Client.client.readInstanceFile(guildId); - - const embed = module.exports.getServerEmbed(guildId, id); - const buttons = module.exports.getServerButtons(guildId, id, state); - - let content = new Object(); - if (e) { - content.embeds = [embed]; - } - if (c) { - content.components = [buttons]; - } - - if (interaction) { - await Client.client.interactionUpdate(interaction, content); - return; - } - - let messageId = instance.serverList[id].messageId; - let message = undefined; - if (messageId !== null) { - message = await module.exports.getMessageById(guildId, instance.channelId.servers, messageId); - } - - if (message !== undefined) { - if (await Client.client.messageEdit(message, content) === undefined) return; - } - else { - const channel = module.exports.getTextChannelById(guildId, instance.channelId.servers); - - if (!channel) { - Client.client.log('ERROR', 'sendServerMessage: Invalid guild or channel.', 'error'); - return; - } - - message = await Client.client.messageSend(channel, content); - instance.serverList[id].messageId = message.id; - Client.client.writeInstanceFile(guildId, instance); - } - }, - - getTrackerEmbed: function (guildId, trackerName) { - const instance = Client.client.readInstanceFile(guildId); - const battlemetricsId = instance.trackers[trackerName].battlemetricsId; - const serverStatus = (instance.trackers[trackerName].status) ? - Constants.ONLINE_EMOJI : Constants.OFFLINE_EMOJI; - - let playerName = ''; - let playerSteamId = ''; - let playerStatus = ''; - for (let player of instance.trackers[trackerName].players) { - playerName += `${player.name}\n`; - if (instance.trackers[trackerName].players.length < 12) { - playerSteamId += `[${player.steamId}](${Constants.STEAM_PROFILES_URL}${player.steamId})\n`; - } - else { - playerSteamId += `${player.steamId}\n`; - } - playerStatus += `${(player.status === true) ? - `${Constants.ONLINE_EMOJI} [${player.time}]` : `${Constants.OFFLINE_EMOJI}`}\n`; - } - - if (playerName === '' || playerSteamId === '' || playerStatus === '') { - playerName = 'Empty'; - playerSteamId = 'Empty'; - playerStatus = 'Empty'; - } - - let embed = new EmbedBuilder() - .setTitle(`${trackerName}`) - .setColor('#ce412b') - .setDescription(`**Battlemetrics ID:** \`${battlemetricsId}\`\n**Server Status:** ${serverStatus}`) - .setThumbnail(`${instance.trackers[trackerName].img}`) - .addFields( - { name: 'Name', value: playerName, inline: true }, - { name: 'SteamID', value: playerSteamId, inline: true }, - { name: 'Status', value: playerStatus, inline: true } - ) - .setFooter({ text: `${instance.trackers[trackerName].title}` }) - - return embed; - }, - - getTrackerButtons: function (guildId, trackerName) { - const instance = Client.client.readInstanceFile(guildId); - - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId(`${trackerName}TrackerActive`) - .setLabel((instance.trackers[trackerName].active) ? 'ACTIVE' : 'INACTIVE') - .setStyle((instance.trackers[trackerName].active) ? ButtonStyle.Success : ButtonStyle.Danger), - new ButtonBuilder() - .setCustomId(`${trackerName}TrackerEveryone`) - .setLabel('@everyone') - .setStyle((instance.trackers[trackerName].everyone) ? ButtonStyle.Success : ButtonStyle.Danger), - new ButtonBuilder() - .setCustomId(`${trackerName}TrackerDelete`) - .setEmoji('🗑️') - .setStyle(ButtonStyle.Secondary)) - }, - - sendTrackerMessage: async function (guildId, trackerName, e = true, c = true, interaction = null) { - const instance = Client.client.readInstanceFile(guildId); - - const embed = module.exports.getTrackerEmbed(guildId, trackerName); - const buttons = module.exports.getTrackerButtons(guildId, trackerName); - - let content = new Object(); - if (e) { - content.embeds = [embed]; - } - if (c) { - content.components = [buttons]; - } - - if (interaction) { - await Client.client.interactionUpdate(interaction, content); - return; - } - - let messageId = instance.trackers[trackerName].messageId; - let message = undefined; - if (messageId !== null) { - message = await module.exports.getMessageById(guildId, instance.channelId.trackers, messageId); - } - - if (message !== undefined) { - if (await Client.client.messageEdit(message, content) === undefined) return; - } - else { - const channel = module.exports.getTextChannelById(guildId, instance.channelId.trackers); - - if (!channel) { - Client.client.log('ERROR', 'sendTrackerMessage: Invalid guild or channel.', 'error'); - return; - } - - message = await Client.client.messageSend(channel, content); - instance.trackers[trackerName].messageId = message.id; - Client.client.writeInstanceFile(guildId, instance); - } - }, - - getSmartSwitchEmbed: function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - - return new EmbedBuilder() - .setTitle(`${instance.switches[id].name}`) - .setColor((instance.switches[id].active) ? '#00ff40' : '#ff0040') - .setDescription(`**ID**: \`${id}\``) - .setThumbnail(`attachment://${instance.switches[id].image}`) - .addFields( - { - name: 'Custom Command', - value: `\`${instance.generalSettings.prefix}${instance.switches[id].command}\``, - inline: true - } - ) - .setFooter({ text: `${instance.switches[id].server}` }) - }, - - getSmartSwitchSelectMenu: function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - - let autoDayNightString = 'AUTO SETTING: '; - switch (instance.switches[id].autoDayNight) { - case 0: { - autoDayNightString += 'OFF'; - } break; - - case 1: { - autoDayNightString += 'AUTO-DAY'; - } break; - - case 2: { - autoDayNightString += 'AUTO-NIGHT'; - } break; - - default: { - } break; - } - - return new ActionRowBuilder() - .addComponents( - new SelectMenuBuilder() - .setCustomId(`${id}AutoDayNight`) - .setPlaceholder(`${autoDayNightString}`) - .addOptions([ - { - label: 'OFF', - description: 'Smart Switch work as normal.', - value: '0', - }, - { - label: 'AUTO-DAY', - description: 'Smart Switch will be active only during the day.', - value: '1', - }, - { - label: 'AUTO-NIGHT', - description: 'Smart Switch will be active only during the night.', - value: '2', - }, - ]), - ); - }, - - getSmartSwitchButtons: function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId(`${id}${(instance.switches[id].active) ? 'Off' : 'On'}SmartSwitch`) - .setLabel((instance.switches[id].active) ? 'TURN OFF' : 'TURN ON') - .setStyle((instance.switches[id].active) ? ButtonStyle.Danger : ButtonStyle.Success), - new ButtonBuilder() - .setCustomId(`${id}SmartSwitchDelete`) - .setEmoji('🗑️') - .setStyle(ButtonStyle.Secondary) - ) - - }, - - sendSmartSwitchMessage: async function (guildId, id, e = true, c = true, f = true, interaction = null) { - const instance = Client.client.readInstanceFile(guildId); - - const file = new AttachmentBuilder(`src/resources/images/electrics/${instance.switches[id].image}`); - let embed = module.exports.getSmartSwitchEmbed(guildId, id); - let selectMenu = module.exports.getSmartSwitchSelectMenu(guildId, id); - let buttons = module.exports.getSmartSwitchButtons(guildId, id); - - if (!instance.switches[id].reachable) { - embed = module.exports.getNotFoundSmartDeviceEmbed(guildId, id, 'switches'); - } - - let content = new Object(); - if (e) { - content.embeds = [embed]; - } - if (c) { - content.components = [selectMenu, buttons]; - } - if (f) { - content.files = [file]; - } - - if (interaction) { - await Client.client.interactionUpdate(interaction, content); - return; - } - - if (Client.client.switchesMessages[guildId][id]) { - let message = Client.client.switchesMessages[guildId][id]; - if (await Client.client.messageEdit(message, content) === undefined) return; - } - else { - const channel = module.exports.getTextChannelById(guildId, instance.channelId.switches); - - if (!channel) { - Client.client.log('ERROR', 'sendSmartSwitchMessage: Invalid guild or channel.', 'error'); - return; - } - Client.client.switchesMessages[guildId][id] = await Client.client.messageSend(channel, content); - } - }, - - getSmartAlarmEmbed: function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - - return new EmbedBuilder() - .setTitle(`${instance.alarms[id].name}`) - .setColor((instance.alarms[id].active) ? '#00ff40' : '#ce412b') - .setDescription(`**ID**: \`${id}\``) - .addFields( - { name: 'Message', value: `\`${instance.alarms[id].message}\``, inline: true } - ) - .setThumbnail(`attachment://${instance.alarms[id].image}`) - .setFooter({ text: `${instance.alarms[id].server}` }) - }, - - getSmartAlarmButtons: function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId(`${id}SmartAlarmEveryone`) - .setLabel('@everyone') - .setStyle((instance.alarms[id].everyone) ? ButtonStyle.Success : ButtonStyle.Danger), - new ButtonBuilder() - .setCustomId(`${id}SmartAlarmDelete`) - .setEmoji('🗑️') - .setStyle(ButtonStyle.Secondary)) - }, - - sendSmartAlarmMessage: async function (guildId, id, e = true, c = true, f = true, interaction = null) { - const instance = Client.client.readInstanceFile(guildId); - - const file = new AttachmentBuilder(`src/resources/images/electrics/${instance.alarms[id].image}`); - let embed = module.exports.getSmartAlarmEmbed(guildId, id); - let buttons = module.exports.getSmartAlarmButtons(guildId, id); - - if (!instance.alarms[id].reachable) { - embed = module.exports.getNotFoundSmartDeviceEmbed(guildId, id, 'alarms'); - } - - let content = new Object(); - if (e) { - content.embeds = [embed]; - } - if (c) { - content.components = [buttons]; - } - if (f) { - content.files = [file]; - } - - if (interaction) { - await Client.client.interactionUpdate(interaction, content); - return; - } - - let messageId = instance.alarms[id].messageId; - let message = undefined; - if (messageId !== null) { - message = await module.exports.getMessageById(guildId, instance.channelId.alarms, messageId); - } - - if (message !== undefined) { - if (await Client.client.messageEdit(message, content) === undefined) return; - } - else { - const channel = module.exports.getTextChannelById(guildId, instance.channelId.alarms); - - if (!channel) { - Client.client.log('ERROR', 'sendSmartAlarmMessage: Invalid guild or channel.', 'error'); - return; - } - - message = await Client.client.messageSend(channel, content); - instance.alarms[id].messageId = message.id; - Client.client.writeInstanceFile(guildId, instance); - } - }, - - getStorageMonitorEmbed: function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - let rustplus = Client.client.rustplusInstances[guildId]; - const isTc = (instance.storageMonitors[id].type === 'toolcupboard'); - const items = rustplus.storageMonitors[id].items; - const expiry = rustplus.storageMonitors[id].expiry; - const capacity = rustplus.storageMonitors[id].capacity; - - let description = `**ID** \`${id}\``; - - if (capacity === 0) { - return new EmbedBuilder() - .setTitle(`${instance.storageMonitors[id].name}`) - .setColor('#ce412b') - .setDescription(`${description}\n**STATUS** \`NOT ELECTRICALLY CONNECTED!\``) - .setThumbnail(`attachment://${instance.storageMonitors[id].image}`) - .setFooter({ text: `${instance.storageMonitors[id].server}` }); - } - - description += `\n**Type** \`${(isTc) ? 'Tool Cupboard' : 'Container'}\``; - - if (isTc) { - let seconds = 0; - if (expiry !== 0) { - seconds = (new Date(expiry * 1000) - new Date()) / 1000; - } - - let upkeep = null; - if (seconds === 0) { - upkeep = ':warning:\`DECAYING\`:warning:'; - instance.storageMonitors[id].upkeep = 'DECAYING'; - } - else { - let upkeepTime = Timer.secondsToFullScale(seconds); - upkeep = `\`${upkeepTime}\``; - instance.storageMonitors[id].upkeep = `${upkeepTime}`; - } - description += `\n**Upkeep** ${upkeep}`; - Client.client.writeInstanceFile(guildId, instance); - } - - let itemName = ''; - let itemQuantity = ''; - let storageItems = new Object(); - for (let item of items) { - if (storageItems.hasOwnProperty(item.itemId)) { - storageItems[item.itemId] += item.quantity; - } - else { - storageItems[item.itemId] = item.quantity; - } - } - - for (const [id, quantity] of Object.entries(storageItems)) { - itemName += `\`${Client.client.items.getName(id)}\`\n`; - itemQuantity += `\`${quantity}\`\n`; - } - - if (itemName === '' || itemQuantity === '') { - itemName = 'Empty'; - itemQuantity = 'Empty'; - } - - return new EmbedBuilder() - .setTitle(`${instance.storageMonitors[id].name}`) - .setColor('#ce412b') - .setDescription(description) - .addFields( - { name: 'Item', value: itemName, inline: true }, - { name: 'Quantity', value: itemQuantity, inline: true } - ) - .setThumbnail(`attachment://${instance.storageMonitors[id].image}`) - .setFooter({ text: `${instance.storageMonitors[id].server}` }); - }, - - getStorageMonitorToolCupboardButtons: function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId(`${id}StorageMonitorToolCupboardEveryone`) - .setLabel('@everyone') - .setStyle((instance.storageMonitors[id].everyone) ? ButtonStyle.Success : ButtonStyle.Danger), - new ButtonBuilder() - .setCustomId(`${id}StorageMonitorToolCupboardInGame`) - .setLabel('IN-GAME') - .setStyle((instance.storageMonitors[id].inGame) ? ButtonStyle.Success : ButtonStyle.Danger), - new ButtonBuilder() - .setCustomId(`${id}StorageMonitorToolCupboardDelete`) - .setEmoji('🗑️') - .setStyle(ButtonStyle.Secondary)) - }, - - getStorageMonitorContainerButton: function (guildId, id) { - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId(`${id}StorageMonitorContainerDelete`) - .setEmoji('🗑️') - .setStyle(ButtonStyle.Secondary)) - }, - - sendStorageMonitorMessage: async function (guildId, id, e = true, c = true, f = true, interaction = null) { - let instance = Client.client.readInstanceFile(guildId); - - const file = new AttachmentBuilder(`src/resources/images/electrics/${instance.storageMonitors[id].image}`); - let embed = null; - - if (instance.storageMonitors[id].reachable) { - embed = module.exports.getStorageMonitorEmbed(guildId, id); - instance = Client.client.readInstanceFile(guildId); - } - else { - embed = module.exports.getNotFoundSmartDeviceEmbed(guildId, id, 'storageMonitors'); - } - - let buttons = null; - if (instance.storageMonitors[id].type === 'toolcupboard') { - buttons = module.exports.getStorageMonitorToolCupboardButtons(guildId, id); - } - else { - buttons = module.exports.getStorageMonitorContainerButton(guildId, id); - } - - let content = new Object(); - if (e) { - content.embeds = [embed]; - } - if (c) { - content.components = [buttons]; - } - if (f) { - content.files = [file]; - } - - if (interaction) { - await Client.client.interactionUpdate(interaction, content); - return; - } - - if (Client.client.storageMonitorsMessages[guildId][id]) { - let message = Client.client.storageMonitorsMessages[guildId][id]; - if (await Client.client.messageEdit(message, content) === undefined) return; - } - else { - const channel = module.exports.getTextChannelById(guildId, instance.channelId.storageMonitors); - - if (!channel) { - Client.client.log('ERROR', 'sendStorageMonitorMessage: Invalid guild or channel.', 'error'); - return; - } - Client.client.storageMonitorsMessages[guildId][id] = await Client.client.messageSend(channel, content); - } - }, - - sendDecayingNotification: async function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - let channel = module.exports.getTextChannelById(guildId, instance.channelId.activity); - const file = new AttachmentBuilder(`src/resources/images/electrics/${instance.storageMonitors[id].image}`); - - if (channel) { - let content = {}; - content.embeds = [new EmbedBuilder() - .setTitle(`${instance.storageMonitors[id].name} is decaying!`) - .setColor('#ff0040') - .setDescription(`**ID** \`${id}\``) - .setThumbnail(`attachment://${instance.storageMonitors[id].image}`) - .setFooter({ text: `${instance.storageMonitors[id].server}` }) - .setTimestamp()]; - - content.files = [file]; - - if (instance.storageMonitors[id].everyone) { - content.content = '@everyone'; - } - - await Client.client.messageSend(channel, content); - } - }, - - sendStorageMonitorDisconnectNotification: async function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - let channel = module.exports.getTextChannelById(guildId, instance.channelId.activity); - const file = new AttachmentBuilder(`src/resources/images/electrics/${instance.storageMonitors[id].image}`); - - if (channel) { - let content = {}; - content.embeds = [new EmbedBuilder() - .setTitle(`${instance.storageMonitors[id].name} is no longer electrically connected!`) - .setColor('#ff0040') - .setDescription(`**ID** \`${id}\``) - .setThumbnail(`attachment://${instance.storageMonitors[id].image}`) - .setFooter({ text: `${instance.storageMonitors[id].server}` }) - .setTimestamp()]; - - content.files = [file]; - - if (instance.storageMonitors[id].everyone) { - content.content = '@everyone'; - } - - await Client.client.messageSend(channel, content); - } - }, - - sendStorageMonitorNotFound: async function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - let channel = module.exports.getTextChannelById(guildId, instance.channelId.activity); - const file = new AttachmentBuilder(`src/resources/images/electrics/${instance.storageMonitors[id].image}`); - - if (channel) { - let content = {}; - content.embeds = [new EmbedBuilder() - .setTitle(`${instance.storageMonitors[id].name} could not be found!` + - ` Either it have been destroyed or Admin have lost tool cupboard access.`) - .setColor('#ff0040') - .setDescription(`**ID** \`${id}\``) - .setThumbnail(`attachment://${instance.storageMonitors[id].image}`) - .setFooter({ text: `${instance.storageMonitors[id].server}` }) - .setTimestamp()]; - - content.files = [file]; - - if (instance.storageMonitors[id].everyone) { - content.content = '@everyone'; - } - - await Client.client.messageSend(channel, content); - } - }, - - sendSmartSwitchNotFound: async function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - let channel = module.exports.getTextChannelById(guildId, instance.channelId.activity); - const file = new AttachmentBuilder(`src/resources/images/electrics/${instance.switches[id].image}`); - - if (channel) { - let content = {}; - content.embeds = [new EmbedBuilder() - .setTitle(`${instance.switches[id].name} could not be found!` + - ` Either it have been destroyed or Admin have lost tool cupboard access.`) - .setColor('#ff0040') - .setDescription(`**ID** \`${id}\``) - .setThumbnail(`attachment://${instance.switches[id].image}`) - .setFooter({ text: `${instance.switches[id].server}` }) - .setTimestamp()]; - - content.files = [file]; - - await Client.client.messageSend(channel, content); - } - }, - - sendSmartAlarmNotFound: async function (guildId, id) { - const instance = Client.client.readInstanceFile(guildId); - let channel = module.exports.getTextChannelById(guildId, instance.channelId.activity); - const file = new AttachmentBuilder(`src/resources/images/electrics/${instance.alarms[id].image}`); - - if (channel) { - let content = {}; - content.embeds = [new EmbedBuilder() - .setTitle(`${instance.alarms[id].name} could not be found!` + - ` Either it have been destroyed or Admin have lost tool cupboard access.`) - .setColor('#ff0040') - .setDescription(`**ID** \`${id}\``) - .setThumbnail(`attachment://${instance.alarms[id].image}`) - .setFooter({ text: `${instance.alarms[id].server}` }) - .setTimestamp()]; - - content.files = [file]; - - await Client.client.messageSend(channel, content); - } - }, - - getSmartSwitchGroupEmbed: function (guildId, name) { - const instance = Client.client.readInstanceFile(guildId); - let rustplus = Client.client.rustplusInstances[guildId]; - let group = instance.serverList[rustplus.serverId].switchGroups[name]; - - let switchName = ''; - let switchId = ''; - let switchActive = ''; - for (let groupSwitchId of group.switches) { - if (instance.switches.hasOwnProperty(groupSwitchId)) { - let active = instance.switches[groupSwitchId].active; - switchName += `${instance.switches[groupSwitchId].name}\n`; - switchId += `${groupSwitchId}\n`; - if (instance.switches[groupSwitchId].reachable) { - switchActive += `${(active) ? Constants.ONLINE_EMOJI : Constants.OFFLINE_EMOJI}\n`; - } - else { - switchActive += `${Constants.NOT_FOUND_EMOJI}\n`; - } - } - else { - instance.serverList[rustplus.serverId].switchGroups[name].switches = - instance.serverList[rustplus.serverId].switchGroups[name].switches.filter(e => e !== groupSwitchId); - } - } - Client.client.writeInstanceFile(guildId, instance); - - if (switchName === '' || switchId === '' || switchActive === '') { - switchName = 'None'; - switchId = 'None'; - switchActive = 'None'; - } - - return new EmbedBuilder() - .setTitle(name) - .setColor('#ce412b') - .setThumbnail('attachment://smart_switch.png') - .addFields( - { - name: 'Custom Command', - value: `\`${instance.generalSettings.prefix}${group.command}\``, - inline: false - }, - { name: 'Switches', value: switchName, inline: true }, - { name: 'ID', value: switchId, inline: true }, - { name: 'Active', value: switchActive, inline: true } - ) - .setFooter({ text: `${instance.serverList[rustplus.serverId].title}` }) - }, - - getSmartSwitchGroupButtons: function (name) { - return new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId(`${name}TurnOnGroup`) - .setLabel('TURN ON') - .setStyle(ButtonStyle.Primary), - new ButtonBuilder() - .setCustomId(`${name}TurnOffGroup`) - .setLabel('TURN OFF') - .setStyle(ButtonStyle.Primary), - new ButtonBuilder() - .setCustomId(`${name}DeleteGroup`) - .setEmoji('🗑️') - .setStyle(ButtonStyle.Secondary)); - }, - - sendSmartSwitchGroupMessage: async function (guildId, name, e = true, c = true, f = true, interaction = null) { - const instance = Client.client.readInstanceFile(guildId); - - const file = new AttachmentBuilder('src/resources/images/electrics/smart_switch.png'); - const embed = module.exports.getSmartSwitchGroupEmbed(guildId, name); - const buttons = module.exports.getSmartSwitchGroupButtons(name); - - let content = new Object(); - if (e) { - content.embeds = [embed]; - } - if (c) { - content.components = [buttons]; - } - if (f) { - content.files = [file]; - } - - if (interaction) { - await Client.client.interactionUpdate(interaction, content); - return; - } - - if (Client.client.switchesMessages[guildId][name]) { - let message = Client.client.switchesMessages[guildId][name]; - if (await Client.client.messageEdit(message, content) === undefined) return; - } - else { - const channel = module.exports.getTextChannelById(guildId, instance.channelId.switches); - - if (!channel) { - Client.client.log('ERROR', 'sendSmartSwitchGroupMessage: Invalid guild or channel.', 'error'); - return; - } - Client.client.switchesMessages[guildId][name] = await Client.client.messageSend(channel, content); - } - }, - - sendTrackerAllOffline: async function (guildId, trackerName) { - const instance = Client.client.readInstanceFile(guildId); - const serverId = instance.trackers[trackerName].serverId; - let channel = module.exports.getTextChannelById(guildId, instance.channelId.activity); - - if (channel) { - let content = {}; - content.embeds = [new EmbedBuilder() - .setTitle(`Everyone from the tracker \`${trackerName}\` just went offline.`) - .setColor('#ff0040') - .setThumbnail(`${instance.serverList[serverId].img}`) - .setFooter({ text: `${instance.serverList[serverId].title}` }) - .setTimestamp()]; - - if (instance.trackers[trackerName].everyone) { - content.content = '@everyone'; - } - - await Client.client.messageSend(channel, content); - } - }, - - sendTrackerAnyOnline: async function (guildId, trackerName) { - const instance = Client.client.readInstanceFile(guildId); - const serverId = instance.trackers[trackerName].serverId; - let channel = module.exports.getTextChannelById(guildId, instance.channelId.activity); - - if (channel) { - let content = {}; - content.embeds = [new EmbedBuilder() - .setTitle(`Someone from tracker \`${trackerName}\` just went online.`) - .setColor('#00ff40') - .setThumbnail(`${instance.serverList[serverId].img}`) - .setFooter({ text: `${instance.serverList[serverId].title}` }) - .setTimestamp()]; - - if (instance.trackers[trackerName].everyone) { - content.content = '@everyone'; - } - - await Client.client.messageSend(channel, content); - } - }, - - getNotFoundSmartDeviceEmbed: function (guildId, id, type) { - const instance = Client.client.readInstanceFile(guildId); - - return new EmbedBuilder() - .setTitle(`${instance[type][id].name}`) - .setColor('#ff0040') - .setDescription(`**ID**: \`${id}\`\n**STATUS**: NOT FOUND ${Constants.NOT_FOUND_EMOJI}`) - .setThumbnail(`attachment://${instance[type][id].image}`) - .setFooter({ text: `${instance[type][id].server}` }) - }, } \ No newline at end of file diff --git a/src/handlers/battlemetricsHandler.js b/src/handlers/battlemetricsHandler.js index 0d054e7ab..90ebd4b5b 100644 --- a/src/handlers/battlemetricsHandler.js +++ b/src/handlers/battlemetricsHandler.js @@ -1,55 +1,55 @@ -const DiscordTools = require('../discordTools/discordTools.js'); const BattlemetricsAPI = require('../util/battlemetricsAPI.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); const Scrape = require('../util/scrape.js'); module.exports = { handler: async function (client) { - let forceSearch = (client.battlemetricsIntervalCounter === 0) ? true : false; + const forceSearch = (client.battlemetricsIntervalCounter === 0) ? true : false; - let calledPages = new Object(); - let calledSteamIdNames = new Object(); + const calledPages = new Object(); + const calledSteamIdNames = new Object(); - for (let guildItem of client.guilds.cache) { - let guild = guildItem[1]; + for (const guildItem of client.guilds.cache) { + const guild = guildItem[1]; let instance = client.readInstanceFile(guild.id); - let activeServer = getActiveServerId(instance.serverList); + const activeServer = getActiveServerId(instance.serverList); if (activeServer !== null && instance.serverList[activeServer].battlemetricsId !== null) { let battlemetricsId = instance.serverList[activeServer].battlemetricsId; if (!Object.keys(calledPages).includes(battlemetricsId)) { - let page = await BattlemetricsAPI.getBattlemetricsServerPage(client, battlemetricsId); + const page = await BattlemetricsAPI.getBattlemetricsServerPage(client, battlemetricsId); if (page !== null) { calledPages[battlemetricsId] = page; } } } - for (const [key, value] of Object.entries(instance.trackers)) { - if (!value.active) continue; + for (const [trackerId, content] of Object.entries(instance.trackers)) { + if (!content.active) continue; instance = client.readInstanceFile(guild.id); let page = null; - if (!Object.keys(calledPages).includes(value.battlemetricsId)) { - page = await BattlemetricsAPI.getBattlemetricsServerPage(client, value.battlemetricsId); + if (!Object.keys(calledPages).includes(content.battlemetricsId)) { + page = await BattlemetricsAPI.getBattlemetricsServerPage(client, content.battlemetricsId); if (page === null) continue; - calledPages[value.battlemetricsId] = page; + calledPages[content.battlemetricsId] = page; } else { - page = calledPages[value.battlemetricsId]; + page = calledPages[content.battlemetricsId]; } - let info = await BattlemetricsAPI.getBattlemetricsServerInfo( - client, value.battlemetricsId, page); + const info = await BattlemetricsAPI.getBattlemetricsServerInfo( + client, content.battlemetricsId, page); if (info === null) continue; - instance.trackers[key].status = info.status; + instance.trackers[trackerId].status = info.status; - let onlinePlayers = await BattlemetricsAPI.getBattlemetricsServerOnlinePlayers( - client, value.battlemetricsId, page); + const onlinePlayers = await BattlemetricsAPI.getBattlemetricsServerOnlinePlayers( + client, content.battlemetricsId, page); if (onlinePlayers === null) continue; - for (let player of value.players) { - player = instance.trackers[key].players.find(e => e.steamId === player.steamId); + for (let player of content.players) { + player = instance.trackers[trackerId].players.find(e => e.steamId === player.steamId); let onlinePlayer = onlinePlayers.find(e => e.name === player.name); if (onlinePlayer) { player.status = true; @@ -89,26 +89,26 @@ module.exports = { instance = client.readInstanceFile(guild.id); let allOffline = true; - for (let player of instance.trackers[key].players) { + for (const player of instance.trackers[trackerId].players) { if (player.status) { allOffline = false; } } - if (!instance.trackers[key].allOffline && allOffline) { + if (!instance.trackers[trackerId].allOffline && allOffline) { if (instance.generalSettings.trackerNotifyAllOffline) { - await DiscordTools.sendTrackerAllOffline(guild.id, key); + await DiscordMessages.sendTrackerAllOfflineMessage(guild.id, trackerId); } } - else if (instance.trackers[key].allOffline && !allOffline) { + else if (instance.trackers[trackerId].allOffline && !allOffline) { if (instance.generalSettings.trackerNotifyAnyOnline) { - await DiscordTools.sendTrackerAnyOnline(guild.id, key); + await DiscordMessages.sendTrackerAnyOnlineMessage(guild.id, trackerId); } } - instance.trackers[key].allOffline = allOffline; + instance.trackers[trackerId].allOffline = allOffline; client.writeInstanceFile(guild.id, instance); - await DiscordTools.sendTrackerMessage(guild.id, key, true, false); + await DiscordMessages.sendTrackerMessage(guild.id, trackerId); } } diff --git a/src/handlers/buttonHandler.js b/src/handlers/buttonHandler.js index 94e305c3f..6b86dfdae 100644 --- a/src/handlers/buttonHandler.js +++ b/src/handlers/buttonHandler.js @@ -1,711 +1,686 @@ +const DiscordMessages = require('../discordTools/discordMessages.js'); const DiscordTools = require('../discordTools/discordTools.js'); const SmartSwitchGroupHandler = require('./smartSwitchGroupHandler.js'); +const DiscordButtons = require('..//discordTools/discordButtons.js'); +const DiscordModals = require('../discordTools/discordModals.js'); +const Recycler = require('../util/recycler.js'); module.exports = async (client, interaction) => { - let guildId = interaction.guildId; - let instance = client.readInstanceFile(guildId); - let rustplus = client.rustplusInstances[guildId]; + const instance = client.readInstanceFile(interaction.guildId); + const guildId = interaction.guildId; + const rustplus = client.rustplusInstances[guildId]; - if (interaction.customId.endsWith('DiscordNotification')) { - let setting = interaction.customId.replace('DiscordNotification', ''); - instance.notificationSettings[setting].discord = !instance.notificationSettings[setting].discord; + if (interaction.customId.startsWith('DiscordNotification')) { + const ids = JSON.parse(interaction.customId.replace('DiscordNotification', '')); + const setting = instance.notificationSettings[ids.setting]; - if (rustplus) { - rustplus.notificationSettings[setting].discord = instance.notificationSettings[setting].discord; - } - - let row = DiscordTools.getNotificationButtons( - setting, - instance.notificationSettings[setting].discord, - instance.notificationSettings[setting].inGame); + setting.discord = !setting.discord; + client.writeInstanceFile(guildId, instance); - await client.interactionUpdate(interaction, { components: [row] }); + if (rustplus) rustplus.notificationSettings[ids.setting].discord = setting.discord; - client.writeInstanceFile(guildId, instance); + await client.interactionUpdate(interaction, { + components: [DiscordButtons.getNotificationButtons(ids.setting, setting.discord, setting.inGame)] + }); } - else if (interaction.customId.endsWith('InGameNotification')) { - let setting = interaction.customId.replace('InGameNotification', ''); - instance.notificationSettings[setting].inGame = !instance.notificationSettings[setting].inGame; - - if (rustplus) { - rustplus.notificationSettings[setting].inGame = instance.notificationSettings[setting].inGame; - } + else if (interaction.customId.startsWith('InGameNotification')) { + const ids = JSON.parse(interaction.customId.replace('InGameNotification', '')); + const setting = instance.notificationSettings[ids.setting]; - let row = DiscordTools.getNotificationButtons( - setting, - instance.notificationSettings[setting].discord, - instance.notificationSettings[setting].inGame); + setting.inGame = !setting.inGame; + client.writeInstanceFile(guildId, instance); - await client.interactionUpdate(interaction, { components: [row] }); + if (rustplus) rustplus.notificationSettings[ids.setting].inGame = setting.inGame; - client.writeInstanceFile(guildId, instance); + await client.interactionUpdate(interaction, { + components: [DiscordButtons.getNotificationButtons(ids.setting, setting.discord, setting.inGame)] + }); } - else if (interaction.customId === 'allowInGameCommands') { + else if (interaction.customId === 'AllowInGameCommands') { instance.generalSettings.inGameCommandsEnabled = !instance.generalSettings.inGameCommandsEnabled; + client.writeInstanceFile(guildId, instance); - if (rustplus) { - rustplus.generalSettings.inGameCommandsEnabled = instance.generalSettings.inGameCommandsEnabled; - } - - let row = DiscordTools.getInGameCommandsEnabledButton(instance.generalSettings.inGameCommandsEnabled); - - await client.interactionUpdate(interaction, { components: [row] }); + if (rustplus) rustplus.generalSettings.inGameCommandsEnabled = instance.generalSettings.inGameCommandsEnabled; - client.writeInstanceFile(guildId, instance); + await client.interactionUpdate(interaction, { + components: [DiscordButtons.getInGameCommandsEnabledButton(instance.generalSettings.inGameCommandsEnabled)] + }); } - else if (interaction.customId === 'inGameTeammateConnection') { + else if (interaction.customId === 'InGameTeammateConnection') { instance.generalSettings.connectionNotify = !instance.generalSettings.connectionNotify; + client.writeInstanceFile(guildId, instance); - if (rustplus) { - rustplus.generalSettings.connectionNotify = instance.generalSettings.connectionNotify; - } - - let row = DiscordTools.getInGameTeammateNotificationsButtons(instance); - - await client.interactionUpdate(interaction, { components: [row] }); + if (rustplus) rustplus.generalSettings.connectionNotify = instance.generalSettings.connectionNotify; - client.writeInstanceFile(guildId, instance); + await client.interactionUpdate(interaction, { + components: [DiscordButtons.getInGameTeammateNotificationsButtons(guildId)] + }); } - else if (interaction.customId === 'inGameTeammateAfk') { + else if (interaction.customId === 'InGameTeammateAfk') { instance.generalSettings.afkNotify = !instance.generalSettings.afkNotify; + client.writeInstanceFile(guildId, instance); - if (rustplus) { - rustplus.generalSettings.afkNotify = instance.generalSettings.afkNotify; - } - - let row = DiscordTools.getInGameTeammateNotificationsButtons(instance); - - await client.interactionUpdate(interaction, { components: [row] }); + if (rustplus) rustplus.generalSettings.afkNotify = instance.generalSettings.afkNotify; - client.writeInstanceFile(guildId, instance); + await client.interactionUpdate(interaction, { + components: [DiscordButtons.getInGameTeammateNotificationsButtons(guildId)] + }); } - else if (interaction.customId === 'inGameTeammateDeath') { + else if (interaction.customId === 'InGameTeammateDeath') { instance.generalSettings.deathNotify = !instance.generalSettings.deathNotify; + client.writeInstanceFile(guildId, instance); - if (rustplus) { - rustplus.generalSettings.deathNotify = instance.generalSettings.deathNotify; - } - - let row = DiscordTools.getInGameTeammateNotificationsButtons(instance); - - await client.interactionUpdate(interaction, { components: [row] }); + if (rustplus) rustplus.generalSettings.deathNotify = instance.generalSettings.deathNotify; - client.writeInstanceFile(guildId, instance); + await client.interactionUpdate(interaction, { + components: [DiscordButtons.getInGameTeammateNotificationsButtons(guildId)] + }); } - else if (interaction.customId === 'fcmAlarmNotification') { + else if (interaction.customId === 'FcmAlarmNotification') { instance.generalSettings.fcmAlarmNotificationEnabled = !instance.generalSettings.fcmAlarmNotificationEnabled; + client.writeInstanceFile(guildId, instance); - if (rustplus) { - rustplus.generalSettings.fcmAlarmNotificationEnabled = instance.generalSettings.fcmAlarmNotificationEnabled; - } - - let row = DiscordTools.getFcmAlarmNotificationButtons( - instance.generalSettings.fcmAlarmNotificationEnabled, - instance.generalSettings.fcmAlarmNotificationEveryone); - - await client.interactionUpdate(interaction, { components: [row] }); + if (rustplus) rustplus.generalSettings.fcmAlarmNotificationEnabled = + instance.generalSettings.fcmAlarmNotificationEnabled; - client.writeInstanceFile(guildId, instance); + await client.interactionUpdate(interaction, { + components: [DiscordButtons.getFcmAlarmNotificationButtons( + instance.generalSettings.fcmAlarmNotificationEnabled, + instance.generalSettings.fcmAlarmNotificationEveryone)] + }); } - else if (interaction.customId === 'fcmAlarmNotificationEveryone') { + else if (interaction.customId === 'FcmAlarmNotificationEveryone') { instance.generalSettings.fcmAlarmNotificationEveryone = !instance.generalSettings.fcmAlarmNotificationEveryone; + client.writeInstanceFile(guildId, instance); - if (rustplus) { - rustplus.generalSettings.fcmAlarmNotificationEveryone = - instance.generalSettings.fcmAlarmNotificationEveryone; - } - - let row = DiscordTools.getFcmAlarmNotificationButtons( - instance.generalSettings.fcmAlarmNotificationEnabled, - instance.generalSettings.fcmAlarmNotificationEveryone); - - await client.interactionUpdate(interaction, { components: [row] }); + if (rustplus) rustplus.generalSettings.fcmAlarmNotificationEveryone = + instance.generalSettings.fcmAlarmNotificationEveryone; - client.writeInstanceFile(guildId, instance); + await client.interactionUpdate(interaction, { + components: [DiscordButtons.getFcmAlarmNotificationButtons( + instance.generalSettings.fcmAlarmNotificationEnabled, + instance.generalSettings.fcmAlarmNotificationEveryone)] + }); } - else if (interaction.customId === 'smartAlarmNotifyInGame') { + else if (interaction.customId === 'SmartAlarmNotifyInGame') { instance.generalSettings.smartAlarmNotifyInGame = !instance.generalSettings.smartAlarmNotifyInGame; + client.writeInstanceFile(guildId, instance); - if (rustplus) { - rustplus.generalSettings.smartAlarmNotifyInGame = instance.generalSettings.smartAlarmNotifyInGame; - } - - let row = DiscordTools.getSmartAlarmNotifyInGameButton(instance.generalSettings.smartAlarmNotifyInGame); - - await client.interactionUpdate(interaction, { components: [row] }); + if (rustplus) rustplus.generalSettings.smartAlarmNotifyInGame = + instance.generalSettings.smartAlarmNotifyInGame; - client.writeInstanceFile(guildId, instance); + await client.interactionUpdate(interaction, { + components: [DiscordButtons.getSmartAlarmNotifyInGameButton( + instance.generalSettings.smartAlarmNotifyInGame)] + }); } - else if (interaction.customId === 'leaderCommandEnabled') { + else if (interaction.customId === 'LeaderCommandEnabled') { instance.generalSettings.leaderCommandEnabled = !instance.generalSettings.leaderCommandEnabled; + client.writeInstanceFile(guildId, instance); - if (rustplus) { - rustplus.generalSettings.leaderCommandEnabled = instance.generalSettings.leaderCommandEnabled; - } - - let row = DiscordTools.getLeaderCommandEnabledButton(instance.generalSettings.leaderCommandEnabled); - - await client.interactionUpdate(interaction, { components: [row] }); + if (rustplus) rustplus.generalSettings.leaderCommandEnabled = instance.generalSettings.leaderCommandEnabled; - client.writeInstanceFile(guildId, instance); + await client.interactionUpdate(interaction, { + components: [DiscordButtons.getLeaderCommandEnabledButton( + instance.generalSettings.leaderCommandEnabled)] + }); } - else if (interaction.customId === 'trackerNotifyAllOffline') { + else if (interaction.customId === 'TrackerNotifyAllOffline') { instance.generalSettings.trackerNotifyAllOffline = !instance.generalSettings.trackerNotifyAllOffline; + client.writeInstanceFile(guildId, instance); - if (rustplus) { - rustplus.generalSettings.trackerNotifyAllOffline = instance.generalSettings.trackerNotifyAllOffline; - } - - let row = DiscordTools.getTrackerNotifyButtons( - instance.generalSettings.trackerNotifyAllOffline, - instance.generalSettings.trackerNotifyAnyOnline); - - await client.interactionUpdate(interaction, { components: [row] }); + if (rustplus) rustplus.generalSettings.trackerNotifyAllOffline = + instance.generalSettings.trackerNotifyAllOffline; - client.writeInstanceFile(guildId, instance); + await client.interactionUpdate(interaction, { + components: [getTrackerNotifyButtons( + instance.generalSettings.trackerNotifyAllOffline, + instance.generalSettings.trackerNotifyAnyOnline)] + }); } - else if (interaction.customId === 'trackerNotifyAnyOnline') { + else if (interaction.customId === 'TrackerNotifyAnyOnline') { instance.generalSettings.trackerNotifyAnyOnline = !instance.generalSettings.trackerNotifyAnyOnline; + client.writeInstanceFile(guildId, instance); - if (rustplus) { - rustplus.generalSettings.trackerNotifyAnyOnline = instance.generalSettings.trackerNotifyAnyOnline; - } - - let row = DiscordTools.getTrackerNotifyButtons( - instance.generalSettings.trackerNotifyAllOffline, - instance.generalSettings.trackerNotifyAnyOnline); - - await client.interactionUpdate(interaction, { components: [row] }); + if (rustplus) rustplus.generalSettings.trackerNotifyAnyOnline = + instance.generalSettings.trackerNotifyAnyOnline; - client.writeInstanceFile(guildId, instance); + await client.interactionUpdate(interaction, { + components: [DiscordButtons.getTrackerNotifyButtons( + instance.generalSettings.trackerNotifyAllOffline, + instance.generalSettings.trackerNotifyAnyOnline)] + }); } - else if (interaction.customId.endsWith('ServerConnect')) { - let serverId = interaction.customId.replace('ServerConnect', ''); + else if (interaction.customId.startsWith('ServerConnect')) { + const ids = JSON.parse(interaction.customId.replace('ServerConnect', '')); + const server = instance.serverList[ids.serverId]; - if (!instance.serverList.hasOwnProperty(serverId)) { - try { - interaction.deferUpdate(); - } - catch (e) { - client.log('ERROR', 'Could not defer interaction.', 'error'); - } - client.log('ERROR', `Server with id '${serverId}' does not exist in the instance file.`, 'error'); + if (!server) { + await interaction.message.delete(); return; } - for (const [key, value] of Object.entries(instance.serverList)) { - if (value.active) { - instance.serverList[key].active = false; - client.writeInstanceFile(guildId, instance); - await DiscordTools.sendServerMessage(guildId, key, null, false, true); + for (const [serverId, content] of Object.entries(instance.serverList)) { + if (content.active) { + instance.serverList[serverId].active = false; + await DiscordMessages.sendServerMessage(guildId, serverId, null); break; } } - instance = client.readInstanceFile(guildId); - instance.serverList[serverId].active = true; + server.active = true; client.writeInstanceFile(guildId, instance); - - await DiscordTools.sendServerMessage(guildId, serverId, null, false, true, interaction); + await DiscordMessages.sendServerMessage(guildId, ids.serverId, null, interaction); /* Disconnect previous instance is any */ - if (rustplus) { - rustplus.disconnect(); - } + if (rustplus) rustplus.disconnect(); /* Create the rustplus instance */ - client.createRustplusInstance( - guildId, - instance.serverList[serverId].serverIp, - instance.serverList[serverId].appPort, - instance.serverList[serverId].steamId, - instance.serverList[serverId].playerToken - ); - } - else if (interaction.customId.endsWith('CreateTracker')) { - let serverId = interaction.customId.replace('CreateTracker', ''); - - if (!instance.serverList.hasOwnProperty(serverId)) { - try { - interaction.deferUpdate(); - } - catch (e) { - client.log('ERROR', 'Could not defer interaction.', 'error'); - } - client.log('ERROR', `Server with id '${serverId}' does not exist in the instance file.`, 'error'); + const newRustplus = client.createRustplusInstance( + guildId, server.serverIp, server.appPort, server.steamId, server.playerToken); + + newRustplus.newConnection = true; + } + else if (interaction.customId.startsWith('CustomTimersEdit')) { + const ids = JSON.parse(interaction.customId.replace('CustomTimersEdit', '')); + const server = instance.serverList[ids.serverId]; + + if (!server) { + await interaction.message.delete(); return; } - let battlemetricsId = instance.serverList[serverId].battlemetricsId; + const modal = DiscordModals.getCustomTimersEditModal(guildId, ids.serverId); + await interaction.showModal(modal); + } + else if (interaction.customId.startsWith('CreateTracker')) { + const ids = JSON.parse(interaction.customId.replace('CreateTracker', '')); + const server = instance.serverList[ids.serverId]; - try { - interaction.deferUpdate(); - } - catch (e) { - client.log('ERROR', 'Could not defer interaction.', 'error'); + if (!server) { + await interaction.message.delete(); + return; } - /* Find an available tracker name */ - let name = client.findAvailableTrackerName(interaction.guildId); + interaction.deferUpdate(); - instance.trackers[name] = { - serverId: serverId, - battlemetricsId: battlemetricsId, + /* Find an available tracker id */ + const trackerId = client.findAvailableTrackerId(guildId); + + instance.trackers[trackerId] = { + name: 'Tracker', + serverId: ids.serverId, + battlemetricsId: server.battlemetricsId, status: false, allOffline: true, messageId: null, active: true, everyone: false, players: [], - img: instance.serverList[serverId].img, - title: instance.serverList[serverId].title + img: server.img, + title: server.title } client.writeInstanceFile(guildId, instance); - await DiscordTools.sendTrackerMessage(guildId, name); + await DiscordMessages.sendTrackerMessage(guildId, trackerId); } - else if (interaction.customId.endsWith('ServerDisconnect') || - interaction.customId.endsWith('ServerReconnecting')) { - let serverId = interaction.customId.replace('ServerDisconnect', ''); - serverId = serverId.replace('ServerReconnecting', ''); + else if (interaction.customId.startsWith('CreateGroup')) { + const ids = JSON.parse(interaction.customId.replace('CreateGroup', '')); + const server = instance.serverList[ids.serverId]; - if (!instance.serverList.hasOwnProperty(serverId)) { - try { - interaction.deferUpdate(); - } - catch (e) { - client.log('ERROR', 'Could not defer interaction.', 'error'); - } - client.log('ERROR', `Server with id '${serverId}' does not exist in the instance file.`, 'error'); + if (!server) { + await interaction.message.delete(); return; } - instance.serverList[serverId].active = false; - client.writeInstanceFile(guildId, instance); + interaction.deferUpdate(); - await DiscordTools.sendServerMessage(guildId, serverId, null, false, true, interaction); + const groupId = client.findAvailableGroupId(guildId, ids.serverId); - /* Disconnect previous instance if any */ - if (rustplus) { - rustplus.disconnect(); - delete client.rustplusInstances[guildId]; + server.switchGroups[groupId] = { + name: 'Group', + command: `${groupId}`, + switches: [], + messageId: null } - } - else if (interaction.customId.endsWith('ServerDelete')) { - let serverId = interaction.customId.replace('ServerDelete', ''); + client.writeInstanceFile(guildId, instance); - if (!instance.serverList.hasOwnProperty(serverId)) { - try { - interaction.deferUpdate(); - } - catch (e) { - client.log('ERROR', 'Could not defer interaction.', 'error'); - } - client.log('ERROR', `Server with id '${serverId}' does not exist in the instance file.`, 'error'); + await DiscordMessages.sendSmartSwitchGroupMessage(guildId, ids.serverId, groupId); + } + else if (interaction.customId.startsWith('ServerDisconnect') || + interaction.customId.startsWith('ServerReconnecting')) { + const ids = JSON.parse(interaction.customId.replace('ServerDisconnect', '') + .replace('ServerReconnecting', '')); + const server = instance.serverList[ids.serverId]; + + if (!server) { + await interaction.message.delete(); return; } - if (instance.serverList[serverId].active) { - if (rustplus) { - rustplus.disconnect(); - rustplus.deleted = true; - delete client.rustplusInstances[guildId]; - } - } + server.active = false; + client.writeInstanceFile(guildId, instance); - let messageId = instance.serverList[serverId].messageId; - let message = await DiscordTools.getMessageById(guildId, instance.channelId.servers, messageId); - if (message !== undefined) { - try { - await message.delete(); - } - catch (e) { - client.log('ERROR', `Could not delete server message with id: ${messageId}.`, 'error'); - } + if (rustplus) { + rustplus.disconnect(); + delete client.rustplusInstances[guildId]; } - delete instance.serverList[serverId]; + await DiscordMessages.sendServerMessage(guildId, ids.serverId, null, interaction); + } + else if (interaction.customId.startsWith('ServerDelete')) { + const ids = JSON.parse(interaction.customId.replace('ServerDelete', '')); + const server = instance.serverList[ids.serverId]; - /* Remove all Smart Switches associated with this server */ - for (const [key, value] of Object.entries(instance.switches)) { - if (`${value.serverId}` === serverId) { - delete instance.switches[key]; - } + if (!server) { + await interaction.message.delete(); + return; } - if (rustplus && (serverId === rustplus.serverId)) { + + if (rustplus && (rustplus.serverId === ids.serverId || server.active)) { await DiscordTools.clearTextChannel(rustplus.guildId, instance.channelId.switches, 100); - } + await DiscordTools.clearTextChannel(rustplus.guildId, instance.channelId.storageMonitors, 100); - /* Remove all Smart Alarms associated with this server */ - for (const [key, value] of Object.entries(instance.alarms)) { - if (`${value.serverId}` === serverId) { - let messageId = instance.alarms[key].messageId; - let message = await DiscordTools.getMessageById( - rustplus.guildId, instance.channelId.alarms, messageId); - if (message !== undefined) { - try { - await message.delete(); - } - catch (e) { - client.log('ERROR', `Could not delete alarm message with id: ${messageId}.`, 'error'); - } - } - - delete instance.alarms[key]; - } + rustplus.disconnect(); + rustplus.deleted = true; + delete client.rustplusInstances[guildId]; } - /* Remove all Storage Monitors associated with this server. */ - for (const [key, value] of Object.entries(instance.storageMonitors)) { - if (`${value.serverId}` === serverId) { - delete instance.storageMonitors[key]; - } - } - if (rustplus && (serverId === rustplus.serverId)) { - await DiscordTools.clearTextChannel(rustplus.guildId, instance.channelId.storageMonitors, 100); + for (const [entityId, content] of Object.entries(server.alarms)) { + await DiscordTools.deleteMessageById(guildId, instance.channelId.alarms, content.messageId); } + await DiscordTools.deleteMessageById(guildId, instance.channelId.servers, server.messageId); + + delete instance.serverList[ids.serverId]; client.writeInstanceFile(guildId, instance); } - else if (interaction.customId.endsWith('SmartSwitch')) { - let id = interaction.customId.replace('OnSmartSwitch', '').replace('OffSmartSwitch', ''); - - if (!instance.switches.hasOwnProperty(id)) { - if (client.switchesMessages[guildId].hasOwnProperty(id)) { - try { - await client.switchesMessages[guildId][id].delete(); - } - catch (e) { - client.log('ERROR', `Could not delete switch message with id: ${id}.`, 'error'); - } - delete client.switchesMessages[guildId][id]; - } + else if (interaction.customId.startsWith('SmartSwitchOn') || + interaction.customId.startsWith('SmartSwitchOff')) { + const ids = JSON.parse(interaction.customId.replace('SmartSwitchOn', '').replace('SmartSwitchOff', '')); + const server = instance.serverList[ids.serverId]; - try { - interaction.deferUpdate(); - } - catch (e) { - client.log('ERROR', 'Could not defer interaction.', 'error'); - } - client.log('ERROR', `Switch with id '${id}' does not exist in the instance file.`, 'error') + if (!server || (server && !server.switches.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); return; } - - - if (!rustplus) { - try { - interaction.deferUpdate(); - } - catch (e) { - client.log('ERROR', 'Could not defer the interaction.', 'error') - } - client.log('ERROR', 'Rustplus is not available, cannot use Smart Switches...', 'error') + if (!rustplus || (rustplus && (rustplus.serverId !== ids.serverId))) { + interaction.deferUpdate(); return; } - else { - if (instance.switches[id].serverId !== rustplus.serverId) { - try { - interaction.deferUpdate(); - } - catch (e) { - client.log('ERROR', 'Could not defer the interaction.', 'error') - } - client.log('ERROR', 'Smart Switch is not part of the connected rustplus instance.', 'error'); - return; - } - else { - if (!rustplus.connected) { - try { - interaction.deferUpdate(); - } - catch (e) { - client.log('ERROR', 'Could not defer the interaction.', 'error') - } - client.log('ERROR', 'Rustplus is not connected, cannot use Smart Switches...', 'error'); - return; - } - } - } - if (rustplus.currentSwitchTimeouts.hasOwnProperty(id)) { - clearTimeout(rustplus.currentSwitchTimeouts[id]); - delete rustplus.currentSwitchTimeouts[id]; - } - - let active = (interaction.customId.endsWith('OnSmartSwitch')) ? true : false; + clearTimeout(rustplus.currentSwitchTimeouts[ids.entityId]); + delete rustplus.currentSwitchTimeouts[ids.entityId]; - let prevActive = instance.switches[id].active; - instance.switches[id].active = active; + const active = (interaction.customId.startsWith('SmartSwitchOn')) ? true : false; + const prevActive = server.switches[ids.entityId].active; + server.switches[ids.entityId].active = active; client.writeInstanceFile(guildId, instance); - rustplus.interactionSwitches.push(id); - - let response = null; - if (active) { - response = await rustplus.turnSmartSwitchOnAsync(id); - } - else { - response = await rustplus.turnSmartSwitchOffAsync(id); - } + rustplus.interactionSwitches.push(ids.entityId); + const response = await rustplus.turnSmartSwitchAsync(ids.entityId, active); if (!(await rustplus.isResponseValid(response))) { - if (instance.switches[id].reachable) { - await DiscordTools.sendSmartSwitchNotFound(rustplus.guildId, id); + if (server.switches[ids.entityId].reachable) { + await DiscordMessages.sendSmartSwitchNotFoundMessage(guildId, ids.serverId, ids.entityId); } - instance.switches[id].reachable = false; - instance.switches[id].active = prevActive; - client.writeInstanceFile(rustplus.guildId, instance); + server.switches[ids.entityId].reachable = false; + server.switches[ids.entityId].active = prevActive; + client.writeInstanceFile(guildId, instance); - rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== id); + rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== ids.entityId); } else { - instance.switches[id].reachable = true; - client.writeInstanceFile(rustplus.guildId, instance); + server.switches[ids.entityId].reachable = true; + client.writeInstanceFile(guildId, instance); } - DiscordTools.sendSmartSwitchMessage(guildId, id, true, true, false, interaction); - SmartSwitchGroupHandler.updateSwitchGroupIfContainSwitch( - client, interaction.guildId, instance.switches[id].serverId, id); + DiscordMessages.sendSmartSwitchMessage(guildId, ids.serverId, ids.entityId, interaction); + SmartSwitchGroupHandler.updateSwitchGroupIfContainSwitch(client, guildId, ids.serverId, ids.entityId); } - else if (interaction.customId.endsWith('SmartSwitchDelete')) { - let id = interaction.customId.replace('SmartSwitchDelete', ''); - let serverId = null; + else if (interaction.customId.startsWith('SmartSwitchEdit')) { + const ids = JSON.parse(interaction.customId.replace('SmartSwitchEdit', '')); + const server = instance.serverList[ids.serverId]; - if (instance.switches.hasOwnProperty(id)) { - serverId = instance.switches[id].serverId; - delete instance.switches[id]; + if (!server || (server && !server.switches.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); + return; } - if (rustplus) { - clearTimeout(rustplus.currentSwitchTimeouts[id]); - delete rustplus.currentSwitchTimeouts[id]; + const modal = DiscordModals.getSmartSwitchEditModal(guildId, ids.serverId, ids.entityId); + await interaction.showModal(modal); + } + else if (interaction.customId.startsWith('SmartSwitchDelete')) { + const ids = JSON.parse(interaction.customId.replace('SmartSwitchDelete', '')); + const server = instance.serverList[ids.serverId]; + + if (!server || (server && !server.switches.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); + return; } - if (client.switchesMessages[guildId].hasOwnProperty(id)) { - try { - await client.switchesMessages[guildId][id].delete(); - } - catch (e) { - client.log('ERROR', `Could not delete switch message with id: ${id}.`, 'error'); - } - delete client.switchesMessages[guildId][id]; + await DiscordTools.deleteMessageById(guildId, instance.channelId.switches, + server.switches[ids.entityId].messageId); + + delete server.switches[ids.entityId]; + client.writeInstanceFile(guildId, instance); + + if (rustplus) { + clearTimeout(rustplus.currentSwitchTimeouts[ids.entityId]); + delete rustplus.currentSwitchTimeouts[ids.entityId]; } - for (const [groupName, groupContent] of Object.entries(instance.serverList[serverId].switchGroups)) { - if (groupContent.switches.includes(id)) { - instance.serverList[serverId].switchGroups[groupName].switches = - groupContent.switches.filter(e => e !== id); + for (const [groupId, content] of Object.entries(server.switchGroups)) { + if (content.switches.includes(ids.entityId.toString())) { + server.switchGroups[groupId].switches = content.switches.filter(e => e !== ids.entityId.toString()); client.writeInstanceFile(guildId, instance); - await DiscordTools.sendSmartSwitchGroupMessage(guildId, groupName, true, false, false); + await DiscordMessages.sendSmartSwitchGroupMessage(guildId, ids.serverId, groupId); } } - client.writeInstanceFile(guildId, instance); } - else if (interaction.customId.endsWith('SmartAlarmEveryone')) { - let id = interaction.customId.replace('SmartAlarmEveryone', ''); + else if (interaction.customId.startsWith('SmartAlarmEveryone')) { + const ids = JSON.parse(interaction.customId.replace('SmartAlarmEveryone', '')); + const server = instance.serverList[ids.serverId]; - if (instance.alarms.hasOwnProperty(id)) { - instance.alarms[id].everyone = !instance.alarms[id].everyone; - client.writeInstanceFile(guildId, instance); - - await DiscordTools.sendSmartAlarmMessage(interaction.guildId, id, false, true, false, interaction); + if (!server || (server && !server.alarms.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); + return; } - else { - try { - interaction.deferUpdate(); - } - catch (e) { - client.log('ERROR', 'Could not defer interaction.', 'error'); - } - client.log('ERROR', `Smart Alarm with id '${id}' does not exist in the instance file.`, 'error'); - } - } - else if (interaction.customId.endsWith('SmartAlarmDelete')) { - let id = interaction.customId.replace('SmartAlarmDelete', ''); - - if (instance.alarms.hasOwnProperty(id)) { - let messageId = instance.alarms[id].messageId; - let message = await DiscordTools.getMessageById(guildId, instance.channelId.alarms, messageId); - if (message !== undefined) { - try { - await message.delete(); - } - catch (e) { - client.log('ERROR', `Could not delete alarm message with id: ${messageId}.`, 'error'); - } - } - delete instance.alarms[id]; - client.writeInstanceFile(guildId, instance); - } - } - else if (interaction.customId.endsWith('StorageMonitorToolCupboardEveryone')) { - let id = interaction.customId.replace('StorageMonitorToolCupboardEveryone', ''); + server.alarms[ids.entityId].everyone = !server.alarms[ids.entityId].everyone; + client.writeInstanceFile(guildId, instance); - if (instance.storageMonitors.hasOwnProperty(id)) { - instance.storageMonitors[id].everyone = !instance.storageMonitors[id].everyone; - client.writeInstanceFile(guildId, instance); + await DiscordMessages.sendSmartAlarmMessage(guildId, ids.serverId, ids.entityId, interaction); + } + else if (interaction.customId.startsWith('SmartAlarmDelete')) { + const ids = JSON.parse(interaction.customId.replace('SmartAlarmDelete', '')); + const server = instance.serverList[ids.serverId]; - await DiscordTools.sendStorageMonitorMessage(interaction.guildId, id, false, true, false, interaction); + if (!server || (server && !server.alarms.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); + return; } - } - else if (interaction.customId.endsWith('StorageMonitorToolCupboardInGame')) { - let id = interaction.customId.replace('StorageMonitorToolCupboardInGame', ''); - if (instance.storageMonitors.hasOwnProperty(id)) { - instance.storageMonitors[id].inGame = !instance.storageMonitors[id].inGame; - client.writeInstanceFile(guildId, instance); + await DiscordTools.deleteMessageById(guildId, instance.channelId.alarms, + server.alarms[ids.entityId].messageId); - await DiscordTools.sendStorageMonitorMessage(interaction.guildId, id, false, true, false, interaction); + delete server.alarms[ids.entityId]; + client.writeInstanceFile(guildId, instance); + } + else if (interaction.customId.startsWith('SmartAlarmEdit')) { + const ids = JSON.parse(interaction.customId.replace('SmartAlarmEdit', '')); + const server = instance.serverList[ids.serverId]; + + if (!server || (server && !server.alarms.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); + return; } + + const modal = DiscordModals.getSmartAlarmEditModal(guildId, ids.serverId, ids.entityId); + await interaction.showModal(modal); } - else if (interaction.customId.endsWith('StorageMonitorToolCupboardDelete')) { - let id = interaction.customId.replace('StorageMonitorToolCupboardDelete', ''); + else if (interaction.customId.startsWith('StorageMonitorToolCupboardEveryone')) { + const ids = JSON.parse(interaction.customId.replace('StorageMonitorToolCupboardEveryone', '')); + const server = instance.serverList[ids.serverId]; - if (instance.storageMonitors.hasOwnProperty(id)) { - delete instance.storageMonitors[id]; + if (!server || (server && !server.storageMonitors.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); + return; } - if (client.storageMonitorsMessages[guildId].hasOwnProperty(id)) { - try { - await client.storageMonitorsMessages[guildId][id].delete(); - } - catch (e) { - client.log('ERROR', `Could not delete storage monitor message with id: ${id}.`, 'error'); - } - delete client.storageMonitorsMessages[guildId][id]; + server.storageMonitors[ids.entityId].everyone = !server.storageMonitors[ids.entityId].everyone; + client.writeInstanceFile(guildId, instance); + + await DiscordMessages.sendStorageMonitorMessage(guildId, ids.serverId, ids.entityId, interaction); + } + else if (interaction.customId.startsWith('StorageMonitorToolCupboardInGame')) { + const ids = JSON.parse(interaction.customId.replace('StorageMonitorToolCupboardInGame', '')); + const server = instance.serverList[ids.serverId]; + + if (!server || (server && !server.storageMonitors.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); + return; } + server.storageMonitors[ids.entityId].inGame = !server.storageMonitors[ids.entityId].inGame; client.writeInstanceFile(guildId, instance); + + await DiscordMessages.sendStorageMonitorMessage(guildId, ids.serverId, ids.entityId, interaction); } - else if (interaction.customId.endsWith('StorageMonitorContainerDelete')) { - let id = interaction.customId.replace('StorageMonitorContainerDelete', ''); + else if (interaction.customId.startsWith('StorageMonitorEdit')) { + const ids = JSON.parse(interaction.customId.replace('StorageMonitorEdit', '')); + const server = instance.serverList[ids.serverId]; - if (instance.storageMonitors.hasOwnProperty(id)) { - delete instance.storageMonitors[id]; + if (!server || (server && !server.storageMonitors.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); + return; } - if (client.storageMonitorsMessages[guildId].hasOwnProperty(id)) { - try { - await client.storageMonitorsMessages[guildId][id].delete(); - } - catch (e) { - client.log('ERROR', `Could not delete storage monitor message with id: ${id}.`, 'error'); - } - delete client.storageMonitorsMessages[guildId][id]; + const modal = DiscordModals.getStorageMonitorEditModal(guildId, ids.serverId, ids.entityId); + await interaction.showModal(modal); + } + else if (interaction.customId.startsWith('StorageMonitorToolCupboardDelete')) { + const ids = JSON.parse(interaction.customId.replace('StorageMonitorToolCupboardDelete', '')); + const server = instance.serverList[ids.serverId]; + + if (!server || (server && !server.storageMonitors.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); + return; } + await DiscordTools.deleteMessageById(guildId, instance.channelId.storageMonitors, + server.storageMonitors[ids.entityId].messageId); + + delete server.storageMonitors[ids.entityId]; client.writeInstanceFile(guildId, instance); } - else if (interaction.customId.endsWith('TurnOnGroup') || - interaction.customId.endsWith('TurnOffGroup')) { - let id = interaction.customId.replace('TurnOnGroup', ''); - id = id.replace('TurnOffGroup', ''); + else if (interaction.customId.startsWith('StorageMonitorRecycle')) { + const ids = JSON.parse(interaction.customId.replace('StorageMonitorRecycle', '')); + const server = instance.serverList[ids.serverId]; - if (rustplus.currentSwitchTimeouts.hasOwnProperty(id)) { - clearTimeout(rustplus.currentSwitchTimeouts[id]); - delete rustplus.currentSwitchTimeouts[id]; + if (!server || (server && !server.storageMonitors.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); + return; } - try { - interaction.deferUpdate(); - } - catch (e) { - client.log('ERROR', 'Could not defer the interaction.', 'error'); + interaction.deferUpdate(); + + if (!rustplus || (rustplus && rustplus.serverId !== ids.serverId)) return; + + const entityInfo = await rustplus.getEntityInfoAsync(ids.entityId); + if (!(await rustplus.isResponseValid(entityInfo))) return; + + server.storageMonitors[ids.entityId].reachable = true; + client.writeInstanceFile(guildId, instance); + + const items = Recycler.calculate(entityInfo.entityInfo.payload.items); + + const message = await DiscordMessages.sendStorageMonitorRecycleMessage( + guildId, ids.serverId, ids.entityId, items); + + setTimeout(async () => { + await DiscordTools.deleteMessageById(guildId, instance.channelId.storageMonitors, message.id); + }, 30000); + } + else if (interaction.customId.startsWith('StorageMonitorContainerDelete')) { + const ids = JSON.parse(interaction.customId.replace('StorageMonitorContainerDelete', '')); + const server = instance.serverList[ids.serverId]; + + if (!server || (server && !server.storageMonitors.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); + return; } - if (!rustplus) { - client.log('ERROR', 'Rustplus is not connected, cannot use Smart Switch Groups...', 'error'); + await DiscordTools.deleteMessageById(guildId, instance.channelId.storageMonitors, + server.storageMonitors[ids.entityId].messageId); + + delete server.storageMonitors[ids.entityId]; + client.writeInstanceFile(guildId, instance); + } + else if (interaction.customId === 'RecycleDelete') { + await interaction.message.delete(); + } + else if (interaction.customId.startsWith('GroupTurnOn') || + interaction.customId.startsWith('GroupTurnOff')) { + const ids = JSON.parse(interaction.customId.replace('GroupTurnOn', '').replace('GroupTurnOff', '')); + const server = instance.serverList[ids.serverId]; + + if (!server || (server && !server.switchGroups.hasOwnProperty(ids.groupId))) { + await interaction.message.delete(); return; } - if (!instance.serverList[rustplus.serverId].switchGroups.hasOwnProperty(id)) { - client.log('ERROR', 'Switch group does not exist.', 'error') + interaction.deferUpdate(); + + if (rustplus) { + clearTimeout(rustplus.currentSwitchTimeouts[ids.group]); + delete rustplus.currentSwitchTimeouts[ids.group]; + + if (rustplus.serverId === ids.serverId) { + const active = (interaction.customId.startsWith('GroupTurnOn') ? true : false); + + await SmartSwitchGroupHandler.TurnOnOffGroup( + client, rustplus, guildId, ids.serverId, ids.groupId, active); + } + } + } + else if (interaction.customId.startsWith('GroupEdit')) { + const ids = JSON.parse(interaction.customId.replace('GroupEdit', '')); + const server = instance.serverList[ids.serverId]; + + if (!server || (server && !server.switchGroups.hasOwnProperty(ids.groupId))) { + await interaction.message.delete(); return; } - if (instance.serverList[rustplus.serverId].switchGroups[id].serverId !== rustplus.serverId) { - client.log('ERROR', 'Smart Switch Group is not part of the connected rustplus instance.', 'error'); + const modal = DiscordModals.getGroupEditModal(guildId, ids.serverId, ids.groupId); + await interaction.showModal(modal); + } + else if (interaction.customId.startsWith('GroupDelete')) { + const ids = JSON.parse(interaction.customId.replace('GroupDelete', '')); + const server = instance.serverList[ids.serverId]; + + if (!server || (server && !server.switchGroups.hasOwnProperty(ids.groupId))) { + await interaction.message.delete(); return; } - else { - if (!rustplus.connected) { - client.log('ERROR', 'Rustplus is not connected, cannot use the Smart Switch Group...', 'error'); - return; - } + + if (rustplus) { + clearTimeout(rustplus.currentSwitchTimeouts[ids.groupId]); + delete rustplus.currentSwitchTimeouts[ids.groupId]; } - let active = (interaction.customId.endsWith('TurnOnGroup') ? true : false); + if (server.switchGroups.hasOwnProperty(ids.groupId)) { + await DiscordTools.deleteMessageById(guildId, instance.channelId.switches, + server.switchGroups[ids.groupId].messageId); - await SmartSwitchGroupHandler.TurnOnOffGroup( - client, rustplus, interaction.guildId, rustplus.serverId, id, active); + delete server.switchGroups[ids.groupId]; + client.writeInstanceFile(guildId, instance); + } } - else if (interaction.customId.endsWith('DeleteGroup')) { - let id = interaction.customId.replace('DeleteGroup', ''); + else if (interaction.customId.startsWith('GroupAddSwitch')) { + const ids = JSON.parse(interaction.customId.replace('GroupAddSwitch', '')); + const server = instance.serverList[ids.serverId]; - if (!rustplus) { - client.log('ERROR', 'Rustplus is not connected, cannot delete the Smart Switch Group...', 'error'); + if (!server || (server && !server.switchGroups.hasOwnProperty(ids.groupId))) { + await interaction.message.delete(); return; } - clearTimeout(rustplus.currentSwitchTimeouts[id]); - delete rustplus.currentSwitchTimeouts[id]; + const modal = DiscordModals.getGroupAddSwitchModal(guildId, ids.serverId, ids.groupId); + await interaction.showModal(modal); + } + else if (interaction.customId.startsWith('GroupRemoveSwitch')) { + const ids = JSON.parse(interaction.customId.replace('GroupRemoveSwitch', '')); + const server = instance.serverList[ids.serverId]; - if (instance.serverList[rustplus.serverId].switchGroups.hasOwnProperty(id)) { - delete instance.serverList[rustplus.serverId].switchGroups[id]; + if (!server || (server && !server.switchGroups.hasOwnProperty(ids.groupId))) { + await interaction.message.delete(); + return; } - if (client.switchesMessages[guildId].hasOwnProperty(id)) { - try { - await client.switchesMessages[guildId][id].delete(); - } - catch (e) { - client.log('ERROR', `Could not delete switch message with id: ${id}.`, 'error'); - } - delete client.switchesMessages[guildId][id]; + const modal = DiscordModals.getGroupRemoveSwitchModal(guildId, ids.serverId, ids.groupId); + await interaction.showModal(modal); + } + else if (interaction.customId.startsWith('TrackerActive')) { + const ids = JSON.parse(interaction.customId.replace('TrackerActive', '')); + const tracker = instance.trackers[ids.trackerId]; + + if (!tracker) { + await interaction.message.delete(); + return; } + tracker.active = !tracker.active; client.writeInstanceFile(guildId, instance); - } - else if (interaction.customId.endsWith('TrackerActive')) { - let trackerName = interaction.customId.replace('TrackerActive', ''); - if (instance.trackers.hasOwnProperty(trackerName)) { - instance.trackers[trackerName].active = !instance.trackers[trackerName].active; - client.writeInstanceFile(guildId, instance); + await DiscordMessages.sendTrackerMessage(guildId, ids.trackerId, interaction); + } + else if (interaction.customId.startsWith('TrackerEveryone')) { + const ids = JSON.parse(interaction.customId.replace('TrackerEveryone', '')); + const tracker = instance.trackers[ids.trackerId]; - await DiscordTools.sendTrackerMessage(interaction.guildId, trackerName, false, true, interaction); + if (!tracker) { + await interaction.message.delete(); + return; } + + tracker.everyone = !tracker.everyone; + client.writeInstanceFile(guildId, instance); + + await DiscordMessages.sendTrackerMessage(guildId, ids.trackerId, interaction); } - else if (interaction.customId.endsWith('TrackerEveryone')) { - let trackerName = interaction.customId.replace('TrackerEveryone', ''); + else if (interaction.customId.startsWith('TrackerEdit')) { + const ids = JSON.parse(interaction.customId.replace('TrackerEdit', '')); + const tracker = instance.trackers[ids.trackerId]; - if (instance.trackers.hasOwnProperty(trackerName)) { - instance.trackers[trackerName].everyone = !instance.trackers[trackerName].everyone; - client.writeInstanceFile(guildId, instance); + if (!tracker) { + await interaction.message.delete(); + return; + } + + const modal = DiscordModals.getTrackerEditModal(guildId, ids.trackerId); + await interaction.showModal(modal); + } + else if (interaction.customId.startsWith('TrackerDelete')) { + const ids = JSON.parse(interaction.customId.replace('TrackerDelete', '')); + const tracker = instance.trackers[ids.trackerId]; - await DiscordTools.sendTrackerMessage(interaction.guildId, trackerName, false, true, interaction); + if (!tracker) { + await interaction.message.delete(); + return; } + + await DiscordTools.deleteMessageById(guildId, instance.channelId.trackers, + tracker.messageId); + + delete instance.trackers[ids.trackerId]; + client.writeInstanceFile(guildId, instance); } - else if (interaction.customId.endsWith('TrackerDelete')) { - let trackerName = interaction.customId.replace('TrackerDelete', ''); + else if (interaction.customId.startsWith('TrackerAddPlayer')) { + const ids = JSON.parse(interaction.customId.replace('TrackerAddPlayer', '')); + const tracker = instance.trackers[ids.trackerId]; - if (instance.trackers.hasOwnProperty(trackerName)) { - let messageId = instance.trackers[trackerName].messageId; - let message = await DiscordTools.getMessageById(guildId, instance.channelId.trackers, messageId); - if (message !== undefined) { - try { - await message.delete(); - } - catch (e) { - client.log('ERROR', `Could not delete tracker message with id: ${messageId}.`, 'error'); - } - } + if (!tracker) { + await interaction.message.delete(); + return; + } - delete instance.trackers[trackerName]; - client.writeInstanceFile(guildId, instance); + const modal = DiscordModals.getTrackerAddPlayerModal(guildId, ids.trackerId); + await interaction.showModal(modal); + } + else if (interaction.customId.startsWith('TrackerRemovePlayer')) { + const ids = JSON.parse(interaction.customId.replace('TrackerRemovePlayer', '')); + const tracker = instance.trackers[ids.trackerId]; + + if (!tracker) { + await interaction.message.delete(); + return; } + + const modal = DiscordModals.getTrackerRemovePlayerModal(guildId, ids.trackerId); + await interaction.showModal(modal); } } diff --git a/src/handlers/inGameCommandHandler.js b/src/handlers/inGameCommandHandler.js index 5ac55e409..e2c78b1fe 100644 --- a/src/handlers/inGameCommandHandler.js +++ b/src/handlers/inGameCommandHandler.js @@ -1,12 +1,14 @@ -const Timer = require('../util/timer'); -const Str = require('../util/string.js'); +const Translate = require('translate'); + +const Constants = require('../util/constants.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); const DiscordTools = require('../discordTools/discordTools.js'); +const Languages = require('../util/languages.js'); const Map = require('../util/map.js'); -const Constants = require('../util/constants.js'); -const TeamHandler = require('../handlers/teamHandler.js'); const SmartSwitchGroupHandler = require('./smartSwitchGroupHandler.js'); -const Translate = require('translate'); -const Languages = require('../util/languages.js'); +const Str = require('../util/string.js'); +const TeamHandler = require('../handlers/teamHandler.js'); +const Timer = require('../util/timer'); module.exports = { inGameCommandHandler: async function (rustplus, client, message) { @@ -98,7 +100,7 @@ module.exports = { /* Maybe a custom command? */ let instance = client.readInstanceFile(rustplus.guildId); - for (const [id, content] of Object.entries(instance.switches)) { + for (const [id, content] of Object.entries(instance.serverList[rustplus.serverId].switches)) { let cmd = `${rustplus.generalSettings.prefix}${content.command}`; if (command.startsWith(cmd)) { let rest = command; @@ -124,19 +126,21 @@ module.exports = { else if (command === `${cmd} status`) { let info = await rustplus.getEntityInfoAsync(id); if (!(await rustplus.isResponseValid(info))) { - instance.switches[id].reachable = false; + instance.serverList[rustplus.serverId].switches[id].reachable = false; client.writeInstanceFile(rustplus.guildId, instance); - DiscordTools.sendSmartSwitchMessage(rustplus.guildId, id, true, true, false); + DiscordMessages.sendSmartSwitchMessage(rustplus.guildId, rustplus.serverId, id); SmartSwitchGroupHandler.updateSwitchGroupIfContainSwitch( client, rustplus.guildId, rustplus.serverId, id); rustplus.printCommandOutput( - `Could not communicate with Smart Switch: ${instance.switches[id].name}`); + `Could not communicate with Smart Switch: ` + + `${instance.serverList[rustplus.serverId].switches[id].name}`); return false; } active = (info.entityInfo.payload.value) ? 'ON' : 'OFF'; - rustplus.printCommandOutput(`${instance.switches[id].name} is currently ${active}.`); + rustplus.printCommandOutput(`${instance.serverList[rustplus.serverId].switches[id].name} ` + + `is currently ${active}.`); return true; } else if (command.startsWith(`${cmd}`)) { @@ -154,8 +158,8 @@ module.exports = { let timeSeconds = Timer.getSecondsFromStringTime(rest); - let prevActive = instance.switches[id].active; - instance.switches[id].active = active; + let prevActive = instance.serverList[rustplus.serverId].switches[id].active; + instance.serverList[rustplus.serverId].switches[id].active = active; client.writeInstanceFile(rustplus.guildId, instance); rustplus.interactionSwitches.push(id); @@ -170,26 +174,27 @@ module.exports = { if (!(await rustplus.isResponseValid(response))) { rustplus.printCommandOutput(`Could not communicate with Smart Switch: ${content.name}`); - if (instance.switches[id].reachable) { - await DiscordTools.sendSmartSwitchNotFound(rustplus.guildId, id); + if (instance.serverList[rustplus.serverId].switches[id].reachable) { + await DiscordMessages.sendSmartSwitchNotFoundMessage(rustplus.guildId, + rustplus.serverId, id); } - instance.switches[id].reachable = false; - instance.switches[id].active = prevActive; + instance.serverList[rustplus.serverId].switches[id].reachable = false; + instance.serverList[rustplus.serverId].switches[id].active = prevActive; client.writeInstanceFile(rustplus.guildId, instance); rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== id); } else { - instance.switches[id].reachable = true; + instance.serverList[rustplus.serverId].switches[id].reachable = true; client.writeInstanceFile(rustplus.guildId, instance); } - DiscordTools.sendSmartSwitchMessage(rustplus.guildId, id, true, true, false); + DiscordMessages.sendSmartSwitchMessage(rustplus.guildId, rustplus.serverId, id); SmartSwitchGroupHandler.updateSwitchGroupIfContainSwitch( client, rustplus.guildId, rustplus.serverId, id); - if (instance.switches[id].reachable) { - let str = `${instance.switches[id].name} was turned `; + if (instance.serverList[rustplus.serverId].switches[id].reachable) { + let str = `${instance.serverList[rustplus.serverId].switches[id].name} was turned `; str += (active) ? 'ON.' : 'OFF.'; if (timeSeconds !== null) { @@ -198,12 +203,12 @@ module.exports = { rustplus.currentSwitchTimeouts[id] = setTimeout(async function () { let instance = client.readInstanceFile(rustplus.guildId); - if (!instance.switches.hasOwnProperty(id)) { + if (!instance.serverList[rustplus.serverId].switches.hasOwnProperty(id)) { return false; } - let prevActive = instance.switches[id].active; - instance.switches[id].active = !active; + let prevActive = instance.serverList[rustplus.serverId].switches[id].active; + instance.serverList[rustplus.serverId].switches[id].active = !active; client.writeInstanceFile(rustplus.guildId, instance); rustplus.interactionSwitches.push(id); @@ -218,25 +223,28 @@ module.exports = { if (!(await rustplus.isResponseValid(response))) { rustplus.printCommandOutput(`Could not communicate with Smart Switch: ${content.name}`); - if (instance.switches[id].reachable) { - await DiscordTools.sendSmartSwitchNotFound(rustplus.guildId, id); + if (instance.serverList[rustplus.serverId].switches[id].reachable) { + await DiscordMessages.sendSmartSwitchNotFoundMessage(rustplus.guildId, + rustplus.serverId, id); } - instance.switches[id].reachable = false; - instance.switches[id].active = prevActive; + instance.serverList[rustplus.serverId].switches[id].reachable = false; + instance.serverList[rustplus.serverId].switches[id].active = prevActive; client.writeInstanceFile(rustplus.guildId, instance); rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== id); } else { - instance.switches[id].reachable = true; + instance.serverList[rustplus.serverId].switches[id].reachable = true; client.writeInstanceFile(rustplus.guildId, instance); } - DiscordTools.sendSmartSwitchMessage(rustplus.guildId, id, true, true, false); + DiscordMessages.sendSmartSwitchMessage(rustplus.guildId, rustplus.serverId, id); SmartSwitchGroupHandler.updateSwitchGroupIfContainSwitch( client, rustplus.guildId, rustplus.serverId, id); - let str = `Automatically turning ${instance.switches[id].name} back ${(!active) ? 'ON' : 'OFF'}.`; + let str = `Automatically turning ` + + `${instance.serverList[rustplus.serverId].switches[id].name} back ` + + `${(!active) ? 'ON' : 'OFF'}.`; rustplus.printCommandOutput(str); }, timeSeconds * 1000); } @@ -249,7 +257,7 @@ module.exports = { } let groups = instance.serverList[rustplus.serverId].switchGroups; - for (const [groupName, content] of Object.entries(groups)) { + for (const [groupId, content] of Object.entries(groups)) { let cmd = `${rustplus.generalSettings.prefix}${content.command}`; if (command.startsWith(cmd)) { let rest = command; @@ -265,7 +273,8 @@ module.exports = { else if (command === `${cmd}`) { /* Get switch info, create message */ var switchStatus = content.switches.map(switchId => { - const { active, name, reachable } = instance.switches[switchId]; + const { active, name, reachable } = + instance.serverList[rustplus.serverId].switches[switchId]; return { active, name, reachable } }); const statusMessage = switchStatus.map(status => @@ -278,30 +287,30 @@ module.exports = { return false; } - if (rustplus.currentSwitchTimeouts.hasOwnProperty(groupName)) { - clearTimeout(rustplus.currentSwitchTimeouts[groupName]); - delete rustplus.currentSwitchTimeouts[groupName]; + if (rustplus.currentSwitchTimeouts.hasOwnProperty(groupId)) { + clearTimeout(rustplus.currentSwitchTimeouts[groupId]); + delete rustplus.currentSwitchTimeouts[groupId]; } let timeSeconds = Timer.getSecondsFromStringTime(rest); - let str = `Turning Group ${groupName} ${(active) ? 'ON' : 'OFF'}.`; + let str = `Turning Group ${content.name} ${(active) ? 'ON' : 'OFF'}.`; if (timeSeconds !== null) { let time = Timer.secondsToFullScale(timeSeconds); str += ` Automatically turned back ${(active) ? 'OFF' : 'ON'} in ${time}.`; - rustplus.currentSwitchTimeouts[groupName] = setTimeout(async function () { + rustplus.currentSwitchTimeouts[groupId] = setTimeout(async function () { let instance = client.readInstanceFile(rustplus.guildId); if (!instance.serverList.hasOwnProperty(rustplus.serverId) || - !instance.serverList[rustplus.serverId].switchGroups.hasOwnProperty(groupName)) { + !instance.serverList[rustplus.serverId].switchGroups.hasOwnProperty(groupId)) { return false; } - let str = `Automatically turning ${groupName} back ${(!active) ? 'ON' : 'OFF'}.`; + let str = `Automatically turning ${content.name} back ${(!active) ? 'ON' : 'OFF'}.`; rustplus.printCommandOutput(str); await SmartSwitchGroupHandler.TurnOnOffGroup( - client, rustplus, rustplus.guildId, rustplus.serverId, groupName, !active); + client, rustplus, rustplus.guildId, rustplus.serverId, groupId, !active); }, timeSeconds * 1000); } @@ -309,7 +318,7 @@ module.exports = { rustplus.printCommandOutput(str); await SmartSwitchGroupHandler.TurnOnOffGroup( - client, rustplus, rustplus.guildId, rustplus.serverId, groupName, active); + client, rustplus, rustplus.guildId, rustplus.serverId, groupId, active); return true; } @@ -659,7 +668,7 @@ module.exports = { } } - instance.markers[rustplus.serverId][command] = callerLocation; + instance.serverList[rustplus.serverId].markers[command] = callerLocation; client.writeInstanceFile(rustplus.guildId, instance); rustplus.markers[command] = callerLocation; @@ -672,7 +681,7 @@ module.exports = { if (command in rustplus.markers) { delete rustplus.markers[command]; - delete instance.markers[rustplus.serverId][command]; + delete instance.serverList[rustplus.serverId].markers[command]; client.writeInstanceFile(rustplus.guildId, instance); let str = `Marker '${command}' was removed.`; @@ -1203,7 +1212,7 @@ module.exports = { commandUpkeep: function (rustplus, client) { let instance = client.readInstanceFile(rustplus.guildId); let cupboardFound = false; - for (const [key, value] of Object.entries(instance.storageMonitors)) { + for (const [key, value] of Object.entries(instance.serverList[rustplus.serverId].storageMonitors)) { if (rustplus.serverId !== `${value.serverId}`) continue; if (value.type !== 'toolcupboard') continue; diff --git a/src/handlers/informationHandler.js b/src/handlers/informationHandler.js index 51408fb35..ee06e8e02 100644 --- a/src/handlers/informationHandler.js +++ b/src/handlers/informationHandler.js @@ -1,7 +1,9 @@ -const Timer = require('../util/timer'); -const { EmbedBuilder, AttachmentBuilder } = require('discord.js'); -const DiscordTools = require('../discordTools/discordTools.js'); +const Discord = require('discord.js'); + const Constants = require('../util/constants.js'); +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); +const DiscordTools = require('../discordTools/discordTools.js'); +const Timer = require('../util/timer'); module.exports = { handler: async function (rustplus, client) { @@ -60,16 +62,17 @@ module.exports = { const mapSeed = `${rustplus.info.seed}`; const mapSalt = `${rustplus.info.salt}`; - let files = [new AttachmentBuilder('src/resources/images/server_info_logo.png')]; - let embed = new EmbedBuilder() - .setTitle('Server Information') - .setColor('#ce412b') - .setThumbnail('attachment://server_info_logo.png') - .setDescription(serverName) - .addFields( + let files = [new Discord.AttachmentBuilder('src/resources/images/server_info_logo.png')]; + const embed = DiscordEmbeds.getEmbed({ + title: 'Server Information', + color: '#ce412b', + thumbnail: 'attachment://server_info_logo.png', + description: serverName, + fields: [ { name: 'Players', value: `\`${pop}\``, inline: true }, { name: 'Time', value: `\`${serverTime}\``, inline: true }, - { name: 'Wipe', value: `\`${wipeDay}\``, inline: true }); + { name: 'Wipe', value: `\`${wipeDay}\``, inline: true }] + }); if (timeLeft !== null) { embed.addFields( @@ -283,23 +286,22 @@ module.exports = { } - let files = [new AttachmentBuilder('src/resources/images/event_info_logo.png')]; - let embed = new EmbedBuilder() - .setTitle('Event Information') - .setColor('#ce412b') - .setThumbnail('attachment://event_info_logo.png') - .setDescription('In-game event information') - .addFields( + let files = [new Discord.AttachmentBuilder('src/resources/images/event_info_logo.png')]; + const embed = DiscordEmbeds.getEmbed({ + title: 'Event Information', + color: '#ce412b', + thumbnail: 'attachment://event_info_logo.png', + description: 'In-game event information', + footer: { text: instance.serverList[rustplus.serverId].title }, + fields: [ { name: 'Cargoship', value: `\`${cargoShipMessage}\``, inline: true }, { name: 'Patrol Helicopter', value: `\`${patrolHelicopterMessage}\``, inline: true }, { name: 'Bradley APC', value: `\`${bradleyAPCMessage}\``, inline: true }, { name: 'Small Oil Rig', value: `\`${smallOilMessage}\``, inline: true }, { name: 'Large Oil Rig', value: `\`${largeOilMessage}\``, inline: true }, { name: 'Chinook 47', value: `\`${ch47Message}\``, inline: true }, - { name: 'Crate', value: `\`${crateMessage}\``, inline: true }) - .setFooter({ - text: instance.serverList[rustplus.serverId].title - }); + { name: 'Crate', value: `\`${crateMessage}\``, inline: true }] + }); if (rustplus.informationIntervalCounter === 0) { await sendInformationEmbed(rustplus, client, instance, embed, files, message, 'event'); @@ -331,18 +333,17 @@ module.exports = { } } - let files = [new AttachmentBuilder('src/resources/images/team_info_logo.png')]; - let embed = new EmbedBuilder() - .setTitle('Team Member Information') - .setColor('#ce412b') - .setThumbnail('attachment://team_info_logo.png') - .addFields( + let files = [new Discord.AttachmentBuilder('src/resources/images/team_info_logo.png')]; + const embed = DiscordEmbeds.getEmbed({ + title: 'Team Member Information', + color: '#ce412b', + thumbnail: 'attachment://team_info_logo.png', + footer: { text: instance.serverList[rustplus.serverId].title }, + fields: [ { name: 'Team Member', value: names, inline: true }, { name: 'Status', value: status, inline: true }, - { name: 'Location', value: locations, inline: true }) - .setFooter({ - text: instance.serverList[rustplus.serverId].title - }); + { name: 'Location', value: locations, inline: true }] + }); if (rustplus.informationIntervalCounter === 0) { await sendInformationEmbed(rustplus, client, instance, embed, files, message, 'team'); diff --git a/src/handlers/modalHandler.js b/src/handlers/modalHandler.js new file mode 100644 index 000000000..e6e74be58 --- /dev/null +++ b/src/handlers/modalHandler.js @@ -0,0 +1,227 @@ +const DiscordMessages = require('../discordTools/discordMessages.js'); +const Keywords = require('../util/keywords.js'); + +module.exports = async (client, interaction) => { + const instance = client.readInstanceFile(interaction.guildId); + const guildId = interaction.guildId; + + if (interaction.customId.startsWith('CustomTimersEdit')) { + const ids = JSON.parse(interaction.customId.replace('CustomTimersEdit', '')); + const server = instance.serverList[ids.serverId]; + const cargoShipEgressTime = parseInt(interaction.fields.getTextInputValue('CargoShipEgressTime')); + const bradleyApcRespawnTime = parseInt(interaction.fields.getTextInputValue('BradleyApcRespawnTime')); + const crateDespawnTime = parseInt(interaction.fields.getTextInputValue('CrateDespawnTime')); + const crateDespawnWarningTime = parseInt(interaction.fields.getTextInputValue('CrateDespawnWarningTime')); + const oilRigCrateUnlockTime = parseInt(interaction.fields.getTextInputValue('OilRigCrateUnlockTime')); + + if (!server) { + interaction.deferUpdate(); + return; + } + + if (cargoShipEgressTime && ((cargoShipEgressTime * 1000) !== server.cargoShipEgressTimeMs)) { + server.cargoShipEgressTimeMs = cargoShipEgressTime * 1000; + } + if (bradleyApcRespawnTime && ((bradleyApcRespawnTime * 1000) !== server.bradleyApcRespawnTimeMs)) { + server.bradleyApcRespawnTimeMs = bradleyApcRespawnTime * 1000; + } + + if (crateDespawnTime && ((crateDespawnTime * 1000) !== server.lockedCrateDespawnTimeMs)) { + if (crateDespawnWarningTime && ((crateDespawnWarningTime * 1000) !== + server.lockedCrateDespawnWarningTimeMs)) { + if (crateDespawnTime > crateDespawnWarningTime) { + server.lockedCrateDespawnTimeMs = crateDespawnTime * 1000; + } + } + else { + if ((crateDespawnTime * 1000) > server.lockedCrateDespawnWarningTimeMs) { + server.lockedCrateDespawnTimeMs = crateDespawnTime * 1000; + } + } + } + if (crateDespawnWarningTime && ((crateDespawnWarningTime * 1000) !== server.lockedCrateDespawnWarningTimeMs)) { + if (crateDespawnTime && ((crateDespawnTime * 1000) !== server.lockedCrateDespawnTimeMs)) { + if (crateDespawnWarningTime < crateDespawnTime) { + server.lockedCrateDespawnWarningTimeMs = crateDespawnWarningTime * 1000; + } + } + else { + if ((crateDespawnWarningTime * 1000) < server.lockedCrateDespawnTimeMs) { + server.lockedCrateDespawnWarningTimeMs = crateDespawnWarningTime * 1000; + } + } + } + if (oilRigCrateUnlockTime && ((oilRigCrateUnlockTime * 1000) !== server.oilRigLockedCrateUnlockTimeMs)) { + server.oilRigLockedCrateUnlockTimeMs = oilRigCrateUnlockTime * 1000; + } + client.writeInstanceFile(guildId, instance); + } + else if (interaction.customId.startsWith('SmartSwitchEdit')) { + const ids = JSON.parse(interaction.customId.replace('SmartSwitchEdit', '')); + const server = instance.serverList[ids.serverId]; + const smartSwitchName = interaction.fields.getTextInputValue('SmartSwitchName'); + const smartSwitchCommand = interaction.fields.getTextInputValue('SmartSwitchCommand'); + + if (!server || (server && !server.switches.hasOwnProperty(ids.entityId))) { + interaction.deferUpdate(); + return; + } + + server.switches[ids.entityId].name = smartSwitchName; + + if (smartSwitchCommand !== server.switches[ids.entityId].command && + !Keywords.getListOfUsedKeywords(client, guildId, ids.serverId).includes(smartSwitchCommand)) { + server.switches[ids.entityId].command = smartSwitchCommand; + } + client.writeInstanceFile(guildId, instance); + + await DiscordMessages.sendSmartSwitchMessage(guildId, ids.serverId, ids.entityId); + } + else if (interaction.customId.startsWith('GroupEdit')) { + const ids = JSON.parse(interaction.customId.replace('GroupEdit', '')); + const server = instance.serverList[ids.serverId]; + const groupName = interaction.fields.getTextInputValue('GroupName'); + const groupCommand = interaction.fields.getTextInputValue('GroupCommand'); + + if (!server || (server && !server.switchGroups.hasOwnProperty(ids.groupId))) { + interaction.deferUpdate(); + return; + } + + server.switchGroups[ids.groupId].name = groupName; + + if (groupCommand !== server.switchGroups[ids.groupId].command && + !Keywords.getListOfUsedKeywords(client, interaction.guildId, ids.serverId).includes(groupCommand)) { + server.switchGroups[ids.groupId].command = groupCommand; + } + client.writeInstanceFile(guildId, instance); + + await DiscordMessages.sendSmartSwitchGroupMessage(interaction.guildId, ids.serverId, ids.groupId); + } + else if (interaction.customId.startsWith('GroupAddSwitch')) { + const ids = JSON.parse(interaction.customId.replace('GroupAddSwitch', '')); + const server = instance.serverList[ids.serverId]; + const switchId = interaction.fields.getTextInputValue('GroupAddSwitchId'); + + if (!server || (server && !server.switchGroups.hasOwnProperty(ids.groupId))) { + interaction.deferUpdate(); + return; + } + + if (!Object.keys(server.switches).includes(switchId) || + server.switchGroups[ids.groupId].switches.includes(switchId)) { + interaction.deferUpdate(); + return; + } + + server.switchGroups[ids.groupId].switches.push(switchId); + client.writeInstanceFile(interaction.guildId, instance); + + await DiscordMessages.sendSmartSwitchGroupMessage(interaction.guildId, ids.serverId, ids.groupId); + } + else if (interaction.customId.startsWith('GroupRemoveSwitch')) { + const ids = JSON.parse(interaction.customId.replace('GroupRemoveSwitch', '')); + const server = instance.serverList[ids.serverId]; + const switchId = interaction.fields.getTextInputValue('GroupRemoveSwitchId'); + + if (!server || (server && !server.switchGroups.hasOwnProperty(ids.groupId))) { + interaction.deferUpdate(); + return; + } + + server.switchGroups[ids.groupId].switches = + server.switchGroups[ids.groupId].switches.filter(e => e !== switchId); + client.writeInstanceFile(interaction.guildId, instance); + + await DiscordMessages.sendSmartSwitchGroupMessage(interaction.guildId, ids.serverId, ids.groupId); + } + else if (interaction.customId.startsWith('SmartAlarmEdit')) { + const ids = JSON.parse(interaction.customId.replace('SmartAlarmEdit', '')); + const server = instance.serverList[ids.serverId]; + let smartAlarmName = interaction.fields.getTextInputValue('SmartAlarmName'); + let smartAlarmMessage = interaction.fields.getTextInputValue('SmartAlarmMessage'); + + if (!server || (server && !server.alarms.hasOwnProperty(ids.entityId))) { + interaction.deferUpdate(); + return; + } + + server.alarms[ids.entityId].name = smartAlarmName; + server.alarms[ids.entityId].message = smartAlarmMessage; + client.writeInstanceFile(guildId, instance); + + await DiscordMessages.sendSmartAlarmMessage(interaction.guildId, ids.serverId, ids.entityId); + } + else if (interaction.customId.startsWith('StorageMonitorEdit')) { + const ids = JSON.parse(interaction.customId.replace('StorageMonitorEdit', '')); + const server = instance.serverList[ids.serverId]; + const storageMonitorName = interaction.fields.getTextInputValue('StorageMonitorName'); + + if (!server || (server && !server.storageMonitors.hasOwnProperty(ids.entityId))) { + interaction.deferUpdate(); + return; + } + + server.storageMonitors[ids.entityId].name = storageMonitorName; + client.writeInstanceFile(interaction.guildId, instance); + + await DiscordMessages.sendStorageMonitorMessage(interaction.guildId, ids.serverId, ids.entityId); + } + else if (interaction.customId.startsWith('TrackerEdit')) { + const ids = JSON.parse(interaction.customId.replace('TrackerEdit', '')); + const tracker = instance.trackers[ids.trackerId]; + const trackerName = interaction.fields.getTextInputValue('TrackerName'); + + if (!tracker) { + interaction.deferUpdate(); + return; + } + + tracker.name = trackerName; + client.writeInstanceFile(guildId, instance); + + await DiscordMessages.sendTrackerMessage(interaction.guildId, ids.trackerId); + } + else if (interaction.customId.startsWith('TrackerAddPlayer')) { + const ids = JSON.parse(interaction.customId.replace('TrackerAddPlayer', '')); + const tracker = instance.trackers[ids.trackerId]; + const steamId = interaction.fields.getTextInputValue('TrackerAddPlayerSteamId'); + + if (!tracker) { + interaction.deferUpdate(); + return; + } + + if (tracker.players.some(e => e.steamId === steamId)) { + interaction.deferUpdate(); + return; + } + + tracker.players.push({ + name: '-', steamId: steamId, playerId: null, status: false, time: null + }); + client.writeInstanceFile(interaction.guildId, instance); + + await DiscordMessages.sendTrackerMessage(interaction.guildId, ids.trackerId); + + /* To force search of player name via scrape */ + client.battlemetricsIntervalCounter = 0; + } + else if (interaction.customId.startsWith('TrackerRemovePlayer')) { + const ids = JSON.parse(interaction.customId.replace('TrackerRemovePlayer', '')); + const tracker = instance.trackers[ids.trackerId]; + const steamId = interaction.fields.getTextInputValue('TrackerRemovePlayerSteamId'); + + if (!tracker) { + interaction.deferUpdate(); + return; + } + + tracker.players = tracker.players.filter(e => e.steamId !== steamId); + client.writeInstanceFile(interaction.guildId, instance); + + await DiscordMessages.sendTrackerMessage(interaction.guildId, ids.trackerId); + } + + interaction.deferUpdate(); +} \ No newline at end of file diff --git a/src/handlers/pollingHandler.js b/src/handlers/pollingHandler.js index a320f1aa2..51092e895 100644 --- a/src/handlers/pollingHandler.js +++ b/src/handlers/pollingHandler.js @@ -1,14 +1,13 @@ -const SmartSwitchHandler = require('../handlers/smartSwitchHandler.js'); -const TimeHandler = require('../handlers/timeHandler.js'); -const TeamHandler = require('../handlers/teamHandler.js'); +const Info = require('../structures/Info'); const InformationHandler = require('../handlers/informationHandler.js'); -const StorageMonitorHandler = require('../handlers/storageMonitorHandler.js'); +const MapMarkers = require('../structures/MapMarkers.js'); const SmartAlarmHandler = require('../handlers/smartAlarmHandler.js'); - -const Time = require('../structures/Time'); +const SmartSwitchHandler = require('../handlers/smartSwitchHandler.js'); +const StorageMonitorHandler = require('../handlers/storageMonitorHandler.js'); const Team = require('../structures/Team'); -const Info = require('../structures/Info'); -const MapMarkers = require('../structures/MapMarkers.js'); +const TeamHandler = require('../handlers/teamHandler.js'); +const Time = require('../structures/Time'); +const TimeHandler = require('../handlers/timeHandler.js'); module.exports = { pollingHandler: async function (rustplus, client) { diff --git a/src/handlers/selectMenuHandler.js b/src/handlers/selectMenuHandler.js index 583dcfdbe..73dc854a1 100644 --- a/src/handlers/selectMenuHandler.js +++ b/src/handlers/selectMenuHandler.js @@ -1,23 +1,22 @@ -const DiscordTools = require('../discordTools/discordTools.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); +const DiscordSelectMenus = require('../discordTools/discordSelectMenus.js'); module.exports = async (client, interaction) => { - let guildId = interaction.guildId; - let instance = client.readInstanceFile(guildId); - let rustplus = client.rustplusInstances[guildId]; + const instance = client.readInstanceFile(interaction.guildId); + const guildId = interaction.guildId; + const rustplus = client.rustplusInstances[guildId]; - if (interaction.customId === 'prefix') { + if (interaction.customId === 'Prefix') { instance.generalSettings.prefix = interaction.values[0]; client.writeInstanceFile(guildId, instance); - if (rustplus) { - rustplus.generalSettings.prefix = interaction.values[0]; - } + if (rustplus) rustplus.generalSettings.prefix = interaction.values[0]; - let row = DiscordTools.getPrefixSelectMenu(interaction.values[0]); - - await client.interactionUpdate(interaction, { components: [row] }); + await client.interactionUpdate(interaction, { + components: [DiscordSelectMenus.getPrefixSelectMenu(interaction.values[0])] + }); } - else if (interaction.customId === 'trademark') { + else if (interaction.customId === 'Trademark') { instance.generalSettings.trademark = interaction.values[0]; client.writeInstanceFile(guildId, instance); @@ -27,39 +26,32 @@ module.exports = async (client, interaction) => { '' : `${instance.generalSettings.trademark} | `; } - let row = DiscordTools.getTrademarkSelectMenu(interaction.values[0]); - - await client.interactionUpdate(interaction, { components: [row] }); + await client.interactionUpdate(interaction, { + components: [DiscordSelectMenus.getTrademarkSelectMenu(interaction.values[0])] + }); } - else if (interaction.customId === 'commandDelay') { + else if (interaction.customId === 'CommandDelay') { instance.generalSettings.commandDelay = interaction.values[0]; client.writeInstanceFile(guildId, instance); - if (rustplus) { - rustplus.generalSettings.commandDelay = interaction.values[0]; - } - - let row = DiscordTools.getCommandDelaySelectMenu(interaction.values[0]); + if (rustplus) rustplus.generalSettings.commandDelay = interaction.values[0]; - await client.interactionUpdate(interaction, { components: [row] }); + await client.interactionUpdate(interaction, { + components: [DiscordSelectMenus.getCommandDelaySelectMenu(interaction.values[0])] + }); } - else if (interaction.customId.endsWith('AutoDayNight')) { - let id = interaction.customId.replace('AutoDayNight', ''); + else if (interaction.customId.startsWith('AutoDayNight')) { + const ids = JSON.parse(interaction.customId.replace('AutoDayNight', '')); + const server = instance.serverList[ids.serverId]; - if (!instance.switches.hasOwnProperty(id)) { - try { - await client.switchesMessages[guildId][id].delete(); - } - catch (e) { - client.log('ERROR', `Could not delete switch message for entityId: ${id}.`, 'error'); - } - delete client.switchesMessages[guildId][id]; + if (!server || (server && !server.switches.hasOwnProperty(ids.entityId))) { + await interaction.message.delete(); return; } - instance.switches[id].autoDayNight = parseInt(interaction.values[0]); + server.switches[ids.entityId].autoDayNight = parseInt(interaction.values[0]); client.writeInstanceFile(guildId, instance); - DiscordTools.sendSmartSwitchMessage(guildId, id, false, true, false, interaction); + DiscordMessages.sendSmartSwitchMessage(guildId, ids.serverId, ids.entityId, interaction); } } \ No newline at end of file diff --git a/src/handlers/smartAlarmHandler.js b/src/handlers/smartAlarmHandler.js index ea07b0d5f..ccb79914b 100644 --- a/src/handlers/smartAlarmHandler.js +++ b/src/handlers/smartAlarmHandler.js @@ -1,37 +1,44 @@ -const DiscordTools = require('../discordTools/discordTools.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); module.exports = { handler: async function (rustplus, client) { + let instance = client.readInstanceFile(rustplus.guildId); + const guildId = rustplus.guildId; + const serverId = rustplus.serverId; + + if (!instance.serverList.hasOwnProperty(serverId)) return; + if (rustplus.smartAlarmIntervalCounter === 29) { rustplus.smartAlarmIntervalCounter = 0; - let instance = client.readInstanceFile(rustplus.guildId); - for (const [key, value] of Object.entries(instance.alarms)) { - if (rustplus.serverId !== `${value.serverId}`) continue; - instance = client.readInstanceFile(rustplus.guildId); + } + else { + rustplus.smartAlarmIntervalCounter += 1; + } + + if (rustplus.smartAlarmIntervalCounter === 0) { + for (const entityId in instance.serverList[serverId].alarms) { + instance = client.readInstanceFile(guildId); - let info = await rustplus.getEntityInfoAsync(key); + const info = await rustplus.getEntityInfoAsync(entityId); if (!(await rustplus.isResponseValid(info))) { - if (instance.alarms[key].reachable) { - await DiscordTools.sendSmartAlarmNotFound(rustplus.guildId, key); + if (instance.serverList[serverId].alarms[entityId].reachable) { + await DiscordMessages.sendSmartAlarmNotFoundMessage(guildId, serverId, entityId); - instance.alarms[key].reachable = false; - client.writeInstanceFile(rustplus.guildId, instance); + instance.serverList[serverId].alarms[entityId].reachable = false; + client.writeInstanceFile(guildId, instance); - await DiscordTools.sendSmartAlarmMessage(rustplus.guildId, key, true, false, false); + await DiscordMessages.sendSmartAlarmMessage(guildId, serverId, entityId); } } else { - if (!instance.alarms[key].reachable) { - instance.alarms[key].reachable = true; - client.writeInstanceFile(rustplus.guildId, instance); + if (!instance.serverList[serverId].alarms[entityId].reachable) { + instance.serverList[serverId].alarms[entityId].reachable = true; + client.writeInstanceFile(guildId, instance); - await DiscordTools.sendSmartAlarmMessage(rustplus.guildId, key, true, false, false); + await DiscordMessages.sendSmartAlarmMessage(guildId, serverId, entityId); } } } } - else { - rustplus.smartAlarmIntervalCounter += 1; - } }, } \ No newline at end of file diff --git a/src/handlers/smartSwitchGroupHandler.js b/src/handlers/smartSwitchGroupHandler.js index c5832e853..d89926ead 100644 --- a/src/handlers/smartSwitchGroupHandler.js +++ b/src/handlers/smartSwitchGroupHandler.js @@ -1,92 +1,80 @@ -const DiscordTools = require('../discordTools/discordTools.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); module.exports = { handler: async function (rustplus, client) { }, updateSwitchGroupIfContainSwitch: async function (client, guildId, serverId, switchId) { - let instance = client.readInstanceFile(guildId); + const instance = client.readInstanceFile(guildId); - for (const [groupName, content] of Object.entries(instance.serverList[serverId].switchGroups)) { + for (const [groupId, content] of Object.entries(instance.serverList[serverId].switchGroups)) { if (content.switches.includes(`${switchId}`)) { - await DiscordTools.sendSmartSwitchGroupMessage(guildId, groupName, true, false, false); + await DiscordMessages.sendSmartSwitchGroupMessage(guildId, serverId, groupId); } } }, getGroupsFromSwitchList: function (client, guildId, serverId, switches) { - let instance = client.readInstanceFile(guildId); + const instance = client.readInstanceFile(guildId); - let groups = []; - for (let sw of switches) { - for (const [groupName, content] of Object.entries(instance.serverList[serverId].switchGroups)) { - if (content.switches.includes(sw) && !groups.includes(groupName)) { - groups.push(groupName); + let groupsId = []; + for (let entity of switches) { + for (const [groupId, content] of Object.entries(instance.serverList[serverId].switchGroups)) { + if (content.switches.includes(entity) && !groupsId.includes(groupId)) { + groupsId.push(groupId); } } } - return groups; + return groupsId; }, - TurnOnOffGroup: async function (client, rustplus, guildId, serverId, group, value) { - let instance = client.readInstanceFile(guildId); + TurnOnOffGroup: async function (client, rustplus, guildId, serverId, groupId, value) { + const instance = client.readInstanceFile(guildId); - let switches = instance.serverList[serverId].switchGroups[group].switches; + const switches = instance.serverList[serverId].switchGroups[groupId].switches; - let actionSwitches = []; - for (const [id, content] of Object.entries(instance.switches)) { - if (switches.includes(id)) { - if (value) { - if (!content.active) { - actionSwitches.push(id); - } + const actionSwitches = []; + for (const [entityId, content] of Object.entries(instance.serverList[serverId].switches)) { + if (switches.includes(entityId)) { + if (value && !content.active) { + actionSwitches.push(entityId); } - else { - if (content.active) { - actionSwitches.push(id); - - } + else if (!value && content.active) { + actionSwitches.push(entityId); } } } - for (let id of actionSwitches) { - let prevActive = instance.switches[id].active; - instance.switches[id].active = value; + for (const entityId of actionSwitches) { + const prevActive = instance.serverList[serverId].switches[entityId].active; + instance.serverList[serverId].switches[entityId].active = value; client.writeInstanceFile(guildId, instance); - rustplus.interactionSwitches.push(id); - - let response = null; - if (value) { - response = await rustplus.turnSmartSwitchOnAsync(id); - } - else { - response = await rustplus.turnSmartSwitchOffAsync(id); - } + rustplus.interactionSwitches.push(entityId); + const response = await rustplus.turnSmartSwitchAsync(entityId, value); if (!(await rustplus.isResponseValid(response))) { - if (instance.switches[id].reachable) { - await DiscordTools.sendSmartSwitchNotFound(rustplus.guildId, id); + if (instance.serverList[serverId].switches[entityId].reachable) { + await DiscordMessages.sendSmartSwitchNotFoundMessage(guildId, serverId, entityId); } - instance.switches[id].reachable = false; - instance.switches[id].active = prevActive; - client.writeInstanceFile(rustplus.guildId, instance); + instance.serverList[serverId].switches[entityId].reachable = false; + instance.serverList[serverId].switches[entityId].active = prevActive; + client.writeInstanceFile(guildId, instance); - rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== id); + rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== entityId); } else { - instance.switches[id].reachable = true; - client.writeInstanceFile(rustplus.guildId, instance); + instance.serverList[serverId].switches[entityId].reachable = true; + client.writeInstanceFile(guildId, instance); } - DiscordTools.sendSmartSwitchMessage(guildId, id, true, true, false); + DiscordMessages.sendSmartSwitchMessage(guildId, serverId, entityId); } if (actionSwitches.length !== 0) { - await DiscordTools.sendSmartSwitchGroupMessage(guildId, group, true, false, false); + await DiscordMessages.sendSmartSwitchGroupMessage(guildId, serverId, groupId); } }, } \ No newline at end of file diff --git a/src/handlers/smartSwitchHandler.js b/src/handlers/smartSwitchHandler.js index 5fdeb0bf1..cb1467cbd 100644 --- a/src/handlers/smartSwitchHandler.js +++ b/src/handlers/smartSwitchHandler.js @@ -1,159 +1,161 @@ -const DiscordTools = require('../discordTools/discordTools.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); const SmartSwitchGroupHandler = require('./smartSwitchGroupHandler.js'); module.exports = { handler: async function (rustplus, client, time) { let instance = client.readInstanceFile(rustplus.guildId); + const guildId = rustplus.guildId; + const serverId = rustplus.serverId; + + if (!instance.serverList.hasOwnProperty(serverId)) return; - let changedSwitches = []; if (rustplus.smartSwitchIntervalCounter === 29) { rustplus.smartSwitchIntervalCounter = 0; - for (const [key, value] of Object.entries(instance.switches)) { - if (rustplus.serverId !== `${value.serverId}`) continue; - instance = client.readInstanceFile(rustplus.guildId); + } + else { + rustplus.smartSwitchIntervalCounter += 1; + } - let info = await rustplus.getEntityInfoAsync(key); + /* Go through all Smart Switches and see if some of them do not answer on request. */ + const changedSwitches = []; + if (rustplus.smartSwitchIntervalCounter === 0) { + for (const entityId in instance.serverList[serverId].switches) { + instance = client.readInstanceFile(guildId); + + const info = await rustplus.getEntityInfoAsync(entityId); if (!(await rustplus.isResponseValid(info))) { - if (instance.switches[key].reachable) { - await DiscordTools.sendSmartSwitchNotFound(rustplus.guildId, key); - instance.switches[key].reachable = false; - client.writeInstanceFile(rustplus.guildId, instance); + if (instance.serverList[serverId].switches[entityId].reachable) { + await DiscordMessages.sendSmartSwitchNotFoundMessage(guildId, serverId, entityId); + instance.serverList[serverId].switches[entityId].reachable = false; + client.writeInstanceFile(guildId, instance); - await DiscordTools.sendSmartSwitchMessage(rustplus.guildId, key, true, true, false); - changedSwitches.push(key); + await DiscordMessages.sendSmartSwitchMessage(guildId, serverId, entityId); + changedSwitches.push(entityId); } } else { - if (!instance.switches[key].reachable) { - instance.switches[key].reachable = true; - client.writeInstanceFile(rustplus.guildId, instance); + if (!instance.serverList[serverId].switches[entityId].reachable) { + instance.serverList[serverId].switches[entityId].reachable = true; + client.writeInstanceFile(guildId, instance); - await DiscordTools.sendSmartSwitchMessage(rustplus.guildId, key, true, true, false); - changedSwitches.push(key); + await DiscordMessages.sendSmartSwitchMessage(guildId, serverId, entityId); + changedSwitches.push(entityId); } } } } - else { - rustplus.smartSwitchIntervalCounter += 1; - } + /* Go through all Smart Switches and see if the auto day/night setting is on and if it just became day/night */ if (rustplus.time.isTurnedDay(time)) { - for (const [key, value] of Object.entries(instance.switches)) { - if (rustplus.serverId !== `${value.serverId}`) continue; - instance = client.readInstanceFile(rustplus.guildId); + for (const [entityId, content] of Object.entries(instance.serverList[serverId].switches)) { + instance = client.readInstanceFile(guildId); - if (value.autoDayNight === 1) { - instance.switches[key].active = true; - client.writeInstanceFile(rustplus.guildId, instance); + if (content.autoDayNight === 1) { + instance.serverList[serverId].switches[entityId].active = true; + client.writeInstanceFile(guildId, instance); - rustplus.interactionSwitches.push(key); + rustplus.interactionSwitches.push(entityId); - let response = await rustplus.turnSmartSwitchOnAsync(key); + const response = await rustplus.turnSmartSwitchOnAsync(entityId); if (!(await rustplus.isResponseValid(response))) { - if (instance.switches[key].reachable) { - await DiscordTools.sendSmartSwitchNotFound(rustplus.guildId, key); + if (instance.serverList[serverId].switches[entityId].reachable) { + await DiscordMessages.sendSmartSwitchNotFoundMessage(guildId, serverId, entityId); } - instance.switches[key].reachable = false; - client.writeInstanceFile(rustplus.guildId, instance); + instance.serverList[serverId].switches[entityId].reachable = false; - rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== key); + rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== entityId); } else { - instance.switches[key].reachable = true; - client.writeInstanceFile(rustplus.guildId, instance); + instance.serverList[serverId].switches[entityId].reachable = true; } + client.writeInstanceFile(guildId, instance); - DiscordTools.sendSmartSwitchMessage(rustplus.guildId, key, true, true, false); - changedSwitches.push(key); + DiscordMessages.sendSmartSwitchMessage(guildId, serverId, entityId); + changedSwitches.push(entityId); } - else if (value.autoDayNight === 2) { - instance.switches[key].active = false; - client.writeInstanceFile(rustplus.guildId, instance); + else if (content.autoDayNight === 2) { + instance.serverList[serverId].switches[entityId].active = false; + client.writeInstanceFile(guildId, instance); - rustplus.interactionSwitches.push(key); + rustplus.interactionSwitches.push(entityId); - let response = await rustplus.turnSmartSwitchOffAsync(key); + const response = await rustplus.turnSmartSwitchOffAsync(entityId); if (!(await rustplus.isResponseValid(response))) { - if (instance.switches[key].reachable) { - await DiscordTools.sendSmartSwitchNotFound(rustplus.guildId, key); + if (instance.serverList[serverId].switches[entityId].reachable) { + await DiscordMessages.sendSmartSwitchNotFoundMessage(guildId, serverId, entityId); } - instance.switches[key].reachable = false; - client.writeInstanceFile(rustplus.guildId, instance); + instance.serverList[serverId].switches[entityId].reachable = false; - rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== key); + rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== entityId); } else { - instance.switches[key].reachable = true; - client.writeInstanceFile(rustplus.guildId, instance); + instance.serverList[serverId].switches[entityId].reachable = true; } + client.writeInstanceFile(guildId, instance); - DiscordTools.sendSmartSwitchMessage(rustplus.guildId, key, true, true, false); - changedSwitches.push(key); + DiscordMessages.sendSmartSwitchMessage(guildId, serverId, entityId); + changedSwitches.push(entityId); } } } else if (rustplus.time.isTurnedNight(time)) { - for (const [key, value] of Object.entries(instance.switches)) { - if (rustplus.serverId !== `${value.serverId}`) continue; - instance = client.readInstanceFile(rustplus.guildId); + for (const [entityId, content] of Object.entries(instance.serverList[serverId].switches)) { + instance = client.readInstanceFile(guildId); - if (value.autoDayNight === 1) { - instance.switches[key].active = false; - client.writeInstanceFile(rustplus.guildId, instance); + if (content.autoDayNight === 1) { + instance.serverList[serverId].switches[entityId].active = false; + client.writeInstanceFile(guildId, instance); - rustplus.interactionSwitches.push(key); + rustplus.interactionSwitches.push(entityId); - let response = await rustplus.turnSmartSwitchOffAsync(key); + const response = await rustplus.turnSmartSwitchOffAsync(entityId); if (!(await rustplus.isResponseValid(response))) { - if (instance.switches[key].reachable) { - await DiscordTools.sendSmartSwitchNotFound(rustplus.guildId, key); + if (instance.serverList[serverId].switches[entityId].reachable) { + await DiscordMessages.sendSmartSwitchNotFoundMessage(guildId, serverId, entityId); } - instance.switches[key].reachable = false; - client.writeInstanceFile(rustplus.guildId, instance); + instance.serverList[serverId].switches[entityId].reachable = false; - rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== key); + rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== entityId); } else { - instance.switches[key].reachable = true; - client.writeInstanceFile(rustplus.guildId, instance); + instance.serverList[serverId].switches[entityId].reachable = true; } + client.writeInstanceFile(guildId, instance); - DiscordTools.sendSmartSwitchMessage(rustplus.guildId, key, true, true, false); - changedSwitches.push(key); + DiscordMessages.sendSmartSwitchMessage(guildId, serverId, entityId); + changedSwitches.push(entityId); } - else if (value.autoDayNight === 2) { - instance.switches[key].active = true; - client.writeInstanceFile(rustplus.guildId, instance); + else if (content.autoDayNight === 2) { + instance.serverList[serverId].switches[entityId].active = true; + client.writeInstanceFile(guildId, instance); - rustplus.interactionSwitches.push(key); + rustplus.interactionSwitches.push(entityId); - let response = await rustplus.turnSmartSwitchOnAsync(key); + const response = await rustplus.turnSmartSwitchOnAsync(entityId); if (!(await rustplus.isResponseValid(response))) { - if (instance.switches[key].reachable) { - await DiscordTools.sendSmartSwitchNotFound(rustplus.guildId, key); + if (instance.serverList[serverId].switches[entityId].reachable) { + await DiscordMessages.sendSmartSwitchNotFoundMessage(guildId, serverId, entityId); } - instance.switches[key].reachable = false; - client.writeInstanceFile(rustplus.guildId, instance); + instance.serverList[serverId].switches[entityId].reachable = false; - rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== key); + rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== entityId); } else { - instance.switches[key].reachable = true; - client.writeInstanceFile(rustplus.guildId, instance); + instance.serverList[serverId].switches[entityId].reachable = true; } + client.writeInstanceFile(guildId, instance); - DiscordTools.sendSmartSwitchMessage(rustplus.guildId, key, true, true, false); - changedSwitches.push(key); + DiscordMessages.sendSmartSwitchMessage(guildId, serverId, entityId); + changedSwitches.push(entityId); } } } - let groups = SmartSwitchGroupHandler.getGroupsFromSwitchList( - client, rustplus.guildId, rustplus.serverId, changedSwitches); + let groupsId = SmartSwitchGroupHandler.getGroupsFromSwitchList( + client, guildId, serverId, changedSwitches); - for (let group of groups) { - await DiscordTools.sendSmartSwitchGroupMessage(rustplus.guildId, group); + for (let groupId of groupsId) { + await DiscordMessages.sendSmartSwitchGroupMessage(guildId, serverId, groupId); } }, } \ No newline at end of file diff --git a/src/handlers/storageMonitorHandler.js b/src/handlers/storageMonitorHandler.js index 9cf9de89f..bfe9a8dbe 100644 --- a/src/handlers/storageMonitorHandler.js +++ b/src/handlers/storageMonitorHandler.js @@ -1,71 +1,81 @@ -const DiscordTools = require('../discordTools/discordTools.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); module.exports = { handler: async function (rustplus, client) { + let instance = client.readInstanceFile(rustplus.guildId); + const guildId = rustplus.guildId; + const serverId = rustplus.serverId; + + if (!instance.serverList.hasOwnProperty(serverId)) return; + if (rustplus.storageMonitorIntervalCounter === 29) { rustplus.storageMonitorIntervalCounter = 0; } else { rustplus.storageMonitorIntervalCounter += 1; - return; } - let instance = client.readInstanceFile(rustplus.guildId); - for (const [id, content] of Object.entries(instance.storageMonitors)) { - if (rustplus.serverId !== content.serverId) continue; - instance = client.readInstanceFile(rustplus.guildId); + if (rustplus.storageMonitorIntervalCounter === 0) { + let instance = client.readInstanceFile(guildId); + for (const entityId in instance.serverList[serverId].storageMonitors) { + instance = client.readInstanceFile(guildId); - let info = await rustplus.getEntityInfoAsync(id); - if (!(await rustplus.isResponseValid(info))) { - if (instance.storageMonitors[id].reachable) { - await DiscordTools.sendStorageMonitorNotFound(rustplus.guildId, id); + const info = await rustplus.getEntityInfoAsync(entityId); + if (!(await rustplus.isResponseValid(info))) { + if (instance.serverList[serverId].storageMonitors[entityId].reachable) { + await DiscordMessages.sendStorageMonitorNotFoundMessage(guildId, serverId, entityId); + } + instance.serverList[serverId].storageMonitors[entityId].reachable = false; } - instance.storageMonitors[id].reachable = false; - client.writeInstanceFile(rustplus.guildId, instance); - } - else { - instance.storageMonitors[id].reachable = true; - client.writeInstanceFile(rustplus.guildId, instance); - } - - if (instance.storageMonitors[id].reachable) { - if (rustplus.storageMonitors.hasOwnProperty(id) && (rustplus.storageMonitors[id].capacity !== 0 && - info.entityInfo.payload.capacity === 0)) { - await DiscordTools.sendStorageMonitorDisconnectNotification(rustplus.guildId, id); + else { + instance.serverList[serverId].storageMonitors[entityId].reachable = true; } + client.writeInstanceFile(guildId, instance); - rustplus.storageMonitors[id] = { - items: info.entityInfo.payload.items, - expiry: info.entityInfo.payload.protectionExpiry, - capacity: info.entityInfo.payload.capacity, - hasProtection: info.entityInfo.payload.hasProtection - } + if (instance.serverList[serverId].storageMonitors[entityId].reachable) { + if (rustplus.storageMonitors.hasOwnProperty(entityId) && + (rustplus.storageMonitors[entityId].capacity !== 0 && + info.entityInfo.payload.capacity === 0)) { + await DiscordMessages.sendStorageMonitorDisconnectNotificationMessage( + guildId, serverId, entityId); + } + + rustplus.storageMonitors[entityId] = { + items: info.entityInfo.payload.items, + expiry: info.entityInfo.payload.protectionExpiry, + capacity: info.entityInfo.payload.capacity, + hasProtection: info.entityInfo.payload.hasProtection + } - if (info.entityInfo.payload.capacity !== 0) { - if (info.entityInfo.payload.capacity === 28) { - instance.storageMonitors[id].type = 'toolcupboard'; - if (info.entityInfo.payload.protectionExpiry === 0 && - instance.storageMonitors[id].decaying === false) { - instance.storageMonitors[id].decaying = true; + if (info.entityInfo.payload.capacity !== 0) { + if (info.entityInfo.payload.capacity === 28) { + instance.serverList[serverId].storageMonitors[entityId].type = 'toolcupboard'; + if (info.entityInfo.payload.protectionExpiry === 0 && + instance.serverList[serverId].storageMonitors[entityId].decaying === false) { + instance.serverList[serverId].storageMonitors[entityId].decaying = true; - await DiscordTools.sendDecayingNotification(rustplus.guildId, id); + await DiscordMessages.sendDecayingNotificationMessage( + guildId, serverId, entityId); - if (instance.storageMonitors[id].inGame) { - rustplus.sendTeamMessageAsync(`${instance.storageMonitors[id].name} is decaying!`); + if (instance.serverList[serverId].storageMonitors[entityId].inGame) { + rustplus.sendTeamMessageAsync( + `${instance.serverList[serverId].storageMonitors[entityId].name}` + + ` is decaying!`); + } + } + else if (info.entityInfo.payload.protectionExpiry !== 0) { + instance.serverList[serverId].storageMonitors[entityId].decaying = false; } } - else if (info.entityInfo.payload.protectionExpiry !== 0) { - instance.storageMonitors[id].decaying = false; + else { + instance.serverList[serverId].storageMonitors[entityId].type = 'container'; } + client.writeInstanceFile(guildId, instance); } - else { - instance.storageMonitors[id].type = 'container'; - } - client.writeInstanceFile(rustplus.guildId, instance); } - } - await DiscordTools.sendStorageMonitorMessage(rustplus.guildId, id, true, false, false); + await DiscordMessages.sendStorageMonitorMessage(guildId, serverId, entityId); + } } }, } \ No newline at end of file diff --git a/src/handlers/teamChatHandler.js b/src/handlers/teamChatHandler.js index 878b25e38..d2bca46a5 100644 --- a/src/handlers/teamChatHandler.js +++ b/src/handlers/teamChatHandler.js @@ -1,15 +1,15 @@ - +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); const DiscordTools = require('../discordTools/discordTools.js'); -const { EmbedBuilder } = require("discord.js"); module.exports = async function (rustplus, client, message) { let instance = client.readInstanceFile(rustplus.guildId); let channel = DiscordTools.getTextChannelById(rustplus.guildId, instance.channelId.teamchat); if (channel !== undefined) { - let embed = new EmbedBuilder() - .setColor(message.color) - .setDescription(`**${message.name}**: ${message.message}`) + const embed = DiscordEmbeds.getEmbed({ + color: message.color, + description: `**${message.name}**: ${message.message}` + }); await client.messageSend(channel, { embeds: [embed] }); } diff --git a/src/handlers/teamHandler.js b/src/handlers/teamHandler.js index 2a8e2625c..f4e712d51 100644 --- a/src/handlers/teamHandler.js +++ b/src/handlers/teamHandler.js @@ -1,7 +1,7 @@ +const Constants = require('../util/constants.js'); +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); const DiscordTools = require('../discordTools/discordTools.js'); -const { EmbedBuilder } = require('discord.js'); const Scrape = require('../util/scrape.js'); -const Constants = require('../util/constants.js'); module.exports = { handler: async function (rustplus, client, teamInfo) { @@ -27,16 +27,16 @@ module.exports = { let player = rustplus.team.getPlayer(steamId); let png = await Scrape.scrapeSteamProfilePicture(client, steamId); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#606060') - .setAuthor({ + embeds: [DiscordEmbeds.getEmbed({ + color: '#606060', + timestamp: true, + footer: { text: instance.serverList[rustplus.serverId].title }, + author: { name: `${player.name} left the team.`, iconURL: (png !== null) ? png : Constants.DEFAULT_SERVER_IMG, url: `${Constants.STEAM_PROFILES_URL}${steamId}` - }) - .setTimestamp() - .setFooter({ text: instance.serverList[rustplus.serverId].title }) - ] + } + })] }); if (instance.generalSettings.connectionNotify) { @@ -51,16 +51,16 @@ module.exports = { if (player.steamId.toString() === steamId) { let png = await Scrape.scrapeSteamProfilePicture(client, steamId); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#00ff40') - .setAuthor({ + embeds: [DiscordEmbeds.getEmbed({ + color: '#00ff40', + timestamp: true, + footer: { text: instance.serverList[rustplus.serverId].title }, + author: { name: `${player.name} joined the team.`, iconURL: (png !== null) ? png : Constants.DEFAULT_SERVER_IMG, url: `${Constants.STEAM_PROFILES_URL}${steamId}` - }) - .setTimestamp() - .setFooter({ text: instance.serverList[rustplus.serverId].title }) - ] + } + })] }); if (instance.generalSettings.connectionNotify) { @@ -83,16 +83,16 @@ module.exports = { let pos = player.pos; let png = await Scrape.scrapeSteamProfilePicture(client, player.steamId); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setAuthor({ + embeds: [DiscordEmbeds.getEmbed({ + color: '#ff0040', + timestamp: true, + footer: { text: instance.serverList[rustplus.serverId].title }, + author: { name: `${player.name} just died at ${pos}.`, iconURL: (png !== null) ? png : Constants.DEFAULT_SERVER_IMG, url: `${Constants.STEAM_PROFILES_URL}${player.steamId}` - }) - .setTimestamp() - .setFooter({ text: instance.serverList[rustplus.serverId].title }) - ] + } + })] }); if (instance.generalSettings.deathNotify) { @@ -120,16 +120,16 @@ module.exports = { if (player.isGoneOnline(playerUpdated)) { let png = await Scrape.scrapeSteamProfilePicture(client, player.steamId); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#00ff40') - .setAuthor({ + embeds: [DiscordEmbeds.getEmbed({ + color: '#00ff40', + timestamp: true, + footer: { text: instance.serverList[rustplus.serverId].title }, + author: { name: `${player.name} just connected.`, iconURL: (png !== null) ? png : Constants.DEFAULT_SERVER_IMG, url: `${Constants.STEAM_PROFILES_URL}${player.steamId}` - }) - .setTimestamp() - .setFooter({ text: instance.serverList[rustplus.serverId].title }) - ] + } + })] }); if (instance.generalSettings.connectionNotify) { @@ -143,16 +143,16 @@ module.exports = { if (player.isGoneOffline(playerUpdated)) { let png = await Scrape.scrapeSteamProfilePicture(client, player.steamId); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setAuthor({ + embeds: [DiscordEmbeds.getEmbed({ + color: '#ff0040', + timestamp: true, + footer: { text: instance.serverList[rustplus.serverId].title }, + author: { name: `${player.name} just disconnected.`, iconURL: (png !== null) ? png : Constants.DEFAULT_SERVER_IMG, url: `${Constants.STEAM_PROFILES_URL}${player.steamId}` - }) - .setTimestamp() - .setFooter({ text: instance.serverList[rustplus.serverId].title }) - ] + } + })] }); if (instance.generalSettings.connectionNotify) { diff --git a/src/rustplusEvents/connected.js b/src/rustplusEvents/connected.js index e6bb4d76c..542ae93b3 100644 --- a/src/rustplusEvents/connected.js +++ b/src/rustplusEvents/connected.js @@ -1,9 +1,11 @@ -const PollingHandler = require('../handlers/pollingHandler.js'); -const DiscordTools = require('../discordTools/discordTools.js'); -const { EmbedBuilder, AttachmentBuilder } = require('discord.js'); +const Discord = require('discord.js'); -const Map = require('../structures/Map'); +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); +const DiscordTools = require('../discordTools/discordTools.js'); const Info = require('../structures/Info'); +const Map = require('../structures/Map'); +const PollingHandler = require('../handlers/pollingHandler.js'); module.exports = { name: 'connected', @@ -22,20 +24,20 @@ module.exports = { if (channel !== undefined) { await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setTitle('The connection to the server seems to be invalid. Try to re-pair to the server.') - .setThumbnail(instance.serverList[rustplus.serverId].img) - .setTimestamp() - .setFooter({ text: instance.serverList[rustplus.serverId].title }) - ] + embeds: [DiscordEmbeds.getEmbed({ + color: '#ff0040', + title: 'The connection to the server seems to be invalid. Try to re-pair to the server.', + thumbnail: instance.serverList[rustplus.serverId].img, + timestamp: true, + footer: { text: instance.serverList[rustplus.serverId].title } + })] }); } instance.serverList[rustplus.serverId].active = false; client.writeInstanceFile(rustplus.guildId, instance); - await DiscordTools.sendServerMessage(rustplus.guildId, rustplus.serverId, null, false, true); + await DiscordMessages.sendServerMessage(rustplus.guildId, rustplus.serverId, null); rustplus.disconnect(); delete client.rustplusInstances[rustplus.guildId]; @@ -63,7 +65,7 @@ module.exports = { message = await DiscordTools.getMessageById(rustplus.guildId, instance.channelId.information, messageId); } - let mapFile = new AttachmentBuilder(`src/resources/images/maps/${rustplus.guildId}_map_full.png`); + let mapFile = new Discord.AttachmentBuilder(`src/resources/images/maps/${rustplus.guildId}_map_full.png`); if (message === undefined) { let infoChannel = DiscordTools.getTextChannelById(rustplus.guildId, instance.channelId.information); @@ -86,15 +88,15 @@ module.exports = { if (isWipe) { if (channel !== undefined) { - let file = new AttachmentBuilder(`src/resources/images/maps/${rustplus.guildId}_map_full.png`); + let file = new Discord.AttachmentBuilder(`src/resources/images/maps/${rustplus.guildId}_map_full.png`); await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#ce412b') - .setTitle('Wipe detected!') - .setImage(`attachment://${rustplus.guildId}_map_full.png`) - .setTimestamp() - .setFooter({ text: instance.serverList[rustplus.serverId].title }) - ], + embeds: [DiscordEmbeds.getEmbed({ + color: '#ce412b', + title: 'Wipe detected!', + image: `attachment://${rustplus.guildId}_map_full.png`, + timestamp: true, + footer: { text: instance.serverList[rustplus.serverId].title } + })], files: [file] }); } @@ -106,28 +108,29 @@ module.exports = { if (rustplus.isReconnect) { if (channel !== undefined) { await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#00ff40') - .setTitle('Server just went online.') - .setThumbnail(instance.serverList[rustplus.serverId].img) - .setTimestamp() - .setFooter({ text: instance.serverList[rustplus.serverId].title }) - ] + embeds: [DiscordEmbeds.getEmbed({ + color: '#00ff40', + title: 'Server just went online.', + thumbnail: instance.serverList[rustplus.serverId].img, + timestamp: true, + footer: { text: instance.serverList[rustplus.serverId].title } + })] }); } } - await DiscordTools.sendServerMessage(rustplus.guildId, rustplus.serverId, null, false, true); + await DiscordMessages.sendServerMessage(rustplus.guildId, rustplus.serverId, null); rustplus.connected = true; rustplus.isReconnect = false; rustplus.refusedConnectionRetry = false; } - await require('../discordTools/SetupSwitches')(client, rustplus); + await require('../discordTools/SetupSwitches')(client, rustplus, rustplus.newConnection); await require('../discordTools/SetupSwitchGroups')(client, rustplus); await require('../discordTools/SetupAlarms')(client, rustplus); - await require('../discordTools/SetupStorageMonitors')(client, rustplus); + await require('../discordTools/SetupStorageMonitors')(client, rustplus, rustplus.newConnection); + rustplus.newConnection = false; rustplus.loadMarkers(); /* Run the first time before starting the interval */ diff --git a/src/rustplusEvents/disconnected.js b/src/rustplusEvents/disconnected.js index 4c9967b5c..6af7ec043 100644 --- a/src/rustplusEvents/disconnected.js +++ b/src/rustplusEvents/disconnected.js @@ -1,5 +1,6 @@ +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); const DiscordTools = require('../discordTools/discordTools.js'); -const { EmbedBuilder } = require('discord.js'); module.exports = { name: 'disconnected', @@ -44,19 +45,17 @@ module.exports = { let channel = DiscordTools.getTextChannelById(rustplus.guildId, channelIdActivity); if (channel !== undefined) { await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setTitle('Server just went offline.') - .setThumbnail(instance.serverList[rustplus.serverId].img) - .setTimestamp() - .setFooter({ - text: instance.serverList[rustplus.serverId].title - }) - ] + embeds: [DiscordEmbeds.getEmbed({ + color: '#ff0040', + title: 'Server just went offline.', + thumbnail: instance.serverList[rustplus.serverId].img, + timestamp: true, + footer: { text: instance.serverList[rustplus.serverId].title } + })] }); } - await DiscordTools.sendServerMessage(rustplus.guildId, rustplus.serverId, 2, false, true); + await DiscordMessages.sendServerMessage(rustplus.guildId, rustplus.serverId, 2); rustplus.firstTime = false; rustplus.connected = false; diff --git a/src/rustplusEvents/error.js b/src/rustplusEvents/error.js index 4c6c78d4f..003193e40 100644 --- a/src/rustplusEvents/error.js +++ b/src/rustplusEvents/error.js @@ -1,5 +1,6 @@ +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); const DiscordTools = require('../discordTools/discordTools.js'); -const { EmbedBuilder } = require('discord.js'); module.exports = { name: 'error', @@ -21,17 +22,17 @@ module.exports = { let channel = DiscordTools.getTextChannelById(rustplus.guildId, channelIdActivity); if (channel !== undefined) { await client.messageSend(channel, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setTitle('Server just went offline.') - .setThumbnail(instance.serverList[rustplus.serverId].img) - .setTimestamp() - .setFooter({ text: instance.serverList[rustplus.serverId].title }) - ] + embeds: [DiscordEmbeds.getEmbed({ + color: '#ff0040', + title: 'Server just went offline.', + thumbnail: instance.serverList[rustplus.serverId].img, + timestamp: true, + footer: { text: instance.serverList[rustplus.serverId].title } + })] }); } - await DiscordTools.sendServerMessage(rustplus.guildId, rustplus.serverId, 2, false, true); + await DiscordMessages.sendServerMessage(rustplus.guildId, rustplus.serverId, 2); rustplus.firstTime = false; rustplus.connected = false; diff --git a/src/rustplusEvents/message.js b/src/rustplusEvents/message.js index a7d4fc412..d38a64fd5 100644 --- a/src/rustplusEvents/message.js +++ b/src/rustplusEvents/message.js @@ -1,9 +1,12 @@ +const Discord = require('discord.js'); + const CommandHandler = require('../handlers/inGameCommandHandler.js'); -const TeamChatHandler = require("../handlers/teamChatHandler.js"); +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); const DiscordTools = require('../discordTools/discordTools.js'); -const TeamHandler = require('../handlers/teamHandler.js'); -const { EmbedBuilder, AttachmentBuilder } = require('discord.js'); const SmartSwitchGroupHandler = require('../handlers/smartSwitchGroupHandler.js'); +const TeamChatHandler = require("../handlers/teamChatHandler.js"); +const TeamHandler = require('../handlers/teamHandler.js'); module.exports = { name: 'message', @@ -35,7 +38,7 @@ module.exports = { else if (message.broadcast.hasOwnProperty('entityChanged')) { let entityId = message.broadcast.entityChanged.entityId; - if (instance.switches.hasOwnProperty(entityId)) { + if (instance.serverList[rustplus.serverId].switches.hasOwnProperty(entityId)) { if (rustplus.currentSwitchTimeouts.hasOwnProperty(entityId)) { clearTimeout(rustplus.currentSwitchTimeouts[entityId]); delete rustplus.currentSwitchTimeouts[entityId]; @@ -46,42 +49,42 @@ module.exports = { } else { let active = message.broadcast.entityChanged.payload.value; - instance.switches[entityId].active = active; + instance.serverList[rustplus.serverId].switches[entityId].active = active; client.writeInstanceFile(rustplus.guildId, instance); - DiscordTools.sendSmartSwitchMessage(rustplus.guildId, entityId, true, true, false); + DiscordMessages.sendSmartSwitchMessage(rustplus.guildId, rustplus.serverId, entityId); SmartSwitchGroupHandler.updateSwitchGroupIfContainSwitch( client, rustplus.guildId, rustplus.serverId, entityId); } } - else if (instance.alarms.hasOwnProperty(entityId)) { + else if (instance.serverList[rustplus.serverId].alarms.hasOwnProperty(entityId)) { let active = message.broadcast.entityChanged.payload.value; - instance.alarms[entityId].active = active; - instance.alarms[entityId].reachable = true; + instance.serverList[rustplus.serverId].alarms[entityId].active = active; + instance.serverList[rustplus.serverId].alarms[entityId].reachable = true; client.writeInstanceFile(rustplus.guildId, instance); if (active) { - let title = instance.alarms[entityId].name; - let message = instance.alarms[entityId].message; + let title = instance.serverList[rustplus.serverId].alarms[entityId].name; + let message = instance.serverList[rustplus.serverId].alarms[entityId].message; let content = {}; - content.embeds = [ - new EmbedBuilder() - .setColor('#ce412b') - .setThumbnail(`attachment://${instance.alarms[entityId].image}`) - .setTitle(title) - .addFields( - { name: 'ID', value: `\`${entityId}\``, inline: true }, - { name: 'Message', value: `\`${message}\``, inline: true } - ) - .setFooter({ text: instance.alarms[entityId].server }) - .setTimestamp()]; + content.embeds = [DiscordEmbeds.getEmbed({ + color: '#ce412b', + thumbnail: `attachment://${instance.serverList[rustplus.serverId].alarms[entityId].image}`, + title: title, + footer: { text: instance.serverList[rustplus.serverId].alarms[entityId].server }, + timestamp: true, + fields: [ + { name: 'ID', value: `\`${entityId}\``, inline: true }, + { name: 'Message', value: `\`${message}\``, inline: true }] + })]; content.files = [ - new AttachmentBuilder( - `src/resources/images/electrics/${instance.alarms[entityId].image}`)]; + new Discord.AttachmentBuilder( + `src/resources/images/electrics/` + + `${instance.serverList[rustplus.serverId].alarms[entityId].image}`)]; - if (instance.alarms[entityId].everyone) { + if (instance.serverList[rustplus.serverId].alarms[entityId].everyone) { content.content = '@everyone'; } @@ -95,28 +98,28 @@ module.exports = { } } - DiscordTools.sendSmartAlarmMessage(rustplus.guildId, entityId, true, false, false); + DiscordMessages.sendSmartAlarmMessage(rustplus.guildId, rustplus.serverId, entityId); } - else if (instance.storageMonitors.hasOwnProperty(entityId)) { + else if (instance.serverList[rustplus.serverId].storageMonitors.hasOwnProperty(entityId)) { if (message.broadcast.entityChanged.payload.value === true) return; - if (!instance.storageMonitors[entityId].reachable && - instance.storageMonitors[entityId].type === 'st') return; + if (!instance.serverList[rustplus.serverId].storageMonitors[entityId].reachable && + instance.serverList[rustplus.serverId].storageMonitors[entityId].type === 'st') return; - if (instance.storageMonitors[entityId].type === 'toolcupboard' || + if (instance.serverList[rustplus.serverId].storageMonitors[entityId].type === 'toolcupboard' || message.broadcast.entityChanged.payload.capacity === 28) { setTimeout(async () => { let info = await rustplus.getEntityInfoAsync(entityId); if (!(await rustplus.isResponseValid(info))) { - instance.storageMonitors[entityId].reachable = false; + instance.serverList[rustplus.serverId].storageMonitors[entityId].reachable = false; client.writeInstanceFile(rustplus.guildId, instance); } else { - instance.storageMonitors[entityId].reachable = true; + instance.serverList[rustplus.serverId].storageMonitors[entityId].reachable = true; client.writeInstanceFile(rustplus.guildId, instance); } - if (instance.storageMonitors[entityId].reachable) { + if (instance.serverList[rustplus.serverId].storageMonitors[entityId].reachable) { rustplus.storageMonitors[entityId] = { items: info.entityInfo.payload.items, expiry: info.entityInfo.payload.protectionExpiry, @@ -125,28 +128,30 @@ module.exports = { } let instance = client.readInstanceFile(rustplus.guildId); - instance.storageMonitors[entityId].type = 'toolcupboard'; + instance.serverList[rustplus.serverId].storageMonitors[entityId].type = 'toolcupboard'; if (info.entityInfo.payload.protectionExpiry === 0 && - instance.storageMonitors[entityId].decaying === false) { - instance.storageMonitors[entityId].decaying = true; + instance.serverList[rustplus.serverId].storageMonitors[entityId].decaying === + false) { + instance.serverList[rustplus.serverId].storageMonitors[entityId].decaying = true; - await DiscordTools.sendDecayingNotification(rustplus.guildId, entityId); + await DiscordMessages.sendDecayingNotificationMessage(rustplus.guildId, + rustplus.serverId, entityId); - if (instance.storageMonitors[entityId].inGame) { + if (instance.serverList[rustplus.serverId].storageMonitors[entityId].inGame) { rustplus.sendTeamMessageAsync( - `${instance.storageMonitors[entityId].name} is decaying!`); + `${instance.serverList[rustplus.serverId].storageMonitors[entityId].name}` + + ` is decaying!`); } } else if (info.entityInfo.payload.protectionExpiry !== 0) { - instance.storageMonitors[entityId].decaying = false; + instance.serverList[rustplus.serverId].storageMonitors[entityId].decaying = false; } client.writeInstanceFile(rustplus.guildId, instance); } - await DiscordTools.sendStorageMonitorMessage( - rustplus.guildId, entityId, true, true, false); - + await DiscordMessages.sendStorageMonitorMessage(rustplus.guildId, rustplus.serverId, + entityId); }, 2000); } else { @@ -159,15 +164,15 @@ module.exports = { let info = await rustplus.getEntityInfoAsync(entityId); if (!(await rustplus.isResponseValid(info))) { - instance.storageMonitors[entityId].reachable = false; + instance.serverList[rustplus.serverId].storageMonitors[entityId].reachable = false; client.writeInstanceFile(rustplus.guildId, instance); } else { - instance.storageMonitors[entityId].reachable = true; + instance.serverList[rustplus.serverId].storageMonitors[entityId].reachable = true; client.writeInstanceFile(rustplus.guildId, instance); } - await DiscordTools.sendStorageMonitorMessage(rustplus.guildId, entityId, true, true, false); + await DiscordMessages.sendStorageMonitorMessage(rustplus.guildId, rustplus.serverId, entityId); } } } diff --git a/src/structures/DiscordBot.js b/src/structures/DiscordBot.js index f9cedf720..e3b043557 100644 --- a/src/structures/DiscordBot.js +++ b/src/structures/DiscordBot.js @@ -1,24 +1,23 @@ -const fs = require('fs'); -const { Collection, Client } = require('discord.js'); +const Fs = require('fs'); +const Discord = require('discord.js'); +const Path = require('path'); + const Config = require('../../config.json'); -const RustPlus = require('../structures/RustPlus'); -const Logger = require('./Logger.js'); -const path = require('path'); -const Items = require('./Items'); +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); const DiscordTools = require('../discordTools/discordTools'); -const { EmbedBuilder } = require('discord.js'); +const Items = require('./Items'); +const Logger = require('./Logger.js'); +const RustPlus = require('../structures/RustPlus'); -class DiscordBot extends Client { +class DiscordBot extends Discord.Client { constructor(props) { super(props); - this.logger = new Logger(path.join(__dirname, '..', 'logs/discordBot.log'), 'default'); + this.logger = new Logger(Path.join(__dirname, '..', 'logs/discordBot.log'), 'default'); - this.commands = new Collection(); + this.commands = new Discord.Collection(); this.rustplusInstances = new Object(); this.currentFcmListeners = new Object(); - this.switchesMessages = new Object(); - this.storageMonitorsMessages = new Object(); this.items = new Items(); @@ -28,28 +27,28 @@ class DiscordBot extends Client { this.battlemetricsIntervalId = null; this.battlemetricsIntervalCounter = 0; - this.loadCommands(); - this.loadEvents(); + this.loadDiscordCommands(); + this.loadDiscordEvents(); } - loadCommands() { - const commandFiles = fs.readdirSync(`${__dirname}/../commands`).filter(file => file.endsWith('.js')); + loadDiscordCommands() { + const commandFiles = Fs.readdirSync(`${__dirname}/../commands`).filter(file => file.endsWith('.js')); for (const file of commandFiles) { const command = require(`../commands/${file}`); this.commands.set(command.data.name, command); } } - loadEvents() { - const discordEventFiles = fs.readdirSync(`${__dirname}/../discordEvents`).filter(file => file.endsWith('.js')); - for (const file of discordEventFiles) { + loadDiscordEvents() { + const eventFiles = Fs.readdirSync(`${__dirname}/../discordEvents`).filter(file => file.endsWith('.js')); + for (const file of eventFiles) { const event = require(`../discordEvents/${file}`); if (event.name === 'rateLimited') { this.rest.on(event.name, (...args) => event.execute(this, ...args)); } else if (event.once) { - this.once(event.name, (...args) => event.execute(...args)); + this.once(event.name, (...args) => event.execute(this, ...args)); } else { this.on(event.name, (...args) => event.execute(this, ...args)); @@ -83,11 +82,6 @@ class DiscordBot extends Client { require('../util/CreateInstanceFile')(this, guild); require('../util/CreateCredentialsFile')(this, guild); - /* If maps/ directory does not exist, create it */ - if (!fs.existsSync(`${__dirname}/../resources/images/maps`)) { - fs.mkdirSync(`${__dirname}/../resources/images/maps`); - } - await require('../discordTools/RegisterSlashCommands')(this, guild); let category = await require('../discordTools/SetupGuildCategory')(this, guild); @@ -98,27 +92,27 @@ class DiscordBot extends Client { } readInstanceFile(guildId) { - return JSON.parse(fs.readFileSync(`${__dirname}/../instances/${guildId}.json`, 'utf8')); + return JSON.parse(Fs.readFileSync(`${__dirname}/../instances/${guildId}.json`, 'utf8')); } writeInstanceFile(guildId, instance) { - fs.writeFileSync(`${__dirname}/../instances/${guildId}.json`, JSON.stringify(instance, null, 2)); + Fs.writeFileSync(`${__dirname}/../instances/${guildId}.json`, JSON.stringify(instance, null, 2)); } readCredentialsFile(guildId) { - return JSON.parse(fs.readFileSync(`${__dirname}/../credentials/${guildId}.json`, 'utf8')); + return JSON.parse(Fs.readFileSync(`${__dirname}/../credentials/${guildId}.json`, 'utf8')); } writeCredentialsFile(guildId, credentials) { - fs.writeFileSync(`${__dirname}/../credentials/${guildId}.json`, JSON.stringify(credentials, null, 2)); + Fs.writeFileSync(`${__dirname}/../credentials/${guildId}.json`, JSON.stringify(credentials, null, 2)); } readNotificationSettingsTemplate() { - return JSON.parse(fs.readFileSync(`${__dirname}/../templates/notificationSettingsTemplate.json`, 'utf8')); + return JSON.parse(Fs.readFileSync(`${__dirname}/../templates/notificationSettingsTemplate.json`, 'utf8')); } readGeneralSettingsTemplate() { - return JSON.parse(fs.readFileSync(`${__dirname}/../templates/generalSettingsTemplate.json`, 'utf8')); + return JSON.parse(Fs.readFileSync(`${__dirname}/../templates/generalSettingsTemplate.json`, 'utf8')); } createRustplusInstance(guildId, serverIp, appPort, steamId, playerToken) { @@ -133,12 +127,7 @@ class DiscordBot extends Client { } createRustplusInstancesFromConfig() { - /* If instances/ directory does not exist, create it */ - if (!fs.existsSync(`${__dirname}/../instances`)) { - fs.mkdirSync(`${__dirname}/../instances`); - } - - let files = fs.readdirSync(`${__dirname}/../instances`); + let files = Fs.readdirSync(`${__dirname}/../instances`); files.forEach(file => { if (file.endsWith('.json')) { @@ -160,23 +149,25 @@ class DiscordBot extends Client { }); } - findAvailableTrackerName(guildId) { - let instance = this.readInstanceFile(guildId); - let baseName = 'Tracker'; + findAvailableTrackerId(guildId) { + const instance = this.readInstanceFile(guildId); - let index = 0; while (true) { - let testName = `${baseName}${(index === 0) ? '' : index}`; - let exist = false; - if (Object.keys(instance.trackers).includes(testName)) { - exist = true; + const randomNumber = Math.floor(Math.random() * 1000); + if (!instance.trackers.hasOwnProperty(randomNumber)) { + return randomNumber; } + } + } + + findAvailableGroupId(guildId, serverId) { + const instance = this.readInstanceFile(guildId); - if (exist) { - index += 1; - continue; + while (true) { + const randomNumber = Math.floor(Math.random() * 1000); + if (!instance.serverList[serverId].switchGroups.hasOwnProperty(randomNumber)) { + return randomNumber; } - return testName; } } @@ -218,6 +209,7 @@ class DiscordBot extends Client { return await message.edit(content); } catch (e) { + console.log(message) this.log('ERROR', `Message edit failed: ${e}`, 'error'); } @@ -236,7 +228,7 @@ class DiscordBot extends Client { } async validatePermissions(interaction) { - let instance = this.readInstanceFile(interaction.guildId); + const instance = this.readInstanceFile(interaction.guildId); /* If role isn't setup yet, validate as true */ if (instance.role === null) return true; @@ -245,13 +237,7 @@ class DiscordBot extends Client { !interaction.member.roles.cache.has(instance.role)) { let role = DiscordTools.getRole(interaction.guildId, instance.role); let str = `You are not part of the '${role.name}' role, therefore you can't run bot commands.`; - await this.interactionReply(interaction, { - embeds: [new EmbedBuilder() - .setColor('#ff0040') - .setDescription(`\`\`\`diff\n- ${str}\n\`\`\``)], - ephemeral: true - }); - + await this.interactionReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str)); this.log('WARNING', str); return false; } diff --git a/src/structures/Items.js b/src/structures/Items.js index f78dd5e25..f48d40698 100644 --- a/src/structures/Items.js +++ b/src/structures/Items.js @@ -1,9 +1,10 @@ -const fs = require('fs'); +const Fs = require('fs'); + const Str = require('../util/string.js'); class Items { constructor() { - this._items = JSON.parse(fs.readFileSync(`${__dirname}/../util/items.json`, 'utf8')); + this._items = JSON.parse(Fs.readFileSync(`${__dirname}/../util/items.json`, 'utf8')); } /* Getters and Setters */ diff --git a/src/structures/Logger.js b/src/structures/Logger.js index e079ee675..db1be9254 100644 --- a/src/structures/Logger.js +++ b/src/structures/Logger.js @@ -1,11 +1,12 @@ -const winston = require("winston"); -const colors = require("colors"); +const Colors = require("colors"); +const Winston = require("winston"); + const Config = require('../../config.json'); class Logger { constructor(logFilePath, type) { - this.logger = winston.createLogger({ - transports: [new winston.transports.File({ + this.logger = Winston.createLogger({ + transports: [new Winston.transports.File({ filename: logFilePath, maxsize: 10000000, maxFiles: 2, @@ -47,14 +48,14 @@ class Logger { }); console.log( - colors.green(`${time} `) + - ((level === 'error') ? colors.red(text) : colors.yellow(text)) + Colors.green(`${time} `) + + ((level === 'error') ? Colors.red(text) : Colors.yellow(text)) ); if (level === 'error' && Config.general.showCallStackError) { for (let line of (new Error().stack.split(/\r?\n/))) { this.logger.log({ level: level, message: `${time} | ${line}` }); - console.log(colors.green(`${time} `) + colors.red(line)); + console.log(Colors.green(`${time} `) + Colors.red(line)); } } } break; @@ -68,10 +69,10 @@ class Logger { }); console.log( - colors.green(`${time} `) + - colors.cyan(`${this.guildId} `) + - colors.white(`${this.serverName} `) + - ((level === 'error') ? colors.red(text) : colors.yellow(text)) + Colors.green(`${time} `) + + Colors.cyan(`${this.guildId} `) + + Colors.white(`${this.serverName} `) + + ((level === 'error') ? Colors.red(text) : Colors.yellow(text)) ); if (level === 'error' && Config.general.showCallStackError) { @@ -81,10 +82,10 @@ class Logger { message: `${time} | ${this.guildId} | ${this.serverName} | ${line}` }); console.log( - colors.green(`${time} `) + - colors.cyan(`${this.guildId} `) + - colors.white(`${this.serverName} `) + - colors.red(line)); + Colors.green(`${time} `) + + Colors.cyan(`${this.guildId} `) + + Colors.white(`${this.serverName} `) + + Colors.red(line)); } } } break; diff --git a/src/structures/Map.js b/src/structures/Map.js index 82cea4740..5db56c1d0 100644 --- a/src/structures/Map.js +++ b/src/structures/Map.js @@ -1,5 +1,5 @@ +const Fs = require("fs"); const Jimp = require("jimp"); -const fs = require("fs"); class Map { constructor(map, rustplus) { @@ -249,7 +249,7 @@ class Map { } async writeMapClean() { - await fs.writeFileSync(this.mapMarkerImageMeta.map.image, this.jpgImage); + await Fs.writeFileSync(this.mapMarkerImageMeta.map.image, this.jpgImage); } async setupFont() { diff --git a/src/structures/Player.js b/src/structures/Player.js index 89bf7214e..47e699ac3 100644 --- a/src/structures/Player.js +++ b/src/structures/Player.js @@ -1,6 +1,6 @@ +const Constants = require('../util/constants.js'); const Map = require('../util/map.js'); const Time = require('../util/timer.js'); -const Constants = require('../util/constants.js'); class Player { constructor(player, rustplus) { diff --git a/src/structures/RustPlus.js b/src/structures/RustPlus.js index 14f083eb6..ab3d0502c 100644 --- a/src/structures/RustPlus.js +++ b/src/structures/RustPlus.js @@ -1,21 +1,24 @@ -const fs = require('fs'); -const RP = require('rustplus.js'); -const Client = require('../../index.js'); -const { EmbedBuilder, AttachmentBuilder } = require('discord.js'); -const Logger = require('./Logger.js'); -const path = require('path'); -const DiscordTools = require('../discordTools/discordTools.js'); +const Discord = require('discord.js'); +const Fs = require('fs'); +const Path = require('path'); + +const Client = require('../../index.ts'); const Constants = require('../util/constants.js'); +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); const Items = require('./Items'); +const Logger = require('./Logger.js'); +const RustPlusLib = require('rustplus.js'); const Timer = require('../util/timer.js'); -class RustPlus extends RP { +class RustPlus extends RustPlusLib { constructor(guildId, serverIp, appPort, steamId, playerToken) { super(serverIp, appPort, steamId, playerToken); this.serverId = `${this.server}-${this.port}`; this.guildId = guildId; + this.newConnection = false; this.intervalId = 0; this.logger = null; this.firstPoll = true; @@ -76,7 +79,7 @@ class RustPlus extends RP { this.interactionSwitches = []; /* Load rustplus events */ - this.loadEvents(); + this.loadRustPlusEvents(); this.tokens = 24; this.tokens_limit = 24; /* Per player */ @@ -84,9 +87,9 @@ class RustPlus extends RP { this.tokens_replenish_task = 0; } - loadEvents() { + loadRustPlusEvents() { /* Dynamically retrieve the rustplus event files */ - const eventFiles = fs.readdirSync(`${__dirname}/../rustplusEvents`).filter(file => file.endsWith('.js')); + const eventFiles = Fs.readdirSync(`${__dirname}/../rustplusEvents`).filter(file => file.endsWith('.js')); for (const file of eventFiles) { const event = require(`../rustplusEvents/${file}`); this.on(event.name, (...args) => event.execute(this, Client.client, ...args)); @@ -94,24 +97,18 @@ class RustPlus extends RP { } loadMarkers() { - let instance = Client.client.readInstanceFile(this.guildId); - let server = `${this.server}-${this.port}`; + const instance = Client.client.readInstanceFile(this.guildId); - if (!instance.markers.hasOwnProperty(server)) { - instance.markers[server] = {}; - Client.client.writeInstanceFile(this.guildId, instance); - } - - for (const [name, location] of Object.entries(instance.markers[server])) { + for (const [name, location] of Object.entries(instance.serverList[this.serverId].markers)) { this.markers[name] = { x: location.x, y: location.y }; } } build() { - let instance = Client.client.readInstanceFile(this.guildId); + const instance = Client.client.readInstanceFile(this.guildId); /* Setup the logger */ - this.logger = new Logger(path.join(__dirname, '..', `logs/${this.guildId}.log`), 'guild'); + this.logger = new Logger(Path.join(__dirname, '..', `logs/${this.guildId}.log`), 'guild'); this.logger.setGuildId(this.guildId); this.logger.serverName = instance.serverList[`${this.server}-${this.port}`].title; @@ -141,7 +138,7 @@ class RustPlus extends RP { } async sendEvent(setting, text, firstPoll = false, image = null) { - let img = (image !== null) ? image : setting.image; + const img = (image !== null) ? image : setting.image; if (!firstPoll && setting.discord) { this.sendDiscordEvent(text, img) @@ -153,22 +150,14 @@ class RustPlus extends RP { } sendDiscordEvent(text, image) { - let instance = Client.client.readInstanceFile(this.guildId); - let channel = DiscordTools.getTextChannelById(this.guildId, instance.channelId.events); - - if (channel !== undefined) { - let file = new AttachmentBuilder(`src/resources/images/events/${image}`); - let embed = new EmbedBuilder() - .setColor('#ce412b') - .setThumbnail(`attachment://${image}`) - .setTitle(text) - .setFooter({ - text: instance.serverList[`${this.server}-${this.port}`].title - }) - .setTimestamp(); - - Client.client.messageSend(channel, { embeds: [embed], files: [file] }); + const instance = Client.client.readInstanceFile(this.guildId); + + const content = { + embeds: [DiscordEmbeds.getEventEmbed(this.guildId, this, text, image)], + files: [new Discord.AttachmentBuilder(`src/resources/images/events/${image}`)] } + + DiscordMessages.sendMessage(this.guildId, content, null, instance.channelId.events); } replenish_tokens() { @@ -183,7 +172,7 @@ class RustPlus extends RP { while (this.tokens < cost) { if (timeoutCounter === 90) return false; - await Timer.sleep(333); + await Timer.sleep(1000 / 3); timeoutCounter += 1; } this.tokens -= cost; diff --git a/src/util/CreateCredentialsFile.js b/src/util/CreateCredentialsFile.js index 020134296..cc5645925 100644 --- a/src/util/CreateCredentialsFile.js +++ b/src/util/CreateCredentialsFile.js @@ -1,13 +1,8 @@ -const fs = require('fs'); +const Fs = require('fs'); module.exports = (client, guild) => { - /* If credential/ directory does not exist, create it */ - if (!fs.existsSync(`${__dirname}/../credentials`)) { - fs.mkdirSync(`${__dirname}/../credentials`); - } - - if (!fs.existsSync(`${__dirname}/../credentials/${guild.id}.json`)) { - fs.writeFileSync(`${__dirname}/../credentials/${guild.id}.json`, JSON.stringify({ + if (!Fs.existsSync(`${__dirname}/../credentials/${guild.id}.json`)) { + Fs.writeFileSync(`${__dirname}/../credentials/${guild.id}.json`, JSON.stringify({ credentials: null }, null, 2)); } diff --git a/src/util/CreateInstanceFile.js b/src/util/CreateInstanceFile.js index 5f41846dc..5b52da220 100644 --- a/src/util/CreateInstanceFile.js +++ b/src/util/CreateInstanceFile.js @@ -1,13 +1,8 @@ -const fs = require('fs'); +const Fs = require('fs'); module.exports = (client, guild) => { - /* If instances/ directory does not exist, create it */ - if (!fs.existsSync(`${__dirname}/../instances`)) { - fs.mkdirSync(`${__dirname}/../instances`); - } - - if (!fs.existsSync(`${__dirname}/../instances/${guild.id}.json`)) { - fs.writeFileSync(`${__dirname}/../instances/${guild.id}.json`, JSON.stringify({ + if (!Fs.existsSync(`${__dirname}/../instances/${guild.id}.json`)) { + Fs.writeFileSync(`${__dirname}/../instances/${guild.id}.json`, JSON.stringify({ firstTime: true, role: null, generalSettings: client.readGeneralSettingsTemplate(), @@ -31,10 +26,6 @@ module.exports = (client, guild) => { event: null, team: null }, - switches: {}, - alarms: {}, - storageMonitors: {}, - markers: {}, serverList: {}, trackers: {}, marketSubscribeItemIds: [] @@ -121,10 +112,6 @@ module.exports = (client, guild) => { if (!inst.informationMessageId.hasOwnProperty('team')) inst.informationMessageId.team = null; } - if (!inst.hasOwnProperty('switches')) inst.switches = {}; - if (!inst.hasOwnProperty('alarms')) inst.alarms = {}; - if (!inst.hasOwnProperty('storageMonitors')) inst.storageMonitors = {}; - if (!inst.hasOwnProperty('markers')) inst.markers = {}; if (!inst.hasOwnProperty('serverList')) inst.serverList = {}; if (!inst.hasOwnProperty('trackers')) inst.trackers = {}; if (!inst.hasOwnProperty('marketSubscribeItemIds')) inst.marketSubscribeItemIds = []; diff --git a/src/util/FcmListener.js b/src/util/FcmListener.js index 77b845be2..bb6586c30 100644 --- a/src/util/FcmListener.js +++ b/src/util/FcmListener.js @@ -1,12 +1,16 @@ -const { ActionRowBuilder, ButtonBuilder, EmbedBuilder, AttachmentBuilder, ButtonStyle } = require('discord.js'); -const { listen } = require('push-receiver'); -const DiscordTools = require('../discordTools/discordTools.js'); +const Discord = require('discord.js'); +const PushReceiver = require('push-receiver'); + +const BattlemetricsAPI = require('../util/battlemetricsAPI.js'); const Constants = require('../util/constants.js'); +const DiscordButtons = require('../discordTools/discordButtons.js'); +const DiscordEmbeds = require('../discordTools/discordEmbeds.js'); +const DiscordMessages = require('../discordTools/discordMessages.js'); +const DiscordTools = require('../discordTools/discordTools.js'); const Scrape = require('../util/scrape.js'); -const BattlemetricsAPI = require('../util/battlemetricsAPI.js'); module.exports = async (client, guild) => { - let credentials = client.readCredentialsFile(guild.id); + const credentials = client.readCredentialsFile(guild.id); if (credentials.credentials === null) { client.log('WARNING', `Credentials is not set for guild: ${guild.id}, cannot start FCM-listener.`); @@ -16,15 +20,13 @@ module.exports = async (client, guild) => { const ownerId = credentials.credentials.owner; /* Destroy previous instance of fcm listener */ - if (client.currentFcmListeners[guild.id]) { - client.currentFcmListeners[guild.id].destroy(); - } + if (client.currentFcmListeners[guild.id]) client.currentFcmListeners[guild.id].destroy(); client.log('INFO', `FCM-listener will start in 5 seconds for guild: ${guild.id}`); let startTime = new Date(); client.currentFcmListeners[guild.id] = - await listen(credentials.credentials.fcm_credentials, async ({ notification, persistentId }) => { + await PushReceiver.listen(credentials.credentials.fcm_credentials, async ({ notification, persistentId }) => { /* Create a delay so that buffered notifications are ignored. */ if ((new Date() - startTime) < 5000) return; @@ -78,6 +80,12 @@ module.exports = async (client, guild) => { } break; default: { + if (data.title === 'You\'re getting raided!') { + /* Custom alarm from plugin: https://umod.org/plugins/raid-alarm */ + client.log('FCM', `${guild.id} alarm: raid-alarm plugin`); + alarmRaidAlarm(client, guild, full, data, body); + break; + } client.log('FCM', `${guild.id} alarm: other\n${JSON.stringify(full)}`); } break; } @@ -130,22 +138,17 @@ module.exports = async (client, guild) => { }; function isValidUrl(url) { - if (url.startsWith('https') || url.startsWith('http')) { - return true; - } + if (url.startsWith('https') || url.startsWith('http')) return true; return false; } async function pairingServer(client, guild, full, data, body) { - let instance = client.readInstanceFile(guild.id); - let serverId = `${body.ip}-${body.port}`; - let serversId = instance.channelId.servers; - let message = undefined; + const instance = client.readInstanceFile(guild.id); + const serverId = `${body.ip}-${body.port}`; + const server = instance.serverList[serverId]; - let serverExist = instance.serverList.hasOwnProperty(serverId); - if (serverExist) { - message = await DiscordTools.getMessageById(guild.id, serversId, instance.serverList[serverId].messageId); - } + let message = undefined; + if (server) message = await DiscordTools.getMessageById(guild.id, instance.channelId.servers, server.messageId); let info = null; let battlemetricsId = await BattlemetricsAPI.getBattlemetricsServerId(client, data.title); @@ -158,7 +161,7 @@ async function pairingServer(client, guild, full, data, body) { } instance.serverList[serverId] = { - active: (serverExist) ? instance.serverList[serverId].active : false, + active: server ? server.active : false, title: data.title, serverIp: body.ip, appPort: body.port, @@ -167,153 +170,151 @@ async function pairingServer(client, guild, full, data, body) { description: body.desc.replace(/\\n/g, '\n').replace(/\\t/g, '\t'), img: isValidUrl(body.img) ? body.img : Constants.DEFAULT_SERVER_IMG, url: isValidUrl(body.url) ? body.url : Constants.DEFAULT_SERVER_URL, - timeTillDay: null, - timeTillNight: null, - notes: {}, - switchGroups: {}, + notes: server ? server.notes : {}, + switches: server ? server.switches : {}, + alarms: server ? server.alarms : {}, + storageMonitors: server ? server.storageMonitors : {}, + markers: server ? server.markers : {}, + switchGroups: server ? server.switchGroups : {}, messageId: (message !== undefined) ? message.id : null, battlemetricsId: battlemetricsId, - connect: (info === null) ? info : `connect ${info.ip}:${info.port}`, - cargoShipEgressTimeMs: Constants.DEFAULT_CARGO_SHIP_EGRESS_TIME_MS, - bradleyApcRespawnTimeMs: Constants.DEFAULT_BRADLEY_APC_RESPAWN_TIME_MS, - lockedCrateDespawnTimeMs: Constants.DEFAULT_LOCKED_CRATE_DESPAWN_TIME_MS, - lockedCrateDespawnWarningTimeMs: Constants.DEFAULT_LOCKED_CRATE_DESPAWN_WARNING_TIME_MS, - oilRigLockedCrateUnlockTimeMs: Constants.DEFAULT_OIL_RIG_LOCKED_CRATE_UNLOCK_TIME_MS + connect: (info === null) ? 'Unavailable' : `connect ${info.ip}:${info.port}`, + cargoShipEgressTimeMs: server ? server.cargoShipEgressTimeMs : Constants.DEFAULT_CARGO_SHIP_EGRESS_TIME_MS, + bradleyApcRespawnTimeMs: server ? server.bradleyApcRespawnTimeMs : + Constants.DEFAULT_BRADLEY_APC_RESPAWN_TIME_MS, + lockedCrateDespawnTimeMs: server ? server.lockedCrateDespawnTimeMs : + Constants.DEFAULT_LOCKED_CRATE_DESPAWN_TIME_MS, + lockedCrateDespawnWarningTimeMs: server ? server.lockedCrateDespawnWarningTimeMs : + Constants.DEFAULT_LOCKED_CRATE_DESPAWN_WARNING_TIME_MS, + oilRigLockedCrateUnlockTimeMs: server ? server.oilRigLockedCrateUnlockTimeMs : + Constants.DEFAULT_OIL_RIG_LOCKED_CRATE_UNLOCK_TIME_MS, + timeTillDay: server ? server.timeTillDay : null, + timeTillNight: server ? server.timeTillNight : null }; client.writeInstanceFile(guild.id, instance); - await DiscordTools.sendServerMessage(guild.id, serverId, null); + await DiscordMessages.sendServerMessage(guild.id, serverId, null); } async function pairingEntitySwitch(client, guild, full, data, body) { - let instance = client.readInstanceFile(guild.id); - let serverId = `${body.ip}-${body.port}`; - let entityId = body.entityId; - - if (instance.switches.hasOwnProperty(entityId)) return; - - instance.switches[entityId] = { - active: false, - reachable: true, - name: 'Smart Switch', - command: entityId, - image: 'smart_switch.png', - autoDayNight: 0, - server: body.name, - serverId: serverId + const instance = client.readInstanceFile(guild.id); + const serverId = `${body.ip}-${body.port}`; + if (!instance.serverList.hasOwnProperty(serverId)) return; + const switches = instance.serverList[serverId].switches; + + const entityExist = instance.serverList[serverId].switches.hasOwnProperty(body.entityId); + instance.serverList[serverId].switches[body.entityId] = { + active: entityExist ? switches[body.entityId].active : false, + reachable: entityExist ? switches[body.entityId].reachable : true, + name: entityExist ? switches[body.entityId].name : 'Smart Switch', + command: entityExist ? switches[body.entityId].command : body.entityId, + image: entityExist ? switches[body.entityId].image : 'smart_switch.png', + autoDayNight: entityExist ? switches[body.entityId].autoDayNight : 0, + server: entityExist ? switches[body.entityId].server : body.name, + messageId: entityExist ? switches[body.entityId].messageId : null }; client.writeInstanceFile(guild.id, instance); - let rustplus = client.rustplusInstances[guild.id]; - if (!rustplus) return; - - if (serverId === rustplus.serverId) { - let info = await rustplus.getEntityInfoAsync(entityId); + const rustplus = client.rustplusInstances[guild.id]; + if (rustplus && serverId === rustplus.serverId) { + const info = await rustplus.getEntityInfoAsync(body.entityId); if (!(await rustplus.isResponseValid(info))) { - instance.switches[entityId].reachable = false; - client.writeInstanceFile(guild.id, instance); + instance.serverList[serverId].switches[body.entityId].reachable = false; } - if (instance.switches[entityId].reachable) { - instance.switches[entityId].active = info.entityInfo.payload.value; - client.writeInstanceFile(guild.id, instance); + if (instance.serverList[serverId].switches[body.entityId].reachable) { + instance.serverList[serverId].switches[body.entityId].active = info.entityInfo.payload.value; } + client.writeInstanceFile(guild.id, instance); - await DiscordTools.sendSmartSwitchMessage(guild.id, entityId); + await DiscordMessages.sendSmartSwitchMessage(guild.id, serverId, body.entityId); } } async function pairingEntitySmartAlarm(client, guild, full, data, body) { - let instance = client.readInstanceFile(guild.id); - let serverId = `${body.ip}-${body.port}`; - let entityId = body.entityId; - - if (instance.alarms.hasOwnProperty(entityId)) return; - - instance.alarms[entityId] = { - active: false, - reachable: true, - everyone: false, - name: 'Smart Alarm', - message: 'Your base is under attack!', - id: entityId, - image: 'smart_alarm.png', - server: body.name, - serverId: serverId, - messageId: null + const instance = client.readInstanceFile(guild.id); + const serverId = `${body.ip}-${body.port}`; + if (!instance.serverList.hasOwnProperty(serverId)) return; + const alarms = instance.serverList[serverId].alarms; + + const entityExist = instance.serverList[serverId].alarms.hasOwnProperty(body.entityId); + instance.serverList[serverId].alarms[body.entityId] = { + active: entityExist ? alarms[body.entityId].active : false, + reachable: entityExist ? alarms[body.entityId].reachable : true, + everyone: entityExist ? alarms[body.entityId].everyone : false, + name: entityExist ? alarms[body.entityId].name : 'Smart Alarm', + message: entityExist ? alarms[body.entityId].message : 'Your base is under attack!', + id: entityExist ? alarms[body.entityId].id : body.entityId, + image: entityExist ? alarms[body.entityId].image : 'smart_alarm.png', + server: entityExist ? alarms[body.entityId].server : body.name, + messageId: entityExist ? alarms[body.entityId].messageId : null }; client.writeInstanceFile(guild.id, instance); - let rustplus = client.rustplusInstances[guild.id]; - if (!rustplus) return; - - if (serverId === rustplus.serverId) { - let info = await rustplus.getEntityInfoAsync(entityId); + const rustplus = client.rustplusInstances[guild.id]; + if (rustplus && serverId === rustplus.serverId) { + const info = await rustplus.getEntityInfoAsync(body.entityId); if (!(await rustplus.isResponseValid(info))) { - instance.alarms[entityId].reachable = false; - client.writeInstanceFile(guild.id, instance); + instance.serverList[serverId].alarms[body.entityId].reachable = false; } - if (instance.alarms[entityId].reachable) { - instance.alarms[entityId].active = info.entityInfo.payload.value; - client.writeInstanceFile(guild.id, instance); + if (instance.serverList[serverId].alarms[body.entityId].reachable) { + instance.serverList[serverId].alarms[body.entityId].active = info.entityInfo.payload.value; } + client.writeInstanceFile(guild.id, instance); } - await DiscordTools.sendSmartAlarmMessage(guild.id, entityId); + await DiscordMessages.sendSmartAlarmMessage(guild.id, serverId, body.entityId); } async function pairingEntityStorageMonitor(client, guild, full, data, body) { - let instance = client.readInstanceFile(guild.id); - let serverId = `${body.ip}-${body.port}`; - let entityId = body.entityId; - - if (instance.storageMonitors.hasOwnProperty(entityId)) return; - - instance.storageMonitors[entityId] = { - name: 'Storage Monitor', - reachable: true, - id: entityId, - type: 'container', - decaying: false, - upkeep: null, - everyone: false, - inGame: true, - image: 'storage_monitor.png', - server: body.name, - serverId: serverId + const instance = client.readInstanceFile(guild.id); + const serverId = `${body.ip}-${body.port}`; + if (!instance.serverList.hasOwnProperty(serverId)) return; + const storageMonitors = instance.serverList[serverId].storageMonitors; + + const entityExist = instance.serverList[serverId].storageMonitors.hasOwnProperty(body.entityId); + instance.serverList[serverId].storageMonitors[body.entityId] = { + name: entityExist ? storageMonitors[body.entityId].name : 'Storage Monitor', + reachable: entityExist ? storageMonitors[body.entityId].reachable : true, + id: entityExist ? storageMonitors[body.entityId].id : body.entityId, + type: entityExist ? storageMonitors[body.entityId].type : 'container', + decaying: entityExist ? storageMonitors[body.entityId].decaying : false, + upkeep: entityExist ? storageMonitors[body.entityId].upkeep : null, + everyone: entityExist ? storageMonitors[body.entityId].everyone : false, + inGame: entityExist ? storageMonitors[body.entityId].inGame : true, + image: entityExist ? storageMonitors[body.entityId].image : 'storage_monitor.png', + server: entityExist ? storageMonitors[body.entityId].server : body.name, + messageId: entityExist ? storageMonitors[body.entityId].messageId : null }; client.writeInstanceFile(guild.id, instance); - let rustplus = client.rustplusInstances[guild.id]; - if (!rustplus) return; - - if (serverId === rustplus.serverId) { - let info = await rustplus.getEntityInfoAsync(entityId); + const rustplus = client.rustplusInstances[guild.id]; + if (rustplus && serverId === rustplus.serverId) { + const info = await rustplus.getEntityInfoAsync(body.entityId); if (!(await rustplus.isResponseValid(info))) { - instance.storageMonitors[entityId].reachable = false; - client.writeInstanceFile(guild.id, instance); + instance.serverList[serverId].storageMonitors[body.entityId].reachable = false; } - if (instance.storageMonitors[entityId].reachable) { + if (instance.serverList[serverId].storageMonitors[body.entityId].reachable) { if (info.entityInfo.payload.capacity === 28) { - instance.storageMonitors[entityId].type = 'toolcupboard'; - instance.storageMonitors[entityId].image = 'tool_cupboard.png'; + instance.serverList[serverId].storageMonitors[body.entityId].type = 'toolcupboard'; + instance.serverList[serverId].storageMonitors[body.entityId].image = 'tool_cupboard.png'; if (info.entityInfo.payload.protectionExpiry === 0) { - instance.storageMonitors[entityId].decaying = true; + instance.serverList[serverId].storageMonitors[body.entityId].decaying = true; } } - client.writeInstanceFile(guild.id, instance); - rustplus.storageMonitors[entityId] = { + rustplus.storageMonitors[body.entityId] = { items: info.entityInfo.payload.items, expiry: info.entityInfo.payload.protectionExpiry, capacity: info.entityInfo.payload.capacity, hasProtection: info.entityInfo.payload.hasProtection } } + client.writeInstanceFile(guild.id, instance); - await DiscordTools.sendStorageMonitorMessage(guild.id, entityId); + await DiscordMessages.sendStorageMonitorMessage(guild.id, serverId, body.entityId); } } @@ -328,119 +329,88 @@ async function alarmAlarm(client, guild, full, data, body) { to the credential owner and which is not part of the currently connected rust server can notify IF the general setting fcmAlarmNotificationEnabled is enabled. Those notifications will be handled here. */ - let instance = client.readInstanceFile(guild.id); - let serverId = `${body.ip}-${body.port}`; - let rustplus = client.rustplusInstances[guild.id]; + const instance = client.readInstanceFile(guild.id); - if (!rustplus || (rustplus && (serverId !== rustplus.serverId))) { - if (instance.generalSettings.fcmAlarmNotificationEnabled) { - let title = (data.title !== '') ? data.title : 'Smart Alarm'; - let message = (data.message !== '') ? data.message : 'Your base is under attack!'; - - let content = {}; - content.embeds = [ - new EmbedBuilder() - .setColor('#ce412b') - .setThumbnail('attachment://smart_alarm.png') - .setTitle(title) - .addFields({ name: 'Message', value: `\`${message}\``, inline: true }) - .setFooter({ text: body.name }) - .setTimestamp()]; - content.files = [new AttachmentBuilder('src/resources/images/electrics/smart_alarm.png')]; - - if (instance.generalSettings.fcmAlarmNotificationEveryone) { - content.content = '@everyone'; - } + const content = { + embeds: [DiscordEmbeds.getAlarmEmbed(data, body)], + files: [new Discord.AttachmentBuilder('src/resources/images/electrics/smart_alarm.png')], + content: instance.generalSettings.fcmAlarmNotificationEveryone ? '@everyone' : '' + } - let channel = DiscordTools.getTextChannelById(rustplus.guildId, instance.channelId.activity); - if (channel) { - await client.messageSend(channel, content); - } + const rustplus = client.rustplusInstances[guild.id]; + const serverId = `${body.ip}-${body.port}`; - if (instance.generalSettings.smartAlarmNotifyInGame && rustplus) { - rustplus.sendTeamMessageAsync(`${title}: ${message}`); - } + if (!rustplus || (rustplus && (serverId !== rustplus.serverId)) && + instance.generalSettings.fcmAlarmNotificationEnabled) { + await DiscordMessages.sendMessage(guild.id, content, null, instance.channelId.activity); + + if (rustplus && instance.generalSettings.smartAlarmNotifyInGame) { + rustplus.sendTeamMessageAsync(`${data.title}: ${data.message}`); } + + client.log('INFO', `${data.title}: ${data.message}`); } } -async function playerDeath(client, guild, full, data, body, ownerId) { - let member = await DiscordTools.getMemberById(guild.id, ownerId); +async function alarmRaidAlarm(client, guild, full, data, body) { + const instance = client.readInstanceFile(guild.id); - if (member !== undefined) { - let png = null; - if (body.targetId !== '') { - png = await Scrape.scrapeSteamProfilePicture(client, body.targetId); - } + const content = { + embeds: [DiscordEmbeds.getAlarmRaidAlarmEmbed(data, body)], + content: '@everyone' + } - if (png === null) { - png = (isValidUrl(body.img)) ? body.img : Constants.DEFAULT_SERVER_IMG; - } + await DiscordMessages.sendMessage(guild.id, content, null, instance.channelId.activity); - let embed = new EmbedBuilder() - .setColor('#ff0040') - .setThumbnail(png) - .setTitle(data.title) - .setTimestamp() - .setFooter({ text: body.name }); + const rustplus = client.rustplusInstances[guild.id]; + const serverId = `${body.ip}-${body.port}`; - if (body.targetId !== '') { - embed.setURL(`${Constants.STEAM_PROFILES_URL}${body.targetId}`) - } + if (rustplus && (serverId === rustplus.serverId)) { + rustplus.sendTeamMessageAsync(`${data.title}: ${data.message}`); + } + + client.log('INFO', `${data.title} ${data.message}`); +} + +async function playerDeath(client, guild, full, data, body, ownerId) { + const user = await DiscordTools.getUserById(guild.id, ownerId); - await client.messageSend(member, { embeds: [embed] }); + let png = null; + if (body.targetId !== '') png = await Scrape.scrapeSteamProfilePicture(client, body.targetId); + if (png === null) png = isValidUrl(body.img) ? body.img : Constants.DEFAULT_SERVER_IMG; + + const content = { + embeds: [DiscordEmbeds.getPlayerDeathEmbed(data, body, png)] + } + + if (user) { + await client.messageSend(user, content); } } async function teamLogin(client, guild, full, data, body) { - let instance = client.readInstanceFile(guild.id); - let serverId = `${body.ip}-${body.port}`; - let rustplus = client.rustplusInstances[guild.id]; - let channel = DiscordTools.getTextChannelById(guild.id, instance.channelId.activity); + const instance = client.readInstanceFile(guild.id); + + const content = { + embeds: [DiscordEmbeds.getTeamLoginEmbed(body, await Scrape.scrapeSteamProfilePicture(client, body.targetId))] + } + + const rustplus = client.rustplusInstances[guild.id]; + const serverId = `${body.ip}-${body.port}`; if (!rustplus || (rustplus && (serverId !== rustplus.serverId))) { - if (channel !== undefined) { - let png = await Scrape.scrapeSteamProfilePicture(client, body.targetId); - await client.messageSend(channel, { - embeds: [ - new EmbedBuilder() - .setColor('#00ff40') - .setAuthor({ - name: `${body.targetName} just connected.`, - iconURL: (png !== null) ? png : Constants.DEFAULT_SERVER_IMG, - url: `${Constants.STEAM_PROFILES_URL}${body.targetId}` - }) - .setTimestamp() - .setFooter({ text: body.name }) - ] - }); - client.log('INFO', `${body.targetName} just connected to ${body.name}.`); - } + await DiscordMessages.sendMessage(guild.id, content, null, instance.channelId.activity); + client.log('INFO', `${body.targetName} just connected to ${body.name}.`); } } async function newsNews(client, guild, full, data, body) { - let instance = client.readInstanceFile(guild.id); - let channel = DiscordTools.getTextChannelById(guild.id, instance.channelId.activity); - - if (channel !== undefined) { - await client.messageSend(channel, { - embeds: [ - new EmbedBuilder() - .setTitle(`NEWS: ${data.title}`) - .setColor('#ce412b') - .setDescription(`${data.message}`) - .setThumbnail(Constants.DEFAULT_SERVER_IMG) - .setTimestamp() - ], - components: [ - new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setStyle(ButtonStyle.Link) - .setLabel('LINK') - .setURL(isValidUrl(body.url) ? body.url : Constants.DEFAULT_SERVER_URL)) - ] - }); + const instance = client.readInstanceFile(guild.id); + + const content = { + embeds: [DiscordEmbeds.getNewsEmbed(data)], + components: [DiscordButtons.getNewsButton(body, isValidUrl(body.url))] } + + await DiscordMessages.sendMessage(guild.id, content, null, instance.channelId.activity); } \ No newline at end of file diff --git a/src/util/battlemetricsAPI.js b/src/util/battlemetricsAPI.js index ed9ad1ce5..11878b496 100644 --- a/src/util/battlemetricsAPI.js +++ b/src/util/battlemetricsAPI.js @@ -1,12 +1,12 @@ -const Scrape = require('./scrape.js'); const RandomUsernames = require('./RandomUsernames.json'); +const Scrape = require('./scrape.js'); module.exports = { getBattlemetricsServerId: async function (client, serverName) { - searchServerName = encodeURI(serverName); + let searchServerName = encodeURI(serverName); serverName = module.exports.escapeRegExp(serverName); searchServerName = searchServerName.replace('\#', '\*'); - const search = `https://www.battlemetrics.com/servers/search?q=${searchServerName}&sort=score`; + const search = `https://www.battlemetrics.com/servers/search?q=${searchServerName}&sort=score&game=rust`; const response = await Scrape.scrape(search); if (response.status !== 200) { @@ -114,4 +114,4 @@ module.exports = { escapeRegExp: function (text) { return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); }, -} \ No newline at end of file +} diff --git a/src/util/external/process_items.js b/src/util/external/process_items.js index fc1f9fa20..fc2fb3bc8 100644 --- a/src/util/external/process_items.js +++ b/src/util/external/process_items.js @@ -4,17 +4,17 @@ * into a single items.json file to be used in this project. */ -const fs = require('fs'); +const Fs = require('fs'); var items = {}; /* Iterate each file in current directory. */ -fs.readdirSync('.').forEach(file => { +Fs.readdirSync('.').forEach(file => { /* Check if file is item meta file. */ if (file.endsWith('.json')) { /* Read item meta. */ - var item = JSON.parse(fs.readFileSync(file)); + var item = JSON.parse(Fs.readFileSync(file)); /* Push item meta we want to keep. */ items[item.itemid] = { @@ -26,4 +26,4 @@ fs.readdirSync('.').forEach(file => { }); /* Write formatted json to items.json. */ -fs.writeFileSync('items.json', JSON.stringify(items, null, 4)); \ No newline at end of file +Fs.writeFileSync('items.json', JSON.stringify(items, null, 4)); \ No newline at end of file diff --git a/src/util/external/scrapeItemsRecycleData.js b/src/util/external/scrapeItemsRecycleData.js index 333eca630..5109639ea 100644 --- a/src/util/external/scrapeItemsRecycleData.js +++ b/src/util/external/scrapeItemsRecycleData.js @@ -5,8 +5,8 @@ * run this code that often. ¯\_(ツ)_/¯ */ -const fs = require('fs'); const Axios = require('axios'); +const Fs = require('fs'); const RUSTLABS_ITEMS_URL = 'https://rustlabs.com/group=itemlist'; const RUSTLABS_ITEM_SEARCH_URL = 'https://rustlabs.com/item/'; @@ -145,7 +145,7 @@ function convertToIdBased(itemsRecycleData) { } async function main() { - if (!fs.existsSync(`${__dirname}/itemsRecycleDataScrape.json`)) { + if (!Fs.existsSync(`${__dirname}/itemsRecycleDataScrape.json`)) { let items = await getArrayOfItemNames(); if (items === null) { console.error('Failed to get array of item names.'); @@ -158,13 +158,13 @@ async function main() { return; } - fs.writeFileSync(`${__dirname}/itemsRecycleDataScrape.json`, JSON.stringify(data, null, 2)); + Fs.writeFileSync(`${__dirname}/itemsRecycleDataScrape.json`, JSON.stringify(data, null, 2)); } - let itemsRecycleData = JSON.parse(fs.readFileSync(`${__dirname}/itemsRecycleDataScrape.json`, 'utf8')); + let itemsRecycleData = JSON.parse(Fs.readFileSync(`${__dirname}/itemsRecycleDataScrape.json`, 'utf8')); itemsRecycleData = convertToIdBased(itemsRecycleData); - fs.writeFileSync(`${__dirname}/itemsRecycleData.json`, JSON.stringify(itemsRecycleData, null, 2)); + Fs.writeFileSync(`${__dirname}/itemsRecycleData.json`, JSON.stringify(itemsRecycleData, null, 2)); } main() \ No newline at end of file diff --git a/src/util/instanceUtils.js b/src/util/instanceUtils.js new file mode 100644 index 000000000..6f3ceaae6 --- /dev/null +++ b/src/util/instanceUtils.js @@ -0,0 +1,21 @@ +const Client = require('../../index.ts'); + +module.exports = { + getSmartDevice: function (guildId, entityId) { + /* Temporary function till discord modals gets more functional */ + const instance = Client.client.readInstanceFile(guildId); + + for (const serverId in instance.serverList) { + for (const switchId in instance.serverList[serverId].switches) { + if (entityId === switchId) return { type: 'switch', serverId: serverId } + } + for (const alarmId in instance.serverList[serverId].alarms) { + if (entityId === alarmId) return { type: 'alarm', serverId: serverId } + } + for (const storageMonitorId in instance.serverList[serverId].storageMonitors) { + if (entityId === storageMonitorId) return { type: 'storageMonitor', serverId: serverId } + } + } + return null; + }, +} diff --git a/src/util/items.json b/src/util/items.json index ff7573b43..aa0c6a0b7 100644 --- a/src/util/items.json +++ b/src/util/items.json @@ -764,6 +764,11 @@ "name": "Skull Trophy", "description": "A decorative mount that can hold the skull of a friend or foe." }, + "975983052": { + "shortname": "trophy", + "name": "Twitch Rivals Trophy", + "description": "A trophy dedicated to the survivors of Rust Twitch Rivals" + }, "980333378": { "shortname": "attire.hide.poncho", "name": "Hide Poncho", @@ -784,6 +789,11 @@ "name": "Human Skull", "description": "A human skull." }, + "996757362": { + "shortname": "wagon", + "name": "Wagon", + "description": "A train car." + }, "998894949": { "shortname": "seed.corn", "name": "Corn Seed", @@ -1334,6 +1344,11 @@ "name": "Bleach", "description": "A powerful oxidizing agent. Can be used as a disinfectant." }, + "1556365900": { + "shortname": "grenade.molotov", + "name": "Molotov Cocktail", + "description": "An incendiary device" + }, "1557173737": { "shortname": "sunglasses02red", "name": "Sunglasses", @@ -1789,6 +1804,11 @@ "name": "Burlap Trousers", "description": "Trousers made out of burlap." }, + "2005491391": { + "shortname": "weapon.mod.extendedmags", + "name": "Extended Magazine", + "description": "Larger magazine size" + }, "2009734114": { "shortname": "xmasdoorwreath", "name": "Christmas Door Wreath", @@ -1982,7 +2002,7 @@ "-747743875": { "shortname": "attire.egg.suit", "name": "Egg Suit", - "description": "An eggsquisite egg costume, can be painted when unequipped." + "description": "An eggsquisite egg costume, can be painted when unequipped. Releasing publicly in 2023" }, "-1773144852": { "shortname": "attire.hide.skirt", @@ -2402,7 +2422,7 @@ "-379734527": { "shortname": "firework.boomer.pattern", "name": "Pattern Boomer", - "description": "A very large mortar type firework with an massive champagne colored explosion followed by smaller orange starbursts" + "description": "A special boomer which allows you light up the night sky with a custom pattern that you draw. Multiple colors and altitude settings are available." }, "-1553999294": { "shortname": "firework.boomer.red", @@ -2629,6 +2649,11 @@ "name": "Granola Bar", "description": "Granola Bar found as loot. Eating it provides a small boost to health, hunger." }, + "-936921910": { + "shortname": "grenade.flashbang", + "name": "Flashbang", + "description": "A bright explosive device which blinds and disorients anyone near it upon detonation" + }, "-568419968": { "shortname": "grub", "name": "Grub", @@ -2734,6 +2759,11 @@ "name": "Heavy Plate Pants", "description": "Offers superior protection at the cost of reduced movement speed." }, + "-1214542497": { + "shortname": "hmlmg", + "name": "HMLMG", + "description": "A hand made belt-fed light machine gun with high damage, high rate of fire, low accuracy during short bursts." + }, "-1442559428": { "shortname": "hobobarrel", "name": "Hobo Barrel", @@ -2794,6 +2824,7 @@ "name": "Inner Tube", "description": "An inflated tube for aquatic activities." }, + "undefined": {}, "-1163532624": { "shortname": "jacket", "name": "Jacket", @@ -2854,6 +2885,11 @@ "name": "Locker", "description": "A locker for keeping your clothes and armor safe!" }, + "-2027988285": { + "shortname": "locomotive", + "name": "Locomotive", + "description": "A powerful locomotive." + }, "-1469578201": { "shortname": "longsword", "name": "Longsword", @@ -3254,11 +3290,6 @@ "name": "Sickle", "description": "A very sharp curved cutting weapon. While its traditional role was to cut grass, this tool is also extremely versatile at cutting throats, perhaps trees, too." }, - "-394470247": { - "shortname": "sign.egg.suit", - "name": "Egg Suit Sign Test", - "description": "A 1-meter by 0.5-meter wooden sign that you can write on." - }, "-1647846966": { "shortname": "sign.hanging.ornate", "name": "Two Sided Ornate Hanging Sign", @@ -3447,7 +3478,12 @@ "-596876839": { "shortname": "spraycan", "name": "Spray Can", - "description": "Use the Spray Can to reskin your items. Press [attack2] while looking at an item to open the skin picker." + "description": "Use the Spray Can to leave Tags or reskin your items. Press [attack] to spray and [attack2] to reskin items. Insert spray attachments to spray in the world." + }, + "-1366326648": { + "shortname": "spraycandecal", + "name": "Spray Can Decal", + "description": "" }, "-369760990": { "shortname": "stash.small", diff --git a/src/util/keywords.js b/src/util/keywords.js index be56323c3..c997b7bd7 100644 --- a/src/util/keywords.js +++ b/src/util/keywords.js @@ -30,26 +30,17 @@ module.exports = { 'wipe' ], - getListOfUsedKeywords(client, guildId, serverId = null) { - let instance = client.readInstanceFile(guildId); + getListOfUsedKeywords: function (client, guildId, serverId) { + const instance = client.readInstanceFile(guildId); + let list = []; list = [...module.exports.commands]; - - for (const [id, value] of Object.entries(instance.switches)) { - if (serverId === null) { - list.push(value.command); - } - else { - if (value.serverId === serverId) { - list.push(value.command); - } - } + for (const [id, value] of Object.entries(instance.serverList[serverId].switches)) { + list.push(value.command); } - if (serverId) { - for (const [id, value] of Object.entries(instance.serverList[serverId].switchGroups)) { - list.push(value.command); - } + for (const [id, value] of Object.entries(instance.serverList[serverId].switchGroups)) { + list.push(value.command); } return list; diff --git a/src/util/scrape.js b/src/util/scrape.js index 5f60d4394..ce20d4097 100644 --- a/src/util/scrape.js +++ b/src/util/scrape.js @@ -1,4 +1,5 @@ const Axios = require('axios'); + const Constants = require('../util/constants.js'); module.exports = { diff --git a/src/util/string.js b/src/util/string.js index f26b811aa..633449ff6 100644 --- a/src/util/string.js +++ b/src/util/string.js @@ -1,16 +1,14 @@ module.exports = { similarity: function (s1, s2) { - var longer = s1; - var shorter = s2; + let longer = s1; + let shorter = s2; if (s1.length < s2.length) { longer = s2; shorter = s1; } - var longerLength = longer.length; - if (longerLength == 0) { - return 1.0; - } + let longerLength = longer.length; + if (longerLength === 0) return 1.0; return (longerLength - module.exports.editDistance(longer, shorter)) / parseFloat(longerLength); }, @@ -19,25 +17,25 @@ module.exports = { s1 = s1.toLowerCase(); s2 = s2.toLowerCase(); - var costs = new Array(); - for (var i = 0; i <= s1.length; i++) { - var lastValue = i; - for (var j = 0; j <= s2.length; j++) { - if (i == 0) + let costs = new Array(); + for (let i = 0; i <= s1.length; i++) { + let lastValue = i; + for (let j = 0; j <= s2.length; j++) { + if (i == 0) { costs[j] = j; + } else { if (j > 0) { - var newValue = costs[j - 1]; + let newValue = costs[j - 1]; if (s1.charAt(i - 1) != s2.charAt(j - 1)) - newValue = Math.min(Math.min(newValue, lastValue), - costs[j]) + 1; + newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1; costs[j - 1] = lastValue; lastValue = newValue; } } } - if (i > 0) - costs[s2.length] = lastValue; + + if (i > 0) costs[s2.length] = lastValue; } return costs[s2.length]; }, diff --git a/src/util/timer.js b/src/util/timer.js index d9d8b7a4a..feac6852a 100644 --- a/src/util/timer.js +++ b/src/util/timer.js @@ -1,6 +1,6 @@ module.exports = { timer: function (callback, delay, ...args) { - var id, started, remaining = delay, running = false; + let id, started, remaining = delay, running = false; this.start = function () { started = new Date(); @@ -39,12 +39,8 @@ module.exports = { this.start(); } - if (remaining <= 0) { - return 0; - } - else { - return remaining; - } + if (remaining <= 0) return 0; + return remaining; } this.isFinished = function () { @@ -64,9 +60,7 @@ module.exports = { getTimeLeftOfTimer: function (timer, ignore = '') { /* Returns the time left of a timer. If timer is not running, null will be returned. */ - if (timer.getStateRunning()) { - return this.secondsToFullScale(timer.getTimeLeft() / 1000, ignore); - } + if (timer.getStateRunning()) return this.secondsToFullScale(timer.getTimeLeft() / 1000, ignore); return null; }, @@ -88,7 +82,7 @@ module.exports = { let minutes = 0; let seconds = 0; - time = ''; + let time = ''; days += originalDays; if (days > 0 && !ignore.includes('d')) { diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..bf11ec948 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "module": "commonjs", /* Specify what module code is generated. */ + "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + "resolveJsonModule": true, /* Enable importing .json files. */ + "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + "checkJs": false, /* Enable error reporting in type-checked JavaScript files. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + "strict": true, /* Enable all strict type-checking options. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "outDir": "./dist", /* Redirect output structure to the directory. */ + } +}