├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.js ├── language ├── de.json └── en.json ├── package-lock.json ├── package.json ├── src ├── Controller │ ├── index.js │ ├── notifications │ │ ├── discord.js │ │ ├── index.js │ │ ├── telegram.js │ │ └── webhook.js │ ├── pterodactyl.js │ └── routes │ │ ├── index.js │ │ ├── stats.js │ │ └── status.js ├── Node │ └── index.js └── index.js └── tests └── index.js /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '15 9 * * 6' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | .env -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 BlueFox Development 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ptero-Status 2 | ![](https://img.shields.io/github/stars/BlueFox-Development/Ptero-Status) ![](https://img.shields.io/github/forks/BlueFox-Development/Ptero-Status) ![](https://img.shields.io/github/issues/BlueFox-Development/Ptero-Status) ![](https://img.shields.io/github/license/BlueFox-Development/Ptero-Status) ![](https://img.shields.io/discord/870418236078960791) 3 | 4 | # About 5 | PteroStatus is an easy to setup [pterodactyl](https://github.com/pterodactyl/panel) daemon status project. It will continuously update a discord embed with live stats from your daemons. 6 | 7 | ## Preview 8 | 9 | ![Preview](https://cdn.flaringphoenix.com/8j1s) 10 | 11 | # Installation 12 | 13 | Run the following command to install the npm package 14 | 15 | ```bash 16 | npm i pterostatus 17 | ``` 18 | 19 | ## Usage 20 | 21 | ### Node: 22 | ```javascript 23 | const Status = require('pterostatus'); 24 | 25 | const Node = new Status.Node({ 26 | name: 'Node1', 27 | interval: 15000, 28 | controller: 'http://91.109.117.42:4000', 29 | bearer_token: 'Some secure string' //Optional 30 | }); 31 | ``` 32 | 33 | ### Controller: (Simple) 34 | ```javascript 35 | const Status = require('pterostatus'); 36 | 37 | const Controller = new Status.Controller(4000, 'en', { 38 | interval: 15000 39 | }); 40 | ``` 41 | 42 | ### Controller: (Advanced) 43 | ```javascript 44 | const Status = require('pterostatus'); 45 | 46 | const Controller = new Status.Controller(4000, 'en', { 47 | discord: { 48 | token: 'BOT-TOKEN', 49 | channel: 'CHANNEL-ID', 50 | }, 51 | pterodactyl: { 52 | panel: 'https://panel.domain.com', 53 | apiKey: 'API-KEY' 54 | }, 55 | telegram: { 56 | tgtoken: 'Telegram Bot Token by @BotFather', 57 | tgchatID: 'Chat ID' 58 | }, 59 | notifications: { 60 | discord: 'https://discord.com/api/webhooks/881362307375067136/zAdAgNEdQ-h3agBh-uCYPBHu47RUWMe_JpBJCUkEelx5oDgIDX_hGi-1_xRT2j6DWZej', 61 | webhook: 'http://0.0.0.0:5000/webhook' 62 | }, 63 | node: { 64 | message: '**{node.name}**: [Memory: {node.memory.used}/{node.memory.total}] [Disk: {node.disk.used}/{node.disk.total}]', 65 | online: '🟢 **ONLINE**', 66 | offline: '🔴 **OFFLINE**' 67 | }, 68 | embed: { 69 | color: '#06cce2', 70 | title: 'Node Status', 71 | description: '**Nodes**:\n{nodes.list}\n\n**Total**:\nMemory: {memory.used}/{memory.total}\nDisk: {disk.used}/{disk.total}\n\n**Pterodactyl:**\nUsers: {pterodactyl.users}\nServers: {pterodactyl.servers}', 72 | footer: { 73 | text: 'Last updated: {lastupdated}', 74 | icon: 'https://i.imgur.com/9b1qwml.jpg' 75 | } 76 | }, 77 | interval: 15000, 78 | bearer_token: 'Some secure string' //Optional 79 | }); 80 | ``` 81 | 82 | ### Events 83 | ```javascript 84 | Controller.on('online', (node) => { 85 | console.log(`Node: "${node.nodeName}" has come back online!`); 86 | }); 87 | 88 | Controller.on('offline', (node) => { 89 | console.log(`Node: "${node.nodeName}" has gone offline!`); 90 | }); 91 | ``` 92 | 93 | ### Pterodactyl Application API Key 94 | You need to have pterodactyl panel installed in order to use PteroStatus' pterodactyl integration. 95 | Not all permissions are required on the api key. Please just give the following permissions to the api key 96 | ![Permissions](https://cdn.flaringphoenix.com/pRoQ) 97 | 98 | ### Placeholders: 99 | **NODE**:
100 | `{node.name}` - Node's name
101 | `{node.memory.used}` - Total node's memory
102 | `{node.memory.total}` - Total used memory
103 | `{node.disk.used}` - Total used disk
104 | `{node.disk.total}` - Total node's disk
105 | `{node.cpu.used}` - Total used cpu
106 | `{node.cpu.cores}` - Total cpu cores
107 | `{node.cpu}` - Displays the cpu model
108 | `{node.os}` - Displays the os
109 | `{node.status}` - Shows if it's online or offline
110 | 111 | **NODES**:
112 | `{nodes.online}` - Number of online nodes
113 | `{nodes.offline}` - Number of offline nodes
114 | `{nodes.list}` - List of nodes along with their statuses
115 | `{nodes.total}` - Number of total nodes
116 | 117 | **TOTAL**:
118 | `{memory.total}` - Total memory
119 | `{disk.total}` - Total disk
120 | `{cores.total}` - Total cores
121 | 122 | **USED**:
123 | `{memory.used}` - Total memory used by nodes
124 | `{disk.used}` - Total disk used by nodes
125 | `{memory.used%}` - Total memory percentage used by nodes
126 | `{disk.used%}` - Total disk percentage used by nodes
127 | 128 | **PTERODACTYL**:
129 | `{pterodactyl.users}` - Number of current panel users
130 | `{pterodactyl.servers}` - Number of current panel servers
131 | 132 | ### Language: 133 | The currently supported languages ​​are English(en) and German(de) 134 | 135 | ### Bearer Authentication: 136 | The option bearer_token can be set in the DAEMON and CONTROLLER, it will make sure that only your nodes can communicate with eatch other. 137 | If you are using this it is recommended to use HTTPS for extra security. 138 | 139 | # Support 140 | Need some help setting up Ptero-Status? 141 | Join BlueFox Development's Discord 142 | > [https://discord.gg/KHbBfWSdnZ](https://discord.gg/KHbBfWSdnZ) 143 | 144 | ## Contributing 145 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 146 | 147 | Please make sure to update tests as appropriate. 148 | 149 | ## License 150 | [MIT](https://choosealicense.com/licenses/mit/) 151 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./src'); -------------------------------------------------------------------------------- /language/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "node": { 3 | "online": "🟢 **ONLINE**", 4 | "offline": "🔴 **OFFLINE**", 5 | "message": "**{node.name}**: {node.status} -> [Arbeitsspeicher: {node.memory.used}/{node.memory.total}] [Festplatte: {node.disk.used}/{node.disk.total}]" 6 | }, 7 | "embed": { 8 | "title": "Knoten Status [{nodes.total}]", 9 | "description": "**Knoten**:\n{nodes.list}" 10 | }, 11 | "notifications": { 12 | "discord": { 13 | "offline": { 14 | "title": "❌ Offline", 15 | "description": "Ein Ausfall des Servers **{{node_nodeName}}** wurde festgestellt" 16 | }, 17 | "online": { 18 | "title": "✅ Online", 19 | "description": "Der Server **{{node_nodeName}}** ist nun wieder erreichbar" 20 | } 21 | }, 22 | "telegram": { 23 | "offline": { 24 | "description": "Ein Ausfall des Servers {{node_nodeName}} wurde festgestellt" 25 | }, 26 | "online": { 27 | "description": "Der Server {{node_nodeName}} ist nun wieder erreichbar" 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /language/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "node": { 3 | "online": "🟢 **ONLINE**", 4 | "offline": "🔴 **OFFLINE**", 5 | "message": "**{node.name}**: {node.status} -> [Memory: {node.memory.used}/{node.memory.total}] [Disk: {node.disk.used}/{node.disk.total}]" 6 | }, 7 | "embed": { 8 | "title": "Node Status [{{nodes_total}}]", 9 | "description": "**Node**:\n{{nodes_list}}" 10 | }, 11 | "notifications": { 12 | "discord": { 13 | "offline": { 14 | "title": "❌ Offline", 15 | "description": "An outage has been detected on **{{node_nodeName}}**" 16 | }, 17 | "online": { 18 | "title": "✅ Online", 19 | "description": "The server is back online **{{node_nodeName}}**" 20 | } 21 | }, 22 | "telegram": { 23 | "offline": { 24 | "description": "An outage has been detected on {{node_nodeName}}" 25 | }, 26 | "online": { 27 | "description": "The server is back online {{node_nodeName}}" 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pterostatus", 3 | "version": "2.0.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "pterostatus", 9 | "version": "2.0.1", 10 | "license": "MIT", 11 | "dependencies": { 12 | "axios": "^0.21.1", 13 | "chalk": "^4.1.0", 14 | "discord.js": "^13.1.0", 15 | "dotenv": "^8.2.0", 16 | "express": "^4.17.1", 17 | "express-rate-limit": "^5.2.5", 18 | "liquidcache": "^1.0.0", 19 | "new-i18n": "^3.0.0-5", 20 | "os": "^0.1.1", 21 | "systeminformation": "^5.3.3" 22 | } 23 | }, 24 | "node_modules/@discordjs/builders": { 25 | "version": "0.5.0", 26 | "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.5.0.tgz", 27 | "integrity": "sha512-HP5y4Rqw68o61Qv4qM5tVmDbWi4mdTFftqIOGRo33SNPpLJ1Ga3KEIR2ibKofkmsoQhEpLmopD1AZDs3cKpHuw==", 28 | "dependencies": { 29 | "@sindresorhus/is": "^4.0.1", 30 | "discord-api-types": "^0.22.0", 31 | "ow": "^0.27.0", 32 | "ts-mixer": "^6.0.0", 33 | "tslib": "^2.3.0" 34 | }, 35 | "engines": { 36 | "node": ">=14.0.0", 37 | "npm": ">=7.0.0" 38 | } 39 | }, 40 | "node_modules/@discordjs/collection": { 41 | "version": "0.2.1", 42 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.1.tgz", 43 | "integrity": "sha512-vhxqzzM8gkomw0TYRF3tgx7SwElzUlXT/Aa41O7mOcyN6wIJfj5JmDWaO5XGKsGSsNx7F3i5oIlrucCCWV1Nog==", 44 | "engines": { 45 | "node": ">=14.0.0" 46 | } 47 | }, 48 | "node_modules/@discordjs/form-data": { 49 | "version": "3.0.1", 50 | "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", 51 | "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", 52 | "dependencies": { 53 | "asynckit": "^0.4.0", 54 | "combined-stream": "^1.0.8", 55 | "mime-types": "^2.1.12" 56 | }, 57 | "engines": { 58 | "node": ">= 6" 59 | } 60 | }, 61 | "node_modules/@sapphire/async-queue": { 62 | "version": "1.1.4", 63 | "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.4.tgz", 64 | "integrity": "sha512-fFrlF/uWpGOX5djw5Mu2Hnnrunao75WGey0sP0J3jnhmrJ5TAPzHYOmytD5iN/+pMxS+f+u/gezqHa9tPhRHEA==", 65 | "engines": { 66 | "node": ">=14", 67 | "npm": ">=6" 68 | } 69 | }, 70 | "node_modules/@sindresorhus/is": { 71 | "version": "4.0.1", 72 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", 73 | "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", 74 | "engines": { 75 | "node": ">=10" 76 | }, 77 | "funding": { 78 | "url": "https://github.com/sindresorhus/is?sponsor=1" 79 | } 80 | }, 81 | "node_modules/@types/node": { 82 | "version": "16.7.5", 83 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.5.tgz", 84 | "integrity": "sha512-E7SpxDXoHEpmZ9C1gSqwadhE6zPRtf3g0gJy9Y51DsImnR5TcDs3QEiV/3Q7zOM8LWaZp5Gph71NK6ElVMG1IQ==" 85 | }, 86 | "node_modules/@types/ws": { 87 | "version": "7.4.7", 88 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", 89 | "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", 90 | "dependencies": { 91 | "@types/node": "*" 92 | } 93 | }, 94 | "node_modules/accepts": { 95 | "version": "1.3.8", 96 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 97 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 98 | "dependencies": { 99 | "mime-types": "~2.1.34", 100 | "negotiator": "0.6.3" 101 | }, 102 | "engines": { 103 | "node": ">= 0.6" 104 | } 105 | }, 106 | "node_modules/ansi-styles": { 107 | "version": "4.3.0", 108 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 109 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 110 | "dependencies": { 111 | "color-convert": "^2.0.1" 112 | }, 113 | "engines": { 114 | "node": ">=8" 115 | }, 116 | "funding": { 117 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 118 | } 119 | }, 120 | "node_modules/array-flatten": { 121 | "version": "1.1.1", 122 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 123 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 124 | }, 125 | "node_modules/asynckit": { 126 | "version": "0.4.0", 127 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 128 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 129 | }, 130 | "node_modules/axios": { 131 | "version": "0.21.2", 132 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.2.tgz", 133 | "integrity": "sha512-87otirqUw3e8CzHTMO+/9kh/FSgXt/eVDvipijwDtEuwbkySWZ9SBm6VEubmJ/kLKEoLQV/POhxXFb66bfekfg==", 134 | "dependencies": { 135 | "follow-redirects": "^1.14.0" 136 | } 137 | }, 138 | "node_modules/body-parser": { 139 | "version": "1.19.2", 140 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", 141 | "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", 142 | "dependencies": { 143 | "bytes": "3.1.2", 144 | "content-type": "~1.0.4", 145 | "debug": "2.6.9", 146 | "depd": "~1.1.2", 147 | "http-errors": "1.8.1", 148 | "iconv-lite": "0.4.24", 149 | "on-finished": "~2.3.0", 150 | "qs": "6.9.7", 151 | "raw-body": "2.4.3", 152 | "type-is": "~1.6.18" 153 | }, 154 | "engines": { 155 | "node": ">= 0.8" 156 | } 157 | }, 158 | "node_modules/bytes": { 159 | "version": "3.1.2", 160 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 161 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 162 | "engines": { 163 | "node": ">= 0.8" 164 | } 165 | }, 166 | "node_modules/callsites": { 167 | "version": "3.1.0", 168 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 169 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 170 | "engines": { 171 | "node": ">=6" 172 | } 173 | }, 174 | "node_modules/chalk": { 175 | "version": "4.1.2", 176 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 177 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 178 | "dependencies": { 179 | "ansi-styles": "^4.1.0", 180 | "supports-color": "^7.1.0" 181 | }, 182 | "engines": { 183 | "node": ">=10" 184 | }, 185 | "funding": { 186 | "url": "https://github.com/chalk/chalk?sponsor=1" 187 | } 188 | }, 189 | "node_modules/color-convert": { 190 | "version": "2.0.1", 191 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 192 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 193 | "dependencies": { 194 | "color-name": "~1.1.4" 195 | }, 196 | "engines": { 197 | "node": ">=7.0.0" 198 | } 199 | }, 200 | "node_modules/color-name": { 201 | "version": "1.1.4", 202 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 203 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 204 | }, 205 | "node_modules/combined-stream": { 206 | "version": "1.0.8", 207 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 208 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 209 | "dependencies": { 210 | "delayed-stream": "~1.0.0" 211 | }, 212 | "engines": { 213 | "node": ">= 0.8" 214 | } 215 | }, 216 | "node_modules/content-disposition": { 217 | "version": "0.5.4", 218 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 219 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 220 | "dependencies": { 221 | "safe-buffer": "5.2.1" 222 | }, 223 | "engines": { 224 | "node": ">= 0.6" 225 | } 226 | }, 227 | "node_modules/content-type": { 228 | "version": "1.0.4", 229 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 230 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 231 | "engines": { 232 | "node": ">= 0.6" 233 | } 234 | }, 235 | "node_modules/cookie": { 236 | "version": "0.4.2", 237 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", 238 | "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", 239 | "engines": { 240 | "node": ">= 0.6" 241 | } 242 | }, 243 | "node_modules/cookie-signature": { 244 | "version": "1.0.6", 245 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 246 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 247 | }, 248 | "node_modules/debug": { 249 | "version": "2.6.9", 250 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 251 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 252 | "dependencies": { 253 | "ms": "2.0.0" 254 | } 255 | }, 256 | "node_modules/delayed-stream": { 257 | "version": "1.0.0", 258 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 259 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 260 | "engines": { 261 | "node": ">=0.4.0" 262 | } 263 | }, 264 | "node_modules/depd": { 265 | "version": "1.1.2", 266 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 267 | "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", 268 | "engines": { 269 | "node": ">= 0.6" 270 | } 271 | }, 272 | "node_modules/destroy": { 273 | "version": "1.0.4", 274 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 275 | "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" 276 | }, 277 | "node_modules/discord-api-types": { 278 | "version": "0.22.0", 279 | "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz", 280 | "integrity": "sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg==", 281 | "engines": { 282 | "node": ">=12" 283 | } 284 | }, 285 | "node_modules/discord.js": { 286 | "version": "13.1.0", 287 | "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.1.0.tgz", 288 | "integrity": "sha512-gxO4CXKdHpqA+WKG+f5RNnd3srTDj5uFJHgOathksDE90YNq/Qijkd2WlMgTTMS6AJoEnHxI7G9eDQHCuZ+xDA==", 289 | "dependencies": { 290 | "@discordjs/builders": "^0.5.0", 291 | "@discordjs/collection": "^0.2.1", 292 | "@discordjs/form-data": "^3.0.1", 293 | "@sapphire/async-queue": "^1.1.4", 294 | "@types/ws": "^7.4.7", 295 | "discord-api-types": "^0.22.0", 296 | "node-fetch": "^2.6.1", 297 | "ws": "^7.5.1" 298 | }, 299 | "engines": { 300 | "node": ">=16.6.0", 301 | "npm": ">=7.0.0" 302 | } 303 | }, 304 | "node_modules/dot-prop": { 305 | "version": "6.0.1", 306 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", 307 | "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", 308 | "dependencies": { 309 | "is-obj": "^2.0.0" 310 | }, 311 | "engines": { 312 | "node": ">=10" 313 | }, 314 | "funding": { 315 | "url": "https://github.com/sponsors/sindresorhus" 316 | } 317 | }, 318 | "node_modules/dotenv": { 319 | "version": "8.6.0", 320 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", 321 | "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", 322 | "engines": { 323 | "node": ">=10" 324 | } 325 | }, 326 | "node_modules/ee-first": { 327 | "version": "1.1.1", 328 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 329 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 330 | }, 331 | "node_modules/encodeurl": { 332 | "version": "1.0.2", 333 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 334 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 335 | "engines": { 336 | "node": ">= 0.8" 337 | } 338 | }, 339 | "node_modules/escape-html": { 340 | "version": "1.0.3", 341 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 342 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 343 | }, 344 | "node_modules/etag": { 345 | "version": "1.8.1", 346 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 347 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 348 | "engines": { 349 | "node": ">= 0.6" 350 | } 351 | }, 352 | "node_modules/express": { 353 | "version": "4.17.3", 354 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", 355 | "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", 356 | "dependencies": { 357 | "accepts": "~1.3.8", 358 | "array-flatten": "1.1.1", 359 | "body-parser": "1.19.2", 360 | "content-disposition": "0.5.4", 361 | "content-type": "~1.0.4", 362 | "cookie": "0.4.2", 363 | "cookie-signature": "1.0.6", 364 | "debug": "2.6.9", 365 | "depd": "~1.1.2", 366 | "encodeurl": "~1.0.2", 367 | "escape-html": "~1.0.3", 368 | "etag": "~1.8.1", 369 | "finalhandler": "~1.1.2", 370 | "fresh": "0.5.2", 371 | "merge-descriptors": "1.0.1", 372 | "methods": "~1.1.2", 373 | "on-finished": "~2.3.0", 374 | "parseurl": "~1.3.3", 375 | "path-to-regexp": "0.1.7", 376 | "proxy-addr": "~2.0.7", 377 | "qs": "6.9.7", 378 | "range-parser": "~1.2.1", 379 | "safe-buffer": "5.2.1", 380 | "send": "0.17.2", 381 | "serve-static": "1.14.2", 382 | "setprototypeof": "1.2.0", 383 | "statuses": "~1.5.0", 384 | "type-is": "~1.6.18", 385 | "utils-merge": "1.0.1", 386 | "vary": "~1.1.2" 387 | }, 388 | "engines": { 389 | "node": ">= 0.10.0" 390 | } 391 | }, 392 | "node_modules/express-rate-limit": { 393 | "version": "5.3.0", 394 | "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.3.0.tgz", 395 | "integrity": "sha512-qJhfEgCnmteSeZAeuOKQ2WEIFTX5ajrzE0xS6gCOBCoRQcU+xEzQmgYQQTpzCcqUAAzTEtu4YEih4pnLfvNtew==" 396 | }, 397 | "node_modules/finalhandler": { 398 | "version": "1.1.2", 399 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 400 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 401 | "dependencies": { 402 | "debug": "2.6.9", 403 | "encodeurl": "~1.0.2", 404 | "escape-html": "~1.0.3", 405 | "on-finished": "~2.3.0", 406 | "parseurl": "~1.3.3", 407 | "statuses": "~1.5.0", 408 | "unpipe": "~1.0.0" 409 | }, 410 | "engines": { 411 | "node": ">= 0.8" 412 | } 413 | }, 414 | "node_modules/follow-redirects": { 415 | "version": "1.14.8", 416 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", 417 | "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", 418 | "funding": [ 419 | { 420 | "type": "individual", 421 | "url": "https://github.com/sponsors/RubenVerborgh" 422 | } 423 | ], 424 | "engines": { 425 | "node": ">=4.0" 426 | }, 427 | "peerDependenciesMeta": { 428 | "debug": { 429 | "optional": true 430 | } 431 | } 432 | }, 433 | "node_modules/forwarded": { 434 | "version": "0.2.0", 435 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 436 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 437 | "engines": { 438 | "node": ">= 0.6" 439 | } 440 | }, 441 | "node_modules/fresh": { 442 | "version": "0.5.2", 443 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 444 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 445 | "engines": { 446 | "node": ">= 0.6" 447 | } 448 | }, 449 | "node_modules/has-flag": { 450 | "version": "4.0.0", 451 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 452 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 453 | "engines": { 454 | "node": ">=8" 455 | } 456 | }, 457 | "node_modules/http-errors": { 458 | "version": "1.8.1", 459 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", 460 | "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", 461 | "dependencies": { 462 | "depd": "~1.1.2", 463 | "inherits": "2.0.4", 464 | "setprototypeof": "1.2.0", 465 | "statuses": ">= 1.5.0 < 2", 466 | "toidentifier": "1.0.1" 467 | }, 468 | "engines": { 469 | "node": ">= 0.6" 470 | } 471 | }, 472 | "node_modules/iconv-lite": { 473 | "version": "0.4.24", 474 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 475 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 476 | "dependencies": { 477 | "safer-buffer": ">= 2.1.2 < 3" 478 | }, 479 | "engines": { 480 | "node": ">=0.10.0" 481 | } 482 | }, 483 | "node_modules/inherits": { 484 | "version": "2.0.4", 485 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 486 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 487 | }, 488 | "node_modules/ipaddr.js": { 489 | "version": "1.9.1", 490 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 491 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 492 | "engines": { 493 | "node": ">= 0.10" 494 | } 495 | }, 496 | "node_modules/is-obj": { 497 | "version": "2.0.0", 498 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", 499 | "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", 500 | "engines": { 501 | "node": ">=8" 502 | } 503 | }, 504 | "node_modules/liquidcache": { 505 | "version": "1.0.0", 506 | "resolved": "https://registry.npmjs.org/liquidcache/-/liquidcache-1.0.0.tgz", 507 | "integrity": "sha512-onylgM5LG3qcgbwmYz4nSbQdSMwXbL+0Xl+uujGbcYkrvLZukdrzNiXGIzZXRL88L+VgQWgk5HP8O2wNi+EMAA==", 508 | "dependencies": { 509 | "viall": "^1.2.0" 510 | } 511 | }, 512 | "node_modules/lodash.isequal": { 513 | "version": "4.5.0", 514 | "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", 515 | "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" 516 | }, 517 | "node_modules/media-typer": { 518 | "version": "0.3.0", 519 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 520 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 521 | "engines": { 522 | "node": ">= 0.6" 523 | } 524 | }, 525 | "node_modules/merge-descriptors": { 526 | "version": "1.0.1", 527 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 528 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 529 | }, 530 | "node_modules/methods": { 531 | "version": "1.1.2", 532 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 533 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", 534 | "engines": { 535 | "node": ">= 0.6" 536 | } 537 | }, 538 | "node_modules/mime": { 539 | "version": "1.6.0", 540 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 541 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 542 | "bin": { 543 | "mime": "cli.js" 544 | }, 545 | "engines": { 546 | "node": ">=4" 547 | } 548 | }, 549 | "node_modules/mime-db": { 550 | "version": "1.52.0", 551 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 552 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 553 | "engines": { 554 | "node": ">= 0.6" 555 | } 556 | }, 557 | "node_modules/mime-types": { 558 | "version": "2.1.35", 559 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 560 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 561 | "dependencies": { 562 | "mime-db": "1.52.0" 563 | }, 564 | "engines": { 565 | "node": ">= 0.6" 566 | } 567 | }, 568 | "node_modules/ms": { 569 | "version": "2.0.0", 570 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 571 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 572 | }, 573 | "node_modules/negotiator": { 574 | "version": "0.6.3", 575 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 576 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 577 | "engines": { 578 | "node": ">= 0.6" 579 | } 580 | }, 581 | "node_modules/new-i18n": { 582 | "version": "3.0.0-5", 583 | "resolved": "https://registry.npmjs.org/new-i18n/-/new-i18n-3.0.0-5.tgz", 584 | "integrity": "sha512-WE6Y/n6wiOwbBCsDDnvtIWPGcHtZdKhbYNWw5IQ32m+Ib78kQ4O8DlfEvFsWhjI/aXjmIt4wf1LuYVr+Xu1bQg==" 585 | }, 586 | "node_modules/node-fetch": { 587 | "version": "2.6.7", 588 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", 589 | "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", 590 | "dependencies": { 591 | "whatwg-url": "^5.0.0" 592 | }, 593 | "engines": { 594 | "node": "4.x || >=6.0.0" 595 | }, 596 | "peerDependencies": { 597 | "encoding": "^0.1.0" 598 | }, 599 | "peerDependenciesMeta": { 600 | "encoding": { 601 | "optional": true 602 | } 603 | } 604 | }, 605 | "node_modules/on-finished": { 606 | "version": "2.3.0", 607 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 608 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 609 | "dependencies": { 610 | "ee-first": "1.1.1" 611 | }, 612 | "engines": { 613 | "node": ">= 0.8" 614 | } 615 | }, 616 | "node_modules/os": { 617 | "version": "0.1.2", 618 | "resolved": "https://registry.npmjs.org/os/-/os-0.1.2.tgz", 619 | "integrity": "sha512-ZoXJkvAnljwvc56MbvhtKVWmSkzV712k42Is2mA0+0KTSRakq5XXuXpjZjgAt9ctzl51ojhQWakQQpmOvXWfjQ==" 620 | }, 621 | "node_modules/ow": { 622 | "version": "0.27.0", 623 | "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", 624 | "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==", 625 | "dependencies": { 626 | "@sindresorhus/is": "^4.0.1", 627 | "callsites": "^3.1.0", 628 | "dot-prop": "^6.0.1", 629 | "lodash.isequal": "^4.5.0", 630 | "type-fest": "^1.2.1", 631 | "vali-date": "^1.0.0" 632 | }, 633 | "engines": { 634 | "node": ">=12" 635 | }, 636 | "funding": { 637 | "url": "https://github.com/sponsors/sindresorhus" 638 | } 639 | }, 640 | "node_modules/parseurl": { 641 | "version": "1.3.3", 642 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 643 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 644 | "engines": { 645 | "node": ">= 0.8" 646 | } 647 | }, 648 | "node_modules/path-to-regexp": { 649 | "version": "0.1.7", 650 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 651 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 652 | }, 653 | "node_modules/proxy-addr": { 654 | "version": "2.0.7", 655 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 656 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 657 | "dependencies": { 658 | "forwarded": "0.2.0", 659 | "ipaddr.js": "1.9.1" 660 | }, 661 | "engines": { 662 | "node": ">= 0.10" 663 | } 664 | }, 665 | "node_modules/qs": { 666 | "version": "6.9.7", 667 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", 668 | "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", 669 | "engines": { 670 | "node": ">=0.6" 671 | }, 672 | "funding": { 673 | "url": "https://github.com/sponsors/ljharb" 674 | } 675 | }, 676 | "node_modules/range-parser": { 677 | "version": "1.2.1", 678 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 679 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 680 | "engines": { 681 | "node": ">= 0.6" 682 | } 683 | }, 684 | "node_modules/raw-body": { 685 | "version": "2.4.3", 686 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", 687 | "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", 688 | "dependencies": { 689 | "bytes": "3.1.2", 690 | "http-errors": "1.8.1", 691 | "iconv-lite": "0.4.24", 692 | "unpipe": "1.0.0" 693 | }, 694 | "engines": { 695 | "node": ">= 0.8" 696 | } 697 | }, 698 | "node_modules/safe-buffer": { 699 | "version": "5.2.1", 700 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 701 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 702 | "funding": [ 703 | { 704 | "type": "github", 705 | "url": "https://github.com/sponsors/feross" 706 | }, 707 | { 708 | "type": "patreon", 709 | "url": "https://www.patreon.com/feross" 710 | }, 711 | { 712 | "type": "consulting", 713 | "url": "https://feross.org/support" 714 | } 715 | ] 716 | }, 717 | "node_modules/safer-buffer": { 718 | "version": "2.1.2", 719 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 720 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 721 | }, 722 | "node_modules/send": { 723 | "version": "0.17.2", 724 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", 725 | "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", 726 | "dependencies": { 727 | "debug": "2.6.9", 728 | "depd": "~1.1.2", 729 | "destroy": "~1.0.4", 730 | "encodeurl": "~1.0.2", 731 | "escape-html": "~1.0.3", 732 | "etag": "~1.8.1", 733 | "fresh": "0.5.2", 734 | "http-errors": "1.8.1", 735 | "mime": "1.6.0", 736 | "ms": "2.1.3", 737 | "on-finished": "~2.3.0", 738 | "range-parser": "~1.2.1", 739 | "statuses": "~1.5.0" 740 | }, 741 | "engines": { 742 | "node": ">= 0.8.0" 743 | } 744 | }, 745 | "node_modules/send/node_modules/ms": { 746 | "version": "2.1.3", 747 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 748 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 749 | }, 750 | "node_modules/serve-static": { 751 | "version": "1.14.2", 752 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", 753 | "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", 754 | "dependencies": { 755 | "encodeurl": "~1.0.2", 756 | "escape-html": "~1.0.3", 757 | "parseurl": "~1.3.3", 758 | "send": "0.17.2" 759 | }, 760 | "engines": { 761 | "node": ">= 0.8.0" 762 | } 763 | }, 764 | "node_modules/setprototypeof": { 765 | "version": "1.2.0", 766 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 767 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 768 | }, 769 | "node_modules/statuses": { 770 | "version": "1.5.0", 771 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 772 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", 773 | "engines": { 774 | "node": ">= 0.6" 775 | } 776 | }, 777 | "node_modules/supports-color": { 778 | "version": "7.2.0", 779 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 780 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 781 | "dependencies": { 782 | "has-flag": "^4.0.0" 783 | }, 784 | "engines": { 785 | "node": ">=8" 786 | } 787 | }, 788 | "node_modules/systeminformation": { 789 | "version": "5.8.6", 790 | "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.8.6.tgz", 791 | "integrity": "sha512-R37NZR9f6OejKvERiatjh1vK49xkJ/MOgFpwpCw2h0NoD+1nKAgGzxkyjNX7bsf6ADaKzyAZ2SFK1mXddytIaA==", 792 | "os": [ 793 | "darwin", 794 | "linux", 795 | "win32", 796 | "freebsd", 797 | "openbsd", 798 | "netbsd", 799 | "sunos" 800 | ], 801 | "bin": { 802 | "systeminformation": "lib/cli.js" 803 | }, 804 | "engines": { 805 | "node": ">=4.0.0" 806 | }, 807 | "funding": { 808 | "type": "Buy me a coffee", 809 | "url": "https://www.buymeacoffee.com/systeminfo" 810 | } 811 | }, 812 | "node_modules/toidentifier": { 813 | "version": "1.0.1", 814 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 815 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 816 | "engines": { 817 | "node": ">=0.6" 818 | } 819 | }, 820 | "node_modules/tr46": { 821 | "version": "0.0.3", 822 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 823 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 824 | }, 825 | "node_modules/ts-mixer": { 826 | "version": "6.0.0", 827 | "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", 828 | "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==" 829 | }, 830 | "node_modules/tslib": { 831 | "version": "2.3.1", 832 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", 833 | "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" 834 | }, 835 | "node_modules/type-fest": { 836 | "version": "1.4.0", 837 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", 838 | "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", 839 | "engines": { 840 | "node": ">=10" 841 | }, 842 | "funding": { 843 | "url": "https://github.com/sponsors/sindresorhus" 844 | } 845 | }, 846 | "node_modules/type-is": { 847 | "version": "1.6.18", 848 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 849 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 850 | "dependencies": { 851 | "media-typer": "0.3.0", 852 | "mime-types": "~2.1.24" 853 | }, 854 | "engines": { 855 | "node": ">= 0.6" 856 | } 857 | }, 858 | "node_modules/unpipe": { 859 | "version": "1.0.0", 860 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 861 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 862 | "engines": { 863 | "node": ">= 0.8" 864 | } 865 | }, 866 | "node_modules/utils-merge": { 867 | "version": "1.0.1", 868 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 869 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", 870 | "engines": { 871 | "node": ">= 0.4.0" 872 | } 873 | }, 874 | "node_modules/vali-date": { 875 | "version": "1.0.0", 876 | "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", 877 | "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", 878 | "engines": { 879 | "node": ">=0.10.0" 880 | } 881 | }, 882 | "node_modules/vary": { 883 | "version": "1.1.2", 884 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 885 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", 886 | "engines": { 887 | "node": ">= 0.8" 888 | } 889 | }, 890 | "node_modules/viall": { 891 | "version": "1.2.0", 892 | "resolved": "https://registry.npmjs.org/viall/-/viall-1.2.0.tgz", 893 | "integrity": "sha512-tkb+fs2VmH/doLAV5dinCfB6QW7ByiMgEwzGDKGuQVmBzOTk1/O9A9RGjuFYVqiLInN3ba6wZAB/0JnM8mvKog==" 894 | }, 895 | "node_modules/webidl-conversions": { 896 | "version": "3.0.1", 897 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 898 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 899 | }, 900 | "node_modules/whatwg-url": { 901 | "version": "5.0.0", 902 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 903 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 904 | "dependencies": { 905 | "tr46": "~0.0.3", 906 | "webidl-conversions": "^3.0.0" 907 | } 908 | }, 909 | "node_modules/ws": { 910 | "version": "7.5.4", 911 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.4.tgz", 912 | "integrity": "sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg==", 913 | "engines": { 914 | "node": ">=8.3.0" 915 | }, 916 | "peerDependencies": { 917 | "bufferutil": "^4.0.1", 918 | "utf-8-validate": "^5.0.2" 919 | }, 920 | "peerDependenciesMeta": { 921 | "bufferutil": { 922 | "optional": true 923 | }, 924 | "utf-8-validate": { 925 | "optional": true 926 | } 927 | } 928 | } 929 | }, 930 | "dependencies": { 931 | "@discordjs/builders": { 932 | "version": "0.5.0", 933 | "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.5.0.tgz", 934 | "integrity": "sha512-HP5y4Rqw68o61Qv4qM5tVmDbWi4mdTFftqIOGRo33SNPpLJ1Ga3KEIR2ibKofkmsoQhEpLmopD1AZDs3cKpHuw==", 935 | "requires": { 936 | "@sindresorhus/is": "^4.0.1", 937 | "discord-api-types": "^0.22.0", 938 | "ow": "^0.27.0", 939 | "ts-mixer": "^6.0.0", 940 | "tslib": "^2.3.0" 941 | } 942 | }, 943 | "@discordjs/collection": { 944 | "version": "0.2.1", 945 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.1.tgz", 946 | "integrity": "sha512-vhxqzzM8gkomw0TYRF3tgx7SwElzUlXT/Aa41O7mOcyN6wIJfj5JmDWaO5XGKsGSsNx7F3i5oIlrucCCWV1Nog==" 947 | }, 948 | "@discordjs/form-data": { 949 | "version": "3.0.1", 950 | "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", 951 | "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", 952 | "requires": { 953 | "asynckit": "^0.4.0", 954 | "combined-stream": "^1.0.8", 955 | "mime-types": "^2.1.12" 956 | } 957 | }, 958 | "@sapphire/async-queue": { 959 | "version": "1.1.4", 960 | "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.4.tgz", 961 | "integrity": "sha512-fFrlF/uWpGOX5djw5Mu2Hnnrunao75WGey0sP0J3jnhmrJ5TAPzHYOmytD5iN/+pMxS+f+u/gezqHa9tPhRHEA==" 962 | }, 963 | "@sindresorhus/is": { 964 | "version": "4.0.1", 965 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", 966 | "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==" 967 | }, 968 | "@types/node": { 969 | "version": "16.7.5", 970 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.5.tgz", 971 | "integrity": "sha512-E7SpxDXoHEpmZ9C1gSqwadhE6zPRtf3g0gJy9Y51DsImnR5TcDs3QEiV/3Q7zOM8LWaZp5Gph71NK6ElVMG1IQ==" 972 | }, 973 | "@types/ws": { 974 | "version": "7.4.7", 975 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", 976 | "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", 977 | "requires": { 978 | "@types/node": "*" 979 | } 980 | }, 981 | "accepts": { 982 | "version": "1.3.8", 983 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 984 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 985 | "requires": { 986 | "mime-types": "~2.1.34", 987 | "negotiator": "0.6.3" 988 | } 989 | }, 990 | "ansi-styles": { 991 | "version": "4.3.0", 992 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 993 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 994 | "requires": { 995 | "color-convert": "^2.0.1" 996 | } 997 | }, 998 | "array-flatten": { 999 | "version": "1.1.1", 1000 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 1001 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 1002 | }, 1003 | "asynckit": { 1004 | "version": "0.4.0", 1005 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 1006 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 1007 | }, 1008 | "axios": { 1009 | "version": "0.21.2", 1010 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.2.tgz", 1011 | "integrity": "sha512-87otirqUw3e8CzHTMO+/9kh/FSgXt/eVDvipijwDtEuwbkySWZ9SBm6VEubmJ/kLKEoLQV/POhxXFb66bfekfg==", 1012 | "requires": { 1013 | "follow-redirects": "^1.14.0" 1014 | } 1015 | }, 1016 | "body-parser": { 1017 | "version": "1.19.2", 1018 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", 1019 | "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", 1020 | "requires": { 1021 | "bytes": "3.1.2", 1022 | "content-type": "~1.0.4", 1023 | "debug": "2.6.9", 1024 | "depd": "~1.1.2", 1025 | "http-errors": "1.8.1", 1026 | "iconv-lite": "0.4.24", 1027 | "on-finished": "~2.3.0", 1028 | "qs": "6.9.7", 1029 | "raw-body": "2.4.3", 1030 | "type-is": "~1.6.18" 1031 | } 1032 | }, 1033 | "bytes": { 1034 | "version": "3.1.2", 1035 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 1036 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 1037 | }, 1038 | "callsites": { 1039 | "version": "3.1.0", 1040 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 1041 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" 1042 | }, 1043 | "chalk": { 1044 | "version": "4.1.2", 1045 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 1046 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 1047 | "requires": { 1048 | "ansi-styles": "^4.1.0", 1049 | "supports-color": "^7.1.0" 1050 | } 1051 | }, 1052 | "color-convert": { 1053 | "version": "2.0.1", 1054 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1055 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1056 | "requires": { 1057 | "color-name": "~1.1.4" 1058 | } 1059 | }, 1060 | "color-name": { 1061 | "version": "1.1.4", 1062 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1063 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 1064 | }, 1065 | "combined-stream": { 1066 | "version": "1.0.8", 1067 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 1068 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 1069 | "requires": { 1070 | "delayed-stream": "~1.0.0" 1071 | } 1072 | }, 1073 | "content-disposition": { 1074 | "version": "0.5.4", 1075 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 1076 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 1077 | "requires": { 1078 | "safe-buffer": "5.2.1" 1079 | } 1080 | }, 1081 | "content-type": { 1082 | "version": "1.0.4", 1083 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 1084 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 1085 | }, 1086 | "cookie": { 1087 | "version": "0.4.2", 1088 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", 1089 | "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" 1090 | }, 1091 | "cookie-signature": { 1092 | "version": "1.0.6", 1093 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 1094 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 1095 | }, 1096 | "debug": { 1097 | "version": "2.6.9", 1098 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1099 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1100 | "requires": { 1101 | "ms": "2.0.0" 1102 | } 1103 | }, 1104 | "delayed-stream": { 1105 | "version": "1.0.0", 1106 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 1107 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 1108 | }, 1109 | "depd": { 1110 | "version": "1.1.2", 1111 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 1112 | "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" 1113 | }, 1114 | "destroy": { 1115 | "version": "1.0.4", 1116 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 1117 | "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" 1118 | }, 1119 | "discord-api-types": { 1120 | "version": "0.22.0", 1121 | "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz", 1122 | "integrity": "sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg==" 1123 | }, 1124 | "discord.js": { 1125 | "version": "13.1.0", 1126 | "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.1.0.tgz", 1127 | "integrity": "sha512-gxO4CXKdHpqA+WKG+f5RNnd3srTDj5uFJHgOathksDE90YNq/Qijkd2WlMgTTMS6AJoEnHxI7G9eDQHCuZ+xDA==", 1128 | "requires": { 1129 | "@discordjs/builders": "^0.5.0", 1130 | "@discordjs/collection": "^0.2.1", 1131 | "@discordjs/form-data": "^3.0.1", 1132 | "@sapphire/async-queue": "^1.1.4", 1133 | "@types/ws": "^7.4.7", 1134 | "discord-api-types": "^0.22.0", 1135 | "node-fetch": "^2.6.1", 1136 | "ws": "^7.5.1" 1137 | } 1138 | }, 1139 | "dot-prop": { 1140 | "version": "6.0.1", 1141 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", 1142 | "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", 1143 | "requires": { 1144 | "is-obj": "^2.0.0" 1145 | } 1146 | }, 1147 | "dotenv": { 1148 | "version": "8.6.0", 1149 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", 1150 | "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" 1151 | }, 1152 | "ee-first": { 1153 | "version": "1.1.1", 1154 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1155 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 1156 | }, 1157 | "encodeurl": { 1158 | "version": "1.0.2", 1159 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 1160 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 1161 | }, 1162 | "escape-html": { 1163 | "version": "1.0.3", 1164 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 1165 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 1166 | }, 1167 | "etag": { 1168 | "version": "1.8.1", 1169 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 1170 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 1171 | }, 1172 | "express": { 1173 | "version": "4.17.3", 1174 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", 1175 | "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", 1176 | "requires": { 1177 | "accepts": "~1.3.8", 1178 | "array-flatten": "1.1.1", 1179 | "body-parser": "1.19.2", 1180 | "content-disposition": "0.5.4", 1181 | "content-type": "~1.0.4", 1182 | "cookie": "0.4.2", 1183 | "cookie-signature": "1.0.6", 1184 | "debug": "2.6.9", 1185 | "depd": "~1.1.2", 1186 | "encodeurl": "~1.0.2", 1187 | "escape-html": "~1.0.3", 1188 | "etag": "~1.8.1", 1189 | "finalhandler": "~1.1.2", 1190 | "fresh": "0.5.2", 1191 | "merge-descriptors": "1.0.1", 1192 | "methods": "~1.1.2", 1193 | "on-finished": "~2.3.0", 1194 | "parseurl": "~1.3.3", 1195 | "path-to-regexp": "0.1.7", 1196 | "proxy-addr": "~2.0.7", 1197 | "qs": "6.9.7", 1198 | "range-parser": "~1.2.1", 1199 | "safe-buffer": "5.2.1", 1200 | "send": "0.17.2", 1201 | "serve-static": "1.14.2", 1202 | "setprototypeof": "1.2.0", 1203 | "statuses": "~1.5.0", 1204 | "type-is": "~1.6.18", 1205 | "utils-merge": "1.0.1", 1206 | "vary": "~1.1.2" 1207 | } 1208 | }, 1209 | "express-rate-limit": { 1210 | "version": "5.3.0", 1211 | "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.3.0.tgz", 1212 | "integrity": "sha512-qJhfEgCnmteSeZAeuOKQ2WEIFTX5ajrzE0xS6gCOBCoRQcU+xEzQmgYQQTpzCcqUAAzTEtu4YEih4pnLfvNtew==" 1213 | }, 1214 | "finalhandler": { 1215 | "version": "1.1.2", 1216 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 1217 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 1218 | "requires": { 1219 | "debug": "2.6.9", 1220 | "encodeurl": "~1.0.2", 1221 | "escape-html": "~1.0.3", 1222 | "on-finished": "~2.3.0", 1223 | "parseurl": "~1.3.3", 1224 | "statuses": "~1.5.0", 1225 | "unpipe": "~1.0.0" 1226 | } 1227 | }, 1228 | "follow-redirects": { 1229 | "version": "1.14.8", 1230 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", 1231 | "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" 1232 | }, 1233 | "forwarded": { 1234 | "version": "0.2.0", 1235 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 1236 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 1237 | }, 1238 | "fresh": { 1239 | "version": "0.5.2", 1240 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 1241 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 1242 | }, 1243 | "has-flag": { 1244 | "version": "4.0.0", 1245 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1246 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" 1247 | }, 1248 | "http-errors": { 1249 | "version": "1.8.1", 1250 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", 1251 | "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", 1252 | "requires": { 1253 | "depd": "~1.1.2", 1254 | "inherits": "2.0.4", 1255 | "setprototypeof": "1.2.0", 1256 | "statuses": ">= 1.5.0 < 2", 1257 | "toidentifier": "1.0.1" 1258 | } 1259 | }, 1260 | "iconv-lite": { 1261 | "version": "0.4.24", 1262 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 1263 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 1264 | "requires": { 1265 | "safer-buffer": ">= 2.1.2 < 3" 1266 | } 1267 | }, 1268 | "inherits": { 1269 | "version": "2.0.4", 1270 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1271 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1272 | }, 1273 | "ipaddr.js": { 1274 | "version": "1.9.1", 1275 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1276 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 1277 | }, 1278 | "is-obj": { 1279 | "version": "2.0.0", 1280 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", 1281 | "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" 1282 | }, 1283 | "liquidcache": { 1284 | "version": "1.0.0", 1285 | "resolved": "https://registry.npmjs.org/liquidcache/-/liquidcache-1.0.0.tgz", 1286 | "integrity": "sha512-onylgM5LG3qcgbwmYz4nSbQdSMwXbL+0Xl+uujGbcYkrvLZukdrzNiXGIzZXRL88L+VgQWgk5HP8O2wNi+EMAA==", 1287 | "requires": { 1288 | "viall": "^1.2.0" 1289 | } 1290 | }, 1291 | "lodash.isequal": { 1292 | "version": "4.5.0", 1293 | "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", 1294 | "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" 1295 | }, 1296 | "media-typer": { 1297 | "version": "0.3.0", 1298 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1299 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" 1300 | }, 1301 | "merge-descriptors": { 1302 | "version": "1.0.1", 1303 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 1304 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 1305 | }, 1306 | "methods": { 1307 | "version": "1.1.2", 1308 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1309 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 1310 | }, 1311 | "mime": { 1312 | "version": "1.6.0", 1313 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1314 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 1315 | }, 1316 | "mime-db": { 1317 | "version": "1.52.0", 1318 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1319 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 1320 | }, 1321 | "mime-types": { 1322 | "version": "2.1.35", 1323 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1324 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1325 | "requires": { 1326 | "mime-db": "1.52.0" 1327 | } 1328 | }, 1329 | "ms": { 1330 | "version": "2.0.0", 1331 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1332 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1333 | }, 1334 | "negotiator": { 1335 | "version": "0.6.3", 1336 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 1337 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 1338 | }, 1339 | "new-i18n": { 1340 | "version": "3.0.0-5", 1341 | "resolved": "https://registry.npmjs.org/new-i18n/-/new-i18n-3.0.0-5.tgz", 1342 | "integrity": "sha512-WE6Y/n6wiOwbBCsDDnvtIWPGcHtZdKhbYNWw5IQ32m+Ib78kQ4O8DlfEvFsWhjI/aXjmIt4wf1LuYVr+Xu1bQg==" 1343 | }, 1344 | "new-i18n": { 1345 | "version": "3.0.0-5", 1346 | "resolved": "https://registry.npmjs.org/new-i18n/-/new-i18n-3.0.0-5.tgz", 1347 | "integrity": "sha512-WE6Y/n6wiOwbBCsDDnvtIWPGcHtZdKhbYNWw5IQ32m+Ib78kQ4O8DlfEvFsWhjI/aXjmIt4wf1LuYVr+Xu1bQg==" 1348 | }, 1349 | "new-i18n": { 1350 | "version": "3.0.0-5", 1351 | "resolved": "https://registry.npmjs.org/new-i18n/-/new-i18n-3.0.0-5.tgz", 1352 | "integrity": "sha512-WE6Y/n6wiOwbBCsDDnvtIWPGcHtZdKhbYNWw5IQ32m+Ib78kQ4O8DlfEvFsWhjI/aXjmIt4wf1LuYVr+Xu1bQg==" 1353 | }, 1354 | "new-i18n": { 1355 | "version": "3.0.0-5", 1356 | "resolved": "https://registry.npmjs.org/new-i18n/-/new-i18n-3.0.0-5.tgz", 1357 | "integrity": "sha512-WE6Y/n6wiOwbBCsDDnvtIWPGcHtZdKhbYNWw5IQ32m+Ib78kQ4O8DlfEvFsWhjI/aXjmIt4wf1LuYVr+Xu1bQg==" 1358 | }, 1359 | "node-fetch": { 1360 | "version": "2.6.7", 1361 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", 1362 | "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", 1363 | "requires": { 1364 | "whatwg-url": "^5.0.0" 1365 | } 1366 | }, 1367 | "on-finished": { 1368 | "version": "2.3.0", 1369 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1370 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 1371 | "requires": { 1372 | "ee-first": "1.1.1" 1373 | } 1374 | }, 1375 | "os": { 1376 | "version": "0.1.2", 1377 | "resolved": "https://registry.npmjs.org/os/-/os-0.1.2.tgz", 1378 | "integrity": "sha512-ZoXJkvAnljwvc56MbvhtKVWmSkzV712k42Is2mA0+0KTSRakq5XXuXpjZjgAt9ctzl51ojhQWakQQpmOvXWfjQ==" 1379 | }, 1380 | "ow": { 1381 | "version": "0.27.0", 1382 | "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", 1383 | "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==", 1384 | "requires": { 1385 | "@sindresorhus/is": "^4.0.1", 1386 | "callsites": "^3.1.0", 1387 | "dot-prop": "^6.0.1", 1388 | "lodash.isequal": "^4.5.0", 1389 | "type-fest": "^1.2.1", 1390 | "vali-date": "^1.0.0" 1391 | } 1392 | }, 1393 | "parseurl": { 1394 | "version": "1.3.3", 1395 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1396 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1397 | }, 1398 | "path-to-regexp": { 1399 | "version": "0.1.7", 1400 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1401 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 1402 | }, 1403 | "proxy-addr": { 1404 | "version": "2.0.7", 1405 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1406 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1407 | "requires": { 1408 | "forwarded": "0.2.0", 1409 | "ipaddr.js": "1.9.1" 1410 | } 1411 | }, 1412 | "qs": { 1413 | "version": "6.9.7", 1414 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", 1415 | "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" 1416 | }, 1417 | "range-parser": { 1418 | "version": "1.2.1", 1419 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1420 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1421 | }, 1422 | "raw-body": { 1423 | "version": "2.4.3", 1424 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", 1425 | "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", 1426 | "requires": { 1427 | "bytes": "3.1.2", 1428 | "http-errors": "1.8.1", 1429 | "iconv-lite": "0.4.24", 1430 | "unpipe": "1.0.0" 1431 | } 1432 | }, 1433 | "safe-buffer": { 1434 | "version": "5.2.1", 1435 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1436 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1437 | }, 1438 | "safer-buffer": { 1439 | "version": "2.1.2", 1440 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1441 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1442 | }, 1443 | "send": { 1444 | "version": "0.17.2", 1445 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", 1446 | "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", 1447 | "requires": { 1448 | "debug": "2.6.9", 1449 | "depd": "~1.1.2", 1450 | "destroy": "~1.0.4", 1451 | "encodeurl": "~1.0.2", 1452 | "escape-html": "~1.0.3", 1453 | "etag": "~1.8.1", 1454 | "fresh": "0.5.2", 1455 | "http-errors": "1.8.1", 1456 | "mime": "1.6.0", 1457 | "ms": "2.1.3", 1458 | "on-finished": "~2.3.0", 1459 | "range-parser": "~1.2.1", 1460 | "statuses": "~1.5.0" 1461 | }, 1462 | "dependencies": { 1463 | "ms": { 1464 | "version": "2.1.3", 1465 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1466 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1467 | } 1468 | } 1469 | }, 1470 | "serve-static": { 1471 | "version": "1.14.2", 1472 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", 1473 | "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", 1474 | "requires": { 1475 | "encodeurl": "~1.0.2", 1476 | "escape-html": "~1.0.3", 1477 | "parseurl": "~1.3.3", 1478 | "send": "0.17.2" 1479 | } 1480 | }, 1481 | "setprototypeof": { 1482 | "version": "1.2.0", 1483 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1484 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1485 | }, 1486 | "statuses": { 1487 | "version": "1.5.0", 1488 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1489 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 1490 | }, 1491 | "supports-color": { 1492 | "version": "7.2.0", 1493 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1494 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1495 | "requires": { 1496 | "has-flag": "^4.0.0" 1497 | } 1498 | }, 1499 | "systeminformation": { 1500 | "version": "5.8.6", 1501 | "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.8.6.tgz", 1502 | "integrity": "sha512-R37NZR9f6OejKvERiatjh1vK49xkJ/MOgFpwpCw2h0NoD+1nKAgGzxkyjNX7bsf6ADaKzyAZ2SFK1mXddytIaA==" 1503 | }, 1504 | "toidentifier": { 1505 | "version": "1.0.1", 1506 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1507 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 1508 | }, 1509 | "tr46": { 1510 | "version": "0.0.3", 1511 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 1512 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 1513 | }, 1514 | "ts-mixer": { 1515 | "version": "6.0.0", 1516 | "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", 1517 | "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==" 1518 | }, 1519 | "tslib": { 1520 | "version": "2.3.1", 1521 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", 1522 | "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" 1523 | }, 1524 | "type-fest": { 1525 | "version": "1.4.0", 1526 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", 1527 | "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==" 1528 | }, 1529 | "type-is": { 1530 | "version": "1.6.18", 1531 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1532 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1533 | "requires": { 1534 | "media-typer": "0.3.0", 1535 | "mime-types": "~2.1.24" 1536 | } 1537 | }, 1538 | "unpipe": { 1539 | "version": "1.0.0", 1540 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1541 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1542 | }, 1543 | "utils-merge": { 1544 | "version": "1.0.1", 1545 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1546 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 1547 | }, 1548 | "vali-date": { 1549 | "version": "1.0.0", 1550 | "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", 1551 | "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=" 1552 | }, 1553 | "vary": { 1554 | "version": "1.1.2", 1555 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1556 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1557 | }, 1558 | "viall": { 1559 | "version": "1.2.0", 1560 | "resolved": "https://registry.npmjs.org/viall/-/viall-1.2.0.tgz", 1561 | "integrity": "sha512-tkb+fs2VmH/doLAV5dinCfB6QW7ByiMgEwzGDKGuQVmBzOTk1/O9A9RGjuFYVqiLInN3ba6wZAB/0JnM8mvKog==" 1562 | }, 1563 | "webidl-conversions": { 1564 | "version": "3.0.1", 1565 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 1566 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 1567 | }, 1568 | "whatwg-url": { 1569 | "version": "5.0.0", 1570 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 1571 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 1572 | "requires": { 1573 | "tr46": "~0.0.3", 1574 | "webidl-conversions": "^3.0.0" 1575 | } 1576 | }, 1577 | "ws": { 1578 | "version": "7.5.4", 1579 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.4.tgz", 1580 | "integrity": "sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg==", 1581 | "requires": {} 1582 | } 1583 | } 1584 | } 1585 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pterostatus", 3 | "version": "2.0.1", 4 | "description": "A npm package meant for tracking your nodes", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/FlaringPhoenix/Ptero-Status.git" 9 | }, 10 | "scripts": { 11 | "test": "node ./tests" 12 | }, 13 | "author": "FlaringPhoenix ", 14 | "license": "MIT", 15 | "homepage": "https://github.com/FlaringPhoenix/Ptero-Status#readme", 16 | "dependencies": { 17 | "axios": "^0.21.1", 18 | "chalk": "^4.1.0", 19 | "discord.js": "^13.1.0", 20 | "dotenv": "^8.2.0", 21 | "express": "^4.17.1", 22 | "express-rate-limit": "^5.2.5", 23 | "liquidcache": "^1.0.0", 24 | "new-i18n": "^3.0.0-5", 25 | "os": "^0.1.1", 26 | "systeminformation": "^5.3.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Controller/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const chalk = require('chalk'); 3 | const Cache = require('liquidcache'); 4 | const Discord = require('discord.js'); 5 | const Notifications = require('./notifications'); 6 | const Pterodactyl = require('./pterodactyl'); 7 | const EventEmitter = require('events'); 8 | const path = require('path'); 9 | const reqPath = path.join(__dirname, '../../'); 10 | const { default: i18n } = require('new-i18n'); 11 | const newi18n = new i18n({ folder: path.join(reqPath, '/language'), languages: ['en','de'], fallback: 'en' }) 12 | 13 | class Panel extends EventEmitter { 14 | constructor(port = 4000, language = 'de', options = {}) { 15 | super(); 16 | 17 | // Node cache 18 | Cache.set('nodes', []); 19 | Cache.set('status', {}); 20 | 21 | // Options 22 | if (options['interval']) this.interval = options['interval'] || 30000; 23 | 24 | if (options['discord']) { 25 | this.discord = options['discord']; 26 | this.token = this.discord['token']; 27 | this.channelID = this.discord['channel']; 28 | } 29 | 30 | if (options['telegram']) { 31 | this.telegram = options['telegram']; 32 | this.tgtoken = this.telegram['tgtoken']; 33 | this.tgchatID = this.telegram['tgchatID']; 34 | } 35 | 36 | if (options['node']) { 37 | this.node = options['node']; 38 | this.online = this.node['online'] || newi18n.translate(language, 'node.online'); 39 | this.offline = this.node['offline'] || newi18n.translate(language, 'node.offline'); 40 | this.nodeMessage = this.node['message'] || newi18n.translate(language, 'node.message'); 41 | } 42 | 43 | if (options['embed']) { 44 | this.embed = options['embed']; 45 | this.color = this.embed['color']; 46 | this.title = this.embed['title'] || newi18n.translate(language, 'embed.title'); 47 | this.description = this.embed['description'] || newi18n.translate(language, 'embed.description'); 48 | this.footer = this.embed['footer']; 49 | this.footerText = this.footer['text'] || ''; 50 | this.footerIcon = this.footer['icon'] || ''; 51 | this.thumbnail = this.embed['thumbnail'] || ''; 52 | } 53 | 54 | if (options['pterodactyl']) { 55 | this.ptero = options['pterodactyl']; 56 | this.panel = this.ptero['panel'] || null; 57 | this.apiKey = this.ptero['apiKey'] || null; 58 | } 59 | 60 | if (options['notifications']) { 61 | this.notifications = options['notifications']; 62 | if (this.notifications['discord']) this.discordWebhook = new Notifications.Discord(this.notifications['discord'], language); 63 | if (this.notifications['webhook']) this.webhook = new Notifications.Webhook(this.notifications['webhook']); 64 | } 65 | 66 | if (options['bearer_token']) { 67 | this.bearer_token = options['bearer_token'] 68 | } 69 | 70 | // Repo Information 71 | this.version = require('../../package.json')['version']; 72 | this.homepage = require('../../package.json')['homepage']; 73 | 74 | // Start 75 | if (this.discord) this.startBot(); 76 | if (this.ptero) this.startPterodactyl(); 77 | if (this.telegram) this.telegram = new Notifications.Telegram(this.tgtoken, this.tgchatID, language) 78 | 79 | // Setup express 80 | this.app = express(); 81 | this.app.use(express.json()); 82 | this.app.use(express.urlencoded({ extended: false })); 83 | 84 | // CORS middleware 85 | this.app.use((req, res, next) => { 86 | res.header('Access-Control-Allow-Origin', '*'); 87 | res.header('Access-Control-Allow-Methods', '*'); 88 | res.header('Access-Control-Allow-Headers', '*'); 89 | next(); 90 | }); 91 | 92 | //Bearer token auth middleware 93 | if (this.bearer_token) { 94 | this.app.use((req, res, next) => { 95 | if (!req.headers['authorization']) { 96 | this.elog(`Deamon "${req.body.nodeName}" tryed to send data without authorization!`) 97 | res.status(403).json({error: 'Bearer token is required'}) 98 | }else if (req.headers['authorization'] !== `Bearer ${this.bearer_token}`){ 99 | this.elog(`Deamon "${req.body.nodeName}" tryed to send data with incorrect authorization!`) 100 | res.status(403).json({error: 'Bearer token is not valid'}) 101 | }else{ 102 | next(); 103 | } 104 | }); 105 | } 106 | 107 | // Logging 108 | this.app.use((req, res, next) => { 109 | let realip = req.headers['x-forwarded-for'] || req.connection.remoteAddress.split(':').pop(); 110 | this.log(`${chalk.green(req.method)} request on ${chalk.red(req.originalUrl)} from ${chalk.white(realip)}`); 111 | next(); 112 | }); 113 | 114 | // Load routes 115 | this.app.use('/', require('./routes')); 116 | 117 | // Listen on the given port 118 | this.app.listen(port); 119 | this.log('Started! Listening on port: ' + port); 120 | } 121 | 122 | startBot() { 123 | this.client = new Discord.Client({ intents: ['GUILDS', 'GUILD_MESSAGES'] }); 124 | try { 125 | this.client.login(this.token); 126 | } catch(e) { 127 | this.log('Invalid bot token!'); 128 | return; 129 | } 130 | 131 | let that = this; 132 | setInterval(() => { 133 | that.log('Updating embed'); 134 | that.updateEmbed(); 135 | }, this.interval); 136 | } 137 | 138 | startPterodactyl(panel = this.panel, apiKey = this.apiKey, interval = this.interval) { 139 | if (!panel) return this.log('Missing pterodactyl panel url'); 140 | if (!apiKey) return this.log('Missing pterodactyl panel application api key'); 141 | 142 | this.pterodactyl = new Pterodactyl(panel, apiKey, interval); 143 | this.pterodactyl.init(); 144 | } 145 | 146 | async updateEmbed() { 147 | if (this.channel == undefined) this.channel = this.client.channels.cache.get(this.channelID); 148 | if (this.message == undefined) { 149 | let messages = await this.channel.messages.fetch({ limit: 5 }); 150 | let lastMessage = (messages.filter(m => m.author.id == this.client.user.id)).first(); 151 | if (!lastMessage) lastMessage = await this.channel.send('Loading...'); 152 | this.message = lastMessage; 153 | } 154 | 155 | let nodes = Cache.get('nodes'); 156 | nodes.map((n, i) => nodes[i]['online'] = (Date.now() - n.lastUpdated) < n.cacheInterval * 2); 157 | 158 | let nodesOnline = nodes.filter(n => n.online).length; 159 | let nodesOffline = nodes.filter(n => !n.online).length; 160 | let nodesList = nodes.map(n => { 161 | 162 | // Node Status 163 | let status = Cache.get('status'); 164 | let lastStatus = status[n.nodeName]; 165 | this.handleStatus(lastStatus, n.online, n); 166 | status[n.nodeName] = n.online; 167 | Cache.set('status', status); 168 | 169 | // Parse 170 | return this.nodeMessage 171 | .replace('{node.name}', n.nodeName) 172 | .replace('{node.memory.used}', `${this.bytesToSize(n.memory.used)}GB`) 173 | .replace('{node.memory.total}', `${this.bytesToSize(n.memory.total)}GB`) 174 | .replace('{node.disk.used}', `${this.bytesToSize(n.disk.used)}GB`) 175 | .replace('{node.disk.total}', `${this.bytesToSize(n.disk.total)}GB`) 176 | .replace('{node.cpu.used}', `${(n.cl).toFixed(2) || 'unknown'}%`) 177 | .replace('{node.cpu.cores}', n.cpu.cores) 178 | .replace('{node.cpu}', `${n.cpu.manufacturer || ''} ${n.cpu.brand || ''}`) 179 | .replace('{node.os}', n.os.platform || 'unknown') 180 | .replace('{node.status}', n.online ? this.online : this.offline); 181 | }).join('\n'); 182 | 183 | this.nodes = nodes; 184 | let nodesTotal = nodes.length; 185 | 186 | let totalMemory = this.bytesToSize(nodes.reduce((acc, node) => acc + node.memory.total, 0)); 187 | let totalDisk = this.bytesToSize(nodes.reduce((acc, node) => acc + node.disk.total, 0)); 188 | let totalCores = nodes.reduce((acc, node) => acc + node.cpu.cores, 0); 189 | let usedMemory = this.bytesToSize(nodes.reduce((acc, node) => acc + node.memory.used, 0)); 190 | let usedDisk = this.bytesToSize(nodes.reduce((acc, node) => acc + node.disk.used, 0)); 191 | 192 | let that = this; 193 | function parse(text = '') { 194 | return text 195 | .replace('{nodes.online}', nodesOnline) 196 | .replace('{nodes.offline}', nodesOffline) 197 | .replace('{nodes.list}', nodesList) 198 | .replace('{nodes.total}', nodesTotal) 199 | 200 | .replace('{memory.total}', totalMemory + 'GB') 201 | .replace('{disk.total}', totalDisk + 'GB') 202 | .replace('{cores.total}', totalCores) 203 | 204 | .replace('{memory.used}', usedMemory + 'GB') 205 | .replace('{disk.used}', usedDisk + 'GB') 206 | .replace('{memory.used%}', (usedMemory/totalMemory).toFixed(2)*100 + '%') 207 | .replace('{disk.used%}', (usedDisk/totalDisk).toFixed(2)*100 + '%') 208 | 209 | .replace('{pterodactyl.users}', that.pterodactyl.users) 210 | .replace('{pterodactyl.servers}', that.pterodactyl.servers) 211 | } 212 | 213 | this.editEmbed( 214 | this.message, 215 | parse(this.title).substr(0, 256), 216 | parse(this.description).substr(0, 2048), 217 | [], 218 | parse(this.footerText).substr(0, 2048), 219 | this.color, 220 | this.thumbnail 221 | ) 222 | } 223 | 224 | editEmbed(message, title, description, fields, footer, color, thumbnail) { 225 | return new Promise(async (resolve, reject) => { 226 | message.edit({ 227 | content: `v${this.version}`, 228 | embeds: [{ 229 | title: title, 230 | description: description, 231 | fields: fields, 232 | thumbnail: { url: thumbnail || '' }, 233 | color: color || this.color, 234 | footer: { text: footer || this.footerText, icon_url: this.footerIcon }, 235 | timestamp: new Date() 236 | }] 237 | }).then(message => { 238 | resolve(message); 239 | }).catch(err => { 240 | reject(err); 241 | }); 242 | }); 243 | } 244 | 245 | handleStatus(oldStatus, newStatus, node) { 246 | if (oldStatus != undefined) { 247 | if (newStatus == true && oldStatus == false) { 248 | if (this.discordWebhook != undefined) this.discordWebhook.up(node); 249 | if (this.webhook != undefined) this.webhook.up(node); 250 | if (this.telegram != undefined) this.telegram.up(node); 251 | this.emit('online', node); 252 | } else if (newStatus == false && oldStatus == true) { 253 | if (this.discordWebhook != undefined) this.discordWebhook.down(node); 254 | if (this.webhook != undefined) this.webhook.down(node); 255 | if (this.telegram != undefined) this.telegram.down(node); 256 | this.emit('offline', node); 257 | } 258 | } 259 | } 260 | 261 | bytesToSize(bytes) { 262 | return (bytes/1024/1024/1024).toFixed(2) 263 | } 264 | 265 | log(message) { 266 | console.log(`${chalk.blue('[CONTROLLER]')}${chalk.gray(':')} ${chalk.yellow(message)}`) 267 | } 268 | 269 | elog(message) { 270 | console.log(`${chalk.blue('[CONTROLLER]')}${chalk.gray(':')} ${chalk.red(message)}`); 271 | } 272 | } 273 | 274 | module.exports = Panel; -------------------------------------------------------------------------------- /src/Controller/notifications/discord.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const chalk = require('chalk'); 3 | const DiscordJS = require('discord.js'); 4 | const path = require('path'); 5 | const reqPath = path.join(__dirname, '../../../'); 6 | const { default: i18n } = require('new-i18n'); 7 | const newi18n = new i18n({ folder: path.join(reqPath, '/language'), languages: ['en','de'], fallback: 'en' }) 8 | 9 | class Discord { 10 | constructor(url, language) { 11 | this.url = url 12 | this.language = language 13 | } 14 | 15 | down(node) { 16 | let data = { 17 | embeds: [{ 18 | title: newi18n.translate(this.language, 'notifications.discord.offline.title'), 19 | description: newi18n.translate(this.language, 'notifications.discord.offline.description', {node_nodeName: node.nodeName}), 20 | thumbnail: { url: 'https://discord.com/assets/8becd37ab9d13cdfe37c08c496a9def3.svg' }, 21 | color: DiscordJS.Util.resolveColor('#AA0000'), 22 | timestamp: new Date() 23 | }] 24 | } 25 | this.post(data); 26 | } 27 | 28 | up(node) { 29 | let data = { 30 | embeds: [{ 31 | title: newi18n.translate(this.language, 'notifications.discord.online.title'), 32 | description: newi18n.translate(this.language, 'notifications.discord.online.description', {node_nodeName: node.nodeName}), 33 | thumbnail: { url: 'https://discord.com/assets/212e30e47232be03033a87dc58edaa95.svg' }, 34 | color: DiscordJS.Util.resolveColor('#55FF55'), 35 | timestamp: new Date() 36 | }] 37 | } 38 | this.post(data); 39 | } 40 | 41 | post(content) { 42 | try { 43 | axios.post(this.url, content); 44 | } catch(e) { 45 | this.log('Failed to post to discord webhook'); 46 | } 47 | } 48 | 49 | log(message) { 50 | console.log(`${chalk.blue('[DISCORD-WEBHOOK]')}${chalk.gray(':')} ${chalk.yellow(message)}`) 51 | } 52 | } 53 | 54 | module.exports = Discord; -------------------------------------------------------------------------------- /src/Controller/notifications/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Discord: require('./discord'), 3 | Webhook: require('./webhook'), 4 | Telegram: require('./telegram') 5 | } -------------------------------------------------------------------------------- /src/Controller/notifications/telegram.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const chalk = require('chalk'); 3 | const path = require('path'); 4 | const reqPath = path.join(__dirname, '../../../'); 5 | const { default: i18n } = require('new-i18n'); 6 | const newi18n = new i18n({ folder: path.join(reqPath, '/language'), languages: ['en','de'], fallback: 'en' }) 7 | 8 | class Telegram { 9 | constructor(token, chatid, language) { 10 | this.url = 'https://api.telegram.org/' 11 | this.token = token 12 | this.chatID = chatid 13 | this.language = language 14 | } 15 | 16 | down(node) { 17 | let message = newi18n.translate(this.language, 'notifications.telegram.offline.description', {node_nodeName: node.nodeName}) 18 | this.post(message); 19 | } 20 | 21 | up(node) { 22 | let message = newi18n.translate(this.language, 'notifications.telegram.online.description', {node_nodeName: node.nodeName}) 23 | this.post(message); 24 | } 25 | 26 | post(content) { 27 | try { 28 | axios.get(`${this.url}bot${this.token}/sendMessage?chat_id=${this.chatID}&text=${content}&parse_mode=HTML`); 29 | } catch(e) { 30 | this.log('Failed to post to discord webhook'); 31 | } 32 | } 33 | 34 | log(message) { 35 | console.log(`${chalk.blue('[TELEGRAM-WEBHOOK]')}${chalk.gray(':')} ${chalk.yellow(message)}`) 36 | } 37 | } 38 | 39 | module.exports = Telegram; -------------------------------------------------------------------------------- /src/Controller/notifications/webhook.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const chalk = require('chalk'); 3 | 4 | class Webhook { 5 | constructor(url) { 6 | this.url = url 7 | } 8 | 9 | down(node) { 10 | let data = { 11 | type: 'offline', 12 | node 13 | } 14 | this.post(data); 15 | } 16 | 17 | up(node) { 18 | let data = { 19 | type: 'online', 20 | node 21 | } 22 | this.post(data); 23 | } 24 | 25 | post(content) { 26 | try { 27 | axios.post(this.url, content); 28 | } catch(e) { 29 | this.log('Failed to post to webhook'); 30 | } 31 | } 32 | 33 | log(message) { 34 | console.log(`${chalk.blue('[WEBHOOK]')}${chalk.gray(':')} ${chalk.yellow(message)}`) 35 | } 36 | } 37 | 38 | module.exports = Webhook; -------------------------------------------------------------------------------- /src/Controller/pterodactyl.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const chalk = require('chalk'); 3 | const { options } = require('./routes'); 4 | 5 | class Pterodactyl { 6 | constructor(panel, key, interval) { 7 | this.panel = panel; 8 | this.key = key; 9 | this.interval = interval; 10 | this.headers = { 'authorization': 'Bearer ' + this.key }; 11 | 12 | this.stats = { 13 | users: 0, 14 | servers: 0 15 | } 16 | } 17 | 18 | init(interval = this.interval) { 19 | let that = this; 20 | setInterval(async () => { 21 | that.fetch('users'); 22 | that.fetch('servers'); 23 | }, interval); 24 | } 25 | 26 | get servers() { 27 | return this.stats.servers || 0; 28 | } 29 | 30 | get users() { 31 | return this.stats.users || 0; 32 | } 33 | 34 | async fetch(type) { 35 | try { 36 | let res = await axios.get(this.panel + '/api/application/' + type, { headers: this.headers }); 37 | let total = res['data']['meta']['pagination']['total']; 38 | this.stats[type] = total; 39 | this.log('Fetched pterodactyl ' + type + ' count'); 40 | return total; 41 | } catch(e) { 42 | this.log('Could not fetch pterodactyl ' + type + ' count'); 43 | return; 44 | } 45 | } 46 | 47 | log(message) { 48 | console.log(`${chalk.blue('[CONTROLLER]')}${chalk.gray(':')} ${chalk.yellow(message)}`); 49 | } 50 | 51 | } 52 | 53 | module.exports = Pterodactyl; -------------------------------------------------------------------------------- /src/Controller/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const rateLimit = require('express-rate-limit'); 4 | 5 | const apiLimiter = rateLimit({ 6 | windowMs: 1 * 60 * 1000, // 1 minute 7 | max: 100 // Amount of requests 8 | }); 9 | 10 | router.use('/stats', apiLimiter, require('./stats')); 11 | router.use('/status', apiLimiter, require('./status')); 12 | 13 | module.exports = router; -------------------------------------------------------------------------------- /src/Controller/routes/stats.js: -------------------------------------------------------------------------------- 1 | const router = require('express').Router(); 2 | const Cache = require('liquidcache'); 3 | 4 | router.post('/:node', function(req, res, next) { 5 | 6 | let nodeName = req.params.node; 7 | if (!nodeName) return res.status(404).json({ error: 'missing node name' }); 8 | 9 | let nodeData = req.body; 10 | if (!nodeData) return res.status(404).json({ error: 'missing body' }); 11 | 12 | let nodes = Cache.get('nodes'); 13 | 14 | let existsIndex = nodes.map(n => n.nodeName).indexOf(nodeData.nodeName); 15 | if (existsIndex == -1) { 16 | nodes.push(nodeData); 17 | } else { 18 | nodes[existsIndex] = nodeData; 19 | } 20 | 21 | // Update nodes in cache 22 | Cache.set('nodes', nodes.sort(function(a, b) { 23 | return a.nodeName.localeCompare(b.nodeName); 24 | })); 25 | 26 | return res.status(200); 27 | 28 | }); 29 | 30 | router.get('/', function(req, res, next) { 31 | 32 | let nodes = Cache.get('nodes'); 33 | if (!nodes) return res.status(404).json({ error: 'no nodes were found' }); 34 | 35 | nodes.forEach((n, i) => { 36 | let difference = Date.now() - n.lastUpdated; 37 | console.log(difference) 38 | nodes[i]['online'] = difference < (n.cacheInterval * 2); 39 | }); 40 | 41 | return res.status(200).json(nodes); 42 | 43 | }); 44 | 45 | module.exports = router; 46 | -------------------------------------------------------------------------------- /src/Controller/routes/status.js: -------------------------------------------------------------------------------- 1 | const router = require('express').Router(); 2 | const Cache = require('liquidcache'); 3 | 4 | router.get('/', function(req, res, next) { 5 | 6 | let status = Cache.get('status'); 7 | return res.status(200).json(status); 8 | 9 | }); 10 | 11 | module.exports = router; 12 | -------------------------------------------------------------------------------- /src/Node/index.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | const si = require('systeminformation'); 3 | const Cache = require('liquidcache'); 4 | const { default: axios } = require('axios'); 5 | const { response } = require('express'); 6 | 7 | class Node { 8 | constructor(options = {}) { 9 | 10 | if (!options['name']) return new Error('Missing node name'); 11 | this.name = options['name']; 12 | 13 | if (!options['interval']) return new Error('Missing node update interval'); 14 | this.interval = options['interval']; 15 | 16 | if (!options['controller']) return new Error('Missing controller address'); 17 | this.controller = options['controller']; 18 | 19 | if (options['bearer_token']) { 20 | this.config = { 21 | headers: { Authorization: `Bearer ${options['bearer_token']}` } 22 | }; 23 | } 24 | 25 | // Toggle running 26 | this.running = true; 27 | 28 | this.log(`Started! Posting to: ${this.controller}`); 29 | this.autoPost(); 30 | } 31 | 32 | start() { 33 | if (this.running) return this.log('Tried to start but already started'); 34 | this.running = true; 35 | this.log('Starting!'); 36 | } 37 | 38 | stop() { 39 | if (!this.running) return this.log('Tried to stop but already stopped'); 40 | this.running = false; 41 | this.log('Stopping!'); 42 | } 43 | 44 | async autoPost() { 45 | let that = this; 46 | setInterval(async function() { 47 | await that.post(await that.stats()); 48 | }, this.interval); 49 | } 50 | 51 | async post(stats) { 52 | if (!this.running) return; 53 | let scheme = this.controller.secure ? 'https://' : 'http://'; 54 | try { 55 | if(this.config){ 56 | await axios.post(`${this.controller}/stats/${this.name}`, stats, this.config); 57 | }else{ 58 | await axios.post(`${this.controller}/stats/${this.name}`, stats); 59 | } 60 | Cache.set('stats', stats); 61 | } catch(e) { 62 | if (e.response.status === 403) { 63 | return this.elog(e.response.data.error); 64 | } 65 | return this.elog('Failed to post stats to controller'); 66 | } 67 | return this.log('Posted stats to controller!') 68 | 69 | } 70 | 71 | async stats() { 72 | if (!this.running) return; 73 | let memory = await si.mem(); 74 | let disk = await si.fsSize(); 75 | let cpu = Cache.get('cpu') || await si.cpu(); 76 | Cache.set('cpu', cpu); 77 | let os = Cache.get('os') || await si.osInfo(); 78 | Cache.set('os', os); 79 | let cl = await si.currentLoad(); 80 | return { 81 | nodeName: this.name, 82 | lastUpdated: Date.now(), 83 | cacheInterval: this.interval, 84 | memory: { 85 | total: memory.total, 86 | used: (memory.total-memory.available), 87 | free: (memory.free+memory.available), 88 | }, 89 | disk: { 90 | total: disk.reduce((last, current) => last.size + current.size, 0) || disk[0].size, 91 | used: disk.reduce((last, current) => last.used + current.used, 0) || disk[0].used, 92 | free: disk.reduce((last, current) => last.available + current.available, 0) || disk[0].available 93 | }, 94 | cpu, 95 | os, 96 | cl: cl['currentLoad'], 97 | } 98 | } 99 | 100 | log(message) { 101 | console.log(`${chalk.blue('[DAEMON]')}${chalk.gray(':')} ${chalk.yellow(message)}`); 102 | } 103 | 104 | elog(message) { 105 | console.log(`${chalk.blue('[DAEMON]')}${chalk.gray(':')} ${chalk.red(message)}`); 106 | } 107 | } 108 | 109 | module.exports = Node; 110 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Node: require('./Node'), 3 | Controller: require('./Controller') 4 | } -------------------------------------------------------------------------------- /tests/index.js: -------------------------------------------------------------------------------- 1 | const Status = require('../index'); 2 | const express = require('express'); 3 | require('dotenv').config(); 4 | 5 | const Controller = new Status.Controller(4000, 'de', { 6 | discord: { 7 | token: process.env.TOKEN, 8 | channel: process.env.CHANNEL, 9 | }, 10 | pterodactyl: { 11 | panel: process.env.PANEL_URL, 12 | apiKey: process.env.PANEL_API_KEY 13 | }, 14 | telegram: { 15 | tgtoken: process.env.TGTOKEN, 16 | tgchatID: process.env.TGCHATID 17 | }, 18 | notifications: { 19 | discord: process.env.DISCORD_WEBHOOK, 20 | webhook: 'http://0.0.0.0:5000/webhook' 21 | }, 22 | node: { 23 | message: '**{node.name}**: {node.status} -> [Memory: {node.memory.used}/{node.memory.total}] [Disk: {node.disk.used}/{node.disk.total}]', 24 | online: '🟢 **ONLINE**', 25 | offline: '🔴 **OFFLINE**' 26 | }, 27 | embed: { 28 | color: '#06cce2', 29 | title: 'Status', 30 | description: '**Nodes**:\n{nodes.list}\n\n**Total**:\nMemory: {memory.used}/{memory.total}\nDisk: {disk.used}/{disk.total}\n\n**Pterodactyl:**\nUsers: {pterodactyl.users}\nServers: {pterodactyl.servers}', 31 | thumbnail: 'https://i.imgur.com/9b1qwml.jpg', 32 | footer: { 33 | text: 'BlueFoxHost', 34 | icon: 'https://i.imgur.com/9b1qwml.jpg' 35 | } 36 | }, 37 | interval: 15000, 38 | bearer_token: 'Test123' 39 | 40 | }); 41 | 42 | Controller.on('online', (node) => { 43 | console.log(`Node: "${node.nodeName}" has come back online!`); 44 | }); 45 | 46 | Controller.on('offline', (node) => { 47 | console.log(`Node: "${node.nodeName}" has gone offline!`); 48 | }); 49 | 50 | const Node1 = new Status.Node({ 51 | name: 'Node1', 52 | interval: 5000, 53 | controller: 'http://0.0.0.0:4000', 54 | bearer_token: 'Test123' 55 | }); 56 | 57 | // Test the node stopping 58 | setTimeout(function() { 59 | Node1.stop(); 60 | 61 | // Test a new node 62 | const Node2 = new Status.Node({ 63 | name: 'Node2', 64 | interval: 5000, 65 | controller: 'http://0.0.0.0:4000', 66 | bearer_token: 'Test12' 67 | }); 68 | 69 | }, 20000); 70 | 71 | // Webhook server 72 | const app = express(); 73 | app.use(express.json()); 74 | app.use(express.urlencoded({ extended: false })); 75 | 76 | app.post('/webhook', (req, res) => { 77 | console.log('Webhook recieved!') 78 | }); 79 | 80 | app.listen(5000); --------------------------------------------------------------------------------