modificando mensajes

This commit is contained in:
Daniel Fernandez Sotolongo
2025-09-27 12:31:54 -04:00
parent 514c655746
commit 89cae3d090
2 changed files with 255 additions and 252 deletions

View File

@ -10,6 +10,8 @@ services:
environment: environment:
- TZ=America/Havana - TZ=America/Havana
- PYTHONUNBUFFERED=1 - PYTHONUNBUFFERED=1
# Pasa el nombre del host al contenedor del notificador
- WATCHTOWER_NOTIFICATIONS_HOSTNAME=Servidor-Easypanel
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
depends_on: depends_on:

View File

@ -1,23 +1,24 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
#watchtower_telegram_notifier.py
""" """
Watchtower Telegram Notifier - Notificaciones personalizadas en español Watchtower Telegram Notifier - Notificaciones personalizadas en español
Monitorea los logs de Watchtower y envía notificaciones detalladas a Telegram Monitorea los logs de Watchtower y envía notificaciones detalladas a Telegram
""" """
import docker import docker
import requests import requests
import time import time
import re import re
import os
from datetime import datetime from datetime import datetime
from threading import Thread from threading import Thread
import logging import logging
# Configuración # Configuración
TELEGRAM_BOT_TOKEN = "7676713419:AAG-tfwzgrA9JaU5xNjvG5iBlFeZpz2ahiY" TELEGRAM_BOT_TOKEN = "7676713419:AAG-tfwzgrA9JaU5xNjvG5iBlFeZpz2ahiY"
TELEGRAM_CHAT_ID = "7940222048" TELEGRAM_CHAT_ID = "7940222048"
WATCHTOWER_CONTAINER_NAME = "watchtower" WATCHTOWER_CONTAINER_NAME = "watchtower"
HOSTNAME = "Servidor-Easypanel" # Obtener el nombre del host de una variable de entorno, con un valor por defecto
HOSTNAME = os.environ.get("WATCHTOWER_NOTIFICATIONS_HOSTNAME", "Servidor-Easypanel")
# Configurar logging # Configurar logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
@ -31,7 +32,7 @@ class WatchtowerTelegramNotifier:
self.scan_in_progress = False self.scan_in_progress = False
def send_telegram_message(self, message): def send_telegram_message(self, message):
"""Envía mensaje a Telegram""" """Envía mensaje a Telegram"""
try: try:
payload = { payload = {
'chat_id': TELEGRAM_CHAT_ID, 'chat_id': TELEGRAM_CHAT_ID,
@ -40,47 +41,47 @@ class WatchtowerTelegramNotifier:
} }
response = requests.post(self.telegram_url, data=payload, timeout=10) response = requests.post(self.telegram_url, data=payload, timeout=10)
if response.status_code == 200: if response.status_code == 200:
logger.info("✅ Mensaje enviado a Telegram exitosamente") logger.info(" Mensaje enviado a Telegram exitosamente")
return True return True
else: else:
logger.error(f"❌ Error enviando mensaje: {response.status_code}") logger.error(f" Error enviando mensaje: {response.status_code}")
return False return False
except Exception as e: except Exception as e:
logger.error(f"❌ Error conectando a Telegram: {e}") logger.error(f" Error conectando a Telegram: {e}")
return False return False
def format_startup_message(self): def format_startup_message(self):
"""Mensaje de inicio del sistema""" """Mensaje de inicio del sistema"""
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
message = f"""🔄 <b>WATCHTOWER INICIADO</b> message = f"""🔄 <b>WATCHTOWER INICIADO</b>
🏠 <b>Servidor:</b> {HOSTNAME} 🏠 <b>Servidor:</b> {HOSTNAME}
📅 <b>Fecha:</b> {now} 📅 <b>Fecha:</b> {now}
⚙️ <b>Estado:</b> Monitoreo activo ⚙️ <b>Estado:</b> Monitoreo activo
🕐 <b>Intervalo:</b> Cada 24 horas 🕐 <b>Intervalo:</b> Cada 24 horas
📋 <b>Contenedores monitoreados:</b>""" 📋 <b>Contenedores monitoreados:</b>"""
try: try:
containers = self.client.containers.list() containers = self.client.containers.list()
for container in containers: for container in containers:
if container.name != WATCHTOWER_CONTAINER_NAME: if container.name != WATCHTOWER_CONTAINER_NAME:
status_emoji = "🟢" if container.status == "running" else "🔴" status_emoji = "🟢" if container.status == "running" else "🔴"
message += f"\n{status_emoji} {container.name}" message += f"\n{status_emoji} {container.name}"
except Exception as e: except Exception as e:
logger.error(f"Error obteniendo contenedores: {e}") logger.error(f"Error obteniendo contenedores: {e}")
message += "\n\n✅ <b>Sistema listo para detectar actualizaciones</b>" message += "\n\n <b>Sistema listo para detectar actualizaciones</b>"
return message return message
def format_scan_start_message(self): def format_scan_start_message(self):
"""Mensaje cuando inicia un escaneo""" """Mensaje cuando inicia un escaneo"""
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return f"""🔍 <b>ESCANEO DE ACTUALIZACIONES INICIADO</b> return f"""🔍 <b>ESCANEO DE ACTUALIZACIONES INICIADO</b>
🏠 <b>Servidor:</b> {HOSTNAME} 🏠 <b>Servidor:</b> {HOSTNAME}
📅 <b>Fecha:</b> {now} 📅 <b>Fecha:</b> {now}
⏳ <b>Estado:</b> Verificando imágenes... <b>Estado:</b> Verificando imágenes...
<i>Buscando actualizaciones disponibles...</i>""" <i>Buscando actualizaciones disponibles...</i>"""
@ -89,47 +90,47 @@ class WatchtowerTelegramNotifier:
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
if updated_containers: if updated_containers:
message = f"""🎉 <b>ACTUALIZACIONES COMPLETADAS</b> message = f"""🎉 <b>ACTUALIZACIONES COMPLETADAS</b>
🏠 <b>Servidor:</b> {HOSTNAME} 🏠 <b>Servidor:</b> {HOSTNAME}
📅 <b>Fecha:</b> {now} 📅 <b>Fecha:</b> {now}
📦 <b>Contenedores verificados:</b> {len(checked_containers)} 📦 <b>Contenedores verificados:</b> {len(checked_containers)}
<b>📥 ACTUALIZACIONES REALIZADAS:</b>""" <b>📥 ACTUALIZACIONES REALIZADAS:</b>"""
for container_info in updated_containers: for container_info in updated_containers:
message += f"\n✅ <b>{container_info['name']}</b>" message += f"\n <b>{container_info['name']}</b>"
message += f"\n 📋 Imagen: <code>{container_info['image']}</code>" message += f"\n   📋 Imagen: <code>{container_info['image']}</code>"
if container_info.get('old_image'): if container_info.get('old_image'):
message += f"\n 🔄 Desde: <code>{container_info['old_image']}</code>" message += f"\n   🔄 Desde: <code>{container_info['old_image']}</code>"
unchanged = [c for c in checked_containers if c not in [u['name'] for u in updated_containers]] unchanged = [c for c in checked_containers if c not in [u['name'] for u in updated_containers]]
if unchanged: if unchanged:
message += f"\n\n<b>ℹ️ SIN CAMBIOS:</b>" message += f"\n\n<b> SIN CAMBIOS:</b>"
for container in unchanged: for container in unchanged:
message += f"\n🔘 {container}" message += f"\n🔘 {container}"
message += f"\n\n🎯 <b>Total actualizados:</b> {len(updated_containers)}" message += f"\n\n🎯 <b>Total actualizados:</b> {len(updated_containers)}"
message += "\n✨ <b>¡Todos los servicios están actualizados!</b>" message += "\n <b>¡Todos los servicios están actualizados!</b>"
else: else:
message = f"""ℹ️ <b>VERIFICACIÓN COMPLETADA</b> message = f""" <b>VERIFICACIÓN COMPLETADA</b>
🏠 <b>Servidor:</b> {HOSTNAME} 🏠 <b>Servidor:</b> {HOSTNAME}
📅 <b>Fecha:</b> {now} 📅 <b>Fecha:</b> {now}
📦 <b>Contenedores verificados:</b> {len(checked_containers)} 📦 <b>Contenedores verificados:</b> {len(checked_containers)}
<b>📋 ESTADO:</b>""" <b>📋 ESTADO:</b>"""
for container in checked_containers: for container in checked_containers:
message += f"\n🔘 <b>{container}</b> - Sin actualizaciones" message += f"\n🔘 <b>{container}</b> - Sin actualizaciones"
message += "\n\n✅ <b>Todos los contenedores están al día</b>" message += "\n\n <b>Todos los contenedores están al día</b>"
return message return message
def parse_watchtower_logs(self, log_line): def parse_watchtower_logs(self, log_line):
"""Analiza líneas de log de Watchtower""" """Analiza líneas de log de Watchtower"""
log_line = log_line.strip() log_line = log_line.strip()
# Detectar inicio de escaneo # Detectar inicio de escaneo
@ -156,7 +157,7 @@ class WatchtowerTelegramNotifier:
'image': 'Detectando...', 'image': 'Detectando...',
'updated': True 'updated': True
} }
logger.info(f"📦 Actualización detectada: {container_name}") logger.info(f"📦 Actualización detectada: {container_name}")
break break
# Detectar fin de proceso # Detectar fin de proceso
@ -166,13 +167,13 @@ class WatchtowerTelegramNotifier:
self.scan_in_progress = False self.scan_in_progress = False
def send_update_report(self): def send_update_report(self):
"""Envía el reporte final de actualizaciones""" """Envía el reporte final de actualizaciones"""
try: try:
# Obtener lista actual de contenedores # Obtener lista actual de contenedores
containers = self.client.containers.list(all=True) containers = self.client.containers.list(all=True)
container_names = [c.name for c in containers if c.name != WATCHTOWER_CONTAINER_NAME] container_names = [c.name for c in containers if c.name != WATCHTOWER_CONTAINER_NAME]
# Completar información de contenedores actualizados # Completar información de contenedores actualizados
updated_list = [] updated_list = []
for container_name, info in self.container_updates.items(): for container_name, info in self.container_updates.items():
try: try:
@ -188,16 +189,16 @@ class WatchtowerTelegramNotifier:
except Exception as e: except Exception as e:
logger.error(f"Error generando reporte: {e}") logger.error(f"Error generando reporte: {e}")
error_msg = f"❌ <b>Error generando reporte de actualizaciones</b>\n\n🏠 <b>Servidor:</b> {HOSTNAME}\n⚠️ <b>Error:</b> {str(e)}" error_msg = f" <b>Error generando reporte de actualizaciones</b>\n\n🏠 <b>Servidor:</b> {HOSTNAME}\n⚠️ <b>Error:</b> {str(e)}"
self.send_telegram_message(error_msg) self.send_telegram_message(error_msg)
def monitor_watchtower(self): def monitor_watchtower(self):
"""Monitorea logs de Watchtower en tiempo real""" """Monitorea logs de Watchtower en tiempo real"""
logger.info("🔍 Iniciando monitoreo de Watchtower...") logger.info("🔍 Iniciando monitoreo de Watchtower...")
try: try:
container = self.client.containers.get(WATCHTOWER_CONTAINER_NAME) container = self.client.containers.get(WATCHTOWER_CONTAINER_NAME)
logger.info(f"✅ Contenedor Watchtower encontrado: {container.id[:12]}") logger.info(f" Contenedor Watchtower encontrado: {container.id[:12]}")
# Enviar mensaje de inicio # Enviar mensaje de inicio
self.send_telegram_message(self.format_startup_message()) self.send_telegram_message(self.format_startup_message())
@ -214,38 +215,38 @@ class WatchtowerTelegramNotifier:
continue continue
except docker.errors.NotFound: except docker.errors.NotFound:
error_msg = f"❌ <b>ERROR: Contenedor Watchtower no encontrado</b>\n\n🏠 <b>Servidor:</b> {HOSTNAME}\n⚠️ <b>Nombre esperado:</b> {WATCHTOWER_CONTAINER_NAME}" error_msg = f" <b>ERROR: Contenedor Watchtower no encontrado</b>\n\n🏠 <b>Servidor:</b> {HOSTNAME}\n⚠️ <b>Nombre esperado:</b> {WATCHTOWER_CONTAINER_NAME}"
self.send_telegram_message(error_msg) self.send_telegram_message(error_msg)
logger.error("❌ Contenedor Watchtower no encontrado") logger.error(" Contenedor Watchtower no encontrado")
except Exception as e: except Exception as e:
error_msg = f"❌ <b>ERROR EN MONITOREO</b>\n\n🏠 <b>Servidor:</b> {HOSTNAME}\n⚠️ <b>Error:</b> {str(e)}" error_msg = f" <b>ERROR EN MONITOREO</b>\n\n🏠 <b>Servidor:</b> {HOSTNAME}\n⚠️ <b>Error:</b> {str(e)}"
self.send_telegram_message(error_msg) self.send_telegram_message(error_msg)
logger.error(f"❌ Error en monitoreo: {e}") logger.error(f" Error en monitoreo: {e}")
def main(): def main():
logger.info("🚀 Iniciando Watchtower Telegram Notifier...") logger.info("🚀 Iniciando Watchtower Telegram Notifier...")
notifier = WatchtowerTelegramNotifier() notifier = WatchtowerTelegramNotifier()
# Verificar conexión a Telegram # Verificar conexión a Telegram
test_message = f"🤖 <b>Bot de notificaciones iniciado</b>\n\n🏠 <b>Servidor:</b> {HOSTNAME}\n📅 <b>Fecha:</b> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n✅ <b>Conexión establecida correctamente</b>" test_message = f"🤖 <b>Bot de notificaciones iniciado</b>\n\n🏠 <b>Servidor:</b> {HOSTNAME}\n📅 <b>Fecha:</b> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n <b>Conexión establecida correctamente</b>"
if notifier.send_telegram_message(test_message): if notifier.send_telegram_message(test_message):
logger.info("✅ Conexión a Telegram verificada") logger.info(" Conexión a Telegram verificada")
else: else:
logger.error("❌ Error de conexión a Telegram") logger.error(" Error de conexión a Telegram")
return return
# Iniciar monitoreo # Iniciar monitoreo
try: try:
notifier.monitor_watchtower() notifier.monitor_watchtower()
except KeyboardInterrupt: except KeyboardInterrupt:
logger.info("🛑 Monitoreo interrumpido por el usuario") logger.info("🛑 Monitoreo interrumpido por el usuario")
farewell_msg = f"👋 <b>Monitoreo detenido</b>\n\n🏠 <b>Servidor:</b> {HOSTNAME}\n📅 <b>Fecha:</b> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n⚠️ <b>Bot desconectado</b>" farewell_msg = f"👋 <b>Monitoreo detenido</b>\n\n🏠 <b>Servidor:</b> {HOSTNAME}\n📅 <b>Fecha:</b> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n⚠️ <b>Bot desconectado</b>"
notifier.send_telegram_message(farewell_msg) notifier.send_telegram_message(farewell_msg)
except Exception as e: except Exception as e:
logger.error(f"❌ Error fatal: {e}") logger.error(f" Error fatal: {e}")
error_msg = f"💥 <b>ERROR FATAL EN BOT</b>\n\n🏠 <b>Servidor:</b> {HOSTNAME}\n⚠️ <b>Error:</b> {str(e)}\n\n🔄 <b>Reinicia el script</b>" error_msg = f"💥 <b>ERROR FATAL EN BOT</b>\n\n🏠 <b>Servidor:</b> {HOSTNAME}\n⚠️ <b>Error:</b> {str(e)}\n\n🔄 <b>Reinicia el script</b>"
notifier.send_telegram_message(error_msg) notifier.send_telegram_message(error_msg)
if __name__ == "__main__": if __name__ == "__main__":