diff --git a/docker-compose.yaml b/docker-compose.yaml
index c61c3f5..83f5802 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -10,6 +10,8 @@ services:
environment:
- TZ=America/Havana
- PYTHONUNBUFFERED=1
+ # Pasa el nombre del host al contenedor del notificador
+ - WATCHTOWER_NOTIFICATIONS_HOSTNAME=Servidor-Easypanel
volumes:
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
diff --git a/watchtower_telegram_notifier.py b/watchtower_telegram_notifier.py
index fe23a60..8134ca0 100644
--- a/watchtower_telegram_notifier.py
+++ b/watchtower_telegram_notifier.py
@@ -1,252 +1,253 @@
-#!/usr/bin/env python3
-#watchtower_telegram_notifier.py
-"""
-Watchtower Telegram Notifier - Notificaciones personalizadas en español
-Monitorea los logs de Watchtower y envÃa notificaciones detalladas a Telegram
-"""
-
-import docker
-import requests
-import time
-import re
-from datetime import datetime
-from threading import Thread
-import logging
-
-# Configuración
-TELEGRAM_BOT_TOKEN = "7676713419:AAG-tfwzgrA9JaU5xNjvG5iBlFeZpz2ahiY"
-TELEGRAM_CHAT_ID = "7940222048"
-WATCHTOWER_CONTAINER_NAME = "watchtower"
-HOSTNAME = "Servidor-Easypanel"
-
-# Configurar logging
-logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
-logger = logging.getLogger(__name__)
-
-class WatchtowerTelegramNotifier:
- def __init__(self):
- self.client = docker.from_env()
- self.telegram_url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
- self.container_updates = {}
- self.scan_in_progress = False
-
- def send_telegram_message(self, message):
- """EnvÃa mensaje a Telegram"""
- try:
- payload = {
- 'chat_id': TELEGRAM_CHAT_ID,
- 'text': message,
- 'parse_mode': 'HTML'
- }
- response = requests.post(self.telegram_url, data=payload, timeout=10)
- if response.status_code == 200:
- logger.info("✅ Mensaje enviado a Telegram exitosamente")
- return True
- else:
- logger.error(f"⌠Error enviando mensaje: {response.status_code}")
- return False
- except Exception as e:
- logger.error(f"⌠Error conectando a Telegram: {e}")
- return False
-
- def format_startup_message(self):
- """Mensaje de inicio del sistema"""
- now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- message = f"""🔄 WATCHTOWER INICIADO
-
-ðŸ Servidor: {HOSTNAME}
-📅 Fecha: {now}
-âš™ï¸ Estado: Monitoreo activo
-🕠Intervalo: Cada 24 horas
-
-📋 Contenedores monitoreados:"""
-
- try:
- containers = self.client.containers.list()
- for container in containers:
- if container.name != WATCHTOWER_CONTAINER_NAME:
- status_emoji = "🟢" if container.status == "running" else "🔴"
- message += f"\n{status_emoji} {container.name}"
- except Exception as e:
- logger.error(f"Error obteniendo contenedores: {e}")
-
- message += "\n\n✅ Sistema listo para detectar actualizaciones"
- return message
-
- def format_scan_start_message(self):
- """Mensaje cuando inicia un escaneo"""
- now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- return f"""🔠ESCANEO DE ACTUALIZACIONES INICIADO
-
-ðŸ Servidor: {HOSTNAME}
-📅 Fecha: {now}
-ⳠEstado: Verificando imágenes...
-
-Buscando actualizaciones disponibles..."""
-
- def format_update_report(self, updated_containers, checked_containers):
- """Formato del reporte final de actualizaciones"""
- now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
-
- if updated_containers:
- message = f"""🎉 ACTUALIZACIONES COMPLETADAS
-
-ðŸ Servidor: {HOSTNAME}
-📅 Fecha: {now}
-📦 Contenedores verificados: {len(checked_containers)}
-
-📥 ACTUALIZACIONES REALIZADAS:"""
-
- for container_info in updated_containers:
- message += f"\n✅ {container_info['name']}"
- message += f"\n 📋 Imagen: {container_info['image']}"
- if container_info.get('old_image'):
- message += f"\n 🔄 Desde: {container_info['old_image']}"
-
- unchanged = [c for c in checked_containers if c not in [u['name'] for u in updated_containers]]
- if unchanged:
- message += f"\n\nâ„¹ï¸ SIN CAMBIOS:"
- for container in unchanged:
- message += f"\n🔘 {container}"
-
- message += f"\n\n🎯 Total actualizados: {len(updated_containers)}"
- message += "\n✨ ¡Todos los servicios están actualizados!"
-
- else:
- message = f"""â„¹ï¸ VERIFICACIÓN COMPLETADA
-
-ðŸ Servidor: {HOSTNAME}
-📅 Fecha: {now}
-📦 Contenedores verificados: {len(checked_containers)}
-
-📋 ESTADO:"""
-
- for container in checked_containers:
- message += f"\n🔘 {container} - Sin actualizaciones"
-
- message += "\n\n✅ Todos los contenedores están al dÃa"
-
- return message
-
- def parse_watchtower_logs(self, log_line):
- """Analiza lÃneas de log de Watchtower"""
- log_line = log_line.strip()
-
- # Detectar inicio de escaneo
- if "Checking all containers" in log_line and not self.scan_in_progress:
- self.scan_in_progress = True
- self.container_updates.clear()
- self.send_telegram_message(self.format_scan_start_message())
- return
-
- # Detectar actualizaciones
- update_patterns = [
- r'Found new.*image for (.+)',
- r'Updating (.+?) with.*',
- r'Updated (.+?) \(.*\)'
- ]
-
- for pattern in update_patterns:
- match = re.search(pattern, log_line, re.IGNORECASE)
- if match:
- container_name = match.group(1)
- if container_name not in self.container_updates:
- self.container_updates[container_name] = {
- 'name': container_name,
- 'image': 'Detectando...',
- 'updated': True
- }
- logger.info(f"📦 Actualización detectada: {container_name}")
- break
-
- # Detectar fin de proceso
- if any(phrase in log_line.lower() for phrase in ["session done", "watchtower will check again", "sleeping"]):
- if self.scan_in_progress:
- self.send_update_report()
- self.scan_in_progress = False
-
- def send_update_report(self):
- """EnvÃa el reporte final de actualizaciones"""
- try:
- # Obtener lista actual de contenedores
- containers = self.client.containers.list(all=True)
- container_names = [c.name for c in containers if c.name != WATCHTOWER_CONTAINER_NAME]
-
- # Completar información de contenedores actualizados
- updated_list = []
- for container_name, info in self.container_updates.items():
- try:
- container = self.client.containers.get(container_name)
- info['image'] = container.image.tags[0] if container.image.tags else "Sin tag"
- except:
- info['image'] = "Imagen no encontrada"
- updated_list.append(info)
-
- # Enviar reporte
- report = self.format_update_report(updated_list, container_names)
- self.send_telegram_message(report)
-
- except Exception as e:
- logger.error(f"Error generando reporte: {e}")
- error_msg = f"⌠Error generando reporte de actualizaciones\n\nðŸ Servidor: {HOSTNAME}\nâš ï¸ Error: {str(e)}"
- self.send_telegram_message(error_msg)
-
- def monitor_watchtower(self):
- """Monitorea logs de Watchtower en tiempo real"""
- logger.info("🔠Iniciando monitoreo de Watchtower...")
-
- try:
- container = self.client.containers.get(WATCHTOWER_CONTAINER_NAME)
- logger.info(f"✅ Contenedor Watchtower encontrado: {container.id[:12]}")
-
- # Enviar mensaje de inicio
- self.send_telegram_message(self.format_startup_message())
-
- # Monitorear logs en tiempo real
- for log in container.logs(stream=True, follow=True, tail=10):
- try:
- log_line = log.decode('utf-8').strip()
- if log_line:
- logger.debug(f"Log: {log_line}")
- self.parse_watchtower_logs(log_line)
- except Exception as e:
- logger.error(f"Error procesando log: {e}")
- continue
-
- except docker.errors.NotFound:
- error_msg = f"⌠ERROR: Contenedor Watchtower no encontrado\n\nðŸ Servidor: {HOSTNAME}\nâš ï¸ Nombre esperado: {WATCHTOWER_CONTAINER_NAME}"
- self.send_telegram_message(error_msg)
- logger.error("⌠Contenedor Watchtower no encontrado")
- except Exception as e:
- error_msg = f"⌠ERROR EN MONITOREO\n\nðŸ Servidor: {HOSTNAME}\nâš ï¸ Error: {str(e)}"
- self.send_telegram_message(error_msg)
- logger.error(f"⌠Error en monitoreo: {e}")
-
-def main():
- logger.info("🚀 Iniciando Watchtower Telegram Notifier...")
-
- notifier = WatchtowerTelegramNotifier()
-
- # Verificar conexión a Telegram
- test_message = f"🤖 Bot de notificaciones iniciado\n\nðŸ Servidor: {HOSTNAME}\n📅 Fecha: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n✅ Conexión establecida correctamente"
-
- if notifier.send_telegram_message(test_message):
- logger.info("✅ Conexión a Telegram verificada")
- else:
- logger.error("⌠Error de conexión a Telegram")
- return
-
- # Iniciar monitoreo
- try:
- notifier.monitor_watchtower()
- except KeyboardInterrupt:
- logger.info("🛑 Monitoreo interrumpido por el usuario")
- farewell_msg = f"👋 Monitoreo detenido\n\nðŸ Servidor: {HOSTNAME}\n📅 Fecha: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\nâš ï¸ Bot desconectado"
- notifier.send_telegram_message(farewell_msg)
- except Exception as e:
- logger.error(f"⌠Error fatal: {e}")
- error_msg = f"💥 ERROR FATAL EN BOT\n\nðŸ Servidor: {HOSTNAME}\nâš ï¸ Error: {str(e)}\n\n🔄 Reinicia el script"
- notifier.send_telegram_message(error_msg)
-
-if __name__ == "__main__":
- main()
+#!/usr/bin/env python3
+"""
+Watchtower Telegram Notifier - Notificaciones personalizadas en español
+Monitorea los logs de Watchtower y envía notificaciones detalladas a Telegram
+"""
+
+import docker
+import requests
+import time
+import re
+import os
+from datetime import datetime
+from threading import Thread
+import logging
+
+# Configuración
+TELEGRAM_BOT_TOKEN = "7676713419:AAG-tfwzgrA9JaU5xNjvG5iBlFeZpz2ahiY"
+TELEGRAM_CHAT_ID = "7940222048"
+WATCHTOWER_CONTAINER_NAME = "watchtower"
+# 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
+logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
+logger = logging.getLogger(__name__)
+
+class WatchtowerTelegramNotifier:
+ def __init__(self):
+ self.client = docker.from_env()
+ self.telegram_url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
+ self.container_updates = {}
+ self.scan_in_progress = False
+
+ def send_telegram_message(self, message):
+ """Envía mensaje a Telegram"""
+ try:
+ payload = {
+ 'chat_id': TELEGRAM_CHAT_ID,
+ 'text': message,
+ 'parse_mode': 'HTML'
+ }
+ response = requests.post(self.telegram_url, data=payload, timeout=10)
+ if response.status_code == 200:
+ logger.info("✅ Mensaje enviado a Telegram exitosamente")
+ return True
+ else:
+ logger.error(f"❌ Error enviando mensaje: {response.status_code}")
+ return False
+ except Exception as e:
+ logger.error(f"❌ Error conectando a Telegram: {e}")
+ return False
+
+ def format_startup_message(self):
+ """Mensaje de inicio del sistema"""
+ now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ message = f"""🔄 WATCHTOWER INICIADO
+
+🏠 Servidor: {HOSTNAME}
+📅 Fecha: {now}
+⚙️ Estado: Monitoreo activo
+🕐 Intervalo: Cada 24 horas
+
+📋 Contenedores monitoreados:"""
+
+ try:
+ containers = self.client.containers.list()
+ for container in containers:
+ if container.name != WATCHTOWER_CONTAINER_NAME:
+ status_emoji = "🟢" if container.status == "running" else "🔴"
+ message += f"\n{status_emoji} {container.name}"
+ except Exception as e:
+ logger.error(f"Error obteniendo contenedores: {e}")
+
+ message += "\n\n✅ Sistema listo para detectar actualizaciones"
+ return message
+
+ def format_scan_start_message(self):
+ """Mensaje cuando inicia un escaneo"""
+ now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ return f"""🔍 ESCANEO DE ACTUALIZACIONES INICIADO
+
+🏠 Servidor: {HOSTNAME}
+📅 Fecha: {now}
+⏳ Estado: Verificando imágenes...
+
+Buscando actualizaciones disponibles..."""
+
+ def format_update_report(self, updated_containers, checked_containers):
+ """Formato del reporte final de actualizaciones"""
+ now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+
+ if updated_containers:
+ message = f"""🎉 ACTUALIZACIONES COMPLETADAS
+
+🏠 Servidor: {HOSTNAME}
+📅 Fecha: {now}
+📦 Contenedores verificados: {len(checked_containers)}
+
+📥 ACTUALIZACIONES REALIZADAS:"""
+
+ for container_info in updated_containers:
+ message += f"\n✅ {container_info['name']}"
+ message += f"\n 📋 Imagen: {container_info['image']}"
+ if container_info.get('old_image'):
+ message += f"\n 🔄 Desde: {container_info['old_image']}"
+
+ unchanged = [c for c in checked_containers if c not in [u['name'] for u in updated_containers]]
+ if unchanged:
+ message += f"\n\nℹ️ SIN CAMBIOS:"
+ for container in unchanged:
+ message += f"\n🔘 {container}"
+
+ message += f"\n\n🎯 Total actualizados: {len(updated_containers)}"
+ message += "\n✨ ¡Todos los servicios están actualizados!"
+
+ else:
+ message = f"""ℹ️ VERIFICACIÓN COMPLETADA
+
+🏠 Servidor: {HOSTNAME}
+📅 Fecha: {now}
+📦 Contenedores verificados: {len(checked_containers)}
+
+📋 ESTADO:"""
+
+ for container in checked_containers:
+ message += f"\n🔘 {container} - Sin actualizaciones"
+
+ message += "\n\n✅ Todos los contenedores están al día"
+
+ return message
+
+ def parse_watchtower_logs(self, log_line):
+ """Analiza líneas de log de Watchtower"""
+ log_line = log_line.strip()
+
+ # Detectar inicio de escaneo
+ if "Checking all containers" in log_line and not self.scan_in_progress:
+ self.scan_in_progress = True
+ self.container_updates.clear()
+ self.send_telegram_message(self.format_scan_start_message())
+ return
+
+ # Detectar actualizaciones
+ update_patterns = [
+ r'Found new.*image for (.+)',
+ r'Updating (.+?) with.*',
+ r'Updated (.+?) \(.*\)'
+ ]
+
+ for pattern in update_patterns:
+ match = re.search(pattern, log_line, re.IGNORECASE)
+ if match:
+ container_name = match.group(1)
+ if container_name not in self.container_updates:
+ self.container_updates[container_name] = {
+ 'name': container_name,
+ 'image': 'Detectando...',
+ 'updated': True
+ }
+ logger.info(f"📦 Actualización detectada: {container_name}")
+ break
+
+ # Detectar fin de proceso
+ if any(phrase in log_line.lower() for phrase in ["session done", "watchtower will check again", "sleeping"]):
+ if self.scan_in_progress:
+ self.send_update_report()
+ self.scan_in_progress = False
+
+ def send_update_report(self):
+ """Envía el reporte final de actualizaciones"""
+ try:
+ # Obtener lista actual de contenedores
+ containers = self.client.containers.list(all=True)
+ container_names = [c.name for c in containers if c.name != WATCHTOWER_CONTAINER_NAME]
+
+ # Completar información de contenedores actualizados
+ updated_list = []
+ for container_name, info in self.container_updates.items():
+ try:
+ container = self.client.containers.get(container_name)
+ info['image'] = container.image.tags[0] if container.image.tags else "Sin tag"
+ except:
+ info['image'] = "Imagen no encontrada"
+ updated_list.append(info)
+
+ # Enviar reporte
+ report = self.format_update_report(updated_list, container_names)
+ self.send_telegram_message(report)
+
+ except Exception as e:
+ logger.error(f"Error generando reporte: {e}")
+ error_msg = f"❌ Error generando reporte de actualizaciones\n\n🏠 Servidor: {HOSTNAME}\n⚠️ Error: {str(e)}"
+ self.send_telegram_message(error_msg)
+
+ def monitor_watchtower(self):
+ """Monitorea logs de Watchtower en tiempo real"""
+ logger.info("🔍 Iniciando monitoreo de Watchtower...")
+
+ try:
+ container = self.client.containers.get(WATCHTOWER_CONTAINER_NAME)
+ logger.info(f"✅ Contenedor Watchtower encontrado: {container.id[:12]}")
+
+ # Enviar mensaje de inicio
+ self.send_telegram_message(self.format_startup_message())
+
+ # Monitorear logs en tiempo real
+ for log in container.logs(stream=True, follow=True, tail=10):
+ try:
+ log_line = log.decode('utf-8').strip()
+ if log_line:
+ logger.debug(f"Log: {log_line}")
+ self.parse_watchtower_logs(log_line)
+ except Exception as e:
+ logger.error(f"Error procesando log: {e}")
+ continue
+
+ except docker.errors.NotFound:
+ error_msg = f"❌ ERROR: Contenedor Watchtower no encontrado\n\n🏠 Servidor: {HOSTNAME}\n⚠️ Nombre esperado: {WATCHTOWER_CONTAINER_NAME}"
+ self.send_telegram_message(error_msg)
+ logger.error("❌ Contenedor Watchtower no encontrado")
+ except Exception as e:
+ error_msg = f"❌ ERROR EN MONITOREO\n\n🏠 Servidor: {HOSTNAME}\n⚠️ Error: {str(e)}"
+ self.send_telegram_message(error_msg)
+ logger.error(f"❌ Error en monitoreo: {e}")
+
+def main():
+ logger.info("🚀 Iniciando Watchtower Telegram Notifier...")
+
+ notifier = WatchtowerTelegramNotifier()
+
+ # Verificar conexión a Telegram
+ test_message = f"🤖 Bot de notificaciones iniciado\n\n🏠 Servidor: {HOSTNAME}\n📅 Fecha: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n✅ Conexión establecida correctamente"
+
+ if notifier.send_telegram_message(test_message):
+ logger.info("✅ Conexión a Telegram verificada")
+ else:
+ logger.error("❌ Error de conexión a Telegram")
+ return
+
+ # Iniciar monitoreo
+ try:
+ notifier.monitor_watchtower()
+ except KeyboardInterrupt:
+ logger.info("🛑 Monitoreo interrumpido por el usuario")
+ farewell_msg = f"👋 Monitoreo detenido\n\n🏠 Servidor: {HOSTNAME}\n📅 Fecha: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n⚠️ Bot desconectado"
+ notifier.send_telegram_message(farewell_msg)
+ except Exception as e:
+ logger.error(f"❌ Error fatal: {e}")
+ error_msg = f"💥 ERROR FATAL EN BOT\n\n🏠 Servidor: {HOSTNAME}\n⚠️ Error: {str(e)}\n\n🔄 Reinicia el script"
+ notifier.send_telegram_message(error_msg)
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file