@fer2809fl/baileys 7.0.4 → 7.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +347 -50
  2. package/lib/Defaults/index.js +1 -1
  3. package/lib/Modded/message_builder.js +2356 -0
  4. package/lib/Socket/chats.d.ts +14 -0
  5. package/lib/Socket/chats.js +48 -0
  6. package/lib/Socket/index.d.ts +17 -0
  7. package/lib/Socket/messages-send.d.ts +18 -0
  8. package/lib/Socket/messages-send.js +50 -2
  9. package/lib/Utils/anti-ban.d.ts +41 -0
  10. package/lib/Utils/anti-ban.js +182 -0
  11. package/lib/Utils/banner.d.ts +8 -0
  12. package/lib/Utils/banner.js +76 -0
  13. package/lib/Utils/bot-utils.d.ts +57 -0
  14. package/lib/Utils/bot-utils.js +241 -0
  15. package/lib/Utils/enhanced-cache.d.ts +40 -0
  16. package/lib/Utils/enhanced-cache.js +242 -0
  17. package/lib/Utils/enhanced-logger.d.ts +41 -0
  18. package/lib/Utils/enhanced-logger.js +185 -0
  19. package/lib/Utils/index.d.ts +14 -0
  20. package/lib/Utils/index.js +13 -0
  21. package/lib/Utils/lid-utils.d.ts +139 -0
  22. package/lib/Utils/lid-utils.js +503 -0
  23. package/lib/Utils/message-queue.d.ts +47 -0
  24. package/lib/Utils/message-queue.js +226 -0
  25. package/lib/Utils/rich-message-utils.d.ts +21 -0
  26. package/lib/Utils/rich-message-utils.js +229 -0
  27. package/lib/Utils/rich-messages.d.ts +52 -0
  28. package/lib/Utils/rich-messages.js +185 -0
  29. package/lib/Utils/scheduled-messages.d.ts +122 -0
  30. package/lib/Utils/scheduled-messages.js +289 -0
  31. package/lib/Utils/smart-reconnect.d.ts +48 -0
  32. package/lib/Utils/smart-reconnect.js +207 -0
  33. package/lib/Utils/use-sqlite-auth-state.d.ts +11 -0
  34. package/lib/Utils/use-sqlite-auth-state.js +95 -0
  35. package/lib/VoIP/audio-feeder.d.ts +15 -0
  36. package/lib/VoIP/audio-feeder.js +132 -0
  37. package/lib/VoIP/index.js +277 -0
  38. package/lib/VoIP/relay-transport.d.ts +43 -0
  39. package/lib/VoIP/relay-transport.js +559 -0
  40. package/lib/VoIP/signaling.js +594 -0
  41. package/lib/VoIP/types.d.ts +69 -0
  42. package/lib/VoIP/types.js +17 -0
  43. package/lib/VoIP/wasm-engine.d.ts +103 -0
  44. package/lib/VoIP/wasm-engine.js +1214 -0
  45. package/lib/VoIP/worker-bootstrap.js +1042 -0
  46. package/lib/assets/wasm/loader.js +5 -0
  47. package/lib/assets/wasm/whatsapp.wasm +0 -0
  48. package/lib/assets/wasm/worker-modules.js +273 -0
  49. package/lib/index.d.ts +41 -0
  50. package/lib/index.js +3 -0
  51. package/package.json +10 -2
package/README.md CHANGED
@@ -16,68 +16,117 @@
16
16
 
17
17
  ---
18
18
 
19
- ## 🆕 Novedades — v7.0.3
19
+ ## 🆕 Novedades — v7.0.5
20
20
 
21
- Actualización de estabilidad y sincronización con las últimas mejoras del protocolo de WhatsApp Web.
21
+ **La actualización más completa hasta ahora.** Se revisó el fork "beta" del proyecto en busca de utilidades que este repo todavía no tenía, se portaron una por una (evitando duplicar nombres ya existentes) y se hizo una auditoría de código de punta a punta — no solo del README.
22
22
 
23
- ### Nuevas funciones añadidas
24
- - **`withUsernameProtocol()`** en `USyncQuery` permite sincronizar contactos por *username* de WhatsApp (la nueva forma de identificar cuentas, además del número de teléfono):
23
+ ### 🔧 Mantenimiento y correcciones
24
+ - **`messages-send.js`** se corrigió un caso donde el nodo `biz` (usado por los botones nativos) podía duplicarse dentro del stanza si ya venía agregado por otra parte del mensaje; ahora se verifica que no exista antes de agregarlo.
25
+ - **Auditoría completa de `lib/`**, archivo por archivo contra el fork beta: no faltaba ninguna función real, solo faltaban algunos exports y tipos, ya corregidos.
26
+ - **Exports arreglados** — `Utils/reporting-utils.js` y `Utils/companion-reg-client-utils.js` existían en el código pero no se exportaban bien desde el paquete; quien instalaba `@fer2809fl/baileys` no podía importar sus funciones. Ya se puede.
27
+ - **Tipos de TypeScript agregados** para los 9 módulos que solo venían en JavaScript — `anti-ban`, `smart-reconnect`, `message-queue`, `enhanced-cache`, `enhanced-logger`, `bot-utils`, `banner`, `rich-message-utils` y `use-sqlite-auth-state` — verificados con `tsc`. Ahora tienen autocompletado y chequeo de tipos.
28
+ - **Limpieza de marca** en `banner.js` y `enhanced-logger.js` (traían branding del proyecto original de donde se portó el código).
29
+ - En general: se optimizó y se prolijaron varios detalles sueltos de código y documentación que quedaron de fusiones anteriores.
30
+
31
+ Se documentaron además funciones que ya existían en el código pero no tenían ejemplo de uso: tablas, bloques de código, carruseles, álbumes y canales/newsletters (ver secciones nuevas más abajo).
32
+
33
+ Próximas tandas (se irán agregando poco a poco): documentación de Grupos avanzados, Comunidades, Negocios, Perfil/Privacidad, Estados (stories) y Eventos.
34
+
35
+ ### 🆕 Protocolo actualizado + funciones nuevas de chat
36
+ - **Versión de WhatsApp Web actualizada** a `2.3000.1047406223` (la más reciente confirmada al momento de esta actualización), reduciendo el riesgo de rechazo de conexión por versión vieja.
37
+ - **Nuevas funciones de chat** (no existían ni en este fork ni en el beta — son de cosecha propia esta vez): atajos simples para las operaciones de chat más comunes, en vez de tener que armar el objeto de `chatModify` a mano:
25
38
  ```javascript
26
- const result = await sock.executeUSyncQuery(
27
- new USyncQuery().withUsernameProtocol().withUser(new USyncUser().withPhone('+123...'))
28
- )
39
+ await sock.pinChat(jid) // fijar chat
40
+ await sock.pinChat(jid, false) // desfijar
41
+ await sock.archiveChat(jid) // archivar
42
+ await sock.archiveChat(jid, false) // desarchivar
43
+ await sock.muteChat(jid, Date.now() + 8 * 60 * 60 * 1000) // silenciar 8 horas
44
+ await sock.muteChat(jid) // quitar silencio
45
+ await sock.markChatRead(jid) // marcar como leído
46
+ await sock.markChatUnread(jid) // marcar como no leído
47
+ await sock.clearChat(jid) // vaciar el historial del chat
48
+ await sock.deleteChat(jid) // eliminar el chat de la lista
49
+ ```
50
+ Todas usan por debajo el mismo `chatModify` de siempre (mismo protocolo, mismos parches de estado), solo que ahora no hay que recordar la forma exacta del objeto `mod`.
51
+ - **Fijar un mensaje dentro del chat** (`pinInChatMessage`) — esta ya existía en el código pero no estaba documentada:
52
+ ```javascript
53
+ // Fijar el mensaje citado por 24 horas (86400 segundos)
54
+ await sock.sendMessage(jid, { pin: quotedMsg.key, type: 1, time: 86400 })
55
+ // Desfijar
56
+ await sock.sendMessage(jid, { pin: quotedMsg.key, type: 2 })
29
57
  ```
30
- - **`sock.fetchAccountReachoutTimelock()`** — consulta si tu cuenta tiene alguna restricción activa para iniciar chats nuevos, y hasta cuándo dura.
31
- - **`sock.fetchNewChatMessageCap()`** — consulta el límite de mensajes que puedes enviar a chats/números nuevos (cupo anti-spam de WhatsApp).
32
- - **`sock.registerSocketEndHandler(handler)`** — registra una función que se ejecuta automáticamente cada vez que la conexión se cierra (útil para limpieza de recursos propios sin tener que escuchar `connection.update` a mano).
33
- - **Nuevo formato de código QR de emparejamiento** — el QR ahora incluye el identificador de plataforma del companion, igual que el WhatsApp Web oficial (mejora la tasa de éxito al vincular).
34
-
35
- ### 🐛 Correcciones de estabilidad y memoria
36
- - **Fuga de memoria en el buffer de eventos** — se agregó limpieza real de timers, cachés y listeners al cerrar una conexión (`ev.destroy()`), evitando que la memoria crezca con reconexiones frecuentes.
37
- - **Loop de reintentos por fallas de descifrado (MAC)** — se agregó detección de colisión de "base key" en reintentos de mensajes: si WhatsApp reenvía el mismo mensaje repetidamente por un fallo de sesión, la librería ahora detecta el patrón y fuerza una sesión nueva en vez de reintentar indefinidamente.
38
- - **Duplicados al sincronizar historial de grupos** — se corrigió el merge de "participantes que salieron" (`pastParticipants`) para no duplicar entradas cuando WhatsApp envía el historial en varios paquetes.
39
- - **IDs de consulta de canales (newsletters) desactualizados** — los IDs internos de `FOLLOW`/`UNFOLLOW` de canales estaban vencidos y podían empezar a fallar silenciosamente; se actualizaron a los vigentes.
40
- - **Versión de protocolo de WhatsApp Web actualizada** — reduce el riesgo de desconexiones forzadas por versión obsoleta.
41
- - **Dependencias actualizadas**: `libsignal` ahora se instala desde npm (antes requería `git` instalado en el servidor), `whatsapp-rust-bridge`, `protobufjs` y otras al día.
42
-
43
- > Nota: las funciones de auto-follow de canales, el motor de envío de mensajes (`sendMessage` y helpers internos) y el manejo avanzado de negocios (`business.js`) son personalizaciones propias de este fork — se mantuvieron intactas durante esta actualización.
44
-
45
- ### 🔧 Fusión profunda adicional
46
- - **`chats.js` reconstruido sobre la base oficial**: recuperación automática de sincronización de estado cuando falta una clave (antes fallaba silenciosamente), resolución correcta de bloqueo de contactos por LID/PN, y tracking de finalización de sincronización de historial.
47
- - **`groups.js` reconstruido**: mejor resolución de LID/PN en metadata de grupos + tus funciones `isGroupAdmin`, `getGroupAdmins`, `resolveParticipantJid`, `groupMetadataCached` intactas.
48
- - **`business.js` alineado al oficial** (era funcionalmente idéntico, solo cambiaba el estilo del código).
49
- - **Endpoint de canales actualizado**: WhatsApp movió `newsletterFollow`/`newsletterUnfollow` a un endpoint nuevo (`_v2`); se actualizó, incluyendo tu sistema de auto-follow interno, para que siga funcionando.
50
58
 
51
- ---
59
+ ### ✅ Nuevas funciones añadidas
52
60
 
61
+ **Anti-Ban** (`Utils/anti-ban.js`)
62
+ - `randomDelay`, `messageDelay`, `typingDelay` — retrasos aleatorios "humanizados" antes de enviar.
63
+ - `RateLimiter`, `globalRateLimiter`, `groupRateLimiter`, `broadcastRateLimiter` — limitadores de tasa listos para usar por chat/grupo/difusión.
64
+ - `PresenceManager`, `generateSessionFingerprint`, `isValidJid`, `sanitizeMessage` — utilidades de apoyo para reducir el riesgo de baneo por comportamiento de bot.
53
65
 
66
+ **Reconexión inteligente** (`Utils/smart-reconnect.js`)
67
+ - `SmartReconnect`, `createConnectionHandler`, `withRetry` — backoff exponencial con jitter y detección de causas de desconexión recuperables vs definitivas.
54
68
 
55
- ### Nuevas funciones añadidas
56
- - **Detección de admins y resolución de JID/LID 100% nativa** Antes, cada bot tenía que reimplementar a mano la comparación de `jid`, `@lid` y número de teléfono contra `groupMetadata` para saber si alguien es admin. Ahora esa lógica vive directamente en el socket:
57
- - `isGroupAdmin(chatId, jid)` — `true`/`false` si ese participante (venga como número o como `@lid`) es admin o superadmin del grupo.
58
- - `getGroupAdmins(chatId)` — lista de admins del grupo, ya resueltos a su jid de número de teléfono real (nunca `@lid`).
59
- - `resolveParticipantJid(chatIdOrParticipants, jid)` — convierte cualquier `@lid` a su número real. Primero busca en los participantes del grupo; si no encuentra coincidencia, usa el mapeo LID↔PN nativo de WhatsApp (`signalRepository.lidMapping`) en vez de adivinar.
60
- - `groupMetadataCached(chatId)` — igual que `groupMetadata`, pero con cache de 30s que se invalida solo apenas hay un alta, baja, ascenso o descenso real de participantes (via `group-participants.update`), para no golpear a WhatsApp en cada mensaje.
69
+ **Cola de mensajes** (`Utils/message-queue.js`)
70
+ - `MessageQueue`, `createMessageQueue`colas con prioridad (`PRIORITY.CRITICAL` a `PRIORITY.BACKGROUND`) y control de tasa por tipo de contenido.
61
71
 
62
- Esto es lo mismo que antes hacían los bots "a mano" con `groupMetadata` + comparaciones manuales de `id`/`lid`/`phoneNumber`, pero ahora resuelto por la librería, con cache y con el mapeo oficial de WhatsApp como respaldo.
72
+ **Caché mejorada** (`Utils/enhanced-cache.js`)
73
+ - `EnhancedCache`, `CacheManager` — caché en memoria con TTL/stale-TTL basada en `lru-cache`, con snapshot a disco.
63
74
 
64
- ---
75
+ **Logger mejorado** (`Utils/enhanced-logger.js`)
76
+ - `createLogger`, `RyzeLogger` — logger con niveles, colores en consola e iconos por categoría (no reemplaza tu logger `pino` existente, es una alternativa opcional).
65
77
 
66
- ## 🆕 Novedades — v7.0.1
78
+ **Mensajes programados** (`Utils/scheduled-messages.js`)
79
+ ```javascript
80
+ import { startScheduler, scheduleMessage, recurringMessage } from '@fer2809fl/baileys'
67
81
 
68
- ### Nuevas funciones añadidas
69
- - **Botones nativos reales** — Se agregaron métodos directos en el socket para enviar botones interactivos de WhatsApp (native flow), reemplazando el viejo formato `buttons: [{text, id}]` que ya no renderiza en WhatsApp:
70
- - `sendQuickReplyButtons` Botones de respuesta rápida
71
- - `sendUrlButton` Botón que abre un enlace
72
- - `sendCallButton` — Botón para iniciar una llamada
73
- - `sendCopyButton` Botón que copia texto al portapapeles
74
- - `sendReminderButton` Botón de recordatorio
75
- - `sendListButton` — Menú desplegable con secciones y filas
76
- - `sendMixedButtons` Combinación libre de varios tipos en un solo mensaje
77
- - **Previsualización automática de links** — `sendLinkPreview` y todos los botones de arriba arman solos la tarjeta grande (imagen + título + descripción) de cualquier URL que detecten en el texto, con el mismo motor que usa WhatsApp para los links normales.
78
-
79
- ### 🐛 Correcciones
80
- - **Error en macOS** — Se reparó un bug crítico que impedía iniciar sesión correctamente en dispositivos Mac. El proceso de pairing/QR ahora funciona de forma estable en macOS.
82
+ startScheduler(sock) // arranca el scheduler una vez tengas el sock conectado
83
+
84
+ // una sola vez, en una fecha exacta
85
+ scheduleMessage('123@s.whatsapp.net', { text: 'Recordatorio' }, Date.now() + 60_000)
86
+
87
+ // recurrente con cron simple: "MIN HOUR DOM MON DOW"
88
+ recurringMessage('123@s.whatsapp.net', { text: 'Buenos días' }, '0 9 * * *')
89
+ ```
90
+ También: `cancelScheduledMessage`, `deleteScheduledMessage`, `listScheduledMessages`, `getScheduledMessage`, `updateScheduledMessage`, `getSchedulerStats`. Persiste en `database/scheduled-messages.json`.
91
+
92
+ **Utilidades de LID** (`Utils/lid-utils.js`)
93
+ - `isLid`, `lidToJid`, `resolveAnyLidToJid`, `resolveParticipant`, `getParticipantJid(s)`, `cacheParticipantLids`, `findParticipantByNumber`, entre otras — resolución y cacheo de `@lid` ↔ número real con persistencia en `database/lid-cache.json`. Complementa (no reemplaza) la resolución de admins/JID-LID nativa que ya tenía este fork desde v1.10.0.
94
+
95
+ **Utilidades para bots** (`Utils/bot-utils.js`)
96
+ - `parseCommand(text, prefix)` — parseo de comandos con flags (`--flag=valor`) y argumentos.
97
+ - `CooldownManager`, `PermissionManager` (owners/admins/baneados/premium).
98
+ - `extractMentions`, `extractQuotedMessage`, `isGroupAdmin`, `isBotAdmin`, `formatPhoneNumber`, `parseTime('10m')`, `formatDuration(ms)`, `sendFast(sock, jid, contenido)`.
99
+
100
+ **Auth state en SQLite** (`Utils/use-sqlite-auth-state.js`)
101
+ ```javascript
102
+ import { useSqliteAuthState } from '@fer2809fl/baileys'
103
+ const { state, saveCreds } = await useSqliteAuthState({ dbPath: './auth.db' })
104
+ ```
105
+ Requiere `better-sqlite3` (peer dependency opcional: `npm i better-sqlite3`).
106
+
107
+ **Banner de inicio** (`Utils/banner.js`) — `printBanner()` opcional para mostrar un logo ASCII al arrancar el bot.
108
+
109
+ **AI Rich Response — helpers de bajo nivel** (`Utils/rich-message-utils.js`)
110
+ - `prepareRichResponseMessage(contenido)` — arma un `AIRichResponseMessage` completo (texto + código + tabla + links) en un solo llamado, incluyendo la firma/certificado de `botMetadata`.
111
+ - `toUnified`, `wrapToBotForwardedMessage`, `botMetadataSignature`, `botMetadataCertificate` — piezas internas reutilizables si armas tus propios mensajes enriquecidos.
112
+ - Se ampliaron los lenguajes soportados para resaltado de código en `LANGUAGE_KEYWORDS` (`Utils/rich-messages.js`): ahora incluye `rust`, `c`, `cpp`/`c++`, `csharp`/`c#`, `html` y `css`, además de los que ya tenías.
113
+
114
+ **Builder "Modded"** (`Modded/message_builder.js`) — clases con API encadenable para armar botones, carruseles y respuestas AI-Rich sin construir el objeto a mano: `Button`, `ButtonV2`, `Carousel`, `AIRich`, `ORich`, `Toolkit`. *(Este archivo trae una nota de autoría de su creador original — se mantuvo intacta tal cual, junto con los términos: uso libre para proyectos propios, pero no puede revenderse ni redistribuirse como librería independiente.)*
115
+
116
+ **VoIP — llamadas de voz** (`VoIP/`) — cliente experimental de llamadas de voz de WhatsApp sobre el motor WASM oficial:
117
+ ```javascript
118
+ import { VoipClient, CallState } from '@fer2809fl/baileys'
119
+
120
+ const voip = new VoipClient(sock)
121
+ const call = await voip.call('123@s.whatsapp.net')
122
+ call.on('stateChange', (state) => console.log(CallState[state]))
123
+ ```
124
+ Incluye `ActiveCall`, manejo de señalización, y el binario WASM necesario (`lib/assets/wasm/`). Es una función pesada y experimental: úsala solo si tu bot realmente necesita hacer/recibir llamadas.
125
+
126
+ ### 📌 Notas finales
127
+ - Se revisó cuidadosamente cada función nueva contra el código ya existente para no pisar ni duplicar exports (por ejemplo, `BufferJSON` y los tipos de resaltado de código se reutilizan de los archivos que ya tenías, en vez de crear una segunda copia).
128
+ - Las funciones marcadas arriba con ejemplo de código ya están 100% cableadas y listas para usar; el resto se documentará con más ejemplos en la próxima revisión.
129
+ - Los archivos `anti-ban.js`, `smart-reconnect.js`, `message-queue.js`, `enhanced-cache.js`, `enhanced-logger.js`, `bot-utils.js`, `banner.js`, `rich-message-utils.js` y `use-sqlite-auth-state.js` se distribuyen por ahora solo en JavaScript (igual que en el fork de origen); los tipos de TypeScript para estos módulos llegarán en una futura actualización.
81
130
 
82
131
  ---
83
132
 
@@ -412,6 +461,253 @@ export default handler
412
461
 
413
462
  ---
414
463
 
464
+ ## 🌐 HTML embebido en WhatsApp *(nuevo en v7.1.0)*
465
+
466
+ WhatsApp expone un renderer HTML interno (diseñado originalmente para Meta AI)
467
+ accesible vía el campo opaco `unifiedResponse.data` de `AIRichResponseMessage`.
468
+ Cuando el JSON embebido contiene un `__typename: "GenAIaeacdsnwHtmlPrimitive"`,
469
+ el cliente levanta un **WebView sandboxed dentro del bocadillo del mensaje** y
470
+ renderiza el HTML+JS indicado en `payload`, con permiso de red limitado a los
471
+ dominios listados en `trusted_sources`.
472
+
473
+ Este fork expone esa capacidad como API de primer nivel:
474
+
475
+ ### `sock.sendHtml` — envía un WebView dentro del chat
476
+
477
+ ```javascript
478
+ await sock.sendHtml(
479
+ jid,
480
+ html, // string con <style>, <body>, <script>
481
+ trustedSources, // ["api.tuyo.com"] ← dominios permitidos para fetch
482
+ quoted, // mensaje a responder (opcional)
483
+ { headerText, footer } // opciones (opcional)
484
+ )
485
+ ```
486
+
487
+ O construí el mensaje por tu cuenta con `generateHtmlContent` (exportado desde
488
+ `@nyxthor-dev/baileys`) y mandalo con `relayMessage` si querés más control.
489
+
490
+ ### Ejemplo mínimo
491
+
492
+ ```javascript
493
+ const html = `
494
+ <body style="margin:0;font-family:sans-serif">
495
+ <h1 style="color:#a3e635">¡Hola desde el WebView!</h1>
496
+ <p>Esto se renderiza dentro del bocadillo de WhatsApp.</p>
497
+ </body>
498
+ `;
499
+ await sock.sendHtml(jid, html, [], msg);
500
+ ```
501
+
502
+ ### ⚠️ Limitaciones estructurales (importante)
503
+
504
+ El WebView tiene 4 restricciones que **no se pueden evitar desde el lado del
505
+ HTML**. El patrón recomendado para resolverlas es mover la lógica a un backend
506
+ HTTP (ver `examples/html-dynamic/` para un demo completo):
507
+
508
+ | Limitación | Qué NO hacer | Patrón recomendado |
509
+ |---|---|---|
510
+ | El WebView es efímero: `localStorage` a menudo se borra al cerrar el chat | Confiar en `localStorage` como única persistencia | Mover la persistencia a un backend HTTP en `trusted_sources` |
511
+ | No existe puente HTML → bot (`window.WhatsApp.postMessage` no existe) | Esperar callbacks automáticos al bot | El HTML hace `fetch` a tu API, y tu API llama `sock.sendMessage(...)` |
512
+ | `fetch()` solo anda hacia dominios listados en `trusted_sources` | Hacer `fetch` a dominios arbitrarios | Listar todos los dominios necesarios al llamar `sendHtml` |
513
+ | El HTML no recibe identidad del usuario automáticamente | Generar el mismo HTML para todos los usuarios | Inyectar `window.__INITIAL__ = { jid, token, ... }` al renderizar |
514
+
515
+ ### Patrón dinámico con estado persistente
516
+
517
+ ```javascript
518
+ // En tu comando del bot:
519
+ const best = await db.scores.get(senderJid); // 1. leer estado
520
+ const token = issueJwt(senderJid, { expiresIn: '5m' }); // 2. firmar identidad
521
+
522
+ let html = readFileSync('game.html', 'utf8');
523
+ const init = JSON.stringify({ jid: senderJid, best, token, apiBase });
524
+ html = html.replace('</body>',
525
+ `<script>window.__INITIAL__ = ${init};</script></body>`);
526
+
527
+ await sock.sendHtml(jid, html, ['api.tuyo.com'], msg, {
528
+ headerText: '🎮 Mini-juego con estado persistente',
529
+ });
530
+ ```
531
+
532
+ ```javascript
533
+ // Dentro del HTML (game.html):
534
+ async function saveScore(score) {
535
+ await fetch(INIT.apiBase + '/score', {
536
+ method: 'POST',
537
+ headers: { 'Authorization': 'Bearer ' + INIT.token,
538
+ 'Content-Type': 'application/json' },
539
+ body: JSON.stringify({ score })
540
+ });
541
+ }
542
+ ```
543
+
544
+ ```javascript
545
+ // En tu backend (Express):
546
+ app.post('/score', authMiddleware, async (req, res) => {
547
+ const { jid } = verifyJwt(req.headers.authorization); // <- identidad del JWT
548
+ const { score } = req.body;
549
+ await db.query('INSERT INTO scores ... ON CONFLICT ...', [jid, score]);
550
+ res.json({ ok: true });
551
+ });
552
+ ```
553
+
554
+ Ver **`examples/html-dynamic/`** para un demo completo y funcional con SQLite.
555
+
556
+ ### Anti-patrones (qué NO hacer)
557
+
558
+ - ❌ Usar `forwardOrigin = META_AI` para broadcast masivo — riesgo de ban.
559
+ - ❌ Enviar HTML > 50KB — puede truncarse.
560
+ - ❌ Confiar en `localStorage` para persistencia entre sesiones.
561
+ - ❌ Hacer `fetch` a dominios fuera de `trusted_sources`.
562
+ - ❌ Generar HTML sin identidad de usuario (no sabrás quién interactúa).
563
+ - ❌ Exponer tokens en texto plano dentro del HTML sin expiración corta.
564
+
565
+ ### ⚠️ Advertencias
566
+
567
+ - Esta capacidad **no es oficial** y **no está documentada** por Meta. Puede
568
+ romperse en cualquier update del cliente de WhatsApp.
569
+ - El renderer depende de `forwardOrigin = META_AI` + `forwardedAiBotMessageInfo`,
570
+ que es una **impersonación** de un mensaje de Meta AI. Usalo en chats propios
571
+ o privados, no en broadcast.
572
+ - Probá siempre en Android, iOS y WhatsApp Web — los tres WebViews tienen
573
+ comportamientos distintos.
574
+
575
+ ---
576
+
577
+ ## 📊 Mensajes Enriquecidos (Tablas, Código, Links, LaTeX)
578
+
579
+ Estas funciones ya vienen integradas en el fork (heredadas de la fusión con el fork beta) — aquí quedan documentadas con ejemplos reales.
580
+
581
+ ```javascript
582
+ // Tabla (formato clásico)
583
+ await sock.sendTable(
584
+ jid,
585
+ 'Precios',
586
+ ['Producto', 'Precio'],
587
+ [['Plan A', '$10'], ['Plan B', '$20']],
588
+ quotedMsg,
589
+ { headerText: 'Nuestros planes', footer: 'Precios en USD' }
590
+ )
591
+
592
+ // Tabla V2 (respuesta unificada tipo "AI Rich")
593
+ await sock.sendTableV2(jid, tablaObjeto, quotedMsg, { title: 'Precios' })
594
+
595
+ // Lista simple
596
+ await sock.sendList(jid, 'Tareas', ['Comprar pan', 'Pagar luz'], quotedMsg)
597
+
598
+ // Bloque de código
599
+ await sock.sendCodeBlock(jid, 'console.log("hola")', quotedMsg, {
600
+ language: 'javascript',
601
+ title: 'Ejemplo'
602
+ })
603
+
604
+ // Bloque de código V2 (unified response)
605
+ await sock.sendCodeBlockV2(jid, 'SELECT * FROM users;', quotedMsg, { language: 'sql' })
606
+
607
+ // Texto con links enriquecidos (embeds inline)
608
+ await sock.sendLink(jid, 'Mira esto: ', [
609
+ { url: 'https://github.com/Fer2809fl/Bail', displayName: 'Repo en GitHub' }
610
+ ], quotedMsg)
611
+
612
+ // LaTeX (fórmulas)
613
+ await sock.sendLatex(quotedMsg, { formula: 'E = mc^2' })
614
+ ```
615
+
616
+ ## 🎠 Carruseles y 🖼️ Álbumes
617
+
618
+ **Carrusel** — se envía como un `interactiveMessage` con `carouselMessage`, cada tarjeta puede llevar imagen/video y sus propios botones nativos:
619
+
620
+ ```javascript
621
+ await sock.sendMessage(jid, {
622
+ interactiveMessage: {
623
+ body: { text: 'Elegí un producto' },
624
+ footer: { text: 'Catálogo 2026' },
625
+ carouselMessage: {
626
+ cards: [
627
+ {
628
+ header: { title: 'Producto 1', imageMessage: 'https://.../foto1.jpg' },
629
+ body: { text: 'Descripción del producto 1' },
630
+ nativeFlowMessage: { buttons: [/* botones nativos, ver sección de Botones */] }
631
+ },
632
+ {
633
+ header: { title: 'Producto 2', videoMessage: 'https://.../video2.mp4' },
634
+ body: { text: 'Descripción del producto 2' }
635
+ }
636
+ ]
637
+ }
638
+ }
639
+ })
640
+ ```
641
+
642
+ **Álbum** — varias imágenes/videos agrupados en un mismo "paquete" visual (como el álbum nativo de WhatsApp):
643
+
644
+ ```javascript
645
+ await sock.sendMessage(jid, {
646
+ album: [
647
+ { image: { url: './foto1.jpg' }, caption: 'Foto 1' },
648
+ { image: { url: './foto2.jpg' } },
649
+ { video: { url: './video1.mp4' } }
650
+ ]
651
+ })
652
+ ```
653
+
654
+ > Ambas funciones viven en `Socket/dugong.js` (el despachador interno que detecta el tipo de contenido especial que le mandás a `sock.sendMessage`) y ya estaban portadas desde la fusión con el fork beta — lo que faltaba era este ejemplo en el README.
655
+
656
+ ---
657
+
658
+ ## 📰 Newsletters / Canales
659
+
660
+ Todo el manejo de canales (newsletters) de WhatsApp ya está integrado en `Socket/newsletter.js`. Resumen de las funciones disponibles en `sock`:
661
+
662
+ ```javascript
663
+ // Crear un canal
664
+ const canal = await sock.newsletterCreate('Mi Canal', 'Descripción del canal')
665
+
666
+ // Seguir / dejar de seguir / silenciar / activar notificaciones
667
+ await sock.newsletterAction(jid, 'follow') // seguir
668
+ await sock.newsletterAction(jid, 'unfollow') // dejar de seguir
669
+ await sock.newsletterAction(jid, 'mute') // silenciar
670
+ await sock.newsletterAction(jid, 'unmute') // reactivar notificaciones
671
+
672
+ // Seguir varios canales de una (separados por espacio en un solo string)
673
+ await sock.newsletterMultipleFollow('120363...@newsletter 120363...@newsletter')
674
+
675
+ // Ver todos los canales a los que estás suscrito
676
+ const misCanales = await sock.newsletterFetchAllSubscribe()
677
+
678
+ // Obtener metadata de un canal por su JID o por su código de invitación
679
+ const meta = await sock.newsletterMetadata('invite', 'codigoDeInvitacion')
680
+ // o, a partir de un link https://whatsapp.com/channel/xxxx o wa.me/channel/xxxx:
681
+ const metaPorLink = await sock.cekIDSaluran('https://whatsapp.com/channel/xxxxxxxx')
682
+
683
+ // Editar (nombre, descripción, foto)
684
+ await sock.newsletterUpdateName(jid, 'Nuevo nombre')
685
+ await sock.newsletterUpdateDescription(jid, 'Nueva descripción')
686
+ await sock.newsletterUpdatePicture(jid, fotoBuffer)
687
+ await sock.newsletterRemovePicture(jid)
688
+
689
+ // Administración
690
+ await sock.newsletterSubscribers(jid) // cantidad/lista de suscriptores
691
+ await sock.newsletterAdminCount(jid) // cantidad de admins
692
+ await sock.newsletterChangeOwner(jid, nuevoOwnerJid)
693
+ await sock.newsletterDemote(jid, userJid)
694
+ await sock.newsletterDelete(jid)
695
+
696
+ // Mensajes del canal
697
+ await sock.newsletterFetchMessages(jid, 20) // últimos 20 mensajes
698
+ await sock.newsletterReactMessage(jid, serverId, '❤️')
699
+ ```
700
+
701
+ **Enviar un mensaje a un canal** es igual que a cualquier chat, usando el JID del canal (termina en `@newsletter`):
702
+
703
+ ```javascript
704
+ await sock.sendMessage(canalJid, { text: 'Novedades de hoy 🎉' })
705
+ ```
706
+
707
+ > Nota de mantenimiento (heredada de v7.0.4): WhatsApp movió los endpoints internos de `follow`/`unfollow` a una versión `_v2`; este fork ya usa los IDs de consulta vigentes, así que el seguimiento de canales no debería fallar por IDs vencidos.
708
+
709
+ ---
710
+
415
711
  ## ✨ Características
416
712
 
417
713
  ### General
@@ -419,6 +715,7 @@ export default handler
419
715
  - 📸 Mensajes multimedia (imágenes, video, audio, documentos)
420
716
  - 🔘 **Botones nativos reales, sin imports sueltos** *(v1.9.0)*
421
717
  - 🖼️ **Previsualización automática de links en botones y mensajes** *(v1.9.0)*
718
+ - 🌐 **HTML embebido en WhatsApp con `sock.sendHtml`** *(v7.1.0)* — WebView sandboxed dentro del bocadillo, con patrón documentado para sitios dinámicos + BD
422
719
  - 👥 Soporte para grupos y chats privados
423
720
 
424
721
  ### Técnicas
@@ -2,7 +2,7 @@ import { proto } from "../../WAProto/index.js";
2
2
  import { makeLibSignalRepository } from "../Signal/libsignal.js";
3
3
  import { Browsers } from "../Utils/browser-utils.js";
4
4
  import logger from "../Utils/logger.js";
5
- const version = [2, 3000, 1043857760];
5
+ const version = [2, 3000, 1047406223];
6
6
  export const UNAUTHORIZED_CODES = [401, 403, 419];
7
7
  export const DEFAULT_ORIGIN = "https://web.whatsapp.com";
8
8
  export const CALL_VIDEO_PREFIX = "https://call.whatsapp.com/video/";