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:
94
Python/whatsapp_modular_v3_6/whatsapp_sender/main.py
Normal file
94
Python/whatsapp_modular_v3_6/whatsapp_sender/main.py
Normal 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
|
||||
Reference in New Issue
Block a user