Files
fn_registry/python/functions/browser/whatsapp_read_chat.py
T
egutierrez 10bfb846a8 ahora si funciona
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-07 16:23:52 +02:00

90 lines
3.5 KiB
Python

"""Lee los ultimos N mensajes de un chat de WhatsApp Web via Chrome DevTools Protocol.
Compone dos funciones del registry para extraer la conversacion reciente del chat
abierto en una pestana ya logueada del navegador, SIN abrir ventana nueva ni darle
foco al sistema:
1. (Opcional) Abre el chat por su nombre exacto con `whatsapp_open_chat`.
2. Evalua una expresion JS via `cdp_eval` que recoge los ultimos `n` `[role="row"]`
del panel principal (`#main`), normaliza su texto y detecta si cada mensaje es
saliente comprobando la presencia de `.message-out` en el row.
Devuelve la lista de mensajes mas recientes con su direccion (entrante/saliente).
"""
import json
import os
import sys
import time
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from browser.cdp_eval import cdp_eval
from browser.whatsapp_open_chat import whatsapp_open_chat
def whatsapp_read_chat(
name: str,
*,
n: int = 15,
port: int = 9222,
target_url_substr: str = "whatsapp",
open_first: bool = True,
) -> dict:
"""Lee los ultimos n mensajes renderizados de un chat de WhatsApp Web via CDP.
Args:
name: Nombre EXACTO del chat/grupo tal y como aparece en la lista lateral
(se pasa a `whatsapp_open_chat` cuando `open_first=True`).
n: Numero maximo de mensajes recientes a leer (los ultimos del viewport).
Default 15.
port: Puerto de remote debugging de Chrome. Default 9222.
target_url_substr: Substring que debe contener la URL del target (pestana).
Default "whatsapp".
open_first: Si True, abre el chat con `whatsapp_open_chat` antes de leer.
Si el chat ya esta abierto y enfocado, puede pasarse False para ahorrar
el paso de apertura. Default True.
Returns:
dict con claves:
ok: bool — True si se pudo leer el chat.
name: str — el nombre solicitado.
messages: list[dict] — mensajes recientes, cada uno {text: str,
outgoing: bool}. Lista vacia si no hay mensajes o fallo la apertura.
count: int — numero de mensajes leidos (solo si ok).
reason: str — motivo del fallo (solo si ok=False).
"""
substr = target_url_substr
if open_first:
o = whatsapp_open_chat(name, port=port, target_url_substr=substr)
if not o.get("opened"):
return {
"ok": False,
"name": name,
"messages": [],
"reason": o.get("reason", "no se pudo abrir el chat"),
}
# Leer los ultimos n rows del panel principal. Detecta mensaje saliente por
# la presencia de .message-out en el row. Normaliza el texto (colapsa espacios)
# y lo trunca a 500 caracteres para acotar el payload.
expr = (
"(() => { const rows=[...document.querySelectorAll('#main [role=\"row\"]')]"
".slice(-" + str(int(n)) + ");"
"return JSON.stringify(rows.map(r=>({"
"text: r.innerText.replace(/\\s+/g,' ').trim().slice(0,500),"
"outgoing: !!r.querySelector('.message-out')"
"})));})()"
)
r = cdp_eval(expr, port=port, target_url_substr=substr)
msgs = json.loads(r.get("value") or "[]")
return {"ok": True, "name": name, "messages": msgs, "count": len(msgs)}
if __name__ == "__main__":
chat = sys.argv[1] if len(sys.argv) > 1 else "NOTAS WASAP"
count = int(sys.argv[2]) if len(sys.argv) > 2 else 15
out = whatsapp_read_chat(chat, n=count, port=9222, target_url_substr="whatsapp")
print(json.dumps(out, ensure_ascii=False, indent=2))