@queenanya/baileys 6.9.5 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -13
- package/lib/Defaults/baileys-version.json +1 -1
- package/lib/Defaults/index.js +4 -1
- package/lib/Socket/business.d.ts +46 -9
- package/lib/Socket/chats.d.ts +10 -2
- package/lib/Socket/chats.js +40 -1
- package/lib/Socket/groups.d.ts +17 -3
- package/lib/Socket/groups.js +12 -1
- package/lib/Socket/index.d.ts +46 -9
- package/lib/Socket/messages-recv.d.ts +45 -9
- package/lib/Socket/messages-recv.js +166 -15
- package/lib/Socket/messages-send.d.ts +39 -5
- package/lib/Socket/messages-send.js +153 -37
- package/lib/Socket/newsletter.d.ts +140 -0
- package/lib/Socket/newsletter.js +249 -0
- package/lib/Socket/registration.d.ts +46 -12
- package/lib/Socket/socket.js +4 -3
- package/lib/Store/make-in-memory-store.js +5 -1
- package/lib/Types/Chat.d.ts +5 -0
- package/lib/Types/Events.d.ts +32 -1
- package/lib/Types/GroupMetadata.d.ts +1 -1
- package/lib/Types/Label.d.ts +11 -0
- package/lib/Types/Message.d.ts +39 -27
- package/lib/Types/Newsletter.d.ts +79 -0
- package/lib/Types/Newsletter.js +18 -0
- package/lib/Types/Socket.d.ts +7 -0
- package/lib/Types/index.d.ts +9 -0
- package/lib/Types/index.js +1 -0
- package/lib/Utils/chat-utils.js +16 -0
- package/lib/Utils/crypto.d.ts +1 -1
- package/lib/Utils/crypto.js +4 -2
- package/lib/Utils/decode-wa-message.d.ts +1 -0
- package/lib/Utils/decode-wa-message.js +50 -22
- package/lib/Utils/generics.d.ts +30 -10
- package/lib/Utils/generics.js +82 -10
- package/lib/Utils/history.d.ts +4 -0
- package/lib/Utils/history.js +3 -0
- package/lib/Utils/logger.d.ts +1 -3
- package/lib/Utils/messages-media.d.ts +10 -1
- package/lib/Utils/messages-media.js +61 -18
- package/lib/Utils/messages.js +72 -69
- package/lib/Utils/noise-handler.d.ts +1 -1
- package/lib/Utils/noise-handler.js +2 -2
- package/lib/Utils/process-message.d.ts +3 -2
- package/lib/Utils/process-message.js +47 -24
- package/lib/Utils/signal.js +21 -16
- package/lib/WABinary/decode.d.ts +2 -2
- package/lib/WABinary/decode.js +6 -4
- package/lib/WABinary/encode.d.ts +1 -2
- package/lib/WABinary/encode.js +1 -1
- package/lib/WABinary/jid-utils.d.ts +3 -1
- package/lib/WABinary/jid-utils.js +4 -1
- package/package.json +31 -27
package/lib/Utils/generics.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.bytesToCrockford = exports.trimUndefined = exports.isWABusinessPlatform = exports.getCodeFromWSError = exports.getCallStatusFromNode = exports.getErrorCodeFromStreamError = exports.getStatusFromReceiptType = exports.generateMdTagPrefix = exports.fetchLatestWaWebVersion = exports.fetchLatestBaileysVersion = exports.printQRIfNecessaryListener = exports.bindWaitForConnectionUpdate = exports.bindWaitForEvent = exports.generateMessageID = exports.promiseTimeout = exports.delayCancellable = exports.delay = exports.debouncedTimeout = exports.unixTimestampSeconds = exports.toNumber = exports.encodeBigEndian = exports.generateRegistrationId = exports.encodeWAMessage = exports.unpadRandomMax16 = exports.writeRandomPadMax16 = exports.getKeyAuthor = exports.BufferJSON = exports.Browsers = void 0;
|
|
6
|
+
exports.bytesToCrockford = exports.trimUndefined = exports.isWABusinessPlatform = exports.getCodeFromWSError = exports.getCallStatusFromNode = exports.getErrorCodeFromStreamError = exports.getStatusFromReceiptType = exports.generateMdTagPrefix = exports.fetchLatestWaWebVersion = exports.fetchLatestBaileysVersion2 = exports.fetchLatestBaileysVersion = exports.printQRIfNecessaryListener = exports.bindWaitForConnectionUpdate = exports.bindWaitForEvent = exports.generateMessageID = exports.generateMessageIDV3 = exports.generateMessageIDV2 = exports.promiseTimeout = exports.delayCancellable = exports.delay = exports.debouncedTimeout = exports.unixTimestampSeconds = exports.toNumber = exports.encodeBigEndian = exports.generateRegistrationId = exports.encodeNewsletterMessage = exports.encodeWAMessage = exports.unpadRandomMax16 = exports.writeRandomPadMax16 = exports.getKeyAuthor = exports.BufferJSON = exports.getPlatformId = exports.Browsers = void 0;
|
|
7
7
|
const boom_1 = require("@hapi/boom");
|
|
8
8
|
const axios_1 = __importDefault(require("axios"));
|
|
9
9
|
const crypto_1 = require("crypto");
|
|
@@ -12,20 +12,39 @@ const WAProto_1 = require("../../WAProto");
|
|
|
12
12
|
const baileys_version_json_1 = require("../Defaults/baileys-version.json");
|
|
13
13
|
const Types_1 = require("../Types");
|
|
14
14
|
const WABinary_1 = require("../WABinary");
|
|
15
|
+
/** Added Extra Browsers or Platforms*/
|
|
15
16
|
const PLATFORM_MAP = {
|
|
16
17
|
'aix': 'AIX',
|
|
17
18
|
'darwin': 'Mac OS',
|
|
18
19
|
'win32': 'Windows',
|
|
19
|
-
'android': 'Android'
|
|
20
|
+
'android': 'Android',
|
|
21
|
+
'freebsd': 'FreeBSD',
|
|
22
|
+
'openbsd': 'OpenBSD',
|
|
23
|
+
'sunos': 'Solaris'
|
|
20
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
const COMPANION_PLATFORM_MAP = {
|
|
27
|
+
'Chrome': '49',
|
|
28
|
+
'Edge': '50',
|
|
29
|
+
'Firefox': '51',
|
|
30
|
+
'Opera': '53',
|
|
31
|
+
'Safari': '54'
|
|
32
|
+
}
|
|
33
|
+
*/
|
|
21
34
|
exports.Browsers = {
|
|
22
|
-
ubuntu: browser => ['Ubuntu', browser, '
|
|
23
|
-
macOS: browser => ['Mac OS', browser, '
|
|
24
|
-
baileys: browser => ['Baileys', browser, '
|
|
25
|
-
windows: browser => ['Windows', browser, '10.0.
|
|
35
|
+
ubuntu: (browser) => ['Ubuntu', browser, '22.04.4'],
|
|
36
|
+
macOS: (browser) => ['Mac OS', browser, '14.4.1'],
|
|
37
|
+
baileys: (browser) => ['Baileys', browser, '6.5.0'],
|
|
38
|
+
windows: (browser) => ['Windows', browser, '10.0.22631'],
|
|
26
39
|
/** The appropriate browser based on your OS & release */
|
|
27
|
-
appropriate: browser => [PLATFORM_MAP[(0, os_1.platform)()] || 'Ubuntu', browser, (0, os_1.release)()]
|
|
40
|
+
appropriate: (browser) => [PLATFORM_MAP[(0, os_1.platform)()] || 'Ubuntu', browser, (0, os_1.release)()]
|
|
28
41
|
};
|
|
42
|
+
/** Other Browser Support for Paircode */
|
|
43
|
+
const getPlatformId = (browser) => {
|
|
44
|
+
const platformType = WAProto_1.proto.DeviceProps.PlatformType[browser.toUpperCase()];
|
|
45
|
+
return platformType ? platformType.toString().charCodeAt(0).toString() : '51'; // Firefox
|
|
46
|
+
};
|
|
47
|
+
exports.getPlatformId = getPlatformId;
|
|
29
48
|
exports.BufferJSON = {
|
|
30
49
|
replacer: (k, value) => {
|
|
31
50
|
if (Buffer.isBuffer(value) || value instanceof Uint8Array || (value === null || value === void 0 ? void 0 : value.type) === 'Buffer') {
|
|
@@ -66,6 +85,8 @@ const unpadRandomMax16 = (e) => {
|
|
|
66
85
|
exports.unpadRandomMax16 = unpadRandomMax16;
|
|
67
86
|
const encodeWAMessage = (message) => ((0, exports.writeRandomPadMax16)(WAProto_1.proto.Message.encode(message).finish()));
|
|
68
87
|
exports.encodeWAMessage = encodeWAMessage;
|
|
88
|
+
const encodeNewsletterMessage = (message) => (WAProto_1.proto.Message.encode(message).finish());
|
|
89
|
+
exports.encodeNewsletterMessage = encodeNewsletterMessage;
|
|
69
90
|
const generateRegistrationId = () => {
|
|
70
91
|
return Uint16Array.from((0, crypto_1.randomBytes)(2))[0] & 16383;
|
|
71
92
|
};
|
|
@@ -147,8 +168,33 @@ async function promiseTimeout(ms, promise) {
|
|
|
147
168
|
return p;
|
|
148
169
|
}
|
|
149
170
|
exports.promiseTimeout = promiseTimeout;
|
|
171
|
+
//Useless but still keep this to avoid unexpected errors and bugs
|
|
172
|
+
const generateMessageIDV2 = (userId) => {
|
|
173
|
+
const data = Buffer.alloc(8 + 20 + 16);
|
|
174
|
+
data.writeBigUInt64BE(BigInt(Math.floor(Date.now() / 1000)));
|
|
175
|
+
if (userId) {
|
|
176
|
+
const id = (0, WABinary_1.jidDecode)(userId);
|
|
177
|
+
if (id === null || id === void 0 ? void 0 : id.user) {
|
|
178
|
+
data.write(id.user, 8);
|
|
179
|
+
data.write('@c.us', 8 + id.user.length);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const random = (0, crypto_1.randomBytes)(16);
|
|
183
|
+
random.copy(data, 28);
|
|
184
|
+
const hash = (0, crypto_1.createHash)('sha256').update(data).digest();
|
|
185
|
+
return 'ANYAWEB' + hash.toString('hex').toUpperCase().substring(0, 18);
|
|
186
|
+
};
|
|
187
|
+
exports.generateMessageIDV2 = generateMessageIDV2;
|
|
188
|
+
//Message ID function for ShizoWeb
|
|
189
|
+
//This V3 is RollBack Update to old Message ID
|
|
190
|
+
const generateMessageIDV3 = (userId) => {
|
|
191
|
+
let swebfix = 'ANYAWEB';
|
|
192
|
+
let swebRandom = (0, crypto_1.randomBytes)(5).toString('hex').toUpperCase().substring(0, 10);
|
|
193
|
+
return swebfix + swebRandom;
|
|
194
|
+
};
|
|
195
|
+
exports.generateMessageIDV3 = generateMessageIDV3;
|
|
150
196
|
// generate a random ID to attach to a message
|
|
151
|
-
const generateMessageID = () => '
|
|
197
|
+
const generateMessageID = () => 'ANYAWEB' + (0, crypto_1.randomBytes)(10).toString('hex').toUpperCase();
|
|
152
198
|
exports.generateMessageID = generateMessageID;
|
|
153
199
|
function bindWaitForEvent(ev, event) {
|
|
154
200
|
return async (check, timeoutMs) => {
|
|
@@ -192,10 +238,36 @@ const printQRIfNecessaryListener = (ev, logger) => {
|
|
|
192
238
|
};
|
|
193
239
|
exports.printQRIfNecessaryListener = printQRIfNecessaryListener;
|
|
194
240
|
/**
|
|
195
|
-
* utility that fetches latest baileys version from the
|
|
241
|
+
* utility that fetches latest baileys version from the main branch.
|
|
196
242
|
* Use to ensure your WA connection is always on the latest version
|
|
197
243
|
*/
|
|
198
244
|
const fetchLatestBaileysVersion = async (options = {}) => {
|
|
245
|
+
try {
|
|
246
|
+
const result = await axios_1.default.get('https://raw.githubusercontent.com/wppconnect-team/wa-version/main/versions.json', {
|
|
247
|
+
...options,
|
|
248
|
+
responseType: 'json'
|
|
249
|
+
});
|
|
250
|
+
const version = result.data.currentVersion.split('.');
|
|
251
|
+
const version2 = version[2].replace('-alpha', '');
|
|
252
|
+
return {
|
|
253
|
+
version: [+version[0], +version[1], +version2],
|
|
254
|
+
isLatest: true
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
return {
|
|
259
|
+
version: baileys_version_json_1.version,
|
|
260
|
+
isLatest: false,
|
|
261
|
+
error
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
exports.fetchLatestBaileysVersion = fetchLatestBaileysVersion;
|
|
266
|
+
/**
|
|
267
|
+
* utility that fetches latest baileys version from the master branch.
|
|
268
|
+
* Use to ensure your WA connection is always on the latest version
|
|
269
|
+
*/
|
|
270
|
+
const fetchLatestBaileysVersion2 = async (options = {}) => {
|
|
199
271
|
const URL = 'https://raw.githubusercontent.com/WhiskeySockets/Baileys/master/src/Defaults/baileys-version.json';
|
|
200
272
|
try {
|
|
201
273
|
const result = await axios_1.default.get(URL, {
|
|
@@ -215,7 +287,7 @@ const fetchLatestBaileysVersion = async (options = {}) => {
|
|
|
215
287
|
};
|
|
216
288
|
}
|
|
217
289
|
};
|
|
218
|
-
exports.
|
|
290
|
+
exports.fetchLatestBaileysVersion2 = fetchLatestBaileysVersion2;
|
|
219
291
|
/**
|
|
220
292
|
* A utility that fetches the latest web version of whatsapp.
|
|
221
293
|
* Use to ensure your WA connection is always on the latest version
|
package/lib/Utils/history.d.ts
CHANGED
|
@@ -6,10 +6,14 @@ export declare const processHistoryMessage: (item: proto.IHistorySync) => {
|
|
|
6
6
|
chats: Chat[];
|
|
7
7
|
contacts: Contact[];
|
|
8
8
|
messages: proto.IWebMessageInfo[];
|
|
9
|
+
syncType: proto.HistorySync.HistorySyncType;
|
|
10
|
+
progress: number | null | undefined;
|
|
9
11
|
};
|
|
10
12
|
export declare const downloadAndProcessHistorySyncNotification: (msg: proto.Message.IHistorySyncNotification, options: AxiosRequestConfig<any>) => Promise<{
|
|
11
13
|
chats: Chat[];
|
|
12
14
|
contacts: Contact[];
|
|
13
15
|
messages: proto.IWebMessageInfo[];
|
|
16
|
+
syncType: proto.HistorySync.HistorySyncType;
|
|
17
|
+
progress: number | null | undefined;
|
|
14
18
|
}>;
|
|
15
19
|
export declare const getHistoryMsg: (message: proto.IMessage) => proto.Message.IHistorySyncNotification | null | undefined;
|
package/lib/Utils/history.js
CHANGED
|
@@ -32,6 +32,7 @@ const processHistoryMessage = (item) => {
|
|
|
32
32
|
case WAProto_1.proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP:
|
|
33
33
|
case WAProto_1.proto.HistorySync.HistorySyncType.RECENT:
|
|
34
34
|
case WAProto_1.proto.HistorySync.HistorySyncType.FULL:
|
|
35
|
+
case WAProto_1.proto.HistorySync.HistorySyncType.ON_DEMAND:
|
|
35
36
|
for (const chat of item.conversations) {
|
|
36
37
|
contacts.push({ id: chat.id, name: chat.name || undefined });
|
|
37
38
|
const msgs = chat.messages || [];
|
|
@@ -74,6 +75,8 @@ const processHistoryMessage = (item) => {
|
|
|
74
75
|
chats,
|
|
75
76
|
contacts,
|
|
76
77
|
messages,
|
|
78
|
+
syncType: item.syncType,
|
|
79
|
+
progress: item.progress,
|
|
77
80
|
};
|
|
78
81
|
};
|
|
79
82
|
exports.processHistoryMessage = processHistoryMessage;
|
package/lib/Utils/logger.d.ts
CHANGED
|
@@ -63,6 +63,15 @@ type EncryptedStreamOptions = {
|
|
|
63
63
|
logger?: Logger;
|
|
64
64
|
opts?: AxiosRequestConfig;
|
|
65
65
|
};
|
|
66
|
+
export declare const prepareStream: (media: WAMediaUpload, mediaType: MediaType, { logger, saveOriginalFileIfRequired, opts }?: EncryptedStreamOptions) => Promise<{
|
|
67
|
+
mediaKey: undefined;
|
|
68
|
+
encWriteStream: Buffer;
|
|
69
|
+
fileLength: number;
|
|
70
|
+
fileSha256: Buffer;
|
|
71
|
+
fileEncSha256: undefined;
|
|
72
|
+
bodyPath: string | undefined;
|
|
73
|
+
didSaveToTmpPath: boolean;
|
|
74
|
+
}>;
|
|
66
75
|
export declare const encryptedStream: (media: WAMediaUpload, mediaType: MediaType, { logger, saveOriginalFileIfRequired, opts }?: EncryptedStreamOptions) => Promise<{
|
|
67
76
|
mediaKey: Buffer;
|
|
68
77
|
encWriteStream: Readable;
|
|
@@ -92,7 +101,7 @@ export declare const getWAUploadToServer: ({ customUploadHosts, fetchAgent, logg
|
|
|
92
101
|
*/
|
|
93
102
|
export declare const encryptMediaRetryRequest: (key: proto.IMessageKey, mediaKey: Buffer | Uint8Array, meId: string) => BinaryNode;
|
|
94
103
|
export declare const decodeMediaRetryNode: (node: BinaryNode) => {
|
|
95
|
-
key:
|
|
104
|
+
key: import("../Types").WAMessageKey;
|
|
96
105
|
media?: {
|
|
97
106
|
ciphertext: Uint8Array;
|
|
98
107
|
iv: Uint8Array;
|
|
@@ -22,9 +22,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
25
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.extensionForMediaMessage = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.getHttpStream = exports.generateThumbnail = exports.getStream = exports.toBuffer = exports.toReadable = exports.getAudioWaveform = exports.getAudioDuration = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.getMediaKeys = exports.hkdfInfoKey = void 0;
|
|
29
|
+
exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.extensionForMediaMessage = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.prepareStream = exports.getHttpStream = exports.generateThumbnail = exports.getStream = exports.toBuffer = exports.toReadable = exports.getAudioWaveform = exports.getAudioDuration = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.getMediaKeys = exports.hkdfInfoKey = void 0;
|
|
27
30
|
const boom_1 = require("@hapi/boom");
|
|
31
|
+
const axios_1 = __importDefault(require("axios"));
|
|
28
32
|
const child_process_1 = require("child_process");
|
|
29
33
|
const Crypto = __importStar(require("crypto"));
|
|
30
34
|
const events_1 = require("events");
|
|
@@ -313,11 +317,54 @@ async function generateThumbnail(file, mediaType, options) {
|
|
|
313
317
|
}
|
|
314
318
|
exports.generateThumbnail = generateThumbnail;
|
|
315
319
|
const getHttpStream = async (url, options = {}) => {
|
|
316
|
-
const
|
|
317
|
-
const fetched = await axios.get(url.toString(), { ...options, responseType: 'stream' });
|
|
320
|
+
const fetched = await axios_1.default.get(url.toString(), { ...options, responseType: 'stream' });
|
|
318
321
|
return fetched.data;
|
|
319
322
|
};
|
|
320
323
|
exports.getHttpStream = getHttpStream;
|
|
324
|
+
const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {
|
|
325
|
+
const { stream, type } = await (0, exports.getStream)(media, opts);
|
|
326
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('fetched media stream');
|
|
327
|
+
let bodyPath;
|
|
328
|
+
let didSaveToTmpPath = false;
|
|
329
|
+
try {
|
|
330
|
+
const buffer = await (0, exports.toBuffer)(stream);
|
|
331
|
+
if (type === 'file') {
|
|
332
|
+
bodyPath = media.url;
|
|
333
|
+
}
|
|
334
|
+
else if (saveOriginalFileIfRequired) {
|
|
335
|
+
bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageID)());
|
|
336
|
+
(0, fs_1.writeFileSync)(bodyPath, buffer);
|
|
337
|
+
didSaveToTmpPath = true;
|
|
338
|
+
}
|
|
339
|
+
const fileLength = buffer.length;
|
|
340
|
+
const fileSha256 = Crypto.createHash('sha256').update(buffer).digest();
|
|
341
|
+
stream === null || stream === void 0 ? void 0 : stream.destroy();
|
|
342
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('prepare stream data successfully');
|
|
343
|
+
return {
|
|
344
|
+
mediaKey: undefined,
|
|
345
|
+
encWriteStream: buffer,
|
|
346
|
+
fileLength,
|
|
347
|
+
fileSha256,
|
|
348
|
+
fileEncSha256: undefined,
|
|
349
|
+
bodyPath,
|
|
350
|
+
didSaveToTmpPath
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
// destroy all streams with error
|
|
355
|
+
stream.destroy();
|
|
356
|
+
if (didSaveToTmpPath) {
|
|
357
|
+
try {
|
|
358
|
+
await fs_1.promises.unlink(bodyPath);
|
|
359
|
+
}
|
|
360
|
+
catch (err) {
|
|
361
|
+
logger === null || logger === void 0 ? void 0 : logger.error({ err }, 'failed to save to tmp path');
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
throw error;
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
exports.prepareStream = prepareStream;
|
|
321
368
|
const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {
|
|
322
369
|
const { stream, type } = await (0, exports.getStream)(media, opts);
|
|
323
370
|
logger === null || logger === void 0 ? void 0 : logger.debug('fetched media stream');
|
|
@@ -523,29 +570,24 @@ function extensionForMediaMessage(message) {
|
|
|
523
570
|
}
|
|
524
571
|
exports.extensionForMediaMessage = extensionForMediaMessage;
|
|
525
572
|
const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options }, refreshMediaConn) => {
|
|
526
|
-
return async (stream, { mediaType, fileEncSha256B64, timeoutMs }) => {
|
|
573
|
+
return async (stream, { mediaType, fileEncSha256B64, newsletter, timeoutMs }) => {
|
|
527
574
|
var _a, _b;
|
|
528
|
-
const { default: axios } = await import('axios');
|
|
529
575
|
// send a query JSON to obtain the url & auth token to upload our media
|
|
530
576
|
let uploadInfo = await refreshMediaConn(false);
|
|
531
577
|
let urls;
|
|
532
578
|
const hosts = [...customUploadHosts, ...uploadInfo.hosts];
|
|
533
|
-
const chunks = [];
|
|
534
|
-
for await (const chunk of stream) {
|
|
535
|
-
chunks.push(chunk);
|
|
536
|
-
}
|
|
537
|
-
const reqBody = Buffer.concat(chunks);
|
|
538
579
|
fileEncSha256B64 = (0, exports.encodeBase64EncodedStringForUpload)(fileEncSha256B64);
|
|
539
|
-
|
|
580
|
+
let media = Defaults_1.MEDIA_PATH_MAP[mediaType];
|
|
581
|
+
if (newsletter) {
|
|
582
|
+
media = media === null || media === void 0 ? void 0 : media.replace('/mms/', '/newsletter/newsletter-');
|
|
583
|
+
}
|
|
584
|
+
for (const { hostname } of hosts) {
|
|
540
585
|
logger.debug(`uploading to "${hostname}"`);
|
|
541
586
|
const auth = encodeURIComponent(uploadInfo.auth); // the auth token
|
|
542
|
-
const url = `https://${hostname}${
|
|
587
|
+
const url = `https://${hostname}${media}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`;
|
|
543
588
|
let result;
|
|
544
589
|
try {
|
|
545
|
-
|
|
546
|
-
throw new boom_1.Boom(`Body too large for "${hostname}"`, { statusCode: 413 });
|
|
547
|
-
}
|
|
548
|
-
const body = await axios.post(url, reqBody, {
|
|
590
|
+
const body = await axios_1.default.post(url, stream, {
|
|
549
591
|
...options,
|
|
550
592
|
headers: {
|
|
551
593
|
...options.headers || {},
|
|
@@ -562,7 +604,8 @@ const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options },
|
|
|
562
604
|
if ((result === null || result === void 0 ? void 0 : result.url) || (result === null || result === void 0 ? void 0 : result.directPath)) {
|
|
563
605
|
urls = {
|
|
564
606
|
mediaUrl: result.url,
|
|
565
|
-
directPath: result.direct_path
|
|
607
|
+
directPath: result.direct_path,
|
|
608
|
+
handle: result.handle
|
|
566
609
|
};
|
|
567
610
|
break;
|
|
568
611
|
}
|
|
@@ -572,7 +615,7 @@ const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options },
|
|
|
572
615
|
}
|
|
573
616
|
}
|
|
574
617
|
catch (error) {
|
|
575
|
-
if (
|
|
618
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
576
619
|
result = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data;
|
|
577
620
|
}
|
|
578
621
|
const isLast = hostname === ((_b = hosts[uploadInfo.hosts.length - 1]) === null || _b === void 0 ? void 0 : _b.hostname);
|
package/lib/Utils/messages.js
CHANGED
|
@@ -30,7 +30,6 @@ const MessageTypeProto = {
|
|
|
30
30
|
'sticker': Types_1.WAProto.Message.StickerMessage,
|
|
31
31
|
'document': Types_1.WAProto.Message.DocumentMessage,
|
|
32
32
|
};
|
|
33
|
-
const ButtonType = WAProto_1.proto.Message.ButtonsMessage.HeaderType;
|
|
34
33
|
/**
|
|
35
34
|
* Uses a regex to test whether the string contains a URL, and returns the URL if it does.
|
|
36
35
|
* @param text eg. hello https://google.com
|
|
@@ -111,14 +110,14 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
111
110
|
const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
|
|
112
111
|
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
|
|
113
112
|
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
|
|
114
|
-
const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath } = await (
|
|
113
|
+
const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
115
114
|
logger,
|
|
116
115
|
saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
|
|
117
116
|
opts: options.options
|
|
118
117
|
});
|
|
119
118
|
// url safe Base64 encode the SHA256 hash of the body
|
|
120
|
-
const fileEncSha256B64 = fileEncSha256.toString('base64');
|
|
121
|
-
const [{ mediaUrl, directPath }] = await Promise.all([
|
|
119
|
+
const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 !== null && fileEncSha256 !== void 0 ? fileEncSha256 : fileSha256).toString('base64');
|
|
120
|
+
const [{ mediaUrl, directPath, handle }] = await Promise.all([
|
|
122
121
|
(async () => {
|
|
123
122
|
const result = await options.upload(encWriteStream, { fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs });
|
|
124
123
|
logger === null || logger === void 0 ? void 0 : logger.debug({ mediaType, cacheableKey }, 'uploaded media');
|
|
@@ -159,7 +158,9 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
159
158
|
})(),
|
|
160
159
|
])
|
|
161
160
|
.finally(async () => {
|
|
162
|
-
|
|
161
|
+
if (!Buffer.isBuffer(encWriteStream)) {
|
|
162
|
+
encWriteStream.destroy();
|
|
163
|
+
}
|
|
163
164
|
// remove tmp files
|
|
164
165
|
if (didSaveToTmpPath && bodyPath) {
|
|
165
166
|
await fs_1.promises.unlink(bodyPath);
|
|
@@ -168,13 +169,13 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
168
169
|
});
|
|
169
170
|
const obj = Types_1.WAProto.Message.fromObject({
|
|
170
171
|
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
171
|
-
url: mediaUrl,
|
|
172
|
+
url: handle ? undefined : mediaUrl,
|
|
172
173
|
directPath,
|
|
173
|
-
mediaKey,
|
|
174
|
-
fileEncSha256,
|
|
174
|
+
mediaKey: mediaKey,
|
|
175
|
+
fileEncSha256: fileEncSha256,
|
|
175
176
|
fileSha256,
|
|
176
177
|
fileLength,
|
|
177
|
-
mediaKeyTimestamp: (0, generics_1.unixTimestampSeconds)(),
|
|
178
|
+
mediaKeyTimestamp: handle ? undefined : (0, generics_1.unixTimestampSeconds)(),
|
|
178
179
|
...uploadData,
|
|
179
180
|
media: undefined
|
|
180
181
|
})
|
|
@@ -238,7 +239,7 @@ const generateForwardMessageContent = (message, forceForward) => {
|
|
|
238
239
|
exports.generateForwardMessageContent = generateForwardMessageContent;
|
|
239
240
|
const generateWAMessageContent = async (message, options) => {
|
|
240
241
|
var _a;
|
|
241
|
-
var _b;
|
|
242
|
+
var _b, _c;
|
|
242
243
|
let m = {};
|
|
243
244
|
if ('text' in message) {
|
|
244
245
|
const extContent = { text: message.text };
|
|
@@ -308,6 +309,41 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
308
309
|
message.disappearingMessagesInChat;
|
|
309
310
|
m = (0, exports.prepareDisappearingMessageSettingContent)(exp);
|
|
310
311
|
}
|
|
312
|
+
else if ('groupInvite' in message) {
|
|
313
|
+
m.groupInviteMessage = {};
|
|
314
|
+
m.groupInviteMessage.inviteCode = message.groupInvite.inviteCode;
|
|
315
|
+
m.groupInviteMessage.inviteExpiration = message.groupInvite.inviteExpiration;
|
|
316
|
+
m.groupInviteMessage.caption = message.groupInvite.text;
|
|
317
|
+
m.groupInviteMessage.groupJid = message.groupInvite.jid;
|
|
318
|
+
m.groupInviteMessage.groupName = message.groupInvite.subject;
|
|
319
|
+
//TODO: use built-in interface and get disappearing mode info etc.
|
|
320
|
+
//TODO: cache / use store!?
|
|
321
|
+
if (options.getProfilePicUrl) {
|
|
322
|
+
const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
|
|
323
|
+
if (pfpUrl) {
|
|
324
|
+
const resp = await axios_1.default.get(pfpUrl, { responseType: 'arraybuffer' });
|
|
325
|
+
if (resp.status === 200) {
|
|
326
|
+
m.groupInviteMessage.jpegThumbnail = resp.data;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
else if ('pin' in message) {
|
|
332
|
+
m.pinInChatMessage = {};
|
|
333
|
+
m.messageContextInfo = {};
|
|
334
|
+
m.pinInChatMessage.key = message.pin;
|
|
335
|
+
m.pinInChatMessage.type = 1;
|
|
336
|
+
m.pinInChatMessage.senderTimestampMs = Date.now();
|
|
337
|
+
m.messageContextInfo.messageAddOnDurationInSecs = message.time || 86400;
|
|
338
|
+
}
|
|
339
|
+
else if ('unpin' in message) {
|
|
340
|
+
m.pinInChatMessage = {};
|
|
341
|
+
m.messageContextInfo = {};
|
|
342
|
+
m.pinInChatMessage.key = message.unpin;
|
|
343
|
+
m.pinInChatMessage.type = 2;
|
|
344
|
+
m.pinInChatMessage.senderTimestampMs = Date.now();
|
|
345
|
+
m.messageContextInfo.messageAddOnDurationInSecs = 0;
|
|
346
|
+
}
|
|
311
347
|
else if ('buttonReply' in message) {
|
|
312
348
|
switch (message.type) {
|
|
313
349
|
case 'template':
|
|
@@ -326,6 +362,10 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
326
362
|
break;
|
|
327
363
|
}
|
|
328
364
|
}
|
|
365
|
+
else if ('ptv' in message && message.ptv) {
|
|
366
|
+
const { videoMessage } = await (0, exports.prepareWAMessageMedia)({ video: message.video }, options);
|
|
367
|
+
m.ptvMessage = videoMessage;
|
|
368
|
+
}
|
|
329
369
|
else if ('product' in message) {
|
|
330
370
|
const { imageMessage } = await (0, exports.prepareWAMessageMedia)({ image: message.product.productImage }, options);
|
|
331
371
|
m.productMessage = Types_1.WAProto.Message.ProductMessage.fromObject({
|
|
@@ -341,6 +381,7 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
341
381
|
}
|
|
342
382
|
else if ('poll' in message) {
|
|
343
383
|
(_b = message.poll).selectableCount || (_b.selectableCount = 0);
|
|
384
|
+
(_c = message.poll).toAnnouncementGroup || (_c.toAnnouncementGroup = false);
|
|
344
385
|
if (!Array.isArray(message.poll.values)) {
|
|
345
386
|
throw new boom_1.Boom('Invalid poll values', { statusCode: 400 });
|
|
346
387
|
}
|
|
@@ -352,11 +393,25 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
352
393
|
// encKey
|
|
353
394
|
messageSecret: message.poll.messageSecret || (0, crypto_1.randomBytes)(32),
|
|
354
395
|
};
|
|
355
|
-
|
|
396
|
+
const pollCreationMessage = {
|
|
356
397
|
name: message.poll.name,
|
|
357
398
|
selectableOptionsCount: message.poll.selectableCount,
|
|
358
399
|
options: message.poll.values.map(optionName => ({ optionName })),
|
|
359
400
|
};
|
|
401
|
+
if (message.poll.toAnnouncementGroup) {
|
|
402
|
+
// poll v2 is for community announcement groups (single select and multiple)
|
|
403
|
+
m.pollCreationMessageV2 = pollCreationMessage;
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
if (message.poll.selectableCount > 0) {
|
|
407
|
+
//poll v3 is for single select polls
|
|
408
|
+
m.pollCreationMessageV3 = pollCreationMessage;
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
// poll v3 for multiple choice polls
|
|
412
|
+
m.pollCreationMessage = pollCreationMessage;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
360
415
|
}
|
|
361
416
|
else if ('sharePhoneNumber' in message) {
|
|
362
417
|
m.protocolMessage = {
|
|
@@ -369,61 +424,6 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
369
424
|
else {
|
|
370
425
|
m = await (0, exports.prepareWAMessageMedia)(message, options);
|
|
371
426
|
}
|
|
372
|
-
if ('buttons' in message && !!message.buttons) {
|
|
373
|
-
const buttonsMessage = {
|
|
374
|
-
buttons: message.buttons.map(b => ({ ...b, type: WAProto_1.proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
|
|
375
|
-
};
|
|
376
|
-
if ('text' in message) {
|
|
377
|
-
buttonsMessage.contentText = message.text;
|
|
378
|
-
buttonsMessage.headerType = ButtonType.EMPTY;
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
if ('caption' in message) {
|
|
382
|
-
buttonsMessage.contentText = message.caption;
|
|
383
|
-
}
|
|
384
|
-
const type = Object.keys(m)[0].replace('Message', '').toUpperCase();
|
|
385
|
-
buttonsMessage.headerType = ButtonType[type];
|
|
386
|
-
Object.assign(buttonsMessage, m);
|
|
387
|
-
}
|
|
388
|
-
if ('footer' in message && !!message.footer) {
|
|
389
|
-
buttonsMessage.footerText = message.footer;
|
|
390
|
-
}
|
|
391
|
-
m = { buttonsMessage };
|
|
392
|
-
}
|
|
393
|
-
else if ('templateButtons' in message && !!message.templateButtons) {
|
|
394
|
-
const msg = {
|
|
395
|
-
hydratedButtons: message.templateButtons
|
|
396
|
-
};
|
|
397
|
-
if ('text' in message) {
|
|
398
|
-
msg.hydratedContentText = message.text;
|
|
399
|
-
}
|
|
400
|
-
else {
|
|
401
|
-
if ('caption' in message) {
|
|
402
|
-
msg.hydratedContentText = message.caption;
|
|
403
|
-
}
|
|
404
|
-
Object.assign(msg, m);
|
|
405
|
-
}
|
|
406
|
-
if ('footer' in message && !!message.footer) {
|
|
407
|
-
msg.hydratedFooterText = message.footer;
|
|
408
|
-
}
|
|
409
|
-
m = {
|
|
410
|
-
templateMessage: {
|
|
411
|
-
fourRowTemplate: msg,
|
|
412
|
-
hydratedTemplate: msg
|
|
413
|
-
}
|
|
414
|
-
};
|
|
415
|
-
}
|
|
416
|
-
if ('sections' in message && !!message.sections) {
|
|
417
|
-
const listMessage = {
|
|
418
|
-
sections: message.sections,
|
|
419
|
-
buttonText: message.buttonText,
|
|
420
|
-
title: message.title,
|
|
421
|
-
footerText: message.footer,
|
|
422
|
-
description: message.text,
|
|
423
|
-
listType: WAProto_1.proto.Message.ListMessage.ListType.SINGLE_SELECT
|
|
424
|
-
};
|
|
425
|
-
m = { listMessage };
|
|
426
|
-
}
|
|
427
427
|
if ('viewOnce' in message && !!message.viewOnce) {
|
|
428
428
|
m = { viewOnceMessage: { message: m } };
|
|
429
429
|
}
|
|
@@ -460,7 +460,8 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
460
460
|
const key = (0, exports.getContentType)(innerMessage);
|
|
461
461
|
const timestamp = (0, generics_1.unixTimestampSeconds)(options.timestamp);
|
|
462
462
|
const { quoted, userJid } = options;
|
|
463
|
-
|
|
463
|
+
// only set quoted if isn't a newsletter message
|
|
464
|
+
if (quoted && !(0, WABinary_1.isJidNewsletter)(jid)) {
|
|
464
465
|
const participant = quoted.key.fromMe ? userJid : (quoted.participant || quoted.key.participant || quoted.key.remoteJid);
|
|
465
466
|
let quotedMsg = (0, exports.normalizeMessageContent)(quoted.message);
|
|
466
467
|
const msgType = (0, exports.getContentType)(quotedMsg);
|
|
@@ -487,7 +488,9 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
487
488
|
// and it's not a protocol message -- delete, toggle disappear message
|
|
488
489
|
key !== 'protocolMessage' &&
|
|
489
490
|
// already not converted to disappearing message
|
|
490
|
-
key !== 'ephemeralMessage'
|
|
491
|
+
key !== 'ephemeralMessage' &&
|
|
492
|
+
// newsletter not accept disappearing messages
|
|
493
|
+
!(0, WABinary_1.isJidNewsletter)(jid)) {
|
|
491
494
|
innerMessage[key].contextInfo = {
|
|
492
495
|
...(innerMessage[key].contextInfo || {}),
|
|
493
496
|
expiration: options.ephemeralExpiration || Defaults_1.WA_DEFAULT_EPHEMERAL,
|
|
@@ -514,7 +517,7 @@ const generateWAMessage = async (jid, content, options) => {
|
|
|
514
517
|
var _a;
|
|
515
518
|
// ensure msg ID is with every log
|
|
516
519
|
options.logger = (_a = options === null || options === void 0 ? void 0 : options.logger) === null || _a === void 0 ? void 0 : _a.child({ msgId: options.messageId });
|
|
517
|
-
return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, options), options);
|
|
520
|
+
return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, { newsletter: (0, WABinary_1.isJidNewsletter)(jid), ...options }), options);
|
|
518
521
|
};
|
|
519
522
|
exports.generateWAMessage = generateWAMessage;
|
|
520
523
|
/** Get the key to access the true type of content */
|
|
@@ -17,5 +17,5 @@ export declare const makeNoiseHandler: ({ keyPair: { private: privateKey, public
|
|
|
17
17
|
finishInit: () => void;
|
|
18
18
|
processHandshake: ({ serverHello }: proto.HandshakeMessage, noiseKey: KeyPair) => Buffer;
|
|
19
19
|
encodeFrame: (data: Buffer | Uint8Array) => Buffer;
|
|
20
|
-
decodeFrame: (newData: Buffer | Uint8Array, onFrame: (buff: Uint8Array | BinaryNode) => void) => void
|
|
20
|
+
decodeFrame: (newData: Buffer | Uint8Array, onFrame: (buff: Uint8Array | BinaryNode) => void) => Promise<void>;
|
|
21
21
|
};
|
|
@@ -125,7 +125,7 @@ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey },
|
|
|
125
125
|
frame.set(data, introSize + 3);
|
|
126
126
|
return frame;
|
|
127
127
|
},
|
|
128
|
-
decodeFrame: (newData, onFrame) => {
|
|
128
|
+
decodeFrame: async (newData, onFrame) => {
|
|
129
129
|
var _a;
|
|
130
130
|
// the binary protocol uses its own framing mechanism
|
|
131
131
|
// on top of the WS frames
|
|
@@ -143,7 +143,7 @@ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey },
|
|
|
143
143
|
inBytes = inBytes.slice(size + 3);
|
|
144
144
|
if (isFinished) {
|
|
145
145
|
const result = decrypt(frame);
|
|
146
|
-
frame = (0, WABinary_1.decodeBinaryNode)(result);
|
|
146
|
+
frame = await (0, WABinary_1.decodeBinaryNode)(result);
|
|
147
147
|
}
|
|
148
148
|
logger.trace({ msg: (_a = frame === null || frame === void 0 ? void 0 : frame.attrs) === null || _a === void 0 ? void 0 : _a.id }, 'recv frame');
|
|
149
149
|
onFrame(frame);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { AxiosRequestConfig } from 'axios';
|
|
2
2
|
import type { Logger } from 'pino';
|
|
3
3
|
import { proto } from '../../WAProto';
|
|
4
|
-
import { AuthenticationCreds, BaileysEventEmitter, SignalKeyStoreWithTransaction, SocketConfig } from '../Types';
|
|
4
|
+
import { AuthenticationCreds, BaileysEventEmitter, CacheStore, SignalKeyStoreWithTransaction, SocketConfig } from '../Types';
|
|
5
5
|
type ProcessMessageContext = {
|
|
6
6
|
shouldProcessHistoryMsg: boolean;
|
|
7
|
+
placeholderResendCache?: CacheStore;
|
|
7
8
|
creds: AuthenticationCreds;
|
|
8
9
|
keyStore: SignalKeyStoreWithTransaction;
|
|
9
10
|
ev: BaileysEventEmitter;
|
|
@@ -37,5 +38,5 @@ type PollContext = {
|
|
|
37
38
|
* @returns list of SHA256 options
|
|
38
39
|
*/
|
|
39
40
|
export declare function decryptPollVote({ encPayload, encIv }: proto.Message.IPollEncValue, { pollCreatorJid, pollMsgId, pollEncKey, voterJid, }: PollContext): proto.Message.PollVoteMessage;
|
|
40
|
-
declare const processMessage: (message: proto.IWebMessageInfo, { shouldProcessHistoryMsg, ev, creds, keyStore, logger, options, getMessage }: ProcessMessageContext) => Promise<void>;
|
|
41
|
+
declare const processMessage: (message: proto.IWebMessageInfo, { shouldProcessHistoryMsg, placeholderResendCache, ev, creds, keyStore, logger, options, getMessage }: ProcessMessageContext) => Promise<void>;
|
|
41
42
|
export default processMessage;
|