mirror of
https://github.com/HirziDevs/PteroStats
synced 2026-07-30 03:52:54 +00:00
@@ -0,0 +1,129 @@
|
||||
<div align="center">
|
||||
|
||||
<img alt="PteroStats Banner" src="https://cdn.discordapp.com/attachments/626755594526916629/978478722489393153/20220524_090325.png" width="400"/>
|
||||
|
||||
## Bahasa / Language
|
||||
[[Indonesia]](https://github.com/HirziDevs/PteroStats/blob/dev/Indo.md) | [[Inggris]](https://github.com/HirziDevs/PteroStats/blob/dev/README.md)
|
||||
|
||||
</div>
|
||||
|
||||
## Pengenalan
|
||||
PteroStats adalah bot yang dirancang untuk memeriksa status panel pterodactyl dan dikirim ke server discord
|
||||
|
||||
## Contoh
|
||||
- Test Panel
|
||||
|
||||
<img alt="Example" src="https://cdn.discordapp.com/attachments/988796533430448148/991520721467613224/example.gif" width="200"/>
|
||||
|
||||
- [Calvs Cloud](https://discord.gg/ssCQjhrBJN)
|
||||
|
||||
<img alt="Calvs Cloud" src="https://media.discordapp.net/attachments/819757140155564062/1037353043487887410/unknown.png" width="200">
|
||||
|
||||
## Instalasi
|
||||
1. [Mendapatkan apikey dari pterodactyl](#mendapatkan-apikey-dari-pterodactyl)
|
||||
2. [Membuat Discord Bot](#membuat-discord-bot)
|
||||
3. [Menginvite Discord Bot](#menginvite-discord-bot)
|
||||
4. [Mendapatkan Channel ID](#mendapatkan-channel-id)
|
||||
5. [Memulai Bot](#memulai-bot)
|
||||
|
||||
- [Mengunakan custom emoji](#mengunakan-custom-emoji)
|
||||
- [Blacklist Nodes](#blacklist-nodes)
|
||||
|
||||
### Mendapatkan apikey dari pterodactyl
|
||||
1. Pergi ke `panel admin pterodactyl` dan pergi ke `Application API`
|
||||
|
||||
<img alt="Admin Panel" src="https://usercontent.catto.pictures/hirzi/aabafe57-cbfe-4d7f-9d6d-4a63a7f23d4c.png" width="400"/>
|
||||
|
||||
2. Klik tombol `Create New`
|
||||
|
||||
<img alt="Application API Page" src="https://usercontent.catto.pictures/hirzi/f916f0c6-0968-4125-8226-ba4daa1de902.png" width="400"/>
|
||||
|
||||
3. Set semua permission ke `read` dan untuk description kamu bisa mengisi apa saja
|
||||
|
||||
<img alt="Create Application API" src="https://usercontent.catto.pictures/hirzi/3e4575cb-4f52-4bd9-9091-36fda20bedad.png" width="400"/>
|
||||
|
||||
4. Copy apikey-nya.
|
||||
|
||||
<img alt="Application API List" src="https://usercontent.catto.pictures/hirzi/9142b0b3-0556-4741-840c-6976c3fe3ad4.png" width="400"/>
|
||||
|
||||
5. Paste panel apikeynya dan panel urlnya di config
|
||||
|
||||
<img alt="Panel Config" src="https://usercontent.catto.pictures/hirzi/2b9365b8-69d2-4fa0-8eac-3efc8591b765.png" width="400"/>
|
||||
|
||||
### Membuat Discord Bot
|
||||
Kalian bisa cek [website ini](https://discordjs.guide/preparations/setting-up-a-bot-application.html)
|
||||
|
||||
Paste bot tokennya di config
|
||||
|
||||
<img alt="Bot Config" src="https://usercontent.catto.pictures/hirzi/4eb4d5ff-6969-4461-b01d-c45888cfc994.png" width="400"/>
|
||||
|
||||
### Menginvite Discord Bot
|
||||
Kalian bisa cek [website ini](https://discordjs.guide/preparations/adding-your-bot-to-servers.html)
|
||||
|
||||
### Mendapatkan Channel ID
|
||||
1. Aktifkan `Developer Mode` di settings discord kamu
|
||||
|
||||
<img alt="Discord User Settings" src="https://usercontent.catto.pictures/hirzi/36894499-b141-488f-98ed-40245c8f6862.png" width="400"/>
|
||||
|
||||
2. Klik kanan teks channel dan pilih `Copy ID`
|
||||
|
||||
<img alt="Right Click Channel" src="https://usercontent.catto.pictures/hirzi/9f8352da-df5b-4587-9594-ced9b11a5507.png" width="250"/>
|
||||
|
||||
3. Paste id channelnya di config
|
||||
|
||||
<img alt="Channel Config" src="https://usercontent.catto.pictures/hirzi/b34cdbee-1e24-49f2-8219-efe0344a24f9.png" width="400"/>
|
||||
|
||||
### Memulai Bot
|
||||
1. Pastikan kamu telah melakukan semua yang ada diatas
|
||||
2. Jalankan command `npm install` di folder yang berisi file bot
|
||||
3. Jalankan command `node index` dan kamu selesai!
|
||||
|
||||
Jika kamu mendapat masalah bisa dm `Hirzi#8701` didiscord atau join [server support kami](https://discord.gg/zv6maQRah3)
|
||||
|
||||
### Mengunakan custom emoji
|
||||
1. ketik `\` di server yang ada custom emojinya
|
||||
|
||||
<img alt="Type \ on the chat" src="https://usercontent.catto.pictures/hirzi/2e3c821f-92f9-4b5c-863a-e020b2fbc426.png" width="350"/>
|
||||
|
||||
2. Pilih custom emoji yang kamu mau
|
||||
|
||||
<img alt="Select Custom Emoji" src="https://usercontent.catto.pictures/hirzi/7c071727-2adb-4c8c-91d3-21664948a334.png" width="300"/>
|
||||
|
||||
3. Copy textnya!
|
||||
|
||||
<img alt="Copy Emoji ID" src="https://usercontent.catto.pictures/hirzi/bd0084ac-f11b-413d-8b66-580efc011908.png" width="400"/>
|
||||
|
||||
4. Paste id emojinya di config
|
||||
|
||||
<img alt="Status Config" src="https://usercontent.catto.pictures/hirzi/458ad1d6-019b-4b27-be60-3cbabfa07c06.png" width="400"/>
|
||||
|
||||
### Blacklist Nodes
|
||||
1. Pilih node yang ada di node list admin page
|
||||
|
||||
<img alt="Nodes List" src="https://usercontent.catto.pictures/hirzi/5699fdbd-7c3c-4fa5-ae2c-d0ccb39cb69e.png" width="400"/>
|
||||
|
||||
2. Cek urlnya dan copy id nodenya
|
||||
|
||||
<img alt="Node Id" src="https://usercontent.catto.pictures/hirzi/45f855fc-6d96-4b23-a96e-892071189d01.png" width="400"/>
|
||||
|
||||
3. Masukan ke blacklist di config
|
||||
|
||||
<img alt="Blacklist Config" src="https://usercontent.catto.pictures/hirzi/cfb479bf-64da-43e5-b0d1-f7c0c78bf068.png" width="400"/>
|
||||
|
||||
Kamu bisa memasukan lebih dari 1 node untuk di blacklist
|
||||
|
||||
<img alt="Blacklist Config" src="https://usercontent.catto.pictures/hirzi/85b6a9b1-8ec9-4395-b5b1-6f85d3f52162.png" width="400"/>
|
||||
|
||||
## Permission apikey
|
||||
|
||||
Jika kamu mengalami error 403 coba aktifkan `read & write` di semua opsi permission
|
||||
|
||||
<img alt="Application API Permission" src="https://usercontent.catto.pictures/hirzi/273d5b86-5249-42d0-bfc6-1dcfcae4efe7.png" width="400"/>
|
||||
|
||||
## Links
|
||||
|
||||
- [Pterodactyl Panel](https://pterodactyl.io)
|
||||
- [Pterodactyl Api Documentation](https://dashflo/docs/api/pterodactyl/v1)
|
||||
- [Pterodactyl Discord Server](https://discord.gg/pterodactyl)
|
||||
- [PteroBot Support Server](https://discord.gg/zv6maQRah3)
|
||||
- [PteroBot Support Server (Indonesia)](https://discord.gg/EYaFB7WSg6)
|
||||
@@ -1,201 +1,21 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
MIT License
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
Copyright (c) 2022 HirziDevs
|
||||
|
||||
1. Definitions.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@@ -1,124 +1,129 @@
|
||||
# PteroStats
|
||||
<div align="center">
|
||||
|
||||

|
||||

|
||||
<img alt="PteroStats Banner" src="https://cdn.discordapp.com/attachments/626755594526916629/978478722489393153/20220524_090325.png" width="400"/>
|
||||
|
||||

|
||||
## Language / Bahasa
|
||||
[[English]](https://github.com/HirziDevs/PteroStats/blob/dev/README.md) | [[Indonesia]](https://github.com/HirziDevs/PteroStats/blob/dev/Indo.md)
|
||||
|
||||
</div>
|
||||
|
||||
## Introduction
|
||||
|
||||
PteroStats is a bot designed to check Pterodactyl Panel and Nodes status and post it to your discord server
|
||||
|
||||
- Written in Javascript, CloudServer is faster and more stable.
|
||||
- PteroControl can be used with any server on Pterodactyl, irregardless of whether it's on shared hosting or your own hosted panel
|
||||
## Example
|
||||
- Test Panel
|
||||
|
||||
PteroStats is still **under development** and we welcome contributions.
|
||||
<img alt="Example" src="https://cdn.discordapp.com/attachments/988796533430448148/991520721467613224/example.gif" width="200"/>
|
||||
|
||||
### How it works?
|
||||
- [Calvs Cloud](https://discord.gg/ssCQjhrBJN)
|
||||
|
||||
PteroStats checks [pterodactyl](https://pterodactyl.io) nodes wings with [axios](https://www.npmjs.com/package/axios) to get nodes wings status, if the api didn't reply that mean the node is having [wings/daemon](https://pterodactyl.io/wings/1.0/installing.html) down and mark the node as offline
|
||||
|
||||
### Screenshot
|
||||
|
||||
- [**TreeCloud**](https://discord.gg/TCBhPan6SY)
|
||||

|
||||
- [**ItzyStore**](https://discord.gg/PS4Mf6DBzt)
|
||||

|
||||
- [**SpaceCloud**](https://discord.gg/28z8CYmPEY)
|
||||

|
||||
<img alt="Calvs Cloud" src="https://media.discordapp.net/attachments/819757140155564062/1037353043487887410/unknown.png" width="200">
|
||||
|
||||
## Installation
|
||||
1. [Getting apikey from pterodactyl](#getting-apikey-from-pterodactyl)
|
||||
2. [Creating Discord Bot](#creating-discord-bot)
|
||||
3. [Inviting Discord Bot](#inviting-discord-bot)
|
||||
4. [Getting Channel ID](#getting-channel-id)
|
||||
5. [Starting bot](#starting-bot)
|
||||
|
||||
- `fill in the required informations in the config.yml file`
|
||||
- `Run npm install in the root directory of the bot files`
|
||||
- `Run node index.js and you are done`
|
||||
- [Using Custom Emoji](#using-custom-emoji)
|
||||
- [Blacklist Nodes](#blacklist-nodes)
|
||||
|
||||
if you need help contact me on discord `Hirzi#8701` or join [our discord server here](https://discord.gg/zv6maQRah3)
|
||||
### Getting apikey from pterodactyl
|
||||
1. Go to your `pterodactyl admin page` and go to `Application API`.
|
||||
|
||||
## Admin Apikey Permission
|
||||
<img alt="Admin Panel" src="https://usercontent.catto.pictures/hirzi/aabafe57-cbfe-4d7f-9d6d-4a63a7f23d4c.png" width="400"/>
|
||||
|
||||
enable `read` on all options, if still didn't work enable `read & write` on all options
|
||||

|
||||
2. Click on the `Create New` button
|
||||
|
||||
### Setuping Config
|
||||
<img alt="Application API Page" src="https://usercontent.catto.pictures/hirzi/f916f0c6-0968-4125-8226-ba4daa1de902.png" width="400"/>
|
||||
|
||||
You need to put right config to make the bot work at [config.yml](https://github.com/HirziDevs/PteroStats/blob/main/config.yml) file
|
||||
```
|
||||
# PteroStats config
|
||||
# If you need help, join our discord server: https://discord.gg/zv6maQRah3
|
||||
3. Set all options permission to `read` and for description you can put whatever you want
|
||||
|
||||
# Bot Info's
|
||||
token: 'BOT TOKEN' # Put bot token here, check https://discord.dev to create and get bot token
|
||||
botstatus:
|
||||
enable: false # Enable Custom Status (MUST BE "true" OR "false")
|
||||
text: 'Hosting Panel' # Bot Status Message
|
||||
type: 'WATCHING' # Bot Status Type. Ex: PLAYING, WATCHING, LISTENING, STREAMING
|
||||
<img alt="Create Application API" src="https://usercontent.catto.pictures/hirzi/3e4575cb-4f52-4bd9-9091-36fda20bedad.png" width="400"/>
|
||||
|
||||
# Channel and RefreshTime Configuration
|
||||
channel: 'CHANNEL ID' # Put channel id here where the embed will be sended
|
||||
refreshtime: 60 # Time when the embed edited/refreshed (MUST BE A SECONDS) (RECOMMENDED MORE THAN 20 SECONDS)
|
||||
4. Copy the apikey.
|
||||
|
||||
# Panel Info's
|
||||
panel:
|
||||
url: 'HOST PANEL LINK' # Put panel url here. Example: https://panel.purenodes.net
|
||||
adminkey: 'ADMIN APIKEY' # Put Admin Apikey here. check https://your.host.url/admin/api (your.host.url is an example link) to get the Admin ApiKey
|
||||
<img alt="Application API List" src="https://usercontent.catto.pictures/hirzi/9142b0b3-0556-4741-840c-6976c3fe3ad4.png" width="400"/>
|
||||
|
||||
# Embed Configuration
|
||||
embed:
|
||||
title: 'EMBED TITLE' # Embed Title here. Ex: PureNodes Stats
|
||||
color: 'E5BE11' # Embed Hex color here.
|
||||
description:
|
||||
enable: false # Enable Embed Description (MUST BE "true" OR "false")
|
||||
text: 'EMBED DESCRIPTION' # Embed Description
|
||||
footer:
|
||||
enable: true # Enable Embed Footer (MUST BE "true" OR "false")
|
||||
text: 'By Hirzi#8701' # Embed Footer
|
||||
timestamp: true # Enable Embed TimeStamp (MUST BE "true" OR "false")
|
||||
5. Paste the panel apikey and panel url at the config
|
||||
|
||||
# Status Message Configuration
|
||||
status:
|
||||
online: ':green_circle: Online' # Message if the status is Online
|
||||
offline: ':red_circle: Offline' # Message if the status is Offline
|
||||
check: ':orange_circle: Checking' # Message if the status is Checking
|
||||
<img alt="Panel Config" src="https://usercontent.catto.pictures/hirzi/2b9365b8-69d2-4fa0-8eac-3efc8591b765.png" width="400"/>
|
||||
|
||||
# Node Resource
|
||||
resource:
|
||||
enable: false # Enable resource option ex [Ram: 2gb/5gb] bellow node name (MUST BE "true" OR "false")
|
||||
servers: true # Enable Total server on the node to resource text (MUST BE "true" OR "false")
|
||||
allocations: true # Enable Total Allocation on the node to resource text (MUST BE "true" OR "false")
|
||||
location: true # Enable location short name on the node to resource text (MUST BE "true" OR "false")
|
||||
unit: 'gb' # Must be 'mb', 'gb', or 'percent'
|
||||
### Creating Discord Bot
|
||||
Please refer to [this website](https://discordjs.guide/preparations/setting-up-a-bot-application.html)
|
||||
|
||||
# Developers feature
|
||||
debug: false # Enable and Disable debug log to console
|
||||
debugaxios: false #Enable and Disable axios error logs
|
||||
```
|
||||
Paste the bot token at the config
|
||||
|
||||
## Other
|
||||
### FAQ
|
||||
<img alt="Bot Config" src="https://usercontent.catto.pictures/hirzi/4eb4d5ff-6969-4461-b01d-c45888cfc994.png" width="400"/>
|
||||
|
||||
Q: Can i use pterodactyl v0.7?
|
||||
### Inviting Discord Bot
|
||||
Please refer to [this website](https://discordjs.guide/preparations/adding-your-bot-to-servers.html)
|
||||
|
||||
A: No, the pterodactyl v0.7 is not supported
|
||||
### Getting Channel ID
|
||||
1. Enable Developer Feature at your discord settings
|
||||
|
||||
-
|
||||
<img alt="Discord User Settings" src="https://usercontent.catto.pictures/hirzi/36894499-b141-488f-98ed-40245c8f6862.png" width="400"/>
|
||||
|
||||
Q: How much nodes can i add?
|
||||
2. Right Click text channel and select `Copy ID`
|
||||
|
||||
A: The bot will automatically add nodes from your panel
|
||||
<img alt="Right Click Channel" src="https://usercontent.catto.pictures/hirzi/9f8352da-df5b-4587-9594-ced9b11a5507.png" width="250"/>
|
||||
|
||||
-
|
||||
3. Paste the channel id at the config
|
||||
|
||||
Q: How i can get support?
|
||||
<img alt="Channel Config" src="https://usercontent.catto.pictures/hirzi/b34cdbee-1e24-49f2-8219-efe0344a24f9.png" width="400"/>
|
||||
|
||||
A: You can join our [discord server](https://discord.gg/zv6maQRah3)
|
||||
### Starting bot
|
||||
1. Make sure you have done the things above
|
||||
2. Run `npm install` in the root directory of the bot files.
|
||||
3. Run `node index` and you are done.
|
||||
|
||||
### Links
|
||||
if you need help contact me on discord `Hirzi#8701` or join [our discord support server](https://discord.gg/zv6maQRah3)
|
||||
|
||||
* __[PteroBot Discord](https://discord.gg/zv6maQRah3)__
|
||||
* __[Pterodactyl Panel](https://pterodactyl.io)__
|
||||
* __[Pterodactyl API](https://dashflo.net/docs/api/pterodactyl/v1)__
|
||||
### Using Custom Emoji
|
||||
1. type `\` in guild that has custom emoji you want
|
||||
|
||||
### Special Thanks to
|
||||
<img alt="Type \ on the chat" src="https://usercontent.catto.pictures/hirzi/2e3c821f-92f9-4b5c-863a-e020b2fbc426.png" width="350"/>
|
||||
|
||||
- ItsJustNickDev(from Discord)
|
||||
2. Select custom emoji you want
|
||||
|
||||
<img alt="Select Custom Emoji" src="https://usercontent.catto.pictures/hirzi/7c071727-2adb-4c8c-91d3-21664948a334.png" width="300"/>
|
||||
|
||||
3. Copy the text!
|
||||
|
||||
<img alt="Copy Emoji ID" src="https://usercontent.catto.pictures/hirzi/bd0084ac-f11b-413d-8b66-580efc011908.png" width="400"/>
|
||||
|
||||
4. Paste the emoji id at the config
|
||||
|
||||
<img alt="Status Config" src="https://usercontent.catto.pictures/hirzi/458ad1d6-019b-4b27-be60-3cbabfa07c06.png" width="400"/>
|
||||
|
||||
### Blacklist Nodes
|
||||
1. Select node from node list on admin page
|
||||
|
||||
<img alt="Nodes List" src="https://usercontent.catto.pictures/hirzi/5699fdbd-7c3c-4fa5-ae2c-d0ccb39cb69e.png" width="400"/>
|
||||
|
||||
2. Check the url and copy the node id
|
||||
|
||||
<img alt="Node Id" src="https://usercontent.catto.pictures/hirzi/45f855fc-6d96-4b23-a96e-892071189d01.png" width="400"/>
|
||||
|
||||
3. Paste the id to the blacklist on config
|
||||
|
||||
<img alt="Blacklist Config" src="https://usercontent.catto.pictures/hirzi/cfb479bf-64da-43e5-b0d1-f7c0c78bf068.png" width="400"/>
|
||||
|
||||
You can add more than one node in the blacklist
|
||||
|
||||
<img alt="Blacklist Config" src="https://usercontent.catto.pictures/hirzi/85b6a9b1-8ec9-4395-b5b1-6f85d3f52162.png" width="400"/>
|
||||
|
||||
## Apikey permission
|
||||
|
||||
If you having issue with 403 error try to enable `read & write` on all options
|
||||
|
||||
<img alt="Application API Permission" src="https://usercontent.catto.pictures/hirzi/273d5b86-5249-42d0-bfc6-1dcfcae4efe7.png" width="400"/>
|
||||
|
||||
## Links
|
||||
|
||||
- [Pterodactyl Panel](https://pterodactyl.io)
|
||||
- [Pterodactyl Api Documentation](https://dashflo/docs/api/pterodactyl/v1)
|
||||
- [Pterodactyl Discord Server](https://discord.gg/pterodactyl)
|
||||
- [PteroBot Support Server](https://discord.gg/zv6maQRah3)
|
||||
- [PteroBot Support Server (Indonesia)](https://discord.gg/EYaFB7WSg6)
|
||||
+64
-36
@@ -1,48 +1,76 @@
|
||||
# PteroStats config
|
||||
# If you need help, join our discord server here: https://discord.gg/zv6maQRah3
|
||||
|
||||
# Bot Info's
|
||||
token: 'BOT TOKEN' # Put bot token here, check https://discord.dev to create and get bot token
|
||||
botstatus:
|
||||
enable: false # Enable Custom Status (MUST BE "true" OR "false")
|
||||
text: 'Hosting Panel' # Bot Status Message
|
||||
type: 'WATCHING' # Bot Status Type. Ex: PLAYING, WATCHING, LISTENING, STREAMING
|
||||
# Bot Configuration
|
||||
token: 'Put bot token here'
|
||||
bot_status:
|
||||
enable: false
|
||||
text: 'Hosting Panel'
|
||||
type: 'WATCHING' # can be 'WATCHING', 'PLAYING', 'LISTENING', or 'COMPETING'. for 'STREAMING' is not working for now
|
||||
|
||||
# Channel and RefreshTime Configuration
|
||||
channel: 'CHANNEL ID' # Put channel id here where the embed will be sended
|
||||
refreshtime: 60 # Time when the embed edited/refreshed (MUST BE A SECONDS) (RECOMMENDED MORE THAN 20 SECONDS)
|
||||
# Discord Channel and Refresh Time Configuration
|
||||
channel: 'Put channel id here'
|
||||
refresh: 60
|
||||
|
||||
# Panel Info's
|
||||
# Panel Configuration
|
||||
panel:
|
||||
url: 'HOST PANEL LINK' # Put panel url here. Example: https://panel.purenodes.net
|
||||
adminkey: 'ADMIN APIKEY' # Put Admin Apikey here. check https://your.host.url/admin/api (your.host.url is an example link) to get the Admin ApiKey
|
||||
url: 'Put panel url here'
|
||||
key: 'Put panel apikey here'
|
||||
|
||||
# Embed Configuration
|
||||
embed:
|
||||
title: 'EMBED TITLE' # Embed Title here. Ex: PureNodes Stats
|
||||
color: 'E5BE11' # Embed Hex color here.
|
||||
description:
|
||||
enable: false # Enable Embed Description (MUST BE "true" OR "false")
|
||||
text: 'EMBED DESCRIPTION' # Embed Description
|
||||
footer:
|
||||
enable: true # Enable Embed Footer (MUST BE "true" OR "false")
|
||||
text: 'By Hirzi#8701' # Embed Footer
|
||||
timestamp: true # Enable Embed TimeStamp (MUST BE "true" OR "false")
|
||||
# Message Configuration
|
||||
# set to false if you want to disable option
|
||||
message:
|
||||
content: false
|
||||
attachment: false # If you enable attachment on message it upload the attachment first before sending or editing message and it will delay the stats
|
||||
|
||||
embed:
|
||||
title: 'PteroStats'
|
||||
color: '5865F2'
|
||||
description: 'Next update {{time}}' # You can use {{time}} to make "in X seconds" time format
|
||||
footer: 'By Hirzi#8701'
|
||||
timestamp: true
|
||||
thumbnail: false
|
||||
image: false
|
||||
field:
|
||||
enable: false
|
||||
title: 'Custom Field'
|
||||
description: 'Custom Field' # You can use {{time}} to make "in X seconds" time format
|
||||
|
||||
# Message Button Configuration
|
||||
button:
|
||||
enable: true
|
||||
btn1:
|
||||
label: 'PteroStats'
|
||||
url: 'https://github.com/HirziDevs/PteroStats'
|
||||
btn2:
|
||||
label: ''
|
||||
url: ''
|
||||
btn3:
|
||||
label: ''
|
||||
url: ''
|
||||
btn4:
|
||||
label: ''
|
||||
url: ''
|
||||
btn5:
|
||||
label: ''
|
||||
url: ''
|
||||
|
||||
# Status Message Configuration
|
||||
status:
|
||||
online: ':green_circle: Online' # Message if the status is Online
|
||||
offline: ':red_circle: Offline' # Message if the status is Offline
|
||||
check: ':orange_circle: Checking' # Message if the status is Checking
|
||||
online: ':green_circle: Online'
|
||||
offline: ':red_circle: Offline'
|
||||
|
||||
# Node Resource
|
||||
resource:
|
||||
enable: true # Enable resource option ex [Ram: 2gb/5gb] bellow node name (MUST BE "true" OR "false")
|
||||
servers: true # Enable Total server on the node to resource text (MUST BE "true" OR "false")
|
||||
allocations: true # Enable Total Allocation on the node to resource text (MUST BE "true" OR "false")
|
||||
location: true # Enable location short name on the node to resource text (MUST BE "true" OR "false")
|
||||
unit: 'gb' # Must be 'mb', 'gb', or 'percent'
|
||||
# Nodes Resource
|
||||
nodes_resource:
|
||||
blacklist: [] # You can add node id to remove the node from status embed (Example: "blacklist: [1]")
|
||||
enable: false
|
||||
servers: true
|
||||
location: true
|
||||
allocations: true
|
||||
unit: 'gb' # You can use "gb", "mb", "tb", or "percent"
|
||||
|
||||
# Developers feature
|
||||
debug: false # Enable and Disable debug log to console
|
||||
debugaxios: false #Enable and Disable axios error logs
|
||||
# Panel Users and Servers
|
||||
panel_resource:
|
||||
enable: true
|
||||
servers: true
|
||||
users: true
|
||||
+23
-293
@@ -1,299 +1,29 @@
|
||||
module.exports = client => {
|
||||
const chalk = require('chalk')
|
||||
const checkStatus = require('../handlers/checkStatus')
|
||||
|
||||
//Code are very sensitive, please changes things on config.yml instead
|
||||
|
||||
const { MessageEmbed } = require('discord.js')
|
||||
const axios = require('axios')
|
||||
const db = require('quick.db')
|
||||
const nodetable = new db.table('node')
|
||||
const paneltable = new db.table('panel')
|
||||
const chalk = require('chalk')
|
||||
const config = client.config
|
||||
module.exports = {
|
||||
name: 'ready',
|
||||
once: true,
|
||||
execute(client) {
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.green('Bot is up!'))
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.green('If you need support you can join our discord server https://discord.gg/zv6maQRah3'))
|
||||
|
||||
let enablecs = config.botstatus.enable
|
||||
let cs = config.botstatus.text
|
||||
let stype = config.botstatus.type
|
||||
let ch = client.channels.cache.find(cn => cn.id === config.channel)
|
||||
let time = config.refreshtime
|
||||
if (client.guilds.cache.size < 1) return console.log(chalk.cyan('[PteroStats] ') + chalk.red('Err! This bot is not on any discord servers'))
|
||||
|
||||
let hosturl = config.panel.url
|
||||
let adminapikey = config.panel.adminkey
|
||||
if (client.config.bot_status.enable && client.config.bot_status.text.length > 0) {
|
||||
if (!['PLAYING', 'WATCHING', 'LISTENING', 'COMPETING'].includes(client.config.bot_status.type.toUpperCase() || client.config.bot_status.type.length < 1)) {
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Err! Invalid Status Type!, Can be "WATCHING", "PLAYING", "LISTENING", or "COMPETING"'))
|
||||
} else {
|
||||
client.user.setActivity(client.config.bot_status.text, { type: client.config.bot_status.type.toUpperCase() })
|
||||
}
|
||||
}
|
||||
|
||||
let statusonline = config.status.online
|
||||
let statusoffline = config.status.offline
|
||||
let checking = config.status.check
|
||||
let resource = config.resource.enable
|
||||
let serverres = config.resource.servers
|
||||
let serverport = config.resource.allocations
|
||||
let serverloc = config.resource.location
|
||||
let unit = config.resource.unit
|
||||
if (client.config.refresh < 10) console.log('Refresh lower than 10 seconds is not recommended!')
|
||||
|
||||
let title = config.embed.title
|
||||
let color = config.embed.color
|
||||
let desc = config.embed.description.text
|
||||
let footer = config.embed.footer.text
|
||||
let enablets = config.embed.timestamp
|
||||
let enabledesc = config.embed.description.enable
|
||||
let enablef = config.embed.footer.enable
|
||||
checkStatus(client)
|
||||
|
||||
let debug = config.debug
|
||||
let debugerror = config.debugaxios
|
||||
|
||||
if (debug === true) {
|
||||
console.log(chalk.red('=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+='))
|
||||
console.log(chalk.magenta('[PteroStats Debug] ') + chalk.green('Debug Mode: ') + chalk.cyan('true'))
|
||||
console.log(chalk.magenta('[PteroStats Debug] ') + chalk.green('Debug Axios Mode: ') + chalk.cyan(debugerror))
|
||||
console.log(chalk.magenta('[PteroStats Debug] ') + chalk.green('Resource: ') + chalk.cyan(resource))
|
||||
console.log(chalk.magenta('[PteroStats Debug] ') + chalk.green('Custom Status: ') + chalk.cyan(enablecs))
|
||||
console.log(chalk.magenta('[PteroStats Debug] ') + chalk.green('Enable Timestamp: ') + chalk.cyan(enablets))
|
||||
console.log(chalk.magenta('[PteroStats Debug] ') + chalk.green('Enable Description: ') + chalk.cyan(enabledesc))
|
||||
console.log(chalk.magenta('[PteroStats Debug] ') + chalk.green('Enable Footer: ') + chalk.cyan(enablef))
|
||||
}
|
||||
|
||||
if (!hosturl.includes('http')) hosturl = 'http://' + hosturl
|
||||
let unapi = hosturl + '/api'
|
||||
let api = unapi.replace('//api', '/api')
|
||||
|
||||
if (enablecs === true) {
|
||||
client.user.setActivity(cs, { type: stype })
|
||||
} else {
|
||||
client.user.setActivity(title + ' Panel Stats', { type: 'WATCHING' })
|
||||
}
|
||||
|
||||
console.log(chalk.red('=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+='))
|
||||
console.log(chalk.green('Name: ') + chalk.cyan('PteroStats'))
|
||||
console.log(chalk.green('Version: ') + chalk.cyan('Stable v1.5.0'))
|
||||
console.log(chalk.green('Refresh Time: ') + chalk.cyan(time + ' Seconds'))
|
||||
console.log(chalk.green('Bot Status: ') + chalk.cyan('Online'))
|
||||
console.log(chalk.green('Support: ') + chalk.cyan('https://discord.gg/zv6maQRah3'))
|
||||
console.log(chalk.red('=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+='))
|
||||
|
||||
if(paneltable.get('URL') === null) console.log(chalk.cyan('It seems you are using our bot for first time, thank you for choosing our bot, if you need help you can join our support server!'))
|
||||
if(paneltable.get('URL') !== api) console.log(chalk.cyan('Panel url changed, please allow the bot to check the nodes status for ' + time + ' seconds'))
|
||||
paneltable.set('URL',api)
|
||||
|
||||
setInterval(() => {
|
||||
if (isNaN(time)) return console.log(chalk.cyan('[PteroStats Checker] ') + chalk.red(time + ' is not a number!'))
|
||||
if (!hosturl.includes('.')) return console.log(chalk.cyan('[PteroStats Checker] ') + chalk.red(hosturl + ' is invalid url!'))
|
||||
if (adminapikey.length < 48) return console.log(chalk.cyan('[PteroStats Checker] ') + chalk.red('Invalid Admin Apikey!!'))
|
||||
|
||||
let list = []
|
||||
axios(api + '/application/nodes/', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + adminapikey
|
||||
}
|
||||
}).then(async (response) => {
|
||||
let data = response.data.data
|
||||
data.forEach(nodes => {
|
||||
let id = nodes.attributes.id
|
||||
axios(api + '/application/nodes/' + id + '?include=servers,location,allocations', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + adminapikey
|
||||
}
|
||||
}).then(node => {
|
||||
axios(api + '/application/nodes/' + id + '/configuration', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + adminapikey
|
||||
}
|
||||
}).then(data => {
|
||||
axios(node.data.attributes.scheme + '://' + node.data.attributes.fqdn + ':' + node.data.attributes.daemon_listen + '/api/servers', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + data.data.token
|
||||
}
|
||||
}).then(status => {
|
||||
let ram = 'temp'
|
||||
let disk = 'temp'
|
||||
|
||||
const mode = node.data.attributes.maintenance_mode
|
||||
const loc = '[Locations: ' + node.data.attributes.relationships.location.attributes.short + ']'
|
||||
const port = '[Allocations: ' + node.data.attributes.relationships.allocations.data.length + ']'
|
||||
const servers = '[Servers: ' + node.data.attributes.relationships.servers.data.length + ']'
|
||||
const rampercent = '[Ram: ' + Math.floor(node.data.attributes.allocated_resources.memory / node.data.attributes.memory * 100) + '%/100%]'
|
||||
const diskpercent = '[Disk: ' + Math.floor(node.data.attributes.allocated_resources.disk / node.data.attributes.disk * 100) + '%/100%]'
|
||||
const rammega = '[Ram: ' + node.data.attributes.allocated_resources.memory + 'MB/' + node.data.attributes.memory + 'MB]'
|
||||
const diskmega = '[Disk: ' + node.data.attributes.allocated_resources.disk + 'MB/' + node.data.attributes.disk + 'MB]'
|
||||
const ramgiga = '[Ram: ' + Math.floor(node.data.attributes.allocated_resources.memory / 1000) + 'GB/' + Math.floor(node.data.attributes.memory / 1000) + 'GB]'
|
||||
const diskgiga = '[Disk: ' + Math.floor(node.data.attributes.allocated_resources.disk / 1000) + 'GB/' + Math.floor(node.data.attributes.disk / 1000) + 'GB]'
|
||||
if (unit === 'mb') {
|
||||
disk = diskmega
|
||||
ram = rammega
|
||||
}
|
||||
if (unit === 'gb') {
|
||||
disk = diskgiga
|
||||
ram = ramgiga
|
||||
}
|
||||
if (unit === 'percent') {
|
||||
disk = diskpercent
|
||||
ram = rampercent
|
||||
}
|
||||
|
||||
nodetable.set('node' + id, {
|
||||
ram: ram,
|
||||
disk: disk,
|
||||
status: true,
|
||||
servers: servers,
|
||||
location: loc,
|
||||
port: port,
|
||||
mode: mode
|
||||
})
|
||||
|
||||
}).catch((err) => {
|
||||
let servers = '[Servers: N/A]'
|
||||
let loc = '[Location: N/A]'
|
||||
let port = '[Allocations: N/A]'
|
||||
let ram = '[Ram: N/A]'
|
||||
let disk = '[Disk: N/A]'
|
||||
|
||||
console.log(chalk.cyan('[PteroStats Checker] ') + chalk.red(node.data.attributes.name + ' is down!'))
|
||||
if (debugerror === true) console.log(chalk.magenta('[PteroStats Debug] ') + chalk.red(err) + chalk.cyan(' Need Support? https://discord.gg/zv6maQRah3'))
|
||||
|
||||
nodetable.set('node' + id, {
|
||||
ram: ram,
|
||||
disk: disk,
|
||||
status: false,
|
||||
servers: servers,
|
||||
location: loc,
|
||||
port: port,
|
||||
mode: false
|
||||
})
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.log(chalk.magenta('[PteroStats Debug] ') + chalk.red(err) + chalk.cyan(' Need Support? https://discord.gg/zv6maQRah3'))
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.log(chalk.magenta('[PteroStats Debug] ') + chalk.red(err) + chalk.cyan(' Need Support? https://discord.gg/zv6maQRah3'))
|
||||
})
|
||||
|
||||
let stats = nodetable.get('node' + id)
|
||||
let msgStats;
|
||||
if (`${stats}` === 'null') msgStats = '**' + nodes.attributes.name + '**: ' + checking + '\n'
|
||||
if (`${stats}` !== 'null') {
|
||||
let statsname = '**' + nodes.attributes.name + '**: '
|
||||
|
||||
if (stats.status === true) statsname = statsname + statusonline
|
||||
if (stats.status === false) statsname = statsname + statusoffline
|
||||
|
||||
if (resource === false) msgStats = statsname + '\n'
|
||||
|
||||
if (stats.mode === true) statsname = statsname + ' [Maintance]'
|
||||
|
||||
if (resource === true) statsname = statsname + '\n```\n' + stats.ram + '\n' + stats.disk
|
||||
if (serverloc === true) statsname = statsname + '\n' + stats.location
|
||||
if (serverport === true) statsname = statsname + '\n' + stats.port
|
||||
if (serverres === true) statsname = statsname + '\n' + stats.servers
|
||||
if (resource === false) statsname = statsname + '\n'
|
||||
|
||||
if (resource === true) msgStats = statsname + '```\n'
|
||||
}
|
||||
|
||||
list.push(msgStats)
|
||||
})
|
||||
|
||||
axios(api + '/application/servers', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + adminapikey
|
||||
}
|
||||
}).then(ser => {
|
||||
let res = ser.data.meta.pagination.total
|
||||
paneltable.set('serverCount', res)
|
||||
}).catch((err) => {
|
||||
paneltable.set('serverCount', 'N/A')
|
||||
console.log(chalk.cyan('[PteroStats Checker] ') + chalk.red('Panel is down'))
|
||||
if (debugerror === true) console.log(chalk.magenta('[PteroStats Debug] ') + err)
|
||||
})
|
||||
|
||||
axios(api + '/application/users', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + adminapikey
|
||||
}
|
||||
}).then(usr => {
|
||||
let res = usr.data.meta.pagination.total
|
||||
paneltable.set('userCount', res)
|
||||
}).catch((err) => {
|
||||
paneltable.set('userCount', 'N/A')
|
||||
console.log(chalk.cyan('[PteroStats Checker] ') + chalk.red('Panel is down!'))
|
||||
if (debugerror === true) console.log(chalk.magenta('[PteroStats Debug] ') + err)
|
||||
})
|
||||
|
||||
let userCount = paneltable.get('userCount')
|
||||
let serverCount = paneltable.get('serverCount')
|
||||
|
||||
if (userCount === null) userCount = 'checking'
|
||||
if (serverCount === null) serverCount = 'checking'
|
||||
|
||||
if (userCount !== 'N/A') paneltable.set('panel', '**Panel**: ' + statusonline)
|
||||
if (userCount === 'N/A') {
|
||||
paneltable.set('panel', '**Panel**: ' + statusoffline)
|
||||
console.log(chalk.cyan('[PteroStats Checker] ') + chalk.red('panel is down!'))
|
||||
}
|
||||
if (userCount === checking) paneltable.set('panel', '**Panel**: ' + checking)
|
||||
let panel = paneltable.get('panel') + '\n\nUsers: ' + userCount + '\nServers: ' + serverCount
|
||||
|
||||
if (panel === null) panel = '**Panel**: ' + checking + '\n\nUsers: ' + userCount + '\nServers: ' + serverCount
|
||||
|
||||
let nodes
|
||||
list.forEach((d) => {
|
||||
if (!nodes) return nodes = d
|
||||
nodes = nodes + d
|
||||
})
|
||||
|
||||
console.log(chalk.cyan(['[PteroStats Checker] ']) + chalk.green('Connected to ' + list.length + ' nodes'))
|
||||
let nodeCount = '[Total ' + list.length + ']'
|
||||
|
||||
if (debug === true) console.log(chalk.magenta('[PteroStats Debug] ') + chalk.blue(nodes))
|
||||
if (nodes === undefined) {
|
||||
nodes = checking + ' Please wait ' + time + ' seconds'
|
||||
console.log(chalk.cyan(['[PteroStats Checker] ']) + chalk.yellow(checking + ' Please wait ' + time + ' seconds'))
|
||||
}
|
||||
|
||||
let embedfooter = 'Updated every ' + time + ' seconds'
|
||||
if (enablef === true) embedfooter = 'Updated every ' + time + ' seconds | ' + footer
|
||||
|
||||
let embed = new MessageEmbed()
|
||||
.setTitle(title)
|
||||
.setColor(color)
|
||||
.addField('Panel Stats', panel)
|
||||
.setFooter(embedfooter)
|
||||
.setThumbnail(client.user.avatarURL())
|
||||
if (enablets === true) {
|
||||
embed.setTimestamp()
|
||||
}
|
||||
if (enabledesc === true) {
|
||||
embed.setDescription(desc + '\n**Nodes Stats' + nodeCount + '**\n' + nodes)
|
||||
} else {
|
||||
embed.setDescription('\n**Nodes Stats' + nodeCount + '**\n' + nodes)
|
||||
}
|
||||
|
||||
let messages = await ch.messages.fetch({limit: 10})
|
||||
messages = messages.filter(m => m.author.id === client.user.id).last();
|
||||
if (messages == null) ch.send(embed)
|
||||
else messages.edit(embed)
|
||||
|
||||
|
||||
console.log(chalk.cyan('[PteroStats Checker] ') + chalk.green('Posted Stats'))
|
||||
if (panel !== null) console.log(chalk.cyan('[PteroStats Checker] ') + chalk.green('Stats Updated'))
|
||||
console.log(chalk.cyan('[PteroStats Checker] ') + chalk.green('Updating Stats in ' + time + ' Seconds'))
|
||||
|
||||
}).catch((err) => {
|
||||
console.log(chalk.magenta('[PteroStats Debug] ') + chalk.red(err) + chalk.cyan(' Need Support? https://discord.gg/zv6maQRah3'))
|
||||
})
|
||||
}, time + '000')
|
||||
}
|
||||
setInterval(() => {
|
||||
checkStatus(client)
|
||||
}, client.config.refresh * 1000)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
const axios = require('axios')
|
||||
const chalk = require('chalk')
|
||||
|
||||
const postStatus = require('./postStatus')
|
||||
|
||||
module.exports = function checkStatus(client) {
|
||||
|
||||
if (client.config.channel.startsWith('Put')) {
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Err! Invalid Channel ID'))
|
||||
process.exit()
|
||||
} else if (client.config.panel.url.startsWith('Put')) {
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Err! Invalid Panel URL'))
|
||||
process.exit()
|
||||
} else if (client.config.panel.key.startsWith('Put')) {
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Err! Invalid Apikey'))
|
||||
process.exit()
|
||||
} else if (!client.config.panel.url.startsWith('http')) {
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Err! Invalid Panel URL'))
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.red('1. Make sure the panel url is starts with "https://" or "http://"'))
|
||||
process.exit()
|
||||
}
|
||||
|
||||
if (client.config.panel.url.endsWith('/')) client.config.panel.url = client.config.panel.url.slice(0, -1)
|
||||
|
||||
const nodes = []
|
||||
|
||||
const panel = {
|
||||
status: false,
|
||||
total_servers: -1,
|
||||
total_users: -1,
|
||||
}
|
||||
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.green('Getting nodes stats'))
|
||||
|
||||
const panelStats = new Promise((resolve, reject) => {
|
||||
axios(client.config.panel.url + '/api/application/users', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + client.config.panel.key
|
||||
}
|
||||
}).then((usr) => {
|
||||
axios(client.config.panel.url + '/api/application/servers', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + client.config.panel.key
|
||||
}
|
||||
}).then((ser) => {
|
||||
panel.total_users = usr.data.meta.pagination.total
|
||||
panel.total_servers = ser.data.meta.pagination.total
|
||||
panel.status = true
|
||||
|
||||
resolve()
|
||||
})
|
||||
}).catch((err) => {
|
||||
if (err.response) {
|
||||
if (err.response.status === 403) {
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Err! Invalid apikey'))
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.red('1. Make sure the apikey is from admin page not account page'))
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.red('2. Make sure the apikey has read permission on all options'))
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.red('3. Make sure the apikey is exist'))
|
||||
} else if (err.response.status === 404) {
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Err! Invalid Panel URL'))
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.red('1. Make sure the panel url is like "https://panel.example.com"'))
|
||||
} else console.log(chalk.cyan('[PteroStats] ') + chalk.red('Err! ' + err))
|
||||
} else console.log(chalk.cyan('[PteroStats] ') + chalk.red('Err! ' + err))
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
const nodeStats = new Promise((resolve, reject) => {
|
||||
axios(client.config.panel.url + '/api/application/nodes?include=servers,location,allocations', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + client.config.panel.key
|
||||
}
|
||||
}).then((res) => {
|
||||
res.data.data.forEach((node, i) => {
|
||||
axios(client.config.panel.url + '/api/application/nodes/' + node.attributes.id + '/configuration', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + client.config.panel.key
|
||||
}
|
||||
}).then((data) => {
|
||||
const body = {
|
||||
id: node.attributes.id,
|
||||
name: node.attributes.name,
|
||||
location: node.attributes.relationships.location.attributes.short,
|
||||
allocations: node.attributes.relationships.allocations.data.length,
|
||||
status: true,
|
||||
maintenance: node.attributes.maintenance_mode,
|
||||
total_servers: node.attributes.relationships.servers.data.length,
|
||||
memory_min: node.attributes.allocated_resources.memory,
|
||||
memory_max: node.attributes.memory,
|
||||
disk_min: node.attributes.allocated_resources.disk,
|
||||
disk_max: node.attributes.disk,
|
||||
}
|
||||
|
||||
const stats = new Promise((statsResolve, statsReject) => {
|
||||
axios(node.attributes.scheme + '://' + node.attributes.fqdn + ':' + node.attributes.daemon_listen + '/api/servers', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + data.data.token
|
||||
}
|
||||
}).then((status) => {
|
||||
return statsResolve()
|
||||
}).catch((err) => {
|
||||
body.status = false
|
||||
return statsResolve()
|
||||
})
|
||||
setTimeout(() => {
|
||||
body.status = false
|
||||
return statsResolve()
|
||||
}, 1000)
|
||||
})
|
||||
stats.then(() => {
|
||||
nodes.push(body)
|
||||
if (nodes.length === res.data.data.length) resolve()
|
||||
})
|
||||
}).catch((err) => {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}).catch((err) => {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
panelStats.then(() => {
|
||||
nodeStats.then(() => {
|
||||
nodes.sort(function (a, b) { return a.id - b.id })
|
||||
postStatus(client, panel, nodes)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
const { EmbedBuilder, time, ActionRowBuilder, ButtonBuilder, ButtonStyle, AttachmentBuilder } = require('discord.js')
|
||||
const chalk = require('chalk')
|
||||
|
||||
module.exports = async function postStatus(client, panel, nodes) {
|
||||
|
||||
if (!client.config.nodes_resource) client.config.nodes_resource = client.config.resource
|
||||
if (!client.config.nodes_resource.blacklist) client.config.nodes_resource.blacklist = []
|
||||
if (!Array.isArray(client.config.nodes_resource.blacklist) && Number.isInteger(client.config.nodes_resource.blacklist)) client.config.nodes_resource.blacklist = [client.config.nodes_resource.blacklist]
|
||||
if (!client.config.message.attachment) client.config.message.attachment = client.config.message.image
|
||||
|
||||
if (client.guilds.cache.size < 1) return console.log(chalk.cyan('[PteroStats] ') + chalk.red('Err! This bot is not on any discord servers'))
|
||||
|
||||
const channel = await client.channels.cache.get(client.config.channel)
|
||||
|
||||
if (!channel) return console.log(chalk.cyan('[PteroStats] ') + chalk.red('Err! Invalid Channel ID'))
|
||||
|
||||
let messages = await channel.messages.fetch({ limit: 10 })
|
||||
messages = messages.filter(m => m.author.id === client.user.id).last();
|
||||
if (messages && messages.embeds.length < 1) {
|
||||
messages.delete()
|
||||
messages = null
|
||||
}
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
|
||||
let text = ''
|
||||
let desc = ''
|
||||
let blacklist = 0
|
||||
|
||||
let content = null
|
||||
const files = []
|
||||
|
||||
if (client.config.message.content) content = client.config.message.content
|
||||
if (client.config.message.attachment) files.push(new AttachmentBuilder(client.config.message.attachment))
|
||||
|
||||
if (client.config.embed.title) embed.setTitle(client.config.embed.title)
|
||||
if (client.config.embed.description) desc = client.config.embed.description + '\n'
|
||||
if (client.config.embed.color) embed.setColor(client.config.embed.color)
|
||||
if (client.config.embed.footer) embed.setFooter({ text: client.config.embed.footer })
|
||||
if (client.config.embed.thumbnail) embed.setThumbnail(client.config.embed.thumbnail)
|
||||
if (client.config.embed.image) embed.setImage(client.config.embed.image)
|
||||
|
||||
panel.total_users = panel.total_users.toLocaleString()
|
||||
panel.total_servers = panel.total_servers.toLocaleString()
|
||||
|
||||
const stats = new Promise((resolve, reject) => {
|
||||
if (nodes.length !== 0) {
|
||||
nodes.forEach((data, i) => {
|
||||
if (!client.config.nodes_resource.blacklist.includes(data.id)) {
|
||||
const title = data.name + ': ' + String(data.status).replace('true', client.config.status.online).replace('false', client.config.status.offline)
|
||||
let description = '```'
|
||||
switch (client.config.nodes_resource.unit.toLowerCase()) {
|
||||
case 'tb':
|
||||
description = description +
|
||||
'\nMemory : ' + Math.floor(data.memory_min / (1024 * 1000)).toLocaleString() + ' TB / ' + Math.floor(data.memory_max / (1024 * 1000)).toLocaleString() + ' TB' +
|
||||
'\nDisk : ' + Math.floor(data.disk_min / (1024 * 1000)).toLocaleString() + ' TB / ' + Math.floor(data.disk_max / (1024 * 1000)).toLocaleString() + ' TB'
|
||||
break;
|
||||
case 'gb':
|
||||
description = description +
|
||||
'\nMemory : ' + Math.floor(data.memory_min / 1024).toLocaleString() + ' GB / ' + Math.floor(data.memory_max / 1024).toLocaleString() + ' GB' +
|
||||
'\nDisk : ' + Math.floor(data.disk_min / 1024).toLocaleString() + ' GB / ' + Math.floor(data.disk_max / 1024).toLocaleString() + ' GB'
|
||||
break;
|
||||
case 'percent':
|
||||
description = description +
|
||||
'\nMemory : ' + Math.floor(data.memory_min / data.memory_max * 100) + ' %' +
|
||||
'\nDisk : ' + Math.floor(data.disk_min / data.disk_max * 100) + ' %'
|
||||
break;
|
||||
default:
|
||||
description = description +
|
||||
'\nMemory : ' + data.memory_min.toLocaleString() + ' MB / ' + data.memory_max.toLocaleString() + ' MB' +
|
||||
'\nDisk : ' + data.disk_min.toLocaleString() + ' MB / ' + data.disk_max.toLocaleString() + ' MB'
|
||||
}
|
||||
|
||||
if (client.config.nodes_resource.servers) description = description + '\nServers : ' + data.total_servers.toLocaleString()
|
||||
if (client.config.nodes_resource.location) description = description + '\nLocation : ' + data.location
|
||||
if (client.config.nodes_resource.allocations) description = description + '\nAllocations : ' + data.allocations.toLocaleString()
|
||||
|
||||
description = description + '\n```'
|
||||
|
||||
if (client.config.nodes_resource.enable) {
|
||||
text = text + '\n**' + title.replace(':', ':**') + '\n' + description
|
||||
} else {
|
||||
text = text + '\n**' + title.replace(':', ':**')
|
||||
}
|
||||
} else {
|
||||
blacklist = blacklist + 1
|
||||
if (nodes.length - client.config.nodes_resource.blacklist.length < 1) text = '\nThere is no nodes to display'
|
||||
}
|
||||
|
||||
if (i + 1 === nodes.length) resolve()
|
||||
})
|
||||
} else if (nodes.length < 1) {
|
||||
if (!messages) {
|
||||
text = '\nThere is no nodes to display'
|
||||
resolve()
|
||||
} else {
|
||||
text = messages.embeds[0].description.replaceAll(client.config.status.online, client.config.status.offline)
|
||||
if (!panel.status && String(String(messages.embeds[0].fields[0].value).split('\n')[2]).split('')[String(String(messages.embeds[0].fields[0].value).split('\n')[2]).length - 1] !== '`') {
|
||||
panel.total_users = String(String(messages.embeds[0].fields[0].value).split('\n')[2]).split('')[String(String(messages.embeds[0].fields[0].value).split('\n')[2]).length - 1]
|
||||
panel.total_servers = String(String(messages.embeds[0].fields[0].value).split('\n')[3]).split('')[String(String(messages.embeds[0].fields[0].value).split('\n')[3]).length - 1]
|
||||
}
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
stats.then(async () => {
|
||||
const format = await time(new Date(Date.now() + client.config.refresh * 1000), 'R')
|
||||
embed.setDescription(desc.replaceAll('{{time}}', format) + '\n**Nodes Stats [' + Math.floor(nodes.length - blacklist) + ']**' + text)
|
||||
const EmbedFields = []
|
||||
|
||||
if (client.config.panel_resource.enable) {
|
||||
let stats = '**Status:** ' + String(panel.status).replace('true', client.config.status.online).replace('false', client.config.status.offline) + '\n\n'
|
||||
|
||||
if (client.config.panel_resource.users) stats = stats + 'Users: ' + String(panel.total_users).replace('-1', '`Unknown`') + '\n'
|
||||
if (client.config.panel_resource.servers) stats = stats + 'Servers: ' + String(panel.total_servers).replace('-1', '`Unknown`')
|
||||
|
||||
EmbedFields.push({ name: 'Panel Stats', value: stats })
|
||||
}
|
||||
|
||||
if (client.config.embed.field.enable) EmbedFields.push({ name: client.config.embed.field.title, value: client.config.embed.field.description.replaceAll('{{time}}', format) })
|
||||
if (client.config.embed.timestamp) embed.setTimestamp()
|
||||
if (EmbedFields.length > 0) embed.addFields(EmbedFields)
|
||||
|
||||
const row = []
|
||||
|
||||
if (client.config.button.enable) {
|
||||
const button = new ActionRowBuilder
|
||||
if (client.config.button.btn1.label.length !== 0 && client.config.button.btn1.url.length !== 0) {
|
||||
button.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setLabel(client.config.button.btn1.label)
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setURL(client.config.button.btn1.url)
|
||||
)
|
||||
}
|
||||
if (client.config.button.btn2.label.length !== 0 && client.config.button.btn2.url.length !== 0) {
|
||||
button.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setLabel(client.config.button.btn2.label)
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setURL(client.config.button.btn2.url)
|
||||
)
|
||||
}
|
||||
if (client.config.button.btn3.label.length !== 0 && client.config.button.btn3.url.length !== 0) {
|
||||
button.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setLabel(client.config.button.btn3.label)
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setURL(client.config.button.btn3.url)
|
||||
)
|
||||
}
|
||||
if (client.config.button.btn4.label.length !== 0 && client.config.button.btn4.url.length !== 0) {
|
||||
button.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setLabel(client.config.button.btn4.label)
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setURL(client.config.button.btn4.url)
|
||||
)
|
||||
}
|
||||
if (client.config.button.btn5.label.length !== 0 && client.config.button.btn5.url.length !== 0) {
|
||||
button.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setLabel(client.config.button.btn5.label)
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setURL(client.config.button.btn5.url)
|
||||
)
|
||||
}
|
||||
row.push(button)
|
||||
}
|
||||
|
||||
if (!messages) channel.send({ content: content, embeds: [embed], components: row, files: files })
|
||||
else messages.edit({ content: content, embeds: [embed], components: row, files: files })
|
||||
console.log(chalk.cyan('[PteroStats] ') + chalk.green('Stats posted!'))
|
||||
})
|
||||
}
|
||||
@@ -1,19 +1,52 @@
|
||||
const { Client, Collection } = require('discord.js')
|
||||
const fs = require('fs')
|
||||
const client = new Client()
|
||||
const yaml = require('js-yaml')
|
||||
const chalk = require('chalk')
|
||||
const config = yaml.load(fs.readFileSync('./config.yml', 'utf8'))
|
||||
const fs = require('fs');
|
||||
const child = require('child_process');
|
||||
|
||||
if (Number(process.version.split('.')[0]) < 16) {
|
||||
console.log('Invalid NodeJS Version!, Please use NodeJS 16.x or upper')
|
||||
process.exit()
|
||||
}
|
||||
if (fs.existsSync('./node_modules')) {
|
||||
const check = require('./node_modules/discord.js/package.json')
|
||||
if (Number(check.version.split('.')[0]) !== 14) {
|
||||
console.log('Invalid Discord.JS Version!, Please use Discord.JS 14.x')
|
||||
process.exit()
|
||||
}
|
||||
} else {
|
||||
console.log('You didn\'t install the required node packages first!')
|
||||
console.log('Please wait... starting to install all required node packages using child process')
|
||||
try {
|
||||
child.execSync('npm i')
|
||||
console.log('Install complete!, please run "node index" command again!')
|
||||
process.exit()
|
||||
} catch (err) {
|
||||
console.log('Err! ', err)
|
||||
console.log('Support Server: https://discord.gg/zv6maQRah3')
|
||||
process.exit()
|
||||
}
|
||||
}
|
||||
|
||||
const chalk = require('chalk');
|
||||
const yaml = require('js-yaml');
|
||||
const { Client, GatewayIntentBits } = require('discord.js');
|
||||
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
|
||||
|
||||
const config = yaml.load(fs.readFileSync('./config.yml', 'utf8'));
|
||||
client.config = config
|
||||
|
||||
fs.readdir('./events/', (err, files) => {
|
||||
if (err) return console.error(err)
|
||||
files.forEach(file => {
|
||||
const event = require(`./events/${file}`)
|
||||
const eventName = file.split('.')[0]
|
||||
client.on(eventName, event.bind(null, client))
|
||||
})
|
||||
})
|
||||
const eventFiles = fs.readdirSync('./events').filter(file => file.endsWith('.js'));
|
||||
|
||||
if (config.token === 'BOT TOKEN') console.log(chalk.blue('[PteroStats Checker] ') + chalk.red('Invalid Token, Check ') + chalk.green('config.yml') + chalk.red(' file to change token'))
|
||||
client.login(config.token)
|
||||
for (const file of eventFiles) {
|
||||
const event = require(`./events/${file}`);
|
||||
if (event.once) {
|
||||
client.once(event.name, (...args) => event.execute(...args));
|
||||
} else {
|
||||
client.on(event.name, (...args) => event.execute(...args));
|
||||
}
|
||||
}
|
||||
|
||||
if (client.config.token.startsWith('Put') || client.config.token.length < 1) {
|
||||
console.log(chalk.cyan('[PteroStats]') + chalk.red(' Err! Invalid Discord Bot Token'))
|
||||
process.exit()
|
||||
}
|
||||
|
||||
client.login(config.token);
|
||||
+23
-24
@@ -1,25 +1,24 @@
|
||||
{
|
||||
"name": "pterostats",
|
||||
"version": "v1.5.5",
|
||||
"description": "PteroStats is a bot designed to check Panel, Nodes, and Databases status and post it to your discord server",
|
||||
"license": "Apache-2.0",
|
||||
"repository": "HirziDevs/PteroStats",
|
||||
"homepage": "https://pterostats.hirzidevs.net",
|
||||
"bugs": {
|
||||
"email": "hirzidevs@gmail.com",
|
||||
"url": "https://github.com/HirziDevs/PteroStats"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.21.1",
|
||||
"chalk": "^4.1.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"discord.js": "12.5.3",
|
||||
"quick.db": "^7.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.x"
|
||||
}
|
||||
}
|
||||
"name": "pterostats",
|
||||
"version": "v3.0.0",
|
||||
"description": "PteroStats is a bot designed to check Pterodactyl Panel and Nodes status and post it to your discord server",
|
||||
"license": "MIT",
|
||||
"repository": "HirziDevs/PteroStats",
|
||||
"homepage": "https://pterostats.hirzidevs.net",
|
||||
"bugs": {
|
||||
"email": "hirzidevs@gmail.com",
|
||||
"url": "https://github.com/HirziDevs/PteroStats"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.1.3",
|
||||
"chalk": "4.1.1",
|
||||
"discord.js": "^14.6.0",
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.x"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user