plogme 1.0.6 → 2.0.1
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 +540 -368
- package/engine-requirements.js +0 -36
- package/lib/Socket/chats.js +1 -0
- package/lib/Socket/index.js +0 -34
- package/lib/Socket/messages-send.js +81 -124
- package/lib/Socket/newsletter.js +37 -3
- package/lib/Socket/socket.js +0 -33
- package/lib/Utils/bot-capabilities.js +84 -0
- package/lib/Utils/channel-policy.js +25 -1
- package/lib/Utils/index.js +1 -0
- package/lib/Utils/messages.js +13 -72
- package/lib/Utils/meta-compositing.js +7 -11
- package/lib/Utils/welcome-flow.js +2 -6
- package/lib/index.d.ts +6 -0
- package/package.json +2 -2
- package/lib/Socket/messages-send.js[latest working] +0 -1759
- package/lib/Utils/integrity.js +0 -296
package/README.md
CHANGED
|
@@ -1,8 +1,35 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
>
|
|
1
|
+
# Plogme
|
|
2
|
+
|
|
3
|
+
**Plogme** is a Node.js WhatsApp Web client built on the Baileys protocol implementation. It provides authentication, messaging, media uploads, groups, status updates, interactive messages, albums, rich responses, Meta AI-style envelopes, HTML screens, and selected WhatsApp Web protocol features.
|
|
4
|
+
|
|
5
|
+
> [!IMPORTANT]
|
|
6
|
+
> Plogme is a protocol library. WhatsApp server behavior and client rendering can change without notice. Rich responses, HTML primitives, native flows, reels, carousels, and experimental protocol fields may render differently across WhatsApp versions.
|
|
7
|
+
|
|
8
|
+
[](https://www.npmjs.com/package/plogme)
|
|
9
|
+
[](https://nodejs.org/)
|
|
10
|
+
[](https://github.com/crysnovax/baileys)
|
|
11
|
+
|
|
12
|
+
## Contents
|
|
13
|
+
|
|
14
|
+
1. [Installation](#installation)
|
|
15
|
+
2. [Quick start](#quick-start)
|
|
16
|
+
3. [Authentication and pairing](#authentication-and-pairing)
|
|
17
|
+
4. [Sending messages](#sending-messages)
|
|
18
|
+
5. [Media and albums](#media-and-albums)
|
|
19
|
+
6. [Interactive messages](#interactive-messages)
|
|
20
|
+
7. [Rich messages](#rich-messages)
|
|
21
|
+
8. [Rich menus, reels, and grids](#rich-menus-reels-and-grids)
|
|
22
|
+
9. [HTML screens and built-in apps](#html-screens-and-built-in-apps)
|
|
23
|
+
10. [Status updates](#status-updates)
|
|
24
|
+
11. [Groups and group history](#groups-and-group-history)
|
|
25
|
+
12. [Reports and moderation](#reports-and-moderation)
|
|
26
|
+
13. [Experimental bot metadata](#experimental-bot-metadata)
|
|
27
|
+
14. [WhatsApp flows and web views](#whatsapp-flows-and-web-views)
|
|
28
|
+
15. [View-once utilities](#view-once-utilities)
|
|
29
|
+
16. [Connection handling](#connection-handling)
|
|
30
|
+
17. [Security and removed automatic behavior](#security-and-removed-automatic-behavior)
|
|
31
|
+
18. [Development](#development)
|
|
32
|
+
19. [License and support](#license-and-support)
|
|
6
33
|
|
|
7
34
|
## Installation
|
|
8
35
|
|
|
@@ -10,20 +37,32 @@
|
|
|
10
37
|
npm install plogme
|
|
11
38
|
```
|
|
12
39
|
|
|
13
|
-
The
|
|
40
|
+
The package currently requires **Node.js 20 or newer**.
|
|
41
|
+
|
|
42
|
+
To install the development branch directly from GitHub:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install github:crysnovax/baileys
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Plogme is an ES module package. Use `import` syntax in Node.js projects configured with `"type": "module"`.
|
|
49
|
+
|
|
50
|
+
> [!WARNING]
|
|
51
|
+
> Never commit authentication state, private keys, `.env` files, or downloaded session data. Add your session directory to `.gitignore`.
|
|
14
52
|
|
|
15
53
|
## Quick start
|
|
16
54
|
|
|
55
|
+
This is the smallest complete connection example. It saves credentials, reconnects after temporary disconnects, and stops reconnecting after logout.
|
|
56
|
+
|
|
17
57
|
```js
|
|
18
|
-
import {
|
|
19
|
-
makeWASocket,
|
|
58
|
+
import makeWASocket, {
|
|
20
59
|
DisconnectReason,
|
|
21
60
|
useMultiFileAuthState
|
|
22
61
|
} from 'plogme'
|
|
23
62
|
import { Boom } from '@hapi/boom'
|
|
24
63
|
import pino from 'pino'
|
|
25
64
|
|
|
26
|
-
async function
|
|
65
|
+
async function connect() {
|
|
27
66
|
const { state, saveCreds } = await useMultiFileAuthState('./session')
|
|
28
67
|
const sock = makeWASocket({
|
|
29
68
|
auth: state,
|
|
@@ -31,38 +70,60 @@ async function start() {
|
|
|
31
70
|
})
|
|
32
71
|
|
|
33
72
|
sock.ev.on('creds.update', saveCreds)
|
|
73
|
+
|
|
34
74
|
sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
|
|
35
|
-
if (connection === 'open')
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
75
|
+
if (connection === 'open') {
|
|
76
|
+
console.log('Connected to WhatsApp')
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (connection !== 'close') return
|
|
81
|
+
|
|
82
|
+
const statusCode = new Boom(lastDisconnect?.error)?.output?.statusCode
|
|
83
|
+
if (statusCode === DisconnectReason.loggedOut) {
|
|
84
|
+
console.error('Logged out. Remove the old session and pair again.')
|
|
85
|
+
return
|
|
39
86
|
}
|
|
87
|
+
|
|
88
|
+
console.log('Connection closed; reconnecting')
|
|
89
|
+
connect().catch(console.error)
|
|
40
90
|
})
|
|
91
|
+
|
|
92
|
+
return sock
|
|
41
93
|
}
|
|
42
94
|
|
|
43
|
-
|
|
95
|
+
await connect()
|
|
44
96
|
```
|
|
45
97
|
|
|
46
|
-
Keep authentication files private. Never commit session credentials, private keys, or `.env` files.
|
|
47
|
-
|
|
48
98
|
## Authentication and pairing
|
|
49
99
|
|
|
100
|
+
### Multi-file authentication
|
|
101
|
+
|
|
102
|
+
`useMultiFileAuthState` is the recommended development setup because credentials and keys are stored as separate files.
|
|
103
|
+
|
|
50
104
|
```js
|
|
51
105
|
const { state, saveCreds } = await useMultiFileAuthState('./session')
|
|
52
|
-
|
|
53
106
|
const sock = makeWASocket({ auth: state })
|
|
54
107
|
sock.ev.on('creds.update', saveCreds)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Pairing code
|
|
111
|
+
|
|
112
|
+
Request a pairing code after creating the socket. Supply a phone number in international format without `+`, spaces, or punctuation.
|
|
55
113
|
|
|
114
|
+
```js
|
|
56
115
|
const code = await sock.requestPairingCode('15551234567')
|
|
57
|
-
console.log(code)
|
|
116
|
+
console.log('Pairing code:', code)
|
|
58
117
|
```
|
|
59
118
|
|
|
60
|
-
|
|
119
|
+
Keep the pairing code private and use it only with the WhatsApp account you control.
|
|
120
|
+
|
|
121
|
+
## Sending messages
|
|
61
122
|
|
|
62
|
-
|
|
123
|
+
### Text, mentions, and reactions
|
|
63
124
|
|
|
64
125
|
```js
|
|
65
|
-
await sock.sendMessage(jid, { text: 'Hello
|
|
126
|
+
await sock.sendMessage(jid, { text: 'Hello from Plogme' })
|
|
66
127
|
|
|
67
128
|
await sock.sendMessage(jid, {
|
|
68
129
|
text: 'Hello @15551234567',
|
|
@@ -70,11 +131,112 @@ await sock.sendMessage(jid, {
|
|
|
70
131
|
})
|
|
71
132
|
|
|
72
133
|
await sock.sendMessage(jid, {
|
|
73
|
-
react: {
|
|
134
|
+
react: {
|
|
135
|
+
text: '👍',
|
|
136
|
+
key: message.key
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### WhatsApp Channels
|
|
142
|
+
|
|
143
|
+
Resolve a Channel invite code or a full WhatsApp Channel invite URL without
|
|
144
|
+
automatically following the Channel:
|
|
145
|
+
|
|
146
|
+
```js
|
|
147
|
+
const channel = await sock.newsletterGetInviteInfo(
|
|
148
|
+
'https://whatsapp.com/channel/0029Vb6pe77K0IBn48HLKb38'
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
console.log(channel?.id, channel?.name, channel?.description)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
React to a Channel post with its Channel JID and `serverId`. Pass `null`,
|
|
155
|
+
`undefined`, or an empty string to remove the reaction:
|
|
156
|
+
|
|
157
|
+
```js
|
|
158
|
+
await sock.newsletterReactMessage(
|
|
159
|
+
'120363000000000000@newsletter',
|
|
160
|
+
'12345',
|
|
161
|
+
'👍'
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
await sock.newsletterReactMessage(
|
|
165
|
+
'120363000000000000@newsletter',
|
|
166
|
+
'12345',
|
|
167
|
+
null
|
|
168
|
+
)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Chat themes and animated wallpapers
|
|
172
|
+
|
|
173
|
+
Send a chat-theme protocol message with a color scheme and an animated
|
|
174
|
+
wallpaper. `chatThemeId` is normalized to the WhatsApp color-scheme form by
|
|
175
|
+
adding `@Tonal`; use `colorSchemeId` when you already have the complete value.
|
|
176
|
+
`dimLevel` is a normalized value from `0` to `1`.
|
|
177
|
+
|
|
178
|
+
```js
|
|
179
|
+
await sock.sendMessage(jid, {
|
|
180
|
+
chatTheme: {
|
|
181
|
+
chatThemeId: 'Royal-Blue',
|
|
182
|
+
animatedWallpaper: {
|
|
183
|
+
id: 'wallpaper-1',
|
|
184
|
+
dimLevel: 0.25
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
// Equivalent explicit color-scheme form:
|
|
190
|
+
await sock.sendMessage(jid, {
|
|
191
|
+
chatTheme: {
|
|
192
|
+
colorSchemeId: 'Royal-Blue@Tonal',
|
|
193
|
+
animatedWallpaper: {
|
|
194
|
+
animatedWallpaperId: 'wallpaper-1',
|
|
195
|
+
opacity: 25
|
|
196
|
+
}
|
|
197
|
+
}
|
|
74
198
|
})
|
|
75
199
|
```
|
|
76
200
|
|
|
77
|
-
|
|
201
|
+
### Editing and deleting
|
|
202
|
+
|
|
203
|
+
```js
|
|
204
|
+
await sock.sendMessage(jid, {
|
|
205
|
+
text: 'Updated text',
|
|
206
|
+
edit: message.key
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
await sock.sendMessage(jid, {
|
|
210
|
+
caption: 'Updated media caption',
|
|
211
|
+
edit: message.key
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
await sock.sendMessage(jid, {
|
|
215
|
+
delete: message.key
|
|
216
|
+
})
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Forwarding
|
|
220
|
+
|
|
221
|
+
```js
|
|
222
|
+
await sock.sendMessage(jid, {
|
|
223
|
+
forward: message,
|
|
224
|
+
force: true
|
|
225
|
+
})
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Profile name and About status
|
|
229
|
+
|
|
230
|
+
These methods update the connected account's own profile.
|
|
231
|
+
|
|
232
|
+
```js
|
|
233
|
+
await sock.updateProfileName('Cody AI')
|
|
234
|
+
await sock.updateProfileStatus('Building helpful WhatsApp tools')
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Media and albums
|
|
238
|
+
|
|
239
|
+
### Images, video, audio, documents, and stickers
|
|
78
240
|
|
|
79
241
|
```js
|
|
80
242
|
await sock.sendMessage(jid, {
|
|
@@ -85,161 +247,245 @@ await sock.sendMessage(jid, {
|
|
|
85
247
|
await sock.sendMessage(jid, {
|
|
86
248
|
video: { url: './video.mp4' },
|
|
87
249
|
caption: 'Video caption',
|
|
88
|
-
gifPlayback: false
|
|
250
|
+
gifPlayback: false,
|
|
251
|
+
ptv: false
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
await sock.sendMessage(jid, {
|
|
255
|
+
audio: { url: './voice.ogg' },
|
|
256
|
+
mimetype: 'audio/ogg; codecs=opus',
|
|
257
|
+
ptt: true
|
|
89
258
|
})
|
|
90
259
|
|
|
91
260
|
await sock.sendMessage(jid, {
|
|
92
261
|
document: { url: './report.pdf' },
|
|
93
262
|
mimetype: 'application/pdf',
|
|
94
|
-
fileName: 'report.pdf'
|
|
263
|
+
fileName: 'report.pdf',
|
|
264
|
+
caption: 'Monthly report'
|
|
95
265
|
})
|
|
96
266
|
|
|
97
267
|
await sock.sendMessage(jid, {
|
|
98
|
-
|
|
99
|
-
mimetype: 'audio/ogg; codecs=opus'
|
|
268
|
+
sticker: { url: './sticker.webp' }
|
|
100
269
|
})
|
|
101
270
|
```
|
|
102
271
|
|
|
103
|
-
|
|
272
|
+
Remote URLs, local file paths, and buffers are supported where the selected media helper accepts them.
|
|
273
|
+
|
|
274
|
+
> [!WARNING]
|
|
275
|
+
> A URL must point to a real, playable media file. A URL returning an HTML error page, an empty file, or an invalid video container can produce a WhatsApp media verification or download warning even when the library code is correct.
|
|
104
276
|
|
|
105
|
-
|
|
106
|
-
`plogme`, use `updateProfileStatus`—not `updateProfileDescription`—and pass a
|
|
107
|
-
plain string:
|
|
277
|
+
### GIF playback and video notes
|
|
108
278
|
|
|
109
279
|
```js
|
|
110
|
-
await sock.
|
|
111
|
-
|
|
112
|
-
|
|
280
|
+
await sock.sendMessage(jid, {
|
|
281
|
+
video: { url: './animation.mp4' },
|
|
282
|
+
gifPlayback: true,
|
|
283
|
+
caption: 'Animated clip'
|
|
284
|
+
})
|
|
113
285
|
|
|
114
|
-
|
|
115
|
-
|
|
286
|
+
await sock.sendMessage(jid, {
|
|
287
|
+
video: { url: './video-note.mp4' },
|
|
288
|
+
ptv: true
|
|
289
|
+
})
|
|
290
|
+
```
|
|
116
291
|
|
|
117
|
-
|
|
292
|
+
### Albums
|
|
118
293
|
|
|
119
|
-
|
|
120
|
-
supported `contextInfo.isSpoiler` flag:
|
|
294
|
+
Use at least two image or video items. Albums are sent as a parent message followed by separately encrypted media children.
|
|
121
295
|
|
|
122
296
|
```js
|
|
123
|
-
await sock.
|
|
124
|
-
image: { url: './
|
|
125
|
-
|
|
126
|
-
|
|
297
|
+
await sock.sendAlbumMessage(jid, [
|
|
298
|
+
{ type: 'image', data: { url: './one.jpg' } },
|
|
299
|
+
{ type: 'image', data: { url: './two.jpg' } }
|
|
300
|
+
], {
|
|
301
|
+
caption: 'Trip photos'
|
|
127
302
|
})
|
|
128
303
|
```
|
|
129
304
|
|
|
130
|
-
|
|
131
|
-
compatibility fallback. This sends a view-once envelope; it is **not** the
|
|
132
|
-
same as a native spoiler:
|
|
305
|
+
The general `sendMessage` album form is also supported:
|
|
133
306
|
|
|
134
307
|
```js
|
|
135
308
|
await sock.sendMessage(jid, {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
309
|
+
album: [
|
|
310
|
+
{ image: { url: './one.jpg' }, caption: 'First' },
|
|
311
|
+
{ video: { url: './clip.mp4' }, caption: 'Second' }
|
|
312
|
+
]
|
|
139
313
|
})
|
|
140
314
|
```
|
|
141
315
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
316
|
+
Rich-response and bot-forwarded messages cannot be nested as album children. Send them as separate messages.
|
|
317
|
+
|
|
318
|
+
## Interactive messages
|
|
319
|
+
|
|
320
|
+
### Buttons and lists
|
|
145
321
|
|
|
146
322
|
```js
|
|
147
323
|
await sock.sendMessage(jid, {
|
|
148
|
-
text: '
|
|
149
|
-
|
|
324
|
+
text: 'Choose an option',
|
|
325
|
+
footer: 'Plogme',
|
|
326
|
+
buttons: [
|
|
327
|
+
{ text: 'Confirm', id: 'confirm' },
|
|
328
|
+
{ text: 'Cancel', id: 'cancel' }
|
|
329
|
+
]
|
|
150
330
|
})
|
|
151
|
-
```
|
|
152
331
|
|
|
153
|
-
|
|
332
|
+
await sock.sendMessage(jid, {
|
|
333
|
+
text: 'Choose a category',
|
|
334
|
+
title: 'Categories',
|
|
335
|
+
buttonText: 'Open list',
|
|
336
|
+
sections: [
|
|
337
|
+
{
|
|
338
|
+
title: 'Available categories',
|
|
339
|
+
rows: [
|
|
340
|
+
{ title: 'Support', description: 'Get help', rowId: 'support' },
|
|
341
|
+
{ title: 'News', description: 'Read updates', rowId: 'news' }
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
]
|
|
345
|
+
})
|
|
346
|
+
```
|
|
154
347
|
|
|
155
|
-
|
|
348
|
+
### Native flow
|
|
156
349
|
|
|
157
350
|
```js
|
|
158
|
-
await sock.
|
|
159
|
-
|
|
351
|
+
await sock.sendWhatsAppFlow(jid, {
|
|
352
|
+
flowId: 'your-flow-id',
|
|
353
|
+
flowToken: 'your-flow-token',
|
|
354
|
+
cta: 'Open form',
|
|
355
|
+
text: 'Complete this form'
|
|
356
|
+
})
|
|
357
|
+
```
|
|
160
358
|
|
|
161
|
-
|
|
359
|
+
For a rich URL call-to-action:
|
|
162
360
|
|
|
163
|
-
|
|
361
|
+
```js
|
|
362
|
+
await sock.sendRichWebview(jid, {
|
|
363
|
+
url: 'https://example.com/app',
|
|
364
|
+
text: 'Open the app',
|
|
365
|
+
buttonText: 'Open',
|
|
366
|
+
useWebview: true
|
|
164
367
|
})
|
|
165
368
|
```
|
|
166
369
|
|
|
167
|
-
|
|
370
|
+
### Interactive table
|
|
168
371
|
|
|
169
372
|
```js
|
|
170
|
-
await sock.
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
373
|
+
await sock.sendInteractiveTable(jid, {
|
|
374
|
+
title: 'Deployment status',
|
|
375
|
+
headers: ['Service', 'State'],
|
|
376
|
+
rows: [
|
|
377
|
+
['API', 'Online'],
|
|
378
|
+
['Worker', 'Online']
|
|
379
|
+
],
|
|
380
|
+
buttons: [],
|
|
381
|
+
footer: 'Updated now'
|
|
174
382
|
})
|
|
175
383
|
```
|
|
176
384
|
|
|
177
|
-
##
|
|
385
|
+
## Rich messages
|
|
178
386
|
|
|
179
|
-
|
|
387
|
+
Rich messages are forwarded GenAI-style envelopes. The sender now routes rich payloads through normal WhatsApp message generation before relay so clients receive the expected message metadata.
|
|
180
388
|
|
|
181
|
-
|
|
182
|
-
|
|
389
|
+
> [!NOTE]
|
|
390
|
+
> Rich rendering is client-dependent. A rich message can be structurally valid while a particular WhatsApp build chooses a fallback rendering.
|
|
183
391
|
|
|
184
|
-
|
|
392
|
+
### Rich text and quotes
|
|
185
393
|
|
|
186
394
|
```js
|
|
187
|
-
await sock.
|
|
188
|
-
text: '
|
|
189
|
-
|
|
190
|
-
|
|
395
|
+
await sock.sendRichText(jid, {
|
|
396
|
+
text: '**Deployment complete**\n\nThe service is online.'
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
await sock.sendMarkdownQuote(jid, {
|
|
400
|
+
text: '> Use the production URL for verification.'
|
|
191
401
|
})
|
|
192
402
|
```
|
|
193
403
|
|
|
194
|
-
|
|
404
|
+
### Copy-to-clipboard actions
|
|
195
405
|
|
|
196
406
|
```js
|
|
197
|
-
await sock.
|
|
198
|
-
text: '
|
|
199
|
-
|
|
200
|
-
copyLabel: 'Copy me'
|
|
407
|
+
await sock.sendCopyButton(jid, {
|
|
408
|
+
text: 'npm install plogme',
|
|
409
|
+
label: 'Copy command'
|
|
201
410
|
})
|
|
202
|
-
```
|
|
203
411
|
|
|
204
|
-
|
|
412
|
+
await sock.sendRichTextCopy(jid, {
|
|
413
|
+
text: 'Install the package first.',
|
|
414
|
+
copyText: 'npm install plogme',
|
|
415
|
+
copyLabel: 'Copy command'
|
|
416
|
+
})
|
|
205
417
|
|
|
206
|
-
```js
|
|
207
418
|
await sock.sendQuoteCopy(jid, {
|
|
208
|
-
text:
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
copyText: 'Use this exact logo image...',
|
|
212
|
-
copyLabel: 'Copy me'
|
|
419
|
+
text: '> Run the tests before publishing.',
|
|
420
|
+
copyText: 'npm test',
|
|
421
|
+
copyLabel: 'Copy test command'
|
|
213
422
|
})
|
|
214
423
|
```
|
|
215
424
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
## Rich links, images, HTML, and menus
|
|
425
|
+
### Rich image and inline links
|
|
219
426
|
|
|
220
427
|
```js
|
|
221
|
-
await sock.sendRichLink(jid, {
|
|
222
|
-
text: 'Open the deployment site',
|
|
223
|
-
url: 'https://example.com'
|
|
224
|
-
})
|
|
225
|
-
|
|
226
428
|
await sock.sendRichImage(jid, {
|
|
227
429
|
url: 'https://example.com/image.jpg',
|
|
228
430
|
mimeType: 'image/jpeg'
|
|
229
431
|
})
|
|
230
432
|
|
|
231
|
-
await sock.
|
|
232
|
-
|
|
433
|
+
await sock.sendRichLink(jid, {
|
|
434
|
+
text: 'Open the documentation',
|
|
435
|
+
links: [
|
|
436
|
+
{
|
|
437
|
+
text: 'Documentation',
|
|
438
|
+
url: 'https://example.com/docs',
|
|
439
|
+
isTrusted: true
|
|
440
|
+
}
|
|
441
|
+
]
|
|
233
442
|
})
|
|
234
443
|
```
|
|
235
444
|
|
|
236
|
-
|
|
445
|
+
### Rich tables, lists, code, and LaTeX
|
|
237
446
|
|
|
238
|
-
|
|
447
|
+
```js
|
|
448
|
+
await sock.sendTable(
|
|
449
|
+
jid,
|
|
450
|
+
'Build status',
|
|
451
|
+
['Service', 'State'],
|
|
452
|
+
[
|
|
453
|
+
{ items: ['API', 'Online'] },
|
|
454
|
+
{ items: ['Worker', 'Online'] }
|
|
455
|
+
]
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
await sock.sendList(jid, 'Next steps', [
|
|
459
|
+
{ title: 'Test', description: 'Run the test suite' },
|
|
460
|
+
{ title: 'Deploy', description: 'Publish the verified build' }
|
|
461
|
+
])
|
|
462
|
+
|
|
463
|
+
await sock.sendCodeBlock(jid, 'console.log("hello")', undefined, {
|
|
464
|
+
language: 'javascript'
|
|
465
|
+
})
|
|
466
|
+
|
|
467
|
+
await sock.sendRichAIResponse(jid, {
|
|
468
|
+
table: {
|
|
469
|
+
title: 'Status',
|
|
470
|
+
headers: ['Name', 'Value'],
|
|
471
|
+
rows: [['version', '2.0.1']]
|
|
472
|
+
}
|
|
473
|
+
})
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
`sendRichAIResponse` also accepts `list`, `codeBlock`, and `latex` content objects. For a pre-existing Meta AI response, `captureAndResendUnifiedResponse(jid, message, quoted)` captures and resends its unified response.
|
|
477
|
+
|
|
478
|
+
## Rich menus, reels, and grids
|
|
479
|
+
|
|
480
|
+
### Original Gen4 rich menu
|
|
481
|
+
|
|
482
|
+
Use `sock.richMenu` for the original Gen4-style menu. This is the primary rich-menu API.
|
|
239
483
|
|
|
240
484
|
```js
|
|
241
485
|
await sock.richMenu(jid, {
|
|
242
|
-
header: {
|
|
486
|
+
header: {
|
|
487
|
+
title: 'Deployment tools'
|
|
488
|
+
},
|
|
243
489
|
body: {
|
|
244
490
|
title: 'Choose an action',
|
|
245
491
|
buttons: [
|
|
@@ -247,136 +493,150 @@ await sock.richMenu(jid, {
|
|
|
247
493
|
{ id: 'logs', text: 'View logs' }
|
|
248
494
|
]
|
|
249
495
|
},
|
|
250
|
-
footer: {
|
|
496
|
+
footer: {
|
|
497
|
+
text: 'Open documentation',
|
|
498
|
+
url: 'https://example.com/docs'
|
|
499
|
+
}
|
|
500
|
+
})
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
Cards and carousel layout are supported:
|
|
504
|
+
|
|
505
|
+
```js
|
|
506
|
+
await sock.richMenu(jid, {
|
|
507
|
+
body: {
|
|
508
|
+
carousel: true,
|
|
509
|
+
cards: [
|
|
510
|
+
{
|
|
511
|
+
title: 'Production',
|
|
512
|
+
toast: 'Production selected',
|
|
513
|
+
buttons: [{ id: 'production', text: 'Open' }]
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
title: 'Staging',
|
|
517
|
+
toast: 'Staging selected',
|
|
518
|
+
buttons: [{ id: 'staging', text: 'Open' }]
|
|
519
|
+
}
|
|
520
|
+
]
|
|
521
|
+
}
|
|
251
522
|
})
|
|
252
523
|
```
|
|
253
524
|
|
|
254
|
-
|
|
525
|
+
Validate button IDs on the server. A button ID is an event value, not an authorization grant.
|
|
255
526
|
|
|
256
|
-
|
|
527
|
+
### Reels and rich media
|
|
257
528
|
|
|
258
|
-
|
|
529
|
+
`sendReels` accepts an array of reel records. The main rich-media path is used for reels, sources, links, tables, and future rich payloads.
|
|
259
530
|
|
|
260
531
|
```js
|
|
261
|
-
await sock.
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
caption: 'Second card description',
|
|
277
|
-
buttons: [
|
|
278
|
-
{ id: 'second', text: 'Select second' }
|
|
279
|
-
]
|
|
280
|
-
}
|
|
281
|
-
]
|
|
532
|
+
await sock.sendReels(jid, [
|
|
533
|
+
{
|
|
534
|
+
title: 'Example reel',
|
|
535
|
+
creator: 'Example creator',
|
|
536
|
+
videoUrl: 'https://cdn.example.com/reel.mp4',
|
|
537
|
+
thumbnailUrl: 'https://cdn.example.com/reel.jpg',
|
|
538
|
+
profileIconUrl: 'https://cdn.example.com/avatar.jpg',
|
|
539
|
+
likesCount: 120,
|
|
540
|
+
sharesCount: 8,
|
|
541
|
+
viewCount: 2400,
|
|
542
|
+
reelSource: 'IG',
|
|
543
|
+
isVerified: true
|
|
544
|
+
}
|
|
545
|
+
], undefined, {
|
|
546
|
+
text: 'Featured reels'
|
|
282
547
|
})
|
|
283
548
|
```
|
|
284
549
|
|
|
285
|
-
|
|
550
|
+
Use a valid MP4 or another supported playable video. Test the URL with a media probe before sending it.
|
|
286
551
|
|
|
287
|
-
For a
|
|
552
|
+
For a general rich response:
|
|
288
553
|
|
|
289
554
|
```js
|
|
290
|
-
await sock.
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
{
|
|
555
|
+
await sock.sendRichMedia(jid, {
|
|
556
|
+
contentText: 'A rich response',
|
|
557
|
+
reels: [
|
|
558
|
+
{
|
|
559
|
+
title: 'Short clip',
|
|
560
|
+
url: 'https://cdn.example.com/clip.mp4'
|
|
561
|
+
}
|
|
294
562
|
]
|
|
295
563
|
})
|
|
296
564
|
```
|
|
297
565
|
|
|
298
|
-
|
|
566
|
+
### Rich button grid
|
|
299
567
|
|
|
300
|
-
|
|
568
|
+
`sendRichButtonGrid` sends ordinary message cards with native-flow buttons. It is distinct from the original Gen4 `richMenu` envelope.
|
|
301
569
|
|
|
302
570
|
```js
|
|
303
|
-
await sock.
|
|
304
|
-
|
|
571
|
+
await sock.sendRichButtonGrid(jid, {
|
|
572
|
+
text: 'Choose a service',
|
|
573
|
+
footer: 'Select one',
|
|
574
|
+
cards: [
|
|
305
575
|
{
|
|
306
|
-
|
|
307
|
-
|
|
576
|
+
title: 'Status',
|
|
577
|
+
image: { url: './status.jpg' },
|
|
578
|
+
buttons: [{ text: 'View status', id: 'status' }]
|
|
308
579
|
},
|
|
309
580
|
{
|
|
310
|
-
|
|
311
|
-
|
|
581
|
+
title: 'Logs',
|
|
582
|
+
image: { url: './logs.jpg' },
|
|
583
|
+
buttons: [{ text: 'View logs', id: 'logs' }]
|
|
312
584
|
}
|
|
313
585
|
]
|
|
314
586
|
})
|
|
315
587
|
```
|
|
316
588
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
## Experimental bot metadata
|
|
320
|
-
|
|
321
|
-
The following methods attach newer `WAProto` bot metadata fields through `messageContextInfo.botMetadata`. They are experimental and may have no visible effect unless the receiving client and server support the corresponding first-party feature.
|
|
589
|
+
## HTML screens and built-in apps
|
|
322
590
|
|
|
323
|
-
###
|
|
591
|
+
### Ordinary HTML message
|
|
324
592
|
|
|
325
593
|
```js
|
|
326
|
-
await sock.
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
toolsUsed: ['web_search', 'image_search'],
|
|
330
|
-
isThinking: true
|
|
594
|
+
await sock.sendHtmlMessage(jid, {
|
|
595
|
+
html: '<h1>Hello</h1><p>Rendered HTML content.</p>',
|
|
596
|
+
trustedSources: []
|
|
331
597
|
})
|
|
332
598
|
```
|
|
333
599
|
|
|
334
|
-
###
|
|
600
|
+
### Tabbed rich HTML screen
|
|
335
601
|
|
|
336
602
|
```js
|
|
337
|
-
await sock.
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
603
|
+
await sock.sendRichHtmlMessage(jid, {
|
|
604
|
+
title: 'Example app',
|
|
605
|
+
url: 'https://your-domain.example',
|
|
606
|
+
trustedSources: ['your-domain.example'],
|
|
607
|
+
tabs: [
|
|
608
|
+
{
|
|
609
|
+
tab_header: 'Home',
|
|
610
|
+
html: '<h1>Home</h1><p>Welcome.</p>'
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
tab_header: 'Help',
|
|
614
|
+
html: '<h2>Help</h2><p>Tap the buttons to continue.</p>'
|
|
615
|
+
}
|
|
616
|
+
]
|
|
342
617
|
})
|
|
343
618
|
```
|
|
344
619
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
```js
|
|
348
|
-
await sock.sendBotToolResult(jid, {
|
|
349
|
-
text: 'Tool result test',
|
|
350
|
-
toolCallId: `tool-${Date.now()}`,
|
|
351
|
-
resolutionData: {
|
|
352
|
-
status: 'success',
|
|
353
|
-
result: { value: 'Completed' }
|
|
354
|
-
}
|
|
355
|
-
})
|
|
356
|
-
```
|
|
620
|
+
`trustedSources` and `url` are application-specific. Sanitize user-controlled HTML before sending it.
|
|
357
621
|
|
|
358
|
-
|
|
622
|
+
### Built-in screens
|
|
359
623
|
|
|
360
624
|
```js
|
|
361
|
-
await sock.
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
status: 'success',
|
|
366
|
-
value: 'Completed'
|
|
367
|
-
})
|
|
368
|
-
})
|
|
625
|
+
await sock.sendSlotMachine(jid)
|
|
626
|
+
await sock.sendMiniApp(jid, { title: 'Pairing mini-app' })
|
|
627
|
+
await sock.sendWebsitePreview(jid, 'https://example.com')
|
|
628
|
+
await sock.sendLinkPreview(jid, 'https://example.com')
|
|
369
629
|
```
|
|
370
630
|
|
|
371
|
-
|
|
631
|
+
The built-in mini-app uses its configured first-party source. Generic rich HTML remains configurable.
|
|
372
632
|
|
|
373
633
|
## Status updates
|
|
374
634
|
|
|
375
|
-
|
|
635
|
+
`sendStatus` sends a status update and resolves recipients from `statusJidList`.
|
|
376
636
|
|
|
377
637
|
```js
|
|
378
638
|
await sock.sendStatus({
|
|
379
|
-
text: 'Service
|
|
639
|
+
text: 'Service online',
|
|
380
640
|
backgroundColor: 0xff102a43,
|
|
381
641
|
font: 2
|
|
382
642
|
}, {
|
|
@@ -384,182 +644,156 @@ await sock.sendStatus({
|
|
|
384
644
|
})
|
|
385
645
|
```
|
|
386
646
|
|
|
387
|
-
|
|
647
|
+
For status mentions:
|
|
648
|
+
|
|
649
|
+
```js
|
|
650
|
+
await sock.sendStatusMention(
|
|
651
|
+
{ text: 'Welcome to the team' },
|
|
652
|
+
['15551234567@s.whatsapp.net']
|
|
653
|
+
)
|
|
654
|
+
```
|
|
388
655
|
|
|
389
|
-
## Groups
|
|
656
|
+
## Groups and group history
|
|
390
657
|
|
|
391
658
|
```js
|
|
392
659
|
const metadata = await sock.groupMetadata(groupJid)
|
|
660
|
+
|
|
393
661
|
await sock.groupParticipantsUpdate(groupJid, [userJid], 'add')
|
|
394
662
|
await sock.groupParticipantsUpdate(groupJid, [userJid], 'remove')
|
|
395
663
|
await sock.groupSettingUpdate(groupJid, 'announcement')
|
|
396
664
|
```
|
|
397
665
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
### Group member labels
|
|
666
|
+
### Member labels
|
|
401
667
|
|
|
402
|
-
`updateMemberLabel` sets the connected account's own
|
|
403
|
-
group. The first argument must be the **group JID** (`123456789-123456@g.us`),
|
|
404
|
-
not the member's individual JID:
|
|
668
|
+
`updateMemberLabel` sets the connected account's own label in a group.
|
|
405
669
|
|
|
406
670
|
```js
|
|
407
671
|
await sock.updateMemberLabel(groupJid, 'Developer')
|
|
672
|
+
await sock.updateMemberLabel(groupJid, '') // remove the label
|
|
408
673
|
```
|
|
409
674
|
|
|
410
|
-
|
|
675
|
+
### Group history sharing
|
|
411
676
|
|
|
412
677
|
```js
|
|
413
|
-
await sock.
|
|
678
|
+
await sock.toggleGroupHistory(groupJid, true) // all members
|
|
679
|
+
await sock.toggleGroupHistory(groupJid, false) // admins only
|
|
414
680
|
```
|
|
415
681
|
|
|
416
|
-
|
|
417
|
-
operation for assigning labels to arbitrary participants; WhatsApp associates
|
|
418
|
-
the label with the account that sends the protocol message.
|
|
682
|
+
## Reports and moderation
|
|
419
683
|
|
|
420
|
-
|
|
684
|
+
The reporting APIs have different wire operations. Use the method that matches the action you intend to perform.
|
|
421
685
|
|
|
422
686
|
```js
|
|
423
|
-
await sock.
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
687
|
+
await sock.reportSpam(
|
|
688
|
+
groupJid,
|
|
689
|
+
[{ id: messageId, from: userJid, t: Math.floor(Date.now() / 1000) }],
|
|
690
|
+
'group_info_report',
|
|
691
|
+
'Example group'
|
|
692
|
+
)
|
|
429
693
|
|
|
430
|
-
await sock.
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
694
|
+
const userAccepted = await sock.reportUser(userJid, 'spam')
|
|
695
|
+
const messageAccepted = await sock.reportMessage(
|
|
696
|
+
userJid,
|
|
697
|
+
messageId,
|
|
698
|
+
'harassment',
|
|
699
|
+
participantJid
|
|
700
|
+
)
|
|
701
|
+
await sock.reportAndBlockUser(userJid, 'scam')
|
|
435
702
|
```
|
|
436
703
|
|
|
437
|
-
|
|
704
|
+
`reportUser` and `reportMessage` return whether WhatsApp acknowledged the request. An acknowledgement is not a guarantee of a particular moderation outcome.
|
|
438
705
|
|
|
439
|
-
##
|
|
706
|
+
## Experimental bot metadata
|
|
707
|
+
|
|
708
|
+
These methods attach experimental fields under `messageContextInfo.botMetadata`.
|
|
440
709
|
|
|
441
710
|
```js
|
|
442
|
-
await sock.
|
|
443
|
-
text: '
|
|
444
|
-
|
|
711
|
+
await sock.sendBotDiagnostics(jid, {
|
|
712
|
+
text: 'Diagnostics test',
|
|
713
|
+
botBackend: 1,
|
|
714
|
+
toolsUsed: ['web_search'],
|
|
715
|
+
isThinking: false
|
|
445
716
|
})
|
|
446
717
|
|
|
447
|
-
await sock.
|
|
448
|
-
text: '
|
|
449
|
-
|
|
718
|
+
await sock.sendBotCommand(jid, {
|
|
719
|
+
text: 'Command test',
|
|
720
|
+
commandName: 'summarize',
|
|
721
|
+
commandDescription: 'Summarize the conversation',
|
|
722
|
+
commandPrompt: 'Summarize the conversation in five bullets'
|
|
450
723
|
})
|
|
451
724
|
|
|
452
|
-
await sock.
|
|
453
|
-
|
|
725
|
+
await sock.sendBotToolResult(jid, {
|
|
726
|
+
text: 'Tool completed',
|
|
727
|
+
toolCallId: 'tool-123',
|
|
728
|
+
resolutionData: { status: 'success', value: 42 }
|
|
454
729
|
})
|
|
455
730
|
```
|
|
456
731
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
## Error handling and reconnection
|
|
732
|
+
These methods do not provide Meta's private verification credentials and must not be used to impersonate a first-party Meta AI message.
|
|
460
733
|
|
|
461
|
-
|
|
734
|
+
## WhatsApp flows and web views
|
|
462
735
|
|
|
463
736
|
```js
|
|
464
|
-
sock.
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
return
|
|
471
|
-
}
|
|
737
|
+
await sock.sendWhatsAppFlow(jid, {
|
|
738
|
+
flowId: 'your-flow-id',
|
|
739
|
+
flowToken: 'your-flow-token',
|
|
740
|
+
cta: 'Open form',
|
|
741
|
+
text: 'Complete this form'
|
|
742
|
+
})
|
|
472
743
|
|
|
473
|
-
|
|
744
|
+
await sock.sendRichWebview(jid, {
|
|
745
|
+
url: 'https://example.com/app',
|
|
746
|
+
text: 'Open the app',
|
|
747
|
+
buttonText: 'Open'
|
|
474
748
|
})
|
|
475
749
|
```
|
|
476
750
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
Version 1.0.6 adds the realvare-style `w:report` methods without replacing plogme's existing evidence-based `reportSpam` method. The methods use different WhatsApp IQ namespaces and should be selected according to the operation you intend to perform.
|
|
751
|
+
Flow identifiers and tokens must belong to a valid business configuration.
|
|
480
752
|
|
|
481
|
-
|
|
482
|
-
| --- | --- | --- |
|
|
483
|
-
| `reportSpam(jid, messages, spamFlow, subject)` | `xmlns="spam"` → `spam_list` | Report a chat or group with message evidence. |
|
|
484
|
-
| `reportUser(jid, reason, waitForAckMs)` | `xmlns="w:report"` → `user` | Report one user. |
|
|
485
|
-
| `reportMessage(jid, messageId, reason, participantJid, waitForAckMs)` | `xmlns="w:report"` → `message` | Report one message. |
|
|
486
|
-
| `reportAndBlockUser(jid, reason, waitForAckMs)` | `w:report` followed by block | Report a user and then block them. |
|
|
753
|
+
## View-once utilities
|
|
487
754
|
|
|
488
755
|
```js
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
'1203630@g.us',
|
|
492
|
-
[{ id: 'ABCD1234', from: '15550001111@s.whatsapp.net', t: 1710000000 }],
|
|
493
|
-
'group_info_report',
|
|
494
|
-
'Example group'
|
|
495
|
-
)
|
|
756
|
+
const info = sock.getViewOnceInfo(message)
|
|
757
|
+
console.log(info)
|
|
496
758
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
'15550001111@s.whatsapp.net', 'ABCD1234', 'harassment',
|
|
501
|
-
'15550001111@s.whatsapp.net'
|
|
502
|
-
)
|
|
503
|
-
await sock.reportAndBlockUser('15550001111@s.whatsapp.net', 'scam')
|
|
759
|
+
if (sock.isViewOnce(message)) {
|
|
760
|
+
await sock.autoVV(message)
|
|
761
|
+
}
|
|
504
762
|
```
|
|
505
763
|
|
|
506
|
-
`
|
|
764
|
+
`autoVV` and `antiVV` are utilities for view-once handling. Their behavior depends on the message shape and client version; use them only for messages you are authorized to process.
|
|
507
765
|
|
|
508
|
-
|
|
766
|
+
## Connection handling
|
|
509
767
|
|
|
510
|
-
|
|
768
|
+
A connection can close because of logout, network interruption, protocol changes, or session invalidation. Avoid starting multiple reconnect loops for the same socket.
|
|
511
769
|
|
|
512
770
|
```js
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
### Two HTML transports
|
|
771
|
+
sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
|
|
772
|
+
if (connection !== 'close') return
|
|
518
773
|
|
|
519
|
-
|
|
774
|
+
const statusCode = new Boom(lastDisconnect?.error)?.output?.statusCode
|
|
775
|
+
if (statusCode === DisconnectReason.loggedOut) {
|
|
776
|
+
console.error('Logged out; pair again with a new session')
|
|
777
|
+
return
|
|
778
|
+
}
|
|
520
779
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
trustedSources: []
|
|
780
|
+
setTimeout(() => {
|
|
781
|
+
connect().catch(console.error)
|
|
782
|
+
}, 3000)
|
|
525
783
|
})
|
|
526
|
-
|
|
527
|
-
await sock.sendRichHtmlMessage(jid, {
|
|
528
|
-
title: 'Games',
|
|
529
|
-
url: 'https://your-domain.example',
|
|
530
|
-
trustedSources: ['your-domain.example'],
|
|
531
|
-
tabs: [
|
|
532
|
-
{ tab_header: 'mini-app', html: '<canvas id="game"></canvas><script>/* game */</script>' },
|
|
533
|
-
{ tab_header: 'Instructions', html: '<h2>How to play</h2><p>Tap to jump.</p>' }
|
|
534
|
-
]
|
|
535
|
-
})
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
The rich transport is deliberately separate because clients that render the normal HTML primitive do not necessarily open the embedded-screen/tabbed envelope the same way.
|
|
539
|
-
|
|
540
|
-
The built-in `sendSlotMachine` keeps its existing ordinary HTML transport. The attached interactive mini-app is available as `sendMiniApp`; because it uses the embedded-screen envelope, plogme configures that built-in game with the owned `pair.crysnova.link` source:
|
|
541
|
-
|
|
542
|
-
```js
|
|
543
|
-
await sock.sendMiniApp(jid)
|
|
544
|
-
await sock.sendMiniApp(jid, { title: 'My mini-app' })
|
|
545
784
|
```
|
|
546
785
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
### Reusable source grep
|
|
550
|
-
|
|
551
|
-
`grepSource` is exported from `lib/Utils/index.js`, and `sock.grepCode` is available after socket creation. It returns exact relative file paths, one-based line numbers, columns, and matching source lines without invoking a shell.
|
|
786
|
+
## Security and removed automatic behavior
|
|
552
787
|
|
|
553
|
-
|
|
554
|
-
const matches = sock.grepCode('sendRichHtmlMessage', { maxResults: 20 })
|
|
555
|
-
console.log(matches)
|
|
556
|
-
// [{ file: 'lib/Socket/messages-send.js', line: 2705, column: 12, text: '...' }]
|
|
788
|
+
Plogme does not automatically follow WhatsApp channels, fingerprint the host machine, contact a remote attestation service, or enforce rebranding through runtime code.
|
|
557
789
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
790
|
+
> [!NOTE]
|
|
791
|
+
> Official update channels are optional. Users who want updates must join them manually:
|
|
792
|
+
>
|
|
793
|
+
> - [CODY AI WhatsApp channel](https://whatsapp.com/channel/0029Vb8296789inZCpWLuS3T)
|
|
794
|
+
> - [CRYSNOVA AI WhatsApp channel](https://whatsapp.com/channel/0029Vb6pe77K0IBn48HLKb38)
|
|
561
795
|
|
|
562
|
-
|
|
796
|
+
The project license still applies. Removing runtime enforcement does not change the license terms.
|
|
563
797
|
|
|
564
798
|
## Development
|
|
565
799
|
|
|
@@ -568,80 +802,18 @@ npm install
|
|
|
568
802
|
npm test
|
|
569
803
|
```
|
|
570
804
|
|
|
571
|
-
Before publishing, verify
|
|
572
|
-
|
|
573
|
-
## License
|
|
574
|
-
|
|
575
|
-
Review the included license before distributing applications built with `plogme`. Keep required notices with redistributed source and binaries.
|
|
576
|
-
|
|
577
|
-
## Support
|
|
578
|
-
|
|
579
|
-
For implementation questions, include the Node.js version, `plogme` version, operating system, relevant error text, and a minimal reproducible example. Never include authentication state or private account data in an issue.
|
|
805
|
+
Before publishing, verify the package contents and ensure no session data, private keys, or environment files are included.
|
|
580
806
|
|
|
807
|
+
The repository includes generated WhatsApp protocol files under `WAProto/`. Changes to generated protocol definitions should be made deliberately and tested against the installed WhatsApp client versions you support.
|
|
581
808
|
|
|
582
|
-
##
|
|
583
|
-
|
|
584
|
-
The bundled WAProto schema is updated to WhatsApp Web version `2.3000.1047412487`, with the generated runtime, TypeScript declarations, and connection version updated together. Selected support includes newsletter follower-invite base/V2 fields, ACP2 receive-state extraction, animated wallpaper encoding, and nested audio in sticker messages. These remain experimental and client-dependent.
|
|
585
|
-
|
|
586
|
-
### Animated wallpaper
|
|
587
|
-
|
|
588
|
-
```js
|
|
589
|
-
await sock.sendMessage(jid, {
|
|
590
|
-
chatTheme: {
|
|
591
|
-
animatedWallpaper: { id: 'wallpaper-id', dimLevel: 0.25 }
|
|
592
|
-
}
|
|
593
|
-
})
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
### Sticker with audio
|
|
809
|
+
## License and support
|
|
597
810
|
|
|
598
|
-
|
|
599
|
-
await sock.sendMessage(jid, {
|
|
600
|
-
sticker: { url: './sticker.webp' },
|
|
601
|
-
stickerAudio: { url: './sound.ogg' }
|
|
602
|
-
})
|
|
603
|
-
```
|
|
811
|
+
Review [`LICENSE`](LICENSE) before redistributing applications or modified source.
|
|
604
812
|
|
|
605
|
-
|
|
813
|
+
For implementation questions, include the Node.js version, Plogme version, operating system, relevant error text, and a minimal reproduction. Do not include authentication state or private account data.
|
|
606
814
|
|
|
607
|
-
|
|
608
|
-
await sock.sendMessage(jid, {
|
|
609
|
-
newsletterFollowerInvite: {
|
|
610
|
-
newsletterJid: '123456789@newsletter',
|
|
611
|
-
newsletterName: 'My newsletter',
|
|
612
|
-
caption: 'Follow this channel'
|
|
613
|
-
}
|
|
614
|
-
})
|
|
615
|
-
|
|
616
|
-
await sock.sendMessage(jid, {
|
|
617
|
-
newsletterFollowerInviteMessageV2: {
|
|
618
|
-
newsletterJid: '123456789@newsletter',
|
|
619
|
-
newsletterName: 'My newsletter',
|
|
620
|
-
caption: 'Follow this channel'
|
|
621
|
-
}
|
|
622
|
-
})
|
|
623
|
-
```
|
|
624
|
-
|
|
625
|
-
### Device-scoped relay options
|
|
626
|
-
|
|
627
|
-
`relayMessage` supports `isSecret`, `protected`, and `me` for supported private-chat device fan-out paths. These select recipients and may add `device_fanout`; they are not encryption, access-control, or delivery guarantees and may not behave identically for groups, statuses, retries, or future clients. They are unrelated to the protobuf field `messageContextInfo.messageSecret`.
|
|
628
|
-
|
|
629
|
-
```js
|
|
630
|
-
await sock.relayMessage(jid, message, {
|
|
631
|
-
messageId: messageId,
|
|
632
|
-
isSecret: true
|
|
633
|
-
})
|
|
634
|
-
```
|
|
635
|
-
|
|
636
|
-
### Explicit album wrapper
|
|
637
|
-
|
|
638
|
-
Albums remain parent/child wire messages: one album header is relayed first, followed by separately encrypted image/video children associated with the parent key. The receiver must group them visually. The explicit wrapper accepts typed media objects and applies a caption to the first child:
|
|
639
|
-
|
|
640
|
-
```js
|
|
641
|
-
await sock.sendAlbumMessage(jid, [
|
|
642
|
-
{ type: 'image', data: { url: './one.jpg' } },
|
|
643
|
-
{ type: 'image', data: { url: './two.jpg' } }
|
|
644
|
-
], { caption: 'Album caption' })
|
|
645
|
-
```
|
|
815
|
+
## References
|
|
646
816
|
|
|
647
|
-
|
|
817
|
+
[1]: https://github.com/crysnovax/baileys "Plogme source repository"
|
|
818
|
+
[2]: https://www.npmjs.com/package/plogme "Plogme on npm"
|
|
819
|
+
[3]: https://github.com/WhiskeySockets/Baileys "Baileys protocol implementation"
|