mirror of
https://github.com/marcogll/soul23_placeholder_site_server.git
synced 2026-01-13 21:35:18 +00:00
feat: Document new service monitoring and quote API, and implement quote API endpoint with enhanced health checks.
This commit is contained in:
82
server.js
82
server.js
@@ -1,44 +1,63 @@
|
||||
const express = require("express");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
const { exec } = require("child_process");
|
||||
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3001;
|
||||
const rootDir = path.join(__dirname);
|
||||
|
||||
// Serve static assets from the project root
|
||||
// --- Middleware ---
|
||||
// Sirve los archivos estáticos (HTML, CSS, JS) desde el directorio raíz del proyecto.
|
||||
// 'index.html' se sirve como el archivo por defecto.
|
||||
app.use(express.static(rootDir, { index: "index.html" }));
|
||||
|
||||
// Health checker should always return the raw script with text/plain
|
||||
|
||||
// --- Rutas de la API ---
|
||||
|
||||
/**
|
||||
* @route GET /healthchecker
|
||||
* @description Ejecuta un script de Python para un chequeo de salud avanzado.
|
||||
* Invoca el script `scripts/health_checker.py`, que monitorea múltiples servicios
|
||||
* y devuelve un reporte detallado en formato JSON.
|
||||
* @returns {object} Un objeto JSON con el estado de los servicios monitoreados.
|
||||
* @throws 500 - Si el script de Python falla o su salida no es un JSON válido.
|
||||
*/
|
||||
app.get("/healthchecker", (req, res) => {
|
||||
const pythonScriptPath = path.join(rootDir, "scripts", "health_checker.py");
|
||||
|
||||
exec(`python3 ${pythonScriptPath}`, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
console.error(`Error executing health_checker.py: ${stderr}`);
|
||||
return res.status(500).json({ error: "Failed to execute health checker" });
|
||||
console.error(`Error al ejecutar health_checker.py: ${stderr}`);
|
||||
return res.status(500).json({ error: "No se pudo ejecutar el chequeo de salud" });
|
||||
}
|
||||
try {
|
||||
const healthData = JSON.parse(stdout);
|
||||
res.status(200).json(healthData);
|
||||
} catch (parseErr) {
|
||||
console.error(`Error parsing health checker output: ${parseErr}`);
|
||||
res.status(500).json({ error: "Failed to parse health checker output" });
|
||||
console.error(`Error al parsear la salida del chequeo de salud: ${parseErr}`);
|
||||
res.status(500).json({ error: "La respuesta del chequeo de salud no es un JSON válido" });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Magic link para redirigir a la app de Telegram según plataforma
|
||||
/**
|
||||
* @route GET /telegram
|
||||
* @description Sirve una página HTML para la redirección a Telegram.
|
||||
* @returns {file} El archivo `htmls/telegram.html`.
|
||||
*/
|
||||
app.get("/telegram", (req, res) => {
|
||||
res.sendFile(path.join(rootDir, "htmls", "telegram.html"));
|
||||
});
|
||||
|
||||
// Standard health check endpoint for monitoring with VPS ping
|
||||
/**
|
||||
* @route GET /health
|
||||
* @description Realiza un chequeo de salud simple haciendo ping a una IP.
|
||||
* @returns {object} Un objeto JSON con el estado de la conectividad.
|
||||
*/
|
||||
app.get("/health", (req, res) => {
|
||||
const vpsIp = "31.97.41.188";
|
||||
// Ping with count 1 and timeout 1 second
|
||||
const vpsIp = "31.97.41.188"; // IP a verificar
|
||||
// Ejecuta un ping con un solo paquete y un timeout de 1 segundo.
|
||||
exec(`ping -c 1 -W 1 ${vpsIp}`, (error, stdout, stderr) => {
|
||||
const isAlive = !error;
|
||||
res.status(200).json({
|
||||
@@ -48,57 +67,70 @@ app.get("/health", (req, res) => {
|
||||
vps_ping: {
|
||||
target: vpsIp,
|
||||
alive: isAlive,
|
||||
output: isAlive ? "VPS Reachable" : "VPS Unreachable",
|
||||
output: isAlive ? "VPS Alcanzable" : "VPS Inalcanzable",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Endpoint to get a random phrase
|
||||
/**
|
||||
* @route GET /day-quote
|
||||
* @description Devuelve una frase aleatoria del archivo de citas.
|
||||
* @returns {object} Un objeto JSON con una única clave "phrase".
|
||||
* @throws 500 - Si no se puede leer o parsear el archivo `data/quotes.json`.
|
||||
*/
|
||||
app.get("/day-quote", (req, res) => {
|
||||
fs.readFile(path.join(rootDir, "data", "quotes.json"), "utf8", (err, data) => {
|
||||
if (err) {
|
||||
console.error("Error reading quotes file:", err);
|
||||
return res.status(500).json({ error: "Could not read quotes file" });
|
||||
console.error("Error al leer el archivo de frases:", err);
|
||||
return res.status(500).json({ error: "No se pudo leer el archivo de frases" });
|
||||
}
|
||||
try {
|
||||
const quotes = JSON.parse(data);
|
||||
const phrases = quotes.phrases;
|
||||
if (!phrases || phrases.length === 0) {
|
||||
return res.status(500).json({ error: "No phrases found" });
|
||||
return res.status(500).json({ error: "No se encontraron frases en el archivo" });
|
||||
}
|
||||
const randomPhrase = phrases[Math.floor(Math.random() * phrases.length)];
|
||||
res.status(200).json({ phrase: randomPhrase });
|
||||
} catch (parseErr) {
|
||||
console.error("Error parsing quotes file:", parseErr);
|
||||
return res.status(500).json({ error: "Could not parse quotes file" });
|
||||
console.error("Error al parsear el archivo de frases:", parseErr);
|
||||
return res.status(500).json({ error: "No se pudo parsear el archivo de frases" });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Endpoint to get the current time in multiple formats
|
||||
/**
|
||||
* @route GET /time-server
|
||||
* @description Proporciona la hora actual del servidor en diferentes formatos.
|
||||
* @returns {object} Un objeto JSON con la hora en formato ISO, Unix y legible.
|
||||
*/
|
||||
app.get("/time-server", (req, res) => {
|
||||
const now = new Date();
|
||||
const timezone = "America/Monterrey";
|
||||
|
||||
res.status(200).json({
|
||||
// Full UTC ISO 8601 string for machines
|
||||
utc_iso: now.toISOString(),
|
||||
// Unix timestamp in seconds for machines
|
||||
unixtime: Math.floor(now.getTime() / 1000),
|
||||
// Human-readable local time for debugging
|
||||
datetime_human: now.toLocaleString("en-US", { timeZone: timezone }),
|
||||
// Timezone identifier
|
||||
timezone: timezone,
|
||||
});
|
||||
});
|
||||
|
||||
// Fallback to index.html for other routes (optional)
|
||||
/**
|
||||
* @route GET *
|
||||
* @description Ruta "catch-all" que sirve la página principal.
|
||||
* Útil para Single Page Applications (SPAs) donde el enrutamiento se maneja
|
||||
* en el lado del cliente.
|
||||
* @returns {file} El archivo `index.html`.
|
||||
*/
|
||||
app.get("*", (req, res) => {
|
||||
res.sendFile(path.join(rootDir, "index.html"));
|
||||
});
|
||||
|
||||
|
||||
// --- Inicio del Servidor ---
|
||||
app.listen(port, () => {
|
||||
console.log(`Soul:23 server listening on port ${port}`);
|
||||
console.log(`Servidor Soul:23 escuchando en el puerto ${port}`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user