├── .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 |     
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 | 
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 | 
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);
--------------------------------------------------------------------------------