feat: add whatsapp_modular_v3_6 - envio automatizado WhatsApp Web con busqueda por nombre, deteccion de ticks via msg-meta/SVG title, y validacion de selectores

This commit is contained in:
2026-06-25 14:25:59 -05:00
parent 3d42e4b84b
commit c1bcd57c4d
15 changed files with 1627 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
import time
from .dependencies import asegurar_dependencias
asegurar_dependencias()
import pandas as pd
from .config import MENSAJES_FILE, PAUSA_ENTRE_FILAS, RESULTADOS_FILE
from .driver_session import ensure_session_active, iniciar_driver
from .messages import cargar_mensajes
from .processor import procesar_row
from .utils import log_text
def actualizar_contadores(estado, nota, contadores):
if estado == "NO_ENCONTRADO":
contadores["no_encontrados"] += 1
elif estado in ["FALLIDO", "ERROR_ENVIO"]:
contadores["fallidos"] += 1
elif estado == "ERROR_SESSION":
contadores["error_sesion"] += 1
elif estado.startswith(("ENVIADO", "ENTREGADO", "LEIDO", "PENDIENTE")) or nota.upper().startswith("ENVIADO"):
contadores["exitos"] += 1
else:
contadores["fallidos"] += 1
def main():
print("Inicio del script v3.6 modular (reconexion + validacion de envio).")
try:
df = cargar_mensajes(MENSAJES_FILE)
except Exception as exc:
print(f"Error cargando archivo de mensajes: {exc}")
return
total = len(df)
print(f"{total} filas validas cargadas desde '{MENSAJES_FILE}'")
if total == 0:
print("No hay filas validas (tipo 'contacto' o 'grupo'). Saliendo.")
return
driver = iniciar_driver()
driver.get("https://web.whatsapp.com")
if not ensure_session_active(driver):
print("No se detecto sesion activa. Abre WhatsApp Web y escanea el QR en la ventana del navegador.")
try:
driver.quit()
except Exception:
pass
return
resultados = []
contadores = {"exitos": 0, "fallidos": 0, "no_encontrados": 0, "error_sesion": 0}
for idx, row in df.iterrows():
print(f"\n--- Procesando fila {idx + 1}/{total} ---")
resultado = procesar_row(driver, row)
resultados.append(resultado)
actualizar_contadores(resultado.get("estado", ""), resultado.get("nota", ""), contadores)
time.sleep(PAUSA_ENTRE_FILAS)
pct = (idx + 1) / total * 100
print(
f"Progreso: {idx + 1}/{total} ({pct:.1f}%) - "
f"Exitos: {contadores['exitos']} - "
f"Fallidos: {contadores['fallidos']} - "
f"No encontrados: {contadores['no_encontrados']} - "
f"ErrSes: {contadores['error_sesion']}"
)
pd.DataFrame(resultados).to_csv(RESULTADOS_FILE, index=False, encoding="utf-8-sig")
print(f"\nResultados guardados en '{RESULTADOS_FILE}'")
log_text(
f"FIN: {total} procesados. Exitos: {contadores['exitos']}. "
f"Fallidos: {contadores['fallidos']}. NoEncontrados: {contadores['no_encontrados']}. "
f"ErrSes: {contadores['error_sesion']}"
)
print("\nRESUMEN FINAL")
print(f"Total filas: {total}")
print(f"Exitos: {contadores['exitos']}")
print(f"Fallidos: {contadores['fallidos']}")
print(f"No encontrados: {contadores['no_encontrados']}")
print(f"Errores de sesion: {contadores['error_sesion']}")
if total:
print(f"Porcentaje exitos: {contadores['exitos'] / total * 100:.1f}%")
try:
driver.quit()
except Exception:
pass