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.

Configuración y Autenticación

Para comenzar a enviar alertas, necesitas obtener una API Key de nuestro bot de Telegram.

  1. Abre Telegram y busca @PinguiAlertBot (o tu instancia hosteada).
  2. Inicia un chat y envía el comando /start para registrarte.
  3. Envía el comando /temporal_token para obtener un token de acceso temporal. (Una vez que crees tu primera integración, obtendrás un nuevo token permanente)
  4. Usa la API para crear tu primera integración y comenzar a enviar alertas.
Nota: El servicio es completamente gratuito. El límite de 10 alertas por día ayuda a prevenir la degradación del servicio debido a los límites de la API de Telegram y las restricciones de capacidad del servidor en @PinguiAlertBot. Si tu instancia es self-hosted, puedes aumentar el límite configurando la variable de entorno 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.

📜 La Regla de Oro: Pingui Alert es para incidentes accionables y críticos. No es un servicio de logging.
  1. 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.
  2. 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.
  3. 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.
  4. IV. Alertas Accionables
    Asegurarás que cada alerta sea accionable. Cada alerta debe incitar una respuesta específica e inmediata.
  5. V. Sin Fugas de Datos
    No enviarás datos sensibles de usuarios (PII), identificadores o secretos en tus alertas. Mantén los mensajes seguros.
  6. 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.

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.

⚠️ Importante: Si usas la instancia hosteada de @PinguiAlertBot en producción, por favor resérvala exclusivamente para alertas críticas (ej: fallos de sistema, incidentes de seguridad, errores críticos). Esto ayuda a mantener la disponibilidad del servicio.

Configuración Recomendada

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.

Self-Hosting

Para hostear Pingui Alert:

git clone https://github.com/juanvidev1/pingui-alert
cd pingui-alert

# Configura tus variables de entorno
export BOT_TOKEN="tu_token_de_telegram"
export JWT_SECRET="tu_clave_secreta"
export MAX_ALERTS=100  # Personaliza tu límite diario

# Instala dependencias
pnpm install

# Corre el servidor
pnpm run dev

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.

Enviar una Alerta

Envía una petición POST al endpoint /alert para entregar un mensaje.

POST /alert

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://api.pingui.com/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.

POST /createIntegration

Headers

Header Valor Descripción
Authorization Bearer <TOKEN_TEMPORAL> El token temporal recibido del comando /temporal_token.
Content-Type application/json Requerido.
POST /createIntegration

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://api.pingui-alert.dev/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.

GET /integrations/:chatId

Headers

Header Valor Descripción
Authorization Bearer <YOUR_API_KEY> Tu token permanente.

Example (cURL)

curl -X GET https://api.pingui-alert.dev/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.

POST /updateRateLimit

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://api.pingui-alert.dev/updateRateLimit \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"chatId": 123456789, "rateLimit": 50}'

Revocar Integración

Revoca (desactiva) una integración.

POST /revokeIntegration

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://api.pingui-alert.dev/revokeIntegration \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"chatId": 123456789}'

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 { Pingui } from 'pingui-alert';

const client = new Pingui('TU_API_KEY');

await client.send('¡Backup de base de datos completado con éxito! ✅');

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).

payment.controller.ts
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).

health-check.sh
#!/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://api.pingui-alert.dev/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).

auth.middleware.ts
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).

backup-cron.ts
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);
  }
});