#!/usr/bin/env python3 import subprocess import sys import os import signal import time from datetime import datetime LOG_DIR = "/app/data/logs" os.makedirs(LOG_DIR, exist_ok=True) def get_timestamp(): return datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_file = open(f"{LOG_DIR}/bots.log", "a") def log(msg): timestamp = get_timestamp() log_line = f"[{timestamp}] {msg}\n" log_file.write(log_line) log_file.flush() print(msg) print("πŸ€– Iniciando Bots de TraducciΓ³n...") print("=" * 40) processes = [] restart_counts = {} MAX_RESTARTS = 3 RESTART_COOLDOWN = 60 def start_process(cmd, name, delay_before=0): if delay_before > 0: log(f"⏳ Esperando {delay_before}s antes de iniciar {name}...") time.sleep(delay_before) log(f"βœ… Iniciando {name}...") log_path = f"{LOG_DIR}/{name.lower().replace(' ', '_')}.log" log_fd = open(log_path, "a") # stdout va al archivo Y a la consola del contenedor (Docker logs) p = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, preexec_fn=os.setsid ) # Hilo que redirige la salida del proceso al archivo + consola import threading def tee_output(proc, fd, label): for line in iter(proc.stdout.readline, b''): decoded = line.decode("utf-8", errors="replace") fd.write(decoded) fd.flush() print(f"[{label}] {decoded}", end="", flush=True) fd.close() t = threading.Thread(target=tee_output, args=(p, log_fd, name), daemon=True) t.start() processes.append((p, name)) return p p1 = start_process(["python3", "-X", "faulthandler", "-X", "importsys", "botdiscord/bot.py"], "Discord Bot", delay_before=10) p2 = start_process(["python3", "-X", "faulthandler", "-X", "importsys", "bottelegram/telegram_bot.py"], "Telegram Bot", delay_before=5) p3 = start_process(["python3", "-X", "faulthandler", "-X", "importsys", "panel/main.py"], "Panel Web", delay_before=0) print("=" * 40) print("πŸŽ‰ Todos los servicios funcionando!") print(f" πŸ“ Panel: http://localhost:8000") print(f" πŸ“ Logs: {LOG_DIR}") print("=" * 40) print("\nCtrl+C para detener") def signal_handler(sig, frame): log("πŸ›‘ Deteniendo...") for p, name in processes: try: os.killpg(os.getpgid(p.pid), signal.SIGTERM) log(f" βœ… {name} detenido") except: pass log_file.close() sys.exit(0) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) while True: for p, name in processes: if p.poll() is not None: if name not in restart_counts: restart_counts[name] = {"count": 0, "last_restart": 0} current_time = time.time() if current_time - restart_counts[name]["last_restart"] > RESTART_COOLDOWN: restart_counts[name]["count"] = 0 restart_counts[name]["count"] += 1 restart_counts[name]["last_restart"] = current_time if restart_counts[name]["count"] > MAX_RESTARTS: log(f"β›” {name} se detuvo {restart_counts[name]['count']} veces. Demasiados reinicios. Esperando {RESTART_COOLDOWN}s...") time.sleep(RESTART_COOLDOWN) restart_counts[name]["count"] = 0 continue log(f"⚠️ {name} se detuvo (intento {restart_counts[name]['count']}/{MAX_RESTARTS}), reiniciando...") delay = 5 if name != "Discord Bot" else 10 if name == "Discord Bot": p1 = start_process(["python3", "-X", "faulthandler", "-X", "importsys", "botdiscord/bot.py"], "Discord Bot", delay_before=delay) elif name == "Telegram Bot": p2 = start_process(["python3", "-X", "faulthandler", "-X", "importsys", "bottelegram/telegram_bot.py"], "Telegram Bot", delay_before=delay) elif name == "Panel Web": p3 = start_process(["python3", "-X", "faulthandler", "-X", "importsys", "panel/main.py"], "Panel Web", delay_before=0) time.sleep(5)