@codexverified/baileys 2.10.12 → 2.11.12

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.
package/README.md CHANGED
@@ -1,19 +1,44 @@
1
1
  # @codexverified/baileys
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@codexverified/baileys.svg)](https://www.npmjs.com/package/@codexverified/baileys)
4
+ [![node](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](#at-a-glance)
5
+ [![license](https://img.shields.io/badge/license-MIT-blue.svg)](#license-and-maintenance)
6
+ [![types](https://img.shields.io/badge/types-included-blue)](#at-a-glance)
7
+
3
8
  > A readable, carefully maintained Baileys distribution for building reliable WhatsApp integrations with codexverified/baileys.
4
9
 
5
10
  `@codexverified/baileys` is a Node.js and TypeScript library for creating WhatsApp automations over the Baileys protocol. It provides a socket-oriented API for authentication, messaging, media, interactive content, rich responses, newsletters, groups, communities, business features, account utilities, and carefully documented extensions.
6
11
 
7
12
  The package is maintained by **Codex** under the **CodexVerified** organization. It is intended for developers who want a practical Baileys foundation with familiar interfaces, public TypeScript declarations, readable source code, explicit behavior, and room for carefully tested improvements.
8
13
 
9
- ## At a glance
14
+ ## Table of contents
15
+
16
+ - [At a glance](#at-a-glance)
17
+ - [Installation](#installation)
18
+ - [Quick start](#quick-start)
19
+ - [CommonJS usage](#commonjs-usage)
20
+ - [Core capabilities](#core-capabilities)
21
+ - [Everyday message usage](#everyday-message-usage)
22
+ - [Rich menu example](#rich-menu-example)
23
+ - [Status, grids, tables, and flows](#status-grids-tables-and-flows)
24
+ - [Authentication and deployment guidance](#authentication-and-deployment-guidance)
25
+ - [Development workflow](#development-workflow)
26
+ - [Recent compatibility updates](#recent-compatibility-updates)
27
+ - [About Codex](#about-codex)
28
+ - [Package layout](#package-layout)
29
+ - [Security and responsible use](#security-and-responsible-use)
30
+ - [License and maintenance](#license-and-maintenance)
31
+ - [Compatibility additions](#compatibility-additions)
32
+ - [Comparison references](#comparison-references)
33
+ - [Additional functional compatibility helpers](#additional-functional-compatibility-helpers)
34
+ - [AI generation primitive](#ai-generation-primitive)
10
35
 
11
- This release is version **2.10.12**. It uses ECMAScript modules, supports CommonJS usage where the installed Node.js version permits it, ships public TypeScript declarations, and targets Node.js 20 or newer.
36
+ ## At a glance
12
37
 
13
38
  | Property | Value |
14
39
  | --- | --- |
15
40
  | Package | `@codexverified/baileys` |
16
- | Version | `2.10.12` |
41
+ | Version | `2.11.12` |
17
42
  | Runtime | Node.js 20 or newer |
18
43
  | Module format | ESM, with CommonJS compatibility where supported |
19
44
  | Type declarations | Included at `lib/index.d.ts` |
@@ -24,30 +49,18 @@ This release is version **2.10.12**. It uses ECMAScript modules, supports Common
24
49
 
25
50
  ## Installation
26
51
 
27
- Install the package from npm when it is published under your organization:
28
-
29
- ```bash
30
- npm install @codexverified/baileys
31
- ```
32
-
33
- To install a local package archive, place the `.tgz` file beside your application and run:
52
+ | Method | Command | Notes |
53
+ | --- | --- | --- |
54
+ | From npm | `npm install @codexverified/baileys` | Standard install when published under your organization |
55
+ | From local archive | `npm install ./codex-baileys-2.11.12.tgz` | Place the `.tgz` beside your application |
56
+ | Source audit (no scripts) | `npm install --ignore-scripts` | Skips install hooks for local review |
34
57
 
35
- ```bash
36
- npm install ./codex-baileys-2.10.12.tgz
37
- ```
38
-
39
- Both installation methods use the same import name:
58
+ Both npm and archive installs use the same import name:
40
59
 
41
60
  ```javascript
42
61
  import { makeWASocket } from '@codexverified/baileys'
43
62
  ```
44
63
 
45
- For local source auditing, install dependencies without executing package installation hooks:
46
-
47
- ```bash
48
- npm install --ignore-scripts
49
- ```
50
-
51
64
  ## Quick start
52
65
 
53
66
  The following example creates a socket, stores multi-file authentication credentials, reconnects after an unexpected disconnect, and replies to incoming messages. Keep the session directory private and never commit it to a public repository.
@@ -99,8 +112,6 @@ start().catch(console.error)
99
112
 
100
113
  ## CommonJS usage
101
114
 
102
- For supported Node.js versions, the package can also be loaded through CommonJS:
103
-
104
115
  ```javascript
105
116
  const {
106
117
  makeWASocket,
@@ -112,88 +123,52 @@ If your runtime or bundler does not support this interop path, use the ESM impor
112
123
 
113
124
  ## Core capabilities
114
125
 
115
- ### Connections and authentication
116
-
117
- The socket layer manages WebSocket connection events, reconnect handling, browser identity configuration, pairing-code flows, and connection state transitions. Authentication helpers include multi-file credentials for standard deployments, single-file state for compact setups, SQLite-backed persistence when the optional driver is installed, and cache-manager integrations for applications that need custom persistence.
118
-
119
- ### Messages and conversations
120
-
121
- The message API supports text, mentions, replies, reactions, edits, deletions, forwards, polls, contacts, locations, events, group invitations, quoted messages, disappearing messages, view-once envelopes, and other protocol message types. Message composition is centralized so applications can use the ordinary `sendMessage` flow while opting into advanced structures when required.
122
-
123
- ### Media and albums
124
-
125
- Images, video, audio, documents, stickers, thumbnails, and albums are supported. Media can be prepared from URLs, local files, or buffers according to the upload configuration. Video messages can opt into GIF playback, and the image-processing layer can use an available `sharp`, `@napi-rs/image`, or `jimp` implementation. Album child-message association uses the WhatsApp-compatible wire value.
126
-
127
- ### Interactive content
128
-
129
- The package includes interactive buttons, lists, native flows, hydrated templates, carousel layouts, button grids, and other structured message formats. Interactive identifiers should be stable and unique within the application. Receiving code should handle the possibility that different WhatsApp clients deliver a selected value through different response envelopes.
130
-
131
- ### Rich content and previews
132
-
133
- Rich-response utilities cover code blocks, tables, inline entities, LaTeX-oriented content, link previews, and structured response arrays. Rich previews can fetch a title, description, and image for a URL when the optional dependency and network access are available. Applications should retain a plain-text fallback for clients that do not render rich content.
134
-
135
- ### Rich menus
136
-
137
- The experimental `richMenu` helper builds a structured rich-response envelope with an optional header image, row or carousel cards, stable button identifiers, toast metadata, disclaimers, and a footer action. The package also exposes lower-level preparation utilities for applications that need more control. Rich menus are client-dependent and should be tested against the WhatsApp versions used by the application.
138
-
139
- ### Groups and communities
140
-
141
- Group operations include group creation, participant management, settings, metadata, invites, labels, and community relationships. Community helpers support linked groups and subgroup operations where the connected account and current protocol permit them.
142
-
143
- ### Newsletters and channel operations
144
-
145
- Newsletter utilities cover channel metadata, following and unfollowing, posts, reactions, media, and polls. Following is consumer-controlled: the library does not silently follow a trusted channel, inject a fallback channel identifier, or add an automatic channel pill to generated media. Applications should request newsletter actions explicitly and validate identifiers before sending requests.
146
-
147
- ### Account, business, and privacy tools
148
-
149
- The package includes profile and business helpers, product and catalog operations, privacy controls, username utilities, account-layer and interoperation helpers, status publishing, favorites management, and selected account-management operations. Availability depends on the connected account, WhatsApp rollout, and the permissions associated with that account.
150
-
151
- ### Storage and protocol utilities
152
-
153
- The distribution includes in-memory and ordered-dictionary stores, cache-manager support, authentication persistence, LID and phone-number resolution, event utilities, message normalization, media retry handling, protocol helpers, and TypeScript declarations in `lib/index.d.ts`.
126
+ | Area | What it covers |
127
+ | --- | --- |
128
+ | Connections & authentication | WebSocket connection events, reconnect handling, browser identity configuration, pairing-code flows, connection state transitions |
129
+ | Auth persistence | Multi-file credentials, single-file state, SQLite-backed persistence (optional driver), cache-manager integrations |
130
+ | Messages & conversations | Text, mentions, replies, reactions, edits, deletions, forwards, polls, contacts, locations, events, group invitations, quoted messages, disappearing messages, view-once envelopes |
131
+ | Media & albums | Images, video, audio, documents, stickers, thumbnails, albums; sourced from URLs, local files, or buffers; optional `sharp` / `@napi-rs/image` / `jimp` image processing; GIF-style video playback |
132
+ | Interactive content | Buttons, lists, native flows, hydrated templates, carousel layouts, button grids |
133
+ | Rich content & previews | Code blocks, tables, inline entities, LaTeX-oriented content, link previews, structured response arrays |
134
+ | Rich menus (experimental) | Header image, row/carousel cards, stable button IDs, toast metadata, disclaimers, footer action |
135
+ | Groups & communities | Group creation, participant management, settings, metadata, invites, labels, community/subgroup relationships |
136
+ | Newsletters & channels | Channel metadata, follow/unfollow, posts, reactions, media, polls |
137
+ | Account, business & privacy | Profile/business helpers, product & catalog operations, privacy controls, username utilities, status publishing, favorites management |
138
+ | Storage & protocol utilities | In-memory and ordered-dictionary stores, cache-manager support, LID/phone-number resolution, event utilities, message normalization, media retry handling, TypeScript declarations |
154
139
 
155
140
  ## Everyday message usage
156
141
 
157
- Send a text message with the standard socket method:
142
+ | Message type | Key options | Example |
143
+ | --- | --- | --- |
144
+ | Text | `text` | `sock.sendMessage(jid, { text: '...' })` |
145
+ | Media with caption | `image` / `video` / `audio` / `document`, `caption` | `sock.sendMessage(jid, { image: { url } , caption: '...' })` |
146
+ | GIF-style video | `video`, `gifPlayback: true` | `sock.sendMessage(jid, { video: { url }, gifPlayback: true })` |
147
+ | View-once media | `viewOnce: true` (also `viewOnceV2`, `viewOnceV2Extension`, `spoiler`) | `sock.sendMessage(jid, { image: { url }, viewOnce: true })` |
148
+ | Spoiler / view-once (new) | `mediaSpoilerMode: 'viewOnce' \| 'native'` | see below |
158
149
 
159
150
  ```javascript
160
151
  await sock.sendMessage(jid, {
161
152
  text: 'A message from Codex'
162
153
  })
163
- ```
164
-
165
- Send media with a caption:
166
154
 
167
- ```javascript
168
155
  await sock.sendMessage(jid, {
169
156
  image: { url: './media/photo.jpg' },
170
157
  caption: 'A photo message'
171
158
  })
172
- ```
173
-
174
- Send a video with GIF-style playback enabled:
175
159
 
176
- ```javascript
177
160
  await sock.sendMessage(jid, {
178
161
  video: { url: './media/animation.mp4' },
179
162
  gifPlayback: true,
180
163
  caption: 'Animated media'
181
164
  })
182
- ```
183
165
 
184
- Use the existing explicit view-once options when you want the media to use a view-once envelope:
185
-
186
- ```javascript
187
166
  await sock.sendMessage(jid, {
188
167
  image: { url: './media/private-image.jpg' },
189
168
  caption: 'Open once',
190
169
  viewOnce: true
191
170
  })
192
- ```
193
-
194
- The compatible `mediaSpoilerMode` option provides an additional explicit path. Set it to `viewOnce` for supported image, video, document, or sticker media, or set it to `native` to apply the native spoiler context flag. The option is intentionally opt-in and does not change the default behavior of existing applications.
195
171
 
196
- ```javascript
197
172
  await sock.sendMessage(jid, {
198
173
  video: { url: './media/clip.mp4' },
199
174
  caption: 'View-once video',
@@ -206,11 +181,16 @@ await sock.sendMessage(jid, {
206
181
  })
207
182
  ```
208
183
 
209
- The existing `viewOnce`, `viewOnceV2`, `viewOnceV2Extension`, and `spoiler` options remain supported. When an explicit view-once option is enabled, it takes precedence over `mediaSpoilerMode`.
184
+ `mediaSpoilerMode` is an additional, opt-in path for supported image, video, document, or sticker media:
210
185
 
211
- ## Rich menu example
186
+ | Value | Effect |
187
+ | --- | --- |
188
+ | `viewOnce` | Wraps supported media in a view-once envelope |
189
+ | `native` | Applies the native spoiler context flag |
190
+
191
+ The existing `viewOnce`, `viewOnceV2`, `viewOnceV2Extension`, and `spoiler` options remain supported and take precedence over `mediaSpoilerMode` when explicitly set.
212
192
 
213
- The experimental rich-menu helper accepts a header, card rows or a carousel, stable button IDs, and a footer action:
193
+ ## Rich menu example
214
194
 
215
195
  ```javascript
216
196
  await sock.richMenu(jid, {
@@ -245,9 +225,21 @@ await sock.richMenu(jid, {
245
225
  })
246
226
  ```
247
227
 
228
+ | Rich menu field | Purpose |
229
+ | --- | --- |
230
+ | `header` | Optional title and image shown above the menu |
231
+ | `body.row` / `body.carousel` | Layout mode for the cards |
232
+ | `body.cards` | Rows of stable button IDs and labels |
233
+ | `footer` | Text plus an optional action URL |
234
+
248
235
  ## Status, grids, tables, and flows
249
236
 
250
- The socket also provides helpers for status posts, status mentions, button grids, interactive tables, and WhatsApp flows:
237
+ | Helper | Purpose |
238
+ | --- | --- |
239
+ | `sendStatus` | Post a status update, optionally with mentions via `statusJidList` |
240
+ | `sendRichButtonGrid` | Send a card grid of stable-ID buttons |
241
+ | `sendInteractiveTable` | Send tabular content with headers, rows, and action buttons |
242
+ | `sendWhatsAppFlow` | Launch a published WhatsApp Flow |
251
243
 
252
244
  ```javascript
253
245
  await sock.sendStatus({ text: 'New Codex status' }, {
@@ -287,14 +279,17 @@ These helpers are protocol- and client-dependent. Use graceful fallbacks when an
287
279
 
288
280
  ## Authentication and deployment guidance
289
281
 
290
- Authentication data contains sensitive account credentials. Keep the session directory private, exclude it from version control, and use a dedicated service account or restricted filesystem permissions where possible. Do not place access tokens, private keys, phone numbers, or personal account data in the README, package archive, or a public repository.
291
-
292
- For production deployments, pin dependencies with a lockfile, use a supported Node.js runtime, monitor connection events, handle logout separately from recoverable disconnects, and keep reconnect logic from creating uncontrolled parallel sockets.
282
+ | Practice | Detail |
283
+ | --- | --- |
284
+ | Session privacy | Keep the session directory private and excluded from version control |
285
+ | Access control | Use a dedicated service account or restricted filesystem permissions where possible |
286
+ | Secrets handling | Do not place access tokens, private keys, phone numbers, or personal account data in the README, package archive, or a public repository |
287
+ | Dependency pinning | Pin dependencies with a lockfile for production deployments |
288
+ | Runtime | Use a supported Node.js runtime |
289
+ | Connection handling | Monitor connection events; handle logout separately from recoverable disconnects; avoid uncontrolled parallel sockets on reconnect |
293
290
 
294
291
  ## Development workflow
295
292
 
296
- Run the package tests with:
297
-
298
293
  ```bash
299
294
  npm test
300
295
  ```
@@ -303,33 +298,155 @@ Before submitting changes, validate ESM syntax, CommonJS compatibility where app
303
298
 
304
299
  ## Recent compatibility updates
305
300
 
306
- The current source includes the verified album compatibility correction: album child messages use association type `1`, the compatible child-association wire value, rather than treating the `MEDIA_ALBUM` message category as the association value.
307
-
308
- The source also preserves the package’s explicit view-once implementations and exposes the opt-in `mediaSpoilerMode` path for applications that want either a view-once envelope or a native spoiler context flag without changing existing defaults.
301
+ | Update | Detail |
302
+ | --- | --- |
303
+ | Album association fix | Album child messages use association type `1`, the compatible child-association wire value, rather than treating the `MEDIA_ALBUM` message category as the association value |
304
+ | View-once preserved | Explicit view-once implementations remain unchanged |
305
+ | `mediaSpoilerMode` | New opt-in path for a view-once envelope or native spoiler flag, without altering existing defaults |
309
306
 
310
307
  ## About Codex
311
308
 
312
309
  This package is built and maintained by **Codex**, also known as **Dev Codex**. Codex is a developer from Nigeria who focuses on practical, accessible, and reliable software projects across the JavaScript and TypeScript ecosystem.
313
310
 
314
- Codex works with JavaScript, HTML, TypeScript, Node.js, GitHub, Baileys, APIs, key-value stores, and related developer tools. Projects include application development, websites, WhatsApp bots, Telegram bots, API endpoints, and games.
315
-
316
- The developer’s work is driven by a commitment to learning, experimentation, clear documentation, and useful software that developers can understand and extend. This package reflects that commitment through its readable source, public declarations, practical examples, and emphasis on responsible automation.
311
+ | | |
312
+ | --- | --- |
313
+ | Tech stack | JavaScript, HTML, TypeScript, Node.js, GitHub, Baileys, APIs, key-value stores |
314
+ | Project types | Application development, websites, WhatsApp bots, Telegram bots, API endpoints, games |
315
+ | Telegram | [@codexverified](https://t.me/codexverified) |
316
+ | Email | codexauthorized@gmail.com |
317
317
 
318
- For updates and direct contact, connect with Codex on Telegram at [@codexverified](https://t.me/codexverified).
319
- Email: codexauthorized@gmail.com
318
+ The developer's work is driven by a commitment to learning, experimentation, clear documentation, and useful software that developers can understand and extend. This package reflects that commitment through its readable source, public declarations, practical examples, and emphasis on responsible automation.
320
319
 
321
320
  ## Package layout
322
321
 
323
- The `lib/` directory contains the JavaScript implementation, supporting utilities, and public TypeScript declarations. `WAProto/` contains generated WhatsApp protocol definitions. `engine-requirements.js` performs installation-time runtime checks. `package.json` contains package metadata, scripts, dependencies, and exports. This `README.md` is the user-facing installation and usage guide.
322
+ | Path | Contents |
323
+ | --- | --- |
324
+ | `lib/` | JavaScript implementation, supporting utilities, public TypeScript declarations |
325
+ | `WAProto/` | Generated WhatsApp protocol definitions |
326
+ | `engine-requirements.js` | Installation-time runtime checks |
327
+ | `package.json` | Package metadata, scripts, dependencies, exports |
328
+ | `README.md` | User-facing installation and usage guide |
324
329
 
325
330
  ## Security and responsible use
326
331
 
327
- This library interacts with WhatsApp accounts and user communications. Use it only with accounts and data you are authorized to control. Respect WhatsApp’s terms, applicable law, and the privacy expectations of message participants. Avoid unsolicited messaging, protect authentication state, limit access to stored media, and provide clear notice when an application performs automated actions.
332
+ This library interacts with WhatsApp accounts and user communications.
328
333
 
329
- Never commit session files, access tokens, private keys, phone numbers, or other personal information to a public repository. Review installation scripts and optional dependencies before deploying to production, and use pinned dependency versions for repeatable builds.
334
+ | Guideline | Detail |
335
+ | --- | --- |
336
+ | Authorization | Use only with accounts and data you are authorized to control |
337
+ | Compliance | Respect WhatsApp's terms, applicable law, and message participants' privacy expectations |
338
+ | Messaging conduct | Avoid unsolicited messaging |
339
+ | Credential safety | Protect authentication state and never commit session files, tokens, private keys, or personal data to a public repository |
340
+ | Media access | Limit access to stored media |
341
+ | Transparency | Provide clear notice when an application performs automated actions |
342
+ | Dependency review | Review installation scripts and optional dependencies before deploying to production; use pinned versions for repeatable builds |
330
343
 
331
344
  ## License and maintenance
332
345
 
333
346
  This distribution is provided under the license declared in `package.json` and the accompanying license file. Review those terms before redistributing or combining this package with third-party code.
334
347
 
335
348
  **@codexverified/baileys is built and maintained by Codex under the CodexVerified organization.** Contributions, bug reports, and carefully documented improvements are welcome through the project repository.
349
+
350
+ ## Compatibility additions
351
+
352
+ The current source includes several independently implemented compatibility helpers identified during comparison with the published upstream package. These additions preserve the Codex package identity and do not copy package-specific attribution enforcement or remote licensing checks.
353
+
354
+ ### Copy-to-clipboard rich response
355
+
356
+ `sendCopyButton` creates a forwarded GenAI-style rich response with a copy-to-clipboard addon action.
357
+
358
+ | Option | Purpose |
359
+ | --- | --- |
360
+ | `text` | The content that gets copied |
361
+ | `label` | Optional visible button text |
362
+ | `alignment` | `END`, `START`, or `CENTER` |
363
+
364
+ ```javascript
365
+ await sock.sendCopyButton(jid, {
366
+ text: 'npm install @codexverified/baileys',
367
+ label: 'Copy install command',
368
+ alignment: 'END'
369
+ })
370
+ ```
371
+
372
+ As with other private or experimental WhatsApp rich-response layouts, clients may fall back to plain rendering or ignore the addon action.
373
+
374
+ ### Slot-machine HTML generator
375
+
376
+ `generateSlotMachineHtml` produces a self-contained five-reel Fruit Bonanza game with adjustable starting credits. It is a standalone HTML payload and performs no network requests.
377
+
378
+ | Option | Purpose |
379
+ | --- | --- |
380
+ | `title` | Display title for the generated page |
381
+ | `startingCredits` | Initial credit balance |
382
+
383
+ ```javascript
384
+ import { generateSlotMachineHtml } from '@codexverified/baileys'
385
+
386
+ const html = generateSlotMachineHtml({
387
+ title: 'Codex Fruit Bonanza',
388
+ startingCredits: 500
389
+ })
390
+ ```
391
+
392
+ The generator does not by itself send HTML through WhatsApp. Applications should only use an HTML-capable message primitive when that primitive is available and authorized for their deployment.
393
+
394
+ ### Optional ban-status checker
395
+
396
+ `checkStatusWA` is an explicit, caller-invoked diagnostic helper. It is never called during installation, socket creation, reconnection, or message sending. The endpoint is configurable, credentials are not embedded, and callers should review the endpoint's terms and privacy implications before sending a phone number.
397
+
398
+ ```javascript
399
+ import { checkStatusWA } from '@codexverified/baileys'
400
+
401
+ const result = await checkStatusWA('+447700900123', {
402
+ diagnostic: true
403
+ })
404
+ console.log(result.status) // active, banned, blocked, not_registered, rate_limited, or unknown
405
+ ```
406
+
407
+ | Status value | Meaning |
408
+ | --- | --- |
409
+ | `active` | Number appears active on WhatsApp |
410
+ | `banned` | Number appears banned |
411
+ | `blocked` | Number appears blocked |
412
+ | `not_registered` | Number is not registered on WhatsApp |
413
+ | `rate_limited` | Check was rate limited |
414
+ | `unknown` | Status could not be determined |
415
+
416
+ This helper is not an anti-ban guarantee, does not bypass enforcement, and should not be used for bulk enumeration or unsolicited checking.
417
+
418
+ ## Comparison references
419
+
420
+ The feature comparison was based on the published package metadata and documentation available from [npm][1] and the independent package analysis page at [Socket][2]. The Codex implementation adds compatible behavior through readable, package-owned code rather than copying upstream-specific integrity, attribution, or remote-verification mechanisms.
421
+
422
+ [1]: https://www.npmjs.com/
423
+ [2]: https://socket.dev/
424
+
425
+ ## Additional functional compatibility helpers
426
+
427
+ The source also exposes portable helpers for native-flow responses, view-once inspection, rich content preparation, HTML payload construction, and website previews. These are functional compatibility APIs only; package-specific identity checks, attribution enforcement, remote license gates, trusted-channel auto-follow behavior, and other ownership structures are not included.
428
+
429
+ | Helper | Purpose |
430
+ | --- | --- |
431
+ | `parseNativeFlowResponse` | Normalize quick-reply, single-select, and Flow response envelopes |
432
+ | `parseWhatsAppFlowResponse` | Return only responses identified as WhatsApp Flow responses |
433
+ | `buildWhatsAppFlowButton` / `makeWhatsAppFlowButton` | Build published Flow button parameters for a caller-owned Flow ID and token |
434
+ | `prepareRichTextMessage` | Build a forwarded rich text response |
435
+ | `prepareRichImageMessage` | Build a forwarded rich image response |
436
+ | `prepareRichLinkMessage` | Build a forwarded response with inline link entities |
437
+ | `prepareRichGenerationMessage` | Build a rich response from caller-provided rich content |
438
+ | `prepareHtmlMessage` | Build an HTML primitive payload for clients that support the experimental structure |
439
+ | `prepareSlotMachineMessage` | Wrap the local slot-machine generator as an HTML message payload |
440
+ | `generateLinkPreviewHtml` / `generateWebsitePreviewHtml` | Create escaped link cards or an explicitly requested metadata preview |
441
+ | `parseViewOnceInfo` and related helpers | Inspect, download, reconstruct, and apply explicit view-once policies |
442
+
443
+ All networked helpers are opt-in. Website previews fetch only when explicitly called, and Flow helpers require credentials and identifiers owned by the application. Experimental WhatsApp layouts remain client-dependent and should always have a plain-text fallback.
444
+
445
+ ## AI generation primitive
446
+
447
+ `buildImaginePrimitive` creates the Meta-style AI image or animation generation-state payload used by rich responses. It is a pure payload builder — it does not call a generation service itself, generate media, or send anything on its own; callers wire it up to whatever AI generation backend they use, then pass the resulting primitive into a rich-response message.
448
+
449
+ | Field | Purpose |
450
+ | --- | --- |
451
+ | `state` | Generation status: `GENERATING`, `COMPLETE`, or `ERROR` |
452
+ | `mediaUrl` | URL of the generated media
@@ -36,7 +36,7 @@ const makeWASocket = (config) => {
36
36
  };
37
37
  console.log(
38
38
  `\n${yellow}${center('CODEX TECHNOLOGY')}${reset}\n` +
39
- `${blue}${center('@codexverified/Baileys')}${reset}\n` +
39
+ `${blue}${center('@codexverified/baileys')}${reset}\n` +
40
40
  `${yellow}${center('premium baileys built by codex')}${reset}\n`
41
41
  );
42
42
  }
@@ -16,7 +16,7 @@ import { collectMetaAIBotParticipantJids, isMetaAIBotResponse, META_AI_BOT_JID }
16
16
  import { makeUsernameSocket } from './username.js';
17
17
 
18
18
  const STATUS_JID = 'status@broadcast';
19
- const normalizeStatusJidList = (value) => {
19
+ export const normalizeStatusJidList = (value) => {
20
20
  if (!Array.isArray(value) || value.length === 0) {
21
21
  throw new Boom('statusJidList must contain at least one recipient JID', { statusCode: 400 });
22
22
  }
@@ -1223,6 +1223,13 @@ export const makeMessagesSocket = (config) => {
1223
1223
  await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata });
1224
1224
  return fullMsg;
1225
1225
  },
1226
+ sendCopyButton: async (jid, content = {}, options = {}) => {
1227
+ const { prepareCopyToClipboardMessage } = await import('../Utils/rich-message-utils.js');
1228
+ const message = prepareCopyToClipboardMessage(content);
1229
+ const fullMsg = await generateWAMessageFromContent(jid, message, { logger, userJid: authState.creds.me?.id, messageId: options.messageId || generateMessageIDV2(authState.creds.me?.id), ...options });
1230
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata });
1231
+ return fullMsg;
1232
+ },
1226
1233
  sendInteractiveTable: async (jid, table, options = {}) => {
1227
1234
  const { title = '', headers = [], rows = [], image, buttons = [], footer } = table || {};
1228
1235
  if (!Array.isArray(headers) || !Array.isArray(rows) || !Array.isArray(buttons)) throw new Boom('sendInteractiveTable expects headers, rows, and buttons arrays', { statusCode: 400 });
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Optional WhatsApp registration-status checker.
3
+ *
4
+ * This module is deliberately opt-in. It does not run during installation,
5
+ * connection setup, or message sending, and it does not contain credentials.
6
+ * Callers should review the endpoint and applicable terms before use.
7
+ */
8
+
9
+ const cleanNumber = (value) => String(value ?? '').replace(/[\s().\-/]/g, '').replace(/^00/, '').replace(/^\+/, '');
10
+
11
+ export const normalizeBanCheckNumber = (value) => {
12
+ const number = cleanNumber(typeof value === 'object' ? value.number : value);
13
+ if (!/^\d{6,15}$/.test(number)) throw new TypeError('number must be an international phone number');
14
+ return `+${number}`;
15
+ };
16
+
17
+ export const checkStatusWA = async (number, options = {}) => {
18
+ const normalized = normalizeBanCheckNumber(number);
19
+ const endpoint = options.endpoint || 'https://v.whatsapp.net/v2/exist';
20
+ const fetchImpl = options.fetch || globalThis.fetch;
21
+ if (typeof fetchImpl !== 'function') throw new TypeError('a fetch implementation is required');
22
+ const url = new URL(endpoint);
23
+ url.searchParams.set('in', normalized.slice(1));
24
+ const response = await fetchImpl(url, {
25
+ method: 'GET',
26
+ headers: { ...(options.headers || {}) },
27
+ signal: options.signal
28
+ });
29
+ let body = null;
30
+ try { body = await response.json(); } catch { body = null; }
31
+ const reason = String(body?.reason || body?.error || body?.status || '').toLowerCase();
32
+ let status = 'unknown';
33
+ if (response.status === 429 || /rate.?limit|too many/.test(reason)) status = 'rate_limited';
34
+ else if (/blocked|official|banned|ban|temporar|perman/.test(reason)) status = /banned|ban|temporar|perman/.test(reason) ? 'banned' : 'blocked';
35
+ else if (/not.?registered|does.?not.?exist/.test(reason)) status = 'not_registered';
36
+ else if (response.ok) status = 'active';
37
+ return {
38
+ number: normalized,
39
+ status,
40
+ isBanned: status === 'banned',
41
+ isNeedOfficialWa: status === 'blocked',
42
+ diagnostics: options.diagnostic === true ? {
43
+ httpStatus: response.status,
44
+ ok: response.ok,
45
+ bodyKeys: body && typeof body === 'object' ? Object.keys(body).sort() : []
46
+ } : undefined
47
+ };
48
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Self-contained, dependency-free slot-machine HTML generator.
3
+ * The generated page is local-only and makes no network requests.
4
+ */
5
+
6
+ const escapeHtml = (value) => String(value ?? '').replace(/[&<>"']/g, (character) => ({
7
+ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;'
8
+ }[character]));
9
+
10
+ export const generateSlotMachineHtml = (options = {}) => {
11
+ const title = escapeHtml(options.title || 'FRUIT BONANZA');
12
+ const startingCredits = Number.isFinite(Number(options.startingCredits)) && Number(options.startingCredits) >= 0
13
+ ? Math.floor(Number(options.startingCredits)) : 500;
14
+ return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style>
15
+ *{box-sizing:border-box}body{margin:0;padding:12px;background:#160704;color:#ffe8a3;font:14px system-ui,sans-serif}.machine{max-width:540px;margin:auto;padding:16px;border:4px solid #e6a139;border-radius:22px;background:linear-gradient(135deg,#230805,#8c3515,#2b0906);box-shadow:0 8px 18px #000a}.title{text-align:center;font-size:24px;font-weight:900;color:#fff2a1;text-shadow:0 2px #8f1c0c}.stats{display:flex;justify-content:space-around;margin:10px 0;padding:8px;border:2px solid #a55c19;border-radius:8px;background:#100303}.reels{display:grid;grid-template-columns:repeat(5,1fr);gap:5px;padding:8px;border:5px solid #9b4e12;border-radius:14px;background:#140604}.reel{height:78px;display:grid;place-items:center;border-radius:6px;background:linear-gradient(#fffce4,#d7bf87);color:#b20f1c;font-size:38px;font-weight:900;overflow:hidden}.reel.spin{animation:spin .16s linear infinite}.message{min-height:30px;margin:10px;text-align:center;font-weight:800}.controls{display:flex;gap:8px}.controls button{flex:1;padding:12px;border:2px solid #351006;border-radius:10px;font-weight:900;cursor:pointer}.bet{background:#1685a5;color:white}.spin{background:#27a93b;color:white}.spin:disabled{opacity:.5}@keyframes spin{50%{transform:translateY(5px);filter:blur(1px)}}small{display:block;margin-top:10px;text-align:center;color:#d6a15b}</style></head><body><main class="machine"><div class="title">${title}</div><div class="stats"><span>Credits <b id="credits">${startingCredits}</b></span><span>Bet <b id="bet">10</b></span><span>Best <b id="best">0</b></span></div><div class="reels">${[0,1,2,3,4].map((index) => `<div class="reel" id="r${index}">🍒</div>`).join('')}</div><div class="message" id="message">SPIN TO PLAY</div><div class="controls"><button class="bet" id="betButton" type="button">BET</button><button class="spin" id="spinButton" type="button">SPIN</button></div><small>Three matching symbols win. This is a local chat-embedded game.</small></main><script>
16
+ (()=>{const symbols=['🍒','🍋','🔔','💎','7️⃣','🅱️'];let credits=${startingCredits},bet=10,best=0,busy=false;const $=id=>document.getElementById(id);const ui=()=>{$('credits').textContent=credits;$('bet').textContent=bet;$('best').textContent=best};$('betButton').onclick=()=>{if(busy)return;bet=bet===10?20:bet===20?50:10;if(bet>credits)bet=10;ui()};$('spinButton').onclick=()=>{if(busy||credits<bet)return;busy=true;credits-=bet;$('message').textContent='GOOD LUCK';ui();const reels=[0,1,2,3,4].map(i=>$('r'+i));reels.forEach(r=>r.classList.add('spin'));setTimeout(()=>{const values=reels.map(r=>{r.classList.remove('spin');const value=symbols[Math.floor(Math.random()*symbols.length)];r.textContent=value;return value});const counts=values.reduce((map,value)=>(map[value]=(map[value]||0)+1,map),{});const match=Math.max(...Object.values(counts));const win=match>=3?bet*(match===5?20:match===4?8:3):0;credits+=win;best=Math.max(best,win);$('message').textContent=win?'WIN +'+win:(credits?'TRY AGAIN':'GAME OVER');busy=false;ui()},700)};ui()})();</script></body></html>`;
17
+ };
18
+
19
+ export default generateSlotMachineHtml;
@@ -32,3 +32,9 @@ export * from './browser-utils.js';
32
32
  export * from './companion-reg-client-utils.js';
33
33
  export * from './identity-change-handler.js';
34
34
  export * from './stanza-ack.js';
35
+ export * from './games/slot-machine.js';
36
+ export * from './ban-checker.js';
37
+ export * from './native-flow.js';
38
+ export * from './view-once-utils.js';
39
+ export * from './website-preview.js';
40
+ export * from './portable-compat.js';
@@ -0,0 +1,48 @@
1
+ const parseJsonObject = (value) => {
2
+ if (!value) return {};
3
+ if (typeof value === 'object') return value;
4
+ try {
5
+ const parsed = JSON.parse(value);
6
+ return parsed && typeof parsed === 'object' ? parsed : {};
7
+ } catch { return {}; }
8
+ };
9
+
10
+ export const parseNativeFlowResponse = (message) => {
11
+ const content = message?.message || message;
12
+ const response = content?.interactiveResponseMessage?.nativeFlowResponseMessage || content?.nativeFlowResponseMessage;
13
+ if (!response) return null;
14
+ const params = parseJsonObject(response.paramsJson);
15
+ const actionPayload = params.flow_action_payload || params.flowActionPayload || {};
16
+ const data = params.data || params.response || params.form_data || params.formData || actionPayload.data || {};
17
+ return {
18
+ name: response.name || '', version: response.version, paramsJson: response.paramsJson || '', params,
19
+ isFlow: response.name === 'galaxy_message' || response.name === 'flow' || Boolean(params.flow_id || params.flow_token || params.flow_message_version),
20
+ flowId: params.flow_id || params.flowId, flowToken: params.flow_token || params.flowToken,
21
+ screen: params.screen || actionPayload.screen, action: params.flow_action || params.flowAction || actionPayload.action,
22
+ actionPayload, data, buttonId: params.id || params.button_id || params.buttonId,
23
+ displayText: params.display_text || params.displayText, raw: response
24
+ };
25
+ };
26
+
27
+ export const parseWhatsAppFlowResponse = (message) => {
28
+ const response = parseNativeFlowResponse(message);
29
+ return response?.isFlow ? response : null;
30
+ };
31
+
32
+ export const buildWhatsAppFlowButton = ({ flowId, flowToken, cta = 'Open form', action = 'navigate', actionPayload, mode = 'published', flowMessageVersion = '3', metadata, name = 'galaxy_message' } = {}) => {
33
+ if (!flowId) throw new TypeError('flowId is required to launch a WhatsApp Flow');
34
+ if (!flowToken) throw new TypeError('flowToken is required to launch a WhatsApp Flow');
35
+ return {
36
+ name, flow_message_version: String(flowMessageVersion), flow_token: String(flowToken), flow_id: String(flowId),
37
+ flow_cta: String(cta), flow_action: action,
38
+ ...(actionPayload ? { flow_action_payload: actionPayload } : {}),
39
+ ...(metadata ? { flow_metadata: metadata } : {}),
40
+ ...(mode ? { flow_mode: String(mode) } : {})
41
+ };
42
+ };
43
+
44
+ export const makeWhatsAppFlowButton = (flow) => ({
45
+ name: flow?.nativeFlowName || 'galaxy_message',
46
+ buttonParamsJson: JSON.stringify(buildWhatsAppFlowButton(flow))
47
+ });
48
+
@@ -0,0 +1,12 @@
1
+ import { generateRichMenuContent } from './message-composer.js';
2
+ import { prepareRichResponseMessage } from './rich-message-utils.js';
3
+
4
+ /** Build a prepared rich-menu payload for direct message generation. */
5
+ export const prepareRichMenuMessage = (content = {}, quoted, options = {}) => generateRichMenuContent(content, quoted, options);
6
+
7
+ /** Convert unsupported premium content to a safe plain-text rich response. */
8
+ export const downgradePremiumContent = (content = {}) => {
9
+ if (typeof content === 'string') return prepareRichResponseMessage({ contentText: content, noDonation: true });
10
+ const text = content.text || content.contentText || content.caption || '';
11
+ return prepareRichResponseMessage({ contentText: String(text), noDonation: true });
12
+ };
@@ -299,7 +299,7 @@ export const prepareRichResponseMessage = (content) => {
299
299
  const defaultDonationLink = {
300
300
  text: '',
301
301
  url: DONATE_URL,
302
- title: 'PAIR CRYSNVA AI :',
302
+ title: 'PAIR CODEX AI :',
303
303
  displayName: 'pair bot'
304
304
  };
305
305
  const resolvedLinks = noDonation ? links : [...(links || []), defaultDonationLink];
@@ -436,4 +436,110 @@ export const wrapToBotForwardedMessage = (richResponseMessage) => ({
436
436
  message: { richResponseMessage }
437
437
  }
438
438
  });
439
- //# sourceMappingURL=rich-message-utils.js.map
439
+ //# sourceMappingURL=rich-message-utils.js.map
440
+
441
+ /**
442
+ * Build a forwarded rich response with an inline copy-to-clipboard action.
443
+ * The payload follows WhatsApp's GenAI addon-action layout and is opt-in.
444
+ * @param {{text?: string, label?: string, alignment?: 'END'|'START'|'CENTER'}} options
445
+ * @returns {{messageContextInfo: object, botForwardedMessage: object}}
446
+ */
447
+ export const prepareCopyToClipboardMessage = (options = {}) => {
448
+ const text = String(options.text ?? '');
449
+ const label = String(options.label ?? text);
450
+ const alignment = ['END', 'START', 'CENTER'].includes(options.alignment) ? options.alignment : 'END';
451
+ const unified = {
452
+ response_id: randomUUID(),
453
+ sections: [{
454
+ __typename: 'GenAIUnifiedResponseSection',
455
+ view_model: {
456
+ __typename: 'GenAIAddonActionLayoutViewModel',
457
+ addon_action_type: 'COPY_TO_CLIPBOARD',
458
+ addon_action_alignment: alignment,
459
+ primitives: [{
460
+ __typename: 'GenAIMarkdownTextUXPrimitive',
461
+ text: label,
462
+ inline_entities: []
463
+ }]
464
+ }
465
+ }]
466
+ };
467
+ const richResponseMessage = proto.AIRichResponseMessage.create({
468
+ submessages: [],
469
+ messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
470
+ unifiedResponse: { data: Buffer.from(JSON.stringify(unified)) },
471
+ contextInfo: { isForwarded: true, forwardingScore: 1, forwardOrigin: 4 }
472
+ });
473
+ return wrapToBotForwardedMessage(richResponseMessage);
474
+ };
475
+
476
+ /** Build a plain rich-text forwarded response. */
477
+ export const prepareRichTextMessage = ({ text = '' } = {}) => prepareRichResponseMessage({ contentText: String(text), noDonation: true });
478
+
479
+ /** Build a rich image forwarded response using a GenAI image primitive. */
480
+ export const prepareRichImageMessage = ({ url = '', mimeType = 'image/png' } = {}) => {
481
+ const media = { __typename: 'GenAIMediaItem', mime_type: mimeType, url: String(url), url_fallback: String(url) };
482
+ const unified = { response_id: randomUUID(), sections: [{ __typename: 'GenAIUnifiedResponseSection', view_model: { __typename: 'GenAISingleLayoutViewModel', primitive: { __typename: 'GenAIImagePrimitive', preview_image: media, full_image: media } } }] };
483
+ const rich = proto.AIRichResponseMessage.create({ submessages: [], messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD, unifiedResponse: { data: Buffer.from(JSON.stringify(unified)) }, contextInfo: { isForwarded: true, forwardingScore: 1, forwardOrigin: 4 } });
484
+ return wrapToBotForwardedMessage(rich);
485
+ };
486
+
487
+ /** Build a rich response containing clickable inline links. */
488
+ export const prepareRichLinkMessage = ({ links = [], text = '' }= {}) => {
489
+ const entities = [];
490
+ let combined = '';
491
+ for (const [index, link] of links.entries()) {
492
+ const key = `INLINE_HYPERLINK_${index}`;
493
+ const display = String(link?.text || link?.displayName || link?.url || '');
494
+ combined += `{{${key}}}${display}{{/${key}}}`;
495
+ entities.push({ key, metadata: { display_name: display, is_trusted: link?.isTrusted !== false, url: String(link?.url || ''), __typename: 'GenAIInlineLinkItem' } });
496
+ }
497
+ return prepareRichResponseMessage({ contentText: combined || String(text), links: [], noDonation: true, noHeading: true, richResponse: [{ text: combined || String(text), inlineEntities: entities }] });
498
+ };
499
+
500
+ /** Build a rich-generation response from existing rich-response content. */
501
+ export const prepareRichGenerationMessage = (content = {}) => prepareRichResponseMessage({ ...content, noDonation: true });
502
+
503
+ /** Build an HTML primitive payload. Use only with an HTML-capable, authorized client. */
504
+ export const prepareHtmlMessage = ({ html = '' } = {}) => {
505
+ const unified = { response_id: randomUUID(), sections: [{ view_model: { primitive: { __typename: 'FOAHtmlPrimitiveDemoDONOTUSE', html: String(html) }, __typename: 'GenAISingleLayoutViewModel' } }] };
506
+ const rich = proto.AIRichResponseMessage.create({ submessages: [], messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD, unifiedResponse: { data: Buffer.from(JSON.stringify(unified)) }, contextInfo: { isForwarded: true, forwardingScore: 1, forwardOrigin: 4 } });
507
+ return wrapToBotForwardedMessage(rich);
508
+ };
509
+
510
+ /** Convenience wrapper for a slot-machine HTML message payload. */
511
+ export const prepareSlotMachineMessage = async (options = {}) => {
512
+ const { generateSlotMachineHtml } = await import('./games/slot-machine.js');
513
+ return prepareHtmlMessage({ html: generateSlotMachineHtml(options) });
514
+ };
515
+
516
+ /**
517
+ * Build a Meta-style AI image/video generation primitive.
518
+ * The payload is useful for displaying generation progress without making any
519
+ * network request or enabling a hidden background process.
520
+ */
521
+ export const buildImaginePrimitive = ({
522
+ mediaType = 'video',
523
+ url = '',
524
+ thumbnail,
525
+ mimeType,
526
+ fileLength = 0,
527
+ duration = 0,
528
+ status = 'GENERATING',
529
+ estimatedMs,
530
+ imagineType
531
+ } = {}) => {
532
+ const normalizedType = String(mediaType).toLowerCase() === 'image' ? 'IMAGE' : 'ANIMATE';
533
+ return {
534
+ __typename: 'GenAIImaginePrimitive',
535
+ media_type: normalizedType,
536
+ imagine_type: imagineType || normalizedType,
537
+ status: String(status),
538
+ ...(url ? { url: String(url), url_fallback: String(url) } : {}),
539
+ ...(thumbnail ? { thumbnail_url: String(thumbnail) } : {}),
540
+ ...(mimeType ? { mime_type: String(mimeType) } : {}),
541
+ ...(fileLength ? { file_length: Number(fileLength) } : {}),
542
+ ...(duration ? { duration: Number(duration) } : {}),
543
+ ...(estimatedMs !== undefined ? { estimated_ms: Number(estimatedMs) } : {})
544
+ };
545
+ };
@@ -0,0 +1,56 @@
1
+ import { downloadContentFromMessage } from './messages-media.js';
2
+
3
+ export const isViewOnceMessage = (message) => Boolean(message?.message?.viewOnceMessage || message?.message?.viewOnceMessageV2 || message?.message?.viewOnceMessageV2Extension || message?.viewOnceMessage || message?.viewOnceMessageV2 || message?.viewOnceMessageV2Extension);
4
+
5
+ export const extractViewOnceContent = (message) => {
6
+ const content = message?.message || message;
7
+ return content?.viewOnceMessage?.message || content?.viewOnceMessageV2?.message || content?.viewOnceMessageV2Extension?.message || null;
8
+ };
9
+
10
+ export const getViewOnceMediaType = (message) => {
11
+ const content = extractViewOnceContent(message);
12
+ if (!content) return null;
13
+ for (const type of ['image', 'video', 'audio', 'document', 'sticker']) if (content[`${type}Message`]) return type;
14
+ return null;
15
+ };
16
+
17
+ export const getViewOnceMediaContent = (message) => {
18
+ const content = extractViewOnceContent(message);
19
+ if (!content) return null;
20
+ return content.imageMessage || content.videoMessage || content.audioMessage || content.documentMessage || content.stickerMessage || null;
21
+ };
22
+
23
+ export const downloadViewOnceMedia = async (message, options = {}) => {
24
+ const media = getViewOnceMediaContent(message);
25
+ const type = getViewOnceMediaType(message);
26
+ if (!media || !type) throw new Error('No supported media content found in view-once message');
27
+ const stream = await downloadContentFromMessage(media, type, options);
28
+ const chunks = [];
29
+ for await (const chunk of stream) chunks.push(chunk);
30
+ return Buffer.concat(chunks);
31
+ };
32
+
33
+ export const createRegularMessageFromViewOnce = (originalMessage, mediaBuffer) => {
34
+ const media = getViewOnceMediaContent(originalMessage);
35
+ const type = getViewOnceMediaType(originalMessage);
36
+ if (!media || !type) return null;
37
+ return {
38
+ key: originalMessage.key, messageTimestamp: originalMessage.messageTimestamp,
39
+ pushName: originalMessage.pushName, participant: originalMessage.participant,
40
+ decryptedMedia: { type, buffer: mediaBuffer, mimeType: media.mimetype, fileName: media.fileName, caption: media.caption, fileLength: media.fileLength },
41
+ originalViewOnceMessage: originalMessage.message
42
+ };
43
+ };
44
+
45
+ export const shouldAutoDecryptViewOnce = (message, config = {}) => isViewOnceMessage(message) && config.autoVV !== false && message.key?.fromMe !== true;
46
+ export const shouldDeleteViewOnce = (message, config = {}) => isViewOnceMessage(message) && config.antiVV !== false && message.key?.fromMe !== true;
47
+
48
+ export const parseViewOnceInfo = (message) => {
49
+ const media = getViewOnceMediaContent(message);
50
+ return {
51
+ isViewOnce: isViewOnceMessage(message), mediaType: getViewOnceMediaType(message), mimeType: media?.mimetype,
52
+ fileName: media?.fileName, caption: media?.caption, fileLength: media?.fileLength,
53
+ hasUrl: Boolean(media?.url), hasDirectPath: Boolean(media?.directPath), hasMediaKey: Boolean(media?.mediaKey)
54
+ };
55
+ };
56
+
@@ -0,0 +1,27 @@
1
+ const escapeHtml = (value) => String(value ?? '').replace(/[&<>"']/g, (character) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[character]));
2
+
3
+ const validateUrl = (value) => {
4
+ const parsed = new URL(value);
5
+ if (!['http:', 'https:'].includes(parsed.protocol)) throw new TypeError('only HTTP(S) preview URLs are supported');
6
+ return parsed;
7
+ };
8
+
9
+ export const generateLinkPreviewHtml = (url, options = {}) => {
10
+ const parsed = validateUrl(url);
11
+ const title = options.title || parsed.hostname;
12
+ const description = options.description || `Open ${parsed.hostname}`;
13
+ const image = options.image ? `<img src="${escapeHtml(options.image)}" alt="" loading="lazy">` : '<div class="placeholder">🌐</div>';
14
+ return `<!doctype html><html><head><meta charset="utf-8"><style>body{margin:0;background:transparent;font:14px system-ui,sans-serif}.card{overflow:hidden;border:1px solid #333;border-radius:12px;background:#1a1a2e;color:#fff}.card img,.placeholder{display:block;width:100%;height:160px;object-fit:cover}.placeholder{display:grid;place-items:center;font-size:48px;background:linear-gradient(135deg,#1a1a2e,#2d2d44)}.body{padding:14px}.title{font-weight:700;margin-bottom:5px}.desc{color:#bbb;line-height:1.4}.url{margin-top:8px;color:#55c878;font-size:11px}</style></head><body><a href="${escapeHtml(parsed.href)}" target="_blank" rel="noopener noreferrer" style="text-decoration:none"><div class="card">${image}<div class="body"><div class="title">${escapeHtml(title)}</div><div class="desc">${escapeHtml(description)}</div><div class="url">${escapeHtml(parsed.hostname)}</div></div></div></a></body></html>`;
15
+ };
16
+
17
+ export const generateWebsitePreviewHtml = async (url, options = {}) => {
18
+ const parsed = validateUrl(url);
19
+ const response = await (options.fetch || globalThis.fetch)(parsed.href, { signal: options.signal, headers: options.headers || {} });
20
+ if (!response?.ok) throw new Error(`website preview request failed with status ${response?.status ?? 'unknown'}`);
21
+ const html = await response.text();
22
+ const title = html.match(/<title[^>]*>([^<]*)<\/title>/i)?.[1] || parsed.hostname;
23
+ const description = html.match(/<meta[^>]+name=["']description["'][^>]+content=["']([^"']*)["']/i)?.[1] || `Preview of ${parsed.hostname}`;
24
+ return generateLinkPreviewHtml(parsed.href, { ...options, title, description });
25
+ };
26
+
27
+ export default generateWebsitePreviewHtml;
package/lib/index.d.ts CHANGED
@@ -259,6 +259,8 @@ export interface WASocket {
259
259
  richMenu(jid: string, content?: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
260
260
  /** Send a rich button-card grid. */
261
261
  sendRichButtonGrid(jid: string, grid: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
262
+ /** Send a GenAI-style inline copy-to-clipboard rich response. */
263
+ sendCopyButton(jid: string, content: { text: string; label?: string; alignment?: 'END' | 'START' | 'CENTER' }, options?: Record<string, unknown>): Promise<unknown>;
262
264
  /** Send a markdown-style interactive table with buttons. */
263
265
  sendInteractiveTable(jid: string, table: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
264
266
  /** Send a WhatsApp native flow button. */
@@ -293,6 +295,37 @@ export declare function makeCacheManagerAuthState(store: CacheManagerStore, sess
293
295
  saveCreds: () => Promise<void>;
294
296
  }>;
295
297
 
298
+ /** Generate a self-contained local slot-machine HTML payload. */
299
+ export declare function generateSlotMachineHtml(options?: { title?: string; startingCredits?: number }): string;
300
+ export declare function buildImaginePrimitive(options?: { mediaType?: 'image' | 'video'; url?: string; thumbnail?: string; mimeType?: string; fileLength?: number; duration?: number; status?: string; estimatedMs?: number; imagineType?: string }): Record<string, unknown>;
301
+ export declare function parseNativeFlowResponse(message: unknown): Record<string, unknown> | null;
302
+ export declare function parseWhatsAppFlowResponse(message: unknown): Record<string, unknown> | null;
303
+ export declare function buildWhatsAppFlowButton(flow?: Record<string, unknown>): Record<string, unknown>;
304
+ export declare function makeWhatsAppFlowButton(flow?: Record<string, unknown>): { name: string; buttonParamsJson: string };
305
+ export declare function isViewOnceMessage(message: unknown): boolean;
306
+ export declare function extractViewOnceContent(message: unknown): Record<string, unknown> | null;
307
+ export declare function getViewOnceMediaType(message: unknown): string | null;
308
+ export declare function getViewOnceMediaContent(message: unknown): Record<string, unknown> | null;
309
+ export declare function parseViewOnceInfo(message: unknown): Record<string, unknown>;
310
+ export declare function shouldAutoDecryptViewOnce(message: unknown, config?: Record<string, unknown>): boolean;
311
+ export declare function shouldDeleteViewOnce(message: unknown, config?: Record<string, unknown>): boolean;
312
+ export declare function generateLinkPreviewHtml(url: string, options?: Record<string, unknown>): string;
313
+ export declare function generateWebsitePreviewHtml(url: string, options?: Record<string, unknown>): Promise<string>;
314
+ export declare function prepareRichTextMessage(options?: { text?: string }): Record<string, unknown>;
315
+ export declare function prepareRichImageMessage(options?: { url?: string; mimeType?: string }): Record<string, unknown>;
316
+ export declare function prepareRichLinkMessage(options?: { links?: Array<Record<string, unknown>>; text?: string }): Record<string, unknown>;
317
+ export declare function prepareRichGenerationMessage(content?: Record<string, unknown>): Record<string, unknown>;
318
+ export declare function prepareHtmlMessage(options?: { html?: string }): Record<string, unknown>;
319
+ export declare function prepareSlotMachineMessage(options?: { title?: string; startingCredits?: number }): Promise<Record<string, unknown>>;
320
+ export declare function prepareRichMenuMessage(content?: Record<string, unknown>, quoted?: unknown, options?: Record<string, unknown>): Record<string, unknown>;
321
+ export declare function downgradePremiumContent(content?: unknown): Record<string, unknown>;
322
+
323
+ /** Normalize an international phone number for an explicit status check. */
324
+ export declare function normalizeBanCheckNumber(value: string | { number: string }): string;
325
+
326
+ /** Perform an explicit, caller-configured WhatsApp registration-status check. */
327
+ export declare function checkStatusWA(number: string | { number: string }, options?: { endpoint?: string; fetch?: typeof fetch; headers?: Record<string, string>; signal?: AbortSignal; diagnostic?: boolean }): Promise<{ number: string; status: string; isBanned: boolean; isNeedOfficialWa: boolean; diagnostics?: { httpStatus: number; ok: boolean; bodyKeys: string[] } }>;
328
+
296
329
  /** Wrap a socket with anti-ban protection (from the baileys-antiban bundle). */
297
330
  export declare function wrapSocket(socket: WASocket, config?: unknown): WASocket;
298
331
 
package/lib/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import makeWASocket from './Socket/index.js';
2
+ export { normalizeStatusJidList } from './Socket/messages-send.js';
2
3
  export * from '../WAProto/index.js';
3
4
  export * from './Utils/index.js';
4
5
  export * from './Types/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codexverified/baileys",
3
- "version": "2.10.12",
3
+ "version": "2.11.12",
4
4
  "description": "CODEX TECHNOLOGY a premium Baileys developed and built by Dev Codex, with Meta compositing, bot planning replay, welcome flow, rich messages, interactive messages, albums, and more.",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",