Introducción
Pingui Alert es un servicio de notificación ligero que te permite enviar alertas a tu cuenta de Telegram directamente desde tu código. Está diseñado para ser extremadamente simple de usar, sin requerir configuración en tu servidor.
Arquitectura del Sistema
Pingui Alert utiliza una arquitectura basada en colas para garantizar la entrega confiable de alertas:
API Request → Validación → Cola Redis → Worker → Telegram
Componentes Principales
- API REST: Recibe las alertas y las encola
- Cola Redis: Almacena alertas pendientes (máx 500 alertas)
- Worker de Cola: Procesa alertas a 1 msg/segundo (límite seguro de Telegram)
- Jobs Programados: Tareas automáticas de mantenimiento
- Bot de Telegram: Interfaz para gestionar integraciones
Jobs Automáticos
El sistema ejecuta tareas de mantenimiento programadas:
- Reset de Rate Limits (00:00 diario): Reinicia el contador de alertas diarias a 10 para todos los usuarios
- Backup de Base de Datos (03:00 diario): Crea backups automáticos de la base de datos SQLite
Configuración y Autenticación
Para comenzar a enviar alertas, necesitas obtener una API Key de nuestro bot de Telegram.
- Abre Telegram y busca @PinguiAlertBot (o tu instancia hosteada).
- Inicia un chat y envía el comando
/startpara registrarte. -
Envía el comando
/temporal_tokenpara obtener un token de acceso temporal. (Una vez que crees tu primera integración, obtendrás un nuevo token permanente) - Usa la API para crear tu primera integración y comenzar a enviar alertas.
MAX_ALERTS.
Los Mandamientos
Para mantener Pingui Alert útil y estable para todos, nos adherimos a un conjunto estricto de reglas. Sigue estos mandamientos para asegurar la mejor experiencia.
-
I. Uso Crítico Solamente
Solo lo usarás para alertas críticas que deban ser corregidas de inmediato. Diseña tu sistema para disparar estas alertas con moderación—solo una vez por tipo de incidente. -
II. Estándares de Producción
Si vas a enviar errores de tu api con nuestro bot, utiliza las mejores prácticas de producción. Asegúrate de que tu manejo de errores es robusto antes de enviarlo como alerta. -
III. Self-Host para Customización
Si requieres alguna customización (por simple que sea), utiliza la opción de self hosted. Puedes hostear Pingui Alert en cualquier lugar; sugerimos un VPS o servidor local por los pocos recursos que consume. -
IV. Alertas Accionables
Asegurarás que cada alerta sea accionable. Cada alerta debe incitar una respuesta específica e inmediata. -
V. Sin Fugas de Datos
No enviarás datos sensibles de usuarios (PII), identificadores o secretos en tus alertas. Mantén los mensajes seguros. -
VI. Fallar de Forma Segura
Implementarás manejo de errores para que una notificación de alerta fallida nunca bloquee tu aplicación principal. El fallo del servicio de alertas debe ser silencioso para tus usuarios finales.
Self-Hosting
Pingui Alert es completamente open source y puede ser auto-hosteado para control total sobre tu infraestructura de alertas.
Prerequisitos
- Node.js: v20 o superior
- pnpm: v9 o superior
- Redis: Para el sistema de colas (local o hosteado)
- Token de Bot de Telegram: Crear vía @BotFather
Configuración Rápida
git clone https://github.com/juanvidev1/pingui-alert
cd pingui-alert
pnpm install
# Configurar entorno
cp .env.example .env
# Editar .env con tus valores
# Ejecutar en desarrollo
pnpm run dev
# O compilar para producción
pnpm run build
pnpm run start
Variables de Entorno
# Requeridas
BOT_TOKEN=tu_token_de_telegram
JWT_SECRET=tu_jwt_secreto
REDIS_URL=redis://localhost:6379
# Opcionales
MAX_ALERTS=100 # Personalizar límite diario
MAX_QUEUE_SIZE=500
SEND_DELAY_MS=1000
Monitoreo y Logs
Pingui Alert proporciona capacidades completas de logging y monitoreo:
Archivos de Log
- logs/info.log: Eventos generales y alertas procesadas
- logs/error.log: Errores de aplicación y fallos de envío
- logs/jobs.log: Ejecución de jobs programados
Comandos de Monitoreo
# Ver alertas en tiempo real
tail -f logs/info.log | grep "Sending alert"
# Monitorear errores
tail -f logs/error.log
# Verificar estado de jobs
tail -f logs/jobs.log
# Tamaño de cola Redis
redis-cli LLEN pingui:queue:alerts
Métricas del Sistema
Rastrea el uso del sistema y rendimiento con métricas integradas:
Métricas Disponibles
- Total de Integraciones: Número de integraciones registradas
- Total de Alertas Enviadas: Alertas entregadas acumulativas
- Total de Errores: Intentos de alerta fallidos
- Última Actualización: Timestamp de frescura de métricas
Respuesta de Ejemplo
{
"totalIntegrations": 1234,
"totalSentAlerts": 45678,
"totalErrors": 23,
"metrics": [
{
"totalIntegrations": 1234,
"totalSentAlerts": 45678,
"totalErrors": 23,
"updatedAt": "2025-01-01T12:00:00Z"
}
]
}
Uso en Producción
Cuando uses Pingui Alert en entornos de producción, sigue estas mejores prácticas para asegurar un servicio óptimo para todos.
Configuración Recomendada para Producción
Para cargas de trabajo en producción con notificaciones frecuentes, recomendamos uno de estos enfoques:
- Hostea tu propia Instancia: Despliega tu propio servidor y bot de Pingui Alert. Esto te da control total sobre los límites de tasa y recursos dedicados.
- Solo Alertas Críticas: Si usas @PinguiAlertBot, implementa lógica de filtrado para enviar solo notificaciones de alta prioridad.
- Implementa Batching: Agrupa múltiples alertas no críticas en mensajes de resumen periódicos en lugar de enviar notificaciones individuales.
Referencia API
Aquí encontrarás toda la información que necesitas para integrar Pingui Alert en tus proyectos.
Enviar una Alerta
Envía una petición POST al endpoint /alert para entregar un mensaje.
/alert para entregar un mensaje.Enviar una Alerta
Envía una petición POST al endpoint /alert para entregar un mensaje.
Headers
| Header | Valor | Descripción |
|---|---|---|
Authorization |
Bearer <TU_API_KEY> |
Tu token JWT recibido del endpoint /createIntegration. |
Content-Type |
application/json |
Requerido. |
Body
{
"title": "Título de la alerta",
"message": "Tu mensaje aquí",
"chatId": "ID del chat de telegram a donde quieres recibir la alerta"
}
Ejemplo (cURL)
curl -X POST https://pingui-alert.dev/api/alert \
-H "Authorization: Bearer TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "Título de la alerta", "message": "Tu mensaje aquí", "chatId": "ID del chat de telegram en donde quieres recibir la alerta"}'
Crear Integración
Crea una nueva integración para un chat específico usando el token temporal. El scope es una cadena
abierta al criterio del usuario.
Crear Integración
Crea una nueva integración para un chat específico usando el token temporal. El scope es una cadena abierta al criterio del usuario.
Headers
| Header | Valor | Descripción |
|---|---|---|
Authorization |
Bearer <TOKEN_TEMPORAL> |
El token temporal recibido del comando /temporal_token. |
Content-Type |
application/json |
Requerido. |
Headers
| Header | Value | Description |
|---|---|---|
Authorization |
Bearer <TEMPORAL_TOKEN> |
The temporal token received from the /temporal_token command. |
Content-Type |
application/json |
Required. |
Body
{
"chatId": 123456789,
"scope": "prod"
}
Example (cURL)
curl -X POST https://pingui-alert.dev/api/createIntegration \
-H "Authorization: Bearer YOUR_TEMPORAL_TOKEN" \
-H "Content-Type: application/json" \
-d '{"chatId": 123456789, "scope": "prod"}'
Obtener Integración
Recupera detalles sobre una integración específica.
Obtener Integración
Recupera detalles sobre una integración específica.
Headers
| Header | Valor | Descripción |
|---|---|---|
Authorization |
Bearer <YOUR_API_KEY> |
Tu token permanente. |
Example (cURL)
curl -X GET https://pingui-alert.dev/api/integrations/123456789 \
-H "Authorization: Bearer TU_TOKEN"
Actualizar Límite de alertas
Actualiza la cantidad del límite de alertas (en el bot público no pueden ser más de 10)
Actualizar Límite de Tasa
Actualiza el límite de tasa para una integración específica.
Headers
| Header | Valor | Descripción |
|---|---|---|
Authorization |
Bearer <YOUR_API_KEY> |
Tu token permanente. |
Content-Type |
application/json |
Requerido. |
Body
{
"chatId": 123456789,
"rateLimit": 50
}
Example (cURL)
curl -X POST https://pingui-alert.dev/api/updateRateLimit \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"chatId": 123456789, "rateLimit": 50}'
Alertar Miembros
Envía una alerta a todos los miembros activos de tu integración.
Alertar Miembros
Envía una alerta a todos los miembros activos vinculados a tu integración.
Headers
| Header | Valor | Descripción |
|---|---|---|
Authorization |
Bearer <TU_API_KEY> |
Tu token JWT permanente. |
Content-Type |
application/json |
Requerido. |
Body
{
"chatId": 123456789,
"title": "Alerta de Despliegue",
"message": "El despliegue en producción falló."
}
Respuesta
{
"message": "Alert enqueued to members",
"succesNotifications": 3,
"totalMembers": 4
}
Ejemplo (cURL)
curl -X POST https://pingui-alert.dev/api/alert/members \
-H "Authorization: Bearer TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{"chatId": 123456789, "title": "Alerta de Despliegue", "message": "El despliegue en producción falló."}'
Obtener Miembros de Integración
Recupera todos los miembros vinculados a una integración.
Obtener Miembros de Integración
Headers
| Header | Valor | Descripción |
|---|---|---|
Authorization |
Bearer <TU_API_KEY> |
Tu token JWT permanente. |
Parámetros de Query
| Parámetro | Descripción |
|---|---|
chatId |
Tu Telegram chat ID (propietario). |
Ejemplo (cURL)
curl -X GET "https://pingui-alert.dev/api/integration-members?chatId=123456789" \
-H "Authorization: Bearer TU_API_KEY"
Cambiar Estado de Miembro
Activa o desactiva un miembro para que reciba alertas.
Cambiar Estado de Miembro
Headers
| Header | Valor | Descripción |
|---|---|---|
Authorization |
Bearer <TU_API_KEY> |
Tu token JWT permanente. |
Content-Type |
application/json |
Requerido. |
Body
{
"chatId": 987654321,
"integrationId": 1,
"activeMember": false
}
Ejemplo (cURL)
curl -X POST https://pingui-alert.dev/api/change-member-status \
-H "Authorization: Bearer TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{"chatId": 987654321, "integrationId": 1, "activeMember": false}'
Revocar Integración
Revoca (desactiva) una integración.
Revocar Integración
Revoca (desactiva) una integración existente.
Headers
| Header | Valor | Descripción |
|---|---|---|
Authorization |
Bearer <YOUR_API_KEY> |
Tu token permanente. |
Content-Type |
application/json |
Requerido. |
Body
{
"chatId": 123456789
}
Example (cURL)
curl -X POST https://pingui-alert.dev/api/revokeIntegration \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"chatId": 123456789}'
Comandos del Bot de Telegram
Toda interacción con Pingui Alert comienza desde el bot de Telegram. Aquí tienes la referencia completa de los comandos disponibles.
/start en el bot primero para que el sistema registre tu chat ID antes de que puedas recibir alertas.
Comandos Generales
/help
Devuelve un enlace a la documentación oficial.
/help
Devuelve un enlace a la documentación oficial.
/help
Respuesta: Un mensaje con el enlace a https://pingui-alert.dev/docs.
/get_me
Devuelve tu Telegram chat ID. Lo necesitarás para enviar alertas vía la API.
/get_me
Devuelve tu Telegram chat ID. Usarás este valor como el campo chatId en todas las peticiones a la API.
/get_me
Respuesta: Your user id is: 123456789
/temporal_token
Genera un token de corta duración (5 min) para crear tu primera integración.
/temporal_token
Genera un token JWT temporal válido por 5 minutos. Úsalo inmediatamente con el endpoint POST /createIntegration para obtener tu API key permanente.
/temporal_token
Respuesta: This is your temporal token, it will expire in 5 minutes: <token>
Comandos de Miembro
/join <code>
Unírete a una integración como miembro usando un código de invitación.
/join <code>
Se une a una integración existente como miembro. El código de invitación debe ser proporcionado por el propietario de la integración mediante /create_invite.
/start en el bot al menos una vez antes de usar este comando, de lo contrario el sistema no podrá registrarte.
/join ABC123
Respuesta: Joined successfully
Comandos Solo para Propietarios
Estos comandos requieren una integración activa y están restringidos al propietario de la integración.
/join_owner
Te añade a ti mismo (el propietario) como miembro de tu propia integración.
/join_owner
Registra al propietario de la integración como miembro para que también reciba las alertas enviadas a POST /alert/members.
/join_owner
/create_invite
Genera un código de invitación para compartir con personas que quieras añadir como miembros.
/create_invite
Crea un nuevo código de invitación para tu integración. Compártelo con quien quieras añadir como miembro — deben usar /join <code> para unirse.
/create_invite
Respuesta: The code for joining the integration alerts is ABC123
/get_members
Abre un panel para ver y gestionar los miembros de tu integración.
/get_members
Devuelve la lista de todos los miembros de tu integración y abre un panel web para activarlos o desactivarlos.
/get_members
Respuesta: Un mensaje con un botón inline para abrir el panel de gestión de miembros.
Paquete NPM
Si usas Node.js o TypeScript, te recomendamos usar nuestro paquete oficial en caso de que solo quieras enviar alertas usando el servidor Pingui Alert. El límite de tasa y la cuota son manejados por el servidor y aún necesitas usar el endpoint createIntegration para obtener tu API KEY.
Instalación
npm install pingui-alert
Uso
import { PinguiAlert } from 'pingui-alert-sdk';
const pinguiAlert = new PinguiAlert({
chatId: process.env.PINGUI_ALERT_CHAT_ID,
token: process.env.PINGUI_ALERT_API_KEY,
});
// Opcional: Validar el estado de la integración antes de enviar una alerta. Esto verifica si la integración está activa y tiene cuota.
const pinguiStatus = await pinguiAlert.validateStatus();
console.log('Estado de Pingui Alert:', pinguiStatus); // Ejemplo de respuesta exitosa: { success: true, remainingAlerts: 9 }
// Este método permite enviar una alerta. El primer parámetro es el mensaje que se enviará. El segundo parámetro es opcional y puede usarse para establecer un título para la alerta
await pinguiAlert.send('¡Backup de base de datos completado con éxito! ✅', 'Trabajo Completado');
Casos de Uso
Aquí tienes algunos ejemplos claros de cómo aplicar Pingui Alert en escenarios reales, cumpliendo estrictamente con los Mandamientos.
1. Monitoreo de Errores Críticos (Pasarela de Pago)
Escenario: El pago de un usuario falla debido a un error 500 del servidor.
Mandamientos Aplicados: I (Uso Crítico Solamente), V (Sin Fugas de Datos).
try {
await processPayment(orderId, amount);
} catch (error) {
// ❌ MAL: Enviando el stack completo o PII del usuario
// await client.send(`Payment failed for user ${user.email}: ${error.stack}`);
// ✅ BIEN: Accionable, específico, seguro
logger.error(error); // Loguear detalles localmente
await client.send(
`🚨 Crítico: Fallo en Pasarela de Pago\n` +
`Pasarela: Stripe\n` +
`OrderId: ${orderId}\n` +
`Acción: Revisar Estado de Stripe y Logs inmediatamente.`
);
}
2. Monitoreo de Recursos del Sistema
Escenario: El espacio en disco del servidor está peligrosamente bajo.
Mandamientos Aplicados: I (Uso Crítico), IV (Accionable).
#!/bin/bash
USAGE=$(df / | grep / | awk '{ print $5 }' | sed 's/%//g')
# Solo alertar si el uso es > 90% (Crítico)
if [ "$USAGE" -gt 90 ]; then
curl -X POST https://pingui-alert.dev/api/alert \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"alert": "💾 Crítico: Disco del Servidor\nUso al '"$USAGE"'%.\nLimpiar logs o expandir volumen AHORA."
}'
fi
3. Incidentes de Seguridad
Escenario: Múltiples intentos de login fallidos detectados desde una misma IP (Brute
Force).
Mandamientos Aplicados: I (Crítico), V (Sin PII).
if (failedAttempts > 10) {
// Lógica de bloqueo de IP...
// Alertar al Equipo de Seguridad
await client.send(
`🛡️ Alerta de Seguridad: Brute Force Detectado\n` +
`IP: ${req.ip}\n` +
`Intentos: ${failedAttempts}\n` +
`Acción: IP baneada temporalmente. Verificar origen del tráfico.`
);
}
4. Fallos en Tareas de Fondo
Escenario: Un backup nocturno falla.
Mandamientos Aplicados: IV (Accionable), VI (Fallar Seguro).
job.on('failed', async (err) => {
try {
await client.send(
`💥 Fallo en Job de Backup\n` +
`Job: nightly_db_backup\n` +
`Error: Connection timeout\n` +
`Acción: Reintentar backup manualmente vía panel de admin.`
);
} catch (alertError) {
// Fallar seguro - no crashear el worker si la alerta falla
console.error('Failed to send alert:', alertError);
}
});