@codexverified/baileys 2.10.11 → 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 +293 -167
- package/lib/Socket/index.js +1 -1
- package/lib/Socket/messages-send.js +11 -3
- package/lib/Utils/ban-checker.js +48 -0
- package/lib/Utils/games/slot-machine.js +19 -0
- package/lib/Utils/index.js +6 -0
- package/lib/Utils/messages.js +25 -0
- package/lib/Utils/native-flow.js +48 -0
- package/lib/Utils/portable-compat.js +12 -0
- package/lib/Utils/rich-message-utils.js +108 -2
- package/lib/Utils/view-once-utils.js +56 -0
- package/lib/Utils/website-preview.js +27 -0
- package/lib/index.d.ts +33 -0
- package/lib/index.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,52 +1,79 @@
|
|
|
1
1
|
# @codexverified/baileys
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@codexverified/baileys)
|
|
4
|
+
[](#at-a-glance)
|
|
5
|
+
[](#license-and-maintenance)
|
|
6
|
+
[](#at-a-glance)
|
|
7
|
+
|
|
8
|
+
> A readable, carefully maintained Baileys distribution for building reliable WhatsApp integrations with codexverified/baileys.
|
|
9
|
+
|
|
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.
|
|
11
|
+
|
|
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.
|
|
13
|
+
|
|
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)
|
|
35
|
+
|
|
36
|
+
## At a glance
|
|
10
37
|
|
|
11
38
|
| Property | Value |
|
|
12
39
|
| --- | --- |
|
|
13
40
|
| Package | `@codexverified/baileys` |
|
|
14
|
-
| Version | `2.
|
|
41
|
+
| Version | `2.11.12` |
|
|
15
42
|
| Runtime | Node.js 20 or newer |
|
|
16
|
-
| Module format | ESM with CommonJS compatibility where supported |
|
|
17
|
-
| Type declarations | Included |
|
|
18
|
-
| License | MIT |
|
|
43
|
+
| Module format | ESM, with CommonJS compatibility where supported |
|
|
44
|
+
| Type declarations | Included at `lib/index.d.ts` |
|
|
45
|
+
| License | MIT, as declared by the package metadata |
|
|
19
46
|
| Maintainer | Codex |
|
|
47
|
+
| Entry point | `lib/index.js` |
|
|
48
|
+
| Repository | `https://github.com/codexverified/baileys` |
|
|
20
49
|
|
|
21
50
|
## Installation
|
|
22
51
|
|
|
23
|
-
|
|
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 |
|
|
24
57
|
|
|
25
|
-
|
|
26
|
-
npm install @codexverified/baileys
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
To install the current local build from the provided archive, place `codex-baileys-2.10.11.tgz` in your project directory and run:
|
|
58
|
+
Both npm and archive installs use the same import name:
|
|
30
59
|
|
|
31
|
-
```
|
|
32
|
-
|
|
60
|
+
```javascript
|
|
61
|
+
import { makeWASocket } from '@codexverified/baileys'
|
|
33
62
|
```
|
|
34
63
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
## Quick Start
|
|
64
|
+
## Quick start
|
|
38
65
|
|
|
39
|
-
The following example creates a socket,
|
|
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.
|
|
40
67
|
|
|
41
68
|
```javascript
|
|
42
69
|
import {
|
|
70
|
+
DisconnectReason,
|
|
43
71
|
makeWASocket,
|
|
44
|
-
useMultiFileAuthState
|
|
45
|
-
DisconnectReason
|
|
72
|
+
useMultiFileAuthState
|
|
46
73
|
} from '@codexverified/baileys'
|
|
47
74
|
import P from 'pino'
|
|
48
75
|
|
|
49
|
-
|
|
76
|
+
async function start() {
|
|
50
77
|
const { state, saveCreds } = await useMultiFileAuthState('./session')
|
|
51
78
|
|
|
52
79
|
const sock = makeWASocket({
|
|
@@ -58,14 +85,12 @@ const start = async () => {
|
|
|
58
85
|
|
|
59
86
|
sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
|
|
60
87
|
if (connection === 'open') {
|
|
61
|
-
console.log('Connected
|
|
88
|
+
console.log('Connected with @codexverified/baileys')
|
|
62
89
|
}
|
|
63
90
|
|
|
64
91
|
if (connection === 'close') {
|
|
65
92
|
const statusCode = lastDisconnect?.error?.output?.statusCode
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (shouldReconnect) {
|
|
93
|
+
if (statusCode !== DisconnectReason.loggedOut) {
|
|
69
94
|
start().catch(console.error)
|
|
70
95
|
}
|
|
71
96
|
}
|
|
@@ -85,9 +110,7 @@ const start = async () => {
|
|
|
85
110
|
start().catch(console.error)
|
|
86
111
|
```
|
|
87
112
|
|
|
88
|
-
## CommonJS
|
|
89
|
-
|
|
90
|
-
For supported Node.js versions, the package can also be loaded through CommonJS:
|
|
113
|
+
## CommonJS usage
|
|
91
114
|
|
|
92
115
|
```javascript
|
|
93
116
|
const {
|
|
@@ -96,162 +119,140 @@ const {
|
|
|
96
119
|
} = require('@codexverified/baileys')
|
|
97
120
|
```
|
|
98
121
|
|
|
99
|
-
|
|
122
|
+
If your runtime or bundler does not support this interop path, use the ESM import form instead.
|
|
100
123
|
|
|
101
|
-
|
|
124
|
+
## Core capabilities
|
|
102
125
|
|
|
103
|
-
| Area |
|
|
126
|
+
| Area | What it covers |
|
|
104
127
|
| --- | --- |
|
|
105
|
-
| Connections | WebSocket connection
|
|
106
|
-
|
|
|
107
|
-
| Messages | Text, mentions, reactions, edits,
|
|
108
|
-
| Media | Images,
|
|
109
|
-
| Interactive content | Buttons, lists, native flows,
|
|
110
|
-
| Rich content | Code blocks, tables, inline entities, LaTeX content, link previews,
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
|
|
|
114
|
-
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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 |
|
|
139
|
+
|
|
140
|
+
## Everyday message usage
|
|
141
|
+
|
|
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 |
|
|
119
149
|
|
|
120
150
|
```javascript
|
|
121
151
|
await sock.sendMessage(jid, {
|
|
122
|
-
text: '
|
|
152
|
+
text: 'A message from Codex'
|
|
123
153
|
})
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
A media message can be sent from a local file, URL, or buffer depending on the upload configuration:
|
|
127
154
|
|
|
128
|
-
```javascript
|
|
129
155
|
await sock.sendMessage(jid, {
|
|
130
|
-
image: { url: './
|
|
131
|
-
caption: 'A
|
|
156
|
+
image: { url: './media/photo.jpg' },
|
|
157
|
+
caption: 'A photo message'
|
|
132
158
|
})
|
|
133
|
-
```
|
|
134
159
|
|
|
135
|
-
A video can be delivered with GIF playback enabled:
|
|
136
|
-
|
|
137
|
-
```javascript
|
|
138
160
|
await sock.sendMessage(jid, {
|
|
139
|
-
video: { url: './animation.mp4' },
|
|
161
|
+
video: { url: './media/animation.mp4' },
|
|
140
162
|
gifPlayback: true,
|
|
141
163
|
caption: 'Animated media'
|
|
142
164
|
})
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## Authentication
|
|
146
|
-
|
|
147
|
-
The recommended authentication helper is `useMultiFileAuthState`:
|
|
148
|
-
|
|
149
|
-
```javascript
|
|
150
|
-
import { useMultiFileAuthState } from '@codexverified/baileys'
|
|
151
|
-
|
|
152
|
-
const { state, saveCreds } = await useMultiFileAuthState('./session')
|
|
153
|
-
```
|
|
154
165
|
|
|
155
|
-
Authentication data contains sensitive account credentials. Keep the session directory private, exclude it from version control, and do not upload it to public repositories.
|
|
156
|
-
|
|
157
|
-
## Explicit Newsletter Following
|
|
158
|
-
|
|
159
|
-
The package does not automatically follow trusted channels, subscribe to fallback channels, or inject a fallback channel identifier into media messages. Newsletter following is consumer-controlled and must be requested explicitly:
|
|
160
|
-
|
|
161
|
-
```javascript
|
|
162
166
|
await sock.sendMessage(jid, {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
167
|
+
image: { url: './media/private-image.jpg' },
|
|
168
|
+
caption: 'Open once',
|
|
169
|
+
viewOnce: true
|
|
166
170
|
})
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
Applications should validate channel identifiers before sending requests and should only follow channels when the behavior is clearly intended by the application owner and its users.
|
|
170
|
-
|
|
171
|
-
## Media Attribution
|
|
172
|
-
|
|
173
|
-
Generated image and video messages do not receive an automatic newsletter annotation or channel pill. If an application intentionally needs message context, it should provide that context explicitly through the supported message options rather than relying on hidden defaults.
|
|
174
|
-
|
|
175
|
-
## CODEX Branding
|
|
176
|
-
|
|
177
|
-
The package displays the following startup identity when a socket is created:
|
|
178
|
-
|
|
179
|
-
```text
|
|
180
|
-
CODEX TECHNOLOGY
|
|
181
|
-
A premium Baileys developed and built by codex
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
Generated message identifiers use the `CODEX` marker. This branding is informational and does not change the WhatsApp protocol or the message transport format.
|
|
185
|
-
|
|
186
|
-
## CODEX Rich Menu and Interactive Helpers
|
|
187
171
|
|
|
188
|
-
The following helpers are available on a socket created with `makeWASocket`. They use the existing message relay and do not change the normal `sendMessage` behavior.
|
|
189
|
-
|
|
190
|
-
### Spoiler media
|
|
191
|
-
|
|
192
|
-
Use `spoiler: true` when sending supported media. The WhatsApp client controls the visual spoiler and download presentation.
|
|
193
|
-
|
|
194
|
-
```javascript
|
|
195
172
|
await sock.sendMessage(jid, {
|
|
196
173
|
video: { url: './media/clip.mp4' },
|
|
197
|
-
caption: '
|
|
198
|
-
|
|
174
|
+
caption: 'View-once video',
|
|
175
|
+
mediaSpoilerMode: 'viewOnce'
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
await sock.sendMessage(jid, {
|
|
179
|
+
image: { url: './media/hidden-preview.jpg' },
|
|
180
|
+
mediaSpoilerMode: 'native'
|
|
199
181
|
})
|
|
200
182
|
```
|
|
201
183
|
|
|
202
|
-
|
|
184
|
+
`mediaSpoilerMode` is an additional, opt-in path for supported image, video, document, or sticker media:
|
|
203
185
|
|
|
204
|
-
|
|
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.
|
|
192
|
+
|
|
193
|
+
## Rich menu example
|
|
205
194
|
|
|
206
195
|
```javascript
|
|
207
196
|
await sock.richMenu(jid, {
|
|
208
197
|
header: {
|
|
209
|
-
title: '
|
|
210
|
-
image: {
|
|
198
|
+
title: 'Codex Menu',
|
|
199
|
+
image: {
|
|
200
|
+
url: 'https://example.com/menu.jpg',
|
|
201
|
+
mime_type: 'image/jpeg'
|
|
202
|
+
}
|
|
211
203
|
},
|
|
212
204
|
body: {
|
|
213
205
|
row: true,
|
|
214
206
|
carousel: false,
|
|
215
|
-
cards: [
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
207
|
+
cards: [
|
|
208
|
+
{
|
|
209
|
+
title: 'Account',
|
|
210
|
+
buttons: [
|
|
211
|
+
{ id: 'profile', text: 'Profile' },
|
|
212
|
+
{ id: 'settings', text: 'Settings' }
|
|
213
|
+
]
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
title: 'Support',
|
|
217
|
+
buttons: ['help', 'contact']
|
|
218
|
+
}
|
|
219
|
+
]
|
|
227
220
|
},
|
|
228
221
|
footer: {
|
|
229
|
-
text: '
|
|
230
|
-
url: 'https://
|
|
231
|
-
image: { url: 'https://example.com/footer.jpg', mime_type: 'image/jpeg' }
|
|
222
|
+
text: 'Codex Technology',
|
|
223
|
+
url: 'https://example.com'
|
|
232
224
|
}
|
|
233
225
|
})
|
|
234
226
|
```
|
|
235
227
|
|
|
236
|
-
|
|
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
|
+
|
|
235
|
+
## Status, grids, tables, and flows
|
|
236
|
+
|
|
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 |
|
|
237
243
|
|
|
238
244
|
```javascript
|
|
239
|
-
await sock.sendStatus({ text: 'New status' }, {
|
|
245
|
+
await sock.sendStatus({ text: 'New Codex status' }, {
|
|
240
246
|
statusJidList: ['1234567890@s.whatsapp.net']
|
|
241
247
|
})
|
|
242
248
|
|
|
243
|
-
await sock.sendStatusMentions({ text: 'Mentioned status' }, [
|
|
244
|
-
'1234567890@s.whatsapp.net',
|
|
245
|
-
'9876543210@s.whatsapp.net'
|
|
246
|
-
])
|
|
247
|
-
|
|
248
249
|
await sock.sendRichButtonGrid(jid, {
|
|
249
250
|
text: 'Choose an option',
|
|
250
251
|
cards: [{
|
|
251
252
|
title: 'Actions',
|
|
252
253
|
buttons: [
|
|
253
|
-
{ id: '
|
|
254
|
-
{ id: '
|
|
254
|
+
{ id: 'first_action', text: 'First action' },
|
|
255
|
+
{ id: 'second_action', text: 'Second action' }
|
|
255
256
|
]
|
|
256
257
|
}]
|
|
257
258
|
})
|
|
@@ -274,53 +275,178 @@ await sock.sendWhatsAppFlow(jid, {
|
|
|
274
275
|
})
|
|
275
276
|
```
|
|
276
277
|
|
|
277
|
-
These helpers
|
|
278
|
+
These helpers are protocol- and client-dependent. Use graceful fallbacks when an application serves a wide range of WhatsApp client versions.
|
|
279
|
+
|
|
280
|
+
## Authentication and deployment guidance
|
|
278
281
|
|
|
279
|
-
|
|
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 |
|
|
280
290
|
|
|
281
|
-
|
|
291
|
+
## Development workflow
|
|
282
292
|
|
|
283
293
|
```bash
|
|
284
|
-
npm
|
|
294
|
+
npm test
|
|
285
295
|
```
|
|
286
296
|
|
|
287
|
-
|
|
297
|
+
Before submitting changes, validate ESM syntax, CommonJS compatibility where applicable, generated protocol files, and the declarations in `lib/index.d.ts`. Keep package metadata, exports, runtime requirements, and documentation synchronized. When a protocol behavior is experimental, document the fallback behavior and the client versions used during testing.
|
|
288
298
|
|
|
289
|
-
|
|
290
|
-
|
|
299
|
+
## Recent compatibility updates
|
|
300
|
+
|
|
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 |
|
|
306
|
+
|
|
307
|
+
## About Codex
|
|
308
|
+
|
|
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.
|
|
310
|
+
|
|
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
|
+
|
|
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.
|
|
319
|
+
|
|
320
|
+
## Package layout
|
|
321
|
+
|
|
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 |
|
|
329
|
+
|
|
330
|
+
## Security and responsible use
|
|
331
|
+
|
|
332
|
+
This library interacts with WhatsApp accounts and user communications.
|
|
333
|
+
|
|
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 |
|
|
343
|
+
|
|
344
|
+
## License and maintenance
|
|
345
|
+
|
|
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.
|
|
347
|
+
|
|
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
|
+
})
|
|
291
370
|
```
|
|
292
371
|
|
|
293
|
-
|
|
372
|
+
As with other private or experimental WhatsApp rich-response layouts, clients may fall back to plain rendering or ignore the addon action.
|
|
294
373
|
|
|
295
|
-
|
|
296
|
-
2. Keep runtime requirements and package metadata synchronized.
|
|
297
|
-
3. Keep authentication data and personal account information out of commits.
|
|
298
|
-
4. Validate ESM syntax and CommonJS compatibility where applicable.
|
|
299
|
-
5. Document user-visible behavior changes in this README.
|
|
374
|
+
### Slot-machine HTML generator
|
|
300
375
|
|
|
301
|
-
|
|
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.
|
|
302
377
|
|
|
303
|
-
|
|
|
378
|
+
| Option | Purpose |
|
|
304
379
|
| --- | --- |
|
|
305
|
-
| `
|
|
306
|
-
| `
|
|
307
|
-
| `engine-requirements.js` | Runtime requirement checks used during installation |
|
|
308
|
-
| `package.json` | Package metadata, dependencies, scripts, and exports |
|
|
309
|
-
| `README.md` | Project documentation and usage reference |
|
|
380
|
+
| `title` | Display title for the generated page |
|
|
381
|
+
| `startingCredits` | Initial credit balance |
|
|
310
382
|
|
|
311
|
-
|
|
383
|
+
```javascript
|
|
384
|
+
import { generateSlotMachineHtml } from '@codexverified/baileys'
|
|
312
385
|
|
|
313
|
-
|
|
386
|
+
const html = generateSlotMachineHtml({
|
|
387
|
+
title: 'Codex Fruit Bonanza',
|
|
388
|
+
startingCredits: 500
|
|
389
|
+
})
|
|
390
|
+
```
|
|
314
391
|
|
|
315
|
-
|
|
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.
|
|
316
393
|
|
|
317
|
-
|
|
394
|
+
### Optional ban-status checker
|
|
318
395
|
|
|
319
|
-
|
|
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.
|
|
320
397
|
|
|
321
|
-
|
|
398
|
+
```javascript
|
|
399
|
+
import { checkStatusWA } from '@codexverified/baileys'
|
|
322
400
|
|
|
323
|
-
|
|
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/
|
|
324
424
|
|
|
425
|
+
## Additional functional compatibility helpers
|
|
325
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.
|
|
326
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
|
package/lib/Socket/index.js
CHANGED
|
@@ -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/
|
|
39
|
+
`${blue}${center('@codexverified/baileys')}${reset}\n` +
|
|
40
40
|
`${yellow}${center('premium baileys built by codex')}${reset}\n`
|
|
41
41
|
);
|
|
42
42
|
}
|
|
@@ -4,7 +4,6 @@ import { randomBytes } from 'crypto';
|
|
|
4
4
|
import { proto } from '../../WAProto/index.js';
|
|
5
5
|
import { BIZ_BOT_SUPPORT_PAYLOAD, DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
|
|
6
6
|
import { aggregateMessageKeysNotFromMe, assertMediaContent, assertMeId, bindWaitForEvent, buildLinkPreview, decryptMediaRetryData, DEF_MEDIA_HOST, delay, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, extractImageThumb, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, generateWAMessageFromContent, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, hasValidAlbumMedia, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, prepareWAMessageMedia, shouldIncludeBizBinaryNode, unixTimestampSeconds } from '../Utils/index.js';
|
|
7
|
-
import { AssociationType } from '../Types/index.js';
|
|
8
7
|
import { getUrlInfo } from '../Utils/link-preview.js';
|
|
9
8
|
import { makeKeyedMutex, makeMutex } from '../Utils/make-mutex.js';
|
|
10
9
|
import { getMessageReportingToken, shouldIncludeReportingToken } from '../Utils/reporting-utils.js';
|
|
@@ -17,7 +16,7 @@ import { collectMetaAIBotParticipantJids, isMetaAIBotResponse, META_AI_BOT_JID }
|
|
|
17
16
|
import { makeUsernameSocket } from './username.js';
|
|
18
17
|
|
|
19
18
|
const STATUS_JID = 'status@broadcast';
|
|
20
|
-
const normalizeStatusJidList = (value) => {
|
|
19
|
+
export const normalizeStatusJidList = (value) => {
|
|
21
20
|
if (!Array.isArray(value) || value.length === 0) {
|
|
22
21
|
throw new Boom('statusJidList must contain at least one recipient JID', { statusCode: 400 });
|
|
23
22
|
}
|
|
@@ -1224,6 +1223,13 @@ export const makeMessagesSocket = (config) => {
|
|
|
1224
1223
|
await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata });
|
|
1225
1224
|
return fullMsg;
|
|
1226
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
|
+
},
|
|
1227
1233
|
sendInteractiveTable: async (jid, table, options = {}) => {
|
|
1228
1234
|
const { title = '', headers = [], rows = [], image, buttons = [], footer } = table || {};
|
|
1229
1235
|
if (!Array.isArray(headers) || !Array.isArray(rows) || !Array.isArray(buttons)) throw new Boom('sendInteractiveTable expects headers, rows, and buttons arrays', { statusCode: 400 });
|
|
@@ -2040,7 +2046,9 @@ export const makeMessagesSocket = (config) => {
|
|
|
2040
2046
|
albumMsg.message.messageContextInfo ||= {};
|
|
2041
2047
|
albumMsg.message.messageContextInfo.messageAssociation = {
|
|
2042
2048
|
parentMessageKey: fullMsg.key,
|
|
2043
|
-
|
|
2049
|
+
// WhatsApp album child messages use association type 1.
|
|
2050
|
+
// MEDIA_ALBUM is a message category, not the child-association wire value.
|
|
2051
|
+
associationType: 1
|
|
2044
2052
|
};
|
|
2045
2053
|
await relayMessage(jid, albumMsg.message, {
|
|
2046
2054
|
messageId: albumMsg.key.id,
|
|
@@ -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
|
+
'&': '&', '<': '<', '>': '>', '"': '"', "'": '''
|
|
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;
|
package/lib/Utils/index.js
CHANGED
|
@@ -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';
|
package/lib/Utils/messages.js
CHANGED
|
@@ -1363,6 +1363,31 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1363
1363
|
};
|
|
1364
1364
|
delete message.interactiveAsTemplate;
|
|
1365
1365
|
}
|
|
1366
|
+
// Codex compatibility: expose the public media-spoiler mode without changing
|
|
1367
|
+
// the existing explicit viewOnce/viewOnceV2 behavior. The mode is opt-in.
|
|
1368
|
+
// Supported values are `viewOnce` and `native` for image, video, document,
|
|
1369
|
+
// and sticker messages. Existing `spoiler` and view-once flags take priority.
|
|
1370
|
+
if (hasOptionalProperty(message, 'mediaSpoilerMode') &&
|
|
1371
|
+
!message.viewOnce &&
|
|
1372
|
+
!message.viewOnceV2 &&
|
|
1373
|
+
!message.viewOnceV2Extension) {
|
|
1374
|
+
const messageType = Object.keys(m)[0];
|
|
1375
|
+
const isSpoilerMedia = ['imageMessage', 'videoMessage', 'documentMessage', 'stickerMessage'].includes(messageType);
|
|
1376
|
+
const mode = message.mediaSpoilerMode;
|
|
1377
|
+
if (isSpoilerMedia && mode === 'viewOnce') {
|
|
1378
|
+
m = { viewOnceMessage: { message: m } };
|
|
1379
|
+
}
|
|
1380
|
+
else if (isSpoilerMedia && mode === 'native') {
|
|
1381
|
+
const key = m[messageType];
|
|
1382
|
+
if (key && 'contextInfo' in key && key.contextInfo) {
|
|
1383
|
+
key.contextInfo.isSpoiler = true;
|
|
1384
|
+
}
|
|
1385
|
+
else if (key) {
|
|
1386
|
+
key.contextInfo = { isSpoiler: true };
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
delete message.mediaSpoilerMode;
|
|
1390
|
+
}
|
|
1366
1391
|
// Lia@Changes 30-01-26 --- Add "ephemeral" boolean to wrap message into ephemeralMessage like "viewOnce"
|
|
1367
1392
|
if (hasOptionalProperty(message, 'ephemeral') && !!message.ephemeral) {
|
|
1368
1393
|
m = { ephemeralMessage: { message: m } };
|
|
@@ -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
|
|
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) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codexverified/baileys",
|
|
3
|
-
"version": "2.
|
|
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",
|