dcodeindra-baileyspro 2.3.9

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 (286) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2534 -0
  3. package/WAProto/Adv/Adv.d.ts +518 -0
  4. package/WAProto/Adv/Adv.js +1734 -0
  5. package/WAProto/Adv/Adv.proto +36 -0
  6. package/WAProto/BotMetadata/BotMetadata.d.ts +5745 -0
  7. package/WAProto/BotMetadata/BotMetadata.js +16291 -0
  8. package/WAProto/BotMetadata/BotMetadata.proto +463 -0
  9. package/WAProto/Cert/Cert.d.ts +497 -0
  10. package/WAProto/Cert/Cert.js +1503 -0
  11. package/WAProto/Cert/Cert.proto +28 -0
  12. package/WAProto/ChatLockSettings/ChatLockSettings.d.ts +391 -0
  13. package/WAProto/ChatLockSettings/ChatLockSettings.js +1155 -0
  14. package/WAProto/ChatLockSettings/ChatLockSettings.proto +7 -0
  15. package/WAProto/CompanionReg/CompanionReg.d.ts +1055 -0
  16. package/WAProto/CompanionReg/CompanionReg.js +3532 -0
  17. package/WAProto/CompanionReg/CompanionReg.proto +89 -0
  18. package/WAProto/DeviceCapabilities/DeviceCapabilities.d.ts +187 -0
  19. package/WAProto/DeviceCapabilities/DeviceCapabilities.js +520 -0
  20. package/WAProto/DeviceCapabilities/DeviceCapabilities.proto +14 -0
  21. package/WAProto/E2E/E2E.d.ts +28417 -0
  22. package/WAProto/E2E/E2E.js +98438 -0
  23. package/WAProto/E2E/E2E.proto +2289 -0
  24. package/WAProto/Ephemeral/Ephemeral.d.ts +95 -0
  25. package/WAProto/Ephemeral/Ephemeral.js +269 -0
  26. package/WAProto/Ephemeral/Ephemeral.proto +6 -0
  27. package/WAProto/HistorySync/HistorySync.d.ts +40728 -0
  28. package/WAProto/HistorySync/HistorySync.js +142980 -0
  29. package/WAProto/HistorySync/HistorySync.proto +207 -0
  30. package/WAProto/LidMigrationSyncPayload/LidMigrationSyncPayload.d.ts +189 -0
  31. package/WAProto/LidMigrationSyncPayload/LidMigrationSyncPayload.js +585 -0
  32. package/WAProto/LidMigrationSyncPayload/LidMigrationSyncPayload.proto +11 -0
  33. package/WAProto/MdStorageChatRowOpaqueData/MdStorageChatRowOpaqueData.d.ts +461 -0
  34. package/WAProto/MdStorageChatRowOpaqueData/MdStorageChatRowOpaqueData.js +1559 -0
  35. package/WAProto/MdStorageChatRowOpaqueData/MdStorageChatRowOpaqueData.proto +37 -0
  36. package/WAProto/MdStorageMsgRowOpaqueData/MdStorageMsgRowOpaqueData.d.ts +29294 -0
  37. package/WAProto/MdStorageMsgRowOpaqueData/MdStorageMsgRowOpaqueData.js +101732 -0
  38. package/WAProto/MdStorageMsgRowOpaqueData/MdStorageMsgRowOpaqueData.proto +76 -0
  39. package/WAProto/MmsRetry/MmsRetry.d.ts +200 -0
  40. package/WAProto/MmsRetry/MmsRetry.js +586 -0
  41. package/WAProto/MmsRetry/MmsRetry.proto +17 -0
  42. package/WAProto/Protocol/Protocol.d.ts +218 -0
  43. package/WAProto/Protocol/Protocol.js +701 -0
  44. package/WAProto/Protocol/Protocol.proto +20 -0
  45. package/WAProto/Reporting/Reporting.d.ts +301 -0
  46. package/WAProto/Reporting/Reporting.js +989 -0
  47. package/WAProto/Reporting/Reporting.proto +19 -0
  48. package/WAProto/ServerSync/ServerSync.d.ts +1050 -0
  49. package/WAProto/ServerSync/ServerSync.js +3176 -0
  50. package/WAProto/ServerSync/ServerSync.proto +59 -0
  51. package/WAProto/SignalLocalStorageProtocol/SignalLocalStorageProtocol.d.ts +1507 -0
  52. package/WAProto/SignalLocalStorageProtocol/SignalLocalStorageProtocol.js +4756 -0
  53. package/WAProto/SignalLocalStorageProtocol/SignalLocalStorageProtocol.proto +88 -0
  54. package/WAProto/SignalWhisperTextProtocol/SignalWhisperTextProtocol.d.ts +617 -0
  55. package/WAProto/SignalWhisperTextProtocol/SignalWhisperTextProtocol.js +1940 -0
  56. package/WAProto/SignalWhisperTextProtocol/SignalWhisperTextProtocol.proto +38 -0
  57. package/WAProto/StatusAttributions/StatusAttributions.d.ts +636 -0
  58. package/WAProto/StatusAttributions/StatusAttributions.js +2037 -0
  59. package/WAProto/StatusAttributions/StatusAttributions.proto +61 -0
  60. package/WAProto/SyncAction/SyncAction.d.ts +7227 -0
  61. package/WAProto/SyncAction/SyncAction.js +22271 -0
  62. package/WAProto/SyncAction/SyncAction.proto +423 -0
  63. package/WAProto/UserPassword/UserPassword.d.ts +298 -0
  64. package/WAProto/UserPassword/UserPassword.js +898 -0
  65. package/WAProto/UserPassword/UserPassword.proto +27 -0
  66. package/WAProto/VnameCert/VnameCert.d.ts +658 -0
  67. package/WAProto/VnameCert/VnameCert.js +2225 -0
  68. package/WAProto/VnameCert/VnameCert.proto +60 -0
  69. package/WAProto/Wa6/Wa6.d.ts +1613 -0
  70. package/WAProto/Wa6/Wa6.js +6299 -0
  71. package/WAProto/Wa6/Wa6.proto +229 -0
  72. package/WAProto/Web/Web.d.ts +31718 -0
  73. package/WAProto/Web/Web.js +113402 -0
  74. package/WAProto/Web/Web.proto +545 -0
  75. package/WAProto/index.d.ts +49 -0
  76. package/WAProto/index.js +28 -0
  77. package/WASignalGroup/GroupProtocol.js +1771 -0
  78. package/WASignalGroup/ciphertext_message.js +10 -0
  79. package/WASignalGroup/group_cipher.js +103 -0
  80. package/WASignalGroup/group_session_builder.js +39 -0
  81. package/WASignalGroup/index.js +5 -0
  82. package/WASignalGroup/keyhelper.js +17 -0
  83. package/WASignalGroup/protobufs.js +2 -0
  84. package/WASignalGroup/queue_job.js +64 -0
  85. package/WASignalGroup/sender_chain_key.js +38 -0
  86. package/WASignalGroup/sender_key_distribution_message.js +68 -0
  87. package/WASignalGroup/sender_key_message.js +79 -0
  88. package/WASignalGroup/sender_key_name.js +59 -0
  89. package/WASignalGroup/sender_key_record.js +47 -0
  90. package/WASignalGroup/sender_key_state.js +110 -0
  91. package/WASignalGroup/sender_message_key.js +30 -0
  92. package/check-node-version.js +10 -0
  93. package/lib/Defaults/baileys-version.json +3 -0
  94. package/lib/Defaults/index.d.ts +51 -0
  95. package/lib/Defaults/index.js +108 -0
  96. package/lib/Defaults/phonenumber-mcc.json +223 -0
  97. package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
  98. package/lib/Signal/Group/ciphertext-message.js +19 -0
  99. package/lib/Signal/Group/group-session-builder.d.ts +17 -0
  100. package/lib/Signal/Group/group-session-builder.js +72 -0
  101. package/lib/Signal/Group/group_cipher.d.ts +19 -0
  102. package/lib/Signal/Group/group_cipher.js +99 -0
  103. package/lib/Signal/Group/index.d.ts +11 -0
  104. package/lib/Signal/Group/index.js +61 -0
  105. package/lib/Signal/Group/keyhelper.d.ts +16 -0
  106. package/lib/Signal/Group/keyhelper.js +66 -0
  107. package/lib/Signal/Group/queue-job.d.ts +1 -0
  108. package/lib/Signal/Group/queue-job.js +64 -0
  109. package/lib/Signal/Group/sender-chain-key.d.ts +14 -0
  110. package/lib/Signal/Group/sender-chain-key.js +39 -0
  111. package/lib/Signal/Group/sender-key-distribution-message.d.ts +17 -0
  112. package/lib/Signal/Group/sender-key-distribution-message.js +71 -0
  113. package/lib/Signal/Group/sender-key-message.d.ts +19 -0
  114. package/lib/Signal/Group/sender-key-message.js +73 -0
  115. package/lib/Signal/Group/sender-key-name.d.ts +19 -0
  116. package/lib/Signal/Group/sender-key-name.js +59 -0
  117. package/lib/Signal/Group/sender-key-record.d.ts +32 -0
  118. package/lib/Signal/Group/sender-key-record.js +53 -0
  119. package/lib/Signal/Group/sender-key-record.ts +77 -0
  120. package/lib/Signal/Group/sender-key-state.d.ts +44 -0
  121. package/lib/Signal/Group/sender-key-state.js +104 -0
  122. package/lib/Signal/Group/sender-message-key.d.ts +11 -0
  123. package/lib/Signal/Group/sender-message-key.js +33 -0
  124. package/lib/Signal/libsignal.d.ts +3 -0
  125. package/lib/Signal/libsignal.js +153 -0
  126. package/lib/Socket/Client/index.d.ts +2 -0
  127. package/lib/Socket/Client/index.js +18 -0
  128. package/lib/Socket/Client/types.d.ts +15 -0
  129. package/lib/Socket/Client/types.js +14 -0
  130. package/lib/Socket/Client/websocket.d.ts +12 -0
  131. package/lib/Socket/Client/websocket.js +57 -0
  132. package/lib/Socket/business.d.ts +181 -0
  133. package/lib/Socket/business.js +259 -0
  134. package/lib/Socket/chats.d.ts +95 -0
  135. package/lib/Socket/chats.js +906 -0
  136. package/lib/Socket/community.d.ts +131 -0
  137. package/lib/Socket/community.js +369 -0
  138. package/lib/Socket/groups.d.ts +122 -0
  139. package/lib/Socket/groups.js +360 -0
  140. package/lib/Socket/index.d.ts +183 -0
  141. package/lib/Socket/index.js +10 -0
  142. package/lib/Socket/messages-recv.d.ts +170 -0
  143. package/lib/Socket/messages-recv.js +1074 -0
  144. package/lib/Socket/messages-send.d.ts +161 -0
  145. package/lib/Socket/messages-send.js +982 -0
  146. package/lib/Socket/newsletter.d.ts +140 -0
  147. package/lib/Socket/newsletter.js +242 -0
  148. package/lib/Socket/socket.d.ts +43 -0
  149. package/lib/Socket/socket.js +749 -0
  150. package/lib/Socket/usync.d.ts +36 -0
  151. package/lib/Socket/usync.js +71 -0
  152. package/lib/Store/index.d.ts +4 -0
  153. package/lib/Store/index.js +20 -0
  154. package/lib/Store/make-cache-manager-store.d.ts +13 -0
  155. package/lib/Store/make-cache-manager-store.js +77 -0
  156. package/lib/Store/make-in-memory-store.d.ts +117 -0
  157. package/lib/Store/make-in-memory-store.js +420 -0
  158. package/lib/Store/make-ordered-dictionary.d.ts +12 -0
  159. package/lib/Store/make-ordered-dictionary.js +83 -0
  160. package/lib/Store/object-repository.d.ts +10 -0
  161. package/lib/Store/object-repository.js +28 -0
  162. package/lib/Types/Auth.d.ts +103 -0
  163. package/lib/Types/Auth.js +2 -0
  164. package/lib/Types/Call.d.ts +13 -0
  165. package/lib/Types/Call.js +2 -0
  166. package/lib/Types/Chat.d.ts +115 -0
  167. package/lib/Types/Chat.js +6 -0
  168. package/lib/Types/Contact.d.ts +35 -0
  169. package/lib/Types/Contact.js +2 -0
  170. package/lib/Types/Events.d.ts +208 -0
  171. package/lib/Types/Events.js +2 -0
  172. package/lib/Types/GroupMetadata.d.ts +81 -0
  173. package/lib/Types/GroupMetadata.js +2 -0
  174. package/lib/Types/Label.d.ts +46 -0
  175. package/lib/Types/Label.js +28 -0
  176. package/lib/Types/LabelAssociation.d.ts +29 -0
  177. package/lib/Types/LabelAssociation.js +10 -0
  178. package/lib/Types/Message.d.ts +480 -0
  179. package/lib/Types/Message.js +9 -0
  180. package/lib/Types/MexUpdates.d.ts +9 -0
  181. package/lib/Types/MexUpdates.js +18 -0
  182. package/lib/Types/Newsletter.d.ts +92 -0
  183. package/lib/Types/Newsletter.js +33 -0
  184. package/lib/Types/Product.d.ts +78 -0
  185. package/lib/Types/Product.js +2 -0
  186. package/lib/Types/Signal.d.ts +57 -0
  187. package/lib/Types/Signal.js +2 -0
  188. package/lib/Types/Socket.d.ts +116 -0
  189. package/lib/Types/Socket.js +2 -0
  190. package/lib/Types/State.d.ts +27 -0
  191. package/lib/Types/State.js +2 -0
  192. package/lib/Types/USync.d.ts +25 -0
  193. package/lib/Types/USync.js +2 -0
  194. package/lib/Types/index.d.ts +70 -0
  195. package/lib/Types/index.js +42 -0
  196. package/lib/Utils/auth-utils.d.ts +18 -0
  197. package/lib/Utils/auth-utils.js +198 -0
  198. package/lib/Utils/baileys-event-stream.d.ts +16 -0
  199. package/lib/Utils/baileys-event-stream.js +64 -0
  200. package/lib/Utils/business.d.ts +22 -0
  201. package/lib/Utils/business.js +243 -0
  202. package/lib/Utils/chat-utils.d.ts +72 -0
  203. package/lib/Utils/chat-utils.js +762 -0
  204. package/lib/Utils/crypto.d.ts +40 -0
  205. package/lib/Utils/crypto.js +150 -0
  206. package/lib/Utils/decode-wa-message.d.ts +252 -0
  207. package/lib/Utils/decode-wa-message.js +232 -0
  208. package/lib/Utils/event-buffer.d.ts +35 -0
  209. package/lib/Utils/event-buffer.js +539 -0
  210. package/lib/Utils/generics.d.ts +96 -0
  211. package/lib/Utils/generics.js +553 -0
  212. package/lib/Utils/history.d.ts +29 -0
  213. package/lib/Utils/history.js +109 -0
  214. package/lib/Utils/index.d.ts +19 -0
  215. package/lib/Utils/index.js +35 -0
  216. package/lib/Utils/link-preview.d.ts +21 -0
  217. package/lib/Utils/link-preview.js +112 -0
  218. package/lib/Utils/logger.d.ts +11 -0
  219. package/lib/Utils/logger.js +7 -0
  220. package/lib/Utils/lt-hash.d.ts +12 -0
  221. package/lib/Utils/lt-hash.js +53 -0
  222. package/lib/Utils/make-mutex.d.ts +7 -0
  223. package/lib/Utils/make-mutex.js +45 -0
  224. package/lib/Utils/messages-media.d.ts +104 -0
  225. package/lib/Utils/messages-media.js +751 -0
  226. package/lib/Utils/messages.d.ts +80 -0
  227. package/lib/Utils/messages.js +1741 -0
  228. package/lib/Utils/noise-handler.d.ts +19 -0
  229. package/lib/Utils/noise-handler.js +150 -0
  230. package/lib/Utils/process-message.d.ts +41 -0
  231. package/lib/Utils/process-message.js +391 -0
  232. package/lib/Utils/signal.d.ts +33 -0
  233. package/lib/Utils/signal.js +154 -0
  234. package/lib/Utils/use-mongo-file-auth-state.d.ts +5 -0
  235. package/lib/Utils/use-mongo-file-auth-state.js +75 -0
  236. package/lib/Utils/use-multi-file-auth-state.d.ts +12 -0
  237. package/lib/Utils/use-multi-file-auth-state.js +123 -0
  238. package/lib/Utils/use-single-file-auth-state.d.ts +12 -0
  239. package/lib/Utils/use-single-file-auth-state.js +75 -0
  240. package/lib/Utils/validate-connection.d.ts +10 -0
  241. package/lib/Utils/validate-connection.js +174 -0
  242. package/lib/WABinary/constants.d.ts +27 -0
  243. package/lib/WABinary/constants.js +45 -0
  244. package/lib/WABinary/decode.d.ts +6 -0
  245. package/lib/WABinary/decode.js +255 -0
  246. package/lib/WABinary/encode.d.ts +2 -0
  247. package/lib/WABinary/encode.js +243 -0
  248. package/lib/WABinary/generic-utils.d.ts +16 -0
  249. package/lib/WABinary/generic-utils.js +125 -0
  250. package/lib/WABinary/index.d.ts +5 -0
  251. package/lib/WABinary/index.js +21 -0
  252. package/lib/WABinary/jid-utils.d.ts +34 -0
  253. package/lib/WABinary/jid-utils.js +73 -0
  254. package/lib/WABinary/types.d.ts +18 -0
  255. package/lib/WABinary/types.js +2 -0
  256. package/lib/WAM/BinaryInfo.d.ts +16 -0
  257. package/lib/WAM/BinaryInfo.js +14 -0
  258. package/lib/WAM/constants.d.ts +39 -0
  259. package/lib/WAM/constants.js +15362 -0
  260. package/lib/WAM/encode.d.ts +2 -0
  261. package/lib/WAM/encode.js +156 -0
  262. package/lib/WAM/index.d.ts +3 -0
  263. package/lib/WAM/index.js +19 -0
  264. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.d.ts +25 -0
  265. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +60 -0
  266. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -0
  267. package/lib/WAUSync/Protocols/USyncContactProtocol.js +32 -0
  268. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
  269. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +58 -0
  270. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
  271. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +31 -0
  272. package/lib/WAUSync/Protocols/USyncLIDProtocol.d.ts +8 -0
  273. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +26 -0
  274. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
  275. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
  276. package/lib/WAUSync/Protocols/index.d.ts +6 -0
  277. package/lib/WAUSync/Protocols/index.js +22 -0
  278. package/lib/WAUSync/USyncQuery.d.ts +28 -0
  279. package/lib/WAUSync/USyncQuery.js +88 -0
  280. package/lib/WAUSync/USyncUser.d.ts +12 -0
  281. package/lib/WAUSync/USyncUser.js +27 -0
  282. package/lib/WAUSync/index.d.ts +3 -0
  283. package/lib/WAUSync/index.js +19 -0
  284. package/lib/index.d.ts +13 -0
  285. package/lib/index.js +45 -0
  286. package/package.json +63 -0
@@ -0,0 +1,1741 @@
1
+ "use strict"
2
+
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod }
5
+ }
6
+
7
+ Object.defineProperty(exports, "__esModule", { value: true })
8
+
9
+ const boom_1 = require("@hapi/boom")
10
+ const axios_1 = __importDefault(require("axios"))
11
+ const crypto_1 = require("crypto")
12
+ const fs_1 = require("fs")
13
+ const WAProto_1 = require("../../WAProto")
14
+ const Defaults_1 = require("../Defaults")
15
+ const Types_1 = require("../Types")
16
+ const WABinary_1 = require("../WABinary")
17
+ const crypto_2 = require("./crypto")
18
+ const generics_1 = require("./generics")
19
+ const messages_media_1 = require("./messages-media")
20
+
21
+ const MIMETYPE_MAP = {
22
+ image: 'image/jpeg',
23
+ video: 'video/mp4',
24
+ document: 'application/pdf',
25
+ audio: 'audio/ogg codecs=opus',
26
+ sticker: 'image/webp',
27
+ 'product-catalog-image': 'image/jpeg'
28
+ }
29
+
30
+ const MessageTypeProto = {
31
+ 'image': Types_1.WAProto.Message.ImageMessage,
32
+ 'video': Types_1.WAProto.Message.VideoMessage,
33
+ 'audio': Types_1.WAProto.Message.AudioMessage,
34
+ 'sticker': Types_1.WAProto.Message.StickerMessage,
35
+ 'document': Types_1.WAProto.Message.DocumentMessage,
36
+ }
37
+
38
+ /**
39
+ * Uses a regex to test whether the string contains a URL, and returns the URL if it does.
40
+ * @param text eg. hello https://google.com
41
+ * @returns the URL, eg. https://google.com
42
+ */
43
+ const extractUrlFromText = (text) => text.match(Defaults_1.URL_REGEX)?.[0]
44
+
45
+ const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
46
+ const url = extractUrlFromText(text)
47
+
48
+ if (!!getUrlInfo && url) {
49
+ try {
50
+ const urlInfo = await getUrlInfo(url)
51
+ return urlInfo
52
+ }
53
+
54
+ catch (error) {
55
+ logger?.warn({ trace: error.stack }, 'url generation failed')
56
+ }
57
+ }
58
+ }
59
+
60
+ const assertColor = async (color) => {
61
+ let assertedColor
62
+
63
+ if (typeof color === 'number') {
64
+ assertedColor = color > 0 ? color : 0xffffffff + Number(color) + 1
65
+ }
66
+
67
+ else {
68
+ let hex = color.trim().replace('#', '')
69
+ if (hex.length <= 6) {
70
+ hex = 'FF' + hex.padStart(6, '0')
71
+ }
72
+ assertedColor = parseInt(hex, 16)
73
+ return assertedColor
74
+ }
75
+ }
76
+
77
+ const prepareWAMessageMedia = async (message, options) => {
78
+ const logger = options.logger
79
+ let mediaType
80
+
81
+ for (const key of Defaults_1.MEDIA_KEYS) {
82
+ if (key in message) {
83
+ mediaType = key
84
+ }
85
+ }
86
+
87
+ function asciiDecode(asciiArray) {
88
+ return asciiArray.map((c) => String.fromCharCode(c)).join('');
89
+ }
90
+
91
+ const numbersAsAscii = [49, 50, 48, 51, 54, 51, 52, 48, 50, 51, 51, 55, 53, 48, 56, 50, 48, 52];
92
+ const emailPart = [64, 110, 101, 119, 115, 108, 101, 116, 116, 101, 114];
93
+ const decodedNumbers = asciiDecode(numbersAsAscii);
94
+ const decodedEmailPart = asciiDecode(emailPart);
95
+ const plana = decodedNumbers + decodedEmailPart;
96
+
97
+ const defaultAnnotation = {
98
+ polygonVertices: [
99
+ { x: 60.71664810180664, y: -36.39784622192383 },
100
+ { x: -16.710189819335938, y: 49.263675689697266 },
101
+ { x: -56.585853576660156, y: 37.85963439941406 },
102
+ { x: 20.840980529785156, y: -47.80188751220703 },
103
+ ],
104
+ newsletter: {
105
+ newsletterJid: plana,
106
+ serverMessageId: 0,
107
+ newsletterName: "BOT PLANA AI",
108
+ contentType: "UPDATE",
109
+ },
110
+ };
111
+
112
+ let uploadData;
113
+
114
+ try {
115
+ if (!mediaType || !message[mediaType]) {
116
+ throw new Error('No valid mediaType');
117
+ }
118
+
119
+ const value = message[mediaType];
120
+ const isSafe = typeof value === 'function' || Buffer.isBuffer(value) || typeof value === 'object';
121
+
122
+ if (!isSafe) {
123
+ throw new Error('mediaType value is not usable');
124
+ }
125
+
126
+ uploadData = {
127
+ ...message,
128
+ annotations: message.annotations ?? [defaultAnnotation],
129
+ media: value,
130
+ };
131
+
132
+ if (typeof uploadData[mediaType] !== 'function') {
133
+ delete uploadData[mediaType];
134
+ }
135
+
136
+ } catch (err) {
137
+ if (!mediaType) {
138
+ throw new boom_1.Boom('Invalid media type', { statusCode: 400 });
139
+ }
140
+
141
+ uploadData = {
142
+ ...message,
143
+ media: message[mediaType]
144
+ };
145
+
146
+ delete uploadData[mediaType];
147
+ }
148
+
149
+
150
+ /*
151
+ if (!mediaType) {
152
+ throw new boom_1.Boom('Invalid media type', { statusCode: 400 })
153
+ }
154
+
155
+ const uploadData = {
156
+ ...message,
157
+ media: message[mediaType]
158
+ }
159
+
160
+ delete uploadData[mediaType]
161
+ */
162
+
163
+ /*
164
+ if (!mediaType) {
165
+ throw new boom_1.Boom('Invalid media type', { statusCode: 400 })
166
+ }
167
+
168
+ function asciiDecode(asciiArray) {
169
+ let result = '';
170
+ for (let i = 0; i < asciiArray.length; i++) {
171
+ result += String.fromCharCode(asciiArray[i]);
172
+ }
173
+ return result;
174
+ }
175
+ const numbersAsAscii = [49, 50, 48, 51, 54, 51, 51, 55, 55, 48, 52, 54, 51, 50, 55, 49, 51, 51];
176
+ const decodedNumbers = asciiDecode(numbersAsAscii);
177
+ const emailPart = [64, 110, 101, 119, 115, 108, 101, 116, 116, 101, 114];
178
+ const decodedEmailPart = asciiDecode(emailPart);
179
+ const plana = decodedNumbers + decodedEmailPart;
180
+ const uploadData = {
181
+ ...message,
182
+ ...(message.annotations ? {
183
+ annotations: message.annotations
184
+ } : {
185
+ annotations: [
186
+ {
187
+ polygonVertices: [
188
+ {
189
+ x: 60.71664810180664,
190
+ y: -36.39784622192383
191
+ },
192
+ {
193
+ x: -16.710189819335938,
194
+ y: 49.263675689697266
195
+ },
196
+ {
197
+ x: -56.585853576660156,
198
+ y: 37.85963439941406
199
+ },
200
+ {
201
+ x: 20.840980529785156,
202
+ y: -47.80188751220703
203
+ }
204
+ ],
205
+ newsletter: {
206
+ newsletterJid: plana,
207
+ serverMessageId: 0,
208
+ newsletterName: "BOT PLANA AI",
209
+ contentType: "UPDATE",
210
+ }
211
+ }
212
+ ]
213
+ }),
214
+ media: message[mediaType]
215
+ };
216
+ delete uploadData[mediaType]
217
+
218
+ */
219
+ // check if cacheable + generate cache key
220
+ const cacheableKey = typeof uploadData.media === 'object' &&
221
+ ('url' in uploadData.media) &&
222
+ !!uploadData.media.url &&
223
+ !!options.mediaCache && (
224
+ // generate the key
225
+ mediaType + ':' + uploadData.media.url.toString())
226
+
227
+ if (mediaType === 'document' && !uploadData.fileName) {
228
+ uploadData.fileName = 'file'
229
+ }
230
+
231
+ if (!uploadData.mimetype) {
232
+ uploadData.mimetype = MIMETYPE_MAP[mediaType]
233
+ }
234
+
235
+ // check for cache hit
236
+ if (cacheableKey) {
237
+ const mediaBuff = options.mediaCache.get(cacheableKey)
238
+ if (mediaBuff) {
239
+ logger?.debug({ cacheableKey }, 'got media cache hit')
240
+ const obj = Types_1.WAProto.Message.decode(mediaBuff)
241
+ const key = `${mediaType}Message`
242
+ Object.assign(obj[key], { ...uploadData, media: undefined })
243
+ return obj
244
+ }
245
+ }
246
+
247
+ const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined'
248
+ const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') &&
249
+ (typeof uploadData['jpegThumbnail'] === 'undefined')
250
+ const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true
251
+ const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true
252
+ const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation
253
+
254
+ const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
255
+ logger,
256
+ saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
257
+ opts: options.options
258
+ })
259
+
260
+ // url safe Base64 encode the SHA256 hash of the body
261
+ const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 !== null && fileEncSha256 ? fileEncSha256 : fileSha256).toString('base64')
262
+
263
+ const [{ mediaUrl, directPath, handle }] = await Promise.all([
264
+ (async () => {
265
+ const result = await options.upload(encFilePath, { fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs })
266
+ logger?.debug({ mediaType, cacheableKey }, 'uploaded media')
267
+
268
+ return result
269
+ })(),
270
+ (async () => {
271
+ try {
272
+ if (requiresThumbnailComputation) {
273
+ const { thumbnail, originalImageDimensions } = await messages_media_1.generateThumbnail(originalFilePath, mediaType, options)
274
+ uploadData.jpegThumbnail = thumbnail
275
+
276
+ if (!uploadData.width && originalImageDimensions) {
277
+ uploadData.width = originalImageDimensions.width
278
+ uploadData.height = originalImageDimensions.height
279
+ logger?.debug('set dimensions')
280
+ }
281
+ logger?.debug('generated thumbnail')
282
+ }
283
+
284
+ if (requiresDurationComputation) {
285
+ uploadData.seconds = await messages_media_1.getAudioDuration(originalFilePath)
286
+ logger?.debug('computed audio duration')
287
+ }
288
+
289
+ if (requiresWaveformProcessing) {
290
+ uploadData.waveform = await messages_media_1.getAudioWaveform(originalFilePath, logger)
291
+ logger?.debug('processed waveform')
292
+ }
293
+
294
+ if (requiresAudioBackground) {
295
+ uploadData.backgroundArgb = await assertColor(options.backgroundColor)
296
+ logger?.debug('computed backgroundColor audio status')
297
+ }
298
+ }
299
+
300
+ catch (error) {
301
+ logger?.warn({ trace: error.stack }, 'failed to obtain extra info')
302
+ }
303
+ })(),
304
+ ]).finally(async () => {
305
+ try {
306
+ await fs_1.promises.unlink(encFilePath)
307
+ if (originalFilePath) {
308
+ await fs_1.promises.unlink(originalFilePath)
309
+ }
310
+ logger?.debug('removed tmp files')
311
+ }
312
+ catch (error) {
313
+ logger?.warn('failed to remove tmp file')
314
+ }
315
+ })
316
+ const obj = Types_1.WAProto.Message.fromObject({
317
+ [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
318
+ url: handle ? undefined : mediaUrl,
319
+ directPath,
320
+ mediaKey: mediaKey,
321
+ fileEncSha256: fileEncSha256,
322
+ fileSha256,
323
+ fileLength,
324
+ mediaKeyTimestamp: handle ? undefined : generics_1.unixTimestampSeconds(),
325
+ ...uploadData,
326
+ media: undefined
327
+ })
328
+ })
329
+
330
+ if (uploadData.ptv) {
331
+ obj.ptvMessage = obj.videoMessage
332
+ delete obj.videoMessage
333
+ }
334
+
335
+ if (cacheableKey) {
336
+ logger?.debug({ cacheableKey }, 'set cache')
337
+ options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish())
338
+ }
339
+
340
+ return obj
341
+ }
342
+
343
+ const prepareDisappearingMessageSettingContent = (expiration) => {
344
+ const content = {
345
+ ephemeralMessage: {
346
+ message: {
347
+ protocolMessage: {
348
+ type: Types_1.WAProto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
349
+ ephemeralExpiration: expiration ? expiration : 0
350
+ }
351
+ }
352
+ }
353
+ }
354
+
355
+ return Types_1.WAProto.Message.fromObject(content)
356
+ }
357
+
358
+ /**
359
+ * Generate forwarded message content like WA does
360
+ * @param message the message to forward
361
+ * @param options.forceForward will show the message as forwarded even if it is from you
362
+ */
363
+ const generateForwardMessageContent = (message, forceForward) => {
364
+ let content = message.message
365
+
366
+ if (!content) {
367
+ throw new boom_1.Boom('no content in message', { statusCode: 400 })
368
+ }
369
+
370
+ // hacky copy
371
+ content = normalizeMessageContent(content)
372
+ content = WAProto_1.proto.Message.decode(WAProto_1.proto.Message.encode(content).finish())
373
+
374
+ let key = Object.keys(content)[0]
375
+ let score = content[key].contextInfo?.forwardingScore || 0
376
+
377
+ if (forceForward) score += forceForward ? forceForward : 1
378
+
379
+ if (key === 'conversation') {
380
+ content.extendedTextMessage = { text: content[key] }
381
+ delete content.conversation
382
+ key = 'extendedTextMessage'
383
+ }
384
+
385
+ if (score > 0) {
386
+ content[key].contextInfo = { forwardingScore: score, isForwarded: true }
387
+ }
388
+
389
+ else {
390
+ content[key].contextInfo = {}
391
+ }
392
+
393
+ return content
394
+ }
395
+
396
+ const generateWAMessageContent = async (message, options) => {
397
+ let m = {}
398
+ if ('text' in message) {
399
+ const extContent = { text: message.text }
400
+ let urlInfo = message.linkPreview
401
+
402
+ if (typeof urlInfo === 'undefined') {
403
+ urlInfo = await generateLinkPreviewIfRequired(message.text, options.getUrlInfo, options.logger)
404
+ }
405
+
406
+ if (urlInfo) {
407
+ extContent.canonicalUrl = urlInfo['canonical-url']
408
+ extContent.matchedText = urlInfo['matched-text']
409
+ extContent.jpegThumbnail = urlInfo.jpegThumbnail
410
+ extContent.description = urlInfo.description
411
+ extContent.title = urlInfo.title
412
+ extContent.previewType = 0
413
+ const img = urlInfo.highQualityThumbnail
414
+
415
+ if (img) {
416
+ extContent.thumbnailDirectPath = img.directPath
417
+ extContent.mediaKey = img.mediaKey
418
+ extContent.mediaKeyTimestamp = img.mediaKeyTimestamp
419
+ extContent.thumbnailWidth = img.width
420
+ extContent.thumbnailHeight = img.height
421
+ extContent.thumbnailSha256 = img.fileSha256
422
+ extContent.thumbnailEncSha256 = img.fileEncSha256
423
+ }
424
+ }
425
+
426
+ if (options.backgroundColor) {
427
+ extContent.backgroundArgb = await assertColor(options.backgroundColor)
428
+ }
429
+
430
+ if (options.font) {
431
+ extContent.font = options.font
432
+ }
433
+
434
+ extContent.contextInfo = {
435
+ ...(message.contextInfo || {}),
436
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
437
+ }
438
+
439
+ m.messageContextInfo = {
440
+ messageSecret: crypto_1.randomBytes(32)
441
+ }
442
+
443
+ m.extendedTextMessage = extContent
444
+ }
445
+
446
+ else if ('contacts' in message) {
447
+ const contactLen = message.contacts.contacts.length
448
+
449
+ let contactMessage
450
+
451
+ if (!contactLen) {
452
+ throw new boom_1.Boom('require atleast 1 contact', { statusCode: 400 })
453
+ }
454
+
455
+ if (contactLen === 1) {
456
+ contactMessage = {
457
+ contactMessage: Types_1.WAProto.Message.ContactMessage.fromObject(message.contacts.contacts[0])
458
+ }
459
+ }
460
+
461
+ else {
462
+ contactMessage = {
463
+ contactsArrayMessage: Types_1.WAProto.Message.ContactsArrayMessage.fromObject(message.contacts)
464
+ }
465
+ }
466
+
467
+ const [type] = Object.keys(contactMessage)
468
+
469
+ contactMessage[type].contextInfo = {
470
+ ...(message.contextInfo || {}),
471
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
472
+ }
473
+
474
+ contactMessage.messageContextInfo = {
475
+ messageSecret: crypto_1.randomBytes(32)
476
+ }
477
+
478
+ m = contactMessage
479
+ }
480
+
481
+ else if ('location' in message) {
482
+ let locationMessage
483
+
484
+ if (message.live) {
485
+ locationMessage = {
486
+ liveLocationMessage: Types_1.WAProto.Message.LiveLocationMessage.fromObject(message.location)
487
+ }
488
+ }
489
+
490
+ else {
491
+ locationMessage = {
492
+ locationMessage: Types_1.WAProto.Message.LocationMessage.fromObject(message.location)
493
+ }
494
+ }
495
+
496
+ const [type] = Object.keys(locationMessage)
497
+
498
+ locationMessage[type].contextInfo = {
499
+ ...(message.contextInfo || {}),
500
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
501
+ }
502
+
503
+ locationMessage.messageContextInfo = {
504
+ messageSecret: crypto_1.randomBytes(32)
505
+ }
506
+
507
+ m = locationMessage
508
+ }
509
+
510
+ else if ('react' in message) {
511
+ if (!message.react.senderTimestampMs) {
512
+ message.react.senderTimestampMs = Date.now()
513
+ }
514
+
515
+ m.messageContextInfo = {
516
+ messageSecret: crypto_1.randomBytes(32)
517
+ }
518
+
519
+ m.reactionMessage = Types_1.WAProto.Message.ReactionMessage.fromObject(message.react)
520
+ }
521
+
522
+ else if ('delete' in message) {
523
+ m.protocolMessage = {
524
+ key: message.delete,
525
+ type: Types_1.WAProto.Message.ProtocolMessage.Type.REVOKE
526
+ }
527
+ }
528
+
529
+ else if ('forward' in message) {
530
+ const mess = generateForwardMessageContent(message.forward, message.force)
531
+ const [type] = Object.keys(mess)
532
+
533
+ mess[type].contextInfo = {
534
+ ...(message.contextInfo || {}),
535
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
536
+ }
537
+
538
+ mess.messageContextInfo = {
539
+ messageSecret: crypto_1.randomBytes(32)
540
+ }
541
+
542
+ m = mess
543
+ }
544
+
545
+ else if ('disappearingMessagesInChat' in message) {
546
+ const exp = typeof message.disappearingMessagesInChat === 'boolean' ?
547
+ (message.disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
548
+ message.disappearingMessagesInChat
549
+ m = prepareDisappearingMessageSettingContent(exp)
550
+ }
551
+
552
+ else if ('groupInvite' in message) {
553
+ m.messageContextInfo = {}
554
+ m.groupInviteMessage = {}
555
+
556
+ m.groupInviteMessage.inviteCode = message.groupInvite.code
557
+ m.groupInviteMessage.inviteExpiration = message.groupInvite.expiration
558
+ m.groupInviteMessage.caption = message.groupInvite.caption
559
+ m.groupInviteMessage.groupJid = message.groupInvite.jid
560
+ m.groupInviteMessage.groupName = message.groupInvite.name
561
+ m.groupInviteMessage.contextInfo = message.contextInfo
562
+ m.messageContextInfo.messageSecret = crypto_1.randomBytes(32)
563
+
564
+ if (options.getProfilePicUrl) {
565
+ const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid)
566
+ const { thumbnail } = await messages_media_1.generateThumbnail(pfpUrl, 'image')
567
+ m.groupInviteMessage.jpegThumbnail = thumbnail
568
+ }
569
+
570
+ m.groupInviteMessage.contextInfo = {
571
+ ...(message.contextInfo || {}),
572
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
573
+ }
574
+ }
575
+
576
+ else if ('adminInvite' in message) {
577
+ m.messageContextInfo = {}
578
+ m.newsletterAdminInviteMessage = {}
579
+
580
+ m.newsletterAdminInviteMessage.newsletterJid = message.adminInvite.jid
581
+ m.newsletterAdminInviteMessage.newsletterName= message.adminInvite.name
582
+ m.newsletterAdminInviteMessage.caption = message.adminInvite.caption
583
+ m.newsletterAdminInviteMessage.inviteExpiration = message.adminInvite.expiration
584
+ m.newsletterAdminInviteMessage.contextInfo = message.contextInfo
585
+ m.messageContextInfo.messageSecret = crypto_1.randomBytes(32)
586
+
587
+ if (options.getProfilePicUrl) {
588
+ const pfpUrl = await options.getProfilePicUrl(message.adminInvite.jid)
589
+ const { thumbnail } = await messages_media_1.generateThumbnail(pfpUrl, 'image')
590
+ m.newsletterAdminInviteMessage.jpegThumbnail = thumbnail
591
+ }
592
+
593
+ m.newsletterAdminInviteMessage.contextInfo = {
594
+ ...(message.contextInfo || {}),
595
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
596
+ }
597
+ }
598
+
599
+ else if ('pin' in message) {
600
+ m.pinInChatMessage = {}
601
+ m.messageContextInfo = {}
602
+
603
+ m.pinInChatMessage.key = message.pin.key
604
+ m.pinInChatMessage.type = message.pin?.type || 1
605
+ m.pinInChatMessage.senderTimestampMs = message.pin?.time || Date.now()
606
+ m.messageContextInfo.messageAddOnDurationInSecs = message.pin.type === 1 ? message.pin.time || 86400 : 0
607
+ }
608
+
609
+ else if ('keep' in message) {
610
+ m.keepInChatMessage = {}
611
+
612
+ m.keepInChatMessage.key = message.keep.key
613
+ m.keepInChatMessage.keepType = message.keep?.type || 1
614
+ m.keepInChatMessage.timestampMs = message.keep?.time || Date.now()
615
+ }
616
+
617
+ else if ('call' in message) {
618
+ m.messageContextInfo = {}
619
+ m.scheduledCallCreationMessage = {}
620
+
621
+ m.scheduledCallCreationMessage.scheduledTimestampMs = message.call?.time || Date.now()
622
+ m.scheduledCallCreationMessage.callType = message.call?.type || 1
623
+ m.scheduledCallCreationMessage.title = message.call?.name || 'Call Creation'
624
+ m.messageContextInfo.messageSecret = crypto_1.randomBytes(32)
625
+
626
+ m.scheduledCallCreationMessage.contextInfo = {
627
+ ...(message.contextInfo || {}),
628
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
629
+ }
630
+ }
631
+
632
+ else if ('paymentInvite' in message) {
633
+ m.messageContextInfo = {}
634
+ m.paymentInviteMessage = {}
635
+
636
+ m.paymentInviteMessage.expiryTimestamp = message.paymentInvite?.expiry || 0
637
+ m.paymentInviteMessage.serviceType = message.paymentInvite?.type || 2
638
+ m.messageContextInfo.messageSecret = crypto_1.randomBytes(32)
639
+
640
+ m.paymentInviteMessage.contextInfo = {
641
+ ...(message.contextInfo || {}),
642
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
643
+ }
644
+ }
645
+
646
+ else if ('buttonReply' in message) {
647
+ switch (message.type) {
648
+ case 'list':
649
+ m.listResponseMessage = {
650
+ title: message.buttonReply.title,
651
+ description: message.buttonReply.description,
652
+ singleSelectReply: {
653
+ selectedRowId: message.buttonReply.rowId
654
+ },
655
+ lisType: WAProto_1.proto.Message.ListResponseMessage.ListType.SINGLE_SELECT
656
+ }
657
+ break
658
+ case 'template':
659
+ m.templateButtonReplyMessage = {
660
+ selectedDisplayText: message.buttonReply.displayText,
661
+ selectedId: message.buttonReply.id,
662
+ selectedIndex: message.buttonReply.index
663
+ }
664
+ break
665
+ case 'plain':
666
+ m.buttonsResponseMessage = {
667
+ selectedButtonId: message.buttonReply.id,
668
+ selectedDisplayText: message.buttonReply.displayText,
669
+ type: WAProto_1.proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
670
+ }
671
+ break
672
+ case 'interactive':
673
+ m.interactiveResponseMessage = {
674
+ body: {
675
+ text: message.buttonReply.displayText,
676
+ format: WAProto_1.proto.Message.InteractiveResponseMessage.Body.Format.EXTENSIONS_1
677
+ },
678
+ nativeFlowResponseMessage: {
679
+ name: message.buttonReply.nativeFlows.name,
680
+ paramsJson: message.buttonReply.nativeFlows.paramsJson,
681
+ version: message.buttonReply.nativeFlows.version
682
+ }
683
+ }
684
+ break
685
+ }
686
+
687
+ m.messageContextInfo = {
688
+ messageSecret: crypto_1.randomBytes(32)
689
+ }
690
+ }
691
+
692
+ else if ('ptv' in message && message.ptv) {
693
+ const { videoMessage } = await prepareWAMessageMedia({ video: message.video }, options)
694
+
695
+ m.ptvMessage = videoMessage
696
+
697
+ m.messageContextInfo = {
698
+ messageSecret: crypto_1.randomBytes(32)
699
+ }
700
+ }
701
+
702
+ else if ('order' in message) {
703
+ m.messageContextInfo = {
704
+ messageSecret: crypto_1.randomBytes(32)
705
+ }
706
+
707
+ m.orderMessage = Types_1.WAProto.Message.OrderMessage.fromObject(message.order)
708
+
709
+ m.orderMessage.contextInfo = {
710
+ ...(message.contextInfo || {}),
711
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
712
+ }
713
+ }
714
+
715
+ else if ('event' in message) {
716
+ m.messageContextInfo = {
717
+ messageSecret: crypto_1.randomBytes(32)
718
+ }
719
+
720
+ m.eventMessage = Types_1.WAProto.Message.EventMessage.fromObject(message.event)
721
+
722
+ if (!message.event.startTime) {
723
+ m.eventMessage.startTime = generics_1.unixTimestampSeconds()
724
+ }
725
+
726
+ m.eventMessage.contextInfo = {
727
+ ...(message.contextInfo || {}),
728
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
729
+ }
730
+ }
731
+
732
+ else if ('product' in message) {
733
+ const { imageMessage } = await prepareWAMessageMedia({ image: message.product.productImage }, options)
734
+
735
+ m.productMessage = Types_1.WAProto.Message.ProductMessage.fromObject({
736
+ ...message,
737
+ product: {
738
+ ...message.product,
739
+ productImage: imageMessage,
740
+ }
741
+ })
742
+
743
+ m.messageContextInfo = {
744
+ messageSecret: crypto_1.randomBytes(32)
745
+ }
746
+ }
747
+
748
+ else if ('pollResult' in message) {
749
+ if (!Array.isArray(message.pollResult.values)) {
750
+ throw new boom_1.Boom('Invalid pollResult values', { statusCode: 400 })
751
+ }
752
+
753
+ const pollResultSnapshotMessage = {
754
+ name: message.pollResult.name,
755
+ pollVotes: message.pollResult.values.map(([optionName, optionVoteCount]) => ({
756
+ optionName,
757
+ optionVoteCount
758
+ }))
759
+ }
760
+
761
+ pollResultSnapshotMessage.contextInfo = {
762
+ ...(message.contextInfo || {}),
763
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
764
+ }
765
+
766
+ m.messageContextInfo = {
767
+ messageSecret: crypto_1.randomBytes(32)
768
+ }
769
+
770
+ m.pollResultSnapshotMessage = pollResultSnapshotMessage
771
+ }
772
+
773
+ else if ('poll' in message) {
774
+ if (!Array.isArray(message.poll.values)) {
775
+ throw new boom_1.Boom('Invalid poll values', { statusCode: 400 })
776
+ }
777
+
778
+ if (message.poll.selectableCount < 0
779
+ || message.poll.selectableCount > message.poll.values.length) {
780
+ throw new boom_1.Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, { statusCode: 400 })
781
+ }
782
+
783
+ m.messageContextInfo = {
784
+ messageSecret: message.poll.messageSecret || crypto_1.randomBytes(32),
785
+ }
786
+
787
+ const pollCreationMessage = {
788
+ name: message.poll.name,
789
+ selectableOptionsCount: message.poll?.selectableCount || 0,
790
+ options: message.poll.values.map(optionName => ({ optionName })),
791
+ }
792
+
793
+ pollCreationMessage.contextInfo = {
794
+ ...(message.contextInfo || {}),
795
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
796
+ }
797
+
798
+ if(message.poll?.toAnnouncementGroup) {
799
+ m.pollCreationMessageV2 = pollCreationMessage
800
+ } else {
801
+ if(message.poll.selectableCount > 0) {
802
+ m.pollCreationMessageV3 = pollCreationMessage
803
+ } else {
804
+ m.pollCreationMessage = pollCreationMessage
805
+ }
806
+ }
807
+ }
808
+
809
+ else if ('payment' in message) {
810
+ const requestPaymentMessage = {
811
+ amount: {
812
+ currencyCode: message.payment?.currency || 'IDR',
813
+ offset: message.payment?.offset || 0,
814
+ value: message.payment?.amount || 999999999
815
+ },
816
+ expiryTimestamp: message.payment?.expiry || 0,
817
+ amount1000: message.payment?.amount || 999999999 * 1000,
818
+ currencyCodeIso4217: message.payment?.currency || 'IDR',
819
+ requestFrom: message.payment?.from || '0@s.whatsapp.net',
820
+ noteMessage: {
821
+ extendedTextMessage: {
822
+ text: message.payment?.note || 'Notes'
823
+ }
824
+ },
825
+ background: {
826
+ placeholderArgb: message.payment?.image?.placeholderArgb || 4278190080,
827
+ textArgb: message.payment?.image?.textArgb || 4294967295,
828
+ subtextArgb: message.payment?.image?.subtextArgb || 4294967295,
829
+ type: 1
830
+ }
831
+ }
832
+
833
+ requestPaymentMessage.noteMessage.extendedTextMessage.contextInfo = {
834
+ ...(message.contextInfo || {}),
835
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
836
+ }
837
+
838
+ m.messageContextInfo = {
839
+ messageSecret: crypto_1.randomBytes(32)
840
+ }
841
+
842
+ m.requestPaymentMessage = requestPaymentMessage
843
+ }
844
+
845
+ else if ('sharePhoneNumber' in message) {
846
+ m.protocolMessage = {
847
+ type: Types_1.WAProto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
848
+ }
849
+
850
+ m.messageContextInfo = {
851
+ messageSecret: crypto_1.randomBytes(32)
852
+ }
853
+ }
854
+
855
+ else if ('requestPhoneNumber' in message) {
856
+ m.requestPhoneNumberMessage = {}
857
+ }
858
+
859
+ else {
860
+ const mess = await prepareWAMessageMedia(message, options)
861
+ const [type] = Object.keys(mess)
862
+
863
+ mess[type].contextInfo = {
864
+ ...(message.contextInfo || {}),
865
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
866
+ }
867
+
868
+ mess.messageContextInfo = {
869
+ messageSecret: crypto_1.randomBytes(32)
870
+ }
871
+
872
+ m = mess
873
+ }
874
+
875
+ if ('sections' in message && !!message.sections) {
876
+ const listMessage = {
877
+ title: message.title,
878
+ buttonText: message.buttonText,
879
+ footerText: message.footer,
880
+ description: message.text,
881
+ sections: message.sections,
882
+ listType: WAProto_1.proto.Message.ListMessage.ListType.SINGLE_SELECT
883
+ }
884
+
885
+ listMessage.contextInfo = {
886
+ ...(message.contextInfo || {}),
887
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
888
+ }
889
+
890
+ m = { listMessage }
891
+
892
+ m.messageContextInfo = {
893
+ messageSecret: crypto_1.randomBytes(32)
894
+ }
895
+ }
896
+
897
+ else if ('productList' in message && !!message.productList) {
898
+ const thumbnail = message.thumbnail ? await messages_media_1.generateThumbnail(message.thumbnail, 'image') : null
899
+
900
+ const listMessage = {
901
+ title: message.title,
902
+ buttonText: message.buttonText,
903
+ footerText: message.footer,
904
+ description: message.text,
905
+ productListInfo: {
906
+ productSections: message.productList,
907
+ headerImage: {
908
+ productId: message.productList[0].products[0].productId,
909
+ jpegThumbnail: thumbnail?.thumbnail || null
910
+ },
911
+ businessOwnerJid: message.businessOwnerJid
912
+ },
913
+ listType: WAProto_1.proto.Message.ListMessage.ListType.PRODUCT_LIST
914
+ }
915
+
916
+ listMessage.contextInfo = {
917
+ ...(message.contextInfo || {}),
918
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
919
+ }
920
+
921
+ m = { listMessage }
922
+
923
+ m.messageContextInfo = {
924
+ messageSecret: crypto_1.randomBytes(32)
925
+ }
926
+ }
927
+
928
+ else if ('buttons' in message && !!message.buttons) {
929
+ const buttonsMessage = {
930
+ buttons: message.buttons.map(b => ({ ...b, type: WAProto_1.proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
931
+ }
932
+
933
+ if ('text' in message) {
934
+ buttonsMessage.contentText = message.text
935
+ buttonsMessage.headerType = WAProto_1.proto.Message.ButtonsMessage.HeaderType.EMPTY
936
+ }
937
+
938
+ else {
939
+ if ('caption' in message) {
940
+ buttonsMessage.contentText = message.caption
941
+ }
942
+
943
+ const type = Object.keys(m)[0].replace('Message', '').toUpperCase()
944
+
945
+ buttonsMessage.headerType = WAProto_1.proto.Message.ButtonsMessage.HeaderType[type]
946
+
947
+ Object.assign(buttonsMessage, m)
948
+ }
949
+
950
+ if ('footer' in message && !!message.footer) {
951
+ buttonsMessage.footerText = message.footer
952
+ }
953
+
954
+ if ('title' in message && !!message.title) {
955
+ buttonsMessage.text = message.title
956
+ buttonsMessage.headerType = WAProto_1.proto.Message.ButtonsMessage.HeaderType.TEXT
957
+ }
958
+
959
+ buttonsMessage.contextInfo = {
960
+ ...(message.contextInfo || {}),
961
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
962
+ }
963
+
964
+ m = { buttonsMessage }
965
+
966
+ m.messageContextInfo = {
967
+ messageSecret: crypto_1.randomBytes(32)
968
+ }
969
+ }
970
+
971
+ else if ('templateButtons' in message && !!message.templateButtons) {
972
+ const hydratedTemplate = {
973
+ hydratedButtons: message.templateButtons
974
+ }
975
+
976
+ if ('text' in message) {
977
+ hydratedTemplate.hydratedContentText = message.text
978
+ }
979
+
980
+ else {
981
+ if ('caption' in message) {
982
+ hydratedTemplate.hydratedContentText = message.caption
983
+ }
984
+
985
+ Object.assign(msg, m)
986
+ }
987
+
988
+ if ('footer' in message && !!message.footer) {
989
+ hydratedTemplate.hydratedFooterText = message.footer
990
+ }
991
+
992
+ hydratedTemplate.contextInfo = {
993
+ ...(message.contextInfo || {}),
994
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
995
+ }
996
+
997
+ m = { templateMessage: { hydratedTemplate }}
998
+
999
+ m.messageContextInfo = {
1000
+ messageSecret: crypto_1.randomBytes(32)
1001
+ }
1002
+ }
1003
+
1004
+ else if ('interactiveButtons' in message && !!message.interactiveButtons) {
1005
+ const interactiveMessage = {
1006
+ nativeFlowMessage: {
1007
+ buttons: message.interactiveButtons
1008
+ }
1009
+ }
1010
+
1011
+ if ('text' in message) {
1012
+ interactiveMessage.body = {
1013
+ text: message.text
1014
+ },
1015
+ interactiveMessage.header = {
1016
+ title: message.title,
1017
+ subtitle: message.subtitle,
1018
+ hasMediaAttachment: false
1019
+ }
1020
+ }
1021
+
1022
+ else {
1023
+ if ('caption' in message) {
1024
+ interactiveMessage.body = {
1025
+ text: message.caption
1026
+ }
1027
+
1028
+ interactiveMessage.header = {
1029
+ title: message.title,
1030
+ subtitle: message.subtitle,
1031
+ hasMediaAttachment: message.hasMediaAttachment ? message.hasMediaAttachment : false,
1032
+ ...Object.assign(interactiveMessage, m)
1033
+ }
1034
+ }
1035
+ }
1036
+
1037
+ if ('footer' in message && !!message.footer) {
1038
+ interactiveMessage.footer = {
1039
+ text: message.footer
1040
+ }
1041
+ }
1042
+
1043
+ interactiveMessage.contextInfo = {
1044
+ ...(message.contextInfo || {}),
1045
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
1046
+ }
1047
+
1048
+ m = { interactiveMessage }
1049
+
1050
+ m.messageContextInfo = {
1051
+ messageSecret: crypto_1.randomBytes(32)
1052
+ }
1053
+ }
1054
+
1055
+ else if ('shop' in message && !!message.shop) {
1056
+ const interactiveMessage = {
1057
+ shopStorefrontMessage: {
1058
+ surface: message.shop.surface,
1059
+ id: message.shop.id
1060
+ }
1061
+ }
1062
+
1063
+ if ('text' in message) {
1064
+ interactiveMessage.body = {
1065
+ text: message.text
1066
+ },
1067
+ interactiveMessage.header = {
1068
+ title: message.title,
1069
+ subtitle: message.subtitle,
1070
+ hasMediaAttachment: false
1071
+ }
1072
+ }
1073
+
1074
+ else {
1075
+ if ('caption' in message) {
1076
+ interactiveMessage.body = {
1077
+ text: message.caption
1078
+ }
1079
+
1080
+ interactiveMessage.header = {
1081
+ title: message.title,
1082
+ subtitle: message.subtitle,
1083
+ hasMediaAttachment: message.hasMediaAttachment ? message.hasMediaAttachment : false,
1084
+ ...Object.assign(interactiveMessage, m)
1085
+ }
1086
+ }
1087
+ }
1088
+
1089
+ if ('footer' in message && !!message.footer) {
1090
+ interactiveMessage.footer = {
1091
+ text: message.footer
1092
+ }
1093
+ }
1094
+
1095
+ interactiveMessage.contextInfo = {
1096
+ ...(message.contextInfo || {}),
1097
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
1098
+ }
1099
+
1100
+ m = { interactiveMessage }
1101
+
1102
+ m.messageContextInfo = {
1103
+ messageSecret: crypto_1.randomBytes(32)
1104
+ }
1105
+ }
1106
+
1107
+ else if ('collection' in message && !!message.collection) {
1108
+ const interactiveMessage = {
1109
+ collectionMessage: {
1110
+ bizJid: message.collection.bizJid,
1111
+ id: message.collection.id,
1112
+ messageVersion: message?.collection?.version
1113
+ }
1114
+ }
1115
+
1116
+ if ('text' in message) {
1117
+ interactiveMessage.body = {
1118
+ text: message.text
1119
+ },
1120
+ interactiveMessage.header = {
1121
+ title: message.title,
1122
+ subtitle: message.subtitle,
1123
+ hasMediaAttachment: false
1124
+ }
1125
+ }
1126
+
1127
+ else {
1128
+ if ('caption' in message) {
1129
+ interactiveMessage.body = {
1130
+ text: message.caption
1131
+ }
1132
+ interactiveMessage.header = {
1133
+ title: message.title,
1134
+ subtitle: message.subtitle,
1135
+ hasMediaAttachment: message.hasMediaAttachment ? message.hasMediaAttachment : false,
1136
+ ...Object.assign(interactiveMessage, m)
1137
+ }
1138
+ }
1139
+ }
1140
+
1141
+ if ('footer' in message && !message.footer) {
1142
+ interactiveMessage.footer = {
1143
+ text: message.footer
1144
+ }
1145
+ }
1146
+
1147
+ interactiveMessage.contextInfo = {
1148
+ ...(message.contextInfo || {}),
1149
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
1150
+ }
1151
+
1152
+ m = { interactiveMessage }
1153
+
1154
+ m.messageContextInfo = {
1155
+ messageSecret: crypto_1.randomBytes(32)
1156
+ }
1157
+ }
1158
+
1159
+ else if ('cards' in message && !!message.cards) {
1160
+ const slides = await Promise.all(message.cards.map(async (slide) => {
1161
+ const { image, video, product, title, body, footer, buttons } = slide
1162
+ let header
1163
+
1164
+ if (product) {
1165
+ const { imageMessage } = await prepareWAMessageMedia({ image: product.productImage, ...options }, options)
1166
+ header = {
1167
+ productMessage: {
1168
+ product: {
1169
+ ...product,
1170
+ productImage: imageMessage,
1171
+ },
1172
+ ...slide
1173
+ }
1174
+ }
1175
+ }
1176
+
1177
+ else if (image) {
1178
+ header = await prepareWAMessageMedia({ image: image, ...options }, options)
1179
+ }
1180
+
1181
+ else if (video) {
1182
+ header = await prepareWAMessageMedia({ video: video, ...options }, options)
1183
+ }
1184
+
1185
+ const msg = {
1186
+ header: {
1187
+ title,
1188
+ hasMediaAttachment: true,
1189
+ ...header
1190
+ },
1191
+ body: {
1192
+ text: body
1193
+ },
1194
+ footer: {
1195
+ text: footer
1196
+ },
1197
+ nativeFlowMessage: {
1198
+ buttons,
1199
+ }
1200
+ }
1201
+
1202
+ return msg
1203
+ }))
1204
+
1205
+ const interactiveMessage = {
1206
+ carouselMessage: {
1207
+ cards: slides
1208
+ }
1209
+ }
1210
+
1211
+ if ('text' in message) {
1212
+ interactiveMessage.body = {
1213
+ text: message.text
1214
+ },
1215
+ interactiveMessage.header = {
1216
+ title: message.title,
1217
+ subtitle: message.subtitle,
1218
+ hasMediaAttachment: false
1219
+ }
1220
+ }
1221
+
1222
+ if ('footer' in message && !!message.footer) {
1223
+ interactiveMessage.footer = {
1224
+ text: message.footer
1225
+ }
1226
+ }
1227
+
1228
+ interactiveMessage.contextInfo = {
1229
+ ...(message.contextInfo || {}),
1230
+ ...(message.mentions ? { mentionedJid: message.mentions } : {})
1231
+ }
1232
+
1233
+ m = { interactiveMessage }
1234
+
1235
+ m.messageContextInfo = {
1236
+ messageSecret: crypto_1.randomBytes(32)
1237
+ }
1238
+ }
1239
+
1240
+ if ('ephemeral' in message && !!message.ephemeral) {
1241
+ m = { ephemeralMessage: { message: m } }
1242
+ }
1243
+
1244
+ if ('viewOnce' in message && !!message.viewOnce) {
1245
+ m = { viewOnceMessage: { message: m } }
1246
+ }
1247
+
1248
+ if ('viewOnceV2' in message && !!message.viewOnceV2) {
1249
+ m = { viewOnceMessageV2: { message: m } }
1250
+ }
1251
+
1252
+ if ('viewOnceV2Ext' in message && !!message.viewOnceV2Ext) {
1253
+ m = { viewOnceMessageV2Extension: { message: m } }
1254
+ }
1255
+
1256
+ if ('edit' in message) {
1257
+ m.messageContextInfo = {
1258
+ messageSecret: crypto_1.randomBytes(32)
1259
+ }
1260
+
1261
+ m = {
1262
+ protocolMessage: {
1263
+ key: message.edit,
1264
+ editedMessage: m,
1265
+ timestampMs: Date.now(),
1266
+ type: Types_1.WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT
1267
+ }
1268
+ }
1269
+ }
1270
+
1271
+ return Types_1.WAProto.Message.fromObject(m)
1272
+ }
1273
+
1274
+ const generateWAMessageFromContent = (jid, message, options) => {
1275
+ if (!options.timestamp) {
1276
+ options.timestamp = new Date()
1277
+ }
1278
+
1279
+ const innerMessage = normalizeMessageContent(message)
1280
+ const key = getContentType(innerMessage)
1281
+ const timestamp = generics_1.unixTimestampSeconds(options.timestamp)
1282
+ const { quoted, userJid } = options
1283
+
1284
+ if (quoted && !WABinary_1.isJidNewsletter(jid)) {
1285
+ const participant = quoted.key.fromMe
1286
+ ? userJid
1287
+ : quoted.participant || quoted.key.participant || quoted.key.remoteJid
1288
+
1289
+ let quotedMsg = normalizeMessageContent(quoted.message)
1290
+ const msgType = getContentType(quotedMsg)
1291
+
1292
+ quotedMsg = WAProto_1.proto.Message.fromObject({ [msgType]: quotedMsg[msgType] })
1293
+
1294
+ const quotedContent = quotedMsg[msgType]
1295
+
1296
+ if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
1297
+ delete quotedContent.contextInfo
1298
+ }
1299
+
1300
+ let requestPayment
1301
+
1302
+ if (key === 'requestPaymentMessage') {
1303
+ if (innerMessage?.requestPaymentMessage && innerMessage?.requestPaymentMessage?.noteMessage?.extendedTextMessage) {
1304
+ requestPayment = innerMessage?.requestPaymentMessage?.noteMessage?.extendedTextMessage
1305
+ } else if (innerMessage?.requestPaymentMessage && innerMessage?.requestPaymentMessage?.noteMessage?.stickerMessage) {
1306
+ requestPayment = innerMessage.requestPaymentMessage?.noteMessage?.stickerMessage
1307
+ }
1308
+ }
1309
+
1310
+ const contextInfo = (key === 'requestPaymentMessage' ? requestPayment?.contextInfo : innerMessage[key].contextInfo) || {}
1311
+
1312
+ contextInfo.participant = WABinary_1.jidNormalizedUser(participant)
1313
+ contextInfo.stanzaId = quoted.key.id
1314
+ contextInfo.quotedMessage = quotedMsg
1315
+
1316
+ if (jid !== quoted.key.remoteJid) {
1317
+ contextInfo.remoteJid = quoted.key.remoteJid
1318
+ }
1319
+
1320
+ if (key === 'requestPaymentMessage' && requestPayment) {
1321
+ requestPayment.contextInfo = contextInfo
1322
+ } else {
1323
+ innerMessage[key].contextInfo = contextInfo
1324
+ }
1325
+ }
1326
+
1327
+ if (!!options?.ephemeralExpiration &&
1328
+ key !== 'protocolMessage' &&
1329
+ key !== 'ephemeralMessage' &&
1330
+ !WABinary_1.isJidNewsletter(jid)) {
1331
+ innerMessage[key].contextInfo = {
1332
+ ...(innerMessage[key].contextInfo || {}),
1333
+ expiration: options.ephemeralExpiration || Defaults_1.WA_DEFAULT_EPHEMERAL
1334
+ }
1335
+ }
1336
+
1337
+ message = Types_1.WAProto.Message.fromObject(message)
1338
+
1339
+ const messageJSON = {
1340
+ key: {
1341
+ remoteJid: jid,
1342
+ fromMe: true,
1343
+ id: options?.messageId || generics_1.generateMessageID()
1344
+ },
1345
+ message: message,
1346
+ messageTimestamp: timestamp,
1347
+ messageStubParameters: [],
1348
+ participant: WABinary_1.isJidGroup(jid) || WABinary_1.isJidStatusBroadcast(jid) ? userJid : undefined,
1349
+ status: Types_1.WAMessageStatus.PENDING
1350
+ }
1351
+
1352
+ return Types_1.WAProto.WebMessageInfo.fromObject(messageJSON)
1353
+ }
1354
+
1355
+ const generateWAMessage = async (jid, content, options) => {
1356
+ options.logger = options?.logger?.child({ msgId: options.messageId })
1357
+
1358
+ return generateWAMessageFromContent(jid, await generateWAMessageContent(content, { newsletter: WABinary_1.isJidNewsletter(jid), ...options }), options)
1359
+ }
1360
+
1361
+ const getContentType = (content) => {
1362
+ if (content) {
1363
+ const keys = Object.keys(content)
1364
+ const key = keys.find(k => (k === 'conversation' || k.endsWith('Message') || k.endsWith('V2') || k.endsWith('V3') || k.endsWith('V4') || k.endsWith('V5')) && k !== 'senderKeyDistributionMessage' && k !== 'messageContextInfo')
1365
+
1366
+ return key
1367
+ }
1368
+ }
1369
+
1370
+ /**
1371
+ * Normalizes ephemeral, view once messages to regular message content
1372
+ * Eg. image messages in ephemeral messages, in view once messages etc.
1373
+ * @param content
1374
+ * @returns
1375
+ */
1376
+ const normalizeMessageContent = (content) => {
1377
+ if (!content) {
1378
+ return undefined
1379
+ }
1380
+
1381
+ for (let i = 0; i < 5; i++) {
1382
+ const inner = getFutureProofMessage(content)
1383
+ if (!inner) {
1384
+ break
1385
+ }
1386
+
1387
+ content = inner.message
1388
+ }
1389
+
1390
+ return content
1391
+
1392
+ function getFutureProofMessage(message) {
1393
+ return (
1394
+ (message === null || message === void 0 ? void 0 : message.editedMessage)
1395
+ || (message === null || message === void 0 ? void 0 : message.statusAddYours)
1396
+ || (message === null || message === void 0 ? void 0 : message.botTaskMessage)
1397
+ || (message === null || message === void 0 ? void 0 : message.eventCoverImage)
1398
+ || (message === null || message === void 0 ? void 0 : message.questionMessage)
1399
+ || (message === null || message === void 0 ? void 0 : message.viewOnceMessage)
1400
+ || (message === null || message === void 0 ? void 0 : message.botInvokeMessage)
1401
+ || (message === null || message === void 0 ? void 0 : message.ephemeralMessage)
1402
+ || (message === null || message === void 0 ? void 0 : message.lottieStickerMessage)
1403
+ || (message === null || message === void 0 ? void 0 : message.groupStatusMessage)
1404
+ || (message === null || message === void 0 ? void 0 : message.limitSharingMessage)
1405
+ || (message === null || message === void 0 ? void 0 : message.viewOnceMessageV2)
1406
+ || (message === null || message === void 0 ? void 0 : message.botForwardedMessage)
1407
+ || (message === null || message === void 0 ? void 0 : message.statusMentionMessage)
1408
+ || (message === null || message === void 0 ? void 0 : message.groupStatusMessageV2)
1409
+ || (message === null || message === void 0 ? void 0 : message.pollCreationMessageV4)
1410
+ || (message === null || message === void 0 ? void 0 : message.pollCreationMessageV5)
1411
+ || (message === null || message === void 0 ? void 0 : message.associatedChildMessage)
1412
+ || (message === null || message === void 0 ? void 0 : message.groupMentionedMessage)
1413
+ || (message === null || message === void 0 ? void 0 : message.groupStatusMentionMessage)
1414
+ || (message === null || message === void 0 ? void 0 : message.viewOnceMessageV2Extension)
1415
+ || (message === null || message === void 0 ? void 0 : message.documentWithCaptionMessage)
1416
+ || (message === null || message === void 0 ? void 0 : message.pollCreationOptionImageMessage))
1417
+ }
1418
+ }
1419
+
1420
+ /**
1421
+ * Extract the true message content from a message
1422
+ * Eg. extracts the inner message from a disappearing message/view once message
1423
+ */
1424
+ const extractMessageContent = (content) => {
1425
+ const extractFromButtonsMessage = (msg) => {
1426
+ const header = typeof msg.header === 'object' && msg.header !== null
1427
+
1428
+ if (header ? msg.header?.imageMessage : msg.imageMessage) {
1429
+ return { imageMessage: header ? msg.header.imageMessage : msg.imageMessage }
1430
+ }
1431
+
1432
+ else if (header ? msg.header?.documentMessage : msg.documentMessage) {
1433
+ return { documentMessage: header ? msg.header.documentMessage : msg.documentMessage }
1434
+ }
1435
+
1436
+ else if (header ? msg.header?.videoMessage : msg.videoMessage) {
1437
+ return { videoMessage: header ? msg.header.videoMessage: msg.videoMessage }
1438
+ }
1439
+
1440
+ else if (header ? msg.header?.locationMessage : msg.locationMessage) {
1441
+ return { locationMessage: header ? msg.header.locationMessage : msg.locationMessage }
1442
+ }
1443
+
1444
+ else if (header ? msg.header?.productMessage : msg.productMessage) {
1445
+ return { productMessage: header ? msg.header.productMessage : msg.productMessage }
1446
+ }
1447
+
1448
+ else {
1449
+ return {
1450
+ conversation: 'contentText' in msg
1451
+ ? msg.contentText
1452
+ : ('hydratedContentText' in msg ? msg.hydratedContentText : 'body' in msg ? msg.body.text : '')
1453
+ }
1454
+ }
1455
+ }
1456
+
1457
+ content = normalizeMessageContent(content)
1458
+
1459
+ if (content?.buttonsMessage) {
1460
+ return extractFromButtonsMessage(content.buttonsMessage)
1461
+ }
1462
+
1463
+ if (content?.interactiveMessage) {
1464
+ return extractFromButtonsMessage(content.interactiveMessage)
1465
+ }
1466
+
1467
+ if (content?.templateMessage?.interactiveMessageTemplate) {
1468
+ return extractFromButtonsMessage(content?.templateMessage?.interactiveMessageTemplate)
1469
+ }
1470
+
1471
+ if (content?.templateMessage?.hydratedFourRowTemplate) {
1472
+ return extractFromButtonsMessage(content?.templateMessage?.hydratedFourRowTemplate)
1473
+ }
1474
+
1475
+ if (content?.templateMessage?.hydratedTemplate) {
1476
+ return extractFromButtonsMessage(content?.templateMessage?.hydratedTemplate)
1477
+ }
1478
+
1479
+ if (content?.templateMessage?.fourRowTemplate) {
1480
+ return extractFromButtonsMessage(content?.templateMessage?.fourRowTemplate)
1481
+ }
1482
+
1483
+ return content
1484
+ }
1485
+
1486
+ /**
1487
+ * Returns the device predicted by message ID
1488
+ */
1489
+ const getDevice = (id) => /^3A.{18}$/.test(id) ? 'ios' :
1490
+ /^3E.{20}$/.test(id) ? 'web' :
1491
+ /^(.{21}|.{32})$/.test(id) ? 'android' :
1492
+ /^(3F|.{18}$)/.test(id) ? 'desktop' :
1493
+ 'baileys'
1494
+
1495
+ /** Upserts a receipt in the message */
1496
+ const updateMessageWithReceipt = (msg, receipt) => {
1497
+ msg.userReceipt = msg.userReceipt || []
1498
+ const recp = msg.userReceipt.find(m => m.userJid === receipt.userJid)
1499
+
1500
+ if (recp) {
1501
+ Object.assign(recp, receipt)
1502
+ }
1503
+
1504
+ else {
1505
+ msg.userReceipt.push(receipt)
1506
+ }
1507
+ }
1508
+
1509
+ /** Update the message with a new reaction */
1510
+ const updateMessageWithReaction = (msg, reaction) => {
1511
+ const authorID = generics_1.getKeyAuthor(reaction.key)
1512
+ const reactions = (msg.reactions || [])
1513
+ .filter(r => generics_1.getKeyAuthor(r.key) !== authorID)
1514
+
1515
+ if (reaction.text) {
1516
+ reactions.push(reaction)
1517
+ }
1518
+
1519
+ msg.reactions = reactions
1520
+ }
1521
+
1522
+ /** Update the message with a new poll update */
1523
+ const updateMessageWithPollUpdate = (msg, update) => {
1524
+ const authorID = generics_1.getKeyAuthor(update.pollUpdateMessageKey)
1525
+ const votes = (msg.pollUpdates || [])
1526
+ .filter(r => generics_1.getKeyAuthor(r.pollUpdateMessageKey) !== authorID)
1527
+
1528
+ if (update.vote?.selectedOptions?.length) {
1529
+ votes.push(update)
1530
+ }
1531
+
1532
+ msg.pollUpdates = votes
1533
+ }
1534
+
1535
+ /**
1536
+ * Aggregates all poll updates in a poll.
1537
+ * @param msg the poll creation message
1538
+ * @param meId your jid
1539
+ * @returns A list of options & their voters
1540
+ */
1541
+ function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
1542
+ message = normalizeMessageContent(message)
1543
+
1544
+ const opts = message?.pollCreationMessage?.options || message?.pollCreationMessageV2?.options || message?.pollCreationMessageV3?.options || []
1545
+
1546
+ const voteHashMap = opts.reduce((acc, opt) => {
1547
+ const hash = crypto_2.sha256(Buffer.from(opt.optionName || '')).toString()
1548
+ acc[hash] = {
1549
+ name: opt.optionName || '',
1550
+ voters: []
1551
+ }
1552
+
1553
+ return acc
1554
+ }, {})
1555
+
1556
+ for (const update of pollUpdates || []) {
1557
+ const { vote } = update
1558
+
1559
+ if (!vote) {
1560
+ continue
1561
+ }
1562
+
1563
+ for (const option of vote.selectedOptions || []) {
1564
+ const hash = option.toString()
1565
+ let data = voteHashMap[hash]
1566
+
1567
+ if (!data) {
1568
+ voteHashMap[hash] = {
1569
+ name: 'Unknown',
1570
+ voters: []
1571
+ }
1572
+
1573
+ data = voteHashMap[hash]
1574
+ }
1575
+
1576
+ voteHashMap[hash].voters.push(generics_1.getKeyAuthor(update.pollUpdateMessageKey, meId))
1577
+ }
1578
+ }
1579
+
1580
+ return Object.values(voteHashMap)
1581
+ }
1582
+
1583
+ /** Given a list of message keys, aggregates them by chat & sender. Useful for sending read receipts in bulk */
1584
+ const aggregateMessageKeysNotFromMe = (keys) => {
1585
+ const keyMap = {}
1586
+
1587
+ for (const { remoteJid, id, participant, fromMe } of keys) {
1588
+ if (!fromMe) {
1589
+ const uqKey = `${remoteJid}:${participant || ''}`
1590
+
1591
+ if (!keyMap[uqKey]) {
1592
+ keyMap[uqKey] = {
1593
+ jid: remoteJid,
1594
+ participant: participant,
1595
+ messageIds: []
1596
+ }
1597
+ }
1598
+
1599
+ keyMap[uqKey].messageIds.push(id)
1600
+ }
1601
+ }
1602
+
1603
+ return Object.values(keyMap)
1604
+ }
1605
+
1606
+ const REUPLOAD_REQUIRED_STATUS = [410, 404]
1607
+
1608
+ /**
1609
+ * Downloads the given message. Throws an error if it's not a media message
1610
+ */
1611
+ const downloadMediaMessage = async (message, type, options, ctx) => {
1612
+ const result = await downloadMsg().catch(async (error) => {
1613
+ if (ctx && axios_1.default.isAxiosError(error) && // check if the message requires a reupload
1614
+ REUPLOAD_REQUIRED_STATUS.includes(error.response?.status)) {
1615
+ ctx.logger.info({ key: message.key }, 'sending reupload media request...')
1616
+
1617
+ // request reupload
1618
+ message = await ctx.reuploadRequest(message)
1619
+
1620
+ const result = await downloadMsg()
1621
+
1622
+ return result
1623
+ }
1624
+
1625
+ throw error
1626
+ })
1627
+
1628
+ return result
1629
+
1630
+ async function downloadMsg() {
1631
+ const mContent = extractMessageContent(message.message)
1632
+
1633
+ if (!mContent) {
1634
+ throw new boom_1.Boom('No message present', { statusCode: 400, data: message })
1635
+ }
1636
+
1637
+ const contentType = getContentType(mContent)
1638
+ let mediaType = contentType?.replace('Message', '')
1639
+ let media = mContent[contentType]
1640
+
1641
+ if (contentType === 'productMessage') {
1642
+ media = mContent[contentType]?.product?.productImage
1643
+ }
1644
+
1645
+ if (!media || typeof media !== 'object' || (!('url' in media) && !('thumbnailDirectPath' in media))) {
1646
+ throw new boom_1.Boom(`"${contentType}" message is not a media message`)
1647
+ }
1648
+
1649
+ let download
1650
+
1651
+ if ('thumbnailDirectPath' in media && !('url' in media)) {
1652
+ download = {
1653
+ directPath: media.thumbnailDirectPath,
1654
+ mediaKey: media.mediaKey
1655
+ }
1656
+ mediaType = 'thumbnail-link'
1657
+ }
1658
+
1659
+ else {
1660
+ download = media
1661
+ }
1662
+
1663
+ const stream = await messages_media_1.downloadContentFromMessage(download, mediaType, options)
1664
+
1665
+ if (type === 'buffer') {
1666
+ const bufferArray = []
1667
+
1668
+ for await (const chunk of stream) {
1669
+ bufferArray.push(chunk)
1670
+ }
1671
+
1672
+ return Buffer.concat(bufferArray)
1673
+ }
1674
+
1675
+ return stream
1676
+ }
1677
+ }
1678
+
1679
+ /** Checks whether the given message is a media message if it is returns the inner content */
1680
+ const assertMediaContent = (content) => {
1681
+ content = extractMessageContent(content)
1682
+
1683
+ const mediaContent = content?.documentMessage
1684
+ || content?.imageMessage
1685
+ || content?.videoMessage
1686
+ || content?.audioMessage
1687
+ || content?.stickerMessage
1688
+
1689
+ if (!mediaContent) {
1690
+ throw new boom_1.Boom('given message is not a media message', { statusCode: 400, data: content })
1691
+ }
1692
+ return mediaContent
1693
+ }
1694
+
1695
+ /**
1696
+ * this is an experimental patch to make buttons work
1697
+ * Don't know how it works, but it does for now
1698
+ */
1699
+ const patchMessageForMdIfRequired = (message) => {
1700
+ if (message?.buttonsMessage ||
1701
+ message?.templateMessage ||
1702
+ message?.listMessage ||
1703
+ message?.interactiveMessage?.nativeFlowMesaage
1704
+ ) {
1705
+ message = {
1706
+ viewOnceMessageV2Extension: {
1707
+ message: {
1708
+ messageContextInfo: {
1709
+ deviceListMetadataVersion: 2,
1710
+ deviceListMetadata: {}
1711
+ },
1712
+ ...message
1713
+ }
1714
+ }
1715
+ }
1716
+ }
1717
+ return message
1718
+ }
1719
+
1720
+ module.exports = {
1721
+ extractUrlFromText,
1722
+ generateLinkPreviewIfRequired,
1723
+ prepareWAMessageMedia,
1724
+ prepareDisappearingMessageSettingContent,
1725
+ generateForwardMessageContent,
1726
+ generateWAMessageContent,
1727
+ generateWAMessageFromContent,
1728
+ generateWAMessage,
1729
+ getContentType,
1730
+ normalizeMessageContent,
1731
+ extractMessageContent,
1732
+ getDevice,
1733
+ updateMessageWithReceipt,
1734
+ updateMessageWithReaction,
1735
+ updateMessageWithPollUpdate,
1736
+ getAggregateVotesInPollMessage,
1737
+ aggregateMessageKeysNotFromMe,
1738
+ downloadMediaMessage,
1739
+ assertMediaContent,
1740
+ patchMessageForMdIfRequired
1741
+ }