@xbibzlibrary/whatsbibz 1.3.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 (260) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/LICENSE +22 -0
  3. package/LICENSE.upstream +21 -0
  4. package/README.md +280 -0
  5. package/VERIFIKASI-IDENTITAS-2026-09-03.md +138 -0
  6. package/WAProto/GenerateStatics.sh +3 -0
  7. package/WAProto/WAProto.proto +6035 -0
  8. package/WAProto/fix-imports.js +81 -0
  9. package/WAProto/index.d.ts +15314 -0
  10. package/WAProto/index.js +132326 -0
  11. package/assets/logo/README.md +21 -0
  12. package/assets/logo/png/banner-1200x360.png +0 -0
  13. package/assets/logo/png/icon-1024.png +0 -0
  14. package/assets/logo/png/icon-128.png +0 -0
  15. package/assets/logo/png/icon-16.png +0 -0
  16. package/assets/logo/png/icon-24.png +0 -0
  17. package/assets/logo/png/icon-256.png +0 -0
  18. package/assets/logo/png/icon-32.png +0 -0
  19. package/assets/logo/png/icon-48.png +0 -0
  20. package/assets/logo/png/icon-512.png +0 -0
  21. package/assets/logo/png/icon-64.png +0 -0
  22. package/assets/logo/png/mark-512.png +0 -0
  23. package/assets/logo/preview.png +0 -0
  24. package/assets/logo/whatsbibz.ico +0 -0
  25. package/lib/BibzWhats/client.d.ts +95 -0
  26. package/lib/BibzWhats/client.js +501 -0
  27. package/lib/BibzWhats/device-identity.d.ts +60 -0
  28. package/lib/BibzWhats/device-identity.js +234 -0
  29. package/lib/BibzWhats/extract.d.ts +29 -0
  30. package/lib/BibzWhats/extract.js +115 -0
  31. package/lib/BibzWhats/index.d.ts +7 -0
  32. package/lib/BibzWhats/index.js +8 -0
  33. package/lib/BibzWhats/jid.d.ts +22 -0
  34. package/lib/BibzWhats/jid.js +98 -0
  35. package/lib/BibzWhats/pairing.d.ts +35 -0
  36. package/lib/BibzWhats/pairing.js +186 -0
  37. package/lib/BibzWhats/send.d.ts +9 -0
  38. package/lib/BibzWhats/send.js +107 -0
  39. package/lib/BibzWhats/version.d.ts +6 -0
  40. package/lib/BibzWhats/version.js +7 -0
  41. package/lib/Defaults/index.d.ts +73 -0
  42. package/lib/Defaults/index.js +141 -0
  43. package/lib/Modded/message_builder.d.ts +15 -0
  44. package/lib/Modded/message_builder.js +2330 -0
  45. package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
  46. package/lib/Signal/Group/ciphertext-message.js +11 -0
  47. package/lib/Signal/Group/group-session-builder.d.ts +14 -0
  48. package/lib/Signal/Group/group-session-builder.js +29 -0
  49. package/lib/Signal/Group/group_cipher.d.ts +16 -0
  50. package/lib/Signal/Group/group_cipher.js +81 -0
  51. package/lib/Signal/Group/index.d.ts +11 -0
  52. package/lib/Signal/Group/index.js +11 -0
  53. package/lib/Signal/Group/keyhelper.d.ts +10 -0
  54. package/lib/Signal/Group/keyhelper.js +17 -0
  55. package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
  56. package/lib/Signal/Group/sender-chain-key.js +25 -0
  57. package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
  58. package/lib/Signal/Group/sender-key-distribution-message.js +62 -0
  59. package/lib/Signal/Group/sender-key-message.d.ts +18 -0
  60. package/lib/Signal/Group/sender-key-message.js +65 -0
  61. package/lib/Signal/Group/sender-key-name.d.ts +17 -0
  62. package/lib/Signal/Group/sender-key-name.js +47 -0
  63. package/lib/Signal/Group/sender-key-record.d.ts +30 -0
  64. package/lib/Signal/Group/sender-key-record.js +40 -0
  65. package/lib/Signal/Group/sender-key-state.d.ts +38 -0
  66. package/lib/Signal/Group/sender-key-state.js +83 -0
  67. package/lib/Signal/Group/sender-message-key.d.ts +11 -0
  68. package/lib/Signal/Group/sender-message-key.js +25 -0
  69. package/lib/Signal/libsignal.d.ts +4 -0
  70. package/lib/Signal/libsignal.js +406 -0
  71. package/lib/Signal/lid-mapping.d.ts +18 -0
  72. package/lib/Signal/lid-mapping.js +276 -0
  73. package/lib/Socket/Client/index.d.ts +2 -0
  74. package/lib/Socket/Client/index.js +2 -0
  75. package/lib/Socket/Client/types.d.ts +15 -0
  76. package/lib/Socket/Client/types.js +10 -0
  77. package/lib/Socket/Client/websocket.d.ts +12 -0
  78. package/lib/Socket/Client/websocket.js +53 -0
  79. package/lib/Socket/business.d.ts +537 -0
  80. package/lib/Socket/business.js +421 -0
  81. package/lib/Socket/chats.d.ts +110 -0
  82. package/lib/Socket/chats.js +1006 -0
  83. package/lib/Socket/communities.d.ts +646 -0
  84. package/lib/Socket/communities.js +430 -0
  85. package/lib/Socket/engine.d.ts +129 -0
  86. package/lib/Socket/engine.js +767 -0
  87. package/lib/Socket/groups.d.ts +149 -0
  88. package/lib/Socket/groups.js +326 -0
  89. package/lib/Socket/index.d.ts +637 -0
  90. package/lib/Socket/index.js +14 -0
  91. package/lib/Socket/messages-recv.d.ts +239 -0
  92. package/lib/Socket/messages-recv.js +1307 -0
  93. package/lib/Socket/messages-send.d.ts +580 -0
  94. package/lib/Socket/messages-send.js +1639 -0
  95. package/lib/Socket/mex.d.ts +2 -0
  96. package/lib/Socket/mex.js +47 -0
  97. package/lib/Socket/newsletter.d.ts +176 -0
  98. package/lib/Socket/newsletter.js +456 -0
  99. package/lib/Socket/socket.d.ts +56 -0
  100. package/lib/Socket/socket.js +998 -0
  101. package/lib/Types/Auth.d.ts +115 -0
  102. package/lib/Types/Auth.js +1 -0
  103. package/lib/Types/Bussines.d.ts +36 -0
  104. package/lib/Types/Bussines.js +1 -0
  105. package/lib/Types/Call.d.ts +14 -0
  106. package/lib/Types/Call.js +1 -0
  107. package/lib/Types/Chat.d.ts +124 -0
  108. package/lib/Types/Chat.js +7 -0
  109. package/lib/Types/Contact.d.ts +23 -0
  110. package/lib/Types/Contact.js +1 -0
  111. package/lib/Types/Events.d.ts +241 -0
  112. package/lib/Types/Events.js +1 -0
  113. package/lib/Types/GroupMetadata.d.ts +67 -0
  114. package/lib/Types/GroupMetadata.js +1 -0
  115. package/lib/Types/Label.d.ts +46 -0
  116. package/lib/Types/Label.js +24 -0
  117. package/lib/Types/LabelAssociation.d.ts +29 -0
  118. package/lib/Types/LabelAssociation.js +6 -0
  119. package/lib/Types/Message.d.ts +427 -0
  120. package/lib/Types/Message.js +10 -0
  121. package/lib/Types/Newsletter.d.ts +134 -0
  122. package/lib/Types/Newsletter.js +30 -0
  123. package/lib/Types/Product.d.ts +78 -0
  124. package/lib/Types/Product.js +1 -0
  125. package/lib/Types/Signal.d.ts +77 -0
  126. package/lib/Types/Signal.js +1 -0
  127. package/lib/Types/Socket.d.ts +173 -0
  128. package/lib/Types/Socket.js +2 -0
  129. package/lib/Types/State.d.ts +38 -0
  130. package/lib/Types/State.js +12 -0
  131. package/lib/Types/USync.d.ts +25 -0
  132. package/lib/Types/USync.js +1 -0
  133. package/lib/Types/index.d.ts +75 -0
  134. package/lib/Types/index.js +32 -0
  135. package/lib/Utils/auth-utils.d.ts +18 -0
  136. package/lib/Utils/auth-utils.js +289 -0
  137. package/lib/Utils/browser-utils.d.ts +3 -0
  138. package/lib/Utils/browser-utils.js +47 -0
  139. package/lib/Utils/business.d.ts +22 -0
  140. package/lib/Utils/business.js +230 -0
  141. package/lib/Utils/chat-utils.d.ts +69 -0
  142. package/lib/Utils/chat-utils.js +811 -0
  143. package/lib/Utils/companion-reg-client-utils.d.ts +20 -0
  144. package/lib/Utils/companion-reg-client-utils.js +66 -0
  145. package/lib/Utils/crypto.d.ts +41 -0
  146. package/lib/Utils/crypto.js +117 -0
  147. package/lib/Utils/decode-wa-message.d.ts +47 -0
  148. package/lib/Utils/decode-wa-message.js +282 -0
  149. package/lib/Utils/event-buffer.d.ts +35 -0
  150. package/lib/Utils/event-buffer.js +590 -0
  151. package/lib/Utils/generics.d.ts +90 -0
  152. package/lib/Utils/generics.js +384 -0
  153. package/lib/Utils/history.d.ts +21 -0
  154. package/lib/Utils/history.js +130 -0
  155. package/lib/Utils/identity-change-handler.d.ts +36 -0
  156. package/lib/Utils/identity-change-handler.js +48 -0
  157. package/lib/Utils/index.d.ts +25 -0
  158. package/lib/Utils/index.js +24 -0
  159. package/lib/Utils/link-preview.d.ts +20 -0
  160. package/lib/Utils/link-preview.js +84 -0
  161. package/lib/Utils/logger.d.ts +12 -0
  162. package/lib/Utils/logger.js +2 -0
  163. package/lib/Utils/lt-hash.d.ts +10 -0
  164. package/lib/Utils/lt-hash.js +7 -0
  165. package/lib/Utils/make-mutex.d.ts +8 -0
  166. package/lib/Utils/make-mutex.js +32 -0
  167. package/lib/Utils/message-retry-manager.d.ts +109 -0
  168. package/lib/Utils/message-retry-manager.js +224 -0
  169. package/lib/Utils/messages-media.d.ts +129 -0
  170. package/lib/Utils/messages-media.js +784 -0
  171. package/lib/Utils/messages.d.ts +90 -0
  172. package/lib/Utils/messages.js +1240 -0
  173. package/lib/Utils/noise-handler.d.ts +19 -0
  174. package/lib/Utils/noise-handler.js +200 -0
  175. package/lib/Utils/offline-node-processor.d.ts +16 -0
  176. package/lib/Utils/offline-node-processor.js +39 -0
  177. package/lib/Utils/platform-identity.d.ts +14 -0
  178. package/lib/Utils/platform-identity.js +148 -0
  179. package/lib/Utils/pre-key-manager.d.ts +27 -0
  180. package/lib/Utils/pre-key-manager.js +105 -0
  181. package/lib/Utils/process-message.d.ts +59 -0
  182. package/lib/Utils/process-message.js +544 -0
  183. package/lib/Utils/reporting-utils.d.ts +10 -0
  184. package/lib/Utils/reporting-utils.js +257 -0
  185. package/lib/Utils/rich-messages.d.ts +276 -0
  186. package/lib/Utils/rich-messages.js +1143 -0
  187. package/lib/Utils/signal.d.ts +33 -0
  188. package/lib/Utils/signal.js +158 -0
  189. package/lib/Utils/stanza-ack.d.ts +10 -0
  190. package/lib/Utils/stanza-ack.js +37 -0
  191. package/lib/Utils/sticker-pack.d.ts +10 -0
  192. package/lib/Utils/sticker-pack.js +111 -0
  193. package/lib/Utils/sync-action-utils.d.ts +18 -0
  194. package/lib/Utils/sync-action-utils.js +47 -0
  195. package/lib/Utils/tc-token-utils.d.ts +8 -0
  196. package/lib/Utils/tc-token-utils.js +45 -0
  197. package/lib/Utils/use-multi-file-auth-state.d.ts +12 -0
  198. package/lib/Utils/use-multi-file-auth-state.js +120 -0
  199. package/lib/Utils/validate-connection.d.ts +10 -0
  200. package/lib/Utils/validate-connection.js +222 -0
  201. package/lib/VoIP/audio-feeder.d.ts +15 -0
  202. package/lib/VoIP/audio-feeder.js +136 -0
  203. package/lib/VoIP/index.d.ts +12 -0
  204. package/lib/VoIP/index.js +282 -0
  205. package/lib/VoIP/relay-transport.d.ts +43 -0
  206. package/lib/VoIP/relay-transport.js +559 -0
  207. package/lib/VoIP/signaling.js +603 -0
  208. package/lib/VoIP/types.d.ts +69 -0
  209. package/lib/VoIP/types.js +17 -0
  210. package/lib/VoIP/wasm-engine.d.ts +103 -0
  211. package/lib/VoIP/wasm-engine.js +1214 -0
  212. package/lib/VoIP/worker-bootstrap.js +1042 -0
  213. package/lib/WABinary/constants.d.ts +27 -0
  214. package/lib/WABinary/constants.js +1300 -0
  215. package/lib/WABinary/decode.d.ts +6 -0
  216. package/lib/WABinary/decode.js +261 -0
  217. package/lib/WABinary/encode.d.ts +2 -0
  218. package/lib/WABinary/encode.js +219 -0
  219. package/lib/WABinary/generic-utils.d.ts +16 -0
  220. package/lib/WABinary/generic-utils.js +190 -0
  221. package/lib/WABinary/index.d.ts +5 -0
  222. package/lib/WABinary/index.js +5 -0
  223. package/lib/WABinary/jid-utils.d.ts +47 -0
  224. package/lib/WABinary/jid-utils.js +95 -0
  225. package/lib/WABinary/types.d.ts +18 -0
  226. package/lib/WABinary/types.js +1 -0
  227. package/lib/WAM/BinaryInfo.d.ts +8 -0
  228. package/lib/WAM/BinaryInfo.js +9 -0
  229. package/lib/WAM/constants.d.ts +39 -0
  230. package/lib/WAM/constants.js +22852 -0
  231. package/lib/WAM/encode.d.ts +2 -0
  232. package/lib/WAM/encode.js +149 -0
  233. package/lib/WAM/index.d.ts +3 -0
  234. package/lib/WAM/index.js +3 -0
  235. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -0
  236. package/lib/WAUSync/Protocols/USyncContactProtocol.js +28 -0
  237. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
  238. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +53 -0
  239. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
  240. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +26 -0
  241. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
  242. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +37 -0
  243. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +25 -0
  244. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -0
  245. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +9 -0
  246. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +28 -0
  247. package/lib/WAUSync/Protocols/index.d.ts +4 -0
  248. package/lib/WAUSync/Protocols/index.js +4 -0
  249. package/lib/WAUSync/USyncQuery.d.ts +28 -0
  250. package/lib/WAUSync/USyncQuery.js +93 -0
  251. package/lib/WAUSync/USyncUser.d.ts +12 -0
  252. package/lib/WAUSync/USyncUser.js +22 -0
  253. package/lib/WAUSync/index.d.ts +3 -0
  254. package/lib/WAUSync/index.js +3 -0
  255. package/lib/assets/wasm/loader.js +5 -0
  256. package/lib/assets/wasm/whatsapp.wasm +0 -0
  257. package/lib/assets/wasm/worker-modules.js +273 -0
  258. package/lib/index.d.ts +21 -0
  259. package/lib/index.js +22 -0
  260. package/package.json +111 -0
@@ -0,0 +1,767 @@
1
+ import crypto from "crypto";
2
+ import { proto } from "../../WAProto/index.js";
3
+ import {
4
+ delay,
5
+ generateMessageID,
6
+ generateWAMessage,
7
+ generateWAMessageContent,
8
+ generateWAMessageFromContent,
9
+ getUrlFromDirectPath,
10
+ normalizeMessageContent,
11
+ prepareWAMessageMedia,
12
+ } from "../Utils/index.js";
13
+ import {
14
+ isJidGroup,
15
+ isPnUser,
16
+ jidNormalizedUser,
17
+ STORIES_JID,
18
+ } from "../WABinary/index.js";
19
+ export class BibzWhatsEngine {
20
+ constructor(waUploadToServer, relayMessageFn, config, sock) {
21
+ this.relayMessage = relayMessageFn;
22
+ this.waUploadToServer = waUploadToServer;
23
+ this.config = config;
24
+ this.sock = sock;
25
+ }
26
+ detectType(content) {
27
+ if (content.requestPaymentMessage) return "PAYMENT";
28
+ if (content.productMessage) return "PRODUCT";
29
+ if (content.interactiveButtons) return "INTERACTIVE_BUTTONS";
30
+ if (content.interactiveMessage?.carouselMessage) return "CAROUSEL";
31
+ if (content.interactiveMessage) return "INTERACTIVE";
32
+ if (content.albumMessage || content.album) return "ALBUM";
33
+ if (content.eventMessage) return "EVENT";
34
+ if (content.pollResultMessage) return "POLL_RESULT";
35
+ if (content.groupStatusMessage) return "GROUP_STORY";
36
+ return null;
37
+ }
38
+ async handlePayment(content, quoted) {
39
+ const data = content.requestPaymentMessage;
40
+ let notes = {};
41
+ if (data.sticker?.stickerMessage) {
42
+ notes = {
43
+ stickerMessage: {
44
+ ...data.sticker.stickerMessage,
45
+ contextInfo: {
46
+ stanzaId: quoted?.key?.id,
47
+ participant: quoted?.key?.participant || content.sender,
48
+ quotedMessage: quoted?.message,
49
+ },
50
+ },
51
+ };
52
+ } else if (data.note) {
53
+ notes = {
54
+ extendedTextMessage: {
55
+ text: data.note,
56
+ contextInfo: {
57
+ stanzaId: quoted?.key?.id,
58
+ participant: quoted?.key?.participant || content.sender,
59
+ quotedMessage: quoted?.message,
60
+ },
61
+ },
62
+ };
63
+ }
64
+ return {
65
+ requestPaymentMessage: proto.Message.RequestPaymentMessage.fromObject({
66
+ expiryTimestamp: data.expiry || 0,
67
+ amount1000: data.amount || 0,
68
+ currencyCodeIso4217: data.currency || "IDR",
69
+ requestFrom: data.from || "0@s.whatsapp.net",
70
+ noteMessage: notes,
71
+ background: data.background ?? {
72
+ id: "DEFAULT",
73
+ placeholderArgb: 0xfff0f0f0,
74
+ },
75
+ }),
76
+ };
77
+ }
78
+ async handleProduct(content, _jid, _quoted) {
79
+ const {
80
+ title,
81
+ description,
82
+ thumbnail,
83
+ productId,
84
+ retailerId,
85
+ url,
86
+ body = "",
87
+ footer = "",
88
+ buttons = [],
89
+ priceAmount1000 = null,
90
+ currencyCode = "IDR",
91
+ } = content.productMessage;
92
+ let productImage;
93
+ if (Buffer.isBuffer(thumbnail)) {
94
+ const { imageMessage } = await generateWAMessageContent(
95
+ { image: thumbnail },
96
+ { upload: this.waUploadToServer },
97
+ );
98
+ productImage = imageMessage;
99
+ } else if (typeof thumbnail === "object" && thumbnail.url) {
100
+ const { imageMessage } = await generateWAMessageContent(
101
+ { image: { url: thumbnail.url } },
102
+ { upload: this.waUploadToServer },
103
+ );
104
+ productImage = imageMessage;
105
+ }
106
+ return {
107
+ viewOnceMessage: {
108
+ message: {
109
+ interactiveMessage: {
110
+ body: { text: body },
111
+ footer: { text: footer },
112
+ header: {
113
+ title,
114
+ hasMediaAttachment: true,
115
+ productMessage: {
116
+ product: {
117
+ productImage,
118
+ productId,
119
+ title,
120
+ description,
121
+ currencyCode,
122
+ priceAmount1000,
123
+ retailerId,
124
+ url,
125
+ productImageCount: 1,
126
+ },
127
+ businessOwnerJid: "0@s.whatsapp.net",
128
+ },
129
+ },
130
+ nativeFlowMessage: { buttons },
131
+ },
132
+ },
133
+ },
134
+ };
135
+ }
136
+ async handleInteractive(content, _jid, _quoted) {
137
+ const {
138
+ title,
139
+ footer,
140
+ thumbnail,
141
+ image,
142
+ video,
143
+ document,
144
+ mimetype,
145
+ fileName,
146
+ jpegThumbnail,
147
+ contextInfo,
148
+ externalAdReply,
149
+ buttons = [],
150
+ nativeFlowMessage,
151
+ header,
152
+ } = content.interactiveMessage;
153
+ let media = null;
154
+ let _mediaType = null;
155
+ if (thumbnail) {
156
+ media = await prepareWAMessageMedia(
157
+ { image: { url: thumbnail } },
158
+ { upload: this.waUploadToServer },
159
+ );
160
+ _mediaType = "image";
161
+ } else if (image) {
162
+ const src =
163
+ typeof image === "object" && image.url
164
+ ? { image: { url: image.url } }
165
+ : { image };
166
+ media = await prepareWAMessageMedia(src, {
167
+ upload: this.waUploadToServer,
168
+ });
169
+ _mediaType = "image";
170
+ } else if (video) {
171
+ const src =
172
+ typeof video === "object" && video.url
173
+ ? { video: { url: video.url } }
174
+ : { video };
175
+ media = await prepareWAMessageMedia(src, {
176
+ upload: this.waUploadToServer,
177
+ });
178
+ _mediaType = "video";
179
+ } else if (document) {
180
+ const docPayload = { document };
181
+ if (jpegThumbnail) {
182
+ docPayload.jpegThumbnail =
183
+ typeof jpegThumbnail === "object" && jpegThumbnail.url
184
+ ? { url: jpegThumbnail.url }
185
+ : jpegThumbnail;
186
+ }
187
+ media = await prepareWAMessageMedia(docPayload, {
188
+ upload: this.waUploadToServer,
189
+ });
190
+ if (fileName) media.documentMessage.fileName = fileName;
191
+ if (mimetype) media.documentMessage.mimetype = mimetype;
192
+ _mediaType = "document";
193
+ }
194
+ const interactiveMessage = {
195
+ body: { text: title || "" },
196
+ footer: { text: footer || "" },
197
+ };
198
+ if (buttons && buttons.length > 0) {
199
+ interactiveMessage.nativeFlowMessage = { buttons };
200
+ if (nativeFlowMessage) {
201
+ interactiveMessage.nativeFlowMessage = {
202
+ ...interactiveMessage.nativeFlowMessage,
203
+ ...nativeFlowMessage,
204
+ };
205
+ }
206
+ } else if (nativeFlowMessage) {
207
+ interactiveMessage.nativeFlowMessage = nativeFlowMessage;
208
+ }
209
+ if (media) {
210
+ interactiveMessage.header = {
211
+ title: header || "",
212
+ hasMediaAttachment: true,
213
+ ...media,
214
+ };
215
+ } else {
216
+ interactiveMessage.header = {
217
+ title: header || "",
218
+ hasMediaAttachment: false,
219
+ };
220
+ }
221
+ const finalContextInfo = {};
222
+ if (contextInfo) {
223
+ Object.assign(finalContextInfo, {
224
+ mentionedJid: contextInfo.mentionedJid || [],
225
+ forwardingScore: contextInfo.forwardingScore || 0,
226
+ isForwarded: contextInfo.isForwarded || false,
227
+ ...contextInfo,
228
+ });
229
+ }
230
+ if (externalAdReply) {
231
+ finalContextInfo.externalAdReply = {
232
+ title: externalAdReply.title || "",
233
+ body: externalAdReply.body || "",
234
+ mediaType: externalAdReply.mediaType || 1,
235
+ thumbnailUrl: externalAdReply.thumbnailUrl || "",
236
+ mediaUrl: externalAdReply.mediaUrl || "",
237
+ sourceUrl: externalAdReply.sourceUrl || "",
238
+ showAdAttribution: externalAdReply.showAdAttribution || false,
239
+ renderLargerThumbnail: externalAdReply.renderLargerThumbnail || false,
240
+ ...externalAdReply,
241
+ };
242
+ }
243
+ if (Object.keys(finalContextInfo).length > 0) {
244
+ interactiveMessage.contextInfo = finalContextInfo;
245
+ }
246
+ return { interactiveMessage };
247
+ }
248
+ async handleInteractiveButtons(content, _jid, _quoted) {
249
+ const {
250
+ text,
251
+ caption,
252
+ title,
253
+ subtitle,
254
+ footer,
255
+ interactiveButtons,
256
+ hasMediaAttachment,
257
+ image,
258
+ video,
259
+ document,
260
+ mimetype,
261
+ jpegThumbnail,
262
+ location,
263
+ product,
264
+ businessOwnerJid,
265
+ } = content;
266
+ const bodyText = text || caption || "";
267
+ const buttons = interactiveButtons.map((btn) => ({
268
+ name: btn.name,
269
+ buttonParamsJson:
270
+ typeof btn.buttonParamsJson === "string"
271
+ ? btn.buttonParamsJson
272
+ : JSON.stringify(btn.buttonParamsJson),
273
+ }));
274
+ let headerContent = {};
275
+ let mediaAttached =
276
+ typeof hasMediaAttachment === "boolean" ? hasMediaAttachment : false;
277
+ if (image) {
278
+ const src =
279
+ typeof image === "object" && image.url
280
+ ? { image: { url: image.url } }
281
+ : { image };
282
+ const uploaded = await prepareWAMessageMedia(src, {
283
+ upload: this.waUploadToServer,
284
+ });
285
+ headerContent = { ...uploaded };
286
+ mediaAttached =
287
+ typeof hasMediaAttachment === "boolean" ? hasMediaAttachment : true;
288
+ } else if (video) {
289
+ const src =
290
+ typeof video === "object" && video.url
291
+ ? { video: { url: video.url } }
292
+ : { video };
293
+ const uploaded = await prepareWAMessageMedia(src, {
294
+ upload: this.waUploadToServer,
295
+ });
296
+ headerContent = { ...uploaded };
297
+ mediaAttached =
298
+ typeof hasMediaAttachment === "boolean" ? hasMediaAttachment : true;
299
+ } else if (document) {
300
+ const docPayload =
301
+ typeof document === "object" && document.url
302
+ ? { document: { url: document.url } }
303
+ : { document };
304
+ if (mimetype) docPayload.mimetype = mimetype;
305
+ const uploaded = await prepareWAMessageMedia(docPayload, {
306
+ upload: this.waUploadToServer,
307
+ });
308
+ if (jpegThumbnail) {
309
+ uploaded.documentMessage.jpegThumbnail =
310
+ typeof jpegThumbnail === "string"
311
+ ? Buffer.from(jpegThumbnail, "base64")
312
+ : jpegThumbnail;
313
+ }
314
+ headerContent = { ...uploaded };
315
+ mediaAttached =
316
+ typeof hasMediaAttachment === "boolean" ? hasMediaAttachment : true;
317
+ } else if (location) {
318
+ headerContent = {
319
+ locationMessage: {
320
+ degreesLatitude:
321
+ location.degressLatitude || location.degreesLatitude || 0,
322
+ degreesLongitude:
323
+ location.degressLongitude || location.degreesLongitude || 0,
324
+ name: location.name || "",
325
+ },
326
+ };
327
+ mediaAttached =
328
+ typeof hasMediaAttachment === "boolean" ? hasMediaAttachment : true;
329
+ } else if (product) {
330
+ let productImage;
331
+ if (product.productImage) {
332
+ const imgSrc =
333
+ typeof product.productImage === "object" && product.productImage.url
334
+ ? { image: { url: product.productImage.url } }
335
+ : { image: product.productImage };
336
+ const uploaded = await prepareWAMessageMedia(imgSrc, {
337
+ upload: this.waUploadToServer,
338
+ });
339
+ productImage = uploaded.imageMessage;
340
+ }
341
+ headerContent = {
342
+ productMessage: {
343
+ product: {
344
+ productImage,
345
+ productId: product.productId,
346
+ title: product.title,
347
+ description: product.description,
348
+ currencyCode: product.currencyCode || "IDR",
349
+ priceAmount1000: product.priceAmount1000,
350
+ retailerId: product.retailerId,
351
+ url: product.url,
352
+ productImageCount: product.productImageCount || 1,
353
+ },
354
+ businessOwnerJid: businessOwnerJid || "0@s.whatsapp.net",
355
+ },
356
+ };
357
+ mediaAttached =
358
+ typeof hasMediaAttachment === "boolean" ? hasMediaAttachment : true;
359
+ }
360
+ const interactiveMessage = {
361
+ body: { text: bodyText },
362
+ footer: { text: footer || "" },
363
+ header: {
364
+ title: title || "",
365
+ subtitle: subtitle || "",
366
+ hasMediaAttachment: mediaAttached,
367
+ ...headerContent,
368
+ },
369
+ nativeFlowMessage: { buttons },
370
+ };
371
+ return {
372
+ viewOnceMessage: {
373
+ message: {
374
+ messageContextInfo: {
375
+ deviceListMetadata: {},
376
+ deviceListMetadataVersion: 2,
377
+ messageSecret: crypto.randomBytes(32),
378
+ },
379
+ interactiveMessage,
380
+ },
381
+ },
382
+ };
383
+ }
384
+ async handleCarousel(content, _jid, _quoted) {
385
+ const { interactiveMessage } = content;
386
+ const { body, footer, header, carouselMessage, contextInfo } =
387
+ interactiveMessage;
388
+ const processedCards = [];
389
+ for (const card of carouselMessage.cards) {
390
+ const cardMsg = {
391
+ body: card.body || { text: "" },
392
+ footer: card.footer || { text: "" },
393
+ header: {
394
+ title: card.header?.title || "",
395
+ hasMediaAttachment: false,
396
+ },
397
+ };
398
+ if (card.nativeFlowMessage) {
399
+ cardMsg.nativeFlowMessage = card.nativeFlowMessage;
400
+ }
401
+ if (
402
+ card.header?.imageMessage ||
403
+ card.header?.videoMessage ||
404
+ card.header?.documentMessage
405
+ ) {
406
+ let headerContent = {};
407
+ let mediaAttached = true;
408
+ if (card.header.imageMessage) {
409
+ const url = card.header.imageMessage.url || card.header.imageMessage;
410
+ const src =
411
+ typeof url === "string" ? { image: { url } } : { image: url };
412
+ const uploaded = await prepareWAMessageMedia(src, {
413
+ upload: this.waUploadToServer,
414
+ });
415
+ headerContent = { ...uploaded };
416
+ } else if (card.header.videoMessage) {
417
+ const url = card.header.videoMessage.url || card.header.videoMessage;
418
+ const src =
419
+ typeof url === "string" ? { video: { url } } : { video: url };
420
+ const uploaded = await prepareWAMessageMedia(src, {
421
+ upload: this.waUploadToServer,
422
+ });
423
+ headerContent = { ...uploaded };
424
+ } else if (card.header.documentMessage) {
425
+ const url =
426
+ card.header.documentMessage.url || card.header.documentMessage;
427
+ const src =
428
+ typeof url === "string" ? { document: { url } } : { document: url };
429
+ const uploaded = await prepareWAMessageMedia(src, {
430
+ upload: this.waUploadToServer,
431
+ });
432
+ headerContent = { ...uploaded };
433
+ }
434
+ cardMsg.header = {
435
+ title: card.header?.title || "",
436
+ hasMediaAttachment: mediaAttached,
437
+ ...headerContent,
438
+ };
439
+ }
440
+ processedCards.push(cardMsg);
441
+ }
442
+ const interactiveMsg = {
443
+ body: body || { text: "" },
444
+ footer: footer || { text: "" },
445
+ header: header || { title: "", hasMediaAttachment: false },
446
+ carouselMessage: {
447
+ cards: processedCards,
448
+ messageVersion: carouselMessage.messageVersion || 1,
449
+ carouselCardType: carouselMessage.carouselCardType ?? 1,
450
+ },
451
+ };
452
+ if (contextInfo) {
453
+ interactiveMsg.contextInfo = contextInfo;
454
+ }
455
+ return {
456
+ viewOnceMessage: {
457
+ message: {
458
+ messageContextInfo: {
459
+ deviceListMetadata: {},
460
+ deviceListMetadataVersion: 2,
461
+ messageSecret: crypto.randomBytes(32),
462
+ },
463
+ interactiveMessage: interactiveMsg,
464
+ },
465
+ },
466
+ };
467
+ }
468
+ async handleAlbum(content, jid, quoted) {
469
+ const array = content.albumMessage || content.album;
470
+ const ctxInfo = content.contextInfo || {};
471
+ const album = await generateWAMessageFromContent(
472
+ jid,
473
+ {
474
+ messageContextInfo: {
475
+ messageSecret: crypto.randomBytes(32),
476
+ },
477
+ albumMessage: {
478
+ expectedImageCount: array.filter((a) => "image" in a).length,
479
+ expectedVideoCount: array.filter((a) => "video" in a).length,
480
+ },
481
+ },
482
+ {
483
+ userJid: jidNormalizedUser(this.sock.authState?.creds?.me?.id || ""),
484
+ quoted,
485
+ upload: this.waUploadToServer,
486
+ },
487
+ );
488
+ await this.relayMessage(jid, album.message, {
489
+ messageId: album.key.id,
490
+ });
491
+ for (let item of array) {
492
+ if (ctxInfo && Object.keys(ctxInfo).length > 0 && !item.contextInfo) {
493
+ item = { ...item, contextInfo: ctxInfo };
494
+ }
495
+ const img = await generateWAMessage(jid, item, {
496
+ upload: this.waUploadToServer,
497
+ userJid: jidNormalizedUser(this.sock.authState?.creds?.me?.id || ""),
498
+ });
499
+ img.message.messageContextInfo = {
500
+ messageSecret: crypto.randomBytes(32),
501
+ messageAssociation: {
502
+ associationType: 1,
503
+ parentMessageKey: album.key,
504
+ },
505
+ };
506
+ await this.relayMessage(jid, img.message, {
507
+ messageId: img.key.id,
508
+ });
509
+ }
510
+ return album;
511
+ }
512
+ async handleEvent(content, jid, quoted) {
513
+ const eventData = content.eventMessage;
514
+ const msg = await generateWAMessageFromContent(
515
+ jid,
516
+ {
517
+ viewOnceMessage: {
518
+ message: {
519
+ messageContextInfo: {
520
+ deviceListMetadata: {},
521
+ deviceListMetadataVersion: 2,
522
+ messageSecret: crypto.randomBytes(32),
523
+ },
524
+ eventMessage: {
525
+ isCanceled: eventData.isCanceled || false,
526
+ name: eventData.name,
527
+ description: eventData.description,
528
+ location: eventData.location || {
529
+ degreesLatitude: 0,
530
+ degreesLongitude: 0,
531
+ name: "Location",
532
+ },
533
+ joinLink: eventData.joinLink || "",
534
+ startTime:
535
+ typeof eventData.startTime === "string"
536
+ ? parseInt(eventData.startTime)
537
+ : eventData.startTime || Date.now(),
538
+ endTime:
539
+ typeof eventData.endTime === "string"
540
+ ? parseInt(eventData.endTime)
541
+ : eventData.endTime || Date.now() + 3600000,
542
+ extraGuestsAllowed: eventData.extraGuestsAllowed !== false,
543
+ },
544
+ },
545
+ },
546
+ },
547
+ {
548
+ quoted,
549
+ userJid: jidNormalizedUser(this.sock.authState?.creds?.me?.id || ""),
550
+ },
551
+ );
552
+ await this.relayMessage(jid, msg.message, {
553
+ messageId: msg.key.id,
554
+ });
555
+ return msg;
556
+ }
557
+ async handlePollResult(content, jid, quoted) {
558
+ const pollData = content.pollResultMessage;
559
+ const msg = await generateWAMessageFromContent(
560
+ jid,
561
+ {
562
+ pollResultSnapshotMessage: {
563
+ name: pollData.name,
564
+ pollVotes: pollData.pollVotes.map((vote) => ({
565
+ optionName: vote.optionName,
566
+ optionVoteCount:
567
+ typeof vote.optionVoteCount === "number"
568
+ ? vote.optionVoteCount.toString()
569
+ : vote.optionVoteCount,
570
+ })),
571
+ },
572
+ },
573
+ {
574
+ quoted,
575
+ userJid: jidNormalizedUser(this.sock.authState?.creds?.me?.id || ""),
576
+ },
577
+ );
578
+ await this.relayMessage(jid, msg.message, {
579
+ messageId: msg.key.id,
580
+ });
581
+ return msg;
582
+ }
583
+ async handleGroupStory(content, jid, _quoted, options = {}) {
584
+ const storyData = content.groupStatusMessage;
585
+ let waMsgContent;
586
+ if (storyData.message) {
587
+ waMsgContent = storyData;
588
+ } else {
589
+ waMsgContent = await generateWAMessageContent(storyData, {
590
+ upload: this.waUploadToServer,
591
+ });
592
+ }
593
+ const innerMsg = waMsgContent.message || waMsgContent;
594
+ const msgKey = Object.keys(innerMsg).find(
595
+ (k) => innerMsg[k] && typeof innerMsg[k] === "object",
596
+ );
597
+ if (msgKey) {
598
+ innerMsg[msgKey].contextInfo = innerMsg[msgKey].contextInfo || {};
599
+ innerMsg[msgKey].contextInfo.isGroupStatus = true;
600
+ if (!innerMsg[msgKey].contextInfo.statusSourceType) {
601
+ if (innerMsg.imageMessage)
602
+ innerMsg[msgKey].contextInfo.statusSourceType = 0;
603
+ else if (innerMsg.videoMessage)
604
+ innerMsg[msgKey].contextInfo.statusSourceType = 1;
605
+ else if (innerMsg.audioMessage)
606
+ innerMsg[msgKey].contextInfo.statusSourceType = 3;
607
+ else if (innerMsg.extendedTextMessage)
608
+ innerMsg[msgKey].contextInfo.statusSourceType = 4;
609
+ }
610
+ }
611
+ const finalMsg = {
612
+ groupStatusMessageV2: {
613
+ message: innerMsg,
614
+ },
615
+ };
616
+ return await this.relayMessage(jid, finalMsg, {
617
+ messageId: generateMessageID(),
618
+ });
619
+ }
620
+ async sendStatusWhatsApp(content, jids = []) {
621
+ const userJid = jidNormalizedUser(this.sock.authState.creds.me.id);
622
+ const allUsers = new Set();
623
+ allUsers.add(userJid);
624
+ for (const id of jids) {
625
+ if (isJidGroup(id)) {
626
+ try {
627
+ const metadata = await this.sock.groupMetadata(id);
628
+ metadata.participants.forEach((p) =>
629
+ allUsers.add(jidNormalizedUser(p.id)),
630
+ );
631
+ } catch (error) {
632
+ this.config.logger.error(
633
+ `Error getting metadata for group ${id}: ${error}`,
634
+ );
635
+ }
636
+ } else if (isPnUser(id)) {
637
+ allUsers.add(jidNormalizedUser(id));
638
+ }
639
+ }
640
+ const uniqueUsers = Array.from(allUsers);
641
+ const getRandomHexColor = () =>
642
+ "#" +
643
+ Math.floor(Math.random() * 16777215)
644
+ .toString(16)
645
+ .padStart(6, "0");
646
+ const isMedia = content.image || content.video || content.audio;
647
+ const isAudio = !!content.audio;
648
+ const messageContent = { ...content };
649
+ if (isMedia && !isAudio) {
650
+ if (messageContent.text) {
651
+ messageContent.caption = messageContent.text;
652
+ delete messageContent.text;
653
+ }
654
+ delete messageContent.ptt;
655
+ delete messageContent.font;
656
+ delete messageContent.backgroundColor;
657
+ delete messageContent.textColor;
658
+ }
659
+ if (isAudio) {
660
+ delete messageContent.text;
661
+ delete messageContent.caption;
662
+ delete messageContent.font;
663
+ delete messageContent.textColor;
664
+ }
665
+ const font = !isMedia
666
+ ? content.font || Math.floor(Math.random() * 9)
667
+ : undefined;
668
+ const textColor = !isMedia
669
+ ? content.textColor || getRandomHexColor()
670
+ : undefined;
671
+ const backgroundColor =
672
+ !isMedia || isAudio
673
+ ? content.backgroundColor || getRandomHexColor()
674
+ : undefined;
675
+ const ptt = isAudio
676
+ ? typeof content.ptt === "boolean"
677
+ ? content.ptt
678
+ : true
679
+ : undefined;
680
+ const { getUrlInfo } = await import("../Utils/link-preview.js");
681
+ const msg = await generateWAMessage(STORIES_JID, messageContent, {
682
+ logger: this.config.logger,
683
+ userJid,
684
+ getUrlInfo: (text) =>
685
+ getUrlInfo(text, {
686
+ thumbnailWidth: this.config.linkPreviewImageThumbnailWidth,
687
+ fetchOpts: { timeout: 3000, ...(this.config.options || {}) },
688
+ logger: this.config.logger,
689
+ uploadImage: this.config.generateHighQualityLinkPreview
690
+ ? this.waUploadToServer
691
+ : undefined,
692
+ }),
693
+ upload: this.waUploadToServer,
694
+ mediaCache: this.config.mediaCache,
695
+ options: this.config.options,
696
+ font,
697
+ textColor,
698
+ backgroundColor,
699
+ ptt,
700
+ });
701
+ await this.relayMessage(STORIES_JID, msg.message, {
702
+ messageId: msg.key.id,
703
+ statusJidList: uniqueUsers,
704
+ additionalNodes: [
705
+ {
706
+ tag: "meta",
707
+ attrs: {},
708
+ content: [
709
+ {
710
+ tag: "mentioned_users",
711
+ attrs: {},
712
+ content: jids.map((jid) => ({
713
+ tag: "to",
714
+ attrs: { jid: jidNormalizedUser(jid) },
715
+ })),
716
+ },
717
+ ],
718
+ },
719
+ ],
720
+ });
721
+ for (const id of jids) {
722
+ try {
723
+ const normalizedId = jidNormalizedUser(id);
724
+ const isPrivate = isPnUser(normalizedId);
725
+ const type = isPrivate
726
+ ? "statusMentionMessage"
727
+ : "groupStatusMentionMessage";
728
+ const protocolMessage = {
729
+ [type]: {
730
+ message: {
731
+ protocolMessage: {
732
+ key: msg.key,
733
+ type: 25,
734
+ },
735
+ },
736
+ },
737
+ messageContextInfo: {
738
+ messageSecret: crypto.randomBytes(32),
739
+ },
740
+ };
741
+ const statusMsg = await generateWAMessageFromContent(
742
+ normalizedId,
743
+ protocolMessage,
744
+ {
745
+ userJid: jidNormalizedUser(
746
+ this.sock.authState?.creds?.me?.id || "",
747
+ ),
748
+ },
749
+ );
750
+ await this.relayMessage(normalizedId, statusMsg.message, {
751
+ additionalNodes: [
752
+ {
753
+ tag: "meta",
754
+ attrs: isPrivate
755
+ ? { is_status_mention: "true" }
756
+ : { is_group_status_mention: "true" },
757
+ },
758
+ ],
759
+ });
760
+ await delay(2000);
761
+ } catch (error) {
762
+ this.config.logger.error(`Error sending to ${id}: ${error}`);
763
+ }
764
+ }
765
+ return msg;
766
+ }
767
+ }