ahora si funciona
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,7 @@ Indice de grupos de capacidades del registry. Cada grupo agrupa >=3 funciones qu
|
||||
| [sink](sink.md) | 11 | Funciones que escriben datos a destino externo (BD, dashboard, alerta, email). Nodos output |
|
||||
| [validator](validator.md) | 6 | Funciones que verifican datos/config contra reglas. Pre-flight de sinks y gates en DAGs |
|
||||
| [navegator](navegator.md) | 4 | Automatización de browser via CDP + AX tree + LLM: obtener, limpiar, chunkear AX tree y llamar a Claude CLI |
|
||||
| [whatsapp](whatsapp.md) | 3 | Operar WhatsApp Web por CDP sobre la pestaña existente (sin ventana ni foco): buscar/abrir chat, leer conversacion, enviar texto. Compone 4 primitivas CDP-Python (cdp_eval/type_chars/press_key/click_xy). No HTTP: WhatsApp usa WebSocket + cifrado E2E |
|
||||
| [cpp-dashboard-viz](cpp-dashboard-viz.md) | 10 | Primitivas C++ ImGui para dashboards: kpi_card, sparkline, line/bar/scatter/pie/heatmap/histogram, panel containers |
|
||||
| [agents](agents.md) | 3 | Orquestar agentes Claude headless en git worktrees: launch, cleanup, DoD evidence schema audit |
|
||||
| [backends](backends.md) | — | Stacks backend (Go net/http+SQLite default, MCP, mautrix, bubbletea, httpx, docker-compose): decision tree + esqueleto canonico + funciones del registry a componer |
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# WhatsApp — Operar WhatsApp Web por CDP sobre la sesión existente
|
||||
|
||||
Tag: `whatsapp`. Grupo de funciones para automatizar WhatsApp Web (buscar/abrir un chat,
|
||||
leer la conversación, enviar texto) operando por Chrome DevTools Protocol sobre la **pestaña
|
||||
ya abierta y logueada** del navegador diario, **sin abrir ventana nueva ni darle foco**.
|
||||
|
||||
Filtro MCP: `mcp__registry__fn_search query="" tag="whatsapp"`.
|
||||
|
||||
## Por qué CDP y no HTTP replay
|
||||
|
||||
WhatsApp Web **no envía mensajes por HTTP requests REST**: usa un **WebSocket** (wss) como
|
||||
transporte y **cifrado extremo a extremo (Signal/Noise)**, con claves que rotan por mensaje y
|
||||
viven en el navegador. El tráfico capturable es binario cifrado e irreproducible — por eso el
|
||||
patrón `flow-replay` (grabar HTTP → reproducir) **no aplica** aquí. La única vía que opera la
|
||||
sesión existente sin ventana nueva es **automatizar el DOM por CDP**. (Baileys/whatsapp-web.js
|
||||
quedan descartados: emparejan un dispositivo nuevo por QR, o abren su propio navegador.)
|
||||
|
||||
## Funciones del grupo
|
||||
|
||||
| ID | Firma corta | Qué hace |
|
||||
|---|---|---|
|
||||
| [whatsapp_open_chat_py_browser](../../python/functions/browser/whatsapp_open_chat.md) | `whatsapp_open_chat(name, *, port=9222) -> dict` | Busca y abre un chat por nombre exacto (ancla `span[title]` + click de ratón real). Verifica el destinatario. Base de read/send. |
|
||||
| [whatsapp_read_chat_py_browser](../../python/functions/browser/whatsapp_read_chat.md) | `whatsapp_read_chat(name, *, n=15, open_first=True) -> dict` | Lee los últimos N mensajes renderizados del chat (`{text, outgoing}`). |
|
||||
| [whatsapp_send_message_py_browser](../../python/functions/browser/whatsapp_send_message.md) | `whatsapp_send_message(name, text, *, open_first=True) -> dict` | Envía un texto. Salvaguarda: verifica destinatario + contenido exacto del composer antes de pulsar Enter. |
|
||||
|
||||
### Primitivas CDP que componen (grupo `navegator`)
|
||||
|
||||
El transport está en 4 primitivas Python reutilizables (cualquier automatización de la sesión diaria):
|
||||
|
||||
| ID | Qué hace |
|
||||
|---|---|
|
||||
| [cdp_eval_py_browser](../../python/functions/browser/cdp_eval.md) | Evalúa JS en un target por substring de URL (leer DOM, `focus()`, resolver coords). |
|
||||
| [cdp_type_chars_py_browser](../../python/functions/browser/cdp_type_chars.md) | Escribe char-by-char con key events reales (único método que funciona con el editor Lexical). |
|
||||
| [cdp_press_key_py_browser](../../python/functions/browser/cdp_press_key.md) | Pulsa una tecla nombrada (Enter, Escape, Backspace, Arrows...) con modificadores. |
|
||||
| [cdp_click_xy_py_browser](../../python/functions/browser/cdp_click_xy.md) | Click de ratón real en coordenadas (necesario: `element.click()` JS no dispara los handlers de React). |
|
||||
|
||||
## Ejemplo canónico end-to-end
|
||||
|
||||
Requisito: WhatsApp Web abierto y logueado en un Chrome con `--remote-debugging-port=9222`
|
||||
(en este equipo, el CDP global de chromium ya lo expone). No hace falta foco ni ventana visible.
|
||||
|
||||
```python
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.join("python", "functions"))
|
||||
from browser.whatsapp_read_chat import whatsapp_read_chat
|
||||
from browser.whatsapp_send_message import whatsapp_send_message
|
||||
|
||||
# Leer los últimos mensajes de un chat
|
||||
r = whatsapp_read_chat("NOTAS WASAP", n=5)
|
||||
for m in r["messages"]:
|
||||
print(("→" if m["outgoing"] else "←"), m["text"])
|
||||
|
||||
# Enviar un mensaje (acción con efecto: envía de verdad)
|
||||
res = whatsapp_send_message("NOTAS WASAP", "hola desde el registry")
|
||||
print(res) # {"sent": True, "last_row": "hola desde el registry 11:48"}
|
||||
```
|
||||
|
||||
## Fronteras y gotchas (leer antes de usar)
|
||||
|
||||
- **Viola los ToS de WhatsApp; riesgo de ban del número.** Probar en un chat propio reduce
|
||||
molestia a terceros pero no elimina el riesgo de detección por patrón.
|
||||
- **Envío irreversible**: `whatsapp_send_message` envía de verdad y WhatsApp no permite
|
||||
des-enviar por esta vía. La función verifica destinatario (`name` exacto en el composer) y
|
||||
contenido antes de Enter, pero el `name` lo das tú: un nombre ambiguo abre el primer match.
|
||||
- **Nombre exacto requerido** (`span[title]` exacto). El buscador **no filtra de forma fiable
|
||||
los contactos NO cargados** en la lista lateral; funciona para chats recientes/visibles. Un
|
||||
contacto sin chat reciente puede no encontrarse (limitación conocida; mejora futura: scroll).
|
||||
- **Lexical**: escribir SOLO con `cdp_type_chars` (key events reales). `execCommand`/`el.value`
|
||||
meten texto fantasma y producen duplicación/intercalado.
|
||||
- **Abrir chats**: requiere click de ratón real (`cdp_click_xy`); `element.click()` JS no abre.
|
||||
- **`outgoing`** se infiere de `.message-out` (heurístico) y puede no marcar bien los mensajes
|
||||
propios en algunos grupos; el `text` siempre es fiable.
|
||||
- **Solo lee lo renderizado** en el viewport del chat; mensajes muy antiguos requieren scroll
|
||||
(no implementado).
|
||||
- Funciona con la ventana **minimizada y sin foco** (CDP no depende del foco del SO).
|
||||
|
||||
## Prerequisitos
|
||||
|
||||
- Chrome/Chromium con remote debugging en el puerto 9222 y WhatsApp Web logueado.
|
||||
- `websocket-client` en `python/.venv` (ya presente). Sin dependencias nuevas.
|
||||
Reference in New Issue
Block a user