@violetix/baileys 0.0.0-stage → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (458) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +3017 -2
  3. package/WAProto/index.d.ts +15932 -0
  4. package/WAProto/index.js +115856 -0
  5. package/engine-requirements.js +13 -0
  6. package/lib/Defaults/index.d.ts +145 -0
  7. package/lib/Defaults/index.d.ts.map +1 -0
  8. package/lib/Defaults/index.js +157 -0
  9. package/lib/Defaults/index.js.map +1 -0
  10. package/lib/Signal/Group/ciphertext-message.d.ts +10 -0
  11. package/lib/Signal/Group/ciphertext-message.d.ts.map +1 -0
  12. package/lib/Signal/Group/ciphertext-message.js +12 -0
  13. package/lib/Signal/Group/ciphertext-message.js.map +1 -0
  14. package/lib/Signal/Group/group-session-builder.d.ts +8 -0
  15. package/lib/Signal/Group/group-session-builder.d.ts.map +1 -0
  16. package/lib/Signal/Group/group-session-builder.js +30 -0
  17. package/lib/Signal/Group/group-session-builder.js.map +1 -0
  18. package/lib/Signal/Group/group_cipher.d.ts +11 -0
  19. package/lib/Signal/Group/group_cipher.d.ts.map +1 -0
  20. package/lib/Signal/Group/group_cipher.js +82 -0
  21. package/lib/Signal/Group/group_cipher.js.map +1 -0
  22. package/lib/Signal/Group/index.d.ts +12 -0
  23. package/lib/Signal/Group/index.d.ts.map +1 -0
  24. package/lib/Signal/Group/index.js +12 -0
  25. package/lib/Signal/Group/index.js.map +1 -0
  26. package/lib/Signal/Group/keyhelper.d.ts +7 -0
  27. package/lib/Signal/Group/keyhelper.d.ts.map +1 -0
  28. package/lib/Signal/Group/keyhelper.js +18 -0
  29. package/lib/Signal/Group/keyhelper.js.map +1 -0
  30. package/lib/Signal/Group/sender-chain-key.d.ts +14 -0
  31. package/lib/Signal/Group/sender-chain-key.d.ts.map +1 -0
  32. package/lib/Signal/Group/sender-chain-key.js +26 -0
  33. package/lib/Signal/Group/sender-chain-key.js.map +1 -0
  34. package/lib/Signal/Group/sender-key-distribution-message.d.ts +17 -0
  35. package/lib/Signal/Group/sender-key-distribution-message.d.ts.map +1 -0
  36. package/lib/Signal/Group/sender-key-distribution-message.js +63 -0
  37. package/lib/Signal/Group/sender-key-distribution-message.js.map +1 -0
  38. package/lib/Signal/Group/sender-key-message.d.ts +19 -0
  39. package/lib/Signal/Group/sender-key-message.d.ts.map +1 -0
  40. package/lib/Signal/Group/sender-key-message.js +66 -0
  41. package/lib/Signal/Group/sender-key-message.js.map +1 -0
  42. package/lib/Signal/Group/sender-key-name.d.ts +12 -0
  43. package/lib/Signal/Group/sender-key-name.d.ts.map +1 -0
  44. package/lib/Signal/Group/sender-key-name.js +48 -0
  45. package/lib/Signal/Group/sender-key-name.js.map +1 -0
  46. package/lib/Signal/Group/sender-key-record.d.ts +13 -0
  47. package/lib/Signal/Group/sender-key-record.d.ts.map +1 -0
  48. package/lib/Signal/Group/sender-key-record.js +41 -0
  49. package/lib/Signal/Group/sender-key-record.js.map +1 -0
  50. package/lib/Signal/Group/sender-key-state.d.ts +17 -0
  51. package/lib/Signal/Group/sender-key-state.d.ts.map +1 -0
  52. package/lib/Signal/Group/sender-key-state.js +84 -0
  53. package/lib/Signal/Group/sender-key-state.js.map +1 -0
  54. package/lib/Signal/Group/sender-message-key.d.ts +12 -0
  55. package/lib/Signal/Group/sender-message-key.d.ts.map +1 -0
  56. package/lib/Signal/Group/sender-message-key.js +26 -0
  57. package/lib/Signal/Group/sender-message-key.js.map +1 -0
  58. package/lib/Signal/libsignal.d.ts +55 -0
  59. package/lib/Signal/libsignal.d.ts.map +1 -0
  60. package/lib/Signal/libsignal.js +403 -0
  61. package/lib/Signal/libsignal.js.map +1 -0
  62. package/lib/Signal/lid-mapping.d.ts +21 -0
  63. package/lib/Signal/lid-mapping.d.ts.map +1 -0
  64. package/lib/Signal/lid-mapping.js +277 -0
  65. package/lib/Signal/lid-mapping.js.map +1 -0
  66. package/lib/Socket/Client/index.d.ts +3 -0
  67. package/lib/Socket/Client/index.d.ts.map +1 -0
  68. package/lib/Socket/Client/index.js +3 -0
  69. package/lib/Socket/Client/index.js.map +1 -0
  70. package/lib/Socket/Client/types.d.ts +6 -0
  71. package/lib/Socket/Client/types.d.ts.map +1 -0
  72. package/lib/Socket/Client/types.js +93 -0
  73. package/lib/Socket/Client/types.js.map +1 -0
  74. package/lib/Socket/Client/websocket.d.ts +13 -0
  75. package/lib/Socket/Client/websocket.d.ts.map +1 -0
  76. package/lib/Socket/Client/websocket.js +57 -0
  77. package/lib/Socket/Client/websocket.js.map +1 -0
  78. package/lib/Socket/business.d.ts +428 -0
  79. package/lib/Socket/business.d.ts.map +1 -0
  80. package/lib/Socket/business.js +380 -0
  81. package/lib/Socket/business.js.map +1 -0
  82. package/lib/Socket/chats.d.ts +176 -0
  83. package/lib/Socket/chats.d.ts.map +1 -0
  84. package/lib/Socket/chats.js +1238 -0
  85. package/lib/Socket/chats.js.map +1 -0
  86. package/lib/Socket/communities.d.ts +595 -0
  87. package/lib/Socket/communities.d.ts.map +1 -0
  88. package/lib/Socket/communities.js +432 -0
  89. package/lib/Socket/communities.js.map +1 -0
  90. package/lib/Socket/graphql.js +908 -0
  91. package/lib/Socket/groups.d.ts +318 -0
  92. package/lib/Socket/groups.d.ts.map +1 -0
  93. package/lib/Socket/groups.js +364 -0
  94. package/lib/Socket/groups.js.map +1 -0
  95. package/lib/Socket/index.d.ts +947 -0
  96. package/lib/Socket/index.d.ts.map +1 -0
  97. package/lib/Socket/index.js +19 -0
  98. package/lib/Socket/index.js.map +1 -0
  99. package/lib/Socket/interop.js +562 -0
  100. package/lib/Socket/managed-account.js +210 -0
  101. package/lib/Socket/messages-recv.d.ts +367 -0
  102. package/lib/Socket/messages-recv.d.ts.map +1 -0
  103. package/lib/Socket/messages-recv.js +2199 -0
  104. package/lib/Socket/messages-recv.js.map +1 -0
  105. package/lib/Socket/messages-send.d.ts +364 -0
  106. package/lib/Socket/messages-send.d.ts.map +1 -0
  107. package/lib/Socket/messages-send.js +1631 -0
  108. package/lib/Socket/messages-send.js.map +1 -0
  109. package/lib/Socket/mex.d.ts +2 -0
  110. package/lib/Socket/mex.d.ts.map +1 -0
  111. package/lib/Socket/mex.js +42 -0
  112. package/lib/Socket/mex.js.map +1 -0
  113. package/lib/Socket/newsletter.d.ts +315 -0
  114. package/lib/Socket/newsletter.d.ts.map +1 -0
  115. package/lib/Socket/newsletter.js +235 -0
  116. package/lib/Socket/newsletter.js.map +1 -0
  117. package/lib/Socket/privacy.js +448 -0
  118. package/lib/Socket/registration.js +430 -0
  119. package/lib/Socket/socket.d.ts +99 -0
  120. package/lib/Socket/socket.d.ts.map +1 -0
  121. package/lib/Socket/socket.js +1290 -0
  122. package/lib/Socket/socket.js.map +1 -0
  123. package/lib/Store/index.d.ts +4 -0
  124. package/lib/Store/index.d.ts.map +1 -0
  125. package/lib/Store/index.js +4 -0
  126. package/lib/Store/index.js.map +1 -0
  127. package/lib/Store/make-in-memory-store.d.ts +63 -0
  128. package/lib/Store/make-in-memory-store.d.ts.map +1 -0
  129. package/lib/Store/make-in-memory-store.js +462 -0
  130. package/lib/Store/make-in-memory-store.js.map +1 -0
  131. package/lib/Store/make-ordered-dictionary.d.ts +13 -0
  132. package/lib/Store/make-ordered-dictionary.d.ts.map +1 -0
  133. package/lib/Store/make-ordered-dictionary.js +79 -0
  134. package/lib/Store/make-ordered-dictionary.js.map +1 -0
  135. package/lib/Store/object-repository.d.ts +11 -0
  136. package/lib/Store/object-repository.d.ts.map +1 -0
  137. package/lib/Store/object-repository.js +24 -0
  138. package/lib/Store/object-repository.js.map +1 -0
  139. package/lib/Types/Auth.d.ts +60 -0
  140. package/lib/Types/Auth.d.ts.map +1 -0
  141. package/lib/Types/Auth.js +2 -0
  142. package/lib/Types/Auth.js.map +1 -0
  143. package/lib/Types/Bussines.d.ts +9 -0
  144. package/lib/Types/Bussines.d.ts.map +1 -0
  145. package/lib/Types/Bussines.js +2 -0
  146. package/lib/Types/Bussines.js.map +1 -0
  147. package/lib/Types/Call.d.ts +22 -0
  148. package/lib/Types/Call.d.ts.map +1 -0
  149. package/lib/Types/Call.js +2 -0
  150. package/lib/Types/Call.js.map +1 -0
  151. package/lib/Types/Chat.d.ts +3 -0
  152. package/lib/Types/Chat.d.ts.map +1 -0
  153. package/lib/Types/Chat.js +8 -0
  154. package/lib/Types/Chat.js.map +1 -0
  155. package/lib/Types/Contact.d.ts +11 -0
  156. package/lib/Types/Contact.d.ts.map +1 -0
  157. package/lib/Types/Contact.js +2 -0
  158. package/lib/Types/Contact.js.map +1 -0
  159. package/lib/Types/Events.d.ts +41 -0
  160. package/lib/Types/Events.d.ts.map +1 -0
  161. package/lib/Types/Events.js +2 -0
  162. package/lib/Types/Events.js.map +1 -0
  163. package/lib/Types/GroupMetadata.d.ts +36 -0
  164. package/lib/Types/GroupMetadata.d.ts.map +1 -0
  165. package/lib/Types/GroupMetadata.js +2 -0
  166. package/lib/Types/GroupMetadata.js.map +1 -0
  167. package/lib/Types/Label.d.ts +3 -0
  168. package/lib/Types/Label.d.ts.map +1 -0
  169. package/lib/Types/Label.js +25 -0
  170. package/lib/Types/Label.js.map +1 -0
  171. package/lib/Types/LabelAssociation.d.ts +3 -0
  172. package/lib/Types/LabelAssociation.d.ts.map +1 -0
  173. package/lib/Types/LabelAssociation.js +7 -0
  174. package/lib/Types/LabelAssociation.js.map +1 -0
  175. package/lib/Types/Message.d.ts +22 -0
  176. package/lib/Types/Message.d.ts.map +1 -0
  177. package/lib/Types/Message.js +18 -0
  178. package/lib/Types/Message.js.map +1 -0
  179. package/lib/Types/Mex.d.ts +3 -0
  180. package/lib/Types/Mex.d.ts.map +1 -0
  181. package/lib/Types/Mex.js +49 -0
  182. package/lib/Types/Mex.js.map +1 -0
  183. package/lib/Types/Product.d.ts +5 -0
  184. package/lib/Types/Product.d.ts.map +1 -0
  185. package/lib/Types/Product.js +2 -0
  186. package/lib/Types/Product.js.map +1 -0
  187. package/lib/Types/RichType.d.ts +3 -0
  188. package/lib/Types/RichType.d.ts.map +1 -0
  189. package/lib/Types/RichType.js +23 -0
  190. package/lib/Types/RichType.js.map +1 -0
  191. package/lib/Types/Signal.d.ts +10 -0
  192. package/lib/Types/Signal.d.ts.map +1 -0
  193. package/lib/Types/Signal.js +2 -0
  194. package/lib/Types/Signal.js.map +1 -0
  195. package/lib/Types/Socket.d.ts +33 -0
  196. package/lib/Types/Socket.d.ts.map +1 -0
  197. package/lib/Types/Socket.js +2 -0
  198. package/lib/Types/Socket.js.map +1 -0
  199. package/lib/Types/State.d.ts +6 -0
  200. package/lib/Types/State.d.ts.map +1 -0
  201. package/lib/Types/State.js +56 -0
  202. package/lib/Types/State.js.map +1 -0
  203. package/lib/Types/USync.d.ts +9 -0
  204. package/lib/Types/USync.d.ts.map +1 -0
  205. package/lib/Types/USync.js +2 -0
  206. package/lib/Types/USync.js.map +1 -0
  207. package/lib/Types/index.d.ts +16 -0
  208. package/lib/Types/index.d.ts.map +1 -0
  209. package/lib/Types/index.js +26 -0
  210. package/lib/Types/index.js.map +1 -0
  211. package/lib/Utils/a2ui.d.ts +50 -0
  212. package/lib/Utils/a2ui.js +168 -0
  213. package/lib/Utils/anchor-guard.d.ts +71 -0
  214. package/lib/Utils/anchor-guard.js +404 -0
  215. package/lib/Utils/async-utils.js +7 -0
  216. package/lib/Utils/auth-utils.d.ts +59 -0
  217. package/lib/Utils/auth-utils.d.ts.map +1 -0
  218. package/lib/Utils/auth-utils.js +306 -0
  219. package/lib/Utils/auth-utils.js.map +1 -0
  220. package/lib/Utils/browser-utils.d.ts +10 -0
  221. package/lib/Utils/browser-utils.d.ts.map +1 -0
  222. package/lib/Utils/browser-utils.js +29 -0
  223. package/lib/Utils/browser-utils.js.map +1 -0
  224. package/lib/Utils/business.d.ts +50 -0
  225. package/lib/Utils/business.d.ts.map +1 -0
  226. package/lib/Utils/business.js +245 -0
  227. package/lib/Utils/business.js.map +1 -0
  228. package/lib/Utils/chat-utils.d.ts +409 -0
  229. package/lib/Utils/chat-utils.d.ts.map +1 -0
  230. package/lib/Utils/chat-utils.js +872 -0
  231. package/lib/Utils/chat-utils.js.map +1 -0
  232. package/lib/Utils/companion-reg-client-utils.d.ts +10 -0
  233. package/lib/Utils/companion-reg-client-utils.d.ts.map +1 -0
  234. package/lib/Utils/companion-reg-client-utils.js +69 -0
  235. package/lib/Utils/companion-reg-client-utils.js.map +1 -0
  236. package/lib/Utils/crypto-worker.js +20 -0
  237. package/lib/Utils/crypto.d.ts +40 -0
  238. package/lib/Utils/crypto.d.ts.map +1 -0
  239. package/lib/Utils/crypto.js +118 -0
  240. package/lib/Utils/crypto.js.map +1 -0
  241. package/lib/Utils/decode-wa-message.d.ts +85 -0
  242. package/lib/Utils/decode-wa-message.d.ts.map +1 -0
  243. package/lib/Utils/decode-wa-message.js +467 -0
  244. package/lib/Utils/decode-wa-message.js.map +1 -0
  245. package/lib/Utils/event-buffer.d.ts +13 -0
  246. package/lib/Utils/event-buffer.d.ts.map +1 -0
  247. package/lib/Utils/event-buffer.js +651 -0
  248. package/lib/Utils/event-buffer.js.map +1 -0
  249. package/lib/Utils/generics.d.ts +64 -0
  250. package/lib/Utils/generics.d.ts.map +1 -0
  251. package/lib/Utils/generics.js +442 -0
  252. package/lib/Utils/generics.js.map +1 -0
  253. package/lib/Utils/history.d.ts +77 -0
  254. package/lib/Utils/history.d.ts.map +1 -0
  255. package/lib/Utils/history.js +188 -0
  256. package/lib/Utils/history.js.map +1 -0
  257. package/lib/Utils/identity-change-handler.d.ts +14 -0
  258. package/lib/Utils/identity-change-handler.d.ts.map +1 -0
  259. package/lib/Utils/identity-change-handler.js +50 -0
  260. package/lib/Utils/identity-change-handler.js.map +1 -0
  261. package/lib/Utils/ignore-key.d.ts +51 -0
  262. package/lib/Utils/ignore-key.js +174 -0
  263. package/lib/Utils/index.d.ts +29 -0
  264. package/lib/Utils/index.d.ts.map +1 -0
  265. package/lib/Utils/index.js +29 -0
  266. package/lib/Utils/index.js.map +1 -0
  267. package/lib/Utils/link-preview.d.ts +13 -0
  268. package/lib/Utils/link-preview.d.ts.map +1 -0
  269. package/lib/Utils/link-preview.js +85 -0
  270. package/lib/Utils/link-preview.js.map +1 -0
  271. package/lib/Utils/listener-guard.js +48 -0
  272. package/lib/Utils/logger.d.ts +3 -0
  273. package/lib/Utils/logger.d.ts.map +1 -0
  274. package/lib/Utils/logger.js +3 -0
  275. package/lib/Utils/logger.js.map +1 -0
  276. package/lib/Utils/lt-hash.d.ts +7 -0
  277. package/lib/Utils/lt-hash.d.ts.map +1 -0
  278. package/lib/Utils/lt-hash.js +8 -0
  279. package/lib/Utils/lt-hash.js.map +1 -0
  280. package/lib/Utils/make-mutex.d.ts +7 -0
  281. package/lib/Utils/make-mutex.d.ts.map +1 -0
  282. package/lib/Utils/make-mutex.js +33 -0
  283. package/lib/Utils/make-mutex.js.map +1 -0
  284. package/lib/Utils/message-retry-manager.d.ts +80 -0
  285. package/lib/Utils/message-retry-manager.d.ts.map +1 -0
  286. package/lib/Utils/message-retry-manager.js +285 -0
  287. package/lib/Utils/message-retry-manager.js.map +1 -0
  288. package/lib/Utils/messages-media.d.ts +166 -0
  289. package/lib/Utils/messages-media.d.ts.map +1 -0
  290. package/lib/Utils/messages-media.js +979 -0
  291. package/lib/Utils/messages-media.js.map +1 -0
  292. package/lib/Utils/messages.d.ts +47 -0
  293. package/lib/Utils/messages.d.ts.map +1 -0
  294. package/lib/Utils/messages.js +1959 -0
  295. package/lib/Utils/messages.js.map +1 -0
  296. package/lib/Utils/meta-ai-msmsg.d.ts +12 -0
  297. package/lib/Utils/meta-ai-msmsg.js +124 -0
  298. package/lib/Utils/noise-handler.d.ts +21 -0
  299. package/lib/Utils/noise-handler.d.ts.map +1 -0
  300. package/lib/Utils/noise-handler.js +206 -0
  301. package/lib/Utils/noise-handler.js.map +1 -0
  302. package/lib/Utils/offline-node-processor.d.ts +10 -0
  303. package/lib/Utils/offline-node-processor.d.ts.map +1 -0
  304. package/lib/Utils/offline-node-processor.js +40 -0
  305. package/lib/Utils/offline-node-processor.js.map +1 -0
  306. package/lib/Utils/pre-key-manager.d.ts +26 -0
  307. package/lib/Utils/pre-key-manager.d.ts.map +1 -0
  308. package/lib/Utils/pre-key-manager.js +106 -0
  309. package/lib/Utils/pre-key-manager.js.map +1 -0
  310. package/lib/Utils/process-message.d.ts +102 -0
  311. package/lib/Utils/process-message.d.ts.map +1 -0
  312. package/lib/Utils/process-message.js +798 -0
  313. package/lib/Utils/process-message.js.map +1 -0
  314. package/lib/Utils/reporting-utils.d.ts +13 -0
  315. package/lib/Utils/reporting-utils.d.ts.map +1 -0
  316. package/lib/Utils/reporting-utils.js +258 -0
  317. package/lib/Utils/reporting-utils.js.map +1 -0
  318. package/lib/Utils/rich-message-utils.d.ts +49 -0
  319. package/lib/Utils/rich-message-utils.d.ts.map +1 -0
  320. package/lib/Utils/rich-message-utils.js +369 -0
  321. package/lib/Utils/rich-message-utils.js.map +1 -0
  322. package/lib/Utils/session-queue.js +33 -0
  323. package/lib/Utils/signal.d.ts +83 -0
  324. package/lib/Utils/signal.d.ts.map +1 -0
  325. package/lib/Utils/signal.js +201 -0
  326. package/lib/Utils/signal.js.map +1 -0
  327. package/lib/Utils/stanza-ack.d.ts +22 -0
  328. package/lib/Utils/stanza-ack.d.ts.map +1 -0
  329. package/lib/Utils/stanza-ack.js +72 -0
  330. package/lib/Utils/stanza-ack.js.map +1 -0
  331. package/lib/Utils/sync-action-utils.d.ts +3 -0
  332. package/lib/Utils/sync-action-utils.d.ts.map +1 -0
  333. package/lib/Utils/sync-action-utils.js +49 -0
  334. package/lib/Utils/sync-action-utils.js.map +1 -0
  335. package/lib/Utils/tc-token-utils.d.ts +30 -0
  336. package/lib/Utils/tc-token-utils.d.ts.map +1 -0
  337. package/lib/Utils/tc-token-utils.js +164 -0
  338. package/lib/Utils/tc-token-utils.js.map +1 -0
  339. package/lib/Utils/use-multi-file-auth-state.d.ts +13 -0
  340. package/lib/Utils/use-multi-file-auth-state.d.ts.map +1 -0
  341. package/lib/Utils/use-multi-file-auth-state.js +196 -0
  342. package/lib/Utils/use-multi-file-auth-state.js.map +1 -0
  343. package/lib/Utils/use-single-file-auth-state.d.ts +11 -0
  344. package/lib/Utils/use-single-file-auth-state.d.ts.map +1 -0
  345. package/lib/Utils/use-single-file-auth-state.js +118 -0
  346. package/lib/Utils/use-single-file-auth-state.js.map +1 -0
  347. package/lib/Utils/use-sqlite-auth-state.d.ts +11 -0
  348. package/lib/Utils/use-sqlite-auth-state.d.ts.map +1 -0
  349. package/lib/Utils/use-sqlite-auth-state.js +109 -0
  350. package/lib/Utils/use-sqlite-auth-state.js.map +1 -0
  351. package/lib/Utils/validate-connection.d.ts +44 -0
  352. package/lib/Utils/validate-connection.d.ts.map +1 -0
  353. package/lib/Utils/validate-connection.js +210 -0
  354. package/lib/Utils/validate-connection.js.map +1 -0
  355. package/lib/Utils/worker-pool.js +73 -0
  356. package/lib/WABinary/constants.d.ts +62 -0
  357. package/lib/WABinary/constants.d.ts.map +1 -0
  358. package/lib/WABinary/constants.js +1467 -0
  359. package/lib/WABinary/constants.js.map +1 -0
  360. package/lib/WABinary/decode.d.ts +10 -0
  361. package/lib/WABinary/decode.d.ts.map +1 -0
  362. package/lib/WABinary/decode.js +262 -0
  363. package/lib/WABinary/decode.js.map +1 -0
  364. package/lib/WABinary/encode.d.ts +3 -0
  365. package/lib/WABinary/encode.d.ts.map +1 -0
  366. package/lib/WABinary/encode.js +220 -0
  367. package/lib/WABinary/encode.js.map +1 -0
  368. package/lib/WABinary/generic-utils.d.ts +77 -0
  369. package/lib/WABinary/generic-utils.d.ts.map +1 -0
  370. package/lib/WABinary/generic-utils.js +226 -0
  371. package/lib/WABinary/generic-utils.js.map +1 -0
  372. package/lib/WABinary/index.d.ts +6 -0
  373. package/lib/WABinary/index.d.ts.map +1 -0
  374. package/lib/WABinary/index.js +6 -0
  375. package/lib/WABinary/index.js.map +1 -0
  376. package/lib/WABinary/jid-utils.d.ts +29 -0
  377. package/lib/WABinary/jid-utils.d.ts.map +1 -0
  378. package/lib/WABinary/jid-utils.js +96 -0
  379. package/lib/WABinary/jid-utils.js.map +1 -0
  380. package/lib/WABinary/types.d.ts +6 -0
  381. package/lib/WABinary/types.d.ts.map +1 -0
  382. package/lib/WABinary/types.js +2 -0
  383. package/lib/WABinary/types.js.map +1 -0
  384. package/lib/WAM/BinaryInfo.d.ts +8 -0
  385. package/lib/WAM/BinaryInfo.d.ts.map +1 -0
  386. package/lib/WAM/BinaryInfo.js +10 -0
  387. package/lib/WAM/BinaryInfo.js.map +1 -0
  388. package/lib/WAM/constants.d.ts +34927 -0
  389. package/lib/WAM/constants.d.ts.map +1 -0
  390. package/lib/WAM/constants.js +22853 -0
  391. package/lib/WAM/constants.js.map +1 -0
  392. package/lib/WAM/encode.d.ts +2 -0
  393. package/lib/WAM/encode.d.ts.map +1 -0
  394. package/lib/WAM/encode.js +150 -0
  395. package/lib/WAM/encode.js.map +1 -0
  396. package/lib/WAM/index.d.ts +4 -0
  397. package/lib/WAM/index.d.ts.map +1 -0
  398. package/lib/WAM/index.js +4 -0
  399. package/lib/WAM/index.js.map +1 -0
  400. package/lib/WAUSync/Protocols/USyncBusinessProtocol.d.ts +8 -0
  401. package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +99 -0
  402. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +37 -0
  403. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -0
  404. package/lib/WAUSync/Protocols/USyncContactProtocol.js +53 -0
  405. package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -0
  406. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +23 -0
  407. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts.map +1 -0
  408. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +54 -0
  409. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js.map +1 -0
  410. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +13 -0
  411. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts.map +1 -0
  412. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -0
  413. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js.map +1 -0
  414. package/lib/WAUSync/Protocols/USyncFeatureProtocol.d.ts +9 -0
  415. package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +70 -0
  416. package/lib/WAUSync/Protocols/USyncPictureProtocol.d.ts +12 -0
  417. package/lib/WAUSync/Protocols/USyncPictureProtocol.js +28 -0
  418. package/lib/WAUSync/Protocols/USyncSidelistProtocol.d.ts +10 -0
  419. package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +25 -0
  420. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +13 -0
  421. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts.map +1 -0
  422. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +38 -0
  423. package/lib/WAUSync/Protocols/USyncStatusProtocol.js.map +1 -0
  424. package/lib/WAUSync/Protocols/USyncTextStatusProtocol.d.ts +11 -0
  425. package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +34 -0
  426. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
  427. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +1 -0
  428. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +31 -0
  429. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +1 -0
  430. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +39 -0
  431. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts.map +1 -0
  432. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +51 -0
  433. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js.map +1 -0
  434. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +15 -0
  435. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts.map +1 -0
  436. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +29 -0
  437. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js.map +1 -0
  438. package/lib/WAUSync/Protocols/index.d.ts +11 -0
  439. package/lib/WAUSync/Protocols/index.d.ts.map +1 -0
  440. package/lib/WAUSync/Protocols/index.js +11 -0
  441. package/lib/WAUSync/Protocols/index.js.map +1 -0
  442. package/lib/WAUSync/USyncQuery.d.ts +32 -0
  443. package/lib/WAUSync/USyncQuery.d.ts.map +1 -0
  444. package/lib/WAUSync/USyncQuery.js +185 -0
  445. package/lib/WAUSync/USyncQuery.js.map +1 -0
  446. package/lib/WAUSync/USyncUser.d.ts +25 -0
  447. package/lib/WAUSync/USyncUser.d.ts.map +1 -0
  448. package/lib/WAUSync/USyncUser.js +48 -0
  449. package/lib/WAUSync/USyncUser.js.map +1 -0
  450. package/lib/WAUSync/index.d.ts +4 -0
  451. package/lib/WAUSync/index.d.ts.map +1 -0
  452. package/lib/WAUSync/index.js +4 -0
  453. package/lib/WAUSync/index.js.map +1 -0
  454. package/lib/index.d.ts +12 -0
  455. package/lib/index.d.ts.map +1 -0
  456. package/lib/index.js +12 -0
  457. package/lib/index.js.map +1 -0
  458. package/package.json +122 -5
package/README.md CHANGED
@@ -1,3 +1,3018 @@
1
- # Temporary Holding Version
1
+ <h1 align="center">@violetix/baileys</h1>
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ <p align="center">
4
+ A WhatsApp Web API for Node — Baileys v7 with interactive messages, albums, payment
5
+ messages, newsletter media, and the protocol surface upstream does not expose yet.
6
+ <br><br>
7
+ <a href="https://www.npmjs.com/package/@violetix/baileys">
8
+ <img src="https://img.shields.io/npm/v/@violetix/baileys?style=for-the-badge&logo=npm" alt="npm version" />
9
+ </a>
10
+ <a href="https://www.npmjs.com/package/@violetix/baileys">
11
+ <img src="https://img.shields.io/npm/dm/@violetix/baileys?style=for-the-badge&logo=npm" alt="npm downloads" />
12
+ </a>
13
+ <a href="https://github.com/cv3inx/bv2">
14
+ <img src="https://img.shields.io/github/stars/cv3inx/bv2?style=for-the-badge&logo=github" alt="GitHub stars" />
15
+ </a>
16
+ <a href="LICENSE">
17
+ <img src="https://img.shields.io/badge/license-MIT-blue?style=for-the-badge" alt="MIT license" />
18
+ </a>
19
+ <a href="https://nodejs.org">
20
+ <img src="https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js&labelColor=green&logoColor=white&style=for-the-badge" alt="Node.js 20 or newer" />
21
+ </a>
22
+ <a href="#-import-esm--cjs">
23
+ <img src="https://img.shields.io/badge/ESM-only?logo=javascript&labelColor=yellow&logoColor=black&style=for-the-badge" alt="ES modules" />
24
+ </a>
25
+ </p>
26
+
27
+ ```bash
28
+ npm i @violetix/baileys
29
+ ```
30
+
31
+ <details>
32
+ <summary><b>📋 Table of contents</b></summary>
33
+
34
+ - [📥 Installation](#-installation)
35
+ - [🧩 Import (ESM & CJS)](#-import-esm--cjs)
36
+ - [🌐 Connect to WhatsApp (Quick Step)](#-connect-to-whatsapp-quick-step)
37
+ - [🔐 Auth State](#-auth-state)
38
+ - [🗄️ Implementing Data Store](#%EF%B8%8F-implementing-data-store)
39
+ - [🪪 WhatsApp IDs Explain](#-whatsapp-ids-explain)
40
+ - [⚡ Why this fork exists](#-why-this-fork-exists)
41
+ - [🛠️ Upstream Fixes & Improvements](#%EF%B8%8F-upstream-fixes--improvements)
42
+ - [📨 Messages Handling & Compatibility](#-messages-handling--compatibility)
43
+ - [🧩 Additional Message Options](#-additional-message-options)
44
+ - [🆕 WhatsApp Protocol Extensions](#-whatsapp-protocol-extensions)
45
+ - [✉️ Sending Messages](#%EF%B8%8F-sending-messages)
46
+ - [🔠 Text](#-text)
47
+ - [🔔 Mention](#-mention)
48
+ - [😁 Reaction](#-reaction)
49
+ - [📌 Pin Message](#-pin-message)
50
+ - [🔖 Keep Chat](#-keep-chat)
51
+ - [➡️ Forward Message](#%EF%B8%8F-forward-message)
52
+ - [👤 Contact](#-contact)
53
+ - [📍 Location](#-location)
54
+ - [🗓️ Event](#%EF%B8%8F-event)
55
+ - [👥 Group Invite](#-group-invite)
56
+ - [🛍️ Product](#%EF%B8%8F-product)
57
+ - [📊 Poll](#-poll)
58
+ - [💭 Button Response](#-button-response)
59
+ - [✨ Rich Response](#-rich-response)
60
+ - [🧾 Message with Code Block](#-message-with-code-block)
61
+ - [🌏 Message with Inline Entities](#-message-with-inline-entities)
62
+ - [📋 Message with Table](#-message-with-table)
63
+ - [🎞️ Status Mention](#%EF%B8%8F-status-mention)
64
+ - [📁 Sending Media Messages](#-sending-media-messages)
65
+ - [🖼️ Image](#%EF%B8%8F-image)
66
+ - [🎥 Video](#-video)
67
+ - [📃 Sticker](#-sticker)
68
+ - [💽 Audio](#-audio)
69
+ - [🗂️ Document](#%EF%B8%8F-document)
70
+ - [🖼️ Album (Image & Video)](#%EF%B8%8F-album-image--video)
71
+ - [📦 Sticker Pack](#-sticker-pack)
72
+ - [📤 Downloading Media](#-downloading-media)
73
+ - [👉🏻 Sending Interactive Messages](#-sending-interactive-messages)
74
+ - [🔘 Buttons](#-buttons)
75
+ - [📋 List](#-list)
76
+ - [🗄️ Interactive](#%EF%B8%8F-interactive)
77
+ - [🫙 Hydrated Template](#-hydrated-template)
78
+ - [💳 Sending Payment Messages](#-sending-payment-messages)
79
+ - [➕ Invite Payment](#-invite-payment)
80
+ - [🧾 Invoice](#-invoice)
81
+ - [🛍️ Order](#%EF%B8%8F-order)
82
+ - [💳 Request Payment](#-request-payment)
83
+ - [👁️ Other Message Options](#%EF%B8%8F-other-message-options)
84
+ - [🤖 AI Icon](#-ai-icon)
85
+ - [🕒 Ephemeral](#-ephemeral)
86
+ - [📰 External Ad Reply](#-external-ad-reply)
87
+ - [🧑‍🧑‍🧒 Group Status](#%E2%80%8D%E2%80%8D-group-status)
88
+ - [🐱 Lottie Sticker](#-lottie-sticker)
89
+ - [🧩 Raw](#-raw)
90
+ - [🏷️ Secure Meta Service Label](#%EF%B8%8F-secure-meta-service-label)
91
+ - [📑 Spoiler](#-spoiler)
92
+ - [👁️ View Once](#%EF%B8%8F-view-once)
93
+ - [👁️ View Once V2](#%EF%B8%8F-view-once-v2)
94
+ - [👁️ View Once V2 Extension](#%EF%B8%8F-view-once-v2-extension)
95
+ - [♻️ Modify Messages](#%EF%B8%8F-modify-messages)
96
+ - [🗑️ Delete Messages](#%EF%B8%8F-delete-messages)
97
+ - [✏️ Edit Messages](#%EF%B8%8F-edit-messages)
98
+ - [🧰 Additional Contents](#-additional-contents)
99
+ - [🏷️ Find User ID (JID|PN/LID)](#%EF%B8%8F-find-user-id-jidpnlid)
100
+ - [🔑 Request Custom Pairing Code](#-request-custom-pairing-code)
101
+ - [🖼️ Image Processing](#%EF%B8%8F-image-processing)
102
+ - [📣 Newsletter Management](#-newsletter-management)
103
+ - [👥 Group Management](#-group-management)
104
+ - [👥 Community Management](#-community-management)
105
+ - [👤 Profile Management](#-profile-management)
106
+ - [🛒 Business Management](#-business-management)
107
+ - [🔐 Privacy Management](#-privacy-management)
108
+ - [🆔 Username Management](#-username-management)
109
+ - [🔍 USync Queries](#-usync-queries)
110
+ - [🤝 Interoperability (BirdyChat & Haiket)](#-interoperability-birdychat--haiket)
111
+ - [🔒 Account Security (Password & Passkey)](#-account-security-password--passkey)
112
+ - [👪 Managed Accounts & Payments](#-managed-accounts--payments)
113
+ - [🌐 HTTPS GraphQL (Meta AI & Imagine)](#-https-graphql-meta-ai--imagine)
114
+ - [📡 Events](#-events)
115
+ - [Development checks](#development-checks)
116
+ - [📦 Fork Base](#-fork-base)
117
+ - [📣 Credits](#-credits)
118
+
119
+ </details>
120
+
121
+ ## 📥 Installation
122
+
123
+ Requires **Node.js 20 or newer**. The package uses **ES modules (ESM)**.
124
+ Save examples as `.mjs` files, or set `"type": "module"` in your application's `package.json`.
125
+
126
+ ```bash
127
+ # from npm
128
+ npm i @violetix/baileys
129
+
130
+ # or straight from the repository, to track main ahead of a release
131
+ npm i github:cv3inx/bv2
132
+ ```
133
+
134
+ Equivalent `package.json` entries — one or the other, not both:
135
+
136
+ ```json
137
+ {
138
+ "dependencies": {
139
+ "@violetix/baileys": "^0.3.18"
140
+ }
141
+ }
142
+ ```
143
+
144
+ ```json
145
+ {
146
+ "dependencies": {
147
+ "@violetix/baileys": "github:cv3inx/bv2"
148
+ }
149
+ }
150
+ ```
151
+
152
+ ### 🧩 Import (ESM & CJS)
153
+
154
+ ES modules:
155
+
156
+ ```javascript
157
+ import makeWASocket, { useMultiFileAuthState } from "@violetix/baileys";
158
+ ```
159
+
160
+ From CommonJS, use dynamic `import()` inside an async function:
161
+
162
+ ```javascript
163
+ async function main() {
164
+ const { makeWASocket, useMultiFileAuthState } = await import("@violetix/baileys");
165
+ // Create your socket here.
166
+ }
167
+
168
+ main().catch(console.error);
169
+ ```
170
+
171
+ ## 🌐 Connect to WhatsApp (Quick Step)
172
+
173
+ 1. Install the package and the logger used by this example:
174
+
175
+ ```bash
176
+ npm install @violetix/baileys pino
177
+ ```
178
+
179
+ 2. Save the following code as `index.mjs`. Replace `myPhoneNumber` with your WhatsApp number, including the country code and using digits only.
180
+
181
+ ```javascript
182
+ import {
183
+ makeWASocket,
184
+ delay,
185
+ DisconnectReason,
186
+ fetchLatestWaWebVersion,
187
+ useMultiFileAuthState,
188
+ } from "@violetix/baileys";
189
+ import pino from "pino";
190
+
191
+ const myPhoneNumber = "6288888888888";
192
+ const logger = pino({ level: "silent" });
193
+
194
+ async function connectToWhatsApp() {
195
+ const { state, saveCreds } = await useMultiFileAuthState("session");
196
+ const sock = makeWASocket({
197
+ logger,
198
+ auth: state,
199
+ // Optional: resolve the WhatsApp Web version on each connection.
200
+ version: async () => (await fetchLatestWaWebVersion()).version,
201
+ });
202
+
203
+ sock.ev.on("creds.update", saveCreds);
204
+
205
+ sock.ev.on("connection.update", async ({ connection, lastDisconnect }) => {
206
+ try {
207
+ if (connection === "close") {
208
+ const statusCode = lastDisconnect?.error?.output?.statusCode;
209
+ const shouldReconnect = statusCode !== DisconnectReason.loggedOut;
210
+ console.log("Connection closed:", lastDisconnect?.error);
211
+
212
+ if (shouldReconnect) {
213
+ await delay(3000);
214
+ await connectToWhatsApp();
215
+ } else {
216
+ console.log("Logged out. Pair a new session to connect again.");
217
+ }
218
+ } else if (connection === "open") {
219
+ console.log("Connected to WhatsApp");
220
+ }
221
+ } catch (error) {
222
+ console.error("Connection error:", error);
223
+ }
224
+ });
225
+
226
+ sock.ev.on("messages.upsert", async ({ type, messages }) => {
227
+ if (type !== "notify") return;
228
+
229
+ for (const message of messages) {
230
+ const jid = message.key.remoteJid;
231
+ if (!message.message || message.key.fromMe || !jid) continue;
232
+ if (!jid.endsWith("@s.whatsapp.net") && !jid.endsWith("@lid")) continue;
233
+
234
+ try {
235
+ await sock.sendMessage(jid, { text: "Hello world" });
236
+ } catch (error) {
237
+ console.error("Failed to reply:", error);
238
+ }
239
+ }
240
+ });
241
+
242
+ if (!state.creds.registered) {
243
+ // This fork waits internally until the server is ready for pairing.
244
+ const code = await sock.requestPairingCode(myPhoneNumber);
245
+ console.log("Pairing code:", code);
246
+ }
247
+ }
248
+
249
+ connectToWhatsApp().catch(console.error);
250
+ ```
251
+
252
+ 3. Run `node index.mjs`, then enter the printed pairing code in WhatsApp's linked-device flow on your phone.
253
+
254
+ This example replies to new incoming direct messages. Credentials are saved in
255
+ `session/` and reused on later runs. Keep that directory private and out of version control.
256
+
257
+ ### 🔐 Auth State
258
+
259
+ > [!NOTE]
260
+ > You can use the experimental `useSingleFileAuthState` and `useSqliteAuthState` as an alternative to `useMultiFileAuthState`. However, `useSingleFileAuthState` already includes an internal caching mechanism, so there is no need to wrap `state.keys` with `makeCacheableSignalKeyStore`.
261
+
262
+ ## 🗄️ Implementing Data Store
263
+
264
+ `makeInMemoryStore` keeps chats, contacts, and messages in memory. For larger deployments,
265
+ use a persistent store appropriate to your application's memory and retention requirements.
266
+
267
+ Add this import and create the store **outside** `connectToWhatsApp()` in the quick-start example,
268
+ after the `logger` declaration, so reconnects reuse the same store:
269
+
270
+ ```javascript
271
+ import { makeInMemoryStore } from "@violetix/baileys";
272
+
273
+ const storePath = "./store.json";
274
+ const store = makeInMemoryStore({ logger });
275
+ store.readFromFile(storePath);
276
+
277
+ // Create one persistence timer for the application, not one per reconnect.
278
+ setInterval(() => {
279
+ try {
280
+ store.writeToFile(storePath);
281
+ } catch (error) {
282
+ console.error("Failed to save the store:", error);
283
+ }
284
+ }, 180_000).unref();
285
+ ```
286
+
287
+ Add `getMessage` to the `makeWASocket` options so retries and poll updates can retrieve
288
+ previously stored messages:
289
+
290
+ ```javascript
291
+ getMessage: async (key) => {
292
+ if (!key.remoteJid || !key.id) return undefined;
293
+ const message = await store.loadMessage(key.remoteJid, key.id);
294
+ return message?.message;
295
+ },
296
+ ```
297
+
298
+ Immediately after creating each socket, bind its events to the store:
299
+
300
+ ```javascript
301
+ store.bind(sock.ev);
302
+
303
+ sock.ev.on("chats.upsert", () => {
304
+ console.log("Chats:", store.chats.all());
305
+ });
306
+
307
+ sock.ev.on("contacts.upsert", () => {
308
+ console.log("Contacts:", Object.values(store.contacts));
309
+ });
310
+ ```
311
+
312
+ The file snapshot is saved every three minutes. Keep `store.json` private as it contains chat data.
313
+
314
+ ## 🪪 WhatsApp IDs Explain
315
+
316
+ A JID identifies a WhatsApp account, group, or destination. A LID is an account identifier;
317
+ it is not a phone number and must not be converted into one by changing its suffix.
318
+
319
+ | Destination | Example JID |
320
+ | --- | --- |
321
+ | User, addressed by phone number | `19999999999@s.whatsapp.net` |
322
+ | User, addressed by LID | `12699999999@lid` |
323
+ | Group | `123456789-123345@g.us` |
324
+ | Newsletter / channel | `120111111111111111@newsletter` |
325
+ | Meta AI | `11111111111@bot` |
326
+ | Broadcast list | `[timestamp of creation]@broadcast` |
327
+ | Status / stories | `status@broadcast` |
328
+
329
+ Use the JID returned by message events or lookup APIs instead of constructing one from an assumed phone number.
330
+
331
+ > [!IMPORTANT]
332
+ > Senders who set a WhatsApp [username](#-username-management) arrive LID-addressed, and WhatsApp sends **no** phone number alongside them. This fork recovers the phone number from the local LID↔PN mapping and fills in `key.remoteJidAlt` (or `key.participantAlt` in groups).
333
+ > That recovery only works once a mapping exists — from history sync, group metadata, or an earlier chat. On a first-ever contact from a username user there is genuinely no phone number to recover, so **handle `@lid` natively** rather than assuming a phone number is always available.
334
+
335
+ ## ⚡ Why this fork exists
336
+
337
+ This is the Baileys build that runs the Violetics bot fleet: roughly 125 WhatsApp sessions inside
338
+ one Node process. Everything in the table below came out of that, and most of it is invisible until
339
+ you run more than a handful of sockets at once — a bug that costs one session a reconnect costs a
340
+ fleet an hour of flapping.
341
+
342
+ | Change | What it fixes |
343
+ | --- | --- |
344
+ | **Disconnect reasons are named** | `CB:failure` closed with the constant message `Connection Failure` for a 401 device-removal and for a transient 503 alike. A host that re-emits the close as its own `error` event forwards `message` and nothing else, so it could not tell a dead session from a blip and reconnected both — one logout became a re-auth loop and the number got banned. `end()` now appends the code and its `DisconnectReason`: `Connection Failure [401 loggedOut]`. |
345
+ | **Retry caches are bounded** | `sessionRecreateHistory` and `retryCounters` had a TTL but no `max`, and one `MessageRetryManager` exists per socket. `retryCounters` sets `updateAgeOnGet`, so a message stuck in a retry loop refreshed its own expiry indefinitely — the opposite of what a TTL backstop is for. |
346
+ | **Keepalive is per socket, and staggered** | A single process-wide 30s timer pinged every socket in the same tick, while the staleness check used the configured interval — so any `keepAliveIntervalMs` other than 30000 produced false `connectionLost` closes. Each socket now owns its timer and starts on a random offset. |
347
+ | **Housekeeping is not gated on presence** | The 24-hour `tcTokenKnownJids` prune only ran while `isOnline` was true, and `isOnline` is only ever set by `sendPresenceUpdate`. A bot that never marks itself online never pruned anything. |
348
+ | **One failing socket cannot take the host down** | A socket that failed to open, and an unhandled rejection out of `end()` mid-teardown, killed the whole process — and with it every other session sharing it. |
349
+ | **Signal writes persist before success** | Key-store writes are awaited, transaction contexts are isolated per auth store, and session deletion is reflected immediately. Close still waits for the key-store flush barrier. |
350
+ | **The offline queue drains fully** | Baileys asked for one `offline_batch` of 100 stanzas and never asked for another, so a larger backlog stayed on the server and grew on every reconnect. |
351
+
352
+ Upstream feature work — newsletter media, interactive messages, albums, the MEX and HTTPS GraphQL
353
+ surface — is listed under [Upstream Fixes & Improvements](#%EF%B8%8F-upstream-fixes--improvements)
354
+ and the sections after it.
355
+
356
+ ## 🛠️ Upstream Fixes & Improvements
357
+
358
+ - 🖼️ Fixed an issue where media could not be sent to newsletters due to an upstream issue.
359
+ - 📁 Reintroduced [`makeInMemoryStore`](#%EF%B8%8F-implementing-data-store) with a minimal ESM adaptation and small adjustments for Baileys v7.
360
+ - 📦 Switched FFmpeg execution from `exec` to `spawn` for safer process handling.
361
+ - 🗃️ Added [`@napi-rs/image`](https://www.npmjs.com/package/@napi-rs/image) as a supported image processing backend in [`getImageProcessingLibrary()`](#%EF%B8%8F-image-processing), offering a balance between performance and compatibility.
362
+ - 🪪 Recovered the phone number for LID-addressed senders that arrive without one, so [username](#-username-management) users no longer show up as a bare `@lid`.
363
+ - 📞 Routed top-level call stanzas (`<offer>`, `<terminate>`, …) that arrive outside a `<call>` wrapper, and acknowledged them — previously they were never acked, so the server kept redelivering them.
364
+ - 🤖 Decrypted `msmsg` Meta AI bot replies instead of dropping them. The `messageSecret` is captured at send time and recovered from `getMessage` after a restart.
365
+ - 🔍 Parsed the USync fields that were previously left as TODOs: per-protocol errors with backoff, cache `refresh` hints, `side_list`, per-contact privacy tokens, and blocked-by-contact detection.
366
+ - 🆔 Fixed the USync username parser, which returned `null` for the `Uint8Array` payloads the binary decoder actually produces.
367
+ - 📥 Drained the whole offline queue on reconnect. Baileys requested a single `offline_batch` of 100 stanzas and never asked for another, so any larger backlog stayed on the server and grew on every reconnect.
368
+ - 📣 Fanned out sends to broadcast lists (`<id>@broadcast`) over a sender key, using the same `statusJidList` option as status posts for the recipient list.
369
+ - 🔑 Surfaced `keyRequired` from `onWhatsAppUsername()` when the server withholds the account until the 4-digit username key is supplied; previously such rows were dropped.
370
+ - 🔔 Emitted `username.update` (a contact set or removed their `@username`), `lid-mapping.update` (a contact's LID rotated; the known phone number is carried over), and `privacy.update` (privacy settings changed on the phone) from server notifications.
371
+ - 🙈 Skipped placeholder resend requests for `<unavailable/>` messages WhatsApp marks as unrecoverable (`<bot/>`, `hosted="true"`, `type="view_once"`); the previous check compared against attribute values the server never sends.
372
+ - 🪪 Recognised own LID / hosted devices as `fromMe` in status posts and group notifications, and read `remoteJidUsername` from the `username` attribute on 1:1 messages.
373
+ - 📌 Requested `fetch_pinned_messages` on `newsletterMetadata()`, so pinned posts come back with the metadata.
374
+ - 🎞️ Attached the `streamingSidecar` WhatsApp Web sends with video and audio uploads, so recipients can seek and play while downloading. Skipped for mp4 files that are not faststart (`mdat` before `moov`), where a sidecar would make playback fail instead of falling back to a plain download.
375
+ - 🕒 Stamped `disappearingMode` (and `ephemeralSettingTimestamp` when passed via `sendMessage` options) on ephemeral messages, matching WhatsApp Web; without it the peer warns the message will not disappear.
376
+ - 🗳️ Added `decryptPollVoteWithFallback()` / `decryptEventResponseWithFallback()`, which try the poll or event creator's PN and LID forms; voters encrypt with whichever form of the creator JID they hold. Event responses now use it internally.
377
+ - 🆔 Username lookups (`onWhatsAppUsername()`) request LID addressing, as WhatsApp Web does; `USyncQuery.withContactProtocol('lid' | 'pn')` exposes the switch.
378
+ - 🗳️ Poll votes are decrypted again inside `processMessage` and surfaced as `pollUpdates` on `messages.update` (like Baileys v6.4 did), trying the creator's PN and LID forms. Requires `getMessage` to return the poll creation message.
379
+ - 🧾 `hideVoter` / `canAddOption` polls go out as `pollCreationMessageV6`, the only version that carries those flags.
380
+ - 🧠 History sync chunks are decoded one conversation at a time instead of materialising the whole `HistorySync` tree, cutting peak memory on large syncs. Output is byte-identical to the previous path.
381
+ - 🔢 `version` accepts a resolver function, and a `405 client_too_old` failure fetches the live WA Web build and applies it on the next reconnect. `fetchLatestWaWebVersion()` now times out after 10s (`timeoutMs` / `signal` options).
382
+ - 🔐 Passkey-gated (Shortcake) accounts are surfaced: `connection.update { passkeyRequired: true }` plus a warning when the server sends `passkey_prologue_request`. Expired pairing codes (`refresh_code`) are re-registered automatically with the same code, or surfaced as `connection.update { pairingCodeExpired: true }`.
383
+ - 🏢 `onWhatsAppUsername()` also reports `isBusiness` / `pnJid`; the USync business parser treats a `<error/>` child as "not a business" instead of failing the whole query, and `withBusinessProtocol(null)` asks for the verified name only.
384
+ - 🖼️ Added [image polls](#%EF%B8%8F-image-poll): `sendMessage(jid, { imagePoll })` uploads one image per option, hashes each option over its uploaded `fileSha256`, sends the `pollCreationMessageV3` parent with `pollContentType: IMAGE`, then one `pollCreationOptionImageMessage` child per option associated back by `MEDIA_POLL`. `hashImagePollOption()` is exported separately. Ported from [`@rennzsync/baileys`](https://github.com/RennZSync/baileys).
385
+ - 🧩 Added [A2UI widgets](#-a2ui-widget): `sendMessage(jid, { a2ui })` with a declarative builder (`Text`, `Image`, `Video`, `Button`, `Card`, `Column`, `Row`, `Divider`, `CheckBox`, `TextField`, `ChoicePicker`, plus `listCard`) compiled into `interactiveMessage.bloksWidget`. Ported from [`@rennzsync/baileys`](https://github.com/RennZSync/baileys), rebuilt on this fork's own interactive path so the `<biz>` node and button shapes are the existing ones.
386
+ - 🙊 Added the [`exclusive`](#-exclusive-message) send option: a group message addressed to a single member (`to=<group> participant=<member>`, per-device encryption instead of the group sender key), so no other member receives the stanza. The recipient comes from the quoted message's author, or from an explicit jid.
387
+ - 🚫 Added [`sock.ignoreKey()`](#-ignoring-inbound-stanzas): drops matching inbound stanzas before any handler — including the decryption and persistence paths — while still acking so the server stops redelivering. Matches by `remoteJid` / `fromMe` / `id` / `participant` (PN ↔ LID alt attributes included) or by predicate, over `message`, `receipt`, `notification`, `presence`, `chatstate` and `call`. `category='peer'` traffic from your own devices is never dropped, so an app-state key share cannot be filtered away by accident.
388
+ - 🛡️ Added [`createAnchorGuard()`](#%EF%B8%8F-anchor-guard) / `detectBug()`: flags payloads that force-close WhatsApp clients — invisible and combining character floods, mention bombs, oversized native-flow / list / carousel payloads, broken `buttonParamsJson`, over-deep or circular structures — then deletes them and optionally blocks the sender or kicks on burst. Ported from [`@rexxhayanasi/elaina-anchorguard`](https://www.npmjs.com/package/@rexxhayanasi/elaina-anchorguard) (MIT) via [`@rennzsync/baileys`](https://github.com/RennZSync/baileys).
389
+ - 🗓️ Sent `encEventResponseMessage` and `EVENT_EDIT` secrets as `type=event`. Only `eventMessage` was matched, so event responses went out as `type=text` — a pairing a real client never sends, and the server validates stanza shape.
390
+ - 🧾 Stamped `mediatype=group_history` on `messageHistoryBundle` sends, which previously carried no media type at all.
391
+ - 🔑 `useMultiFileAuthState(folder, logger)` and `useSingleFileAuthState(file, logger)` accept a logger. Credential write failures were swallowed entirely (the internal logger was hard-wired to `null`), so a full disk or a permission error lost the session and looked like a random logout on the next boot. Corrupt or unreadable key files are reported too, and `_destroy()` releases the process exit hooks a long-lived multi-session host would otherwise leak.
392
+
393
+ ## 📨 Messages Handling & Compatibility
394
+
395
+ - 📩 Expanded messages support for:
396
+ - 🖼️ [Album Message](#%EF%B8%8F-album-image--video)
397
+ - 👤 [Group Status Message](#%E2%80%8D%E2%80%8D-group-status)
398
+ - 👉🏻 [Interactive Message](#-sending-interactive-messages) (buttons, lists, native flows, templates, carousels).
399
+ - 🎞️ [Status Mention Message](#%EF%B8%8F-status-mention)
400
+ - 📦 [Sticker Pack Message](#-sticker-pack)
401
+ - 🖼️ [Image Poll](#%EF%B8%8F-image-poll)
402
+ - 🧩 [A2UI Widget](#-a2ui-widget)
403
+ - ✨ [Rich Response Message](#-rich-response)
404
+ - 🧾 [Message with Code Blocks](#-message-with-code-block)
405
+ - [🌏 Message with Inline Entities](#-message-with-inline-entities)
406
+ - 📋 [Message with Table](#-message-with-table)
407
+ - 💳 [Payment-related Message](#-sending-payment-messages) (payment requests, invites, orders, invoices).
408
+ - 📰 Simplified sending messages with ad thumbnail using [`externalAdReply`](#-external-ad-reply), without requiring manual `contextInfo`.
409
+ - 💭 Added support for quoting messages inside channel (newsletter).
410
+ - 🎀 Added support for [custom button icon](#%EF%B8%8F-interactive).
411
+
412
+ ## 🧩 Additional Message Options
413
+
414
+ - 👁️ Added optional boolean flags for message handling:
415
+ - 🤖 [`ai`](#-ai-icon) - AI icon on message
416
+ - 📣 [`mentionAll`](#-mention) - Mention all group participants without requiring their JIDs in `mentions` or `mentionedJid`
417
+ - 🔧 [`ephemeral`](#-ephemeral), [`groupStatus`](#%E2%80%8D%E2%80%8D-group-status), [`isLottie`](#-lottie-sticker), [`spoiler`](#-spoiler), [`viewOnce`](#%EF%B8%8F-view-once), [`viewOnceV2`](#%EF%B8%8F-view-once-v2), [`viewOnceV2Extension`](#%EF%B8%8F-view-once-v2-extension), [`interactiveAsTemplate`](#%EF%B8%8F-interactive) - Message wrappers
418
+ - 🔒 [`secureMetaServiceLabel`](#%EF%B8%8F-secure-meta-service-label) - Secure meta service label on message
419
+ - 🙊 [`exclusive`](#-exclusive-message) - Send into a group addressed to one member only
420
+ - 📄 [`raw`](#-raw) - Build your message manually **(DO NOT USE FOR EXPLOITATION)**
421
+ - 🎞️ [`statusPrivacy`](#%EF%B8%8F-status-mention) - Control who receives a status broadcast (`contacts` | `allowlist` | `denylist`)
422
+
423
+ ## 🆕 WhatsApp Protocol Extensions
424
+
425
+ Support for WhatsApp features that upstream Baileys does not expose yet.
426
+
427
+ | Feature | What it does | Reference |
428
+ | ------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------- |
429
+ | 🆔 **Username** | Look up accounts by `@username`, and claim / change / remove your own | [Username Management](#-username-management) |
430
+ | 🔍 **USync protocols** | Business profile, profile picture, About text, side list, and device feature queries | [USync Queries](#-usync-queries) |
431
+ | 🔐 **MEX privacy** | Privacy settings, contact allow/deny lists, About text, contact integrity checks | [Privacy Management](#-privacy-management) |
432
+ | 🤝 **Interoperability** | Cross-platform chats and groups with BirdyChat and Haiket | [Interoperability](#-interoperability-birdychat--haiket) |
433
+ | 🔒 **Account security** | Account password and passkey (FIDO2 / WebAuthn) management | [Account Security](#-account-security-password--passkey) |
434
+ | 👪 **Managed accounts** | Parental / family account linking, payments passkey, UPI onboarding | [Managed Accounts](#-managed-accounts--payments) |
435
+ | 🌐 **HTTPS GraphQL** | Meta AI memory, Imagine image/video generation, AI personas, events, payments | [HTTPS GraphQL](#-https-graphql-meta-ai--imagine) |
436
+ | 🤖 **Meta AI decryption** | Decrypts `msmsg` (`messageSecret`-encrypted) Meta AI bot replies | — |
437
+ | 📞 **Call details** | `callKey` (raw SRTP key), audio/video codecs, group roster, call-link waiting room | [Events](#-events) |
438
+ | 📰 **Newsletter status** | `newsletter.status` event for server-pushed channel posts, with engagement counters | [Events](#-events) |
439
+ | 🪪 **LID fallback** | Recovers the phone number for senders who only expose a `@lid` (e.g. username users) | [WhatsApp IDs Explain](#-whatsapp-ids-explain) |
440
+
441
+ > [!WARNING]
442
+ > These features rely on WhatsApp's internal MEX (GraphQL-over-WebSocket) and HTTPS GraphQL protocols. The numeric query IDs were captured from a specific WhatsApp client version and **may stop working after a WhatsApp update** — a rejected query usually means the ID is stale, not that the code is broken.
443
+
444
+ ## ✉️ Sending Messages
445
+
446
+ > [!NOTE]
447
+ > The examples below are snippets for an already connected `sock`. Get `jid` from
448
+ > `message.key.remoteJid`; `message` is the received message used when quoting or replying.
449
+ > Replace sample IDs and media paths with your own values. Await `sock.sendMessage(...)`
450
+ > inside your async handler when you need to handle send errors.
451
+
452
+ Examples using `fs` require this Node.js import:
453
+
454
+ ```javascript
455
+ import fs from "node:fs";
456
+ ```
457
+
458
+ ### 🔠 Text
459
+
460
+ ```javascript
461
+ // --- Send a regular text message
462
+ sock.sendMessage(
463
+ jid,
464
+ {
465
+ text: "👋🏻 Hello",
466
+ },
467
+ {
468
+ quoted: message,
469
+ },
470
+ );
471
+
472
+ // --- Send a text message with a link preview
473
+ const urlA = "https://www.npmjs.com/package/@violetix/baileys";
474
+
475
+ sock.sendMessage(jid, {
476
+ text: urlA + " 👆🏻 Check it out!",
477
+ linkPreview: {
478
+ "matched-text": urlA,
479
+ title: "🌱 @violetix/baileys",
480
+ description: "Underrated Baileys Fork",
481
+ previewType: 0, // --- Use 1 for video playback in the link preview
482
+ jpegThumbnail: fs.readFileSync("./path/to/image.jpg"),
483
+ },
484
+ });
485
+
486
+ // --- Send a text message with a large link preview and favicon
487
+ import { prepareWAMessageMedia } from "@violetix/baileys";
488
+
489
+ const urlB = "https://www.npmjs.com/package/@violetix/baileys#readme";
490
+
491
+ const { imageMessage: image } = await prepareWAMessageMedia(
492
+ {
493
+ image: {
494
+ url: "./path/to/image.jpg",
495
+ },
496
+ },
497
+ {
498
+ upload: sock.waUploadToServer,
499
+ mediaTypeOverride: "thumbnail-link",
500
+ },
501
+ );
502
+
503
+ // --- Set the thumbnail display size
504
+ image.height = 720;
505
+ image.width = 480;
506
+
507
+ sock.sendMessage(jid, {
508
+ text: urlB + " 👆🏻 Check it out!",
509
+ linkPreview: {
510
+ "matched-text": urlB,
511
+ title: "🌱 @violetix/baileys",
512
+ description: "Underrated Baileys Fork",
513
+ previewType: 0,
514
+ jpegThumbnail: fs.readFileSync("./path/to/image.jpg"),
515
+ highQualityThumbnail: image,
516
+ linkPreviewMetadata: {
517
+ linkMediaDuration: 0, // --- Duration in seconds (for video/audio content)
518
+ socialMediaPostType: 1, // --- Enum: 0 = NONE, 1 = REEL, 2 = LIVE_VIDEO, 3 = LONG_VIDEO, 4 = SINGLE_IMAGE, 5 = CAROUSEL
519
+ }, // --- Additional metadata for large link preview
520
+ },
521
+ favicon: {
522
+ url: "./path/to/tiny-image.ico",
523
+ },
524
+ });
525
+ ```
526
+
527
+ ### 🔔 Mention
528
+
529
+ ```javascript
530
+ // --- Regular mention
531
+ sock.sendMessage(
532
+ jid,
533
+ {
534
+ text: "👋🏻 Hello @628123456789",
535
+ mentions: ["628123456789@s.whatsapp.net"],
536
+ },
537
+ {
538
+ quoted: message,
539
+ },
540
+ );
541
+
542
+ // --- Mention all
543
+ sock.sendMessage(
544
+ jid,
545
+ {
546
+ text: "👋🏻 Hello @all",
547
+ mentionAll: true,
548
+ },
549
+ {
550
+ quoted: message,
551
+ },
552
+ );
553
+ ```
554
+
555
+ ### 😁 Reaction
556
+
557
+ ```javascript
558
+ sock.sendMessage(jid, {
559
+ react: {
560
+ key: message.key,
561
+ text: "✨",
562
+ },
563
+ });
564
+ ```
565
+
566
+ ### 📌 Pin Message
567
+
568
+ ```javascript
569
+ sock.sendMessage(jid, {
570
+ pin: message.key,
571
+ time: 86400, // --- Set the value in seconds: 86400 (1d), 604800 (7d), or 2592000 (30d)
572
+ type: 1, // --- Or 2 to remove
573
+ });
574
+ ```
575
+
576
+ ### 🔖 Keep Chat
577
+
578
+ > [!NOTE]
579
+ > Keep Chat can only be used in chats or groups with disappearing messages enabled.
580
+
581
+ ```javascript
582
+ sock.sendMessage(jid, {
583
+ keep: message.key,
584
+ type: 1, // --- Or 2 to remove
585
+ });
586
+ ```
587
+
588
+ ### ➡️ Forward Message
589
+
590
+ ```javascript
591
+ sock.sendMessage(jid, {
592
+ forward: message,
593
+ force: true, // --- Optional
594
+ });
595
+ ```
596
+
597
+ ### 👤 Contact
598
+
599
+ ```javascript
600
+ const vcard =
601
+ "BEGIN:VCARD\n" +
602
+ "VERSION:3.0\n" +
603
+ "FN:Lia Wynn\n" +
604
+ "ORG:Waitress;\n" +
605
+ "TEL;type=CELL;type=VOICE;waid=628123456789:+62 8123 4567 89\n" +
606
+ "END:VCARD";
607
+
608
+ sock.sendMessage(
609
+ jid,
610
+ {
611
+ contacts: {
612
+ displayName: "Lia Wynn",
613
+ contacts: [{ vcard }],
614
+ },
615
+ },
616
+ {
617
+ quoted: message,
618
+ },
619
+ );
620
+ ```
621
+
622
+ ### 📍 Location
623
+
624
+ ```javascript
625
+ sock.sendMessage(
626
+ jid,
627
+ {
628
+ location: {
629
+ degreesLatitude: 24.121231,
630
+ degreesLongitude: 55.1121221,
631
+ name: "👋🏻 I am here",
632
+ },
633
+ },
634
+ {
635
+ quoted: message,
636
+ },
637
+ );
638
+ ```
639
+
640
+ ### 🗓️ Event
641
+
642
+ ```javascript
643
+ sock.sendMessage(
644
+ jid,
645
+ {
646
+ event: {
647
+ name: "🎶 Meet & Mingle Party",
648
+ description:
649
+ "Meet & Mingle Party is a fun, casual gathering to connect, chat, and build new relationships within the community.",
650
+ call: "audio", // --- Or "video", this field is optional
651
+ startDate: new Date(Date.now() + 3600000),
652
+ endDate: new Date(Date.now() + 28800000),
653
+ isCancelled: false, // --- Optional
654
+ isScheduleCall: false, // --- Optional
655
+ extraGuestsAllowed: false, // --- Optional
656
+ location: {
657
+ name: "Jakarta",
658
+ degreesLatitude: -6.2,
659
+ degreesLongitude: 106.8,
660
+ },
661
+ },
662
+ },
663
+ {
664
+ quoted: message,
665
+ },
666
+ );
667
+ ```
668
+
669
+ ### 👥 Group Invite
670
+
671
+ ```javascript
672
+ const inviteCode = groupUrl.split("chat.whatsapp.com/")[1]?.split("?")[0];
673
+
674
+ const groupJid = "1201111111111@g.us";
675
+ const groupName = "@violetix/baileys";
676
+
677
+ sock.sendMessage(
678
+ jid,
679
+ {
680
+ groupInvite: {
681
+ inviteCode,
682
+ inviteExpiration: Date.now() + 86400000,
683
+ text: "👋🏻 Hello, we invite you to join our group.",
684
+ jid: groupJid,
685
+ subject: groupName,
686
+ },
687
+ },
688
+ {
689
+ quoted: message,
690
+ },
691
+ );
692
+ ```
693
+
694
+ ### 🛍️ Product
695
+
696
+ ```javascript
697
+ import { randomUUID } from "crypto";
698
+
699
+ sock.sendMessage(jid, {
700
+ image: {
701
+ url: "./path/to/image.jpg",
702
+ },
703
+ body: "👋🏻 Check my product here!",
704
+ footer: "@violetix/baileys",
705
+ product: {
706
+ currencyCode: "IDR",
707
+ description: "🛍️ Interesting product!",
708
+ priceAmount1000: 70_000_000,
709
+ productId: randomUUID(),
710
+ productImageCount: 1,
711
+ salePriceAmount1000: 65_000_000,
712
+ signedUrl: "https://www.npmjs.com/package/@violetix/baileys",
713
+ title: "📦 Starseed (Premium)",
714
+ url: "https://www.npmjs.com/package/@violetix/baileys",
715
+ },
716
+ businessOwnerJid: "0@s.whatsapp.net",
717
+ });
718
+ ```
719
+
720
+ ### 📊 Poll
721
+
722
+ ```javascript
723
+ // --- Regular poll message
724
+ sock.sendMessage(jid, {
725
+ poll: {
726
+ name: '🔥 Voting time',
727
+ values: ['Yes', 'No'],
728
+ selectableCount: 1,
729
+ toAnnouncementGroup: false,
730
+ endDate: new Date(Date.now() + 28800000), // --- Optional
731
+ hideVoter: false, // --- Optional
732
+ canAddOption: false // --- Optional
733
+ }
734
+ }, {
735
+ quoted: message
736
+ })
737
+
738
+ // --- Quiz (only for newsletter)
739
+ sock.sendMessage('1211111111111@newsletter', {
740
+ poll: {
741
+ name: '🔥 Quiz',
742
+ values: ['Yes', 'No'],
743
+ correctAnswer: 'Yes',
744
+ pollType: 1
745
+ }
746
+ }, {
747
+ quoted: message
748
+ })
749
+
750
+ // --- Poll result
751
+ sock.sendMessage(jid, {
752
+ pollResult: {
753
+ name: '📝 Poll Result',
754
+ votes: [{
755
+ name: 'Nice',
756
+ voteCount: 10
757
+ }, {
758
+ name: 'Nah',
759
+ voteCount: 2
760
+ }],
761
+ pollType: 0 // Or 1 for quiz
762
+ }
763
+ }, {
764
+ quoted: message
765
+ })
766
+
767
+ // --- Poll update: supply the encrypted vote IV and payload as Buffers/Uint8Arrays.
768
+ sock.sendMessage(jid, {
769
+ pollUpdate: {
770
+ metadata: {},
771
+ key: message.key,
772
+ vote: {
773
+ encIv: encryptedVoteIv,
774
+ encPayload: encryptedVotePayload
775
+ }
776
+ }
777
+ }, {
778
+ quoted: message
779
+ })
780
+ ```
781
+
782
+ ### 🖼️ Image Poll
783
+
784
+ A poll whose options are images instead of text.
785
+
786
+ ```javascript
787
+ sock.sendMessage(jid, {
788
+ imagePoll: {
789
+ name: '🖼️ Pick your favourite',
790
+ selectableCount: 1, // --- Optional, defaults to 1
791
+ options: [
792
+ { name: 'Gambar 1', image: { url: 'https://example.com/1.jpg' } },
793
+ { name: 'Gambar 2', image: { url: 'https://example.com/2.jpg' } }
794
+ ]
795
+ }
796
+ }, {
797
+ quoted: message
798
+ })
799
+ ```
800
+
801
+ Each option's image is uploaded first, because the option hash covers the uploaded media's `fileSha256` — `sha256(hex(sha256(name)) + base64(fileSha256))`, exported as `hashImagePollOption(name, fileSha256)` if you need it on its own. The parent goes out as `pollCreationMessageV3` with `pollContentType: IMAGE` carrying only the names and hashes; the images follow as one `pollCreationOptionImageMessage` each, tied back to the parent by a `MEDIA_POLL` association (the same mechanism albums use). A vote carries the hash, not the name.
802
+
803
+ > [!WARNING]
804
+ > This is a client-side implementation of a message type WhatsApp's proto defines but no Baileys fork ships a builder for. Treat it as experimental and check how it renders on your target client before relying on it.
805
+
806
+ ### 💭 Button Response
807
+
808
+ ```javascript
809
+ // --- Using buttonsResponseMessage
810
+ sock.sendMessage(
811
+ jid,
812
+ {
813
+ type: "plain",
814
+ buttonReply: {
815
+ id: "#Menu",
816
+ displayText: "✨ Interesting Menu",
817
+ },
818
+ },
819
+ {
820
+ quoted: message,
821
+ },
822
+ );
823
+
824
+ // --- Using interactiveResponseMessage
825
+ sock.sendMessage(
826
+ jid,
827
+ {
828
+ flowReply: {
829
+ format: 0,
830
+ text: "💭 Response",
831
+ name: "menu_options",
832
+ paramsJson: JSON.stringify({
833
+ id: "#Menu",
834
+ description: "✨ Interesting Menu",
835
+ }),
836
+ },
837
+ },
838
+ {
839
+ quoted: message,
840
+ },
841
+ );
842
+
843
+ // --- Using listResponseMessage
844
+ sock.sendMessage(
845
+ jid,
846
+ {
847
+ listReply: {
848
+ title: "📄 See More",
849
+ description: "✨ Interesting Menu",
850
+ id: "#Menu",
851
+ },
852
+ },
853
+ {
854
+ quoted: message,
855
+ },
856
+ );
857
+
858
+ // --- Using templateButtonReplyMessage
859
+ sock.sendMessage(
860
+ jid,
861
+ {
862
+ type: "template",
863
+ buttonReply: {
864
+ id: "#Menu",
865
+ displayText: "✨ Interesting Menu",
866
+ index: 1,
867
+ },
868
+ },
869
+ {
870
+ quoted: message,
871
+ },
872
+ );
873
+ ```
874
+
875
+ ### ✨ Rich Response
876
+
877
+ > [!NOTE]
878
+ > `richResponse[]` is a representation of [`submessages[]`](https://baileys.wiki/docs/api/namespaces/proto/interfaces/IAIRichResponseSubMessage) inside `richResponseMessage`.
879
+
880
+ > [!TIP]
881
+ > You can still use the original [`submessages[]`](https://baileys.wiki/docs/api/namespaces/proto/interfaces/IAIRichResponseSubMessage) field directly.
882
+ > The code example below is just an implementation using a helper, not a required structure.
883
+
884
+ ```javascript
885
+ sock.sendMessage(jid, {
886
+ disclaimerText: "RAW submessages structure example",
887
+ richResponse: [
888
+ {
889
+ text: "Example Usage",
890
+ },
891
+ {
892
+ language: "javascript",
893
+ code: [
894
+ {
895
+ highlightType: 0,
896
+ codeContent: 'console.log("Hello, World!")',
897
+ },
898
+ ],
899
+ },
900
+ {
901
+ text: "Pretty simple, right?\n",
902
+ },
903
+ {
904
+ text: "Comparison between Node.js, Bun, and Deno",
905
+ },
906
+ {
907
+ title: "Runtime Comparison",
908
+ table: [
909
+ {
910
+ isHeading: true,
911
+ items: ["", "Node.js", "Bun", "Deno"],
912
+ },
913
+ {
914
+ isHeading: false,
915
+ items: ["Engine", "V8 (C++)", "JavaScriptCore (C++)", "V8 (C++)"],
916
+ },
917
+ {
918
+ isHeading: false,
919
+ items: ["Performance", "4/5", "5/5", "4/5"],
920
+ },
921
+ ],
922
+ },
923
+ {
924
+ text: "Does this help clarify the differences?",
925
+ },
926
+ ],
927
+ });
928
+ ```
929
+
930
+ > [!TIP]
931
+ > You can easily add syntax highlighting by importing `tokenizeCode` directly from Baileys.
932
+
933
+ ```javascript
934
+ import { tokenizeCode } from "@violetix/baileys";
935
+
936
+ const language = "javascript";
937
+ const code = 'console.log("Hello, World!")';
938
+
939
+ sock.sendMessage(jid, {
940
+ disclaimerText: "Example of tokenizing Code Block",
941
+ richResponse: [
942
+ {
943
+ text: "Example Usage",
944
+ },
945
+ {
946
+ language,
947
+ code: tokenizeCode(code, language),
948
+ },
949
+ {
950
+ text: "Pretty simple, right?",
951
+ },
952
+ ],
953
+ });
954
+ ```
955
+
956
+ > 💡 Supported Languages: `css`, `html`, `javascript`, `typescript`, `python`, `golang`, `rust`, `c`, `c#`, `c++`, `bash`, `bat`, `powershell`.
957
+
958
+ ### 🧾 Message with Code Block
959
+
960
+ > [!NOTE]
961
+ > This feature already includes a built-in tokenizer with `tokenizeCode`.
962
+
963
+ ```javascript
964
+ sock.sendMessage(jid, {
965
+ disclaimerText: "Code Block",
966
+ headerText: "## Example Usage",
967
+ contentText: "---",
968
+ code: 'console.log("Hello, World!")',
969
+ language: "javascript",
970
+ footerText: "Pretty simple, right?",
971
+ });
972
+ ```
973
+
974
+ ### 🌏 Message with Inline Entities
975
+
976
+ ```javascript
977
+ sock.sendMessage(jid, {
978
+ disclaimerText: "Inline Entities",
979
+ headerText: "## Check Out!",
980
+ contentText: "---",
981
+ links: [
982
+ {
983
+ text: "1. Google",
984
+ title: "Popular Search Engine",
985
+ url: "https://www.google.com/",
986
+ },
987
+ {
988
+ text: "2. YouTube",
989
+ title: "Popular Streaming Platform",
990
+ url: "https://www.youtube.com/",
991
+ },
992
+ {
993
+ text: "3. Modded Baileys",
994
+ title: "Underrated Baileys Fork",
995
+ url: "https://www.npmjs.com/package/@violetix/baileys",
996
+ },
997
+ ],
998
+ footerText: "---",
999
+ });
1000
+ ```
1001
+
1002
+ ### 📋 Message with Table
1003
+
1004
+ ```javascript
1005
+ sock.sendMessage(jid, {
1006
+ disclaimerText: "Table",
1007
+ headerText: "## Comparison between Node.js, Bun, and Deno",
1008
+ contentText: "---",
1009
+ title: "Runtime Comparison",
1010
+ table: [
1011
+ ["", "Node.js", "Bun", "Deno"],
1012
+ ["Engine", "V8 (C++)", "JavaScriptCore (C++)", "V8 (C++)"],
1013
+ ["Performance", "4/5", "5/5", "4/5"],
1014
+ ],
1015
+ noHeading: false, // --- Optional
1016
+ footerText: "Does this help clarify the differences?",
1017
+ });
1018
+ ```
1019
+
1020
+ ### 🎞️ Status Mention
1021
+
1022
+ ```javascript
1023
+ sock.sendMessage([jidA, jidB, jidC], {
1024
+ text: "Hello! 👋🏻",
1025
+ });
1026
+ ```
1027
+
1028
+ Pass `statusPrivacy` to control who receives a status broadcast.
1029
+ ```javascript
1030
+ sock.sendMessage(
1031
+ "status@broadcast",
1032
+ {
1033
+ text: "Hello! 👋🏻",
1034
+ },
1035
+ {
1036
+ statusPrivacy: "contacts", // 'contacts' | 'allowlist' | 'denylist'
1037
+ },
1038
+ );
1039
+ ```
1040
+
1041
+ > [!NOTE]
1042
+ > The allow and deny lists themselves are managed separately, via [`updatePrivacyContactList`](#-privacy-management).
1043
+
1044
+ ## 📁 Sending Media Messages
1045
+
1046
+ > [!NOTE]
1047
+ > For media messages, you can pass a `Buffer` directly, or an object with either `{ stream: Readable }` or `{ url: string }` (local file path or HTTP/HTTPS URL).
1048
+
1049
+ ### 🖼️ Image
1050
+
1051
+ ```javascript
1052
+ sock.sendMessage(
1053
+ jid,
1054
+ {
1055
+ image: {
1056
+ url: "./path/to/image.jpg",
1057
+ },
1058
+ caption: "🔥 Superb",
1059
+ },
1060
+ {
1061
+ quoted: message,
1062
+ },
1063
+ );
1064
+ ```
1065
+
1066
+ ### 🎥 Video
1067
+
1068
+ ```javascript
1069
+ sock.sendMessage(
1070
+ jid,
1071
+ {
1072
+ video: {
1073
+ url: "./path/to/video.mp4",
1074
+ },
1075
+ gifPlayback: false, // --- Set true if you want to send video as GIF
1076
+ ptv: false, // --- Set true if you want to send video as PTV
1077
+ caption: "🔥 Superb",
1078
+ },
1079
+ {
1080
+ quoted: message,
1081
+ },
1082
+ );
1083
+ ```
1084
+
1085
+ ### 📃 Sticker
1086
+
1087
+ ```javascript
1088
+ sock.sendMessage(
1089
+ jid,
1090
+ {
1091
+ sticker: {
1092
+ url: "./path/to/sticker.webp",
1093
+ },
1094
+ },
1095
+ {
1096
+ quoted: message,
1097
+ },
1098
+ );
1099
+ ```
1100
+
1101
+ ### 💽 Audio
1102
+
1103
+ ```javascript
1104
+ sock.sendMessage(
1105
+ jid,
1106
+ {
1107
+ audio: {
1108
+ url: "./path/to/audio.mp3",
1109
+ },
1110
+ ptt: false, // --- Set true if you want to send audio as Voice Note
1111
+ },
1112
+ {
1113
+ quoted: message,
1114
+ },
1115
+ );
1116
+ ```
1117
+
1118
+ ### 🗂️ Document
1119
+
1120
+ ```javascript
1121
+ sock.sendMessage(
1122
+ jid,
1123
+ {
1124
+ document: {
1125
+ url: "./path/to/document.pdf",
1126
+ },
1127
+ mimetype: "application/pdf",
1128
+ caption: "✨ My work!",
1129
+ },
1130
+ {
1131
+ quoted: message,
1132
+ },
1133
+ );
1134
+ ```
1135
+
1136
+ ### 🖼️ Album (Image & Video)
1137
+
1138
+ ```javascript
1139
+ sock.sendMessage(
1140
+ jid,
1141
+ {
1142
+ album: [
1143
+ {
1144
+ image: {
1145
+ url: "./path/to/image.jpg",
1146
+ },
1147
+ caption: "1st image",
1148
+ },
1149
+ {
1150
+ video: {
1151
+ url: "./path/to/video.mp4",
1152
+ },
1153
+ caption: "1st video",
1154
+ },
1155
+ {
1156
+ image: {
1157
+ url: "./path/to/image.jpg",
1158
+ },
1159
+ caption: "2nd image",
1160
+ },
1161
+ {
1162
+ video: {
1163
+ url: "./path/to/video.mp4",
1164
+ },
1165
+ caption: "2nd video",
1166
+ },
1167
+ ],
1168
+ },
1169
+ {
1170
+ quoted: message,
1171
+ },
1172
+ );
1173
+ ```
1174
+
1175
+ ### 📦 Sticker Pack
1176
+
1177
+ > [!IMPORTANT]
1178
+ > If `sharp` or `@napi-rs/image` is not installed, the `cover` and `stickers` must already be in WebP format.
1179
+
1180
+ ```javascript
1181
+ sock.sendMessage(
1182
+ jid,
1183
+ {
1184
+ cover: {
1185
+ url: "./path/to/image.webp",
1186
+ },
1187
+ stickers: [
1188
+ {
1189
+ data: {
1190
+ url: "./path/to/image.webp",
1191
+ },
1192
+ },
1193
+ {
1194
+ data: {
1195
+ url: "./path/to/image.webp",
1196
+ },
1197
+ },
1198
+ {
1199
+ data: {
1200
+ url: "./path/to/image.webp",
1201
+ },
1202
+ },
1203
+ ],
1204
+ name: "📦 My Sticker Pack",
1205
+ publisher: "🌟 Lia Wynn",
1206
+ description: "@violetix/baileys",
1207
+ },
1208
+ {
1209
+ quoted: message,
1210
+ },
1211
+ );
1212
+ ```
1213
+
1214
+ ## 📤 Downloading Media
1215
+
1216
+ ```javascript
1217
+ import { downloadMediaMessage } from "@violetix/baileys";
1218
+
1219
+ const media = await downloadMediaMessage(message, "buffer", {});
1220
+ ```
1221
+
1222
+ Media downloads verify the complete ciphertext HMAC before returning plaintext.
1223
+ The encrypted object is downloaded in full, even when `startByte` or `endByte` is
1224
+ specified. Byte ranges use an inclusive start and an exclusive end.
1225
+
1226
+ To keep RAM usage bounded, downloads decrypt into a temporary file and expose the
1227
+ requested range after authentication succeeds. This requires writable temporary
1228
+ disk space and delays access to the stream until verification finishes. When using
1229
+ stream mode, consume the stream or call `stream.destroy()` to release its temporary
1230
+ file. HTTP `Range` headers are removed so callers cannot accidentally bypass full
1231
+ verification. `options.signal` supports cancellation.
1232
+
1233
+ For the lower-level `downloadEncryptedContent(url, keys, options)` API, `keys` must
1234
+ include `cipherKey`, `iv`, and `macKey`; `getMediaKeys()` supplies all three.
1235
+
1236
+ ## 👉🏻 Sending Interactive Messages
1237
+
1238
+ ### 🔘 Buttons
1239
+
1240
+ ```javascript
1241
+ // --- Regular buttons message
1242
+ sock.sendMessage(
1243
+ jid,
1244
+ {
1245
+ text: "👆🏻 Buttons!",
1246
+ footer: "@violetix/baileys",
1247
+ buttons: [
1248
+ {
1249
+ text: "👋🏻 SignUp",
1250
+ id: "#SignUp",
1251
+ },
1252
+ ],
1253
+ },
1254
+ {
1255
+ quoted: message,
1256
+ },
1257
+ );
1258
+
1259
+ // --- Buttons with Media & Native Flow
1260
+ sock.sendMessage(
1261
+ jid,
1262
+ {
1263
+ image: {
1264
+ url: "./path/to/image.jpg",
1265
+ },
1266
+ caption: "👆🏻 Buttons and Native Flow!",
1267
+ footer: "@violetix/baileys",
1268
+ buttons: [
1269
+ {
1270
+ text: "👋🏻 Rating",
1271
+ id: "#Rating",
1272
+ },
1273
+ {
1274
+ text: "📋 Select",
1275
+ sections: [
1276
+ {
1277
+ title: "✨ Section 1",
1278
+ rows: [
1279
+ {
1280
+ header: "",
1281
+ title: "💭 Secret Ingredient",
1282
+ description: "",
1283
+ id: "#SecretIngredient",
1284
+ },
1285
+ ],
1286
+ },
1287
+ {
1288
+ title: "✨ Section 2",
1289
+ highlight_label: "🔥 Popular",
1290
+ rows: [
1291
+ {
1292
+ header: "",
1293
+ title: "🏷️ Coupon",
1294
+ description: "",
1295
+ id: "#CouponCode",
1296
+ },
1297
+ ],
1298
+ },
1299
+ ],
1300
+ },
1301
+ ],
1302
+ },
1303
+ {
1304
+ quoted: message,
1305
+ },
1306
+ );
1307
+ ```
1308
+
1309
+ ### 📋 List
1310
+
1311
+ > [!NOTE]
1312
+ > It only works in private chat (`@s.whatsapp.net`).
1313
+
1314
+ ```javascript
1315
+ sock.sendMessage(
1316
+ jid,
1317
+ {
1318
+ text: "📋 List!",
1319
+ footer: "@violetix/baileys",
1320
+ buttonText: "📋 Select",
1321
+ title: "👋🏻 Hello",
1322
+ sections: [
1323
+ {
1324
+ title: "🚀 Menu 1",
1325
+ rows: [
1326
+ {
1327
+ title: "✨ AI",
1328
+ description: "",
1329
+ rowId: "#AI",
1330
+ },
1331
+ ],
1332
+ },
1333
+ {
1334
+ title: "🌱 Menu 2",
1335
+ rows: [
1336
+ {
1337
+ title: "🔍 Search",
1338
+ description: "",
1339
+ rowId: "#Search",
1340
+ },
1341
+ ],
1342
+ },
1343
+ ],
1344
+ },
1345
+ {
1346
+ quoted: message,
1347
+ },
1348
+ );
1349
+ ```
1350
+
1351
+ ### 🗄️ Interactive
1352
+
1353
+ ```javascript
1354
+ // --- Native Flow
1355
+ sock.sendMessage(
1356
+ jid,
1357
+ {
1358
+ image: {
1359
+ url: "./path/to/image.jpg",
1360
+ },
1361
+ caption: "🗄️️ Interactive!",
1362
+ footer: "@violetix/baileys",
1363
+ optionText: "👉🏻 Select Options", // --- Optional, wrap all native flow into a single list
1364
+ optionTitle: "📄 Select Options", // --- Optional
1365
+ offerText: "🏷️ Newest Coupon!", // --- Optional, add an offer into message
1366
+ offerCode: "@violetix/baileys", // --- Optional
1367
+ offerUrl: "https://www.npmjs.com/package/@violetix/baileys", // --- Optional
1368
+ offerExpiration: Date.now() + 3_600_000, // --- Optional
1369
+ nativeFlow: [
1370
+ {
1371
+ text: "👋🏻 Greeting",
1372
+ id: "#Greeting",
1373
+ icon: "review", // --- Optional
1374
+ },
1375
+ {
1376
+ text: "📞 Call",
1377
+ call: "628123456789",
1378
+ },
1379
+ {
1380
+ text: "📋 Copy",
1381
+ copy: "@violetix/baileys",
1382
+ },
1383
+ {
1384
+ text: "🌐 Source",
1385
+ url: "https://www.npmjs.com/package/@violetix/baileys",
1386
+ useWebview: true, // --- Optional
1387
+ },
1388
+ {
1389
+ text: "📋 Select",
1390
+ sections: [
1391
+ {
1392
+ title: "✨ Section 1",
1393
+ rows: [
1394
+ {
1395
+ header: "",
1396
+ title: "🏷️ Coupon",
1397
+ description: "",
1398
+ id: "#CouponCode",
1399
+ },
1400
+ ],
1401
+ },
1402
+ {
1403
+ title: "✨ Section 2",
1404
+ highlight_label: "🔥 Popular",
1405
+ rows: [
1406
+ {
1407
+ header: "",
1408
+ title: "💭 Secret Ingredient",
1409
+ description: "",
1410
+ id: "#SecretIngredient",
1411
+ },
1412
+ ],
1413
+ },
1414
+ ],
1415
+ icon: "default", // --- Optional
1416
+ },
1417
+ ],
1418
+ interactiveAsTemplate: false, // --- Optional, wrap the interactive message into a template
1419
+ },
1420
+ {
1421
+ quoted: message,
1422
+ },
1423
+ );
1424
+
1425
+ // --- Carousel & Native Flow
1426
+ sock.sendMessage(
1427
+ jid,
1428
+ {
1429
+ text: "🗂️ Interactive with Carousel!",
1430
+ footer: "@violetix/baileys",
1431
+ cards: [
1432
+ {
1433
+ image: {
1434
+ url: "./path/to/image.jpg",
1435
+ },
1436
+ caption: "🖼️ Image 1",
1437
+ footer: "🏷️️ Pinterest",
1438
+ nativeFlow: [
1439
+ {
1440
+ text: "🌐 Source",
1441
+ url: "https://www.npmjs.com/package/@violetix/baileys",
1442
+ useWebview: true,
1443
+ },
1444
+ ],
1445
+ },
1446
+ {
1447
+ image: {
1448
+ url: "./path/to/image.jpg",
1449
+ },
1450
+ caption: "🖼️ Image 2",
1451
+ footer: "🏷️ Pinterest",
1452
+ offerText: "🏷️ New Coupon!",
1453
+ offerCode: "@violetix/baileys",
1454
+ offerUrl: "https://www.npmjs.com/package/@violetix/baileys",
1455
+ offerExpiration: Date.now() + 3_600_000,
1456
+ nativeFlow: [
1457
+ {
1458
+ text: "🌐 Source",
1459
+ url: "https://www.npmjs.com/package/@violetix/baileys",
1460
+ },
1461
+ ],
1462
+ },
1463
+ {
1464
+ image: {
1465
+ url: "./path/to/image.jpg",
1466
+ },
1467
+ caption: "🖼️ Image 3",
1468
+ footer: "🏷️ Pinterest",
1469
+ optionText: "👉🏻 Select Options",
1470
+ optionTitle: "👉🏻 Select Options",
1471
+ offerText: "🏷️ New Coupon!",
1472
+ offerCode: "@violetix/baileys",
1473
+ offerUrl: "https://www.npmjs.com/package/@violetix/baileys",
1474
+ offerExpiration: Date.now() + 3_600_000,
1475
+ nativeFlow: [
1476
+ {
1477
+ text: "🛒 Product",
1478
+ id: "#Product",
1479
+ icon: "default",
1480
+ },
1481
+ {
1482
+ text: "🌐 Source",
1483
+ url: "https://www.npmjs.com/package/@violetix/baileys",
1484
+ },
1485
+ ],
1486
+ },
1487
+ ],
1488
+ },
1489
+ {
1490
+ quoted: message,
1491
+ },
1492
+ );
1493
+
1494
+ // --- Native Flow with Audio in the Footer
1495
+ sock.sendMessage(
1496
+ jid,
1497
+ {
1498
+ text: "🔈 Music in the footer!",
1499
+ audioFooter: {
1500
+ url: "./path/to/audio.mp3",
1501
+ }, // --- Like other media upload methods, buffers and streams are supported
1502
+ nativeFlow: [
1503
+ {
1504
+ text: "👍🏻 Good, next",
1505
+ id: "#Next",
1506
+ icon: "review",
1507
+ },
1508
+ {
1509
+ text: "👎🏻 Skip",
1510
+ id: "#Skip",
1511
+ icon: "default",
1512
+ },
1513
+ ],
1514
+ },
1515
+ {
1516
+ quoted: message,
1517
+ },
1518
+ );
1519
+ ```
1520
+
1521
+ ### 🫙 Hydrated Template
1522
+
1523
+ ```javascript
1524
+ sock.sendMessage(
1525
+ jid,
1526
+ {
1527
+ title: "👋🏻 Hello",
1528
+ image: {
1529
+ url: "./path/to/image.jpg",
1530
+ },
1531
+ caption: "🫙 Template!",
1532
+ footer: "@violetix/baileys",
1533
+ templateButtons: [
1534
+ {
1535
+ text: "👉?? Tap Here",
1536
+ id: "#Order",
1537
+ },
1538
+ {
1539
+ text: "🌐 Source",
1540
+ url: "https://www.npmjs.com/package/@violetix/baileys",
1541
+ },
1542
+ {
1543
+ text: "📞 Call",
1544
+ call: "628123456789",
1545
+ },
1546
+ ],
1547
+ },
1548
+ {
1549
+ quoted: message,
1550
+ },
1551
+ );
1552
+ ```
1553
+
1554
+ ## 💳 Sending Payment Messages
1555
+
1556
+ ### ➕ Invite Payment
1557
+
1558
+ ```javascript
1559
+ sock.sendMessage(jid, {
1560
+ paymentInviteServiceType: 3, // 1, 2, or 3
1561
+ });
1562
+ ```
1563
+
1564
+ ### 🧾 Invoice
1565
+
1566
+ > [!NOTE]
1567
+ > Invoice message are not supported yet.
1568
+
1569
+ ```javascript
1570
+ sock.sendMessage(jid, {
1571
+ image: {
1572
+ url: "./path/to/image.jpg",
1573
+ },
1574
+ invoiceNote: "🏷️ Invoice",
1575
+ });
1576
+ ```
1577
+
1578
+ ### 🛍️ Order
1579
+
1580
+ ```javascript
1581
+ sock.sendMessage(
1582
+ chat,
1583
+ {
1584
+ orderText: "🛍️ Order",
1585
+ thumbnail: fs.readFileSync("./path/to/image.jpg"), // --- Must in buffer format
1586
+ },
1587
+ {
1588
+ quoted: message,
1589
+ },
1590
+ );
1591
+ ```
1592
+
1593
+ ### 💳 Request Payment
1594
+
1595
+ ```javascript
1596
+ sock.sendMessage(jid, {
1597
+ text: "💳 Request Payment",
1598
+ requestPaymentFrom: "0@s.whatsapp.net",
1599
+ });
1600
+ ```
1601
+
1602
+ ## 👁️ Other Message Options
1603
+
1604
+ ### 🤖 AI Icon
1605
+
1606
+ > [!NOTE]
1607
+ > It only works in private chat (`@s.whatsapp.net`).
1608
+
1609
+ ```javascript
1610
+ sock.sendMessage(
1611
+ jid,
1612
+ {
1613
+ image: {
1614
+ url: "./path/to/image.jpg",
1615
+ },
1616
+ caption: "🤖 With AI icon!",
1617
+ ai: true,
1618
+ },
1619
+ {
1620
+ quoted: message,
1621
+ },
1622
+ );
1623
+ ```
1624
+
1625
+ ### 🕒 Ephemeral
1626
+
1627
+ > [!NOTE]
1628
+ > Wrap message into `ephemeralMessage`
1629
+
1630
+ ```javascript
1631
+ sock.sendMessage(jid, {
1632
+ image: {
1633
+ url: "./path/to/image.jpg",
1634
+ },
1635
+ caption: "👁️ Ephemeral",
1636
+ ephemeral: true,
1637
+ });
1638
+ ```
1639
+
1640
+ ### 📰 External Ad Reply
1641
+
1642
+ > [!NOTE]
1643
+ > Add an ad thumbnail to messages (may not be displayed on some WhatsApp versions).
1644
+
1645
+ ```javascript
1646
+ sock.sendMessage(
1647
+ jid,
1648
+ {
1649
+ text: "📰 External Ad Reply",
1650
+ externalAdReply: {
1651
+ title: "📝 Did you know?",
1652
+ body: "❓ I dont know",
1653
+ thumbnail: fs.readFileSync("./path/to/image.jpg"), // --- Must in buffer format
1654
+ largeThumbnail: false, // --- Or true for bigger thumbnail
1655
+ url: "https://www.npmjs.com/package/@violetix/baileys", // --- Optional, used for WhatsApp internal thumbnail caching and direct URL
1656
+ },
1657
+ },
1658
+ {
1659
+ quoted: message,
1660
+ },
1661
+ );
1662
+ ```
1663
+
1664
+ ### 🧑‍🧑‍🧒 Group Status
1665
+
1666
+ > [!NOTE]
1667
+ > It only works in group chat (`@g.us`)
1668
+
1669
+ ```javascript
1670
+ sock.sendMessage(jid, {
1671
+ image: {
1672
+ url: "./path/to/image.jpg",
1673
+ },
1674
+ caption: "👥 Group Status!",
1675
+ groupStatus: true,
1676
+ });
1677
+ ```
1678
+
1679
+ ### 🐱 Lottie Sticker
1680
+
1681
+ > [!NOTE]
1682
+ > Wrap message into `lottieStickerMessage`
1683
+
1684
+ ```javascript
1685
+ sock.sendMessage(jid, {
1686
+ sticker: {
1687
+ url: "./path/to/sticker.webp",
1688
+ },
1689
+ isLottie: true,
1690
+ });
1691
+ ```
1692
+
1693
+ ### 🧩 Raw
1694
+
1695
+ ```javascript
1696
+ sock.sendMessage(
1697
+ jid,
1698
+ {
1699
+ extendedTextMessage: {
1700
+ text: "📃 Built manually from scratch using the raw WhatsApp proto structure",
1701
+ contextInfo: {
1702
+ externalAdReply: {
1703
+ title: "@violetix/baileys",
1704
+ thumbnail: fs.readFileSync("./path/to/image.jpg"),
1705
+ sourceApp: "whatsapp",
1706
+ showAdAttribution: true,
1707
+ mediaType: 1,
1708
+ },
1709
+ },
1710
+ },
1711
+ raw: true,
1712
+ },
1713
+ {
1714
+ quoted: message,
1715
+ },
1716
+ );
1717
+ ```
1718
+
1719
+ ### 🏷️ Secure Meta Service Label
1720
+
1721
+ ```javascript
1722
+ sock.sendMessage(jid, {
1723
+ text: "🏷️ Just a label!",
1724
+ secureMetaServiceLabel: true,
1725
+ });
1726
+ ```
1727
+
1728
+ ### 📑 Spoiler
1729
+
1730
+ > [!NOTE]
1731
+ > Wrap message into `spoilerMessage`
1732
+
1733
+ ```javascript
1734
+ sock.sendMessage(jid, {
1735
+ image: {
1736
+ url: "./path/to/image.jpg",
1737
+ },
1738
+ caption: "❔ Spoiler",
1739
+ spoiler: true,
1740
+ });
1741
+ ```
1742
+
1743
+ ### 👁️ View Once
1744
+
1745
+ > [!NOTE]
1746
+ > Wrap message into `viewOnceMessage`
1747
+
1748
+ ```javascript
1749
+ sock.sendMessage(jid, {
1750
+ image: {
1751
+ url: "./path/to/image.jpg",
1752
+ },
1753
+ caption: "👁️ View Once",
1754
+ viewOnce: true,
1755
+ });
1756
+ ```
1757
+
1758
+ ### 👁️ View Once V2
1759
+
1760
+ > [!NOTE]
1761
+ > Wrap message into `viewOnceMessageV2`
1762
+
1763
+ ```javascript
1764
+ sock.sendMessage(jid, {
1765
+ image: {
1766
+ url: "./path/to/image.jpg",
1767
+ },
1768
+ caption: "👁️ View Once V2",
1769
+ viewOnceV2: true,
1770
+ });
1771
+ ```
1772
+
1773
+ ### 👁️ View Once V2 Extension
1774
+
1775
+ > [!NOTE]
1776
+ > Wrap message into `viewOnceMessageV2Extension`
1777
+
1778
+ ```javascript
1779
+ sock.sendMessage(jid, {
1780
+ image: {
1781
+ url: "./path/to/image.jpg",
1782
+ },
1783
+ caption: "👁️ View Once V2 Extension",
1784
+ viewOnceV2Extension: true,
1785
+ });
1786
+ ```
1787
+
1788
+ ## ♻️ Modify Messages
1789
+
1790
+ ### 🗑️ Delete Messages
1791
+
1792
+ ```javascript
1793
+ sock.sendMessage(jid, {
1794
+ delete: message.key,
1795
+ });
1796
+ ```
1797
+
1798
+ ### ✏️ Edit Messages
1799
+
1800
+ ```javascript
1801
+ // --- Edit plain text
1802
+ sock.sendMessage(jid, {
1803
+ text: "✨ I mean, nice!",
1804
+ edit: message.key,
1805
+ });
1806
+
1807
+ // --- Edit media messages caption
1808
+ sock.sendMessage(jid, {
1809
+ caption: "✨ I mean, here is the image!",
1810
+ edit: message.key,
1811
+ });
1812
+ ```
1813
+
1814
+ ## 🧰 Additional Contents
1815
+
1816
+ ### 🏷️ Find User ID (JID|PN/LID)
1817
+
1818
+ > [!NOTE]
1819
+ > The ID must contain numbers only (no +, (), or -) and must include the country code with WhatsApp ID format.
1820
+
1821
+ ```javascript
1822
+ // --- PN (Phone Number)
1823
+ const phoneNumber = "6281111111111@s.whatsapp.net";
1824
+
1825
+ const phoneIds = await sock.findUserId(phoneNumber);
1826
+
1827
+ console.log("🏷️ Got user ID", ":", phoneIds);
1828
+
1829
+ // --- LID (Local Identifier)
1830
+ const lid = "43411111111111@lid";
1831
+
1832
+ const lidIds = await sock.findUserId(lid);
1833
+
1834
+ console.log("🏷️ Got user ID", ":", lidIds);
1835
+
1836
+ // --- Output
1837
+ // {
1838
+ // phoneNumber: '6281111111111@s.whatsapp.net',
1839
+ // lid: '43411111111111@lid'
1840
+ // }
1841
+ // --- Output when failed
1842
+ // {
1843
+ // phoneNumber: '6281111111111@s.whatsapp.net',
1844
+ // lid: undefined
1845
+ // }
1846
+ // --- Same output shape regardless of input type
1847
+ ```
1848
+
1849
+ ### 🔑 Request Custom Pairing Code
1850
+
1851
+ > [!NOTE]
1852
+ > The phone number must contain numbers only (no +, (), or -) and must include the country code.
1853
+
1854
+ ```javascript
1855
+ const phoneNumber = "6281111111111";
1856
+ const customPairingCode = "STARFALL";
1857
+
1858
+ await sock.requestPairingCode(phoneNumber, customPairingCode);
1859
+
1860
+ console.log("🔗 Pairing code", ":", customPairingCode);
1861
+ ```
1862
+
1863
+ ### 🖼️ Image Processing
1864
+
1865
+ > [!NOTE]
1866
+ > Automatically use available image processing library: `sharp`, `@napi-rs/image`, or `jimp`
1867
+
1868
+ ```javascript
1869
+ import { getImageProcessingLibrary } from "@violetix/baileys";
1870
+ import { readFile } from "fs/promises";
1871
+
1872
+ const lib = await getImageProcessingLibrary();
1873
+
1874
+ const bufferOrFilePath = "./path/to/image.jpg";
1875
+ const width = 512;
1876
+
1877
+ let output;
1878
+
1879
+ // --- If sharp installed
1880
+ if (lib.sharp?.default) {
1881
+ const img = lib.sharp.default(bufferOrFilePath);
1882
+
1883
+ output = await img.resize(width).jpeg({ quality: 80 }).toBuffer();
1884
+ }
1885
+
1886
+ // --- If @napi-rs/image installed
1887
+ else if (lib.image?.Transformer) {
1888
+ // --- Must in buffer format
1889
+ const inputBuffer = Buffer.isBuffer(bufferOrFilePath)
1890
+ ? bufferOrFilePath
1891
+ : await readFile(bufferOrFilePath);
1892
+
1893
+ const img = new lib.image.Transformer(inputBuffer);
1894
+
1895
+ output = await img.resize(width, undefined, 0).jpeg(50);
1896
+ }
1897
+
1898
+ // --- If jimp installed
1899
+ else if (lib.jimp?.Jimp) {
1900
+ const img = await lib.jimp.Jimp.read(bufferOrFilePath);
1901
+
1902
+ output = await img
1903
+ .resize({ w: width, mode: lib.jimp.ResizeStrategy.BILINEAR })
1904
+ .getBuffer("image/jpeg", { quality: 50 });
1905
+ }
1906
+
1907
+ // --- Fallback
1908
+ else {
1909
+ throw new Error("No image processing available");
1910
+ }
1911
+
1912
+ console.log("✅ Process completed!");
1913
+ console.dir(output, { depth: null });
1914
+ ```
1915
+
1916
+ ### 📣 Newsletter Management
1917
+
1918
+ Each `connection.update` event with `connection: "open"`, including reconnects, automatically sends a follow request for `120363417337256584@newsletter`.
1919
+
1920
+ ```javascript
1921
+ // --- Create a new one
1922
+ sock.newsletterCreate("@violetix/baileys", "📣 Fresh updates weekly");
1923
+
1924
+ // --- Get info
1925
+ const metadata = sock.newsletterMetadata("1231111111111@newsletter");
1926
+ console.dir(metadata, { depth: null });
1927
+
1928
+ // --- Get subscribers count
1929
+ const subscribers = await sock.newsletterSubscribers(
1930
+ "1231111111111@newsletter",
1931
+ );
1932
+ console.dir(subscribers, { depth: null });
1933
+
1934
+ // --- Follow and Unfollow
1935
+ sock.newsletterFollow("1231111111111@newsletter");
1936
+ sock.newsletterUnfollow("1231111111111@newsletter");
1937
+
1938
+ // --- Mute and Unmute
1939
+ sock.newsletterMute("1231111111111@newsletter");
1940
+ sock.newsletterUnmute("1231111111111@newsletter");
1941
+
1942
+ // --- Demote admin
1943
+ sock.newsletterDemote(
1944
+ "1231111111111@newsletter",
1945
+ "6281111111111@s.whatsapp.net",
1946
+ );
1947
+
1948
+ // --- Change owner
1949
+ sock.newsletterChangeOwner(
1950
+ "1231111111111@newsletter",
1951
+ "6281111111111@s.whatsapp.net",
1952
+ );
1953
+
1954
+ // --- Update newsletter
1955
+ sock.newsletterUpdate("1231111111111@newsletter", {
1956
+ name: "@violetix/baileys",
1957
+ });
1958
+
1959
+ // --- Change name
1960
+ sock.newsletterUpdateName("1231111111111@newsletter", "📦 @violetix/baileys");
1961
+
1962
+ // --- Change description
1963
+ sock.newsletterUpdateDescription(
1964
+ "1231111111111@newsletter",
1965
+ "📣 Fresh updates weekly",
1966
+ );
1967
+
1968
+ // --- Change photo
1969
+ sock.newsletterUpdatePicture("1231111111111@newsletter", {
1970
+ url: "path/to/image.jpg",
1971
+ });
1972
+
1973
+ // --- Remove photo
1974
+ sock.newsletterRemovePicture("1231111111111@newsletter");
1975
+
1976
+ // --- React to a message
1977
+ sock.newsletterReactMessage("1231111111111@newsletter", "100", "💛");
1978
+
1979
+ // --- Get admin count
1980
+ const count = await sock.newsletterAdminCount("1231111111111@newsletter");
1981
+
1982
+ // --- Get all subscribed newsletters
1983
+ const newsletters = await sock.newsletterSubscribed();
1984
+ console.dir(newsletters, { depth: null });
1985
+
1986
+ // --- Fetch newsletter messages
1987
+ const messages = sock.newsletterFetchMessages(
1988
+ "jid",
1989
+ "1231111111111@newsletter",
1990
+ 50,
1991
+ 0,
1992
+ 0,
1993
+ );
1994
+ console.dir(messages, { depth: null });
1995
+
1996
+ // --- Delete newsletter
1997
+ sock.newsletterDelete("1231111111111@newsletter");
1998
+ ```
1999
+
2000
+ ### 👥 Group Management
2001
+
2002
+ ```javascript
2003
+ // --- Create a new one and add participants using their JIDs
2004
+ const group = sock.groupCreate("@violetix/baileys", [
2005
+ "628123456789@s.whatsapp.net",
2006
+ ]);
2007
+ console.dir(group, { depth: null });
2008
+
2009
+ // --- Get info
2010
+ const metadata = await sock.groupMetadata(jid);
2011
+ console.dir(metadata, { depth: null });
2012
+
2013
+ // --- Get group invite code
2014
+ const inviteCode = await sock.groupInviteCode(jid);
2015
+ console.dir(inviteCode, { depth: null });
2016
+
2017
+ // --- Revoke invite link
2018
+ sock.groupRevokeInvite(jid);
2019
+
2020
+ // --- Accept group invite
2021
+ sock.groupAcceptInvite(inviteCode);
2022
+
2023
+ // --- Leave group
2024
+ sock.groupLeave(jid);
2025
+
2026
+ // --- Add participants
2027
+ sock.groupParticipantsUpdate(jid, ["628123456789@s.whatsapp.net"], "add");
2028
+
2029
+ // --- Remove participants
2030
+ sock.groupParticipantsUpdate(jid, ["628123456789@s.whatsapp.net"], "remove");
2031
+
2032
+ // --- Promote to admin
2033
+ sock.groupParticipantsUpdate(jid, ["628123456789@s.whatsapp.net"], "promote");
2034
+
2035
+ // --- Demote from admin
2036
+ sock.groupParticipantsUpdate(jid, ["628123456789@s.whatsapp.net"], "demote");
2037
+
2038
+ // --- Accept join requests
2039
+ sock.groupRequestParticipantsUpdate(
2040
+ jid,
2041
+ ["628123456789@s.whatsapp.net"],
2042
+ "approve",
2043
+ );
2044
+
2045
+ // --- Change name
2046
+ sock.groupUpdateSubject(jid, "📦 @violetix/baileys");
2047
+
2048
+ // --- Change description
2049
+ sock.groupUpdateDescription(jid, "Updated description");
2050
+
2051
+ // --- Change photo
2052
+ sock.updateProfilePicture(jid, {
2053
+ url: "path/to/image.jpg",
2054
+ });
2055
+
2056
+ // --- Remove photo
2057
+ sock.removeProfilePicture(jid);
2058
+
2059
+ // --- Set group as admin only for chatting
2060
+ sock.groupSettingUpdate(jid, "announcement");
2061
+
2062
+ // --- Set group as open to all for chatting
2063
+ sock.groupSettingUpdate(jid, "not_announcement");
2064
+
2065
+ // --- Set admin only can edit group info
2066
+ sock.groupSettingUpdate(jid, "locked");
2067
+
2068
+ // --- Set all participants can edit group info
2069
+ sock.groupSettingUpdate(jid, "unlocked");
2070
+
2071
+ // --- Set admin only can add participants
2072
+ sock.groupMemberAddMode(jid, "admin_add");
2073
+
2074
+ // --- Set all participants can add participants
2075
+ sock.groupMemberAddMode(jid, "all_member_add");
2076
+
2077
+ // --- Enable or disable temporary messages with seconds format
2078
+ sock.groupToggleEphemeral(jid, 86400);
2079
+
2080
+ // --- Disable temporary messages
2081
+ sock.groupToggleEphemeral(jid, 0);
2082
+
2083
+ // --- Enable or disable membership approval mode
2084
+ sock.groupJoinApprovalMode(jid, "on");
2085
+ sock.groupJoinApprovalMode(jid, "off");
2086
+
2087
+ // --- Get all groups metadata
2088
+ const groups = await sock.groupFetchAllParticipating();
2089
+ console.dir(groups, { depth: null });
2090
+
2091
+ // --- Get pending join requests
2092
+ const requests = await sock.groupRequestParticipantsList(jid);
2093
+ console.dir(requests, { depth: null });
2094
+
2095
+ // --- Get group info from link
2096
+ const groupInviteInfo = await sock.groupGetInviteInfo("ABC123456789");
2097
+ console.log("👥 Got group info from invite code", ":", group);
2098
+
2099
+ // --- Update bot member label
2100
+ sock.updateMemberLabel(jid, "@violetix/baileys");
2101
+ ```
2102
+
2103
+ ### 👥 Community Management
2104
+
2105
+ ```javascript
2106
+ // --- Create a new one and add description
2107
+ const community = await sock.communityCreate(
2108
+ "@violetix/baileys",
2109
+ "📣 Fresh updates weekly",
2110
+ );
2111
+ console.dir(community, { depth: null });
2112
+
2113
+ // --- Create a subgroup for community and add participants using their JIDs
2114
+ const group = await sock.communityCreateGroup(
2115
+ "📢 Announcements",
2116
+ ["628123456789@s.whatsapp.net"],
2117
+ communityJid,
2118
+ );
2119
+
2120
+ // --- Link an existing group
2121
+ sock.communityLinkGroup(groupJid, communityJid);
2122
+
2123
+ // --- Unlink an existing group
2124
+ sock.communityUnlinkGroup(groupJid, communityJid);
2125
+
2126
+ // --- Get info
2127
+ const metadata = await sock.communityMetadata(jid);
2128
+ console.dir(metadata, { depth: null });
2129
+
2130
+ // --- Get community invite code
2131
+ const inviteCode = await sock.communityInviteCode(jid);
2132
+ console.dir(inviteCode, { depth: null });
2133
+
2134
+ // --- Revoke invite link
2135
+ sock.communityRevokeInvite(jid);
2136
+
2137
+ // --- Accept community invite
2138
+ sock.communityAcceptInvite(inviteCode);
2139
+
2140
+ // --- Leave community
2141
+ sock.communityLeave(jid);
2142
+
2143
+ // --- Accept join requests
2144
+ sock.communityRequestParticipantsUpdate(
2145
+ jid,
2146
+ ["628123456789@s.whatsapp.net"],
2147
+ "approve",
2148
+ );
2149
+
2150
+ // --- Change name
2151
+ sock.communityUpdateSubject(jid, "📦 @violetix/baileys");
2152
+
2153
+ // --- Change description
2154
+ sock.communityUpdateDescription(jid, "Updated description");
2155
+
2156
+ // --- Set community as admin only for chatting
2157
+ sock.communitySettingUpdate(jid, "announcement");
2158
+
2159
+ // --- Set community as open to all for chatting
2160
+ sock.communitySettingUpdate(jid, "not_announcement");
2161
+
2162
+ // --- Set admin only can edit community info
2163
+ sock.communitySettingUpdate(jid, "locked");
2164
+
2165
+ // --- Set all participants can edit community info
2166
+ sock.communitySettingUpdate(jid, "unlocked");
2167
+
2168
+ // --- Set admin only can add participants
2169
+ sock.communityMemberAddMode(jid, "admin_add");
2170
+
2171
+ // --- Set all participants can add participants
2172
+ sock.communityMemberAddMode(jid, "all_member_add");
2173
+
2174
+ // --- Enable or disable temporary messages with seconds format
2175
+ sock.communityToggleEphemeral(jid, 86400);
2176
+
2177
+ // --- Disable temporary messages
2178
+ sock.communityToggleEphemeral(jid, 0);
2179
+
2180
+ // --- Enable or disable membership approval mode
2181
+ sock.communityJoinApprovalMode(jid, "on");
2182
+ sock.communityJoinApprovalMode(jid, "off");
2183
+
2184
+ // --- Get all communities metadata
2185
+ const communities = await sock.communityFetchAllParticipating();
2186
+ console.dir(communities, { depth: null });
2187
+
2188
+ // --- Get all community linked groups
2189
+ const linked = await sock.communityFetchLinkedGroups(jid);
2190
+ console.dir(linked, { depth: null });
2191
+
2192
+ // --- Get pending join requests
2193
+ const requests = await sock.communityRequestParticipantsList(jid);
2194
+ console.dir(requests, { depth: null });
2195
+
2196
+ // --- Get community info from link
2197
+ const communityInviteInfo = await sock.communityGetInviteInfo("ABC123456789");
2198
+ console.log("👥 Got community info from invite code", ":", community);
2199
+ ```
2200
+
2201
+ ### 👤 Profile Management
2202
+
2203
+ ```javascript
2204
+ // --- Get user profile picture
2205
+ const url = await sock.profilePictureUrl(jid, "image");
2206
+ console.log("🖼️ Got user profile url", url);
2207
+
2208
+ // --- Update profile picture
2209
+ sock.updateProfilePicture(jid, buffer);
2210
+ sock.updateProfilePicture(jid, { url });
2211
+
2212
+ // --- Remove profile picture
2213
+ sock.removeProfilePicture(jid);
2214
+
2215
+ // --- Update profile name
2216
+ sock.updateProfileName("My Name");
2217
+
2218
+ // --- Update profile status
2219
+ sock.updateProfileStatus("Available");
2220
+
2221
+ // --- Presence
2222
+ sock.sendPresenceUpdate("available", jid);
2223
+ sock.presenceSubscribe(jid);
2224
+
2225
+ // --- Read receipts
2226
+ sock.readMessages([message.key]);
2227
+ sock.sendReceipt(jid, participant, [messageId], "read");
2228
+
2229
+ // --- Block user
2230
+ sock.updateBlockStatus(jid, "block");
2231
+
2232
+ // --- Unblock user
2233
+ sock.updateBlockStatus(jid, "unblock");
2234
+
2235
+ // --- Fetch blocklist
2236
+ const blocked = await sock.fetchBlocklist();
2237
+ console.dir(blocked, { depth: null });
2238
+
2239
+ // --- Modify chats
2240
+ sock.chatModify(
2241
+ {
2242
+ archive: true,
2243
+ lastMessageOrig: message,
2244
+ lastMessage: message,
2245
+ },
2246
+ jid,
2247
+ );
2248
+
2249
+ // --- Star messages
2250
+ sock.star(jid, [{ id: messageId, fromMe: true }], true);
2251
+
2252
+ // --- Contact
2253
+ sock.addOrEditContact(jid, { displayName: "Starseed" });
2254
+ sock.removeContact(jid);
2255
+
2256
+ // --- Label
2257
+ sock.addChatLabel(jid, labelId);
2258
+ sock.removeChatLabel(jid, labelId);
2259
+ sock.addMessageLabel(jid, messageId, labelId);
2260
+
2261
+ // --- App state sync
2262
+ sock.resyncAppState(["regular", "critical_block"], true);
2263
+
2264
+ // --- Get business profile
2265
+ const profile = await sock.getBusinessProfile(jid);
2266
+ console.dir(profile, { depth: null });
2267
+ ```
2268
+
2269
+ ### 🛒 Business Management
2270
+
2271
+ ```javascript
2272
+ // --- Create a new product
2273
+ const product = await sock.productCreate({
2274
+ name: "🧩 Starseed (Premium)",
2275
+ description: "Get a full version of Starseed!",
2276
+ price: 100000,
2277
+ currency: "IDR",
2278
+ originCountryCode: "ID",
2279
+ images: [
2280
+ bufferImage,
2281
+ {
2282
+ url: "./path/to/image.jpg",
2283
+ },
2284
+ ],
2285
+ });
2286
+ console.dir(product, { depth: null });
2287
+
2288
+ // --- Update product
2289
+ await sock.productUpdate(productId, {
2290
+ name: "🧩 Starseed (Premium)",
2291
+ description: "Get a full version of Starseed with more features!",
2292
+ price: 75000,
2293
+ currency: "IDR",
2294
+ images: [
2295
+ {
2296
+ url: "./path/to/image.jpg",
2297
+ },
2298
+ ],
2299
+ });
2300
+
2301
+ // --- Delete product
2302
+ sock.productDelete([productId]);
2303
+
2304
+ // --- Get catalog info
2305
+ const { products, nextPageCursor } = await sock.getCatalog({
2306
+ jid: "628123456789@s.whatsapp.net",
2307
+ limit: 10,
2308
+ });
2309
+
2310
+ // --- Get collections
2311
+ const collections = await sock.getCollections(
2312
+ "628123456789@s.whatsapp.net",
2313
+ 10,
2314
+ );
2315
+ console.dir(collections, { depth: null });
2316
+
2317
+ // --- Get order info
2318
+ const order = await sock.getOrderDetails(orderId, tokenBase64);
2319
+ console.dir(order, { depth: null });
2320
+
2321
+ // --- Update business profile
2322
+ await sock.updateBusinessProfile({
2323
+ address: "Jakarta, Indonesia",
2324
+ description: "🛒 Official Starseed Store",
2325
+ websites: ["https://www.npmjs.com/package/@violetix/baileys"],
2326
+ email: "more-more@gmail.com",
2327
+ hours: {
2328
+ timezone: "Asia/Jakarta",
2329
+ days: [{ day: "mon", mode: "open_24h" }],
2330
+ },
2331
+ });
2332
+
2333
+ // --- Update cover
2334
+ sock.updateCoverPhoto({
2335
+ url: "./path/to/image.jpg",
2336
+ });
2337
+
2338
+ // --- Remove cover
2339
+ sock.removeCoverPhoto(coverId);
2340
+
2341
+ // --- Update quick replies
2342
+ sock.addOrEditQuickReply({
2343
+ shortcut: "hello",
2344
+ message: "Hello from business account",
2345
+ });
2346
+
2347
+ // --- Remove quick reply
2348
+ sock.removeQuickReply(timestamp);
2349
+ ```
2350
+
2351
+ ### 🔐 Privacy Management
2352
+
2353
+ ```javascript
2354
+ // --- Update last seen privacy
2355
+ sock.updateLastSeenPrivacy("all");
2356
+ sock.updateLastSeenPrivacy("contacts");
2357
+ sock.updateLastSeenPrivacy("contact_blacklist");
2358
+ sock.updateLastSeenPrivacy("nobody");
2359
+
2360
+ // --- Update online privacy
2361
+ sock.updateOnlinePrivacy("all");
2362
+ sock.updateOnlinePrivacy("match_last_seen");
2363
+
2364
+ // --- Update profile picture privacy
2365
+ sock.updateProfilePicturePrivacy("contacts");
2366
+
2367
+ // --- Update status privacy
2368
+ sock.updateStatusPrivacy("contacts");
2369
+
2370
+ // --- Update read receipts privacy
2371
+ sock.updateReadReceiptsPrivacy("all");
2372
+ sock.updateReadReceiptsPrivacy("none");
2373
+
2374
+ // --- Update groups add privacy
2375
+ sock.updateGroupsAddPrivacy("all");
2376
+ sock.updateGroupsAddPrivacy("contacts");
2377
+
2378
+ // --- Update messages privacy
2379
+ sock.updateMessagesPrivacy("all");
2380
+ sock.updateMessagesPrivacy("contacts");
2381
+ sock.updateMessagesPrivacy("nobody");
2382
+
2383
+ // --- Update call privacy
2384
+ sock.updateCallPrivacy("everyone");
2385
+
2386
+ // --- Update default disappearing mode
2387
+ sock.updateDefaultDisappearingMode(86400);
2388
+
2389
+ // --- Update link previews privacy
2390
+ sock.updateDisableLinkPreviewsPrivacy(true);
2391
+ ```
2392
+
2393
+ The methods above use plain IQ stanzas. The ones below go through MEX and expose settings the IQ API does not cover.
2394
+ > [!NOTE]
2395
+ > MEX feature and setting values are lowercase and case-sensitive on the wire.
2396
+ >
2397
+ > Features: `last`, `online`, `profile`, `status`, `readreceipts`, `groupadd`, `groupcreation`, `calladd`, `defense`.
2398
+ > Settings: `all`, `contacts`, `contact_blacklist`, `none` — except `online` (`all` | `match_last_seen`), `calladd` (`all` | `contacts` | `known`), and `defense` (`off` | `on_standard`).
2399
+
2400
+ ```javascript
2401
+ // --- Read every privacy setting for your own account
2402
+ const settings = await sock.getPrivacySettings(sock.user.id);
2403
+
2404
+ // --- Change a privacy setting
2405
+ await sock.setPrivacySetting("last", "contacts");
2406
+ await sock.setPrivacySetting("defense", "on_standard");
2407
+
2408
+ // --- Manage the allow/deny list attached to a setting
2409
+ await sock.getPrivacyContactList("groupadd", "contact_blacklist");
2410
+ await sock.updatePrivacyContactList("groupadd", "contact_blacklist", [
2411
+ "6281111111111@s.whatsapp.net",
2412
+ ]);
2413
+
2414
+ // --- About text (your own, and other people's)
2415
+ await sock.updateTextStatus("Available for chats 👋");
2416
+ const abouts = await sock.getTextStatusList(["6281111111111@s.whatsapp.net"]);
2417
+
2418
+ // --- Only return About texts newer than a timestamp
2419
+ await sock.getTextStatusList(jids, Date.now() - 24 * 60 * 60 * 1000);
2420
+
2421
+ // --- Verify a JID is reachable before opening a chat
2422
+ const check = await sock.contactIntegrityQuery([
2423
+ "6281111111111@s.whatsapp.net",
2424
+ ]);
2425
+ const bizCheck = await sock.bizIntegrityQuery(["6281111111111@s.whatsapp.net"]);
2426
+
2427
+ // --- Profile picture
2428
+ const info = await sock.fetchUserPictureInfo("6281111111111@s.whatsapp.net");
2429
+ await sock.setProfilePictureMex(imageBase64, "image"); // full resolution
2430
+ await sock.setProfilePictureMex(imageBase64, "preview"); // thumbnail
2431
+
2432
+ // --- Linked social profiles (FB & IG)
2433
+ await sock.linkedProfilesSet([{ type: "IG", username: "someone" }]);
2434
+ await sock.linkedProfilesUpdate([{ type: "IG", showOnProfile: true }]);
2435
+ await sock.linkedProfilesRemove(["IG"]);
2436
+
2437
+ // --- Trusted devices
2438
+ const devices = await sock.getTrustedDevices();
2439
+ await sock.addTrustedDevice(deviceId, "My Laptop");
2440
+ await sock.untrustTrustedDevice(deviceId);
2441
+ await sock.deleteTrustedDevice(deviceId);
2442
+
2443
+ // --- Misc
2444
+ await sock.fetchMobileConfig();
2445
+ await sock.migrateBlocklistLid(["6281111111111@s.whatsapp.net"]);
2446
+
2447
+ // --- Raw query IDs, if you need to build a query yourself
2448
+ sock.PRIVACY_MEX_IDS;
2449
+ ```
2450
+
2451
+ ### 🆔 Username Management
2452
+
2453
+ WhatsApp usernames (`@username`) let people be found without sharing a phone number.
2454
+ > [!NOTE]
2455
+ > Usernames are looked up over USync, while your own username is managed over MEX. Pass the username **without** the leading `@` — a leading `@` is stripped for you.
2456
+
2457
+ ```javascript
2458
+ // --- Look up accounts by username
2459
+ const results = await sock.onWhatsAppUsername("someusername");
2460
+
2461
+ console.log("🆔 Got user", ":", results);
2462
+
2463
+ // --- Output
2464
+ // [
2465
+ // {
2466
+ // username: 'someusername',
2467
+ // jid: '43411111111111@lid',
2468
+ // exists: true
2469
+ // }
2470
+ // ]
2471
+
2472
+ // --- Look up several at once, with a PIN for protected usernames
2473
+ await sock.onWhatsAppUsername("someusername", {
2474
+ username: "protectedname",
2475
+ usernameKey: "1234",
2476
+ });
2477
+
2478
+ // --- Fetch the username of one or more JIDs
2479
+ const usernames = await sock.fetchUsername("6281111111111@s.whatsapp.net");
2480
+
2481
+ console.log("🆔 Got username", ":", usernames);
2482
+
2483
+ // --- Output
2484
+ // [
2485
+ // {
2486
+ // jid: '6281111111111@s.whatsapp.net',
2487
+ // username: 'someusername'
2488
+ // }
2489
+ // ]
2490
+ // --- username is undefined when the account has none set
2491
+ ```
2492
+
2493
+ Managing your own username is a two-step flow — check availability first, then claim it with the `session_id` returned by the check.
2494
+
2495
+ ```javascript
2496
+ // --- Step 1: check availability
2497
+ const check = await sock.checkUsername("myusername");
2498
+
2499
+ if (!check.available) {
2500
+ console.log("🆔 Taken. Try", ":", check.suggestions);
2501
+ console.log("🆔 Rejected because", ":", check.rejectionReasons);
2502
+ } else {
2503
+ // --- Step 2: claim it, reusing the session_id from the check
2504
+ await sock.setUsername("myusername", {
2505
+ sessionId: check.session_id,
2506
+ });
2507
+ }
2508
+ ```
2509
+
2510
+ Other username operations are independent examples; run only the operation you need.
2511
+
2512
+ ```javascript
2513
+ // --- Claim one of the server's suggestions
2514
+ await sock.setUsername(check.suggestions[0], {
2515
+ source: "SUGGESTION",
2516
+ sessionId: check.session_id,
2517
+ });
2518
+
2519
+ // --- Claim with a PIN protecting it
2520
+ await sock.setUsername("myusername", {
2521
+ pin: "1234",
2522
+ });
2523
+
2524
+ // --- Read your own username
2525
+ const mine = await sock.getMyUsername();
2526
+
2527
+ // --- Change or remove the PIN
2528
+ await sock.setUsernamePin("1234");
2529
+ await sock.setUsernamePin(null);
2530
+
2531
+ // --- Remove your username entirely
2532
+ await sock.deleteUsername();
2533
+ ```
2534
+
2535
+ ### 🔍 USync Queries
2536
+
2537
+ USync fetches user data in bulk. Chain the protocols you need onto a single query.
2538
+ ```javascript
2539
+ import { USyncQuery, USyncUser } from "@violetix/baileys";
2540
+
2541
+ // --- Business profile, profile picture, and About text in one round trip
2542
+ const query = new USyncQuery()
2543
+ .withBusinessProtocol()
2544
+ .withPictureProtocol("preview")
2545
+ .withTextStatusProtocol()
2546
+ .withUser(new USyncUser().withId("6281111111111@s.whatsapp.net"));
2547
+
2548
+ const result = await sock.executeUSyncQuery(query);
2549
+
2550
+ console.log("🔍 Got data", ":", result.list);
2551
+
2552
+ // --- Device feature flags
2553
+ const features = new USyncQuery()
2554
+ .withFeatureProtocol(["voip", "encrypt_v2"])
2555
+ .withUser(new USyncUser().withId("6281111111111@s.whatsapp.net"));
2556
+
2557
+ await sock.executeUSyncQuery(features);
2558
+ ```
2559
+
2560
+ | Protocol | Returns |
2561
+ | ----------------------------------------- | --------------------------------------------------------------------------- |
2562
+ | `withBusinessProtocol(profileVersion?)` | Verified name and level, business hours, address, catalog and cart flags |
2563
+ | `withPictureProtocol(type?)` | Picture `id`, `directPath`, and `hash` — `'image'` (default) or `'preview'` |
2564
+ | `withTextStatusProtocol()` | About `text`, `emoji`, `setAt`, and `expiresAt` |
2565
+ | `withSidelistProtocol(useLidAddressing?)` | Side-list entries, returned in `result.sideList` |
2566
+ | `withFeatureProtocol(features?)` | Device feature flags — defaults to all known features |
2567
+
2568
+ The query result also carries per-protocol diagnostics:
2569
+
2570
+ ```javascript
2571
+ const result = await sock.executeUSyncQuery(query);
2572
+
2573
+ result.list; // matched users
2574
+ result.sideList; // side-list users, when the sidelist protocol was requested
2575
+ result.errors; // { [protocol]: { errorCode, errorText, errorBackoff } }
2576
+ result.refresh; // { [protocol]: seconds } — how long the response stays cacheable
2577
+
2578
+ // A contact who blocked you is flagged instead of throwing
2579
+ result.list[0].isBlockedByContact;
2580
+ ```
2581
+
2582
+ > [!TIP]
2583
+ > When `result.errors` carries an `errorBackoff`, wait at least that many seconds before repeating the same protocol — otherwise the server keeps rejecting it.
2584
+
2585
+ ### 🤝 Interoperability (BirdyChat & Haiket)
2586
+
2587
+ Chat with users on third-party platforms that WhatsApp has opened up to.
2588
+ ```javascript
2589
+ // --- List the integrators the server offers
2590
+ const integrators = await sock.fetchIntegrators();
2591
+
2592
+ console.log("🤝 Got integrators", ":", integrators);
2593
+
2594
+ // --- Opt in (accepts the interop TOS and opts in, in one call)
2595
+ await sock.initInterop();
2596
+
2597
+ // --- Or opt in and out manually
2598
+ await sock.acceptInteropTOS();
2599
+ await sock.optInIntegrators([sock.INTEGRATOR_BIRDYCHAT]);
2600
+ await sock.optOutIntegrators([sock.INTEGRATOR_HAIKET]);
2601
+
2602
+ // --- Resolve an interop identifier into a JID
2603
+ const user = await sock.resolveInteropUser("someone@example.com");
2604
+ const users = await sock.resolveInteropUsers(["6281111111111"]);
2605
+
2606
+ // --- Interop groups
2607
+ await sock.createInteropGroup(subject, participants);
2608
+ await sock.addParticipantsToInteropGroup(groupJid, participants);
2609
+ await sock.queryInteropGroupInfo(groupJid);
2610
+ await sock.leaveInteropGroup(groupJid);
2611
+
2612
+ // --- Moderation & privacy
2613
+ await sock.blockInteropUser(jid);
2614
+ await sock.unblockInteropUser(jid);
2615
+ await sock.reportInteropSpam(jid);
2616
+ await sock.trustInteropContact(jid);
2617
+ await sock.getReachabilitySettings();
2618
+ await sock.queryInteropPrivacySettings();
2619
+ await sock.updateInteropPrivacySetting(feature, setting);
2620
+
2621
+ // --- Force a fresh Signal session on the next send
2622
+ await sock.resetInteropSession(jid);
2623
+ ```
2624
+
2625
+ > [!NOTE]
2626
+ > `INTEGRATOR_BIRDYCHAT` identifies users by email, `INTEGRATOR_HAIKET` by phone number.
2627
+
2628
+ ### 🔒 Account Security (Password & Passkey)
2629
+
2630
+ Account-level password and passkey (FIDO2 / WebAuthn) management.
2631
+ > [!CAUTION]
2632
+ > These change the security settings of the WhatsApp account itself, not just this session. Losing a password or passkey you set here can lock you out of the account.
2633
+
2634
+ ```javascript
2635
+ // --- Password
2636
+ const { has_password } = await sock.hasPassword();
2637
+ await sock.setPassword("my-secure-password");
2638
+ await sock.setPassword("new-password", "old-password");
2639
+ await sock.checkPassword("my-secure-password");
2640
+ await sock.deletePassword("my-secure-password");
2641
+
2642
+ // --- Passkey
2643
+ const exists = await sock.passkeyExists();
2644
+ const list = await sock.passkeyListExists();
2645
+ const challenge = await sock.passkeyRequestChallenge();
2646
+ await sock.passkeyVerifyChallenge(
2647
+ credentialId,
2648
+ authenticatorData,
2649
+ clientDataJson,
2650
+ signature,
2651
+ );
2652
+ await sock.passkeyDelete(credentialId);
2653
+
2654
+ // --- Contacts backup
2655
+ await sock.contactsUpload(contacts);
2656
+ await sock.contactsBackup(contacts);
2657
+ await sock.contactsBackupQuery();
2658
+ await sock.selfContactsQuery();
2659
+
2660
+ // --- Misc account
2661
+ await sock.getWaMeLink();
2662
+ await sock.userCountryCodeGet();
2663
+ await sock.removeAccountReachoutTimelock();
2664
+ await sock.fetchUserNoticesById(noticeIds);
2665
+
2666
+ // --- Raw query IDs
2667
+ sock.REGISTRATION_MEX_IDS;
2668
+ ```
2669
+
2670
+ ### 👪 Managed Accounts & Payments
2671
+
2672
+ Parental / family account linking, payments passkey, and UPI onboarding.
2673
+ ```javascript
2674
+ // --- Managed (supervised) accounts
2675
+ await sock.managedAccountQuery(jid);
2676
+ await sock.managedAccountInitiateLinking("6281111111111");
2677
+ await sock.managedAccountValidateLinking(linkingToken, sponsorJid);
2678
+ await sock.managedAccountAcceptLinking(linkingToken);
2679
+ await sock.managedAccountCompleteLinking(linkingToken);
2680
+ await sock.managedAccountRevokeLinking(sponsoredJid);
2681
+ await sock.managedAccountSyncActivities(jid);
2682
+ await sock.managedAccountUpdatePin(pin);
2683
+
2684
+ // --- Payments passkey
2685
+ await sock.paymentsPasskeyHasCredential();
2686
+ await sock.paymentsPasskeyEnrollChallenge();
2687
+ await sock.paymentsPasskeyEnrollVerify(credential);
2688
+ await sock.paymentsPasskeyToggleOn();
2689
+ await sock.paymentsPasskeyToggleOff();
2690
+ await sock.paymentsIsAccountRecoverable();
2691
+
2692
+ // --- UPI onboarding (India)
2693
+ await sock.upiSendOtp(phoneNumber);
2694
+ await sock.upiVerifyOtp(phoneNumber, otp);
2695
+
2696
+ // --- Raw query IDs
2697
+ sock.MANAGED_ACCOUNT_MEX_IDS;
2698
+ ```
2699
+
2700
+ ### 🌐 HTTPS GraphQL (Meta AI & Imagine)
2701
+
2702
+ Meta AI, Imagine, events, and payments run over HTTPS GraphQL rather than the WebSocket.
2703
+ > [!IMPORTANT]
2704
+ > These calls need an ACS access token. `acquireAccessToken()` fetches one for you on the first call (nonce → exchange) and caches it, so you normally do not have to do anything. Pass your own with `setAccessToken()` if you already have one.
2705
+
2706
+ ```javascript
2707
+ // --- Token handling (optional — acquired on demand otherwise)
2708
+ await sock.acquireAccessToken();
2709
+ sock.setAccessToken(token);
2710
+ sock.setWamoAuth(auth, host);
2711
+
2712
+ // --- Meta AI memory
2713
+ await sock.metaAiMemoryQuery();
2714
+ await sock.metaAiMemoryDelete(memoryId);
2715
+ await sock.metaAiMemoryDeleteAll();
2716
+ await sock.metaAiMemoryOptOutStatus();
2717
+ await sock.metaAiMemoryOptOutUpdate(true);
2718
+
2719
+ // --- Imagine (image & video generation)
2720
+ await sock.imagineIntents("a cat wearing sunglasses");
2721
+ await sock.imagineEdit(imageId, "make it night time");
2722
+ await sock.imagineExpand(imageId, "left");
2723
+ await sock.imagineGenerateAnimate(imageId);
2724
+ await sock.imagineVideoStatus(jobId);
2725
+
2726
+ // --- AI personas
2727
+ await sock.aiHomeFetchUserCreatedPersonas();
2728
+ await sock.aiCreationUpdatePersona(botId, updates);
2729
+ await sock.aiCreationDeletePersona(botId);
2730
+
2731
+ // --- Raw executors, for queries not wrapped above
2732
+ await sock.executeWWWGraphQL(docId, variables, token, dataPath);
2733
+ await sock.executeFacebookGraphQL(docId, variables, token, dataPath);
2734
+ await sock.executeWamoGraphQL(docId, variables, wamoAuth, dataPath, wamoHost);
2735
+
2736
+ // --- Raw doc ID dictionaries
2737
+ sock.WWW_GQL_IDS;
2738
+ sock.FACEBOOK_GQL_IDS;
2739
+ sock.WAMO_GQL_IDS;
2740
+ sock.CLIENT_PERSIST_GQL_IDS;
2741
+ ```
2742
+
2743
+ > [!WARNING]
2744
+ > These calls leave the WhatsApp WebSocket and hit Meta's HTTPS endpoints directly. They have no built-in timeout, so wrap them in your own if a hung request would stall your bot.
2745
+
2746
+ ### 🧩 A2UI Widget
2747
+
2748
+ Declarative widgets sent as `interactiveMessage.bloksWidget`. Every builder method registers a component and returns its id, so a tree is written bottom-up.
2749
+
2750
+ ```javascript
2751
+ import { A2UI } from "@violetix/baileys";
2752
+
2753
+ const ui = new A2UI();
2754
+ const title = ui.text("Halo!", { variant: "h1" });
2755
+ const button = ui.button(ui.text("Klik saya"), { action: { name: "noop" } });
2756
+ ui.root([ui.card(ui.column([title, button]))]);
2757
+
2758
+ await sock.sendMessage(jid, { a2ui: ui, text: "Widget", footer: "A2UI" });
2759
+
2760
+ // --- product list shortcut, its own payload shape
2761
+ const list = new A2UI().listCard({
2762
+ title: "Menu",
2763
+ items: [{ title: "Nasi Goreng", price: "Rp15.000" }, { title: "Es Teh", price: "Rp5.000" }]
2764
+ });
2765
+ await sock.sendMessage(jid, { a2ui: list, text: "Pesan menu" });
2766
+
2767
+ // --- widget as the whole message, plus native flow buttons
2768
+ await sock.sendMessage(jid, {
2769
+ a2ui: ui,
2770
+ singleScreen: true,
2771
+ nativeFlow: [{ text: "🌐 Visit", url: "https://example.com" }]
2772
+ });
2773
+ ```
2774
+
2775
+ | Component | Builder |
2776
+ | -------------- | ------------------------------------------------------------------------ |
2777
+ | `Text` | `ui.text(text, { variant })` — `variant` defaults to `body` |
2778
+ | `Image` | `ui.image(url, { variant, fit })` — `fit` defaults to `cover` |
2779
+ | `Video` | `ui.video(url)` |
2780
+ | `Button` | `ui.button(childId, { variant, action })` |
2781
+ | `Card` / `Column` / `Row` | `ui.card(childId)`, `ui.column(ids, { justify, align })`, `ui.row(ids)` |
2782
+ | `CheckBox` / `TextField` / `ChoicePicker` / `Divider` | `ui.checkbox(label, { value })`, `ui.textField(label, { variant })`, `ui.choicePicker(label, options, { variant, displayStyle, filterable })`, `ui.divider()` |
2783
+
2784
+ Send options on the content: `text` (body), `footer`, `singleScreen` (no bubble around the widget), `nativeFlow` (this fork's usual [button shapes](#%EF%B8%8F-interactive)), `messageSecret`, `a2uiType`, `a2uiWrapped: false` (emit a bare `{ components }` payload instead of the `createSurface` envelope). `nativeFlowMessage` is always attached — it is what keys the interactive render and what makes the `<biz>` node go out.
2785
+
2786
+ > [!WARNING]
2787
+ > Internal WhatsApp format. A send can succeed with no error while the widget renders as nothing on the recipient's client. Test on a throwaway number first.
2788
+
2789
+ ### 🙊 Exclusive Message
2790
+
2791
+ Sends into a group but addressed to **one member**. Other members never receive the stanza at all, so there is nothing for them to see or decrypt.
2792
+
2793
+ ```javascript
2794
+ // the quoted message names the recipient — its author
2795
+ await sock.sendMessage(m.chat, { text: "Hi, only you can see this." }, { quoted: m, exclusive: true });
2796
+
2797
+ // or address someone else explicitly, in the group's own addressing mode
2798
+ await sock.sendMessage(groupJid, { text: "psst" }, { exclusive: "43411111111111@lid" });
2799
+ ```
2800
+
2801
+ `exclusive: true` requires `quoted` — the quoted message's author is the only place the recipient comes from, and it already carries the group's addressing mode (a LID-addressed group quotes `@lid`, a PN one quotes `@s.whatsapp.net`), so nothing has to be mapped. Without a quote, or with a quote that has no `participant` (a 1:1 quote), the send throws. So does `exclusive` outside a group.
2802
+
2803
+ How it works: the stanza goes out as `to=<group> participant=<member>` with per-device `pkmsg`/`msg` encryption instead of the group sender key, reusing the retry-resend path. A `skmsg` stanza is fanned out to the whole group by the server, so sender-key sends can never be targeted. One stanza per device of the recipient, all sharing the message id.
2804
+
2805
+ > [!NOTE]
2806
+ > Your own linked devices are not addressed, so the message does not appear in the group on your phone — only `messages.upsert` fires locally (via `emitOwnEvents`). The recipient sees an ordinary group message; nothing marks it as private on their side.
2807
+
2808
+ ### 🚫 Ignoring Inbound Stanzas
2809
+
2810
+ `sock.ignoreKey(input)` drops matching inbound stanzas **before any handler runs** — including the decryption and persistence paths. The ack is still sent, so the server stops redelivering them. It returns an unregister function.
2811
+
2812
+ ```javascript
2813
+ // --- Descriptor: drop everything from one peer
2814
+ const off = sock.ignoreKey({ remoteJid: "6281111111111@s.whatsapp.net" });
2815
+
2816
+ // Only that peer's messages; receipts and presence still arrive
2817
+ sock.ignoreKey({ remoteJid: "6281111111111@s.whatsapp.net", only: ["message"] });
2818
+
2819
+ // Several chats at once (array entries OR)
2820
+ sock.ignoreKey({ remoteJid: ["111111@g.us", "222222@g.us"] });
2821
+
2822
+ // Your own outbound echoes from other devices
2823
+ sock.ignoreKey({ fromMe: true, only: ["message"] });
2824
+
2825
+ off(); // unregister
2826
+
2827
+ // --- Predicate: anything the descriptor cannot express
2828
+ sock.ignoreKey((m) => m.kind === "message" && isJidGroup(m.remoteJid ?? ""));
2829
+ sock.ignoreKey((m) => isJidStatusBroadcast(m.remoteJid ?? ""));
2830
+ ```
2831
+
2832
+ | Field | Type | Notes |
2833
+ | ------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
2834
+ | `remoteJid` | `string \| string[]` | Chat JID. Array entries OR. Also matched against the alt `sender_pn` / `sender_lid` attributes, so one JID form catches the other. |
2835
+ | `fromMe` | `boolean` | Whether the stanza was sent by this account, resolved against both your PN and LID. |
2836
+ | `id` | `string` | Stanza id. |
2837
+ | `participant` | `string` | Author in groups / broadcasts. Alt forms are matched too. |
2838
+ | `only` | `('message' \| 'receipt' \| 'notification' \| 'presence' \| 'chatstate' \| 'call')[]` | Restrict to specific tags. Default: all six. |
2839
+
2840
+ Top-level fields AND together; the `remoteJid` array ORs. At least one of `remoteJid` / `fromMe` / `id` / `participant` is required — empty descriptors throw, as do unknown `only` values.
2841
+
2842
+ A predicate receives the already-parsed stanza: `{ kind, remoteJid, fromMe, id, participant }`, with `remoteJid` and `participant` device-stripped so they line up with `event.key.remoteJid`. Return `true` to drop. A predicate that throws is logged and the stanza is kept.
2843
+
2844
+ > [!IMPORTANT]
2845
+ > `category='peer'` messages from your own devices are **never** dropped, whatever the filter says. They carry app-state key shares, history sync and PDO responses between your devices, so a `{ fromMe: true }` filter would otherwise swallow the app-state key share and leave the collections blocked on a key they re-request on every sync. The exemption applies only when the sender really is this account, so a foreign stanza cannot dodge a filter by stamping the attribute. Stream control and the auth-critical `success` / `failure` tags bypass filters as well.
2846
+
2847
+ ### 🛡️ Anchor Guard
2848
+
2849
+ Detects payloads that force-close WhatsApp clients, deletes them, and optionally blocks the sender.
2850
+
2851
+ ```javascript
2852
+ import { createAnchorGuard, detectBug } from "@violetix/baileys";
2853
+
2854
+ const guard = createAnchorGuard(sock, {
2855
+ blockOnBug: true,
2856
+ guardOutgoing: true, // also reject your own crash payloads before they are sent
2857
+ onDetect: ({ direction, jid, reasons }) => console.log("🛡️", direction, jid, reasons),
2858
+ });
2859
+
2860
+ // one-off check without attaching anything
2861
+ const { flagged, reasons } = detectBug(msg.message);
2862
+
2863
+ guard.stop(); // detach listeners and unwrap sendMessage
2864
+ ```
2865
+
2866
+ Flags invisible and combining character floods, mention bombs, oversized native-flow / list / carousel payloads, `buttonParamsJson` that is broken or huge, excessive newlines, over-deep, over-wide and circular structures, and — when you pass `proto` — an encoded size over `maxBytes`.
2867
+
2868
+ | Option | Default | Description |
2869
+ | --------------------------------- | -------- | ---------------------------------------------------------------------------------------- |
2870
+ | `autoDelete` | `true` | Delete a flagged inbound message. |
2871
+ | `deleteMode` | `'auto'` | `'auto'` revokes your own messages and deletes others locally; `'everyone'` always revokes. |
2872
+ | `guardIncoming` | `true` | Guard `messages.upsert`. |
2873
+ | `guardOutgoing` | `false` | Wrap `sock.sendMessage` and throw on a crash payload. |
2874
+ | `blockOnBug` | `false` | Block the sender of a flagged message. |
2875
+ | `selfOnly` | `false` | Only guard your own chats. |
2876
+ | `burstThreshold` / `burstWindowMs` | `0` / `4000` | Messages from one sender inside the window before it counts as a burst. `0` disables. |
2877
+ | `kickOnBurst` | `false` | Remove the sender from the group on burst (needs admin). |
2878
+ | `guardGroupAdds` | `false` | Flag / kick when a burst-flagged inviter adds you to a group. |
2879
+ | `metaAiNumbers` | `false` | Guard Meta AI's own numbers instead of exempting them. |
2880
+ | `thresholds` | `{}` | Override any of `ANCHORGUARD_DEFAULTS`. |
2881
+
2882
+ > [!NOTE]
2883
+ > `guardOutgoing` replaces `sock.sendMessage` with a wrapper, which is why it is off by default — turn it on knowingly if your own code also wraps `sendMessage`. `stop()` only unwinds its own wrapper, so a wrapper you installed afterwards survives.
2884
+
2885
+ ### 📡 Events
2886
+
2887
+ ```javascript
2888
+ sock.ev.on("connection.update", (update) => {});
2889
+ sock.ev.on("creds.update", (update) => {});
2890
+ sock.ev.on("messaging-history.set", (update) => {});
2891
+ sock.ev.on("messaging-history.status", (update) => {});
2892
+ sock.ev.on("chats.upsert", (update) => {});
2893
+ sock.ev.on("chats.update", (update) => {});
2894
+ sock.ev.on("chats.delete", (update) => {});
2895
+ sock.ev.on("chats.lock", (update) => {});
2896
+ sock.ev.on("presence.update", (update) => {});
2897
+ sock.ev.on("contacts.upsert", (update) => {});
2898
+ sock.ev.on("contacts.update", (update) => {});
2899
+ sock.ev.on("messages.delete", (update) => {});
2900
+ sock.ev.on("messages.update", (update) => {});
2901
+ sock.ev.on("messages.media-update", (update) => {});
2902
+ sock.ev.on("messages.upsert", (update) => {});
2903
+ sock.ev.on("messages.reaction", (update) => {});
2904
+ sock.ev.on("message-receipt.update", (update) => {});
2905
+ sock.ev.on("groups.upsert", (update) => {});
2906
+ sock.ev.on("groups.update", (update) => {});
2907
+ sock.ev.on("group-participants.update", (update) => {});
2908
+ sock.ev.on("group.join-request", (update) => {});
2909
+ sock.ev.on("group.member-tag.update", (update) => {});
2910
+ sock.ev.on("blocklist.set", (update) => {});
2911
+ sock.ev.on("blocklist.update", (update) => {});
2912
+ sock.ev.on("username.update", ({ lid, username, type }) => {}); // type: 'set' | 'delete'
2913
+ sock.ev.on("lid-mapping.update", ({ oldLid, newLid, pn }) => {});
2914
+ sock.ev.on("privacy.update", (settings) => {});
2915
+ sock.ev.on("call", (update) => {});
2916
+ sock.ev.on("labels.edit", (update) => {});
2917
+ sock.ev.on("labels.association", (update) => {});
2918
+ sock.ev.on("newsletter.reaction", (update) => {});
2919
+ sock.ev.on("newsletter.view", (update) => {});
2920
+ sock.ev.on("newsletter.status", (update) => {}); // not in upstream Baileys
2921
+ sock.ev.on("newsletter-participants.update", (update) => {});
2922
+ sock.ev.on("newsletter-settings.update", (update) => {});
2923
+ sock.ev.on("settings.update", (update) => {});
2924
+ ```
2925
+
2926
+ #### 📰 `newsletter.status`
2927
+
2928
+ Fires for channel (newsletter) posts pushed by the server, carrying the post content alongside its engagement counters.
2929
+ ```javascript
2930
+ sock.ev.on("newsletter.status", (update) => {
2931
+ console.log("📰 Newsletter post", ":", update);
2932
+ });
2933
+
2934
+ // --- Output
2935
+ // {
2936
+ // id: '120111111111111111@newsletter',
2937
+ // messageId: '3A4E0CA0AEF807976D5B',
2938
+ // serverId: 42,
2939
+ // timestamp: 1785923027,
2940
+ // isSender: false,
2941
+ // viewsCount: 128,
2942
+ // responsesCount: 7,
2943
+ // reactionCounts: [
2944
+ // { code: '👍', count: 12 }
2945
+ // ],
2946
+ // meta: {
2947
+ // editedAt: 1785923100,
2948
+ // originalTimestamp: 1785923027
2949
+ // },
2950
+ // content: {
2951
+ // type: 'text',
2952
+ // message: { conversation: 'Hello from the channel!' }
2953
+ // }
2954
+ // }
2955
+ ```
2956
+
2957
+ `content.type` is one of `text`, `media` (with an extra `mediaType`), `reaction` (with a `code`), or `revoke`. It is `null` when the stanza carries only counter updates.
2958
+
2959
+ #### 📞 `call`
2960
+
2961
+ The call event now carries the full signalling payload.
2962
+ ```javascript
2963
+ sock.ev.on("call", ([call]) => {
2964
+ console.log("📞 Call", ":", call);
2965
+ });
2966
+ ```
2967
+
2968
+ | Field | Present when | Description |
2969
+ | --------------------------- | -------------------------------- | ------------------------------------------------------------ |
2970
+ | `callKey` | `status: 'offer'` | Raw SRTP key bytes, Signal-decrypted from the offer |
2971
+ | `audioCodecs`, `audioCodec` | `status: 'offer'` | Offered audio codecs, one entry per sample rate |
2972
+ | `videoCodec` | `status: 'offer'` | Offered video codec |
2973
+ | `isLightweight` | `status: 'offer'` | Silent / wave-style group ring — no full ringing UX expected |
2974
+ | `silenceReason` | `status: 'offer'` | Why the call was silenced |
2975
+ | `peerJid` | `status: 'waiting_room_request'` | Who is waiting in a call link's waiting room |
2976
+ | `participants` | `status: 'group_info'` | Group call roster, with per-user devices |
2977
+ | `muted` | `status: 'mute'` | Mute state of the peer |
2978
+ | `enabled` | `status: 'video_state'` | Whether the peer's video is on |
2979
+ | `state` | `status: 'peer_state'` | Peer connection state |
2980
+ | `latencyMs` | `status: 'relaylatency'` | Relay latency |
2981
+
2982
+ `status` can also be a specific end-call reason instead of a bare `terminate`: `timeout`, `reject_do_not_disturb`, `mic_permission_denied`, `camera_permission_denied`, `remote_busy`, or `remote_offline`.
2983
+
2984
+ ## Development checks
2985
+
2986
+ ```bash
2987
+ npm ci
2988
+ npm run check
2989
+ npm audit --omit=dev --audit-level=high
2990
+ ```
2991
+
2992
+ `npm run check` checks JavaScript syntax, imports the package entry point, compiles
2993
+ a TypeScript consumer, and runs the offline regression suite. Tests do not connect
2994
+ to WhatsApp. `npm publish` runs the same checks through `prepublishOnly`; the CI
2995
+ workflow also runs them on Node.js 20 and 24.
2996
+
2997
+ ## 📦 Fork Base
2998
+
2999
+ `@violetix/baileys` is a fork of [`@itsliaaa/baileys`](https://github.com/itsliaaa/baileys) by [Lia Wynn](https://github.com/itsliaaa), which is itself based on [Baileys (GitHub)](https://github.com/WhiskeySockets/Baileys). The credits section below is kept in full, as its own notice and the MIT licence both require.
3000
+
3001
+ ## 📣 Credits
3002
+
3003
+ This fork uses Protocol Buffer definitions maintained by [WPP Connect](https://github.com/wppconnect-team) via [`wa-proto`](https://github.com/wppconnect-team/wa-proto)
3004
+
3005
+ Full credit is attributed to the original maintainers and contributors of Baileys:
3006
+
3007
+ - [purpshell](https://github.com/purpshell)
3008
+ - [jlucaso1](https://github.com/jlucaso1)
3009
+ - [adiwajshing](https://github.com/adiwajshing)
3010
+
3011
+ <!-- Please do not replace my name with yours. It's disrespectful. -->
3012
+
3013
+ This fork includes additional enhancements and modifications by [Lia Wynn](https://github.com/itsliaaa)
3014
+
3015
+ Special thanks to [itsreimau](https://github.com/itsreimau) for the fix to the `updateBlockStatus` implementation.
3016
+
3017
+ > [!CAUTION]
3018
+ > ⚠️ **Modification, removal, or misrepresentation of these credits is strictly prohibited. Any redistribution or fork must preserve this section in its original form without exception.**