This commit is contained in:
root 2025-05-01 09:44:32 +02:00
commit e05db3ba4d
5 changed files with 313 additions and 42 deletions

3
.gitignore vendored
View file

@ -137,3 +137,6 @@ dist
# pm2 ecosystem file # pm2 ecosystem file
ecosystem.config.js ecosystem.config.js
# firebase service file
firebase-service-account.json

View file

@ -3,6 +3,19 @@ const ping = require("ping");
const pm2 = require("pm2"); const pm2 = require("pm2");
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const axios = require("axios");
const admin = require("firebase-admin");
// Initialize Firebase Admin SDK
try {
const serviceAccount = require("../../firebase-service-account.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
console.log("Firebase Admin SDK initialized successfully");
} catch (error) {
console.error("Error initializing Firebase Admin SDK:", error);
}
const router = express.Router(); const router = express.Router();
@ -30,6 +43,10 @@ function ensureLogDirectories() {
} }
} }
// Track previous states for notifications
let previousServersStatus = {};
let previousPM2Status = {};
let serversStatus = {}; let serversStatus = {};
REMOTE_SERVERS.forEach(server => { REMOTE_SERVERS.forEach(server => {
serversStatus[server.name] = { serversStatus[server.name] = {
@ -37,11 +54,41 @@ REMOTE_SERVERS.forEach(server => {
lastChecked: null, lastChecked: null,
responseTime: null, responseTime: null,
}; };
// Initialize previous status
previousServersStatus[server.name] = false;
}); });
// Add PM2 services status object // Add PM2 services status object
let pm2ServicesStatus = {}; let pm2ServicesStatus = {};
// Function to send FCM notification
async function sendFCMNotification(message, topic) {
try {
if (!admin.apps.length) {
console.warn("Firebase Admin not initialized, skipping notification");
return;
}
// Create the message object according to Firebase Admin SDK format
const fcmMessage = {
topic: topic,
notification: {
title: 'Server Status Alert',
body: message
},
data: {
type: 'server_status',
timestamp: Date.now().toString()
}
};
await admin.messaging().send(fcmMessage);
console.log(`Notification sent: ${message}`);
} catch (error) {
console.error('Error sending notification:', error);
}
}
async function checkServers() { async function checkServers() {
try { try {
ensureLogDirectories(); ensureLogDirectories();
@ -51,13 +98,37 @@ async function checkServers() {
const res = await ping.promise.probe(server.host, { const res = await ping.promise.probe(server.host, {
timeout: 4, // Set a timeout of 4 seconds timeout: 4, // Set a timeout of 4 seconds
}); });
serversStatus[server.name].online = res.alive;
// Get previous status before updating
const wasOnline = previousServersStatus[server.name];
const isNowOnline = res.alive;
// Update status
serversStatus[server.name].online = isNowOnline;
serversStatus[server.name].responseTime = res.time; serversStatus[server.name].responseTime = res.time;
// Send notifications for status changes
if (wasOnline === false && isNowOnline) {
await sendFCMNotification(`Server ${server.name} is back online`, 'service_online');
} else if (wasOnline === true && !isNowOnline) {
await sendFCMNotification(`Server ${server.name} is offline`, 'service_offline');
}
// Update previous status
previousServersStatus[server.name] = isNowOnline;
} catch (error) { } catch (error) {
console.error(`Error pinging ${server.host}:`, error); console.error(`Error pinging ${server.host}:`, error);
serversStatus[server.name].online = false; serversStatus[server.name].online = false;
serversStatus[server.name].responseTime = null; serversStatus[server.name].responseTime = null;
// Check if status changed from online to offline
if (previousServersStatus[server.name] === true) {
await sendFCMNotification(`Server ${server.name} is unreachable`, 'service_offline');
previousServersStatus[server.name] = false;
}
} }
serversStatus[server.name].lastChecked = new Date().toISOString(); serversStatus[server.name].lastChecked = new Date().toISOString();
// Log server status to the appropriate folder // Log server status to the appropriate folder
@ -85,47 +156,73 @@ async function checkServers() {
} }
async function checkPM2Services() { async function checkPM2Services() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
pm2.connect(function(err) { pm2.connect(function(err) {
if (err) { if (err) {
console.error('Error connecting to PM2:', err); console.error('Error connecting to PM2:', err);
pm2.disconnect(); pm2.disconnect();
resolve(); resolve();
return; return;
} }
pm2.list((err, list) => { pm2.list(async (err, list) => {
if (err) { if (err) {
console.error('Error getting PM2 process list:', err); console.error('Error getting PM2 process list:', err);
pm2.disconnect(); pm2.disconnect();
resolve(); resolve();
return; return;
} }
// Update PM2 services status try {
list.forEach(process => { // Process each PM2 service sequentially with proper async handling
// Calculate uptime correctly - pm_uptime is a timestamp, not a duration for (const process of list) {
const uptimeMs = process.pm2_env.pm_uptime ? const uptimeMs = process.pm2_env.pm_uptime ?
Date.now() - process.pm2_env.pm_uptime : Date.now() - process.pm2_env.pm_uptime :
null; null;
pm2ServicesStatus[process.name] = { const processName = process.name;
name: process.name, const isNowOnline = process.pm2_env.status === 'online';
id: process.pm_id,
status: process.pm2_env.status,
cpu: process.monit ? process.monit.cpu : null,
memory: process.monit ? process.monit.memory : null,
uptime: uptimeMs, // Store the uptime in milliseconds
restarts: process.pm2_env.restart_time,
lastChecked: new Date().toISOString()
};
});
pm2.disconnect(); // Check if we've seen this process before
resolve(); if (previousPM2Status[processName] === undefined) {
}); // First time seeing this process - initialize and don't send notification
}); previousPM2Status[processName] = isNowOnline;
}); console.log(`Initializing PM2 service status for ${processName}: ${isNowOnline ? 'online' : 'offline'}`);
}
// Check if status changed
else if (previousPM2Status[processName] === false && isNowOnline) {
await sendFCMNotification(`PM2 service ${processName} is back online`, 'service_online');
console.log(`PM2 service ${processName} changed from offline to online`);
}
else if (previousPM2Status[processName] === true && !isNowOnline) {
await sendFCMNotification(`PM2 service ${processName} is offline (status: ${process.pm2_env.status})`, 'service_offline');
console.log(`PM2 service ${processName} changed from online to ${process.pm2_env.status}`);
}
// Update previous status
previousPM2Status[processName] = isNowOnline;
// Update status object
pm2ServicesStatus[processName] = {
name: processName,
id: process.pm_id,
status: process.pm2_env.status,
cpu: process.monit ? process.monit.cpu : null,
memory: process.monit ? process.monit.memory : null,
uptime: uptimeMs,
restarts: process.pm2_env.restart_time,
lastChecked: new Date().toISOString()
};
}
} catch (error) {
console.error('Error processing PM2 services:', error);
}
pm2.disconnect();
resolve();
});
});
});
} }
async function checkAll() { async function checkAll() {

107
package-lock.json generated
View file

@ -15,13 +15,17 @@
"dotenv": "^16.5.0", "dotenv": "^16.5.0",
"express": "^4.21.2", "express": "^4.21.2",
"firebase-admin": "^13.3.0", "firebase-admin": "^13.3.0",
<<<<<<< HEAD
"googleapis": "^148.0.0", "googleapis": "^148.0.0",
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"nodejs": "^0.0.0", "nodejs": "^0.0.0",
"ping": "^0.4.4", "ping": "^0.4.4",
"pm2": "^6.0.5", "pm2": "^6.0.5",
"whois-json": "^2.0.4" "whois-json": "^2.0.4"
} }
}, },
<<<<<<< HEAD
"node_modules/@discordjs/builders": { "node_modules/@discordjs/builders": {
"version": "1.11.1", "version": "1.11.1",
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.11.1.tgz", "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.11.1.tgz",
@ -149,6 +153,8 @@
"url": "https://github.com/discordjs/discord.js?sponsor" "url": "https://github.com/discordjs/discord.js?sponsor"
} }
}, },
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/@fastify/busboy": { "node_modules/@fastify/busboy": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.1.1.tgz", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.1.1.tgz",
@ -884,6 +890,7 @@
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"optional": true "optional": true
}, },
<<<<<<< HEAD
"node_modules/@sapphire/async-queue": { "node_modules/@sapphire/async-queue": {
"version": "1.5.5", "version": "1.5.5",
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.5.tgz", "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.5.tgz",
@ -917,6 +924,8 @@
"npm": ">=7.0.0" "npm": ">=7.0.0"
} }
}, },
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/@tootallnate/once": { "node_modules/@tootallnate/once": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
@ -1019,9 +1028,15 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
<<<<<<< HEAD
"version": "22.15.2", "version": "22.15.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.2.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.2.tgz",
"integrity": "sha512-uKXqKN9beGoMdBfcaTY1ecwz6ctxuJAcUlwE55938g0ZJ8lRxwAZqRz2AJ4pzpt5dHdTPMB863UZ0ESiFUcP7A==", "integrity": "sha512-uKXqKN9beGoMdBfcaTY1ecwz6ctxuJAcUlwE55938g0ZJ8lRxwAZqRz2AJ4pzpt5dHdTPMB863UZ0ESiFUcP7A==",
=======
"version": "22.15.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz",
"integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==",
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"undici-types": "~6.21.0" "undici-types": "~6.21.0"
@ -1097,6 +1112,7 @@
"license": "MIT", "license": "MIT",
"optional": true "optional": true
}, },
<<<<<<< HEAD
"node_modules/@types/ws": { "node_modules/@types/ws": {
"version": "8.18.1", "version": "8.18.1",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
@ -1116,6 +1132,8 @@
"npm": ">=7.0.0" "npm": ">=7.0.0"
} }
}, },
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/abort-controller": { "node_modules/abort-controller": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@ -2061,7 +2079,12 @@
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
<<<<<<< HEAD
"license": "MIT" "license": "MIT"
=======
"license": "MIT",
"optional": true
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
}, },
"node_modules/fast-json-patch": { "node_modules/fast-json-patch": {
"version": "3.1.1", "version": "3.1.1",
@ -2173,6 +2196,7 @@
"@google-cloud/storage": "^7.14.0" "@google-cloud/storage": "^7.14.0"
} }
}, },
<<<<<<< HEAD
"node_modules/firebase-admin/node_modules/uuid": { "node_modules/firebase-admin/node_modules/uuid": {
"version": "11.1.0", "version": "11.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
@ -2186,6 +2210,8 @@
"uuid": "dist/esm/bin/uuid" "uuid": "dist/esm/bin/uuid"
} }
}, },
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/follow-redirects": { "node_modules/follow-redirects": {
"version": "1.15.9", "version": "1.15.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
@ -2280,6 +2306,22 @@
"node": ">=14" "node": ">=14"
} }
}, },
<<<<<<< HEAD
=======
"node_modules/gaxios/node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist/bin/uuid"
}
},
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/gcp-metadata": { "node_modules/gcp-metadata": {
"version": "6.1.1", "version": "6.1.1",
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz",
@ -2440,6 +2482,23 @@
"node": ">=14" "node": ">=14"
} }
}, },
<<<<<<< HEAD
=======
"node_modules/google-gax/node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"optional": true,
"bin": {
"uuid": "dist/bin/uuid"
}
},
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/google-logging-utils": { "node_modules/google-logging-utils": {
"version": "0.0.2", "version": "0.0.2",
"resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz", "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz",
@ -2449,6 +2508,7 @@
"node": ">=14" "node": ">=14"
} }
}, },
<<<<<<< HEAD
"node_modules/googleapis": { "node_modules/googleapis": {
"version": "148.0.0", "version": "148.0.0",
"resolved": "https://registry.npmjs.org/googleapis/-/googleapis-148.0.0.tgz", "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-148.0.0.tgz",
@ -2479,6 +2539,8 @@
"node": ">=14.0.0" "node": ">=14.0.0"
} }
}, },
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/gopd": { "node_modules/gopd": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@ -3038,12 +3100,15 @@
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
"license": "MIT" "license": "MIT"
}, },
<<<<<<< HEAD
"node_modules/lodash.snakecase": { "node_modules/lodash.snakecase": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
"integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==",
"license": "MIT" "license": "MIT"
}, },
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/long": { "node_modules/long": {
"version": "5.3.2", "version": "5.3.2",
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
@ -3097,12 +3162,15 @@
"node": ">=10" "node": ">=10"
} }
}, },
<<<<<<< HEAD
"node_modules/magic-bytes.js": { "node_modules/magic-bytes.js": {
"version": "1.12.1", "version": "1.12.1",
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.12.1.tgz", "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.12.1.tgz",
"integrity": "sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==", "integrity": "sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==",
"license": "MIT" "license": "MIT"
}, },
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/math-intrinsics": { "node_modules/math-intrinsics": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@ -4577,6 +4645,23 @@
"license": "MIT", "license": "MIT",
"optional": true "optional": true
}, },
<<<<<<< HEAD
=======
"node_modules/teeny-request/node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"optional": true,
"bin": {
"uuid": "dist/bin/uuid"
}
},
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/title-case": { "node_modules/title-case": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz", "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz",
@ -4613,12 +4698,15 @@
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"license": "MIT" "license": "MIT"
}, },
<<<<<<< HEAD
"node_modules/ts-mixer": { "node_modules/ts-mixer": {
"version": "6.0.4", "version": "6.0.4",
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz",
"integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==", "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==",
"license": "MIT" "license": "MIT"
}, },
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.8.1", "version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@ -4670,6 +4758,7 @@
"integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==",
"license": "MIT" "license": "MIT"
}, },
<<<<<<< HEAD
"node_modules/undici": { "node_modules/undici": {
"version": "6.21.1", "version": "6.21.1",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz",
@ -4679,6 +4768,8 @@
"node": ">=18.17" "node": ">=18.17"
} }
}, },
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/undici-types": { "node_modules/undici-types": {
"version": "6.21.0", "version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
@ -4708,12 +4799,15 @@
"upper-case": "^1.1.1" "upper-case": "^1.1.1"
} }
}, },
<<<<<<< HEAD
"node_modules/url-template": { "node_modules/url-template": {
"version": "2.0.8", "version": "2.0.8",
"resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
"integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==", "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==",
"license": "BSD" "license": "BSD"
}, },
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/util-deprecate": { "node_modules/util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -4730,16 +4824,26 @@
} }
}, },
"node_modules/uuid": { "node_modules/uuid": {
<<<<<<< HEAD
"version": "9.0.1", "version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
=======
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
"integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"funding": [ "funding": [
"https://github.com/sponsors/broofa", "https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan" "https://github.com/sponsors/ctavan"
], ],
"license": "MIT", "license": "MIT",
"bin": { "bin": {
<<<<<<< HEAD
"uuid": "dist/bin/uuid" "uuid": "dist/bin/uuid"
=======
"uuid": "dist/esm/bin/uuid"
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
} }
}, },
"node_modules/vary": { "node_modules/vary": {
@ -4867,6 +4971,7 @@
"license": "ISC", "license": "ISC",
"optional": true "optional": true
}, },
<<<<<<< HEAD
"node_modules/ws": { "node_modules/ws": {
"version": "8.18.1", "version": "8.18.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
@ -4888,6 +4993,8 @@
} }
} }
}, },
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"node_modules/y18n": { "node_modules/y18n": {
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",

View file

@ -26,7 +26,10 @@
"dotenv": "^16.5.0", "dotenv": "^16.5.0",
"express": "^4.21.2", "express": "^4.21.2",
"firebase-admin": "^13.3.0", "firebase-admin": "^13.3.0",
<<<<<<< HEAD
"googleapis": "^148.0.0", "googleapis": "^148.0.0",
=======
>>>>>>> 917b12bb273711b9117a93963c6ee0ff957376a8
"nodejs": "^0.0.0", "nodejs": "^0.0.0",
"ping": "^0.4.4", "ping": "^0.4.4",
"pm2": "^6.0.5", "pm2": "^6.0.5",

61
test-firebase.js Normal file
View file

@ -0,0 +1,61 @@
const admin = require('firebase-admin');
const path = require('path');
// Get path to service account file
const serviceAccountPath = path.join(__dirname, 'firebase-service-account.json');
// Log the path to verify
console.log(`Loading Firebase service account from: ${serviceAccountPath}`);
// Initialize Firebase Admin SDK
try {
const serviceAccount = require(serviceAccountPath);
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
console.log("Firebase Admin SDK initialized successfully");
// Function to send FCM notification
async function sendTestNotification() {
try {
// Send to both topics to test both scenarios
const topics = ['service_online', 'service_offline'];
for (const topic of topics) {
// Correctly format the message for Firebase Cloud Messaging
const message = {
topic: topic,
notification: {
title: 'Test Notification',
body: `This is a test notification to the ${topic} topic`
},
data: {
type: 'test',
timestamp: Date.now().toString()
}
};
console.log(`Sending test notification to topic: ${topic}`);
// Use the send method instead of sendToTopic
const response = await admin.messaging().send(message);
console.log(`Successfully sent message to ${topic}:`, response);
}
console.log("All test notifications sent successfully!");
process.exit(0);
} catch (error) {
console.error('Error sending notification:', error);
process.exit(1);
}
}
// Execute the test
sendTestNotification();
} catch (error) {
console.error("Error initializing Firebase Admin SDK:", error);
console.error("Make sure firebase-service-account.json exists in the repository root");
process.exit(1);
}