New Features-Replace promises with async await, recoded and fixed bugs i could find, created seperate modules for calculation, made the pakcges intrigity check better, updated packages version

This commit is contained in:
ShreshthTiwari
2023-07-11 18:11:17 +05:30
committed by Hirzi
parent bf2cbf24a1
commit 9b2e6adefa
8 changed files with 985 additions and 435 deletions

View File

@@ -1,55 +1,90 @@
const { ActivityType } = require('discord.js')
const chalk = require('chalk')
const checkStatus = require('../handlers/checkStatus')
const { ActivityType } = require("discord.js");
const chalk = require("chalk");
const checkStatus = require("../handlers/checkStatus");
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'))
console.log(chalk.cyan('[PteroStats] ') + chalk.yellow('If some node is online but the embed is read as offline, please enable ') + chalk.green('log_error') + chalk.yellow(' on config file and report it at https://discord.gg/zv6maQRah3'))
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"
)
);
console.log(
chalk.cyan("[PteroStats] ") +
chalk.yellow(
"If some node is online but the embed is read as offline, please enable "
) +
chalk.green("log_error") +
chalk.yellow(
" on config file and report it at https://discord.gg/zv6maQRah3"
)
);
if (client.guilds.cache.size < 1) return console.log(chalk.cyan('[PteroStats] ') + chalk.red('Error! This bot is not on any discord servers'))
if (client.config.timeout < 1) {
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Timeout cannot be less than 1 seconds!'))
client.config.timeout = 1
}
if (client.guilds.cache.size < 1)
return console.log(
chalk.cyan("[PteroStats] ") +
chalk.red("Error! This bot is not on any discord servers")
);
if (client.config.timeout < 1) {
console.log(
chalk.cyan("[PteroStats] ") +
chalk.red("Timeout cannot be less than 1 seconds!")
);
client.config.timeout = 1;
}
if (client.config.refresh > 1 && client.config.refresh < 10) console.log(chalk.cyan('[PteroStats] ') + chalk.red('Refresh Time below 10 seconds is not recommended!'))
else if (client.config.refresh < 1) {
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Refresh Time cannot be less than 1 seconds!'))
client.config.refresh = 10
}
if (client.config.refresh > 1 && client.config.refresh < 10)
console.log(
chalk.cyan("[PteroStats] ") +
chalk.red("Refresh Time below 10 seconds is not recommended!")
);
else if (client.config.refresh < 1) {
console.log(
chalk.cyan("[PteroStats] ") +
chalk.red("Refresh Time cannot be less than 1 seconds!")
);
client.config.refresh = 10;
}
if (client.config.presence.text && client.config.presence.type) {
switch (client.config.presence.type.toLowerCase()) {
case 'playing':
client.config.presence.type = ActivityType.Playing
break;
case 'listening':
client.config.presence.type = ActivityType.Listening
break;
case 'competing':
client.config.presence.type = ActivityType.Competing
break;
default:
client.config.presence.type = ActivityType.Watching
}
if (client.config.presence.text && client.config.presence.type) {
switch (client.config.presence.type.toLowerCase()) {
case "playing":
client.config.presence.type = ActivityType.Playing;
break;
case "listening":
client.config.presence.type = ActivityType.Listening;
break;
case "competing":
client.config.presence.type = ActivityType.Competing;
break;
default:
client.config.presence.type = ActivityType.Watching;
}
client.user.setActivity(client.config.presence.text, { type: client.config.presence.type })
}
client.user.setActivity(client.config.presence.text, {
type: client.config.presence.type,
});
}
if (client.config.presence.status) {
if (!['idle', 'online', 'dnd', 'invisible'].includes(client.config.presence.status.toLowerCase())) client.config.presence.status = 'online'
if (client.config.presence.status) {
if (
!["idle", "online", "dnd", "invisible"].includes(
client.config.presence.status.toLowerCase()
)
)
client.config.presence.status = "online";
client.user.setStatus(client.config.presence.status);
}
client.user.setStatus(client.config.presence.status);
}
checkStatus({ client: client })
checkStatus({ client: client });
setInterval(() => {
checkStatus({ client: client })
}, client.config.refresh * 1000)
}
}
setInterval(async () => {
await checkStatus({ client: client });
}, client.config.refresh * 1000);
},
};

View File

@@ -1,189 +1,343 @@
const { EmbedBuilder } = require('discord.js')
const axios = require('axios')
const chalk = require('chalk')
const { EmbedBuilder } = require("discord.js");
const axios = require("axios");
const axiosRetry = require("axios-retry");
const chalk = require("chalk");
const postStatus = require('./postStatus')
const postStatus = require("./postStatus");
module.exports = function checkStatus({ client }) {
axiosRetry(axios, { retries: 5 });
function Embed({ node }) {
return new EmbedBuilder()
.setTitle('Node Logging') //if you wanted to change this please change at line 175 too
.setDescription('`' + node.name + '` is down!')
.setFooter({ text: 'Please see console for more details' })
.setTimestamp()
.setColor('ED4245')
}
module.exports = async ({ client }) => {
function Embed({ node }) {
return new EmbedBuilder()
.setTitle("Node Logging") //if you wanted to change this please change at line 175 too
.setDescription("`" + node.name + "` is down!")
.setFooter({ text: "Please see console for more details" })
.setTimestamp()
.setColor("ED4245");
}
if (client.config.channel.startsWith('Put')) {
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Error! Invalid Channel ID'))
process.exit()
} else if (client.config.panel.url.startsWith('Put')) {
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Error! Invalid Panel URL'))
process.exit()
} else if (client.config.panel.key.startsWith('Put')) {
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Error! Invalid Apikey'))
process.exit()
} else if (!client.config.panel.url.startsWith('http')) {
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Error! 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.channel.startsWith("Put")) {
console.log(
chalk.cyan("[PteroStats] ") + chalk.red("Error! Invalid Channel ID")
);
process.exit();
} else if (client.config.panel.url.startsWith("Put")) {
console.log(
chalk.cyan("[PteroStats] ") + chalk.red("Error! Invalid Panel URL")
);
process.exit();
} else if (client.config.panel.key.startsWith("Put")) {
console.log(
chalk.cyan("[PteroStats] ") + chalk.red("Error! Invalid Apikey")
);
process.exit();
} else if (!client.config.panel.url.startsWith("http")) {
console.log(
chalk.cyan("[PteroStats] ") + chalk.red("Error! 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)
if (client.config.panel.url.endsWith("/"))
client.config.panel.url = client.config.panel.url.slice(0, -1);
const nodes = []
const embeds = []
const nodes = [];
const embeds = [];
const panel = {
status: false,
total_servers: -1,
total_users: -1,
}
const panel = {
status: false,
total_servers: -1,
total_users: -1,
};
console.log(chalk.cyan('[PteroStats] ') + chalk.green('Getting nodes stats'))
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((users) => {
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((servers) => {
panel.total_users = users.data.meta.pagination.total
panel.total_servers = servers.data.meta.pagination.total
panel.status = true
try {
const users = await axios(
client.config.panel.url + "/api/application/users",
{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Bearer " + client.config.panel.key,
},
}
);
resolve()
})
}).catch((error) => {
if (error.response) {
if (error.response.status === 403) {
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Error! 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 (error.response.status === 404) {
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Error! 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('Error! ' + error))
} else console.log(chalk.cyan('[PteroStats] ') + chalk.red('Error! ' + error))
resolve()
})
})
if (users?.status === 200 && users?.data) {
const servers = await axios(
client.config.panel.url + "/api/application/servers",
{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Bearer " + client.config.panel.key,
},
}
);
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,
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,
}
if (servers?.status === 200 && users?.data) {
panel.total_users = users?.data?.meta?.pagination?.total || "ERROR";
panel.total_servers = servers?.data.meta?.pagination?.total || "ERROR";
panel.status = true;
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(() => {
body.status = true
return statsResolve()
}).catch((error) => {
if (client.config.log_error) console.log(chalk.cyan('[PteroStats] ') + chalk.yellow('[Node: ' + node.attributes.name + '] ') + chalk.red(error))
embeds.push(Embed({ node: body }))
body.status = false
return statsResolve()
})
setTimeout(() => {
if (body.status === undefined) {
if (client.config.log_error) console.log(chalk.cyan('[PteroStats] ') + chalk.yellow('[Node: ' + node.attributes.name + '] ') + chalk.red('Timeout!'))
embeds.push(Embed({ node: body }))
body.status = false
return statsResolve()
}
}, client.config.timeout * 1000)
})
stats.then(() => {
nodes.push(body)
if (nodes.length === res.data.data.length) resolve()
})
}).catch(() => resolve())
})
}).catch(() => resolve())
})
const res = await 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,
},
}
);
panelStats.then(() => {
nodeStats.then(async () => {
nodes.sort(function (a, b) { return a.id - b.id })
postStatus({ client: client, panel: panel, nodes: nodes })
if (res?.status === 200 && res?.data?.data) {
for (const node of res.data.data) {
const data = await 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,
},
}
);
// this feature is still in testing
if (client.config.mentions.user.length > 0 || client.config.mentions.role.length > 0 && client.config.mentions.channel) {
if (Array.isArray(client.config.mentions.user) || Array.isArray(client.config.mentions.role)) {
let mentions = ''
if (data?.status === 200 && data?.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,
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,
};
await client.config.mentions.user.forEach((user) => {
if (!isNaN(Number(user))) {
mentions = mentions + ' <@' + user + '>'
}
})
await client.config.mentions.role.forEach((role) => {
if (!isNaN(Number(role))) {
mentions = mentions + ' <@&' + role + '>'
}
})
try {
const stats = await 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,
},
}
);
const channel = await client.channels.cache.get(client.config.mentions.channel)
if (channel) {
const messages = await channel.messages.fetch({ limit: 10 }).then(msg => msg.filter(m => m.author.id === client.user.id && m.embeds[0].data.title === 'Node Logging').first())
if (messages) messages.embeds.forEach((MsgEmbed) => {
embeds.forEach((embed, i) => {
if (MsgEmbed.data.description === embed.data.description) embeds.splice(i, 1)
nodes.forEach((node) => {
if (MsgEmbed.data.description.startsWith('`' + node.name) && node.status === true) messages.delete()
})
})
})
if (embeds.length > 0) channel.send({ content: mentions, embeds: embeds })
}
}
}
})
})
}
if (stats?.status === 200 && stats?.data) {
body.status = true;
} else {
body.status = false;
}
setTimeout(() => {
if (!body?.status) {
if (client.config.log_error)
console.log(
chalk.cyan("[PteroStats] ") +
chalk.yellow(
"[Node: " + node.attributes.name + "] "
) +
chalk.red("Timeout!")
);
embeds.push(Embed({ node: body }));
body.status = false;
return statsResolve();
}
}, client.config.timeout * 1000);
} catch (error) {
if (client.config.log_error)
console.log(
chalk.cyan("[PteroStats] ") +
chalk.yellow("[Node: " + node.attributes.name + "] ") +
chalk.red(error)
);
embeds.push(Embed({ node: body }));
body.status = false;
}
nodes.push(body);
} else {
throw new Error(
JSON.stringify({
response: {
status: data.status,
},
})
);
}
}
nodes.sort(function (a, b) {
return a.id - b.id;
});
await postStatus({ client: client, panel: panel, nodes: nodes });
if (
client.config.mentions.user.length > 0 ||
(client.config.mentions.role.length > 0 &&
client.config.mentions.channel)
) {
if (
Array.isArray(client.config.mentions.user) ||
Array.isArray(client.config.mentions.role)
) {
let mentions = "";
await client.config.mentions.user.forEach((user) => {
if (!isNaN(Number(user))) {
mentions = mentions + " <@" + user + ">";
}
});
await client.config.mentions.role.forEach((role) => {
if (!isNaN(Number(role))) {
mentions = mentions + " <@&" + role + ">";
}
});
const channel = await client.channels.cache.get(
client.config.mentions.channel
);
if (channel) {
const messages = await channel.messages
.fetch({ limit: 10 })
.then((msg) =>
msg
.filter(
(m) =>
m.author.id === client.user.id &&
m.embeds[0].data.title === "Node Logging"
)
.first()
);
if (messages)
messages.embeds.forEach((MsgEmbed) => {
for (const embed of embeds) {
if (MsgEmbed.data.description === embed.data.description)
embeds.splice(i, 1);
nodes.forEach((node) => {
if (
MsgEmbed.data.description.startsWith(
"`" + node.name
) &&
node.status === true
)
messages.delete();
});
}
});
if (embeds.length > 0)
channel.send({ content: mentions, embeds: embeds });
}
}
}
} else {
throw new Error(
JSON.stringify({
response: {
status: res.status,
},
})
);
}
} else {
throw new Error(
JSON.stringify({
response: {
status: servers.status,
},
})
);
}
} else {
throw new Error(
JSON.stringify({
response: {
status: users.status,
},
})
);
}
} catch (error) {
try {
if (typeof error === "string") {
error = JSON.parse(error);
}
} catch {}
if (error?.response) {
if (error.response?.status === 403) {
console.log(
chalk.cyan("[PteroStats] ") + chalk.red("Error! 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 (error.response?.status === 404) {
console.log(
chalk.cyan("[PteroStats] ") + chalk.red("Error! 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("Error! " + error)
);
}
} else {
console.log(chalk.cyan("[PteroStats] ") + chalk.red("Error! " + error));
}
}
};

View File

@@ -1,169 +1,365 @@
const { EmbedBuilder, time, ActionRowBuilder, ButtonBuilder, ButtonStyle, AttachmentBuilder } = require('discord.js')
const chalk = require('chalk')
const {
EmbedBuilder,
time,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
AttachmentBuilder,
} = require("discord.js");
const chalk = require("chalk");
module.exports = async function postStatus({ client, panel, nodes }) {
const memorySizeConverter = require("../modules/memorySizeConverter");
const percentageCalculator = require("../modules/percentageCalculator");
const channel = await client.channels.cache.get(client.config.channel)
if (!channel) return console.log(chalk.cyan('[PteroStats] ') + chalk.red('Error! Invalid Channel ID'))
const BUFFER_MS = 2000; //Added these extra milliseconds to prevent the stats timer from showing "1 or 2 seconds ago" before updating the stats.
const files = []
const embed = new EmbedBuilder()
let messages = await channel.messages.fetch({ limit: 10 }).then(msg => msg.filter(m => m.author.id === client.user.id).last())
let text = ''
let desc = ''
let blacklist = 0
let content = null
module.exports = async ({ client, panel, nodes }) => {
const channel = await client.channels.cache.get(client.config.channel);
if (!channel) {
return console.log(
chalk.cyan("[PteroStats] ") + chalk.red("Error! Invalid Channel ID")
);
}
if (!client.config.nodes_settings.blacklist) client.config.nodes_settings.blacklist = []
if (!Array.isArray(client.config.nodes_settings.blacklist) && Number.isInteger(client.config.nodes_settings.blacklist)) client.config.nodes_settings.blacklist = [client.config.nodes_settings.blacklist]
if (client.guilds.cache.size < 1) return console.log(chalk.cyan('[PteroStats] ') + chalk.red('Error! This bot is not on any discord servers'))
if (messages && messages.embeds.length < 1) {
messages.delete()
messages = 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)
const embed = new EmbedBuilder();
panel.total_users = panel.total_users.toLocaleString()
panel.total_servers = panel.total_servers.toLocaleString()
let messages = await channel.messages
.fetch({ limit: 10 })
.then((msg) => msg.filter((m) => m.author.id === client.user.id).last());
const stats = new Promise((resolve, reject) => {
if (nodes.length !== 0) {
nodes.forEach((data, i) => {
if (!client.config.nodes_settings.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_settings.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'
}
let text = "";
let desc = "";
let blacklist = 0;
let content = null;
if (client.config.nodes_settings.servers) description = description + '\nServers : ' + data.total_servers.toLocaleString()
if (client.config.nodes_settings.location) description = description + '\nLocation : ' + data.location
if (client.config.nodes_settings.allocations) description = description + '\nAllocations : ' + data.allocations.toLocaleString()
if (!client.config.nodes_settings.blacklist) {
client.config.nodes_settings.blacklist = [];
}
description = description + '\n```'
if (
!Array.isArray(client.config.nodes_settings.blacklist) &&
Number.isInteger(client.config.nodes_settings.blacklist)
) {
client.config.nodes_settings.blacklist = [
client.config.nodes_settings.blacklist,
];
}
if (client.config.nodes_settings.details) {
text = text + '\n**' + title.replace(':', ':**') + '\n' + description
} else {
text = text + '\n**' + title.replace(':', ':**')
}
} else {
blacklist = blacklist + 1
if (nodes.length - client.config.nodes_settings.blacklist.length < 1) text = '\nThere is no nodes to display'
}
if (client.guilds.cache.size < 1) {
return console.log(
chalk.cyan("[PteroStats] ") +
chalk.red("Error! This bot is not on any discord servers")
);
}
if (i + 1 === nodes.length) resolve()
})
} else if (nodes.length < 1) {
if (!messages) {
text = '\nThere is no nodes to display'
resolve()
} else {
if (messages.embeds.length > 0 && client.config.embed.title && messages.embeds[0].data.title === client.config.embed.title) {
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()
}
}
})
if (messages && messages.embeds.length < 1) {
messages.delete();
messages = null;
}
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.message.content) {
content = client.config.message.content;
}
if (client.config.panel_settings.status) {
let stats = '**Status:** ' + String(panel.status).replace('true', client.config.status.online).replace('false', client.config.status.offline) + '\n\n'
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.panel_settings.users) stats = stats + 'Users: ' + String(panel.total_users).replace('-1', '`Unknown`') + '\n'
if (client.config.panel_settings.servers) stats = stats + 'Servers: ' + String(panel.total_servers).replace('-1', '`Unknown`')
if (client.config.embed.description) {
desc = client.config.embed.description + "\n";
}
EmbedFields.push({ name: 'Panel Stats', value: stats })
}
if (client.config.embed.color) {
embed.setColor(client.config.embed.color);
}
if (client.config.embed.field.title && client.config.embed.field.description) 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)
if (client.config.embed.footer) {
embed.setFooter({ text: client.config.embed.footer });
}
const row = []
if (client.config.embed.thumbnail) {
embed.setThumbnail(client.config.embed.thumbnail);
}
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 (client.config.embed.image) {
embed.setImage(client.config.embed.image);
}
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!'))
})
}
panel.total_users = panel.total_users.toLocaleString();
panel.total_servers = panel.total_servers.toLocaleString();
if (nodes?.length >= 1) {
for (const data of nodes) {
if (!client.config.nodes_settings.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_settings.unit.toLowerCase()) {
case "tb":
description =
description +
"\nMemory : " +
memorySizeConverter(data.memory_min, "TB") +
" / " +
memorySizeConverter(data.memory_max, "TB") +
"\nDisk : " +
memorySizeConverter(data.disk_min, "TB") +
" / " +
memorySizeConverter(data.disk_max, "TB");
break;
case "gb":
description =
description +
"\nMemory : " +
memorySizeConverter(data.memory_min, "GB") +
" / " +
memorySizeConverter(data.memory_max, "GB") +
"\nDisk : " +
memorySizeConverter(data.disk_min, "GB") +
" / " +
memorySizeConverter(data.disk_max, "GB");
break;
case "percent":
description =
description +
"\nMemory : " +
percentageCalculator(data.memory_min, data.memory_max) +
"\nDisk : " +
percentageCalculator(data.disk_min, data.disk_max);
break;
default:
description =
description +
"\nMemory : " +
memorySizeConverter(data.memory_min, "MB") +
" / " +
memorySizeConverter(data.memory_max, "MB") +
"\nDisk : " +
memorySizeConverter(data.disk_min, "MB") +
" / " +
memorySizeConverter(data.disk_max, "MB");
}
if (client.config.nodes_settings.servers) {
description =
description + "\nServers : " + data.total_servers.toLocaleString();
}
if (client.config.nodes_settings.location) {
description = description + "\nLocation : " + data.location;
}
if (client.config.nodes_settings.allocations) {
description =
description +
"\nAllocations : " +
data.allocations.toLocaleString();
}
description = description + "\n```";
if (client.config.nodes_settings.details) {
text = text + "\n**" + title.replace(":", ":**") + "\n" + description;
} else {
text = text + "\n**" + title.replace(":", ":**");
}
} else {
blacklist = blacklist + 1;
if (nodes.length - client.config.nodes_settings.blacklist.length < 1) {
text = "\nThere is no nodes to display";
}
}
}
const format = time(
new Date(Date.now() + client.config.refresh * 1000 + BUFFER_MS),
"R"
);
embed.setDescription(
desc.replaceAll("{{time}}", format) +
"\n**Nodes Stats [" +
Math.floor(nodes.length - blacklist) +
"]**" +
text
);
const EmbedFields = [];
if (client.config.panel_settings.status) {
let stats =
"**Status:** " +
String(panel.status)
.replace("true", client.config.status.online)
.replace("false", client.config.status.offline) +
"\n\n";
if (client.config.panel_settings.users) {
stats =
stats +
"Users: " +
String(panel.total_users).replace("-1", "`Unknown`") +
"\n";
}
if (client.config.panel_settings.servers) {
stats =
stats +
"Servers: " +
String(panel.total_servers).replace("-1", "`Unknown`");
}
EmbedFields.push({ name: "Panel Stats", value: stats });
}
if (
client.config.embed.field.title &&
client.config.embed.field.description
) {
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.setFields(EmbedFields); //try it and see
}
const row = [];
if (client.config.button.enable) {
const button = new ActionRowBuilder();
if (client.config.button.btn1.label.length >= 1 && client.config.button.btn1.url.length >= 1) {
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 >= 1 && client.config.button.btn2.url.length >= 1) {
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 >= 1 && client.config.button.btn3.url.length >= 1) {
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 >= 1 && client.config.button.btn4.url.length >= 1) {
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 >= 1 && client.config.button.btn5.url.length >= 1) {
button.addComponents(
new ButtonBuilder()
.setLabel(client.config.button.btn5.label)
.setStyle(ButtonStyle.Link)
.setURL(client.config.button.btn5.url)
);
}
row.push(button);
}
try {
if (!messages) {
channel.send({
content: content,
embeds: [embed],
components: row,
files: files,
});
} else {
messages.edit({
content: content,
embeds: [embed],
components: row,
files: files,
});
}
} catch (error) {
console.log(error);
}
console.log(chalk.cyan("[PteroStats] ") + chalk.green("Stats posted!"));
} else {
if (!messages) {
text = "\nThere are no nodes to display.";
} else {
if (
messages?.embeds?.length > 0 &&
client.config.embed.title &&
messages?.embeds[0]?.data?.title === client.config.embed.title
) {
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
] || 0;
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
] || 0;
}
}
}
}
};

103
index.js
View File

@@ -1,75 +1,52 @@
const fs = require('fs');
const child = require('child_process');
const intigrityCheck = require("./modules/intigrityCheck");
function InstallPackages() {
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')
console.log('If the bot can\'t install the package please install it manually')
try {
child.execSync('npm i')
console.log('Install complete!, please run "node index" command again!')
process.exit()
} catch (err) {
console.log('Error! ', err)
console.log('Support Server: https://discord.gg/zv6maQRah3')
process.exit()
}
if(!intigrityCheck()){
return console.log("Intigrity check failed!");
}
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')) {
if (fs.existsSync('./node_modules/discord.js')) {
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 InstallPackages()
if (fs.existsSync('./node_modules/axios')) {
const check = require('./node_modules/axios/package.json')
if (Number(check.version.split('.')[1]) > 1) {
console.log('Invalid Axios Version!, Please use Axios 1.1.3')
process.exit()
}
} else InstallPackages()
if (fs.existsSync('./node_modules/chalk')) {
const check = require('./node_modules/chalk/package.json')
if (Number(check.version.split('.')[0]) > 4) {
console.log('Invalid Chalk Version!, Please use Chalk 4.1.2')
process.exit()
}
} else InstallPackages()
if (!fs.existsSync('./node_modules/js-yaml')) InstallPackages()
} else InstallPackages()
const chalk = require('chalk');
const yaml = require('js-yaml');
const { Client, GatewayIntentBits } = require('discord.js');
const fs = require("node:fs");
const chalk = require("chalk");
const yaml = require("js-yaml");
const { Client, GatewayIntentBits } = require("discord.js");
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.config = yaml.load(fs.readFileSync('./config.yml', 'utf8'));
client.config = yaml.load(fs.readFileSync("./config.yml", "utf8"));
if (client.config.panel.adminkey || client.config.resource || client.config.message.image) {
console.log(chalk.cyan('[PteroStats] ') + chalk.red('You are using old config file, please update your config file at ') + chalk.green('https://github.com/HirziDevs/PteroStats/blob/main/config.yml'))
process.exit()
}
if (client.config.token.startsWith('Put') || !client.config.token.length) {
console.log(chalk.cyan('[PteroStats] ') + chalk.red('Error! Invalid Discord Bot Token'))
process.exit()
if (
client.config.panel.adminkey ||
client.config.resource ||
client.config.message.image
) {
console.log(
chalk.cyan("[PteroStats] ") +
chalk.red(
"You are using old config file, please update your config file at "
) +
chalk.green(
"https://github.com/HirziDevs/PteroStats/blob/main/config.yml"
)
);
process.exit();
}
const eventFiles = fs.readdirSync('./events').filter(file => file.endsWith('.js'));
if (client.config.token.startsWith("Put") || !client.config.token.length) {
console.log(
chalk.cyan("[PteroStats] ") + chalk.red("Error! Invalid Discord Bot Token")
);
process.exit();
}
const eventFiles = fs
.readdirSync("./events")
.filter((file) => file.endsWith(".js"));
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));
}
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));
}
}
client.login(client.config.token);
client.login(client.config.token);

127
modules/intigrityCheck.js Normal file
View File

@@ -0,0 +1,127 @@
const fs = require("node:fs");
const child = require("node:child_process");
const path = require("node:path");
const REQUIRED_PACKAGES = [
{
name: "axios",
version: "1.4.0",
},
{
name: "axios-retry",
version: "3.5.1",
},
{
name: "chalk",
version: "4.1.2",
},
{
name: "discord.js",
version: "14.11.0",
},
{
name: "js-yaml",
version: "4.1.0",
},
];
const NODE_VERSION = 16;
function InstallPackages() {
console.log("Required nodejs packages not found!");
console.log("Please wait... starting to install all required node packages.");
console.log(
"If the bot can't install the packages please install them manually."
);
try {
let packagesList = "";
for (const package of REQUIRED_PACKAGES) {
packagesList += ` ${package.name}@${package.version}`;
}
child.execSync(`npm i${packagesList}`);
console.log('Install complete!, please run "node index" command again!');
process.exit();
} catch (err) {
console.log("Error! ", err);
console.log("Support Server: https://discord.gg/zv6maQRah3");
process.exit();
}
}
module.exports = () => {
if (Number(process.version.split(".")[0]) < NODE_VERSION) {
console.log(
`Unsupported NodeJS Version!, Please use NodeJS ${NODE_VERSION}.x or higher.`
);
process.exit();
}
const nodeModulesFolderPath = path.join(__dirname, "../", "node_modules");
if (fs.existsSync(nodeModulesFolderPath)) {
let success = false;
let errorMessage = "";
for (const package of REQUIRED_PACKAGES) {
const packageFilePath = path.join(
__dirname,
"../",
"node_modules",
package.name,
"package.json"
);
if (fs.existsSync(packageFilePath)) {
let packageFile = fs.readFileSync(packageFilePath, 'utf-8');
if (packageFile) {
packageFile = JSON.parse(packageFile);
if (
Number(packageFile.version.split(".")[1]) !==
Number(package.version.split(".")[1])
) {
console.log(
`Unsupported "${package.name}" version!.\nPlease delete your "node_modules" and "package-lock.json".\nAnd restart the bot.`
);
process.exit();
} else {
success = true;
continue;
}
} else {
success = false;
errorMessage = `Unknown package version- "${package.name}".`;
break;
}
} else {
success = false;
errorMessage = `Missing package- "${package.name}".`;
break;
}
}
if (!success) {
if (errorMessage) {
console.log(errorMessage);
}
InstallPackages();
}
} else {
InstallPackages();
}
return true;
};

View File

@@ -0,0 +1,44 @@
const SUPPORTED_TYPES = ["MB", "GB", "TB"];
module.exports = (value, type) => {
if (value && type) {
value = parseInt(value);
if (value > 0) {
if (SUPPORTED_TYPES.includes(type)) {
let result = "";
switch (type) {
case "MB":
result =
value.toFixed(2).toLocaleString().replace(".00", "") + " MB";
break;
case "GB":
result =
(value / 1024).toFixed(2).toLocaleString().replace(".00", "") +
" GB";
break;
case "TB":
result =
(value / (1024 * 1000))
.toFixed(2)
.toLocaleString()
.replace(".00", "") + " TB";
break;
default:
result =
value.toFixed(2).toLocaleString().replace(".00", "") + " MB";
break;
}
return result;
} else {
return "INVALID TYPE";
}
} else {
return "INVALID VALUE";
}
} else {
return "ERROR";
}
};

View File

@@ -0,0 +1,16 @@
module.exports = (used, total) => {
if (used && total) {
used = parseInt(used);
total = parseInt(total);
if (used >= 1 && total >= 1) {
let percentage = ((used / total) * 100).toFixed(2).toLocaleString().replace(".00", "") + " %";
return percentage;
} else {
return "ERROR";
}
} else {
return "ERROR";
}
};

View File

@@ -13,12 +13,13 @@
"start": "node index.js"
},
"dependencies": {
"axios": "1.1.3",
"chalk": "4.1.2",
"discord.js": "^14.7.1",
"axios": "^1.4.0",
"axios-retry": "^3.5.1",
"chalk": "^4.1.2",
"discord.js": "^14.11.0",
"js-yaml": "^4.1.0"
},
"engines": {
"node": ">=16.9.0"
}
}
}