feat(browser): auto-commit con 6 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
---
|
||||
name: whatsapp_send_image
|
||||
kind: function
|
||||
lang: py
|
||||
domain: browser
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "def whatsapp_send_image(name: str, image_path: str, *, caption: str = '', port: int = 9222, target_url_substr: str = 'whatsapp', open_first: bool = True) -> dict"
|
||||
description: "Envia una imagen (con caption opcional) a un chat de WhatsApp Web en una pestana ya logueada del navegador diario via CDP, sin abrir ventana nueva ni darle foco. Abre el chat por nombre exacto (whatsapp_open_chat) y verifica el destinatario (salvaguarda anti-envio-equivocado), hace click real en 'Adjuntar' para exponer el <input type=file> vivo, asigna la imagen con cdp_set_file_input (DOM.setFileInputFiles), espera el preview de la bandeja inline, teclea el caption opcional con teclado CDP real, y hace click en el boton enviar (icono wds-ic-send-filled) verificando que la bandeja se cerro. Accion con efecto: envia la imagen DE VERDAD, no reversible."
|
||||
tags: [whatsapp, cdp, browser, automation, image, upload, python, navegator]
|
||||
uses_functions: [whatsapp_open_chat_py_browser, cdp_eval_py_browser, cdp_click_xy_py_browser, cdp_type_chars_py_browser, cdp_set_file_input_py_browser]
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: ["os", "sys", "time", "json"]
|
||||
params_schema:
|
||||
params:
|
||||
- name: name
|
||||
desc: "Nombre EXACTO del chat o grupo destinatario tal y como aparece en la lista lateral. Se usa para abrir el chat y como salvaguarda de que el composer apunta al destinatario correcto antes de adjuntar."
|
||||
- name: image_path
|
||||
desc: "Ruta de la imagen a enviar. Se expande (~) y se convierte a ruta ABSOLUTA; debe existir en disco o aborta con error sin abrir el chat."
|
||||
- name: caption
|
||||
desc: "Texto opcional que acompana la imagen. Se teclea en el composer con teclado CDP real caracter a caracter; '' (default) envia la imagen sin caption."
|
||||
- name: port
|
||||
desc: "Puerto de remote debugging de Chrome. Default 9222."
|
||||
- name: target_url_substr
|
||||
desc: "Substring que debe contener la URL del target (pestana). Default 'whatsapp'."
|
||||
- name: open_first
|
||||
desc: "Si True (default), abre el chat por su nombre antes de adjuntar. Si False, asume el chat ya abierto pero verifica el aria-label del composer contra name (aborta si no coincide)."
|
||||
output: "dict {ok: bool (alias de sent), sent: bool, recipient: str, image: str (ruta absoluta), caption: str, error: str (motivo del fallo, vacio si sent=True)}. sent=True solo si la imagen se adjunto, el caption (si lo hay) se verifico y se pulso enviar dejando la bandeja vacia. Nunca lanza: los fallos se reportan en 'sent'/'ok' + 'error'."
|
||||
tested: true
|
||||
tests: ["test_golden_adjunta_caption_y_envia", "test_envia_sin_caption_no_teclea", "test_edge_imagen_no_existe_error_sin_abrir", "test_edge_open_fallido_error_sin_adjuntar", "test_seguridad_open_first_false_label_no_coincide_aborta", "test_error_set_file_input_falla_no_envia"]
|
||||
test_file_path: "python/functions/browser/whatsapp_send_image_test.py"
|
||||
file_path: "python/functions/browser/whatsapp_send_image.py"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.join("python", "functions"))
|
||||
from browser.whatsapp_send_image import whatsapp_send_image
|
||||
|
||||
# Requiere WhatsApp Web abierto y logueado (y DESBLOQUEADO si tiene app-lock) en un
|
||||
# Chrome lanzado con --remote-debugging-port=9222.
|
||||
res = whatsapp_send_image(
|
||||
"NOTAS WASAP",
|
||||
"/home/enmanuel/ComfyUI/output/item_icon_potion_00001_.png",
|
||||
caption="item icon: potion",
|
||||
)
|
||||
print(res)
|
||||
# -> {"ok": True, "sent": True, "recipient": "NOTAS WASAP",
|
||||
# "image": ".../item_icon_potion_00001_.png", "caption": "item icon: potion", "error": ""}
|
||||
```
|
||||
|
||||
O directo por CLI: `python3 python/functions/browser/whatsapp_send_image.py "NOTAS WASAP" /ruta/abs.png "mi caption"`.
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando necesites **enviar una imagen (foto, captura, asset generado) a un contacto o grupo
|
||||
por su nombre exacto** en WhatsApp Web, sin abrir ventana nueva ni robar el foco al usuario.
|
||||
Es la version "imagen" de `whatsapp_send_message_py_browser`: usala cuando ya tienes el
|
||||
nombre exacto del destinatario y la ruta de un archivo de imagen en disco. Para texto plano,
|
||||
usa `whatsapp_send_message`; para leer/confirmar lo enviado, `whatsapp_read_chat`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Accion con efecto: envia la imagen DE VERDAD.** No es reversible. Verifica que `name` es
|
||||
EXACTO antes de llamar (la salvaguarda abre el chat y comprueba el composer, pero el nombre
|
||||
debe coincidir con el `title` de la lista lateral).
|
||||
- **App-lock de WhatsApp Web.** Si la cuenta tiene el "bloqueo de la aplicacion" activo, el DOM
|
||||
de chats no se renderiza (solo la pantalla de password) y la funcion fallara al abrir el chat.
|
||||
Hay que desbloquearlo primero (teclear el password en `input[type=password]` + boton
|
||||
"Desbloquear"). Sintoma: `whatsapp_open_chat` devuelve `opened: False` y la lista lateral sale
|
||||
vacia aunque la sesion siga logueada.
|
||||
- **El input vivo solo existe tras pulsar "Adjuntar".** Por eso la funcion hace el click real en
|
||||
el boton "Adjuntar" antes de `setFileInputFiles`; asignar al input persistente decoy no abre el
|
||||
preview. La WhatsApp Web actual usa una **bandeja de medios INLINE** sobre el composer (no un
|
||||
drawer a pantalla completa): el caption se escribe en el MISMO composer del footer.
|
||||
- **Selector de aria-label en espanol.** El preview se detecta por `[aria-label="Quitar archivo
|
||||
adjunto"]` y el boton de adjuntar por `[aria-label="Adjuntar"]`: dependen del idioma de la UI
|
||||
(espanol). En otro locale habria que ajustar los aria-labels.
|
||||
- **Las imagenes se ACUMULAN en la bandeja.** Cada `setFileInputFiles` anade una miniatura; si un
|
||||
envio queda a medias, la siguiente llamada podria sumar a las pendientes. La funcion verifica que
|
||||
la bandeja queda vacia tras enviar (adjuntos=0) para confirmar; si no se cierra, devuelve
|
||||
`sent=False` con "envio incierto".
|
||||
- **Salvaguarda anti-destinatario-equivocado**: con `open_first=True` abre y verifica el chat; con
|
||||
`open_first=False` lee el aria-label del composer y aborta si no contiene `name`.
|
||||
- **Caption verificado**: tras teclear, re-lee el `innerText` del composer y solo envia si coincide
|
||||
EXACTAMENTE con `caption`; si no, devuelve `sent=False` sin enviar.
|
||||
- **Funciona con la ventana minimizada o sin foco**: CDP opera la pestana sin traerla a primer plano.
|
||||
- **Viola los ToS de WhatsApp**: automatizar la web tiene riesgo de ban del numero personal. Usar
|
||||
con cautela y bajo tu responsabilidad.
|
||||
Reference in New Issue
Block a user