socketon 1.31.2-rc → 1.51.16

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