@crysnovax/baileys 2.6.2 โ†’ 2.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,60 +1,3 @@
1
-
2
- <h2 align="center">
3
- <img src="https://media2.giphy.com/media/QssGEmpkyEOhBCb7e1/giphy.gif?cid=ecf05e47a0n3gi1bfqntqmob8g9aid1oyj2wr3ds3mg700bl&rid=giphy.gif" width="28" />
4
- About Me
5
- <img src="https://media2.giphy.com/media/QssGEmpkyEOhBCb7e1/giphy.gif?cid=ecf05e47a0n3gi1bfqntqmob8g9aid1oyj2wr3ds3mg700bl&rid=giphy.gif" width="28" />
6
- </h2>
7
-
8
- ```javascript
9
- const crysnova = {
10
- name: "CRYSNOVA AI",
11
- location: "๐ŸŒ Global",
12
- role: "Full Stack Developer & Bot Creator",
13
- stack: ["JavaScript", "Node.js", "Cloudflare Workers", "WhatsApp Bot Development"],
14
- interests: ["AI", "Automation", "Open Source", "Building Cool Stuff"],
15
- currentFocus: "Building the most powerful WhatsApp bot ecosystem ๐Ÿš€",
16
- funFact: "My code runs 24/7 on Cloudflare's edge network โšก"
17
- };
18
- ```
19
-
20
- <br />
21
-
22
- <h2 align="center">
23
- <img src="https://media.giphy.com/media/iY8CRBdQXODJSCERIr/giphy.gif" width="28" />
24
- Tech Stack
25
- <img src="https://media.giphy.com/media/iY8CRBdQXODJSCERIr/giphy.gif" width="28" />
26
- </h2>
27
-
28
- <p align="center">
29
- <img src="https://img.shields.io/badge/JavaScript-F7DF1E?style=for-the-badge&logo=javascript&logoColor=black&labelColor=0a0f0a&color=10b981" />
30
- <img src="https://img.shields.io/badge/Node.js-339933?style=for-the-badge&logo=node.js&logoColor=white&labelColor=0a0f0a&color=10b981" />
31
- <img src="https://img.shields.io/badge/Cloudflare-F38020?style=for-the-badge&logo=cloudflare&logoColor=white&labelColor=0a0f0a&color=10b981" />
32
- <img src="https://img.shields.io/badge/Workers-F38020?style=for-the-badge&logo=cloudflareworkers&logoColor=white&labelColor=0a0f0a&color=10b981" />
33
- <img src="https://img.shields.io/badge/GitHub-181717?style=for-the-badge&logo=github&logoColor=white&labelColor=0a0f0a&color=10b981" />
34
- <img src="https://img.shields.io/badge/Baileys-25D366?style=for-the-badge&logo=whatsapp&logoColor=white&labelColor=0a0f0a&color=10b981" />
35
- <img src="https://img.shields.io/badge/API-FF6F00?style=for-the-badge&logo=fastapi&logoColor=white&labelColor=0a0f0a&color=10b981" />
36
- <img src="https://img.shields.io/badge/KV-FF4F00?style=for-the-badge&logo=cloudflare&logoColor=white&labelColor=0a0f0a&color=10b981" />
37
- </p>
38
- <br />
39
-
40
- <h2 align="center">
41
- <img src="https://media.giphy.com/media/W5eoZHPpUx9sapR0eu/giphy.gif" width="28" />
42
- Featured Projects
43
- <img src="https://media.giphy.com/media/W5eoZHPpUx9sapR0eu/giphy.gif" width="28" />
44
- </h2>
45
-
46
- <div align="center">
47
-
48
- | ๐Ÿš€ Project | โญ Stars | ๐Ÿ“ Description |
49
- |-----------|---------|---------------|
50
- | **CRYSNOVA AI** | [![Stars](https://img.shields.io/github/stars/crysnovax/CRYSNOVA_AI?style=flat&color=10b981)](https://github.com/crysnovax/CRYSNOVA_AI) | 550+ Command WhatsApp Bot with AI Integration |
51
- | **API Gateway** | [![Stars](https://img.shields.io/github/stars/crysnovax/API?style=flat&color=10b981)](https://github.com/crysnovax/API) | Nexray Endpoints Unified API Gateway |
52
- | **Economy Engine** | [![Stars](https://img.shields.io/github/stars/crysnovax?style=flat&color=10b981)](https://github.com/crysnovax) | Realistic Virtual Economy with Banking System |
53
-
54
- </div>
55
-
56
-
57
-
58
1
  <p align="center">
59
2
  <img src="https://readme-typing-svg.demolab.com?font=Fira+Code&weight=700&size=32&duration=3000&pause=800&color=10B981&center=true&vCenter=true&width=650&lines=%F0%9F%9A%80+%40crysnovax%2Fbailey%3B+WhatsApp+API+for+Node.js%3B+Rich+Messages+%7C+Meta+AI+Style%3B+Production+Ready+%E2%9C%85" alt="Typing Animation" />
60
3
  </p>
@@ -90,15 +33,18 @@ const crysnova = {
90
33
  | 10 | [Welcome Flow](#welcome-flow) | Auto-greet new contacts with FAQ menus |
91
34
  | 11 | [Payment Messages](#payment-messages) | Invites, invoices, orders, payment requests |
92
35
  | 12 | [Message Options](#message-options) | AI icon, ephemeral, spoilers, view once, raw, and more |
93
- | 13 | [Newsletter Management](#newsletter-management) | Create, update, follow, react, delete newsletters |
94
- | 14 | [Group Management](#group-management) | Create, settings, participants, invites, metadata |
95
- | 15 | [Community Management](#community-management) | Communities, subgroups, linked groups |
96
- | 16 | [Profile & Business](#profile--business) | Profile pictures, business catalog, products, quick replies |
97
- | 17 | [Privacy & Security](#privacy--security) | Last seen, online, status, read receipts, calls |
98
- | 18 | [Events Reference](#events-reference) | Full list of socket event listeners |
99
- | 19 | [Image Processing](#image-processing) | Sharp, NAPI-RS, Jimp auto-detection |
100
- | 20 | [Condition of Use](#condition-of-use) | Channel follow agreement |
101
- | 21 | [Credits](#credits) | Attribution and enhancements |
36
+ | 13 | [Status & Stories](#status--stories) | Post status updates with text, media, mentions |
37
+ | 14 | [Favorites](#favorites) | Manage WhatsApp Favorites list |
38
+ | 15 | [Newsletter Management](#newsletter-management) | Create, update, follow, react, delete newsletters |
39
+ | 16 | [Group Management](#group-management) | Create, settings, participants, invites, metadata |
40
+ | 17 | [Community Management](#community-management) | Communities, subgroups, linked groups |
41
+ | 18 | [Profile & Business](#profile--business) | Profile pictures, business catalog, products, quick replies |
42
+ | 19 | [Privacy & Security](#privacy--security) | Last seen, online, status, read receipts, calls |
43
+ | 20 | [Utility Methods](#utility-methods) | LID mapping, dirty bits, app state sync, props |
44
+ | 21 | [Events Reference](#events-reference) | Full list of socket event listeners |
45
+ | 22 | [Image Processing](#image-processing) | Sharp, NAPI-RS, Jimp auto-detection |
46
+ | 23 | [Condition of Use](#condition-of-use) | Channel follow agreement |
47
+ | 24 | [Credits](#credits) | Attribution and enhancements |
102
48
 
103
49
  ---
104
50
 
@@ -113,12 +59,16 @@ const crysnova = {
113
59
  | Rich Messages | โœ… | Code blocks, tables, inline entities, carousel cards |
114
60
  | Meta AI Style | โœ… | Live thinking indicators without "edited" badges |
115
61
  | Welcome Flow | โœ… | Auto-greet new contacts with interactive FAQ menus |
62
+ | Status Posting | โœ… | Text with colors/fonts, image, video, audio, mentions |
63
+ | Favorites Management | โœ… | Add/remove JIDs with local persistence |
64
+ | HD Profile Picture | โœ… | Full-size upload with no crop or resize via `{ hd: true }` (max 720px) |
65
+ | LID/PN Resolution | โœ… | Cross-resolve LID and phone number JIDs |
66
+ | Member Labels | โœ… | Group participant labels |
116
67
  | No Obfuscation | โœ… | Fully readable, auditable source code |
117
68
  | Newsletter Ready | โœ… | Full media support, quoting, quiz polls |
118
69
  | Image Processing | โœ… | Auto-detects `sharp`, `@napi-rs/image`, or `jimp` |
119
70
  | Safe FFmpeg | โœ… | Uses `spawn` instead of `exec` |
120
71
  | In-Memory Store | โœ… | Reintroduced with minimal ESM adaptation |
121
- | HD Profile Picture | โœ… | Full-size upload with no crop or resize via `{ hd: true }` (max 720px) |
122
72
 
123
73
  ---
124
74
 
@@ -771,7 +721,26 @@ sock.sendMessage(jid, {
771
721
  ]
772
722
  })
773
723
  ```
724
+ ### Rich preview
725
+ ```
726
+ await sock.sendMessage(jid, {
727
+ text: 'https://chat.whatsapp.com/CODE',
728
+ richPreview: true,
729
+ previewTitle: 'My Group',
730
+ previewDescription: '42 members ยท Tap to join',
731
+ previewImage: imageBufferOrUrl // Buffer, or a URL string
732
+ })
733
+ ```
774
734
 
735
+ ### WHATSAPP VERIFIED โ˜‘๏ธ โš‰
736
+ send Media messages with verified WhatsApp check โœ”๏ธ
737
+ ```
738
+ await sock.sendMessage(jid, {
739
+ image: buffer,
740
+ caption: 'Hello',
741
+ verifiedMe: true
742
+ })
743
+ ```
775
744
  ---
776
745
 
777
746
  ## Meta AI Features
@@ -1190,6 +1159,161 @@ sock.sendMessage(jid, {
1190
1159
 
1191
1160
  ---
1192
1161
 
1162
+ ## Status & Stories
1163
+
1164
+ Post WhatsApp status updates with text, media, and targeted mentions.
1165
+
1166
+ ### Text Status
1167
+
1168
+ ```javascript
1169
+ // Plain text status
1170
+ sock.sendMessage(jid, {
1171
+ text: 'Hello world!',
1172
+ status: true
1173
+ })
1174
+
1175
+ // With background color (named)
1176
+ sock.sendMessage(jid, {
1177
+ text: 'Hello world!',
1178
+ status: true,
1179
+ backgroundColor: '#FFD32B2B' // red
1180
+ })
1181
+
1182
+ // With hex color
1183
+ sock.sendMessage(jid, {
1184
+ text: 'Hello world!',
1185
+ status: true,
1186
+ backgroundColor: '#FF0057FF' // blue
1187
+ })
1188
+
1189
+ // With font style (0-5)
1190
+ sock.sendMessage(jid, {
1191
+ text: 'Hello world!',
1192
+ status: true,
1193
+ backgroundColor: '#FF1FA15A', // green
1194
+ font: 2 // norican
1195
+ })
1196
+ ```
1197
+
1198
+ **Available colors:** `red`, `blue`, `green`, `black`, `white`, `purple`, `orange`, `pink`, `yellow`, `teal`
1199
+
1200
+ **Available fonts:** `0=sans`, `1=serif`, `2=norican`, `3=bryndan`, `4=bebasneue`, `5=futura`
1201
+
1202
+ ### Media Status
1203
+
1204
+ ```javascript
1205
+ // Image status
1206
+ sock.sendMessage(jid, {
1207
+ image: { url: './image.jpg' },
1208
+ caption: 'My status!',
1209
+ status: true
1210
+ })
1211
+
1212
+ // Video status
1213
+ sock.sendMessage(jid, {
1214
+ video: { url: './video.mp4' },
1215
+ caption: 'Watch this!',
1216
+ status: true
1217
+ })
1218
+
1219
+ // Audio status
1220
+ sock.sendMessage(jid, {
1221
+ audio: { url: './audio.mp3' },
1222
+ ptt: false,
1223
+ status: true
1224
+ })
1225
+ ```
1226
+
1227
+ ### Status with Targeted Viewers
1228
+
1229
+ ```javascript
1230
+ // Only specific contacts can see the status
1231
+ sock.sendMessage(jid, {
1232
+ text: 'Exclusive status!',
1233
+ status: true,
1234
+ statusJidList: [
1235
+ '628123456789@s.whatsapp.net',
1236
+ '628987654321@s.whatsapp.net'
1237
+ ]
1238
+ })
1239
+ ```
1240
+
1241
+ ### Status Mentions
1242
+
1243
+ ```javascript
1244
+ // Mention users/groups in status (they get a notification)
1245
+ sock.sendMessage([jidA, jidB, jidC], {
1246
+ text: 'Hey check my status!'
1247
+ })
1248
+ ```
1249
+
1250
+ ---
1251
+
1252
+ ## Favorites
1253
+
1254
+ Manage your WhatsApp Favorites list โ€” add, remove, and sync across devices.
1255
+
1256
+ ### Add to Favorites
1257
+
1258
+ ```javascript
1259
+ // Add a single JID
1260
+ await sock.addToFavorites(['628123456789@s.whatsapp.net'])
1261
+
1262
+ // Add multiple JIDs (replaces entire list โ€” merge handled by caller)
1263
+ await sock.addToFavorites([
1264
+ '628123456789@s.whatsapp.net',
1265
+ '628987654321@s.whatsapp.net',
1266
+ '1234@g.us'
1267
+ ])
1268
+ ```
1269
+
1270
+ ### Remove from Favorites
1271
+
1272
+ ```javascript
1273
+ // Remove specific JIDs (pass remaining list after filter)
1274
+ await sock.removeFromFavorites([
1275
+ '628123456789@s.whatsapp.net' // only this one remains
1276
+ ])
1277
+ ```
1278
+
1279
+ ### Full Example with Local Persistence
1280
+
1281
+ ```javascript
1282
+ const fs = require('fs')
1283
+ const path = require('path')
1284
+
1285
+ const FAV_FILE = path.join(__dirname, 'database', 'favorites.json')
1286
+
1287
+ const loadFavs = () => {
1288
+ try { return JSON.parse(fs.readFileSync(FAV_FILE, 'utf8')) }
1289
+ catch { return [] }
1290
+ }
1291
+
1292
+ const saveFavs = (favs) => {
1293
+ fs.mkdirSync(path.dirname(FAV_FILE), { recursive: true })
1294
+ fs.writeFileSync(FAV_FILE, JSON.stringify(favs, null, 2))
1295
+ }
1296
+
1297
+ // Add
1298
+ const existing = loadFavs()
1299
+ const target = '628123456789@s.whatsapp.net'
1300
+ if (!existing.includes(target)) {
1301
+ const merged = [...existing, target]
1302
+ await sock.addToFavorites(merged)
1303
+ saveFavs(merged)
1304
+ }
1305
+
1306
+ // Remove
1307
+ const toRemove = '628123456789@s.whatsapp.net'
1308
+ const remaining = existing.filter(jid => jid !== toRemove)
1309
+ await sock.addToFavorites(remaining)
1310
+ saveFavs(remaining)
1311
+ ```
1312
+
1313
+ > **Note:** WhatsApp favorites use a single app state record. Each `SET` replaces the entire list. Always pass the complete desired array.
1314
+
1315
+ ---
1316
+
1193
1317
  ## Newsletter Management
1194
1318
 
1195
1319
  ```javascript
@@ -1541,6 +1665,91 @@ sock.updateDisableLinkPreviewsPrivacy(true)
1541
1665
 
1542
1666
  ---
1543
1667
 
1668
+ ## Utility Methods
1669
+
1670
+ ### LID / Phone Number Resolution
1671
+
1672
+ ```javascript
1673
+ // Resolve LID โ†” PN cross-mappings
1674
+ const userId = await sock.findUserId('628123456789@s.whatsapp.net')
1675
+ console.log(userId)
1676
+ // { lid: '1234567890@lid', phoneNumber: '628123456789@s.whatsapp.net' }
1677
+
1678
+ const userId2 = await sock.findUserId('1234567890@lid')
1679
+ console.log(userId2)
1680
+ // { lid: '1234567890@lid', phoneNumber: '628123456789@s.whatsapp.net' }
1681
+ ```
1682
+
1683
+ ### Fetch User Status
1684
+
1685
+ ```javascript
1686
+ // Fetch status metadata for one or more users
1687
+ const statusList = await sock.fetchStatus('628123456789@s.whatsapp.net', '628987654321@s.whatsapp.net')
1688
+ ```
1689
+
1690
+ ### Fetch Disappearing Duration
1691
+
1692
+ ```javascript
1693
+ // Get disappearing message duration for contacts
1694
+ const durations = await sock.fetchDisappearingDuration('628123456789@s.whatsapp.net')
1695
+ ```
1696
+
1697
+ ### Bot List
1698
+
1699
+ ```javascript
1700
+ // Fetch official bot list (v2)
1701
+ const bots = await sock.getBotListV2()
1702
+ // [{ jid: '...', personaId: '...' }]
1703
+ ```
1704
+
1705
+ ### Call Links
1706
+
1707
+ ```javascript
1708
+ // Create voice/video call link
1709
+ const token = await sock.createCallLink('audio') // voice call
1710
+ const token2 = await sock.createCallLink('video') // video call
1711
+ const token3 = await sock.createCallLink('video', { // with scheduled event
1712
+ startTime: Date.now() + 3600000
1713
+ })
1714
+ ```
1715
+
1716
+ ### Server Properties
1717
+
1718
+ ```javascript
1719
+ // Access server-assigned AB props
1720
+ console.log(sock.serverProps)
1721
+ // {
1722
+ // privacyTokenOn1to1: true, // tctoken on 1:1 messages
1723
+ // profilePicPrivacyToken: true, // tctoken on profile pic IQs
1724
+ // lidTrustedTokenIssueToLid: false // issue tctokens to LID
1725
+ // }
1726
+ ```
1727
+
1728
+ ### App State Sync
1729
+
1730
+ ```javascript
1731
+ // Force resync specific collections
1732
+ await sock.resyncAppState(['regular_high', 'regular_low'], false)
1733
+
1734
+ // Apply custom app patch
1735
+ await sock.appPatch({
1736
+ syncAction: { ... },
1737
+ index: ['...'],
1738
+ type: 'regular_low',
1739
+ apiVersion: 5,
1740
+ operation: proto.SyncdMutation.SyncdOperation.SET
1741
+ })
1742
+ ```
1743
+
1744
+ ### Clean Dirty Bits
1745
+
1746
+ ```javascript
1747
+ // Clear dirty bits for specific sync types
1748
+ await sock.cleanDirtyBits('account_sync', timestamp)
1749
+ ```
1750
+
1751
+ ---
1752
+
1544
1753
  ## Events Reference
1545
1754
 
1546
1755
  ```javascript
@@ -1654,6 +1863,10 @@ Full credit to the original maintainers and contributors:
1654
1863
  - Rich message types (code blocks, tables, inline entities)
1655
1864
  - Meta AI-style compositing and replay planning
1656
1865
  - Welcome flow with FAQ auto-greeting
1866
+ - Status posting with text, media, colors, fonts, mentions
1867
+ - Favorites management with full list sync
1868
+ - LID/PN cross-resolution
1869
+ - Member labels for groups
1657
1870
  - Newsletter media fixes and quiz support
1658
1871
  - Image processing auto-detection
1659
1872
  - Safe FFmpeg spawn-based execution
@@ -936,6 +936,26 @@ export const makeChatsSocket = (config) => {
936
936
  quickReply: { timestamp, deleted: true }
937
937
  }, '');
938
938
  };
939
+ /**
940
+ * crysnovax@Favorites --- Set complete WhatsApp Favorites list.
941
+ * Replaces server-side list with the provided array (merging is handled by caller).
942
+ * @param jids โ€” complete array of JIDs to set as favorites
943
+ */
944
+ const addToFavorites = (jids) => {
945
+ return chatModify({
946
+ favorites: { jids, add: true }
947
+ }, '');
948
+ };
949
+ /**
950
+ * crysnovax@Favorites --- Remove all favorites (clear list).
951
+ */
952
+ const removeFromFavorites = (jids) => {
953
+ // For single removal, caller must pass remaining list to addToFavorites
954
+ // This sends the provided jids array (should be remaining items after filter)
955
+ return chatModify({
956
+ favorites: { jids, add: true }
957
+ }, '');
958
+ };
939
959
  /**
940
960
  * queries need to be fired on connection open
941
961
  * help ensure parity with WA Web
@@ -1222,6 +1242,8 @@ export const makeChatsSocket = (config) => {
1222
1242
  removeMessageLabel,
1223
1243
  star,
1224
1244
  addOrEditQuickReply,
1225
- removeQuickReply
1245
+ removeQuickReply,
1246
+ addToFavorites,
1247
+ removeFromFavorites
1226
1248
  };
1227
1249
  };
@@ -5,6 +5,7 @@ import { DEFAULT_CACHE_TTLS, HISTORY_SYNC_PAUSED_TIMEOUT_MS, PROCESSABLE_HISTORY
5
5
  import { ALL_WA_PATCH_NAMES } from '../Types/index.js';
6
6
  import { SyncState } from '../Types/State.js';
7
7
  import { chatModificationToAppPatch, decodePatches, decodeSyncdSnapshot, encodeSyncdPatch, ensureLTHashStateVersion, extractSyncdPatches, generateProfilePicture, getHistoryMsg, isAppStateSyncIrrecoverable, isMissingKeyError, MAX_SYNC_ATTEMPTS, newLTHashState, processSyncAction } from '../Utils/index.js';
8
+ import { generateProfilePictureHD } from '../Utils/messages-media.js';
8
9
  import { makeMutex } from '../Utils/make-mutex.js';
9
10
  import processMessage from '../Utils/process-message.js';
10
11
  import { buildTcTokenFromJid } from '../Utils/tc-token-utils.js';
@@ -207,7 +208,15 @@ export const makeChatsSocket = (config) => {
207
208
  }
208
209
  return userId;
209
210
  };
210
- /** update the profile picture for yourself or a group */
211
+ /** update the profile picture for yourself or a group
212
+ *
213
+ * Standard (crop + resize to 720ร—720):
214
+ * sock.updateProfilePicture(jid, content)
215
+ * sock.updateProfilePicture(jid, content, { width: 640, height: 640 })
216
+ *
217
+ * HD (full-size, no crop, no resize):
218
+ * sock.updateProfilePicture(jid, content, { hd: true })
219
+ */
211
220
  const updateProfilePicture = async (jid, content, dimensions) => {
212
221
  let targetJid;
213
222
  if (!jid) {
@@ -219,7 +228,12 @@ export const makeChatsSocket = (config) => {
219
228
  else {
220
229
  targetJid = undefined;
221
230
  }
222
- const { img } = await generateProfilePicture(content, dimensions);
231
+ // crysnovax@HD-Profile --- Dual mode:
232
+ // hd:true โ†’ generateProfilePictureHD (preserves aspect ratio, caps at 1920, manages file size)
233
+ // standard โ†’ generateProfilePicture (720ร—720 square crop, or custom dimensions)
234
+ const { img } = dimensions?.hd
235
+ ? await generateProfilePictureHD(content)
236
+ : await generateProfilePicture(content, dimensions);
223
237
  await query({
224
238
  tag: 'iq',
225
239
  attrs: {
@@ -3,7 +3,7 @@ import { Boom } from '@hapi/boom';
3
3
  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
- import { aggregateMessageKeysNotFromMe, assertMediaContent, assertMeId, bindWaitForEvent, decryptMediaRetryData, DEF_MEDIA_HOST, delay, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, generateWAMessageFromContent, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, hasValidAlbumMedia, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, shouldIncludeBizBinaryNode, unixTimestampSeconds } from '../Utils/index.js';
6
+ import { aggregateMessageKeysNotFromMe, assertMediaContent, assertMeId, bindWaitForEvent, 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
7
  import { AssociationType } from '../Types/index.js';
8
8
  import { getUrlInfo } from '../Utils/link-preview.js';
9
9
  import { makeKeyedMutex, makeMutex } from '../Utils/make-mutex.js';
@@ -1218,6 +1218,169 @@ export const makeMessagesSocket = (config) => {
1218
1218
  : disappearingMessagesInChat;
1219
1219
  await groupToggleEphemeral(jid, value);
1220
1220
  }
1221
+ // crysnovax@Status --- status:true flag routes any message type to status@broadcast
1222
+ // Supports: text with backgroundColor + font, image, video, audio, sticker
1223
+ // Usage: sock.sendMessage(jid, { text: 'Hello', status: true, backgroundColor: '#FF0000', font: 2 })
1224
+ // sock.sendMessage(jid, { audio: buffer, status: true, ptt: false })
1225
+ else if ('status' in content && content.status === true) {
1226
+ const { status: _, backgroundColor, font, statusJidList: contentJidList, ...statusContent } = content;
1227
+ const fullMsg = await generateWAMessage('status@broadcast', statusContent, {
1228
+ logger,
1229
+ userJid,
1230
+ upload: waUploadToServer,
1231
+ mediaCache: config.mediaCache,
1232
+ options: config.options,
1233
+ ...options,
1234
+ ...(backgroundColor ? { backgroundColor } : {}),
1235
+ ...(font !== undefined ? { font } : {}),
1236
+ messageId: generateMessageIDV2(userJid)
1237
+ });
1238
+ await relayMessage('status@broadcast', fullMsg.message, {
1239
+ messageId: fullMsg.key.id,
1240
+ statusJidList: contentJidList || options.statusJidList,
1241
+ additionalAttributes: options.additionalAttributes || {},
1242
+ additionalNodes: options.additionalNodes || []
1243
+ });
1244
+ if (config.emitOwnEvents) {
1245
+ process.nextTick(async () => {
1246
+ await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
1247
+ });
1248
+ }
1249
+ return fullMsg;
1250
+ }
1251
+ // crysnovax@RichPreview --- richPreview:true auto-builds a manually-constructed
1252
+ // extendedTextMessage with a large preview image, bypassing generateWAMessage's
1253
+ // getUrlInfo scraper (which fails on bot-blocked domains like chat.whatsapp.com)
1254
+ // and avoiding the undocumented ~7KB jpegThumbnail size ceiling that causes a
1255
+ // blank/black render on WA clients when exceeded.
1256
+ //
1257
+ // Usage:
1258
+ // sock.sendMessage(jid, {
1259
+ // text: 'https://chat.whatsapp.com/CODE',
1260
+ // richPreview: true,
1261
+ // previewTitle: 'Group Name',
1262
+ // previewDescription: '12 members ยท Tap to join',
1263
+ // previewImage: imageBufferOrUrl // Buffer, or a URL string to fetch
1264
+ // })
1265
+ else if ('richPreview' in content && content.richPreview === true) {
1266
+ const {
1267
+ richPreview: __rp,
1268
+ text: previewLink,
1269
+ previewTitle,
1270
+ previewDescription,
1271
+ previewImage,
1272
+ quoted,
1273
+ ...restContent
1274
+ } = content;
1275
+
1276
+ if (!previewLink || typeof previewLink !== 'string') {
1277
+ throw new Boom('richPreview requires a `text` field containing the URL', { statusCode: 400 });
1278
+ }
1279
+
1280
+ // Resolve previewImage into a raw Buffer, whether given as
1281
+ // a Buffer directly or a URL string to fetch
1282
+ let imageBuffer = null;
1283
+ if (previewImage) {
1284
+ if (Buffer.isBuffer(previewImage)) {
1285
+ imageBuffer = previewImage;
1286
+ }
1287
+ else if (typeof previewImage === 'string') {
1288
+ try {
1289
+ const res = await fetch(previewImage);
1290
+ imageBuffer = Buffer.from(await res.arrayBuffer());
1291
+ }
1292
+ catch (err) {
1293
+ logger?.warn({ err }, 'richPreview: failed to fetch previewImage URL');
1294
+ }
1295
+ }
1296
+ }
1297
+
1298
+ // Small embedded jpegThumbnail โ€” kept under the ~7KB ceiling
1299
+ // that causes WA clients to render a blank/black preview if exceeded.
1300
+ // 296px @ quality 50 (fixed internally by extractImageThumb) sits
1301
+ // safely under that threshold while staying as sharp as reliably possible.
1302
+ let smallThumb = null;
1303
+ if (imageBuffer) {
1304
+ try {
1305
+ const { buffer } = await extractImageThumb(imageBuffer, 296);
1306
+ smallThumb = buffer;
1307
+ }
1308
+ catch (err) {
1309
+ logger?.warn({ err }, 'richPreview: failed to generate small thumbnail');
1310
+ }
1311
+ }
1312
+
1313
+ // Upload the image through the real media pipeline to get a
1314
+ // proper highQualityThumbnail reference (directPath/mediaKey/etc)
1315
+ let hq = null;
1316
+ if (imageBuffer) {
1317
+ try {
1318
+ const prepared = await prepareWAMessageMedia({ image: imageBuffer }, { upload: waUploadToServer });
1319
+ hq = prepared.imageMessage;
1320
+ }
1321
+ catch (err) {
1322
+ logger?.warn({ err }, 'richPreview: failed to upload HQ thumbnail');
1323
+ }
1324
+ }
1325
+
1326
+ const previewMessage = {
1327
+ extendedTextMessage: {
1328
+ text: previewLink,
1329
+ matchedText: previewLink,
1330
+ canonicalUrl: previewLink,
1331
+ title: previewTitle || '',
1332
+ description: previewDescription || '',
1333
+ previewType: 5, // IMAGE
1334
+ jpegThumbnail: smallThumb || undefined,
1335
+ ...(hq
1336
+ ? {
1337
+ thumbnailDirectPath: hq.directPath,
1338
+ mediaKey: hq.mediaKey,
1339
+ mediaKeyTimestamp: hq.mediaKeyTimestamp,
1340
+ thumbnailWidth: hq.width,
1341
+ thumbnailHeight: hq.height,
1342
+ thumbnailSha256: hq.fileSha256,
1343
+ thumbnailEncSha256: hq.fileEncSha256
1344
+ }
1345
+ : {}),
1346
+ ...restContent
1347
+ }
1348
+ };
1349
+
1350
+ const msgId = options.messageId || generateMessageIDV2(userJid);
1351
+
1352
+ if (quoted) {
1353
+ previewMessage.extendedTextMessage.contextInfo = {
1354
+ ...(previewMessage.extendedTextMessage.contextInfo || {}),
1355
+ stanzaId: quoted.key.id,
1356
+ participant: jidNormalizedUser(quoted.key.fromMe ? userJid : (quoted.key.participant || quoted.key.remoteJid)),
1357
+ quotedMessage: quoted.message
1358
+ };
1359
+ }
1360
+
1361
+ await relayMessage(jid, previewMessage, {
1362
+ messageId: msgId,
1363
+ additionalAttributes: options.additionalAttributes || {},
1364
+ additionalNodes: options.additionalNodes || []
1365
+ });
1366
+
1367
+ const fullMsg = {
1368
+ key: {
1369
+ remoteJid: jid,
1370
+ fromMe: true,
1371
+ id: msgId
1372
+ },
1373
+ message: previewMessage,
1374
+ messageTimestamp: unixTimestampSeconds()
1375
+ };
1376
+
1377
+ if (config.emitOwnEvents) {
1378
+ process.nextTick(async () => {
1379
+ await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
1380
+ });
1381
+ }
1382
+ return fullMsg;
1383
+ }
1221
1384
  else {
1222
1385
  const fullMsg = await generateWAMessage(jid, content, {
1223
1386
  logger,