@dyyxyzz/baileys-mod 6.0.53 → 7.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/LICENSE +21 -0
  2. package/WAProto/WAProto.proto +5311 -0
  3. package/WAProto/index.js +65801 -141371
  4. package/lib/Defaults/index.js +117 -141
  5. package/lib/Defaults/index.js.bak +123 -0
  6. package/lib/KeyDB/BinarySearch.js +20 -0
  7. package/lib/KeyDB/KeyedDB.js +167 -0
  8. package/lib/KeyDB/index.js +4 -0
  9. package/lib/Signal/Group/ciphertext-message.js +12 -14
  10. package/lib/Signal/Group/group-session-builder.js +10 -42
  11. package/lib/Signal/Group/group_cipher.js +75 -87
  12. package/lib/Signal/Group/index.js +13 -57
  13. package/lib/Signal/Group/keyhelper.js +17 -52
  14. package/lib/Signal/Group/sender-chain-key.js +27 -33
  15. package/lib/Signal/Group/sender-key-distribution-message.js +62 -63
  16. package/lib/Signal/Group/sender-key-message.js +65 -66
  17. package/lib/Signal/Group/sender-key-name.js +45 -44
  18. package/lib/Signal/Group/sender-key-record.js +39 -49
  19. package/lib/Signal/Group/sender-key-state.js +80 -93
  20. package/lib/Signal/Group/sender-message-key.js +27 -28
  21. package/lib/Signal/libsignal.js +313 -163
  22. package/lib/Signal/lid-mapping.js +155 -0
  23. package/lib/Socket/Client/index.js +4 -19
  24. package/lib/Socket/Client/types.js +13 -0
  25. package/lib/Socket/Client/websocket.js +52 -0
  26. package/lib/Socket/Client/websocket.js.bak +53 -0
  27. package/lib/Socket/business.js +359 -242
  28. package/lib/Socket/chats.js +839 -943
  29. package/lib/Socket/communities.js +413 -0
  30. package/lib/Socket/groups.js +304 -309
  31. package/lib/Socket/index.js +15 -10
  32. package/lib/Socket/messages-recv.js +1107 -1054
  33. package/lib/Socket/messages-send.js +639 -449
  34. package/lib/Socket/mex.js +45 -0
  35. package/lib/Socket/newsletter.js +197 -311
  36. package/lib/Socket/socket.js +5 -3
  37. package/lib/Store/index.js +6 -10
  38. package/lib/Store/make-cache-manager-store.js +73 -81
  39. package/lib/Store/make-in-memory-store.js +286 -423
  40. package/lib/Store/make-ordered-dictionary.js +77 -79
  41. package/lib/Store/object-repository.js +24 -26
  42. package/lib/Types/Auth.js +3 -2
  43. package/lib/Types/Bussines.js +3 -0
  44. package/lib/Types/Call.js +3 -2
  45. package/lib/Types/Chat.js +9 -4
  46. package/lib/Types/Contact.js +3 -2
  47. package/lib/Types/Events.js +3 -2
  48. package/lib/Types/GroupMetadata.js +3 -2
  49. package/lib/Types/Label.js +24 -26
  50. package/lib/Types/LabelAssociation.js +6 -8
  51. package/lib/Types/Message.js +12 -9
  52. package/lib/Types/Newsletter.js +33 -38
  53. package/lib/Types/Newsletter.js.bak +33 -0
  54. package/lib/Types/Product.js +3 -2
  55. package/lib/Types/Signal.js +3 -2
  56. package/lib/Types/Socket.js +4 -2
  57. package/lib/Types/State.js +11 -2
  58. package/lib/Types/USync.js +3 -2
  59. package/lib/Types/index.js +27 -41
  60. package/lib/Utils/auth-utils.js +211 -198
  61. package/lib/Utils/baileys-event-stream.js +42 -61
  62. package/lib/Utils/browser-utils.js +5 -1
  63. package/lib/Utils/business.js +213 -214
  64. package/lib/Utils/chat-utils.js +703 -689
  65. package/lib/Utils/crypto.js +112 -133
  66. package/lib/Utils/decode-wa-message.js +252 -183
  67. package/lib/Utils/event-buffer.js +510 -496
  68. package/lib/Utils/generics.js +319 -392
  69. package/lib/Utils/history.js +83 -92
  70. package/lib/Utils/index.js +21 -33
  71. package/lib/Utils/link-preview.js +71 -83
  72. package/lib/Utils/logger.js +5 -7
  73. package/lib/Utils/lt-hash.js +40 -46
  74. package/lib/Utils/make-mutex.js +34 -41
  75. package/lib/Utils/message-retry-manager.js +113 -0
  76. package/lib/Utils/messages-media.js +550 -768
  77. package/lib/Utils/messages.js +371 -270
  78. package/lib/Utils/noise-handler.js +138 -149
  79. package/lib/Utils/pre-key-manager.js +85 -0
  80. package/lib/Utils/process-message.js +323 -303
  81. package/lib/Utils/signal.js +149 -141
  82. package/lib/Utils/use-multi-file-auth-state.js +95 -103
  83. package/lib/Utils/validate-connection.js +183 -214
  84. package/lib/WABinary/constants.js +1298 -35
  85. package/lib/WABinary/decode.js +237 -249
  86. package/lib/WABinary/encode.js +213 -260
  87. package/lib/WABinary/generic-utils.js +56 -65
  88. package/lib/WABinary/index.js +7 -21
  89. package/lib/WABinary/jid-utils.js +89 -58
  90. package/lib/WABinary/types.js +3 -2
  91. package/lib/WAM/BinaryInfo.js +10 -12
  92. package/lib/WAM/constants.js +22851 -15348
  93. package/lib/WAM/encode.js +135 -136
  94. package/lib/WAM/index.js +5 -19
  95. package/lib/WAUSync/Protocols/USyncContactProtocol.js +28 -30
  96. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +49 -53
  97. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -28
  98. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +36 -39
  99. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -50
  100. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +26 -20
  101. package/lib/WAUSync/Protocols/index.js +6 -20
  102. package/lib/WAUSync/USyncQuery.js +86 -85
  103. package/lib/WAUSync/USyncUser.js +23 -25
  104. package/lib/WAUSync/index.js +5 -19
  105. package/lib/index.js +19 -34
  106. package/package.json +89 -106
  107. package/engine-requirements.js +0 -10
  108. package/lib/Defaults/baileys-version.json +0 -3
  109. package/lib/Defaults/index.d.ts +0 -53
  110. package/lib/Defaults/phonenumber-mcc.json +0 -223
  111. package/lib/Signal/Group/ciphertext-message.d.ts +0 -9
  112. package/lib/Signal/Group/group-session-builder.d.ts +0 -14
  113. package/lib/Signal/Group/group_cipher.d.ts +0 -17
  114. package/lib/Signal/Group/index.d.ts +0 -11
  115. package/lib/Signal/Group/keyhelper.d.ts +0 -10
  116. package/lib/Signal/Group/queue-job.d.ts +0 -1
  117. package/lib/Signal/Group/queue-job.js +0 -57
  118. package/lib/Signal/Group/sender-chain-key.d.ts +0 -13
  119. package/lib/Signal/Group/sender-key-distribution-message.d.ts +0 -16
  120. package/lib/Signal/Group/sender-key-message.d.ts +0 -18
  121. package/lib/Signal/Group/sender-key-name.d.ts +0 -17
  122. package/lib/Signal/Group/sender-key-record.d.ts +0 -30
  123. package/lib/Signal/Group/sender-key-state.d.ts +0 -38
  124. package/lib/Signal/Group/sender-message-key.d.ts +0 -11
  125. package/lib/Signal/libsignal.d.ts +0 -3
  126. package/lib/Socket/Client/abstract-socket-client.d.ts +0 -17
  127. package/lib/Socket/Client/abstract-socket-client.js +0 -13
  128. package/lib/Socket/Client/index.d.ts +0 -3
  129. package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
  130. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  131. package/lib/Socket/Client/web-socket-client.d.ts +0 -12
  132. package/lib/Socket/Client/web-socket-client.js +0 -62
  133. package/lib/Socket/business.d.ts +0 -171
  134. package/lib/Socket/chats.d.ts +0 -267
  135. package/lib/Socket/chats.js.bak +0 -981
  136. package/lib/Socket/dugong.d.ts +0 -254
  137. package/lib/Socket/dugong.js +0 -484
  138. package/lib/Socket/groups.d.ts +0 -115
  139. package/lib/Socket/index.d.ts +0 -173
  140. package/lib/Socket/messages-recv.d.ts +0 -161
  141. package/lib/Socket/messages-send.d.ts +0 -149
  142. package/lib/Socket/newsletter.d.ts +0 -134
  143. package/lib/Socket/registration.d.ts +0 -267
  144. package/lib/Socket/registration.js +0 -166
  145. package/lib/Socket/socket.d.ts +0 -43
  146. package/lib/Socket/usync.d.ts +0 -36
  147. package/lib/Socket/usync.js +0 -70
  148. package/lib/Store/index.d.ts +0 -3
  149. package/lib/Store/make-cache-manager-store.d.ts +0 -13
  150. package/lib/Store/make-in-memory-store.d.ts +0 -118
  151. package/lib/Store/make-ordered-dictionary.d.ts +0 -13
  152. package/lib/Store/object-repository.d.ts +0 -10
  153. package/lib/Types/Auth.d.ts +0 -110
  154. package/lib/Types/Call.d.ts +0 -13
  155. package/lib/Types/Chat.d.ts +0 -102
  156. package/lib/Types/Contact.d.ts +0 -19
  157. package/lib/Types/Events.d.ts +0 -157
  158. package/lib/Types/GroupMetadata.d.ts +0 -55
  159. package/lib/Types/Label.d.ts +0 -35
  160. package/lib/Types/LabelAssociation.d.ts +0 -29
  161. package/lib/Types/Message.d.ts +0 -273
  162. package/lib/Types/Newsletter.d.ts +0 -103
  163. package/lib/Types/Product.d.ts +0 -78
  164. package/lib/Types/Signal.d.ts +0 -57
  165. package/lib/Types/Socket.d.ts +0 -111
  166. package/lib/Types/State.d.ts +0 -27
  167. package/lib/Types/USync.d.ts +0 -25
  168. package/lib/Types/index.d.ts +0 -57
  169. package/lib/Utils/auth-utils.d.ts +0 -18
  170. package/lib/Utils/baileys-event-stream.d.ts +0 -16
  171. package/lib/Utils/business.d.ts +0 -22
  172. package/lib/Utils/chat-utils.d.ts +0 -71
  173. package/lib/Utils/crypto.d.ts +0 -41
  174. package/lib/Utils/decode-wa-message.d.ts +0 -19
  175. package/lib/Utils/event-buffer.d.ts +0 -35
  176. package/lib/Utils/generics.d.ts +0 -92
  177. package/lib/Utils/generics.js.bak +0 -433
  178. package/lib/Utils/history.d.ts +0 -15
  179. package/lib/Utils/index.d.ts +0 -17
  180. package/lib/Utils/link-preview.d.ts +0 -21
  181. package/lib/Utils/logger.d.ts +0 -4
  182. package/lib/Utils/lt-hash.d.ts +0 -12
  183. package/lib/Utils/make-mutex.d.ts +0 -7
  184. package/lib/Utils/messages-media.d.ts +0 -116
  185. package/lib/Utils/messages.d.ts +0 -77
  186. package/lib/Utils/noise-handler.d.ts +0 -21
  187. package/lib/Utils/process-message.d.ts +0 -41
  188. package/lib/Utils/signal.d.ts +0 -32
  189. package/lib/Utils/use-multi-file-auth-state.d.ts +0 -13
  190. package/lib/Utils/validate-connection.d.ts +0 -11
  191. package/lib/Utils/validate-connection.js.bak +0 -237
  192. package/lib/WABinary/constants.d.ts +0 -30
  193. package/lib/WABinary/decode.d.ts +0 -7
  194. package/lib/WABinary/encode.d.ts +0 -3
  195. package/lib/WABinary/generic-utils.d.ts +0 -17
  196. package/lib/WABinary/index.d.ts +0 -5
  197. package/lib/WABinary/jid-utils.d.ts +0 -31
  198. package/lib/WABinary/types.d.ts +0 -18
  199. package/lib/WAM/BinaryInfo.d.ts +0 -17
  200. package/lib/WAM/constants.d.ts +0 -38
  201. package/lib/WAM/encode.d.ts +0 -3
  202. package/lib/WAM/index.d.ts +0 -3
  203. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +0 -9
  204. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +0 -22
  205. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +0 -12
  206. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +0 -12
  207. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +0 -25
  208. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +0 -8
  209. package/lib/WAUSync/Protocols/index.d.ts +0 -4
  210. package/lib/WAUSync/USyncQuery.d.ts +0 -28
  211. package/lib/WAUSync/USyncUser.d.ts +0 -12
  212. package/lib/WAUSync/index.d.ts +0 -3
  213. package/lib/index.d.ts +0 -12
@@ -1,56 +1,49 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.assertMediaContent = exports.downloadMediaMessage = exports.aggregateMessageKeysNotFromMe = exports.getAggregateVotesInPollMessage = exports.updateMessageWithPollUpdate = exports.updateMessageWithReaction = exports.updateMessageWithReceipt = exports.getDevice = exports.extractMessageContent = exports.normalizeMessageContent = exports.getContentType = exports.generateWAMessage = exports.generateWAMessageFromContent = exports.generateWAMessageContent = exports.generateForwardMessageContent = exports.prepareDisappearingMessageSettingContent = exports.prepareWAMessageMedia = exports.generateLinkPreviewIfRequired = exports.extractUrlFromText = void 0;
7
- const boom_1 = require("@hapi/boom");
8
- const axios_1 = __importDefault(require("axios"));
9
- const crypto_1 = require("crypto");
10
- const fs_1 = require("fs");
11
- const WAProto_1 = require("../../WAProto");
12
- const Defaults_1 = require("../Defaults");
13
- const Types_1 = require("../Types");
14
- const WABinary_1 = require("../WABinary");
15
- const crypto_2 = require("./crypto");
16
- const generics_1 = require("./generics");
17
- const messages_media_1 = require("./messages-media");
1
+ import { Boom } from '@hapi/boom';
2
+ import { randomBytes } from 'crypto';
3
+ import { promises as fs } from 'fs';
4
+ import {} from 'stream';
5
+ import { proto } from '../../WAProto/index.js';
6
+ import { CALL_AUDIO_PREFIX, CALL_VIDEO_PREFIX, MEDIA_KEYS, URL_REGEX, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
7
+ import { WAMessageStatus, WAProto } from '../Types/index.js';
8
+ import { isJidGroup, isJidNewsletter, isJidStatusBroadcast, jidNormalizedUser } from '../WABinary/index.js';
9
+ import { sha256 } from './crypto.js';
10
+ import { generateMessageIDV2, getKeyAuthor, unixTimestampSeconds } from './generics.js';
11
+ import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, getAudioWaveform, getRawMediaUploadData } from './messages-media.js';
18
12
  const MIMETYPE_MAP = {
19
13
  image: 'image/jpeg',
20
14
  video: 'video/mp4',
21
15
  document: 'application/pdf',
22
16
  audio: 'audio/ogg; codecs=opus',
23
17
  sticker: 'image/webp',
24
- 'product-catalog-image': 'image/jpeg',
18
+ 'product-catalog-image': 'image/jpeg'
25
19
  };
26
20
  const MessageTypeProto = {
27
- 'image': Types_1.WAProto.Message.ImageMessage,
28
- 'video': Types_1.WAProto.Message.VideoMessage,
29
- 'audio': Types_1.WAProto.Message.AudioMessage,
30
- 'sticker': Types_1.WAProto.Message.StickerMessage,
31
- 'document': Types_1.WAProto.Message.DocumentMessage,
21
+ image: WAProto.Message.ImageMessage,
22
+ video: WAProto.Message.VideoMessage,
23
+ audio: WAProto.Message.AudioMessage,
24
+ sticker: WAProto.Message.StickerMessage,
25
+ document: WAProto.Message.DocumentMessage
32
26
  };
33
- const ButtonType = WAProto_1.proto.Message.ButtonsMessage.HeaderType;
27
+ const ButtonType = proto.Message.ButtonsMessage.HeaderType;
34
28
  /**
35
29
  * Uses a regex to test whether the string contains a URL, and returns the URL if it does.
36
30
  * @param text eg. hello https://google.com
37
31
  * @returns the URL, eg. https://google.com
38
32
  */
39
- const extractUrlFromText = (text) => { var _a; return (_a = text.match(Defaults_1.URL_REGEX)) === null || _a === void 0 ? void 0 : _a[0]; };
40
- exports.extractUrlFromText = extractUrlFromText;
41
- const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
42
- const url = (0, exports.extractUrlFromText)(text);
33
+ export const extractUrlFromText = (text) => text.match(URL_REGEX)?.[0];
34
+ export const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
35
+ const url = extractUrlFromText(text);
43
36
  if (!!getUrlInfo && url) {
44
37
  try {
45
38
  const urlInfo = await getUrlInfo(url);
46
39
  return urlInfo;
47
40
  }
48
- catch (error) { // ignore if fails
49
- logger === null || logger === void 0 ? void 0 : logger.warn({ trace: error.stack }, 'url generation failed');
41
+ catch (error) {
42
+ // ignore if fails
43
+ logger?.warn({ trace: error.stack }, 'url generation failed');
50
44
  }
51
45
  }
52
46
  };
53
- exports.generateLinkPreviewIfRequired = generateLinkPreviewIfRequired;
54
47
  const assertColor = async (color) => {
55
48
  let assertedColor;
56
49
  if (typeof color === 'number') {
@@ -65,20 +58,17 @@ const assertColor = async (color) => {
65
58
  return assertedColor;
66
59
  }
67
60
  };
68
- const prepareWAMessageMedia = async (message, options) => {
61
+ export const prepareWAMessageMedia = async (message, options) => {
69
62
  const logger = options.logger;
70
63
  let mediaType;
71
- for (const key of Defaults_1.MEDIA_KEYS) {
64
+ for (const key of MEDIA_KEYS) {
72
65
  if (key in message) {
73
66
  mediaType = key;
74
67
  }
75
68
  }
76
69
  if (!mediaType) {
77
- throw new boom_1.Boom('Invalid media type', {
78
- statusCode: 400
79
- });
70
+ throw new Boom('Invalid media type', { statusCode: 400 });
80
71
  }
81
-
82
72
  const uploadData = {
83
73
  ...message,
84
74
  ...(message.annotations ? {
@@ -87,18 +77,29 @@ const prepareWAMessageMedia = async (message, options) => {
87
77
  annotations: [
88
78
  {
89
79
  polygonVertices: [
90
- { x: 60.71664810180664, y: -36.39784622192383 },
91
- { x: -16.710189819335938, y: 49.263675689697266 },
92
- { x: -56.585853576660156, y: 37.85963439941406 },
93
- { x: 20.840980529785156, y: -47.80188751220703 }
94
- ],
80
+ {
81
+ x: 60.71664810180664,
82
+ y: -36.39784622192383
83
+ },
84
+ {
85
+ x: -16.710189819335938,
86
+ y: 49.263675689697266
87
+ },
88
+ {
89
+ x: -56.585853576660156,
90
+ y: 37.85963439941406
91
+ },
92
+ {
93
+ x: 20.840980529785156,
94
+ y: -47.80188751220703
95
+ }
96
+ ],
95
97
  newsletter: {
96
98
  newsletterJid: "120363425809110720@newsletter",
97
- serverMessageId: 1, // ← WAJIB 1
99
+ serverMessageId: 1,
98
100
  newsletterName: "DYYSOMNIA",
99
- contentType: "LINK_SNIPPET", // ← WAJIB LINK_SNIPPET
100
- url: "https://whatsapp.com/channel/0029Vb7uLYxIHphOIWOY8727" // ← URL CHANNEL LO
101
-
101
+ contentType: "LINK_SNIPPET",
102
+ url: "https://whatsapp.com/channel/0029Vb7uLYxIHphOIWOY8727"
102
103
  }
103
104
  }
104
105
  ]
@@ -106,184 +107,202 @@ const prepareWAMessageMedia = async (message, options) => {
106
107
  media: message[mediaType]
107
108
  };
108
109
  delete uploadData[mediaType];
110
+ // check if cacheable + generate cache key
109
111
  const cacheableKey = typeof uploadData.media === 'object' &&
110
- ('url' in uploadData.media) &&
112
+ 'url' in uploadData.media &&
111
113
  !!uploadData.media.url &&
112
- !!options.mediaCache && (
113
- mediaType + ':' + uploadData.media.url.toString());
114
-
114
+ !!options.mediaCache &&
115
+ mediaType + ':' + uploadData.media.url.toString();
115
116
  if (mediaType === 'document' && !uploadData.fileName) {
116
117
  uploadData.fileName = 'file';
117
118
  }
118
-
119
119
  if (!uploadData.mimetype) {
120
120
  uploadData.mimetype = MIMETYPE_MAP[mediaType];
121
121
  }
122
-
123
122
  if (cacheableKey) {
124
- const mediaBuff = options.mediaCache.get(cacheableKey);
123
+ const mediaBuff = await options.mediaCache.get(cacheableKey);
125
124
  if (mediaBuff) {
126
- logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'got media cache hit');
127
- const obj = Types_1.WAProto.Message.decode(mediaBuff);
125
+ logger?.debug({ cacheableKey }, 'got media cache hit');
126
+ const obj = proto.Message.decode(mediaBuff);
128
127
  const key = `${mediaType}Message`;
129
128
  Object.assign(obj[key], { ...uploadData, media: undefined });
130
129
  return obj;
131
130
  }
132
131
  }
133
-
132
+ const isNewsletter = !!options.jid && isJidNewsletter(options.jid);
133
+ if (isNewsletter) {
134
+ logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
135
+ const { filePath, fileSha256, fileLength } = await getRawMediaUploadData(uploadData.media, options.mediaTypeOverride || mediaType, logger);
136
+ const fileSha256B64 = fileSha256.toString('base64');
137
+ const { mediaUrl, directPath } = await options.upload(filePath, {
138
+ fileEncSha256B64: fileSha256B64,
139
+ mediaType: mediaType,
140
+ timeoutMs: options.mediaUploadTimeoutMs
141
+ });
142
+ await fs.unlink(filePath);
143
+ const obj = WAProto.Message.fromObject({
144
+ // todo: add more support here
145
+ [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
146
+ url: mediaUrl,
147
+ directPath,
148
+ fileSha256,
149
+ fileLength,
150
+ ...uploadData,
151
+ media: undefined
152
+ })
153
+ });
154
+ if (uploadData.ptv) {
155
+ obj.ptvMessage = obj.videoMessage;
156
+ delete obj.videoMessage;
157
+ }
158
+ if (obj.stickerMessage) {
159
+ obj.stickerMessage.stickerSentTs = Date.now();
160
+ }
161
+ if (cacheableKey) {
162
+ logger?.debug({ cacheableKey }, 'set cache');
163
+ await options.mediaCache.set(cacheableKey, WAProto.Message.encode(obj).finish());
164
+ }
165
+ return obj;
166
+ }
134
167
  const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
135
- const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') &&
136
- (typeof uploadData['jpegThumbnail'] === 'undefined');
168
+ const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && typeof uploadData['jpegThumbnail'] === 'undefined';
137
169
  const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
138
170
  const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
139
171
  const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
140
-
141
- const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, opusConverted } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
172
+ const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength } = await encryptedStream(uploadData.media, options.mediaTypeOverride || mediaType, {
142
173
  logger,
143
174
  saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
144
- opts: options.options,
145
- isPtt: uploadData.ptt,
146
- forceOpus: (mediaType === "audio" && uploadData.mimetype && uploadData.mimetype.includes('opus'))
175
+ opts: options.options
147
176
  });
148
-
149
- if (mediaType === 'audio' && opusConverted) {
150
- uploadData.mimetype = 'audio/ogg; codecs=opus';
151
- }
152
-
153
- const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 !== null && fileEncSha256 !== void 0 ? fileEncSha256 : fileSha256).toString('base64');
154
-
155
- const [{ mediaUrl, directPath, handle }] = await Promise.all([
177
+ const fileEncSha256B64 = fileEncSha256.toString('base64');
178
+ const [{ mediaUrl, directPath }] = await Promise.all([
156
179
  (async () => {
157
- const result = await options.upload(encWriteStream, { fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs });
158
- logger === null || logger === void 0 ? void 0 : logger.debug({ mediaType, cacheableKey }, 'uploaded media');
180
+ const result = await options.upload(encFilePath, {
181
+ fileEncSha256B64,
182
+ mediaType,
183
+ timeoutMs: options.mediaUploadTimeoutMs
184
+ });
185
+ logger?.debug({ mediaType, cacheableKey }, 'uploaded media');
159
186
  return result;
160
187
  })(),
161
188
  (async () => {
162
189
  try {
163
190
  if (requiresThumbnailComputation) {
164
- const { thumbnail, originalImageDimensions } = await (0, messages_media_1.generateThumbnail)(bodyPath, mediaType, options);
191
+ const { thumbnail, originalImageDimensions } = await generateThumbnail(originalFilePath, mediaType, options);
165
192
  uploadData.jpegThumbnail = thumbnail;
166
193
  if (!uploadData.width && originalImageDimensions) {
167
194
  uploadData.width = originalImageDimensions.width;
168
195
  uploadData.height = originalImageDimensions.height;
169
- logger === null || logger === void 0 ? void 0 : logger.debug('set dimensions');
196
+ logger?.debug('set dimensions');
170
197
  }
171
- logger === null || logger === void 0 ? void 0 : logger.debug('generated thumbnail');
198
+ logger?.debug('generated thumbnail');
172
199
  }
173
200
  if (requiresDurationComputation) {
174
- uploadData.seconds = await (0, messages_media_1.getAudioDuration)(bodyPath);
175
- logger === null || logger === void 0 ? void 0 : logger.debug('computed audio duration');
201
+ uploadData.seconds = await getAudioDuration(originalFilePath);
202
+ logger?.debug('computed audio duration');
176
203
  }
177
204
  if (requiresWaveformProcessing) {
178
- uploadData.waveform = await (0, messages_media_1.getAudioWaveform)(bodyPath, logger);
179
- logger === null || logger === void 0 ? void 0 : logger.debug('processed waveform');
205
+ uploadData.waveform = await getAudioWaveform(originalFilePath, logger);
206
+ logger?.debug('processed waveform');
180
207
  }
181
208
  if (requiresAudioBackground) {
182
209
  uploadData.backgroundArgb = await assertColor(options.backgroundColor);
183
- logger === null || logger === void 0 ? void 0 : logger.debug('computed backgroundColor audio status');
210
+ logger?.debug('computed backgroundColor audio status');
184
211
  }
185
212
  }
186
213
  catch (error) {
187
- logger === null || logger === void 0 ? void 0 : logger.warn({ trace: error.stack }, 'failed to obtain extra info');
214
+ logger?.warn({ trace: error.stack }, 'failed to obtain extra info');
188
215
  }
189
- })(),
190
- ])
191
- .finally(async () => {
192
- if (!Buffer.isBuffer(encWriteStream)) {
193
- encWriteStream.destroy();
216
+ })()
217
+ ]).finally(async () => {
218
+ try {
219
+ await fs.unlink(encFilePath);
220
+ if (originalFilePath) {
221
+ await fs.unlink(originalFilePath);
222
+ }
223
+ logger?.debug('removed tmp files');
194
224
  }
195
-
196
- if (didSaveToTmpPath && bodyPath) {
197
- await fs_1.promises.unlink(bodyPath);
198
- logger === null || logger === void 0 ? void 0 : logger.debug('removed tmp files');
225
+ catch (error) {
226
+ logger?.warn('failed to remove tmp file');
199
227
  }
200
228
  });
201
-
202
- const obj = Types_1.WAProto.Message.fromObject({
229
+ const obj = WAProto.Message.fromObject({
203
230
  [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
204
- url: handle ? undefined : mediaUrl,
231
+ url: mediaUrl,
205
232
  directPath,
206
- mediaKey: mediaKey,
207
- fileEncSha256: fileEncSha256,
233
+ mediaKey,
234
+ fileEncSha256,
208
235
  fileSha256,
209
236
  fileLength,
210
- mediaKeyTimestamp: handle ? undefined : (0, generics_1.unixTimestampSeconds)(),
237
+ mediaKeyTimestamp: unixTimestampSeconds(),
211
238
  ...uploadData,
212
239
  media: undefined
213
240
  })
214
241
  });
215
-
216
242
  if (uploadData.ptv) {
217
243
  obj.ptvMessage = obj.videoMessage;
218
244
  delete obj.videoMessage;
219
245
  }
220
-
221
246
  if (cacheableKey) {
222
- logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'set cache');
223
- options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish());
247
+ logger?.debug({ cacheableKey }, 'set cache');
248
+ await options.mediaCache.set(cacheableKey, WAProto.Message.encode(obj).finish());
224
249
  }
225
-
226
250
  return obj;
227
251
  };
228
- exports.prepareWAMessageMedia = prepareWAMessageMedia;
229
- const prepareDisappearingMessageSettingContent = (ephemeralExpiration) => {
252
+ export const prepareDisappearingMessageSettingContent = (ephemeralExpiration) => {
230
253
  ephemeralExpiration = ephemeralExpiration || 0;
231
254
  const content = {
232
255
  ephemeralMessage: {
233
256
  message: {
234
257
  protocolMessage: {
235
- type: Types_1.WAProto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
258
+ type: WAProto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
236
259
  ephemeralExpiration
237
260
  }
238
261
  }
239
262
  }
240
263
  };
241
- return Types_1.WAProto.Message.fromObject(content);
264
+ return WAProto.Message.fromObject(content);
242
265
  };
243
- exports.prepareDisappearingMessageSettingContent = prepareDisappearingMessageSettingContent;
244
266
  /**
245
267
  * Generate forwarded message content like WA does
246
268
  * @param message the message to forward
247
269
  * @param options.forceForward will show the message as forwarded even if it is from you
248
270
  */
249
- const generateForwardMessageContent = (message, forceForward) => {
250
- var _a;
271
+ export const generateForwardMessageContent = (message, forceForward) => {
251
272
  let content = message.message;
252
273
  if (!content) {
253
- throw new boom_1.Boom('no content in message', { statusCode: 400 });
274
+ throw new Boom('no content in message', { statusCode: 400 });
254
275
  }
255
276
  // hacky copy
256
- content = (0, exports.normalizeMessageContent)(content);
257
- content = WAProto_1.proto.Message.decode(WAProto_1.proto.Message.encode(content).finish());
277
+ content = normalizeMessageContent(content);
278
+ content = proto.Message.decode(proto.Message.encode(content).finish());
258
279
  let key = Object.keys(content)[0];
259
- let score = ((_a = content[key].contextInfo) === null || _a === void 0 ? void 0 : _a.forwardingScore) || 0;
280
+ let score = content?.[key]?.contextInfo?.forwardingScore || 0;
260
281
  score += message.key.fromMe && !forceForward ? 0 : 1;
261
282
  if (key === 'conversation') {
262
283
  content.extendedTextMessage = { text: content[key] };
263
284
  delete content.conversation;
264
285
  key = 'extendedTextMessage';
265
286
  }
287
+ const key_ = content?.[key];
266
288
  if (score > 0) {
267
- content[key].contextInfo = { forwardingScore: score, isForwarded: true };
289
+ key_.contextInfo = { forwardingScore: score, isForwarded: true };
268
290
  }
269
291
  else {
270
- content[key].contextInfo = {};
292
+ key_.contextInfo = {};
271
293
  }
272
294
  return content;
273
295
  };
274
- exports.generateForwardMessageContent = generateForwardMessageContent;
275
- const generateWAMessageContent = async (message, options) => {
276
- var _a;
277
- var _b;
296
+ export const generateWAMessageContent = async (message, options) => {
297
+ var _a, _b;
278
298
  let m = {};
279
299
  if ('text' in message) {
280
300
  const extContent = { text: message.text };
281
301
  let urlInfo = message.linkPreview;
282
302
  if (typeof urlInfo === 'undefined') {
283
- urlInfo = await (0, exports.generateLinkPreviewIfRequired)(message.text, options.getUrlInfo, options.logger);
303
+ urlInfo = await generateLinkPreviewIfRequired(message.text, options.getUrlInfo, options.logger);
284
304
  }
285
305
  if (urlInfo) {
286
- extContent.canonicalUrl = urlInfo['canonical-url'];
287
306
  extContent.matchedText = urlInfo['matched-text'];
288
307
  extContent.jpegThumbnail = urlInfo.jpegThumbnail;
289
308
  extContent.description = urlInfo.description;
@@ -311,38 +330,68 @@ const generateWAMessageContent = async (message, options) => {
311
330
  else if ('contacts' in message) {
312
331
  const contactLen = message.contacts.contacts.length;
313
332
  if (!contactLen) {
314
- throw new boom_1.Boom('require atleast 1 contact', { statusCode: 400 });
333
+ throw new Boom('require atleast 1 contact', { statusCode: 400 });
315
334
  }
316
335
  if (contactLen === 1) {
317
- m.contactMessage = Types_1.WAProto.Message.ContactMessage.fromObject(message.contacts.contacts[0]);
336
+ m.contactMessage = WAProto.Message.ContactMessage.create(message.contacts.contacts[0]);
318
337
  }
319
338
  else {
320
- m.contactsArrayMessage = Types_1.WAProto.Message.ContactsArrayMessage.fromObject(message.contacts);
339
+ m.contactsArrayMessage = WAProto.Message.ContactsArrayMessage.create(message.contacts);
321
340
  }
322
341
  }
323
342
  else if ('location' in message) {
324
- m.locationMessage = Types_1.WAProto.Message.LocationMessage.fromObject(message.location);
343
+ m.locationMessage = WAProto.Message.LocationMessage.create(message.location);
325
344
  }
326
345
  else if ('react' in message) {
327
346
  if (!message.react.senderTimestampMs) {
328
347
  message.react.senderTimestampMs = Date.now();
329
348
  }
330
- m.reactionMessage = Types_1.WAProto.Message.ReactionMessage.fromObject(message.react);
349
+ m.reactionMessage = WAProto.Message.ReactionMessage.create(message.react);
331
350
  }
332
351
  else if ('delete' in message) {
333
352
  m.protocolMessage = {
334
353
  key: message.delete,
335
- type: Types_1.WAProto.Message.ProtocolMessage.Type.REVOKE
354
+ type: WAProto.Message.ProtocolMessage.Type.REVOKE
336
355
  };
337
356
  }
338
357
  else if ('forward' in message) {
339
- m = (0, exports.generateForwardMessageContent)(message.forward, message.force);
358
+ m = generateForwardMessageContent(message.forward, message.force);
340
359
  }
341
360
  else if ('disappearingMessagesInChat' in message) {
342
- const exp = typeof message.disappearingMessagesInChat === 'boolean' ?
343
- (message.disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
344
- message.disappearingMessagesInChat;
345
- m = (0, exports.prepareDisappearingMessageSettingContent)(exp);
361
+ const exp = typeof message.disappearingMessagesInChat === 'boolean'
362
+ ? message.disappearingMessagesInChat
363
+ ? WA_DEFAULT_EPHEMERAL
364
+ : 0
365
+ : message.disappearingMessagesInChat;
366
+ m = prepareDisappearingMessageSettingContent(exp);
367
+ }
368
+ else if ('groupInvite' in message) {
369
+ m.groupInviteMessage = {};
370
+ m.groupInviteMessage.inviteCode = message.groupInvite.inviteCode;
371
+ m.groupInviteMessage.inviteExpiration = message.groupInvite.inviteExpiration;
372
+ m.groupInviteMessage.caption = message.groupInvite.text;
373
+ m.groupInviteMessage.groupJid = message.groupInvite.jid;
374
+ m.groupInviteMessage.groupName = message.groupInvite.subject;
375
+ //TODO: use built-in interface and get disappearing mode info etc.
376
+ //TODO: cache / use store!?
377
+ if (options.getProfilePicUrl) {
378
+ const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
379
+ if (pfpUrl) {
380
+ const resp = await fetch(pfpUrl, { method: 'GET', dispatcher: options?.options?.dispatcher });
381
+ if (resp.ok) {
382
+ const buf = Buffer.from(await resp.arrayBuffer());
383
+ m.groupInviteMessage.jpegThumbnail = buf;
384
+ }
385
+ }
386
+ }
387
+ }
388
+ else if ('pin' in message) {
389
+ m.pinInChatMessage = {};
390
+ m.messageContextInfo = {};
391
+ m.pinInChatMessage.key = message.pin;
392
+ m.pinInChatMessage.type = message.type;
393
+ m.pinInChatMessage.senderTimestampMs = Date.now();
394
+ m.messageContextInfo.messageAddOnDurationInSecs = message.type === 1 ? message.time || 86400 : 0;
346
395
  }
347
396
  else if ('buttonReply' in message) {
348
397
  switch (message.type) {
@@ -350,64 +399,115 @@ const generateWAMessageContent = async (message, options) => {
350
399
  m.templateButtonReplyMessage = {
351
400
  selectedDisplayText: message.buttonReply.displayText,
352
401
  selectedId: message.buttonReply.id,
353
- selectedIndex: message.buttonReply.index,
402
+ selectedIndex: message.buttonReply.index
354
403
  };
355
404
  break;
356
405
  case 'plain':
357
406
  m.buttonsResponseMessage = {
358
407
  selectedButtonId: message.buttonReply.id,
359
408
  selectedDisplayText: message.buttonReply.displayText,
360
- type: WAProto_1.proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT,
409
+ type: proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
361
410
  };
362
411
  break;
363
412
  }
364
413
  }
414
+ else if ('ptv' in message && message.ptv) {
415
+ const { videoMessage } = await prepareWAMessageMedia({ video: message.video }, options);
416
+ m.ptvMessage = videoMessage;
417
+ }
365
418
  else if ('product' in message) {
366
- const { imageMessage } = await (0, exports.prepareWAMessageMedia)({ image: message.product.productImage }, options);
367
- m.productMessage = Types_1.WAProto.Message.ProductMessage.fromObject({
419
+ const { imageMessage } = await prepareWAMessageMedia({ image: message.product.productImage }, options);
420
+ m.productMessage = WAProto.Message.ProductMessage.create({
368
421
  ...message,
369
422
  product: {
370
423
  ...message.product,
371
- productImage: imageMessage,
424
+ productImage: imageMessage
372
425
  }
373
426
  });
374
427
  }
375
428
  else if ('listReply' in message) {
376
429
  m.listResponseMessage = { ...message.listReply };
377
430
  }
431
+ else if ('event' in message) {
432
+ m.eventMessage = {};
433
+ const startTime = Math.floor(message.event.startDate.getTime() / 1000);
434
+ if (message.event.call && options.getCallLink) {
435
+ const token = await options.getCallLink(message.event.call, { startTime });
436
+ m.eventMessage.joinLink = (message.event.call === 'audio' ? CALL_AUDIO_PREFIX : CALL_VIDEO_PREFIX) + token;
437
+ }
438
+ m.messageContextInfo = {
439
+ // encKey
440
+ messageSecret: message.event.messageSecret || randomBytes(32)
441
+ };
442
+ m.eventMessage.name = message.event.name;
443
+ m.eventMessage.description = message.event.description;
444
+ m.eventMessage.startTime = startTime;
445
+ m.eventMessage.endTime = message.event.endDate ? message.event.endDate.getTime() / 1000 : undefined;
446
+ m.eventMessage.isCanceled = message.event.isCancelled ?? false;
447
+ m.eventMessage.extraGuestsAllowed = message.event.extraGuestsAllowed;
448
+ m.eventMessage.isScheduleCall = message.event.isScheduleCall ?? false;
449
+ m.eventMessage.location = message.event.location;
450
+ }
378
451
  else if ('poll' in message) {
379
- (_b = message.poll).selectableCount || (_b.selectableCount = 0);
452
+ (_a = message.poll).selectableCount || (_a.selectableCount = 0);
453
+ (_b = message.poll).toAnnouncementGroup || (_b.toAnnouncementGroup = false);
380
454
  if (!Array.isArray(message.poll.values)) {
381
- throw new boom_1.Boom('Invalid poll values', { statusCode: 400 });
455
+ throw new Boom('Invalid poll values', { statusCode: 400 });
382
456
  }
383
- if (message.poll.selectableCount < 0
384
- || message.poll.selectableCount > message.poll.values.length) {
385
- throw new boom_1.Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, { statusCode: 400 });
457
+ if (message.poll.selectableCount < 0 || message.poll.selectableCount > message.poll.values.length) {
458
+ throw new Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, {
459
+ statusCode: 400
460
+ });
386
461
  }
387
462
  m.messageContextInfo = {
388
463
  // encKey
389
- messageSecret: message.poll.messageSecret || (0, crypto_1.randomBytes)(32),
464
+ messageSecret: message.poll.messageSecret || randomBytes(32)
390
465
  };
391
- m.pollCreationMessage = {
466
+ const pollCreationMessage = {
392
467
  name: message.poll.name,
393
468
  selectableOptionsCount: message.poll.selectableCount,
394
- options: message.poll.values.map(optionName => ({ optionName })),
469
+ options: message.poll.values.map(optionName => ({ optionName }))
395
470
  };
471
+ if (message.poll.toAnnouncementGroup) {
472
+ // poll v2 is for community announcement groups (single select and multiple)
473
+ m.pollCreationMessageV2 = pollCreationMessage;
474
+ }
475
+ else {
476
+ if (message.poll.selectableCount === 1) {
477
+ //poll v3 is for single select polls
478
+ m.pollCreationMessageV3 = pollCreationMessage;
479
+ }
480
+ else {
481
+ // poll for multiple choice polls
482
+ m.pollCreationMessage = pollCreationMessage;
483
+ }
484
+ }
396
485
  }
397
486
  else if ('sharePhoneNumber' in message) {
398
487
  m.protocolMessage = {
399
- type: WAProto_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
488
+ type: proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
400
489
  };
401
490
  }
402
491
  else if ('requestPhoneNumber' in message) {
403
492
  m.requestPhoneNumberMessage = {};
404
493
  }
494
+ else if ('limitSharing' in message) {
495
+ m.protocolMessage = {
496
+ type: proto.Message.ProtocolMessage.Type.LIMIT_SHARING,
497
+ limitSharing: {
498
+ sharingLimited: message.limitSharing === true,
499
+ trigger: 1,
500
+ limitSharingSettingTimestamp: Date.now(),
501
+ initiatedByMe: true
502
+ }
503
+ };
504
+ }
405
505
  else {
406
- m = await (0, exports.prepareWAMessageMedia)(message, options);
506
+ m = await prepareWAMessageMedia(message, options);
407
507
  }
408
508
  if ('buttons' in message && !!message.buttons) {
409
509
  const buttonsMessage = {
410
- buttons: message.buttons.map(b => ({ ...b, type: WAProto_1.proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
510
+ buttons: message.buttons.map(b => ({ ...b, type: proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
411
511
  };
412
512
  if ('text' in message) {
413
513
  buttonsMessage.contentText = message.text;
@@ -456,17 +556,24 @@ const generateWAMessageContent = async (message, options) => {
456
556
  title: message.title,
457
557
  footerText: message.footer,
458
558
  description: message.text,
459
- listType: WAProto_1.proto.Message.ListMessage.ListType.SINGLE_SELECT
559
+ listType: proto.Message.ListMessage.ListType.SINGLE_SELECT
460
560
  };
461
561
  m = { listMessage };
462
562
  }
463
563
  if ('viewOnce' in message && !!message.viewOnce) {
464
564
  m = { viewOnceMessage: { message: m } };
465
565
  }
466
- if ('mentions' in message && ((_a = message.mentions) === null || _a === void 0 ? void 0 : _a.length)) {
467
- const [messageType] = Object.keys(m);
468
- m[messageType].contextInfo = m[messageType] || {};
469
- m[messageType].contextInfo.mentionedJid = message.mentions;
566
+ if ('mentions' in message && message.mentions?.length) {
567
+ const messageType = Object.keys(m)[0];
568
+ const key = m[messageType];
569
+ if ('contextInfo' in key && !!key.contextInfo) {
570
+ key.contextInfo.mentionedJid = message.mentions;
571
+ }
572
+ else if (key) {
573
+ key.contextInfo = {
574
+ mentionedJid: message.mentions
575
+ };
576
+ }
470
577
  }
471
578
  if ('edit' in message) {
472
579
  m = {
@@ -474,40 +581,46 @@ const generateWAMessageContent = async (message, options) => {
474
581
  key: message.edit,
475
582
  editedMessage: m,
476
583
  timestampMs: Date.now(),
477
- type: Types_1.WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT
584
+ type: WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT
478
585
  }
479
586
  };
480
587
  }
481
588
  if ('contextInfo' in message && !!message.contextInfo) {
482
- const [messageType] = Object.keys(m);
483
- m[messageType] = m[messageType] || {};
484
- m[messageType].contextInfo = message.contextInfo;
589
+ const messageType = Object.keys(m)[0];
590
+ const key = m[messageType];
591
+ if ('contextInfo' in key && !!key.contextInfo) {
592
+ key.contextInfo = { ...key.contextInfo, ...message.contextInfo };
593
+ }
594
+ else if (key) {
595
+ key.contextInfo = message.contextInfo;
596
+ }
485
597
  }
486
- return Types_1.WAProto.Message.fromObject(m);
598
+ return WAProto.Message.create(m);
487
599
  };
488
- exports.generateWAMessageContent = generateWAMessageContent;
489
- const generateWAMessageFromContent = (jid, message, options) => {
600
+ export const generateWAMessageFromContent = (jid, message, options) => {
490
601
  // set timestamp to now
491
602
  // if not specified
492
603
  if (!options.timestamp) {
493
604
  options.timestamp = new Date();
494
605
  }
495
- const innerMessage = (0, exports.normalizeMessageContent)(message);
496
- const key = (0, exports.getContentType)(innerMessage);
497
- const timestamp = (0, generics_1.unixTimestampSeconds)(options.timestamp);
606
+ const innerMessage = normalizeMessageContent(message);
607
+ const key = getContentType(innerMessage);
608
+ const timestamp = unixTimestampSeconds(options.timestamp);
498
609
  const { quoted, userJid } = options;
499
- if (quoted && !(0, WABinary_1.isJidNewsLetter)(jid)) {
500
- const participant = quoted.key.fromMe ? userJid : (quoted.participant || quoted.key.participant || quoted.key.remoteJid);
501
- let quotedMsg = (0, exports.normalizeMessageContent)(quoted.message);
502
- const msgType = (0, exports.getContentType)(quotedMsg);
610
+ if (quoted && !isJidNewsletter(jid)) {
611
+ const participant = quoted.key.fromMe
612
+ ? userJid // TODO: Add support for LIDs
613
+ : quoted.participant || quoted.key.participant || quoted.key.remoteJid;
614
+ let quotedMsg = normalizeMessageContent(quoted.message);
615
+ const msgType = getContentType(quotedMsg);
503
616
  // strip any redundant properties
504
- quotedMsg = WAProto_1.proto.Message.fromObject({ [msgType]: quotedMsg[msgType] });
617
+ quotedMsg = proto.Message.create({ [msgType]: quotedMsg[msgType] });
505
618
  const quotedContent = quotedMsg[msgType];
506
619
  if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
507
620
  delete quotedContent.contextInfo;
508
621
  }
509
- const contextInfo = innerMessage[key].contextInfo || {};
510
- contextInfo.participant = (0, WABinary_1.jidNormalizedUser)(participant);
622
+ const contextInfo = ('contextInfo' in innerMessage[key] && innerMessage[key]?.contextInfo) || {};
623
+ contextInfo.participant = jidNormalizedUser(participant);
511
624
  contextInfo.stanzaId = quoted.key.id;
512
625
  contextInfo.quotedMessage = quotedMsg;
513
626
  // if a participant is quoted, then it must be a group
@@ -515,62 +628,63 @@ const generateWAMessageFromContent = (jid, message, options) => {
515
628
  if (jid !== quoted.key.remoteJid) {
516
629
  contextInfo.remoteJid = quoted.key.remoteJid;
517
630
  }
518
- innerMessage[key].contextInfo = contextInfo;
631
+ if (contextInfo && innerMessage[key]) {
632
+ /* @ts-ignore */
633
+ innerMessage[key].contextInfo = contextInfo;
634
+ }
519
635
  }
520
636
  if (
521
637
  // if we want to send a disappearing message
522
- !!(options === null || options === void 0 ? void 0 : options.ephemeralExpiration) &&
638
+ !!options?.ephemeralExpiration &&
523
639
  // and it's not a protocol message -- delete, toggle disappear message
524
640
  key !== 'protocolMessage' &&
525
641
  // already not converted to disappearing message
526
642
  key !== 'ephemeralMessage' &&
527
- // newsletter not accept disappearing messages
528
- !(0, WABinary_1.isJidNewsLetter)(jid)) {
643
+ // newsletters don't support ephemeral messages
644
+ !isJidNewsletter(jid)) {
645
+ /* @ts-ignore */
529
646
  innerMessage[key].contextInfo = {
530
647
  ...(innerMessage[key].contextInfo || {}),
531
- expiration: options.ephemeralExpiration || Defaults_1.WA_DEFAULT_EPHEMERAL,
648
+ expiration: options.ephemeralExpiration || WA_DEFAULT_EPHEMERAL
532
649
  //ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
533
650
  };
534
651
  }
535
- message = Types_1.WAProto.Message.fromObject(message);
652
+ message = WAProto.Message.create(message);
536
653
  const messageJSON = {
537
654
  key: {
538
655
  remoteJid: jid,
539
656
  fromMe: true,
540
- id: (options === null || options === void 0 ? void 0 : options.messageId) || (0, generics_1.generateMessageID)(),
657
+ id: options?.messageId || generateMessageIDV2()
541
658
  },
542
659
  message: message,
543
660
  messageTimestamp: timestamp,
544
661
  messageStubParameters: [],
545
- participant: (0, WABinary_1.isJidGroup)(jid) || (0, WABinary_1.isJidStatusBroadcast)(jid) ? userJid : undefined,
546
- status: Types_1.WAMessageStatus.PENDING
662
+ participant: isJidGroup(jid) || isJidStatusBroadcast(jid) ? userJid : undefined, // TODO: Add support for LIDs
663
+ status: WAMessageStatus.PENDING
547
664
  };
548
- return Types_1.WAProto.WebMessageInfo.fromObject(messageJSON);
665
+ return WAProto.WebMessageInfo.fromObject(messageJSON);
549
666
  };
550
- exports.generateWAMessageFromContent = generateWAMessageFromContent;
551
- const generateWAMessage = async (jid, content, options) => {
552
- var _a;
667
+ export const generateWAMessage = async (jid, content, options) => {
553
668
  // ensure msg ID is with every log
554
- options.logger = (_a = options === null || options === void 0 ? void 0 : options.logger) === null || _a === void 0 ? void 0 : _a.child({ msgId: options.messageId });
555
- return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, { newsletter: (0, WABinary_1.isJidNewsLetter)(jid), ...options }), options);
669
+ options.logger = options?.logger?.child({ msgId: options.messageId });
670
+ // Pass jid in the options to generateWAMessageContent
671
+ return generateWAMessageFromContent(jid, await generateWAMessageContent(content, { ...options, jid }), options);
556
672
  };
557
- exports.generateWAMessage = generateWAMessage;
558
673
  /** Get the key to access the true type of content */
559
- const getContentType = (content) => {
674
+ export const getContentType = (content) => {
560
675
  if (content) {
561
676
  const keys = Object.keys(content);
562
677
  const key = keys.find(k => (k === 'conversation' || k.includes('Message')) && k !== 'senderKeyDistributionMessage');
563
678
  return key;
564
679
  }
565
680
  };
566
- exports.getContentType = getContentType;
567
681
  /**
568
682
  * Normalizes ephemeral, view once messages to regular message content
569
683
  * Eg. image messages in ephemeral messages, in view once messages etc.
570
684
  * @param content
571
685
  * @returns
572
686
  */
573
- const normalizeMessageContent = (content) => {
687
+ export const normalizeMessageContent = (content) => {
574
688
  if (!content) {
575
689
  return undefined;
576
690
  }
@@ -584,21 +698,19 @@ const normalizeMessageContent = (content) => {
584
698
  }
585
699
  return content;
586
700
  function getFutureProofMessage(message) {
587
- return ((message === null || message === void 0 ? void 0 : message.ephemeralMessage)
588
- || (message === null || message === void 0 ? void 0 : message.viewOnceMessage)
589
- || (message === null || message === void 0 ? void 0 : message.documentWithCaptionMessage)
590
- || (message === null || message === void 0 ? void 0 : message.viewOnceMessageV2)
591
- || (message === null || message === void 0 ? void 0 : message.viewOnceMessageV2Extension)
592
- || (message === null || message === void 0 ? void 0 : message.editedMessage));
701
+ return (message?.ephemeralMessage ||
702
+ message?.viewOnceMessage ||
703
+ message?.documentWithCaptionMessage ||
704
+ message?.viewOnceMessageV2 ||
705
+ message?.viewOnceMessageV2Extension ||
706
+ message?.editedMessage);
593
707
  }
594
708
  };
595
- exports.normalizeMessageContent = normalizeMessageContent;
596
709
  /**
597
710
  * Extract the true message content from a message
598
711
  * Eg. extracts the inner message from a disappearing message/view once message
599
712
  */
600
- const extractMessageContent = (content) => {
601
- var _a, _b, _c, _d, _e, _f;
713
+ export const extractMessageContent = (content) => {
602
714
  const extractFromTemplateMessage = (msg) => {
603
715
  if (msg.imageMessage) {
604
716
  return { imageMessage: msg.imageMessage };
@@ -614,35 +726,39 @@ const extractMessageContent = (content) => {
614
726
  }
615
727
  else {
616
728
  return {
617
- conversation: 'contentText' in msg
618
- ? msg.contentText
619
- : ('hydratedContentText' in msg ? msg.hydratedContentText : '')
729
+ conversation: 'contentText' in msg ? msg.contentText : 'hydratedContentText' in msg ? msg.hydratedContentText : ''
620
730
  };
621
731
  }
622
732
  };
623
- content = (0, exports.normalizeMessageContent)(content);
624
- if (content === null || content === void 0 ? void 0 : content.buttonsMessage) {
733
+ content = normalizeMessageContent(content);
734
+ if (content?.buttonsMessage) {
625
735
  return extractFromTemplateMessage(content.buttonsMessage);
626
736
  }
627
- if ((_a = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _a === void 0 ? void 0 : _a.hydratedFourRowTemplate) {
628
- return extractFromTemplateMessage((_b = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _b === void 0 ? void 0 : _b.hydratedFourRowTemplate);
737
+ if (content?.templateMessage?.hydratedFourRowTemplate) {
738
+ return extractFromTemplateMessage(content?.templateMessage?.hydratedFourRowTemplate);
629
739
  }
630
- if ((_c = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _c === void 0 ? void 0 : _c.hydratedTemplate) {
631
- return extractFromTemplateMessage((_d = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _d === void 0 ? void 0 : _d.hydratedTemplate);
740
+ if (content?.templateMessage?.hydratedTemplate) {
741
+ return extractFromTemplateMessage(content?.templateMessage?.hydratedTemplate);
632
742
  }
633
- if ((_e = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _e === void 0 ? void 0 : _e.fourRowTemplate) {
634
- return extractFromTemplateMessage((_f = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _f === void 0 ? void 0 : _f.fourRowTemplate);
743
+ if (content?.templateMessage?.fourRowTemplate) {
744
+ return extractFromTemplateMessage(content?.templateMessage?.fourRowTemplate);
635
745
  }
636
746
  return content;
637
747
  };
638
- exports.extractMessageContent = extractMessageContent;
639
748
  /**
640
749
  * Returns the device predicted by message ID
641
750
  */
642
- const getDevice = (id) => /^3A.{18}$/.test(id) ? 'ios' : /^3E.{20}$/.test(id) ? 'web' : /^(.{21}|.{32})$/.test(id) ? 'android' : /^.{18}$/.test(id) ? 'desktop' : 'unknown';
643
- exports.getDevice = getDevice;
751
+ export const getDevice = (id) => /^3A.{18}$/.test(id)
752
+ ? 'ios'
753
+ : /^3E.{20}$/.test(id)
754
+ ? 'web'
755
+ : /^(.{21}|.{32})$/.test(id)
756
+ ? 'android'
757
+ : /^(3F|.{18}$)/.test(id)
758
+ ? 'desktop'
759
+ : 'unknown';
644
760
  /** Upserts a receipt in the message */
645
- const updateMessageWithReceipt = (msg, receipt) => {
761
+ export const updateMessageWithReceipt = (msg, receipt) => {
646
762
  msg.userReceipt = msg.userReceipt || [];
647
763
  const recp = msg.userReceipt.find(m => m.userJid === receipt.userJid);
648
764
  if (recp) {
@@ -652,41 +768,36 @@ const updateMessageWithReceipt = (msg, receipt) => {
652
768
  msg.userReceipt.push(receipt);
653
769
  }
654
770
  };
655
- exports.updateMessageWithReceipt = updateMessageWithReceipt;
656
771
  /** Update the message with a new reaction */
657
- const updateMessageWithReaction = (msg, reaction) => {
658
- const authorID = (0, generics_1.getKeyAuthor)(reaction.key);
659
- const reactions = (msg.reactions || [])
660
- .filter(r => (0, generics_1.getKeyAuthor)(r.key) !== authorID);
661
- if (reaction.text) {
662
- reactions.push(reaction);
663
- }
772
+ export const updateMessageWithReaction = (msg, reaction) => {
773
+ const authorID = getKeyAuthor(reaction.key);
774
+ const reactions = (msg.reactions || []).filter(r => getKeyAuthor(r.key) !== authorID);
775
+ reaction.text = reaction.text || '';
776
+ reactions.push(reaction);
664
777
  msg.reactions = reactions;
665
778
  };
666
- exports.updateMessageWithReaction = updateMessageWithReaction;
667
779
  /** Update the message with a new poll update */
668
- const updateMessageWithPollUpdate = (msg, update) => {
669
- var _a, _b;
670
- const authorID = (0, generics_1.getKeyAuthor)(update.pollUpdateMessageKey);
671
- const reactions = (msg.pollUpdates || [])
672
- .filter(r => (0, generics_1.getKeyAuthor)(r.pollUpdateMessageKey) !== authorID);
673
- if ((_b = (_a = update.vote) === null || _a === void 0 ? void 0 : _a.selectedOptions) === null || _b === void 0 ? void 0 : _b.length) {
780
+ export const updateMessageWithPollUpdate = (msg, update) => {
781
+ const authorID = getKeyAuthor(update.pollUpdateMessageKey);
782
+ const reactions = (msg.pollUpdates || []).filter(r => getKeyAuthor(r.pollUpdateMessageKey) !== authorID);
783
+ if (update.vote?.selectedOptions?.length) {
674
784
  reactions.push(update);
675
785
  }
676
786
  msg.pollUpdates = reactions;
677
787
  };
678
- exports.updateMessageWithPollUpdate = updateMessageWithPollUpdate;
679
788
  /**
680
789
  * Aggregates all poll updates in a poll.
681
790
  * @param msg the poll creation message
682
791
  * @param meId your jid
683
792
  * @returns A list of options & their voters
684
793
  */
685
- function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
686
- var _a, _b, _c;
687
- const opts = ((_a = message === null || message === void 0 ? void 0 : message.pollCreationMessage) === null || _a === void 0 ? void 0 : _a.options) || ((_b = message === null || message === void 0 ? void 0 : message.pollCreationMessageV2) === null || _b === void 0 ? void 0 : _b.options) || ((_c = message === null || message === void 0 ? void 0 : message.pollCreationMessageV3) === null || _c === void 0 ? void 0 : _c.options) || [];
794
+ export function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
795
+ const opts = message?.pollCreationMessage?.options ||
796
+ message?.pollCreationMessageV2?.options ||
797
+ message?.pollCreationMessageV3?.options ||
798
+ [];
688
799
  const voteHashMap = opts.reduce((acc, opt) => {
689
- const hash = (0, crypto_2.sha256)(Buffer.from(opt.optionName || '')).toString();
800
+ const hash = sha256(Buffer.from(opt.optionName || '')).toString();
690
801
  acc[hash] = {
691
802
  name: opt.optionName || '',
692
803
  voters: []
@@ -708,14 +819,13 @@ function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
708
819
  };
709
820
  data = voteHashMap[hash];
710
821
  }
711
- voteHashMap[hash].voters.push((0, generics_1.getKeyAuthor)(update.pollUpdateMessageKey, meId));
822
+ voteHashMap[hash].voters.push(getKeyAuthor(update.pollUpdateMessageKey, meId));
712
823
  }
713
824
  }
714
825
  return Object.values(voteHashMap);
715
826
  }
716
- exports.getAggregateVotesInPollMessage = getAggregateVotesInPollMessage;
717
827
  /** Given a list of message keys, aggregates them by chat & sender. Useful for sending read receipts in bulk */
718
- const aggregateMessageKeysNotFromMe = (keys) => {
828
+ export const aggregateMessageKeysNotFromMe = (keys) => {
719
829
  const keyMap = {};
720
830
  for (const { remoteJid, id, participant, fromMe } of keys) {
721
831
  if (!fromMe) {
@@ -732,40 +842,34 @@ const aggregateMessageKeysNotFromMe = (keys) => {
732
842
  }
733
843
  return Object.values(keyMap);
734
844
  };
735
- exports.aggregateMessageKeysNotFromMe = aggregateMessageKeysNotFromMe;
736
845
  const REUPLOAD_REQUIRED_STATUS = [410, 404];
737
846
  /**
738
847
  * Downloads the given message. Throws an error if it's not a media message
739
848
  */
740
- const downloadMediaMessage = async (message, type, options, ctx) => {
741
- const result = await downloadMsg()
742
- .catch(async (error) => {
743
- var _a;
744
- if (ctx) {
745
- if (axios_1.default.isAxiosError(error)) {
746
- // check if the message requires a reupload
747
- if (REUPLOAD_REQUIRED_STATUS.includes((_a = error.response) === null || _a === void 0 ? void 0 : _a.status)) {
748
- ctx.logger.info({ key: message.key }, 'sending reupload media request...');
749
- // request reupload
750
- message = await ctx.reuploadRequest(message);
751
- const result = await downloadMsg();
752
- return result;
753
- }
754
- }
849
+ export const downloadMediaMessage = async (message, type, options, ctx) => {
850
+ const result = await downloadMsg().catch(async (error) => {
851
+ if (ctx &&
852
+ typeof error?.status === 'number' && // treat errors with status as HTTP failures requiring reupload
853
+ REUPLOAD_REQUIRED_STATUS.includes(error.status)) {
854
+ ctx.logger.info({ key: message.key }, 'sending reupload media request...');
855
+ // request reupload
856
+ message = await ctx.reuploadRequest(message);
857
+ const result = await downloadMsg();
858
+ return result;
755
859
  }
756
860
  throw error;
757
861
  });
758
862
  return result;
759
863
  async function downloadMsg() {
760
- const mContent = (0, exports.extractMessageContent)(message.message);
864
+ const mContent = extractMessageContent(message.message);
761
865
  if (!mContent) {
762
- throw new boom_1.Boom('No message present', { statusCode: 400, data: message });
866
+ throw new Boom('No message present', { statusCode: 400, data: message });
763
867
  }
764
- const contentType = (0, exports.getContentType)(mContent);
765
- let mediaType = contentType === null || contentType === void 0 ? void 0 : contentType.replace('Message', '');
868
+ const contentType = getContentType(mContent);
869
+ let mediaType = contentType?.replace('Message', '');
766
870
  const media = mContent[contentType];
767
871
  if (!media || typeof media !== 'object' || (!('url' in media) && !('thumbnailDirectPath' in media))) {
768
- throw new boom_1.Boom(`"${contentType}" message is not a media message`);
872
+ throw new Boom(`"${contentType}" message is not a media message`);
769
873
  }
770
874
  let download;
771
875
  if ('thumbnailDirectPath' in media && !('url' in media)) {
@@ -778,7 +882,7 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
778
882
  else {
779
883
  download = media;
780
884
  }
781
- const stream = await (0, messages_media_1.downloadContentFromMessage)(download, mediaType, options);
885
+ const stream = await downloadContentFromMessage(download, mediaType, options);
782
886
  if (type === 'buffer') {
783
887
  const bufferArray = [];
784
888
  for await (const chunk of stream) {
@@ -789,19 +893,16 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
789
893
  return stream;
790
894
  }
791
895
  };
792
- exports.downloadMediaMessage = downloadMediaMessage;
793
- /** Checks whether the given message is a media message; if it is returns the inner content */
794
- const assertMediaContent = (content) => {
795
- content = (0, exports.extractMessageContent)(content);
796
- const mediaContent = (content === null || content === void 0 ? void 0 : content.documentMessage)
797
- || (content === null || content === void 0 ? void 0 : content.imageMessage)
798
- || (content === null || content === void 0 ? void 0 : content.videoMessage)
799
- || (content === null || content === void 0 ? void 0 : content.audioMessage)
800
- || (content === null || content === void 0 ? void 0 : content.stickerMessage);
896
+
897
+ export const assertMediaContent = (content) => {
898
+ content = extractMessageContent(content);
899
+ const mediaContent = content?.documentMessage ||
900
+ content?.imageMessage ||
901
+ content?.videoMessage ||
902
+ content?.audioMessage ||
903
+ content?.stickerMessage;
801
904
  if (!mediaContent) {
802
- throw new boom_1.Boom('given message is not a media message', { statusCode: 400, data: content });
905
+ throw new Boom('given message is not a media message', { statusCode: 400, data: content });
803
906
  }
804
907
  return mediaContent;
805
908
  };
806
- exports.assertMediaContent = assertMediaContent;
807
-