@japofc/baileys 2.1.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 (342) hide show
  1. package/NOTICE.md +111 -0
  2. package/README.md +1254 -0
  3. package/WAProto/index.d.ts +9 -0
  4. package/WAProto/index.js +142276 -0
  5. package/engine-requirements.js +13 -0
  6. package/lib/Builders/A2UI.d.ts +242 -0
  7. package/lib/Builders/A2UI.js +308 -0
  8. package/lib/Builders/AIRich.d.ts +105 -0
  9. package/lib/Builders/AIRich.js +2286 -0
  10. package/lib/Builders/Button.d.ts +103 -0
  11. package/lib/Builders/Button.js +883 -0
  12. package/lib/Builders/ButtonV2.d.ts +28 -0
  13. package/lib/Builders/ButtonV2.js +144 -0
  14. package/lib/Builders/ButtonV3.d.ts +25 -0
  15. package/lib/Builders/ButtonV3.js +184 -0
  16. package/lib/Builders/Carousel.d.ts +22 -0
  17. package/lib/Builders/Carousel.js +111 -0
  18. package/lib/Builders/JapBaileys.d.ts +34 -0
  19. package/lib/Builders/JapBaileys.js +108 -0
  20. package/lib/Builders/Poll.d.ts +25 -0
  21. package/lib/Builders/Poll.js +128 -0
  22. package/lib/Builders/index.d.ts +17 -0
  23. package/lib/Builders/index.js +11 -0
  24. package/lib/Builders/shared.d.ts +67 -0
  25. package/lib/Builders/shared.js +652 -0
  26. package/lib/Defaults/index.d.ts +154 -0
  27. package/lib/Defaults/index.js +178 -0
  28. package/lib/Framework/Bot.d.ts +61 -0
  29. package/lib/Framework/Bot.js +248 -0
  30. package/lib/Framework/Context.d.ts +21 -0
  31. package/lib/Framework/Context.js +89 -0
  32. package/lib/Framework/MediaManager.d.ts +17 -0
  33. package/lib/Framework/MediaManager.js +151 -0
  34. package/lib/Framework/SessionManager.d.ts +13 -0
  35. package/lib/Framework/SessionManager.js +33 -0
  36. package/lib/Framework/StatsManager.d.ts +26 -0
  37. package/lib/Framework/StatsManager.js +119 -0
  38. package/lib/Framework/Store/SQLiteStore.d.ts +11 -0
  39. package/lib/Framework/Store/SQLiteStore.js +73 -0
  40. package/lib/Framework/index.d.ts +9 -0
  41. package/lib/Framework/index.js +10 -0
  42. package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
  43. package/lib/Signal/Group/ciphertext-message.js +11 -0
  44. package/lib/Signal/Group/group-session-builder.d.ts +7 -0
  45. package/lib/Signal/Group/group-session-builder.js +29 -0
  46. package/lib/Signal/Group/group_cipher.d.ts +10 -0
  47. package/lib/Signal/Group/group_cipher.js +81 -0
  48. package/lib/Signal/Group/index.d.ts +11 -0
  49. package/lib/Signal/Group/index.js +11 -0
  50. package/lib/Signal/Group/keyhelper.d.ts +6 -0
  51. package/lib/Signal/Group/keyhelper.js +17 -0
  52. package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
  53. package/lib/Signal/Group/sender-chain-key.js +25 -0
  54. package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
  55. package/lib/Signal/Group/sender-key-distribution-message.js +62 -0
  56. package/lib/Signal/Group/sender-key-message.d.ts +18 -0
  57. package/lib/Signal/Group/sender-key-message.js +65 -0
  58. package/lib/Signal/Group/sender-key-name.d.ts +11 -0
  59. package/lib/Signal/Group/sender-key-name.js +47 -0
  60. package/lib/Signal/Group/sender-key-record.d.ts +12 -0
  61. package/lib/Signal/Group/sender-key-record.js +40 -0
  62. package/lib/Signal/Group/sender-key-state.d.ts +16 -0
  63. package/lib/Signal/Group/sender-key-state.js +83 -0
  64. package/lib/Signal/Group/sender-message-key.d.ts +11 -0
  65. package/lib/Signal/Group/sender-message-key.js +25 -0
  66. package/lib/Signal/libsignal.d.ts +54 -0
  67. package/lib/Signal/libsignal.js +430 -0
  68. package/lib/Signal/lid-mapping.d.ts +20 -0
  69. package/lib/Signal/lid-mapping.js +276 -0
  70. package/lib/Socket/Client/index.d.ts +2 -0
  71. package/lib/Socket/Client/index.js +2 -0
  72. package/lib/Socket/Client/types.d.ts +5 -0
  73. package/lib/Socket/Client/types.js +10 -0
  74. package/lib/Socket/Client/websocket.d.ts +12 -0
  75. package/lib/Socket/Client/websocket.js +53 -0
  76. package/lib/Socket/business.d.ts +395 -0
  77. package/lib/Socket/business.js +379 -0
  78. package/lib/Socket/chats.d.ts +136 -0
  79. package/lib/Socket/chats.js +1327 -0
  80. package/lib/Socket/communities.d.ts +562 -0
  81. package/lib/Socket/communities.js +439 -0
  82. package/lib/Socket/dugong.d.ts +117 -0
  83. package/lib/Socket/dugong.js +798 -0
  84. package/lib/Socket/groups.d.ts +285 -0
  85. package/lib/Socket/groups.js +354 -0
  86. package/lib/Socket/index.d.ts +585 -0
  87. package/lib/Socket/index.js +52 -0
  88. package/lib/Socket/messages-recv.d.ts +333 -0
  89. package/lib/Socket/messages-recv.js +1781 -0
  90. package/lib/Socket/messages-send.d.ts +353 -0
  91. package/lib/Socket/messages-send.js +1524 -0
  92. package/lib/Socket/mex.d.ts +1 -0
  93. package/lib/Socket/mex.js +41 -0
  94. package/lib/Socket/newsletter.d.ts +286 -0
  95. package/lib/Socket/newsletter.js +364 -0
  96. package/lib/Socket/socket.d.ts +60 -0
  97. package/lib/Socket/socket.js +1012 -0
  98. package/lib/Socket/username.d.ts +82 -0
  99. package/lib/Socket/username.js +159 -0
  100. package/lib/Store/index.d.ts +3 -0
  101. package/lib/Store/index.js +3 -0
  102. package/lib/Store/make-in-memory-store.d.ts +62 -0
  103. package/lib/Store/make-in-memory-store.js +428 -0
  104. package/lib/Store/make-ordered-dictionary.d.ts +12 -0
  105. package/lib/Store/make-ordered-dictionary.js +78 -0
  106. package/lib/Store/object-repository.d.ts +10 -0
  107. package/lib/Store/object-repository.js +23 -0
  108. package/lib/Types/Auth.d.ts +117 -0
  109. package/lib/Types/Auth.js +1 -0
  110. package/lib/Types/Bussines.d.ts +25 -0
  111. package/lib/Types/Call.d.ts +15 -0
  112. package/lib/Types/Call.js +1 -0
  113. package/lib/Types/Chat.d.ts +124 -0
  114. package/lib/Types/Chat.js +7 -0
  115. package/lib/Types/Contact.d.ts +26 -0
  116. package/lib/Types/Contact.js +1 -0
  117. package/lib/Types/Events.d.ts +256 -0
  118. package/lib/Types/Events.js +1 -0
  119. package/lib/Types/GroupMetadata.d.ts +71 -0
  120. package/lib/Types/GroupMetadata.js +1 -0
  121. package/lib/Types/Label.d.ts +5 -0
  122. package/lib/Types/Label.js +24 -0
  123. package/lib/Types/LabelAssociation.d.ts +6 -0
  124. package/lib/Types/LabelAssociation.js +6 -0
  125. package/lib/Types/Message.d.ts +62 -0
  126. package/lib/Types/Message.js +17 -0
  127. package/lib/Types/Mex.d.ts +2 -0
  128. package/lib/Types/Mex.js +38 -0
  129. package/lib/Types/Product.d.ts +79 -0
  130. package/lib/Types/Product.js +1 -0
  131. package/lib/Types/RichType.d.ts +2 -0
  132. package/lib/Types/RichType.js +22 -0
  133. package/lib/Types/Signal.d.ts +87 -0
  134. package/lib/Types/Signal.js +1 -0
  135. package/lib/Types/Socket.d.ts +138 -0
  136. package/lib/Types/Socket.js +1 -0
  137. package/lib/Types/State.d.ts +8 -0
  138. package/lib/Types/State.js +55 -0
  139. package/lib/Types/USync.d.ts +26 -0
  140. package/lib/Types/index.d.ts +68 -0
  141. package/lib/Types/index.js +27 -0
  142. package/lib/Utils/MessageBuilder.d.ts +2 -0
  143. package/lib/Utils/MessageBuilder.js +2 -0
  144. package/lib/Utils/PersistentStore.d.ts +60 -0
  145. package/lib/Utils/PersistentStore.js +592 -0
  146. package/lib/Utils/anti-delete.d.ts +74 -0
  147. package/lib/Utils/anti-delete.js +221 -0
  148. package/lib/Utils/auth-secure.d.ts +86 -0
  149. package/lib/Utils/auth-secure.js +764 -0
  150. package/lib/Utils/auth-utils.d.ts +57 -0
  151. package/lib/Utils/auth-utils.js +306 -0
  152. package/lib/Utils/auto-reply.d.ts +47 -0
  153. package/lib/Utils/auto-reply.js +157 -0
  154. package/lib/Utils/baileys-event-stream.d.ts +8 -0
  155. package/lib/Utils/baileys-event-stream.js +62 -0
  156. package/lib/Utils/browser-utils.d.ts +8 -0
  157. package/lib/Utils/browser-utils.js +27 -0
  158. package/lib/Utils/business.d.ts +49 -0
  159. package/lib/Utils/business.js +239 -0
  160. package/lib/Utils/button-helper-utils.d.ts +53 -0
  161. package/lib/Utils/button-helper-utils.js +312 -0
  162. package/lib/Utils/button-sender.d.ts +54 -0
  163. package/lib/Utils/button-sender.js +822 -0
  164. package/lib/Utils/chat-control.d.ts +159 -0
  165. package/lib/Utils/chat-control.js +230 -0
  166. package/lib/Utils/chat-history-helpers.d.ts +21 -0
  167. package/lib/Utils/chat-history-helpers.js +70 -0
  168. package/lib/Utils/chat-utils.d.ts +407 -0
  169. package/lib/Utils/chat-utils.js +885 -0
  170. package/lib/Utils/companion-reg-client-utils.d.ts +4 -0
  171. package/lib/Utils/companion-reg-client-utils.js +39 -0
  172. package/lib/Utils/crypto.d.ts +41 -0
  173. package/lib/Utils/crypto.js +147 -0
  174. package/lib/Utils/decode-wa-message.d.ts +83 -0
  175. package/lib/Utils/decode-wa-message.js +316 -0
  176. package/lib/Utils/event-buffer.d.ts +12 -0
  177. package/lib/Utils/event-buffer.js +635 -0
  178. package/lib/Utils/generics.d.ts +69 -0
  179. package/lib/Utils/generics.js +438 -0
  180. package/lib/Utils/history-share.d.ts +11 -0
  181. package/lib/Utils/history-share.js +70 -0
  182. package/lib/Utils/history.d.ts +90 -0
  183. package/lib/Utils/history.js +146 -0
  184. package/lib/Utils/humanizer.d.ts +12 -0
  185. package/lib/Utils/humanizer.js +73 -0
  186. package/lib/Utils/identity-change-handler.d.ts +13 -0
  187. package/lib/Utils/identity-change-handler.js +49 -0
  188. package/lib/Utils/index.d.ts +57 -0
  189. package/lib/Utils/index.js +56 -0
  190. package/lib/Utils/jid-tools.d.ts +6 -0
  191. package/lib/Utils/jid-tools.js +77 -0
  192. package/lib/Utils/link-preview.d.ts +12 -0
  193. package/lib/Utils/link-preview.js +84 -0
  194. package/lib/Utils/logger.d.ts +4 -0
  195. package/lib/Utils/logger.js +2 -0
  196. package/lib/Utils/lt-hash.d.ts +12 -0
  197. package/lib/Utils/lt-hash.js +26 -0
  198. package/lib/Utils/make-mutex.d.ts +6 -0
  199. package/lib/Utils/make-mutex.js +32 -0
  200. package/lib/Utils/media-messages.d.ts +18 -0
  201. package/lib/Utils/media-messages.js +70 -0
  202. package/lib/Utils/media-set.d.ts +13 -0
  203. package/lib/Utils/media-set.js +171 -0
  204. package/lib/Utils/message-kind.d.ts +32 -0
  205. package/lib/Utils/message-kind.js +136 -0
  206. package/lib/Utils/message-retry-manager.d.ts +79 -0
  207. package/lib/Utils/message-retry-manager.js +264 -0
  208. package/lib/Utils/message-search.d.ts +44 -0
  209. package/lib/Utils/message-search.js +188 -0
  210. package/lib/Utils/messages-media.d.ts +135 -0
  211. package/lib/Utils/messages-media.js +868 -0
  212. package/lib/Utils/messages.d.ts +44 -0
  213. package/lib/Utils/messages.js +2326 -0
  214. package/lib/Utils/meta-ai.d.ts +13 -0
  215. package/lib/Utils/meta-ai.js +74 -0
  216. package/lib/Utils/mini-app.d.ts +35 -0
  217. package/lib/Utils/mini-app.js +213 -0
  218. package/lib/Utils/noise-handler.d.ts +20 -0
  219. package/lib/Utils/noise-handler.js +200 -0
  220. package/lib/Utils/offline-node-processor.d.ts +9 -0
  221. package/lib/Utils/offline-node-processor.js +39 -0
  222. package/lib/Utils/past-participants.d.ts +14 -0
  223. package/lib/Utils/past-participants.js +40 -0
  224. package/lib/Utils/pre-key-manager.d.ts +25 -0
  225. package/lib/Utils/pre-key-manager.js +105 -0
  226. package/lib/Utils/process-message.d.ts +82 -0
  227. package/lib/Utils/process-message.js +808 -0
  228. package/lib/Utils/qr-render.d.ts +59 -0
  229. package/lib/Utils/qr-render.js +179 -0
  230. package/lib/Utils/qrcodegen.d.ts +79 -0
  231. package/lib/Utils/qrcodegen.js +848 -0
  232. package/lib/Utils/reporting-utils.d.ts +12 -0
  233. package/lib/Utils/reporting-utils.js +257 -0
  234. package/lib/Utils/rich-message-utils.d.ts +48 -0
  235. package/lib/Utils/rich-message-utils.js +444 -0
  236. package/lib/Utils/router.d.ts +37 -0
  237. package/lib/Utils/router.js +165 -0
  238. package/lib/Utils/scheduled-posts.d.ts +30 -0
  239. package/lib/Utils/scheduled-posts.js +110 -0
  240. package/lib/Utils/scheduling.d.ts +42 -0
  241. package/lib/Utils/scheduling.js +139 -0
  242. package/lib/Utils/signal.d.ts +82 -0
  243. package/lib/Utils/signal.js +200 -0
  244. package/lib/Utils/stanza-ack.d.ts +16 -0
  245. package/lib/Utils/stanza-ack.js +37 -0
  246. package/lib/Utils/status.d.ts +50 -0
  247. package/lib/Utils/status.js +107 -0
  248. package/lib/Utils/stickerpack.d.ts +51 -0
  249. package/lib/Utils/stickerpack.js +274 -0
  250. package/lib/Utils/sync-action-utils.d.ts +2 -0
  251. package/lib/Utils/sync-action-utils.js +48 -0
  252. package/lib/Utils/tag.d.ts +12 -0
  253. package/lib/Utils/tag.js +44 -0
  254. package/lib/Utils/tc-token-utils.d.ts +29 -0
  255. package/lib/Utils/tc-token-utils.js +162 -0
  256. package/lib/Utils/templates.d.ts +76 -0
  257. package/lib/Utils/templates.js +150 -0
  258. package/lib/Utils/transcribe.d.ts +12 -0
  259. package/lib/Utils/transcribe.js +107 -0
  260. package/lib/Utils/use-cache-manager-auth-state.d.ts +13 -0
  261. package/lib/Utils/use-cache-manager-auth-state.js +81 -0
  262. package/lib/Utils/use-multi-file-auth-state.d.ts +10 -0
  263. package/lib/Utils/use-multi-file-auth-state.js +166 -0
  264. package/lib/Utils/use-single-file-auth-state.d.ts +10 -0
  265. package/lib/Utils/use-single-file-auth-state.js +113 -0
  266. package/lib/Utils/use-sqlite-auth-state.d.ts +11 -0
  267. package/lib/Utils/use-sqlite-auth-state.js +169 -0
  268. package/lib/Utils/validate-connection.d.ts +42 -0
  269. package/lib/Utils/validate-connection.js +198 -0
  270. package/lib/Utils/vcard.d.ts +58 -0
  271. package/lib/Utils/vcard.js +104 -0
  272. package/lib/Utils/voice-note.d.ts +15 -0
  273. package/lib/Utils/voice-note.js +63 -0
  274. package/lib/VoIP/audio-feeder.d.ts +18 -0
  275. package/lib/VoIP/audio-feeder.js +160 -0
  276. package/lib/VoIP/call-recorder.d.ts +13 -0
  277. package/lib/VoIP/call-recorder.js +73 -0
  278. package/lib/VoIP/index.d.ts +86 -0
  279. package/lib/VoIP/index.js +611 -0
  280. package/lib/VoIP/relay-transport.d.ts +43 -0
  281. package/lib/VoIP/relay-transport.js +563 -0
  282. package/lib/VoIP/signaling.d.ts +26 -0
  283. package/lib/VoIP/signaling.js +662 -0
  284. package/lib/VoIP/types.d.ts +69 -0
  285. package/lib/VoIP/types.js +17 -0
  286. package/lib/VoIP/wasm-engine.d.ts +120 -0
  287. package/lib/VoIP/wasm-engine.js +1358 -0
  288. package/lib/VoIP/worker-bootstrap.d.ts +4 -0
  289. package/lib/VoIP/worker-bootstrap.js +1046 -0
  290. package/lib/WABinary/constants.d.ts +61 -0
  291. package/lib/WABinary/constants.js +1466 -0
  292. package/lib/WABinary/decode.d.ts +9 -0
  293. package/lib/WABinary/decode.js +261 -0
  294. package/lib/WABinary/encode.d.ts +2 -0
  295. package/lib/WABinary/encode.js +219 -0
  296. package/lib/WABinary/generic-utils.d.ts +74 -0
  297. package/lib/WABinary/generic-utils.js +276 -0
  298. package/lib/WABinary/index.d.ts +5 -0
  299. package/lib/WABinary/index.js +5 -0
  300. package/lib/WABinary/jid-utils.d.ts +28 -0
  301. package/lib/WABinary/jid-utils.js +95 -0
  302. package/lib/WABinary/types.d.ts +19 -0
  303. package/lib/WABinary/types.js +1 -0
  304. package/lib/WAM/BinaryInfo.d.ts +7 -0
  305. package/lib/WAM/BinaryInfo.js +9 -0
  306. package/lib/WAM/constants.d.ts +34926 -0
  307. package/lib/WAM/constants.js +22852 -0
  308. package/lib/WAM/encode.d.ts +1 -0
  309. package/lib/WAM/encode.js +149 -0
  310. package/lib/WAM/index.d.ts +3 -0
  311. package/lib/WAM/index.js +3 -0
  312. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +36 -0
  313. package/lib/WAUSync/Protocols/USyncContactProtocol.js +51 -0
  314. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +29 -0
  315. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +62 -0
  316. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
  317. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +26 -0
  318. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
  319. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +37 -0
  320. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +9 -0
  321. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +24 -0
  322. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +38 -0
  323. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -0
  324. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +14 -0
  325. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +28 -0
  326. package/lib/WAUSync/Protocols/index.d.ts +7 -0
  327. package/lib/WAUSync/Protocols/index.js +7 -0
  328. package/lib/WAUSync/USyncQuery.d.ts +20 -0
  329. package/lib/WAUSync/USyncQuery.js +121 -0
  330. package/lib/WAUSync/USyncUser.d.ts +16 -0
  331. package/lib/WAUSync/USyncUser.js +30 -0
  332. package/lib/WAUSync/index.d.ts +3 -0
  333. package/lib/WAUSync/index.js +3 -0
  334. package/lib/assets/wasm/loader.d.ts +5 -0
  335. package/lib/assets/wasm/loader.js +5 -0
  336. package/lib/assets/wasm/whatsapp.wasm +0 -0
  337. package/lib/assets/wasm/worker-modules.d.ts +5 -0
  338. package/lib/assets/wasm/worker-modules.js +273 -0
  339. package/lib/index.d.ts +18 -0
  340. package/lib/index.js +23 -0
  341. package/package.json +180 -0
  342. package/postinstall-banner.js +82 -0
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Uploads images not already uploaded to WA's servers
3
+ */
4
+ export function uploadingNecessaryImagesOfProduct(product: any, waUploadToServer: any, timeoutMs?: number): Promise<any>;
5
+ export function parseCatalogNode(node: any): {
6
+ products: any;
7
+ nextPageCursor: any;
8
+ };
9
+ export function parseCollectionsNode(node: any): {
10
+ collections: any;
11
+ };
12
+ export function parseOrderDetailsNode(node: any): {
13
+ price: {
14
+ total: number;
15
+ currency: any;
16
+ };
17
+ products: any;
18
+ };
19
+ export function toProductNode(productId: any, product: any): {
20
+ tag: string;
21
+ attrs: {
22
+ compliance_category: string;
23
+ is_hidden: any;
24
+ };
25
+ content: {
26
+ tag: string;
27
+ attrs: {};
28
+ content: any;
29
+ }[];
30
+ };
31
+ export function parseProductNode(productNode: any): {
32
+ id: any;
33
+ imageUrls: {
34
+ requested: any;
35
+ original: any;
36
+ };
37
+ reviewStatus: {
38
+ whatsapp: any;
39
+ };
40
+ availability: string;
41
+ name: any;
42
+ retailerId: any;
43
+ url: any;
44
+ description: any;
45
+ price: number;
46
+ currency: any;
47
+ isHidden: boolean;
48
+ };
49
+ export function uploadingNecessaryImages(images: any, waUploadToServer: any, timeoutMs?: number): Promise<any[]>;
@@ -0,0 +1,239 @@
1
+ import { Boom } from '@hapi/boom';
2
+ import { createHash } from 'crypto';
3
+ import { createWriteStream, promises as fs } from 'fs';
4
+ import { tmpdir } from 'os';
5
+ import { join } from 'path';
6
+ import { getBinaryNodeChild, getBinaryNodeChildren, getBinaryNodeChildString } from '../WABinary/index.js';
7
+ import { generateMessageIDV2 } from './generics.js';
8
+ import logger from './logger.js';
9
+ import { getStream, getUrlFromDirectPath } from './messages-media.js';
10
+ export const parseCatalogNode = (node) => {
11
+ const catalogNode = getBinaryNodeChild(node, 'product_catalog');
12
+ const products = getBinaryNodeChildren(catalogNode, 'product').map(parseProductNode);
13
+ const paging = getBinaryNodeChild(catalogNode, 'paging');
14
+ return {
15
+ products,
16
+ nextPageCursor: paging ? getBinaryNodeChildString(paging, 'after') : undefined
17
+ };
18
+ };
19
+ export const parseCollectionsNode = (node) => {
20
+ const collectionsNode = getBinaryNodeChild(node, 'collections');
21
+ const collections = getBinaryNodeChildren(collectionsNode, 'collection').map(collectionNode => {
22
+ const id = getBinaryNodeChildString(collectionNode, 'id');
23
+ const name = getBinaryNodeChildString(collectionNode, 'name');
24
+ const products = getBinaryNodeChildren(collectionNode, 'product').map(parseProductNode);
25
+ return {
26
+ id,
27
+ name,
28
+ products,
29
+ status: parseStatusInfo(collectionNode)
30
+ };
31
+ });
32
+ return {
33
+ collections
34
+ };
35
+ };
36
+ export const parseOrderDetailsNode = (node) => {
37
+ const orderNode = getBinaryNodeChild(node, 'order');
38
+ const products = getBinaryNodeChildren(orderNode, 'product').map(productNode => {
39
+ const imageNode = getBinaryNodeChild(productNode, 'image');
40
+ return {
41
+ id: getBinaryNodeChildString(productNode, 'id'),
42
+ name: getBinaryNodeChildString(productNode, 'name'),
43
+ imageUrl: getBinaryNodeChildString(imageNode, 'url'),
44
+ price: +getBinaryNodeChildString(productNode, 'price'),
45
+ currency: getBinaryNodeChildString(productNode, 'currency'),
46
+ quantity: +getBinaryNodeChildString(productNode, 'quantity')
47
+ };
48
+ });
49
+ const priceNode = getBinaryNodeChild(orderNode, 'price');
50
+ const orderDetails = {
51
+ price: {
52
+ total: +getBinaryNodeChildString(priceNode, 'total'),
53
+ currency: getBinaryNodeChildString(priceNode, 'currency')
54
+ },
55
+ products
56
+ };
57
+ return orderDetails;
58
+ };
59
+ export const toProductNode = (productId, product) => {
60
+ const attrs = {};
61
+ const content = [];
62
+ if (typeof productId !== 'undefined') {
63
+ content.push({
64
+ tag: 'id',
65
+ attrs: {},
66
+ content: Buffer.from(productId)
67
+ });
68
+ }
69
+ if (typeof product.name !== 'undefined') {
70
+ content.push({
71
+ tag: 'name',
72
+ attrs: {},
73
+ content: Buffer.from(product.name)
74
+ });
75
+ }
76
+ if (typeof product.description !== 'undefined') {
77
+ content.push({
78
+ tag: 'description',
79
+ attrs: {},
80
+ content: Buffer.from(product.description)
81
+ });
82
+ }
83
+ if (typeof product.retailerId !== 'undefined') {
84
+ content.push({
85
+ tag: 'retailer_id',
86
+ attrs: {},
87
+ content: Buffer.from(product.retailerId)
88
+ });
89
+ }
90
+ if (product.images.length) {
91
+ content.push({
92
+ tag: 'media',
93
+ attrs: {},
94
+ content: product.images.map(img => {
95
+ if (!('url' in img)) {
96
+ throw new Boom('Expected img for product to already be uploaded', { statusCode: 400 });
97
+ }
98
+ return {
99
+ tag: 'image',
100
+ attrs: {},
101
+ content: [
102
+ {
103
+ tag: 'url',
104
+ attrs: {},
105
+ content: Buffer.from(img.url.toString())
106
+ }
107
+ ]
108
+ };
109
+ })
110
+ });
111
+ }
112
+ if (typeof product.price !== 'undefined') {
113
+ content.push({
114
+ tag: 'price',
115
+ attrs: {},
116
+ content: Buffer.from(product.price.toString())
117
+ });
118
+ }
119
+ if (typeof product.currency !== 'undefined') {
120
+ content.push({
121
+ tag: 'currency',
122
+ attrs: {},
123
+ content: Buffer.from(product.currency)
124
+ });
125
+ }
126
+ if ('originCountryCode' in product) {
127
+ if (typeof product.originCountryCode === 'undefined') {
128
+ attrs['compliance_category'] = 'COUNTRY_ORIGIN_EXEMPT';
129
+ }
130
+ else {
131
+ content.push({
132
+ tag: 'compliance_info',
133
+ attrs: {},
134
+ content: [
135
+ {
136
+ tag: 'country_code_origin',
137
+ attrs: {},
138
+ content: Buffer.from(product.originCountryCode)
139
+ }
140
+ ]
141
+ });
142
+ }
143
+ }
144
+ if (typeof product.isHidden !== 'undefined') {
145
+ attrs['is_hidden'] = product.isHidden.toString();
146
+ }
147
+ const node = {
148
+ tag: 'product',
149
+ attrs,
150
+ content
151
+ };
152
+ return node;
153
+ };
154
+ export const parseProductNode = (productNode) => {
155
+ const isHidden = productNode.attrs.is_hidden === 'true';
156
+ const id = getBinaryNodeChildString(productNode, 'id');
157
+ const mediaNode = getBinaryNodeChild(productNode, 'media');
158
+ const statusInfoNode = getBinaryNodeChild(productNode, 'status_info');
159
+ const product = {
160
+ id,
161
+ imageUrls: parseImageUrls(mediaNode),
162
+ reviewStatus: {
163
+ whatsapp: getBinaryNodeChildString(statusInfoNode, 'status')
164
+ },
165
+ availability: 'in stock',
166
+ name: getBinaryNodeChildString(productNode, 'name'),
167
+ retailerId: getBinaryNodeChildString(productNode, 'retailer_id'),
168
+ url: getBinaryNodeChildString(productNode, 'url'),
169
+ description: getBinaryNodeChildString(productNode, 'description'),
170
+ price: +getBinaryNodeChildString(productNode, 'price'),
171
+ currency: getBinaryNodeChildString(productNode, 'currency'),
172
+ isHidden
173
+ };
174
+ return product;
175
+ };
176
+ /**
177
+ * Uploads images not already uploaded to WA's servers
178
+ */
179
+ export async function uploadingNecessaryImagesOfProduct(product, waUploadToServer, timeoutMs = 30000) {
180
+ product = {
181
+ ...product,
182
+ images: product.images
183
+ ? await uploadingNecessaryImages(product.images, waUploadToServer, timeoutMs)
184
+ : product.images
185
+ };
186
+ return product;
187
+ }
188
+ /**
189
+ * Uploads images not already uploaded to WA's servers
190
+ */
191
+ export const uploadingNecessaryImages = async (images, waUploadToServer, timeoutMs = 30000) => {
192
+ const results = await Promise.all(images.map(async (img) => {
193
+ if ('url' in img) {
194
+ const url = img.url.toString();
195
+ if (url.includes('.whatsapp.net')) {
196
+ return { url };
197
+ }
198
+ }
199
+ const { stream } = await getStream(img);
200
+ const hasher = createHash('sha256');
201
+ const filePath = join(tmpdir(), 'img' + generateMessageIDV2());
202
+ const encFileWriteStream = createWriteStream(filePath);
203
+ // JAP@Fix (bug 61): no 'error' listener meant a write failure (e.g. disk
204
+ // full) would surface as an unhandled 'error' event instead of rejecting
205
+ // this promise; and the stream was never closed before unlink() below.
206
+ const writeStreamError = new Promise((_, reject) => encFileWriteStream.on('error', reject));
207
+ for await (const block of stream) {
208
+ hasher.update(block);
209
+ encFileWriteStream.write(block);
210
+ }
211
+ await Promise.race([
212
+ new Promise((resolve) => encFileWriteStream.end(resolve)),
213
+ writeStreamError
214
+ ]);
215
+ const sha = hasher.digest('base64');
216
+ const { directPath } = await waUploadToServer(filePath, {
217
+ mediaType: 'product-catalog-image',
218
+ fileEncSha256B64: sha,
219
+ timeoutMs
220
+ });
221
+ await fs.unlink(filePath).catch(err => logger.warn({ err, filePath }, 'JAP@Fix (bug 57): error deleting temp file')); // was console.log
222
+ return { url: getUrlFromDirectPath(directPath) };
223
+ }));
224
+ return results;
225
+ };
226
+ const parseImageUrls = (mediaNode) => {
227
+ const imgNode = getBinaryNodeChild(mediaNode, 'image');
228
+ return {
229
+ requested: getBinaryNodeChildString(imgNode, 'request_image_url'),
230
+ original: getBinaryNodeChildString(imgNode, 'original_image_url')
231
+ };
232
+ };
233
+ const parseStatusInfo = (mediaNode) => {
234
+ const node = getBinaryNodeChild(mediaNode, 'status_info');
235
+ return {
236
+ status: getBinaryNodeChildString(node, 'status'),
237
+ canAppeal: getBinaryNodeChildString(node, 'can_appeal') === 'true'
238
+ };
239
+ };
@@ -0,0 +1,53 @@
1
+ import type { BinaryNode } from '../WABinary/index.js';
2
+
3
+ export type DetectedMediaType =
4
+ | 'image' | 'gif' | 'video' | 'ptt' | 'audio' | 'vcard' | 'document'
5
+ | 'contact_array' | 'livelocation' | 'sticker' | 'list' | 'list_response'
6
+ | 'buttons_response' | 'order' | 'product' | 'native_flow_response' | 'url' | '';
7
+
8
+ export type DetectedMessageType = 'reaction' | 'poll' | 'event' | 'media' | 'text';
9
+ export type DetectedButtonType = 'list' | 'buttons' | 'native_flow' | undefined;
10
+
11
+ export declare function getMediaType(message: any): DetectedMediaType;
12
+ export declare function getMessageType(message: any): DetectedMessageType;
13
+ export declare function getButtonType(message: any): DetectedButtonType;
14
+ /** Derive the binary node(s) that must accompany a button/interactive/list message. */
15
+ export declare function getButtonArgs(message: any): BinaryNode;
16
+ /** Build contextInfo for @mention or @all. */
17
+ export declare const buildMentionContextInfo: (message: any) => {
18
+ contextInfo: Record<string, any>;
19
+ };
20
+ /** Extract embedded media from buttons/interactive message (top-level or header-nested). */
21
+ export declare const extractFromButtonsMessage: (msg: any) => {
22
+ imageMessage?: any;
23
+ videoMessage?: any;
24
+ documentMessage?: any;
25
+ } | null;
26
+ /** Normalise media input: string → { url }, Buffer → as-is, others → as-is. */
27
+ export declare const normalizeMediaInput: (media: any) => any;
28
+ /** Wrap buttons/template/list/interactive in viewOnceMessageV2Extension for MD clients. */
29
+ export declare const patchMessageForMdIfRequired: (message: any) => any;
30
+
31
+ export interface AlbumMessageOptions {
32
+ userJid: string;
33
+ /** Socket surface used for relay + upload (`sock`). */
34
+ suki: any;
35
+ }
36
+
37
+ /** Build and relay an album (multi-image/video) message. Returns the individual media WAMessages. */
38
+ export declare const prepareAlbumMessageContent: (jid: string, albums: any[], options: AlbumMessageOptions) => Promise<any[]>;
39
+
40
+ export interface MessageExtrasContext {
41
+ query: (...args: any[]) => Promise<any>;
42
+ newsletterWMexQuery?: (...args: any[]) => Promise<any>;
43
+ }
44
+
45
+ export interface MessageExtrasAddon {
46
+ /** Fetch profile picture URL for any JID, including newsletters. */
47
+ profilePictureUrl: (jid: string) => Promise<string | null>;
48
+ /** Query the ephemeral (disappearing messages) timer for a group. 0 if not set. */
49
+ getEphemeralGroup: (jid: string) => Promise<number | string>;
50
+ }
51
+
52
+ /** Addon factory for socket-level message extras (profilePictureUrl, getEphemeralGroup). */
53
+ export declare const makeMessageExtrasAddon: (ctx: MessageExtrasContext) => MessageExtrasAddon;
@@ -0,0 +1,312 @@
1
+ // Evernight AI — lib/Utils/button-helper-utils.js / Creator : J.AP
2
+ // Converted TS -> JS ESM to match @japofc/baileys compiled-lib conventions.
3
+
4
+ import { randomBytes } from 'crypto';
5
+ import { generateWAMessage, generateWAMessageFromContent, normalizeMessageContent } from './messages.js';
6
+ import { getUrlFromDirectPath } from './messages-media.js';
7
+ import { unixTimestampSeconds } from './generics.js';
8
+ import { getBinaryNodeChild, isJidGroup, isJidNewsletter, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
9
+ import { QueryIds, XWAPaths } from '../Types/Mex.js';
10
+
11
+ // ─────────────────────────────────────────────────────────────────────────────
12
+ // SECTION 1 — Message Type Detection
13
+ // ─────────────────────────────────────────────────────────────────────────────
14
+
15
+ /** @param {import('../../WAProto/index.js').proto.IMessage} message */
16
+ export function getMediaType(message) {
17
+ if (message.imageMessage) return 'image';
18
+ if (message.videoMessage) return message.videoMessage.gifPlayback ? 'gif' : 'video';
19
+ if (message.audioMessage) return message.audioMessage.ptt ? 'ptt' : 'audio';
20
+ if (message.contactMessage) return 'vcard';
21
+ if (message.documentMessage) return 'document';
22
+ if (message.contactsArrayMessage) return 'contact_array';
23
+ if (message.liveLocationMessage) return 'livelocation';
24
+ if (message.stickerMessage) return 'sticker';
25
+ if (message.listMessage) return 'list';
26
+ if (message.listResponseMessage) return 'list_response';
27
+ if (message.buttonsResponseMessage) return 'buttons_response';
28
+ if (message.orderMessage) return 'order';
29
+ if (message.productMessage) return 'product';
30
+ if (message.interactiveResponseMessage) return 'native_flow_response';
31
+ if (message.groupInviteMessage) return 'url';
32
+ return '';
33
+ }
34
+
35
+ /** @param {import('../../WAProto/index.js').proto.IMessage} message */
36
+ export function getMessageType(message) {
37
+ const normalizedMessage = normalizeMessageContent(message);
38
+ if (!normalizedMessage) return 'text';
39
+ if (normalizedMessage.reactionMessage || normalizedMessage.encReactionMessage) return 'reaction';
40
+ if (
41
+ normalizedMessage.pollCreationMessage ||
42
+ normalizedMessage.pollCreationMessageV2 ||
43
+ normalizedMessage.pollCreationMessageV3 ||
44
+ normalizedMessage.pollUpdateMessage
45
+ )
46
+ return 'poll';
47
+ if (normalizedMessage.eventMessage) return 'event';
48
+ if (getMediaType(normalizedMessage) !== '') return 'media';
49
+ return 'text';
50
+ }
51
+
52
+ // ─────────────────────────────────────────────────────────────────────────────
53
+ // SECTION 2 — Button / Biz Node Helpers
54
+ // ─────────────────────────────────────────────────────────────────────────────
55
+
56
+ /** @param {import('../../WAProto/index.js').proto.IMessage} message */
57
+ export function getButtonType(message) {
58
+ const inner = message.viewOnceMessageV2Extension?.message || message;
59
+ if (inner.listMessage) return 'list';
60
+ if (inner.buttonsMessage) return 'buttons';
61
+ if (inner.interactiveMessage?.nativeFlowMessage) return 'native_flow';
62
+ if (inner.interactiveMessage?.carouselMessage) return 'native_flow';
63
+ if (message.viewOnceMessage?.message?.interactiveMessage?.carouselMessage) return 'native_flow';
64
+ if (message.viewOnceMessageV2?.message?.interactiveMessage?.carouselMessage) return 'native_flow';
65
+ if (message.viewOnceMessage?.message?.interactiveMessage?.nativeFlowMessage) return 'native_flow';
66
+ if (message.viewOnceMessageV2?.message?.interactiveMessage?.nativeFlowMessage) return 'native_flow';
67
+ if (message.viewOnceMessageV2Extension?.message?.interactiveMessage?.nativeFlowMessage) return 'native_flow';
68
+ if (message.viewOnceMessageV2Extension?.message?.interactiveMessage?.carouselMessage) return 'native_flow';
69
+ return undefined;
70
+ }
71
+
72
+ /**
73
+ * Derive the binary node(s) that must accompany a button/interactive/list
74
+ * message so it renders correctly across WA Messenger + WA Business,
75
+ * Android + iOS.
76
+ * @param {import('../../WAProto/index.js').proto.IMessage} message
77
+ * @returns {import('../WABinary/index.js').BinaryNode}
78
+ */
79
+ export function getButtonArgs(message) {
80
+ const inner = message.viewOnceMessageV2Extension?.message || message;
81
+ const nativeFlow =
82
+ inner.interactiveMessage?.nativeFlowMessage ||
83
+ message.viewOnceMessage?.message?.interactiveMessage?.nativeFlowMessage ||
84
+ message.viewOnceMessageV2?.message?.interactiveMessage?.nativeFlowMessage;
85
+ const carouselMessage =
86
+ inner.interactiveMessage?.carouselMessage ||
87
+ message.viewOnceMessage?.message?.interactiveMessage?.carouselMessage ||
88
+ message.viewOnceMessageV2?.message?.interactiveMessage?.carouselMessage;
89
+
90
+ const firstButtonName =
91
+ nativeFlow?.buttons?.[0]?.name ||
92
+ carouselMessage?.cards?.[0]?.nativeFlowMessage?.buttons?.[0]?.name;
93
+ const nativeFlowSpecials = [
94
+ 'mpm',
95
+ 'cta_catalog',
96
+ 'send_location',
97
+ 'call_permission_request',
98
+ 'wa_payment_transaction_details',
99
+ 'automated_greeting_message_view_catalog'
100
+ ];
101
+ const ts = unixTimestampSeconds().toString();
102
+ if (nativeFlow && (firstButtonName === 'review_and_pay' || firstButtonName === 'payment_info')) {
103
+ return {
104
+ tag: 'biz',
105
+ attrs: { native_flow_name: firstButtonName === 'review_and_pay' ? 'order_details' : firstButtonName }
106
+ };
107
+ }
108
+
109
+ if (nativeFlow && nativeFlowSpecials.includes(firstButtonName ?? '')) {
110
+ return {
111
+ tag: 'biz',
112
+ attrs: { actual_actors: '2', host_storage: '2', privacy_mode_ts: ts },
113
+ content: [
114
+ {
115
+ tag: 'interactive',
116
+ attrs: { type: 'native_flow', v: '1' },
117
+ content: [{ tag: 'native_flow', attrs: { v: '2', name: firstButtonName } }]
118
+ },
119
+ { tag: 'quality_control', attrs: { source_type: 'third_party' } }
120
+ ]
121
+ };
122
+ }
123
+
124
+ if (nativeFlow || carouselMessage || message.buttonsMessage) {
125
+ return {
126
+ tag: 'biz',
127
+ attrs: {},
128
+ content: [
129
+ {
130
+ tag: 'interactive',
131
+ attrs: { type: 'native_flow', v: '1' },
132
+ content: [{ tag: 'native_flow', attrs: { v: '9', name: 'mixed' } }]
133
+ }
134
+ ]
135
+ };
136
+ }
137
+
138
+ if (inner.listMessage) {
139
+ return { tag: 'biz', attrs: {}, content: [{ tag: 'list', attrs: { v: '2', type: 'product_list' } }] };
140
+ }
141
+
142
+ return { tag: 'biz', attrs: {} };
143
+ }
144
+
145
+ // ─────────────────────────────────────────────────────────────────────────────
146
+ // SECTION 3 — WS Extras (mentions, media, MD patch, album, socket extras)
147
+ // ─────────────────────────────────────────────────────────────────────────────
148
+
149
+ /** Build contextInfo for @mention or @all. */
150
+ export const buildMentionContextInfo = (message) => {
151
+ if (message.mentionAll) return { contextInfo: { nonJidMentions: 1 } };
152
+ if (message.mentions?.length) return { contextInfo: { mentionedJid: message.mentions } };
153
+ return { contextInfo: {} };
154
+ };
155
+
156
+ /** Extract embedded media from buttons/interactive message (top-level or header-nested). */
157
+ export const extractFromButtonsMessage = (msg) => {
158
+ const header = typeof msg.header === 'object' && msg.header !== null;
159
+ if (header ? msg.header?.imageMessage : msg.imageMessage)
160
+ return { imageMessage: header ? msg.header.imageMessage : msg.imageMessage };
161
+ if (header ? msg.header?.videoMessage : msg.videoMessage)
162
+ return { videoMessage: header ? msg.header.videoMessage : msg.videoMessage };
163
+ if (header ? msg.header?.documentMessage : msg.documentMessage)
164
+ return { documentMessage: header ? msg.header.documentMessage : msg.documentMessage };
165
+ return null;
166
+ };
167
+
168
+ /** Normalise media input: string → { url }, Buffer → as-is, others → as-is. */
169
+ export const normalizeMediaInput = (media) => {
170
+ if (!media) return media;
171
+ if (Buffer.isBuffer(media)) return media;
172
+ if (typeof media === 'string') return { url: media };
173
+ return media;
174
+ };
175
+
176
+ /** Wrap buttons/template/list/interactive in viewOnceMessageV2Extension for MD clients. */
177
+ export const patchMessageForMdIfRequired = (message) => {
178
+ if (
179
+ message?.buttonsMessage ||
180
+ message?.templateMessage ||
181
+ message?.listMessage ||
182
+ message?.interactiveMessage?.nativeFlowMessage
183
+ ) {
184
+ return {
185
+ viewOnceMessageV2Extension: {
186
+ message: {
187
+ messageContextInfo: { deviceListMetadataVersion: 2, deviceListMetadata: {} },
188
+ ...message
189
+ }
190
+ }
191
+ };
192
+ }
193
+
194
+ return message;
195
+ };
196
+
197
+ /**
198
+ * Build and relay an album (multi-image/video) message.
199
+ * @param {string} jid
200
+ * @param {Array<object>} albums
201
+ * @param {{ userJid: string, suki: { relayMessage: Function, waUploadToServer: Function } }} options
202
+ * @returns {Promise<Array<object>>} Array of individual media WAMessage objects
203
+ * @example
204
+ * const items = await prepareAlbumMessageContent(jid, [
205
+ * { image: { url: 'https://...' }, caption: 'Photo 1' },
206
+ * { video: { url: 'https://...' }, caption: 'Video 1' }
207
+ * ], { userJid: sock.user.id, suki: sock })
208
+ */
209
+ export const prepareAlbumMessageContent = async (jid, albums, options) => {
210
+ const messages = [];
211
+
212
+ const albumMsg = generateWAMessageFromContent(
213
+ jid,
214
+ {
215
+ albumMessage: {
216
+ expectedImageCount: albums.filter((item) => 'image' in item).length,
217
+ expectedVideoCount: albums.filter((item) => 'video' in item).length
218
+ }
219
+ },
220
+ { userJid: options.userJid }
221
+ );
222
+
223
+ await options.suki.relayMessage(jid, albumMsg.message, { messageId: albumMsg.key.id });
224
+
225
+ for (const media of albums) {
226
+ let mediaMsg;
227
+ const uploadFn = async (encFilePath, opts) => {
228
+ const res = await options.suki.waUploadToServer(encFilePath, {
229
+ ...opts,
230
+ newsletter: isJidNewsletter(jid)
231
+ });
232
+ return {
233
+ mediaUrl: res.url ?? '',
234
+ directPath: res.directPath ?? '',
235
+ handle: res.handle,
236
+ mediaKey: res.mediaKey,
237
+ fileEncSha256: res.fileEncSha256,
238
+ fileSha256: res.fileSha256,
239
+ fileLength: res.fileLength
240
+ };
241
+ };
242
+
243
+ const sharedOpts = { userJid: options.userJid, upload: uploadFn };
244
+
245
+ if ('image' in media && media.image) mediaMsg = await generateWAMessage(jid, media, sharedOpts);
246
+ else if ('video' in media && media.video) mediaMsg = await generateWAMessage(jid, media, sharedOpts);
247
+
248
+ if (mediaMsg) {
249
+ mediaMsg.message.messageContextInfo = {
250
+ messageSecret: randomBytes(32),
251
+ messageAssociation: { associationType: 1, parentMessageKey: albumMsg.key }
252
+ };
253
+ messages.push(mediaMsg);
254
+ }
255
+ }
256
+
257
+ return messages;
258
+ };
259
+
260
+ /**
261
+ * Addon factory for socket-level message extras (profilePictureUrl, getEphemeralGroup).
262
+ * @param {{ query: Function, newsletterWMexQuery?: Function }} ctx
263
+ */
264
+ export const makeMessageExtrasAddon = (ctx) => {
265
+ const { query, newsletterWMexQuery } = ctx;
266
+
267
+ /**
268
+ * Fetch profile picture URL for any JID, including newsletters.
269
+ * @example
270
+ * const url = await sock.profilePictureUrl('1234567890@s.whatsapp.net')
271
+ */
272
+ const profilePictureUrl = async (jid) => {
273
+ if (isJidNewsletter(jid) && newsletterWMexQuery) {
274
+ const node = await newsletterWMexQuery(undefined, QueryIds.METADATA, {
275
+ input: { key: jid, type: 'JID', view_role: 'GUEST' },
276
+ fetch_viewer_metadata: true,
277
+ fetch_full_image: true,
278
+ fetch_creation_time: true
279
+ });
280
+ const resultStr = getBinaryNodeChild(node, 'result')?.content?.toString();
281
+ if (!resultStr) return null;
282
+
283
+ const metadata = JSON.parse(resultStr).data[XWAPaths.xwa2_newsletter_metadata];
284
+ return getUrlFromDirectPath(metadata?.thread_metadata?.picture?.direct_path || '');
285
+ }
286
+
287
+ const result = await query({
288
+ tag: 'iq',
289
+ attrs: { target: jidNormalizedUser(jid), to: S_WHATSAPP_NET, type: 'get', xmlns: 'w:profile:picture' },
290
+ content: [{ tag: 'picture', attrs: { type: 'image', query: 'url' }, content: undefined }]
291
+ });
292
+ return getBinaryNodeChild(result, 'picture')?.attrs?.url || null;
293
+ };
294
+
295
+ /**
296
+ * Query the ephemeral (disappearing messages) timer for a group.
297
+ * @returns {Promise<number|string>} timer in seconds, or 0 if not set
298
+ * @example
299
+ * const timer = await sock.getEphemeralGroup('120363xxx@g.us')
300
+ */
301
+ const getEphemeralGroup = async (jid) => {
302
+ if (!isJidGroup(jid)) throw new TypeError('Jid should originate from a group!');
303
+ const result = await query({
304
+ tag: 'iq',
305
+ attrs: { id: `ephemeral-${Date.now()}`, to: jid, type: 'get', xmlns: 'w:g2' },
306
+ content: [{ tag: 'query', attrs: { request: 'interactive' }, content: undefined }]
307
+ });
308
+ return getBinaryNodeChild(getBinaryNodeChild(result, 'group'), 'ephemeral')?.attrs?.expiration || 0;
309
+ };
310
+
311
+ return { profilePictureUrl, getEphemeralGroup };
312
+ };