Status management by a service. Displays the ping of the bot and the API.

This commit is contained in:
2025-10-29 08:43:47 +01:00
parent 1689a34d75
commit dd8fc81097
6 changed files with 146 additions and 77 deletions

View File

@@ -14,6 +14,6 @@ export default {
InteractionContextType.PrivateChannel
),
async execute(interaction : ChatInputCommandInteraction) {
await interaction.reply('Pong !');
await interaction.reply(`🏓 Latency is ${Date.now() - interaction.createdTimestamp}ms. API Latency : ${interaction.client.ws.ping}ms`);
}
}

View File

@@ -1,5 +1,6 @@
import { ApplicationIntegrationType, ChatInputCommandInteraction, CommandInteraction, EmbedBuilder, InteractionContextType, SlashCommandBuilder } from "discord.js";
import ping from "ping";
import statusService from "../../services/status.service";
export default {
data: new SlashCommandBuilder()
@@ -16,81 +17,6 @@ export default {
),
async execute(interaction : ChatInputCommandInteraction) {
await interaction.deferReply();
const hosts : {host: string, name: string, alive: boolean, type: 'ping' | 'website'}[] = [
{
'host': 'https://protojx.com',
'name': 'Protojx Website 🌐',
alive: false,
type: 'website'
},
{
'host': 'https://manager.protojx.com',
'name': 'Espace Client 💻',
alive: false,
type: 'website'
},
{
host: '5.178.99.4',
name: 'RYZEN 01 🖥️',
alive: false,
type: 'ping'
},
{
host: '5.167.99.6',
name: 'RYZEN 02 🖥️',
alive: false,
type: 'ping'
},
{
host: '5.178.99.5',
name: 'RYZEN 03 🖥️',
alive: false,
type: 'ping'
},
{
host: '5.178.99.177',
name: 'XEON 01 (2697A V4) 🖥️',
alive: false,
type: 'ping'
},
{
host: '5.178.99.248',
name: 'XEON 02 (2687W V4) 🖥️',
alive: false,
type: 'ping'
},
{
host: '5.178.99.53',
name: 'RYZEN-GAME 01 👾',
alive: false,
type: 'ping'
},
{
host: '5.178.99.63',
name: 'XEON-GAME 01 👾',
alive: false,
type: 'ping'
}
]
async function fetchAlive(host: {host: string, name: string, alive: boolean, type: 'ping' | 'website'}) {
if(host.type === 'ping'){
let res = await ping.promise.probe(host.host, {timeout: 5});
host.alive = res.alive;
}else if(host.type === 'website'){
try {
const response = await fetch(host.host, { method: 'HEAD', signal: AbortSignal.timeout(3000) });
host.alive = response.ok;
} catch (error) {
host.alive = false;
}
}
return host;
}
const fetchPromises = hosts.map(host => fetchAlive(host));
const hosts_ = await Promise.all(fetchPromises);
const embed = new EmbedBuilder();
embed.setTitle('Status of protojx servers');
@@ -98,7 +24,7 @@ export default {
embed.setTimestamp(new Date());
embed.setThumbnail(interaction.client.user.avatarURL())
for(let host of hosts_){
for(let host of statusService.hosts){
embed.addFields({name: host.name, value: host.alive ? '<a:online:1432684754276323431> Online' : '<a:offline:1432684900175183882> Offline', inline: false});
}

View File

@@ -0,0 +1,112 @@
import ping from "ping";
import * as cron from 'cron';
export class StatusService {
public hosts : Host[] = [
{
'host': 'https://protojx.com',
'name': 'Protojx Website 🌐',
alive: false,
type: 'website'
},
{
'host': 'https://manager.protojx.com',
'name': 'Espace Client 💻',
alive: false,
type: 'website'
},
{
host: '5.178.99.4',
name: 'RYZEN 01 🖥️',
alive: false,
type: 'ping'
},
{
host: '5.167.99.6',
name: 'RYZEN 02 🖥️',
alive: false,
type: 'ping'
},
{
host: '5.178.99.5',
name: 'RYZEN 03 🖥️',
alive: false,
type: 'ping'
},
{
host: '5.178.99.177',
name: 'XEON 01 (2697A V4) 🖥️',
alive: false,
type: 'ping'
},
{
host: '5.178.99.248',
name: 'XEON 02 (2687W V4) 🖥️',
alive: false,
type: 'ping'
},
{
host: '5.178.99.53',
name: 'RYZEN-GAME 01 👾',
alive: false,
type: 'ping'
},
{
host: '5.178.99.63',
name: 'XEON-GAME 01 👾',
alive: false,
type: 'ping'
}
]
constructor() {
const cronJob = new cron.CronJob('*/2 * * * *', async () => {
try {
await this.fetch();
console.log('Status check completed at:', new Date().toISOString());
} catch (error) {
console.error('Error during status check:', error);
}
});
cronJob.start();
console.log('Status monitoring started - checking every 2 minutes');
}
async fetch(max = 1): Promise<Host[]> {
const hosts = this.hosts.filter((value, index) => index < max * 10 && index >= (max - 1) * 10);
async function fetchAlive(host: Host) {
if(host.type === 'ping'){
let res = await ping.promise.probe(host.host, {timeout: 5});
host.alive = res.alive;
}else if(host.type === 'website'){
try {
const response = await fetch(host.host, { method: 'HEAD', signal: AbortSignal.timeout(3000) });
host.alive = response.ok;
} catch (error) {
host.alive = false;
}
}
return host;
}
const fetchPromises = hosts.map(host => fetchAlive(host));
const updatedHosts = await Promise.all(fetchPromises);
updatedHosts.forEach((updatedHost, index) => {
const originalIndex = (max - 1) * 10 + index;
if (originalIndex < this.hosts.length) {
this.hosts[originalIndex] = updatedHost;
}
});
if(this.hosts.length > max * 10) {
await this.fetch(max + 1);
}
return this.hosts;
}
}
export default new StatusService();

1
src/type.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
type Host = { host: string, name: string, alive: boolean, type: 'ping' | 'website' };