From 0e5efbf6199347ad1ed8d416edf8ad90307d3069 Mon Sep 17 00:00:00 2001 From: MacRimi Date: Wed, 26 Mar 2025 18:54:30 +0100 Subject: [PATCH] Create telegram-notifier.sh --- scripts/telegram-notifier.sh | 714 +++++++++++++++++++++++++++++++++++ 1 file changed, 714 insertions(+) create mode 100644 scripts/telegram-notifier.sh diff --git a/scripts/telegram-notifier.sh b/scripts/telegram-notifier.sh new file mode 100644 index 0000000..85e97f6 --- /dev/null +++ b/scripts/telegram-notifier.sh @@ -0,0 +1,714 @@ +#!/bin/bash +#set -x + + +# Configuration ============================================ +REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main" +BASE_DIR="/usr/local/share/proxmenux" +UTILS_FILE="$BASE_DIR/utils.sh" +VENV_PATH="/opt/googletrans-env" + +if [[ -f "$UTILS_FILE" ]]; then + source "$UTILS_FILE" +fi +load_language +initialize_cache + + +CONFIG_FILE="/etc/proxmox-telegram.conf" +PID_DIR="/var/run/proxmox-telegram" + + +# Crear archivo de configuración si no existe +if [[ ! -f "$CONFIG_FILE" ]]; then + cat < "$CONFIG_FILE" +BOT_TOKEN="" +CHAT_ID="" +vm_start=0 +vm_shutdown=0 +vm_restart=0 +vm_fail=0 +update_available=0 +update_complete=0 +system_shutdown=0 +system_problem=0 +system_load_high=0 +kernel_panic=0 +disk_fail=0 +disk_full=0 +disk_io_error=0 +node_disconnect=0 +split_brain=0 +network_down=0 +network_saturation=0 +firewall_issue=0 +backup_complete=0 +backup_fail=0 +snapshot_complete=0 +snapshot_fail=0 +auth_fail=0 +ip_block=0 +user_permission_change=0 +cpu_high=0 +ram_high=0 +temp_high=0 +low_disk_space=0 +EOF + chmod 600 "$CONFIG_FILE" # Proteger el archivo de configuración +fi + +# Leer configuración actual +source "$CONFIG_FILE" + +# Función para enviar notificaciones a Telegram (sin logging) +send_notification() { + local message="$1" + + # Si el token o chat ID están vacíos → No enviar nada + if [[ -z "$BOT_TOKEN" || -z "$CHAT_ID" ]]; then + return 1 + fi + + # Enviar notificación a Telegram (sin output) + curl -s -X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage" \ + -d "chat_id=$CHAT_ID" \ + -d "text=$message" > /dev/null 2>&1 +} + +# Opciones para el menú +options=( + "VM y Contenedor|Inicio de VM/Contenedor|vm_start" + "VM y Contenedor|Apagado de VM/Contenedor|vm_shutdown" + "VM y Contenedor|Reinicio de VM/Contenedor|vm_restart" + "VM y Contenedor|Error en inicio de VM/Contenedor|vm_fail" + "Sistema|Nueva actualización disponible|update_available" + "Sistema|Actualización completada|update_complete" + "Sistema|Apagado del sistema|system_shutdown" + "Sistema|Problema con el sistema|system_problem" + "Sistema|Carga del sistema alta|system_load_high" + "Sistema|Kernel Panic|kernel_panic" + "Almacenamiento|Fallo de disco|disk_fail" + "Almacenamiento|Almacenamiento lleno|disk_full" + "Almacenamiento|Problemas de lectura/escritura|disk_io_error" + "Clúster|Nodo desconectado|node_disconnect" + "Clúster|Split-brain (conflicto en quorum)|split_brain" + "Red|Interfaz de red caída|network_down" + "Red|Saturación de red|network_saturation" + "Red|Problema con el firewall|firewall_issue" + "Backup y Snapshot|Backup completado|backup_complete" + "Backup y Snapshot|Backup fallido|backup_fail" + "Backup y Snapshot|Snapshot completado|snapshot_complete" + "Backup y Snapshot|Snapshot fallido|snapshot_fail" + "Seguridad|Intento de autenticación fallido|auth_fail" + "Seguridad|Bloqueos automáticos de IP|ip_block" + "Seguridad|Cambio de permisos de usuario|user_permission_change" + "Recursos|Uso alto de CPU|cpu_high" + "Recursos|Uso alto de RAM|ram_high" + "Recursos|Temperatura alta del sistema|temp_high" + "Recursos|Bajo espacio en disco|low_disk_space" +) + +# Función para obtener el nombre de una VM/CT a partir de su ID +get_vm_name() { + local vmid="$1" + local name="" + + if [[ -f "/etc/pve/qemu-server/$vmid.conf" ]]; then + name=$(grep -i "^name:" "/etc/pve/qemu-server/$vmid.conf" | cut -d ' ' -f2-) + elif [[ -f "/etc/pve/lxc/$vmid.conf" ]]; then + name=$(grep -i "^hostname:" "/etc/pve/lxc/$vmid.conf" | cut -d ' ' -f2-) + fi + + # Siempre devolver el nombre y el ID en el mismo formato + if [[ -n "$name" ]]; then + echo "$name ($vmid)" + else + echo "$vmid" + fi +} + +# Función para configurar notificaciones +configure_notifications() { + # Ordenar las opciones por categoría y descripción + IFS=$'\n' sorted_options=($(for option in "${options[@]}"; do + IFS='|' read -r category description var_name <<< "$option" + printf "%s|%s|%s\n" "$category" "$description" "$var_name" + done | sort -t'|' -k1,1 -k2,2)) + unset IFS + + # Crear un mapeo de índices a nombres de variables + declare -A index_to_var + index=1 + + # Preparar las opciones para `whiptail` + menu_items=() + for option in "${sorted_options[@]}"; do + IFS='|' read -r category description var_name <<< "$option" + + # Guardar el mapeo de índice a nombre de variable + index_to_var["$index"]="$var_name" + + # Formatear descripción con espacios para alinear la categoría a la derecha + formatted_item="$description" + current_length=${#formatted_item} + spaces_needed=$((50 - current_length)) + + for ((j = 0; j < spaces_needed; j++)); do + formatted_item+=" " + done + + formatted_item+="$category" + + # Marcar como ON u OFF según la configuración guardada + state="OFF" + [[ "$(eval echo \$$var_name)" -eq 1 ]] && state="ON" + + menu_items+=("$index" "$formatted_item" "$state") + ((index++)) + done + + # Mostrar menú `whiptail` + selected_indices=$(whiptail --title "$(translate "Configuración de Notificaciones a Telegram")" \ + --checklist --separate-output \ + "\n$(translate "Selecciona los eventos que deseas recibir:")\n" \ + 30 100 20 \ + "${menu_items[@]}" \ + 3>&1 1>&2 2>&3) + + local result=$? + + # Si se ha seleccionado alguna opción, actualizar configuración + if [[ $result -eq 0 ]]; then + # Hacer una copia de seguridad del archivo de configuración + cp "$CONFIG_FILE" "${CONFIG_FILE}.bak" 2>/dev/null + + # Establecer todas las opciones en OFF + for var_name in "${index_to_var[@]}"; do + sed -i "s/^$var_name=.*/$var_name=0/" "$CONFIG_FILE" + done + + # Activar las opciones seleccionadas + for selected_index in $selected_indices; do + var_name="${index_to_var[$selected_index]}" + sed -i "s/^$var_name=.*/$var_name=1/" "$CONFIG_FILE" + done + + # Recargar la configuración + source "$CONFIG_FILE" + + whiptail --title "$(translate "Éxito")" \ + --msgbox "$(translate "Configuración actualizada correctamente.")" 10 70 + fi +} + +# Función: captura eventos desde journalctl +capture_journal_events() { + # Usar un archivo para almacenar eventos ya procesados + local processed_events_file="$PID_DIR/processed_events" + + # Crear directorio si no existe + mkdir -p "$PID_DIR" 2>/dev/null + + # Crear el archivo si no existe + if [[ ! -f "$processed_events_file" ]]; then + touch "$processed_events_file" + fi + + # Monitorear continuamente el log + while true; do + # Usar tail para el archivo de tareas de Proxmox + tail -F /var/log/pve/tasks/index 2>/dev/null | while read -r line; do + # Crear un identificador único para este evento + event_id=$(echo "$line" | md5sum | cut -d' ' -f1) + + # Verificar si ya procesamos este evento + if grep -q "$event_id" "$processed_events_file" 2>/dev/null; then + continue + fi + + # Añadir el ID al archivo de eventos procesados + echo "$event_id" >> "$processed_events_file" + + # Limitar el tamaño del archivo de eventos procesados + tail -n 1000 "$processed_events_file" > "${processed_events_file}.tmp" 2>/dev/null && mv "${processed_events_file}.tmp" "$processed_events_file" 2>/dev/null + + # Variable para controlar si el evento ya fue procesado por algún patrón + local event_processed=false + + # ===== EVENTOS CRÍTICOS (INMEDIATOS) ===== + + # Error al iniciar VM (CRÍTICO) + if [[ "$line" =~ "Failed to start VM" ]] && [[ "$vm_fail" -eq 1 ]] && [[ "$event_processed" = false ]]; then + VM_ID=$(echo "$line" | grep -oP 'VM \K[0-9]+') + NAME=$(get_vm_name "$VM_ID") + send_notification "🚨 $(translate "CRÍTICO: Error al iniciar la VM:") $NAME" + event_processed=true + fi + + # Errores de I/O de disco (CRÍTICO) + if [[ "$disk_io_error" -eq 1 ]] && [[ "$event_processed" = false ]]; then + if [[ "$line" =~ "I/O error" || "$line" =~ "read error" || "$line" =~ "write error" || "$line" =~ "blk_update_request" || "$line" =~ "buffer I/O error" ]]; then + DISK=$(echo "$line" | grep -oE "/dev/[a-zA-Z0-9]+" || echo "desconocido") + send_notification "🚨 $(translate "CRÍTICO: Error de lectura/escritura en disco:") $DISK" + event_processed=true + fi + fi + + # Fallo de disco (CRÍTICO) + if [[ "$disk_fail" -eq 1 ]] && [[ "$line" =~ "disk failure" ]] && [[ "$event_processed" = false ]]; then + DISK=$(echo "$line" | grep -oE "/dev/[a-zA-Z0-9]+" || echo "desconocido") + send_notification "🚨 $(translate "CRÍTICO: Fallo de disco detectado:") $DISK" + event_processed=true + fi + + # Snapshot fallido (CRÍTICO) + if [[ "$line" =~ "snapshot" ]] && [[ "$snapshot_fail" -eq 1 ]] && [[ "$line" =~ "error" ]] && [[ "$event_processed" = false ]]; then + VM_ID=$(echo "$line" | grep -oP 'TASK \K[0-9]+' || echo "") + if [[ -n "$VM_ID" ]]; then + NAME=$(get_vm_name "$VM_ID") + send_notification "🚨 $(translate "CRÍTICO: Snapshot fallido para:") $NAME" + else + send_notification "🚨 $(translate "CRÍTICO: Snapshot fallido")" + fi + event_processed=true + fi + + # Backup fallido (CRÍTICO) + if [[ "$line" =~ "backup" ]] && [[ "$backup_fail" -eq 1 ]] && [[ "$line" =~ "error" ]] && [[ "$event_processed" = false ]]; then + VM_ID=$(echo "$line" | grep -oP 'TASK \K[0-9]+' || echo "") + if [[ -n "$VM_ID" ]]; then + NAME=$(get_vm_name "$VM_ID") + send_notification "🚨 $(translate "CRÍTICO: Backup fallido para:") $NAME" + else + send_notification "🚨 $(translate "CRÍTICO: Backup fallido")" + fi + event_processed=true + fi + + # Intento de autenticación fallido (CRÍTICO) + if [[ "$line" =~ "authentication failure" ]] && [[ "$auth_fail" -eq 1 ]] && [[ "$event_processed" = false ]]; then + USER=$(echo "$line" | grep -oP 'user=\K[^ ]+' || echo "desconocido") + IP=$(echo "$line" | grep -oP 'rhost=\K[^ ]+' || echo "desconocida") + send_notification "🚨 $(translate "CRÍTICO: Intento de autenticación fallido:") $USER desde $IP" + event_processed=true + fi + + # Problema con el firewall (CRÍTICO) + if [[ "$line" =~ "firewall" ]] && [[ "$firewall_issue" -eq 1 ]] && [[ "$line" =~ "error|block|reject" ]] && [[ "$event_processed" = false ]]; then + send_notification "🚨 $(translate "CRÍTICO: Problema con el firewall:") $line" + event_processed=true + fi + + # Interfaz de red caída (CRÍTICO) + if [[ "$line" =~ "network" ]] && [[ "$network_down" -eq 1 ]] && [[ "$line" =~ "down" ]] && [[ "$event_processed" = false ]]; then + IFACE=$(echo "$line" | grep -oP 'interface \K[^ ]+' || echo "desconocida") + send_notification "🚨 $(translate "CRÍTICO: Interfaz de red caída:") $IFACE" + event_processed=true + fi + + # Split-brain detectado (CRÍTICO) + if [[ "$line" =~ "Split-Brain" ]] && [[ "$split_brain" -eq 1 ]] && [[ "$event_processed" = false ]]; then + send_notification "🚨 $(translate "CRÍTICO: Split-brain detectado en el clúster")" + event_processed=true + fi + + # Nodo desconectado del clúster (CRÍTICO) + if [[ "$line" =~ "quorum" ]] && [[ "$node_disconnect" -eq 1 ]] && [[ "$line" =~ "lost" ]] && [[ "$event_processed" = false ]]; then + NODE=$(echo "$line" | grep -oP 'node \K[^ ]+' || echo "desconocido") + send_notification "🚨 $(translate "CRÍTICO: Nodo desconectado del clúster:") $NODE" + event_processed=true + fi + + # Kernel panic (CRÍTICO) + if [[ "$line" =~ "kernel panic" ]] && [[ "$kernel_panic" -eq 1 ]] && [[ "$event_processed" = false ]]; then + send_notification "🚨 $(translate "CRÍTICO: Kernel panic detectado")" + event_processed=true + fi + + # ===== EVENTOS NO CRÍTICOS (INMEDIATOS) ===== + + # Inicio de VM (NO CRÍTICO pero inmediato) + if [[ "$line" =~ "qmstart" ]] && [[ "$vm_start" -eq 1 ]] && [[ "$event_processed" = false ]]; then + VM_ID=$(echo "$line" | grep -oP 'qmstart:\K[0-9]+') + NAME=$(get_vm_name "$VM_ID") + send_notification "✅ $(translate "VM comenzó con éxito:") $NAME" + event_processed=true + fi + + # Apagado de VM (NO CRÍTICO pero inmediato) + if [[ "$line" =~ "qmstop" ]] && [[ "$vm_shutdown" -eq 1 ]] && [[ "$event_processed" = false ]]; then + VM_ID=$(echo "$line" | grep -oP 'qmstop:\K[0-9]+') + NAME=$(get_vm_name "$VM_ID") + send_notification "✅ $(translate "VM se detuvo con éxito:") $NAME" + event_processed=true + fi + + # Reinicio de VM (NO CRÍTICO pero inmediato) + if [[ "$line" =~ "qmreset" || "$line" =~ "qmreboot" ]] && [[ "$vm_restart" -eq 1 ]] && [[ "$event_processed" = false ]]; then + VM_ID=$(echo "$line" | grep -oP '(qmreset|qmreboot):\K[0-9]+') + NAME=$(get_vm_name "$VM_ID") + send_notification "✅ $(translate "VM reinició con éxito:") $NAME" + event_processed=true + fi + + # Snapshot completado (NO CRÍTICO pero inmediato) + if [[ "$line" =~ "snapshot" ]] && [[ "$snapshot_complete" -eq 1 ]] && [[ ! "$line" =~ "error" ]] && [[ "$event_processed" = false ]]; then + VM_ID=$(echo "$line" | grep -oP 'TASK \K[0-9]+' || echo "") + if [[ -n "$VM_ID" ]]; then + NAME=$(get_vm_name "$VM_ID") + send_notification "✅ $(translate "Snapshot completado para:") $NAME" + else + send_notification "✅ $(translate "Snapshot completado")" + fi + event_processed=true + fi + + # Backup completado (NO CRÍTICO pero inmediato) + if [[ "$line" =~ "backup" ]] && [[ "$backup_complete" -eq 1 ]] && [[ "$line" =~ "successful" ]] && [[ "$event_processed" = false ]]; then + VM_ID=$(echo "$line" | grep -oP 'TASK \K[0-9]+' || echo "") + if [[ -n "$VM_ID" ]]; then + NAME=$(get_vm_name "$VM_ID") + send_notification "✅ $(translate "Backup completado para:") $NAME" + else + send_notification "✅ $(translate "Backup completado")" + fi + event_processed=true + fi + + # Actualización completada (NO CRÍTICO pero inmediato) + if [[ "$line" =~ "update" ]] && [[ "$update_complete" -eq 1 ]] && [[ "$line" =~ "complete" ]] && [[ "$event_processed" = false ]]; then + send_notification "✅ $(translate "Actualización del sistema completada")" + event_processed=true + fi + done + + # Si llegamos aquí, es porque tail -F terminó inesperadamente + sleep 5 + done +} + +# Función: captura eventos directos del sistema +capture_direct_events() { + # Variables para controlar la frecuencia de las notificaciones + local last_load_notification=0 + local last_temp_notification=0 + local last_disk_space_notification=0 + local last_cpu_notification=0 + local last_ram_notification=0 + local last_update_notification=0 + + # Tiempo mínimo entre notificaciones repetitivas (en segundos) + local resource_interval=900 # 15 minutos para recursos + local update_interval=86400 # 24 horas para actualizaciones + + # Variables para eventos CRÍTICOS (sin intervalo) + local disk_full_detected=false + + while true; do + current_time=$(date +%s) + + # ===== EVENTOS CRÍTICOS (INMEDIATOS) ===== + + # Disco lleno (CRÍTICO - inmediato) + if [[ "$disk_full" -eq 1 ]]; then + full_disks=$(df -h | awk '$5 == "100%" {print $1 " (100% lleno)"}') + if [[ -n "$full_disks" && "$disk_full_detected" = false ]]; then + send_notification "🚨 $(translate "CRÍTICO: Almacenamiento completamente lleno:") $full_disks" + disk_full_detected=true + elif [[ -z "$full_disks" ]]; then + disk_full_detected=false + fi + fi + + # ===== EVENTOS NO CRÍTICOS (CON INTERVALO) ===== + + # Carga alta del sistema (NO CRÍTICO - con intervalo) + if [[ "$system_load_high" -eq 1 ]]; then + load=$(awk '{print $1}' /proc/loadavg) + if (( $(echo "$load > 5.00" | bc -l) )) && (( current_time - last_load_notification > resource_interval )); then + send_notification "⚠️ $(translate "Carga alta del sistema detectada:") $load" + last_load_notification=$current_time + fi + fi + + # Actualizaciones disponibles (NO CRÍTICO - con intervalo diario) + if [[ "$update_available" -eq 1 ]] && (( current_time - last_update_notification > update_interval )); then + if command -v apt-get &>/dev/null; then + apt-get update -qq &>/dev/null + updates=$(apt list --upgradable 2>/dev/null | grep -v "Listing..." | wc -l) + if [[ $updates -gt 0 ]]; then + send_notification "ℹ️ $(translate "Actualizaciones disponibles:") $updates" + last_update_notification=$current_time + fi + fi + fi + + # Espacio en disco bajo (NO CRÍTICO - con intervalo) + if [[ "$low_disk_space" -eq 1 ]] && (( current_time - last_disk_space_notification > resource_interval )); then + # Comprobar particiones con más del 90% pero menos del 100% de uso + low_space=$(df -h | awk '$5 ~ /9[0-9]%/ && $5 != "100%" {print $1 " (" $5 " lleno)"}') + if [[ -n "$low_space" ]]; then + send_notification "⚠️ $(translate "Espacio en disco bajo:") $low_space" + last_disk_space_notification=$current_time + fi + fi + + # Uso alto de CPU (NO CRÍTICO - con intervalo) + if [[ "$cpu_high" -eq 1 ]] && (( current_time - last_cpu_notification > resource_interval )); then + # Usar mpstat si está disponible, si no, usar top + if command -v mpstat &>/dev/null; then + cpu_usage=$(mpstat 1 1 | awk '/Average:/ {print 100 - $NF}') + else + cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}') + fi + + if (( $(echo "$cpu_usage > 90" | bc -l) )); then + send_notification "⚠️ $(translate "Uso alto de CPU:") $cpu_usage%" + last_cpu_notification=$current_time + fi + fi + + # Uso alto de RAM (NO CRÍTICO - con intervalo) + if [[ "$ram_high" -eq 1 ]] && (( current_time - last_ram_notification > resource_interval )); then + ram_usage=$(free | awk '/Mem:/ {printf "%.2f", $3/$2 * 100}') + if (( $(echo "$ram_usage > 90" | bc -l) )); then + send_notification "⚠️ $(translate "Uso alto de RAM:") $ram_usage%" + last_ram_notification=$current_time + fi + fi + + # Temperatura alta (NO CRÍTICO - con intervalo) + if [[ "$temp_high" -eq 1 ]] && (( current_time - last_temp_notification > resource_interval )); then + if command -v sensors &>/dev/null; then + # Intentar diferentes patrones para detectar la temperatura + temp=$(sensors | grep -E 'Package id 0:|Core 0:|CPU:' | head -1 | grep -oP '\+\d+\.\d+°C' | grep -oP '\d+\.\d+' || echo "0") + + if [[ -n "$temp" && "$temp" != "0" ]] && (( $(echo "$temp > 80" | bc -l) )); then + send_notification "⚠️ $(translate "Temperatura alta del sistema:") $temp°C" + last_temp_notification=$current_time + fi + fi + fi + + # Pausa entre comprobaciones + sleep 30 + done +} + +# Función para configurar Telegram +configure_telegram() { + # Cargar configuración existente (si existe) + [[ -f "$CONFIG_FILE" ]] && source "$CONFIG_FILE" + + # Solicitar BOT_TOKEN + BOT_TOKEN=$(whiptail --title "$(translate "Configuración de Telegram")" \ + --inputbox "$(translate "Introduce tu Token de Bot de Telegram:")" 10 70 "$BOT_TOKEN" 3>&1 1>&2 2>&3) + + if [[ $? -ne 0 ]]; then + return + fi + + # Solicitar CHAT_ID + CHAT_ID=$(whiptail --title "$(translate "Configuración de Telegram")" \ + --inputbox "$(translate "Introduce tu ID de Chat de Telegram:")" 10 70 "$CHAT_ID" 3>&1 1>&2 2>&3) + + if [[ $? -ne 0 ]]; then + return + fi + + # Guardar configuración en archivo + if [[ -n "$BOT_TOKEN" && -n "$CHAT_ID" ]]; then + # Hacer una copia de seguridad del archivo de configuración + cp "$CONFIG_FILE" "${CONFIG_FILE}.bak" 2>/dev/null + + # Verificar si las variables ya existen en el archivo + if grep -q "^BOT_TOKEN=" "$CONFIG_FILE"; then + sed -i "s/^BOT_TOKEN=.*/BOT_TOKEN=\"$BOT_TOKEN\"/" "$CONFIG_FILE" + else + echo "BOT_TOKEN=\"$BOT_TOKEN\"" >> "$CONFIG_FILE" + fi + + if grep -q "^CHAT_ID=" "$CONFIG_FILE"; then + sed -i "s/^CHAT_ID=.*/CHAT_ID=\"$CHAT_ID\"/" "$CONFIG_FILE" + else + echo "CHAT_ID=\"$CHAT_ID\"" >> "$CONFIG_FILE" + fi + + # Recargar la configuración + source "$CONFIG_FILE" + + # Probar la configuración inmediatamente + response=$(curl -s -X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage" \ + -d "chat_id=$CHAT_ID" \ + -d "text=$(translate "¡Telegram está funcionando correctamente!")") + + if [[ "$response" =~ "ok\":true" ]]; then + whiptail --title "$(translate "Éxito")" \ + --msgbox "$(translate "Configuración de Telegram válida. Las notificaciones serán enviadas.")" 10 70 + else + whiptail --title "$(translate "Error")" \ + --msgbox "$(translate "Configuración de Telegram inválida. Por favor, verifica el token y el ID de chat.")" 10 70 + fi + else + whiptail --title "$(translate "Error")" \ + --msgbox "$(translate "Configuración de Telegram incompleta. Por favor, proporciona tanto el token como el ID de chat.")" 10 70 + fi +} + + + + + + + +# Función para iniciar el servicio de notificaciones +start_notification_service() { + if [[ ! -f /etc/systemd/system/proxmox-telegram.service ]]; then + install_systemd_service + fi + + if systemctl is-active --quiet proxmox-telegram.service; then + whiptail --title "$(translate "Información")" \ + --msgbox "$(translate "El servicio de notificaciones ya está en ejecución.")" 10 70 + else + systemctl start proxmox-telegram.service + if systemctl is-active --quiet proxmox-telegram.service; then + whiptail --title "$(translate "Iniciado")" \ + --msgbox "$(translate "El servicio se ha iniciado correctamente.")" 10 70 + else + whiptail --title "$(translate "Error")" \ + --msgbox "$(translate "No se pudo iniciar el servicio de notificaciones.")" 10 70 + fi + fi +} + +# Función para detener el servicio +stop_notification_service() { + if [[ -f /etc/systemd/system/proxmox-telegram.service ]]; then + if systemctl is-active --quiet proxmox-telegram.service; then + systemctl stop proxmox-telegram.service + sleep 2 + fi + + if ! systemctl is-active --quiet proxmox-telegram.service; then + whiptail --title "$(translate "Detenido")" \ + --msgbox "$(translate "El servicio ha sido detenido correctamente.")" 10 70 + else + whiptail --title "$(translate "Error")" \ + --msgbox "$(translate "No se pudo detener el servicio de notificaciones.")" 10 70 + fi + else + whiptail --title "$(translate "Información")" \ + --msgbox "$(translate "El servicio de notificaciones no está instalado aún.")" 10 70 + fi +} + +# Función para verificar el estado del servicio +check_service_status() { + clear + if [[ -f /etc/systemd/system/proxmox-telegram.service ]]; then + systemctl status proxmox-telegram.service + else + echo "$(translate "El servicio no está instalado.")" + fi + echo + echo "$(translate "Pulsa Enter para volver al menú...")" + read -r +} + +# Función para eliminar el servicio systemd +remove_systemd_service() { + if [[ -f /etc/systemd/system/proxmox-telegram.service ]]; then + if systemctl is-active --quiet proxmox-telegram.service; then + systemctl stop proxmox-telegram.service + fi + systemctl disable proxmox-telegram.service + rm -f /etc/systemd/system/proxmox-telegram.service + systemctl daemon-reexec + whiptail --title "$(translate "Eliminado")" \ + --msgbox "$(translate "El servicio ha sido eliminado correctamente. Puedes reinstalarlo desde el menú si lo deseas.")" 10 70 + else + whiptail --title "$(translate "Información")" \ + --msgbox "$(translate "El servicio no existe, no se requiere eliminar nada.")" 10 70 + fi +} + +# Función para instalar el servicio como un servicio systemd +install_systemd_service() { + SCRIPT_PATH=$(readlink -f "$0") + mkdir -p "$PID_DIR" + cat > /etc/systemd/system/proxmox-telegram.service < /dev/null 2>&1 & echo $! > "$PID_DIR/journal.pid" + capture_direct_events > /dev/null 2>&1 & echo $! > "$PID_DIR/direct.pid" + echo $$ > "$PID_DIR/service.pid" +} + +stop_silent() { + kill $(cat "$PID_DIR/journal.pid" 2>/dev/null) 2>/dev/null + kill $(cat "$PID_DIR/direct.pid" 2>/dev/null) 2>/dev/null + kill $(cat "$PID_DIR/service.pid" 2>/dev/null) 2>/dev/null + rm -f "$PID_DIR"/*.pid +} + + + + + + +# Menú principal +main_menu() { + local extra_option="" + if [[ -f /etc/systemd/system/proxmox-telegram.service ]]; then + extra_option="8 \"$(translate \"Eliminar Servicio de Notificaciones\")\"" + fi + + while true; do + OPTION=$(whiptail --title "$(translate 'Configuración de Notificaciones de Proxmox')" \ + --menu "$(translate 'Elige una opción:')" 20 70 10 \ + "1" "$(translate 'Configurar Telegram')" \ + "2" "$(translate 'Configurar Notificaciones')" \ + "3" "$(translate 'Iniciar Servicio de Notificaciones')" \ + "4" "$(translate 'Detener Servicio de Notificaciones')" \ + "5" "$(translate 'Verificar Estado del Servicio')" \ + "7" "$(translate 'Salir')" \ + $extra_option 3>&1 1>&2 2>&3) + + + if [[ $? -ne 0 ]]; then exit 0; fi + + case "$OPTION" in + 1) configure_telegram ;; + 2) configure_notifications ;; + 3) start_notification_service ;; + 4) stop_notification_service ;; + 5) check_service_status ;; + 7) exit 0 ;; + 8) remove_systemd_service ;; + esac + done +} + +# Ejecutar el menú principal +main_menu