import os import time from datetime import datetime, timedelta from .config import EVIDENCIAS_DIR, MAX_REINTENTOS, MINUTOS_ANTICIPACION, WAIT_CHAT from .driver_session import ensure_session_active from .utils import asegurar_directorio, log_text from .whatsapp import abrir_chat, enviar_mensaje, obtener_nombre_chat_actual, validate_sent, verificar_ticks def construir_resultado(tipo, destino, mensaje, hora, minuto): return { "tipo": tipo, "destino": destino, "mensaje": mensaje, "hora_programada": f"{hora if hora is not None else ''}:{minuto if minuto is not None else ''}", "estado": "NO_INTENTADO", "intento_exitoso": None, "timestamp": None, "captura": None, "nota": "", } def obtener_hora_minuto(row): try: return int(float(row["hora"])), int(float(row["minuto"])) except Exception: return None, None def esperar_hora_programada(hora, minuto, destino): if hora is None or minuto is None: return ahora = datetime.now() hora_envio = datetime(ahora.year, ahora.month, ahora.day, hora, minuto) if hora_envio <= ahora + timedelta(minutes=MINUTOS_ANTICIPACION): hora_envio = ahora + timedelta(minutes=2) espera = (hora_envio - datetime.now()).total_seconds() if espera > 0: print(f"Esperando {int(espera)}s hasta {hora_envio.strftime('%H:%M')} para destino {destino}") time.sleep(espera) def guardar_captura_evidencia(driver, destino): nombre_chat = obtener_nombre_chat_actual(driver) asegurar_directorio(EVIDENCIAS_DIR) safe = "".join(c for c in nombre_chat if c.isalnum() or c in (" ", "_", "-")).strip().replace(" ", "_")[:40] if nombre_chat == "chat_desconocido": nombre_captura = os.path.join(EVIDENCIAS_DIR, f"envio_{destino[:12]}_{int(time.time())}.png") else: nombre_captura = os.path.join(EVIDENCIAS_DIR, f"envio_{safe}_{int(time.time())}.png") try: driver.save_screenshot(nombre_captura) return nombre_captura except Exception: return None def procesar_row(driver, row): tipo = str(row["tipo"]).strip().lower() destino = str(row["id_destino"]).strip() mensaje = str(row["mensaje"]) hora, minuto = obtener_hora_minuto(row) resultado = construir_resultado(tipo, destino, mensaje, hora, minuto) esperar_hora_programada(hora, minuto, destino) for intento in range(1, MAX_REINTENTOS + 1): print(f"Intento {intento}/{MAX_REINTENTOS} -> {tipo} '{destino}'") if not ensure_session_active(driver): resultado["estado"] = "ERROR_SESSION" resultado["nota"] = "No se pudo recuperar sesion" resultado["timestamp"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_text(f"{destino} | ERROR_SESSION") return resultado if not abrir_chat(driver, tipo, destino): resultado["estado"] = "NO_ENCONTRADO" resultado["nota"] = "No se encontro chat/grupo" resultado["timestamp"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_text(f"{destino} | NO_ENCONTRADO") return resultado try: time.sleep(WAIT_CHAT) if not enviar_mensaje(driver, mensaje): raise Exception("Error al ejecutar accion de envio") time.sleep(1) validacion = validate_sent(driver, mensaje, timeout=15) if validacion is True: resultado["estado"] = verificar_ticks(driver) resultado["nota"] = "ENVIADO_CONFIRMED" elif validacion is None: print("La sesion se perdio durante validacion. Intentando recuperacion...") if ensure_session_active(driver): print("Sesion recuperada. Reintentando envio.") time.sleep(2) continue resultado["estado"] = "ERROR_SESSION" resultado["nota"] = "Sesion perdida y no recuperada" resultado["timestamp"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_text(f"{destino} | ERROR_SESSION durante validacion") return resultado else: resultado["estado"] = "ENVIADO (SIN CONFIRMACION)" resultado["nota"] = "ENVIADO_SIN_CONFIRMACION" resultado["captura"] = guardar_captura_evidencia(driver, destino) resultado["intento_exitoso"] = intento resultado["timestamp"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_text(f"{destino} | {resultado['estado']} | intento {intento} | captura:{resultado['captura']}") print(f"Resultado para {destino}: {resultado['estado']}") return resultado except Exception as exc: print(f"Error en intento {intento} con {destino}: {exc}") log_text(f"{destino} | ERROR intento {intento}: {exc}") resultado["nota"] = str(exc) if intento < MAX_REINTENTOS: print("Reintentando en 3s...") time.sleep(3) resultado["estado"] = "FALLIDO" resultado["timestamp"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_text(f"{destino} | FALLIDO despues de {MAX_REINTENTOS} intentos") return resultado