@rexxhayanasi/elaina-baileys 1.2.0 → 1.2.1-rc.2
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/lib/Utils/index.js +0 -1
- package/lib/Utils/messages-media.js +48 -4
- package/lib/Utils/messages.js +90 -10
- package/package.json +1 -1
- package/lib/Utils/newslettermedia.js +0 -110
package/lib/Utils/index.js
CHANGED
|
@@ -34,4 +34,3 @@ __exportStar(require("./process-message"), exports);
|
|
|
34
34
|
__exportStar(require("./message-retry-manager"), exports);
|
|
35
35
|
__exportStar(require("./browser-utils"), exports);
|
|
36
36
|
__exportStar(require("./resolveJid"), exports);
|
|
37
|
-
__exportStar(require("./newslettermedia"), exports);
|
|
@@ -76,7 +76,7 @@ const getImageProcessingLibrary = async () => {
|
|
|
76
76
|
if (sharp) {
|
|
77
77
|
return { sharp };
|
|
78
78
|
}
|
|
79
|
-
|
|
79
|
+
const jimp = (_jimp === null || _jimp === void 0 ? void 0 : _jimp.default) || _jimp;
|
|
80
80
|
if (jimp) {
|
|
81
81
|
return { jimp };
|
|
82
82
|
}
|
|
@@ -87,6 +87,53 @@ const hkdfInfoKey = (type) => {
|
|
|
87
87
|
return `WhatsApp ${hkdfInfo} Keys`;
|
|
88
88
|
};
|
|
89
89
|
exports.hkdfInfoKey = hkdfInfoKey;
|
|
90
|
+
|
|
91
|
+
const getRawMediaUploadData = async (media, mediaType, logger) => {
|
|
92
|
+
|
|
93
|
+
const { stream } = await exports.getStream(media);
|
|
94
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('got stream for raw upload');
|
|
95
|
+
const hasher = Crypto.createHash('sha256');
|
|
96
|
+
|
|
97
|
+
// Generate file temp
|
|
98
|
+
const filePath = (0, path_1.join)((0, os_1.tmpdir)(), mediaType + (0, generics_1.generateMessageIDV2)());
|
|
99
|
+
const fileWriteStream = (0, fs_1.createWriteStream)(filePath);
|
|
100
|
+
|
|
101
|
+
let fileLength = 0;
|
|
102
|
+
try {
|
|
103
|
+
for await (const data of stream) {
|
|
104
|
+
fileLength += data.length;
|
|
105
|
+
hasher.update(data);
|
|
106
|
+
// Handle backpressure
|
|
107
|
+
if (!fileWriteStream.write(data)) {
|
|
108
|
+
await (0, events_1.once)(fileWriteStream, 'drain');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
fileWriteStream.end();
|
|
112
|
+
await (0, events_1.once)(fileWriteStream, 'finish');
|
|
113
|
+
stream.destroy();
|
|
114
|
+
|
|
115
|
+
const fileSha256 = hasher.digest();
|
|
116
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('hashed data for raw upload');
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
filePath: filePath,
|
|
120
|
+
fileSha256,
|
|
121
|
+
fileLength
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
fileWriteStream.destroy();
|
|
126
|
+
stream.destroy();
|
|
127
|
+
try {
|
|
128
|
+
await fs_1.promises.unlink(filePath);
|
|
129
|
+
}
|
|
130
|
+
catch (_a) {
|
|
131
|
+
// ignore
|
|
132
|
+
}
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
exports.getRawMediaUploadData = getRawMediaUploadData;
|
|
90
137
|
/** generates all the keys required to encrypt/decrypt & sign a media message */
|
|
91
138
|
async function getMediaKeys(buffer, mediaType) {
|
|
92
139
|
if (!buffer) {
|
|
@@ -874,6 +921,3 @@ const MEDIA_RETRY_STATUS_MAP = {
|
|
|
874
921
|
[WAProto_1.proto.MediaRetryNotification.ResultType.NOT_FOUND]: 404,
|
|
875
922
|
[WAProto_1.proto.MediaRetryNotification.ResultType.GENERAL_ERROR]: 418,
|
|
876
923
|
};
|
|
877
|
-
function __importStar(arg0) {
|
|
878
|
-
throw new Error('Function not implemented.');
|
|
879
|
-
}
|
package/lib/Utils/messages.js
CHANGED
|
@@ -82,20 +82,20 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
82
82
|
media: message[mediaType]
|
|
83
83
|
};
|
|
84
84
|
delete uploadData[mediaType];
|
|
85
|
-
|
|
85
|
+
|
|
86
|
+
// Check cache
|
|
86
87
|
const cacheableKey = typeof uploadData.media === 'object' &&
|
|
87
88
|
('url' in uploadData.media) &&
|
|
88
89
|
!!uploadData.media.url &&
|
|
89
|
-
!!options.mediaCache && (
|
|
90
|
-
|
|
91
|
-
mediaType + ':' + uploadData.media.url.toString());
|
|
90
|
+
!!options.mediaCache && (mediaType + ':' + uploadData.media.url.toString());
|
|
91
|
+
|
|
92
92
|
if (mediaType === 'document' && !uploadData.fileName) {
|
|
93
93
|
uploadData.fileName = 'file';
|
|
94
94
|
}
|
|
95
95
|
if (!uploadData.mimetype) {
|
|
96
96
|
uploadData.mimetype = MIMETYPE_MAP[mediaType];
|
|
97
97
|
}
|
|
98
|
-
|
|
98
|
+
|
|
99
99
|
if (cacheableKey) {
|
|
100
100
|
const mediaBuff = options.mediaCache.get(cacheableKey);
|
|
101
101
|
if (mediaBuff) {
|
|
@@ -106,19 +106,96 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
106
106
|
return obj;
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
+
|
|
110
|
+
const isNewsletter = !!options.jid && (0, WABinary_1.isJidNewsletter)(options.jid);
|
|
111
|
+
|
|
112
|
+
if (isNewsletter) {
|
|
113
|
+
logger === null || logger === void 0 ? void 0 : logger.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
|
|
114
|
+
|
|
115
|
+
const { filePath, fileSha256, fileLength } = await (0, messages_media_1.getRawMediaUploadData)(
|
|
116
|
+
uploadData.media,
|
|
117
|
+
options.mediaTypeOverride || mediaType,
|
|
118
|
+
logger
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const fileSha256B64 = fileSha256.toString('base64');
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
if (mediaType === 'video' || mediaType === 'image') {
|
|
125
|
+
const { thumbnail, originalImageDimensions } = await (0, messages_media_1.generateThumbnail)(filePath, mediaType, options);
|
|
126
|
+
uploadData.jpegThumbnail = thumbnail;
|
|
127
|
+
|
|
128
|
+
if (!uploadData.width && originalImageDimensions) {
|
|
129
|
+
uploadData.width = originalImageDimensions.width;
|
|
130
|
+
uploadData.height = originalImageDimensions.height;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (mediaType === 'audio' || mediaType === 'video') {
|
|
135
|
+
if (typeof uploadData.seconds === 'undefined') {
|
|
136
|
+
uploadData.seconds = await (0, messages_media_1.getAudioDuration)(filePath);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (mediaType === 'audio' && uploadData.ptt === true) {
|
|
141
|
+
uploadData.waveform = await (0, messages_media_1.getAudioWaveform)(filePath, logger);
|
|
142
|
+
}
|
|
143
|
+
} catch (err) {
|
|
144
|
+
logger === null || logger === void 0 ? void 0 : logger.warn({ trace: err.stack }, 'Failed to generate metadata for newsletter media');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const streamToUpload = (0, fs_1.createReadStream)(filePath);
|
|
148
|
+
|
|
149
|
+
const { mediaUrl, directPath } = await options.upload(streamToUpload, {
|
|
150
|
+
fileEncSha256B64: fileSha256B64,
|
|
151
|
+
mediaType: mediaType,
|
|
152
|
+
timeoutMs: options.mediaUploadTimeoutMs
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
await fs_1.promises.unlink(filePath);
|
|
156
|
+
|
|
157
|
+
const obj = Types_1.WAProto.Message.fromObject({
|
|
158
|
+
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
159
|
+
url: mediaUrl,
|
|
160
|
+
directPath,
|
|
161
|
+
fileSha256,
|
|
162
|
+
fileLength,
|
|
163
|
+
...uploadData,
|
|
164
|
+
media: undefined
|
|
165
|
+
})
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
if (uploadData.ptv) {
|
|
169
|
+
obj.ptvMessage = obj.videoMessage;
|
|
170
|
+
delete obj.videoMessage;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (obj.stickerMessage) {
|
|
174
|
+
obj.stickerMessage.stickerSentTs = Date.now();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (cacheableKey) {
|
|
178
|
+
logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'set cache');
|
|
179
|
+
options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish());
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return obj;
|
|
183
|
+
}
|
|
109
184
|
const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
|
|
110
185
|
const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') &&
|
|
111
186
|
(typeof uploadData['jpegThumbnail'] === 'undefined');
|
|
112
187
|
const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
|
|
113
188
|
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
|
|
114
189
|
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
|
|
115
|
-
|
|
190
|
+
|
|
191
|
+
const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, } = await (0, messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
116
192
|
logger,
|
|
117
193
|
saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
|
|
118
194
|
opts: options.options
|
|
119
195
|
});
|
|
120
|
-
|
|
121
|
-
const fileEncSha256B64 = (
|
|
196
|
+
|
|
197
|
+
const fileEncSha256B64 = (fileEncSha256 !== null && fileEncSha256 !== void 0 ? fileEncSha256 : fileSha256).toString('base64');
|
|
198
|
+
|
|
122
199
|
const [{ mediaUrl, directPath, handle }] = await Promise.all([
|
|
123
200
|
(async () => {
|
|
124
201
|
const result = await options.upload(encWriteStream, { fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs });
|
|
@@ -159,7 +236,7 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
159
236
|
if (!Buffer.isBuffer(encWriteStream)) {
|
|
160
237
|
encWriteStream.destroy();
|
|
161
238
|
}
|
|
162
|
-
|
|
239
|
+
|
|
163
240
|
if (didSaveToTmpPath && bodyPath) {
|
|
164
241
|
try {
|
|
165
242
|
await fs_1.promises.access(bodyPath);
|
|
@@ -171,6 +248,7 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
171
248
|
}
|
|
172
249
|
}
|
|
173
250
|
});
|
|
251
|
+
|
|
174
252
|
const obj = Types_1.WAProto.Message.fromObject({
|
|
175
253
|
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
176
254
|
url: handle ? undefined : mediaUrl,
|
|
@@ -184,10 +262,12 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
184
262
|
media: undefined
|
|
185
263
|
})
|
|
186
264
|
});
|
|
265
|
+
|
|
187
266
|
if (uploadData.ptv) {
|
|
188
267
|
obj.ptvMessage = obj.videoMessage;
|
|
189
268
|
delete obj.videoMessage;
|
|
190
269
|
}
|
|
270
|
+
|
|
191
271
|
if (cacheableKey) {
|
|
192
272
|
logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'set cache');
|
|
193
273
|
options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish());
|
|
@@ -221,7 +301,7 @@ const generateForwardMessageContent = (message, forceForward) => {
|
|
|
221
301
|
if (!content) {
|
|
222
302
|
throw new boom_1.Boom('no content in message', { statusCode: 400 });
|
|
223
303
|
}
|
|
224
|
-
|
|
304
|
+
|
|
225
305
|
content = (0, exports.normalizeMessageContent)(content);
|
|
226
306
|
content = WAProto_1.proto.Message.decode(WAProto_1.proto.Message.encode(content).finish());
|
|
227
307
|
let key = Object.keys(content)[0];
|
package/package.json
CHANGED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.getWAUploadToServerNewsletter = exports.prepareWAMessageMediaNewsletter = exports.getRawMediaUploadDataNewsletter = void 0;
|
|
5
|
-
|
|
6
|
-
const crypto_1 = require("crypto");
|
|
7
|
-
const boom_1 = require("@hapi/boom");
|
|
8
|
-
const WAProto_1 = require("../../WAProto");
|
|
9
|
-
const axios_1 = require("axios");
|
|
10
|
-
const Defaults_1 = require("../Defaults");
|
|
11
|
-
|
|
12
|
-
function getRawMediaUploadDataNewsletter(buffer) {
|
|
13
|
-
if (!Buffer.isBuffer(buffer)) {
|
|
14
|
-
throw new boom_1.Boom("Newsletter media must be Buffer");
|
|
15
|
-
}
|
|
16
|
-
const fileSha256 = (0, crypto_1.createHash)("sha256").update(buffer).digest();
|
|
17
|
-
return {
|
|
18
|
-
buffer,
|
|
19
|
-
fileSha256,
|
|
20
|
-
fileLength: buffer.length
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
exports.getRawMediaUploadDataNewsletter = getRawMediaUploadDataNewsletter;
|
|
24
|
-
|
|
25
|
-
function getWAUploadToServerNewsletter({ customUploadHosts = [], fetchAgent, logger, options = {} }, refreshMediaConn) {
|
|
26
|
-
return async (buffer, { mediaType, fileEncSha256B64 }) => {
|
|
27
|
-
if (!Buffer.isBuffer(buffer)) {
|
|
28
|
-
throw new boom_1.Boom("Upload expects Buffer");
|
|
29
|
-
}
|
|
30
|
-
let uploadInfo = await refreshMediaConn(false);
|
|
31
|
-
const hosts = [...customUploadHosts, ...uploadInfo.hosts];
|
|
32
|
-
let urls;
|
|
33
|
-
for (const { hostname, maxContentLengthBytes } of hosts) {
|
|
34
|
-
const auth = encodeURIComponent(uploadInfo.auth);
|
|
35
|
-
let mediaPath = Defaults_1.MEDIA_PATH_MAP[mediaType];
|
|
36
|
-
if (!mediaPath) {
|
|
37
|
-
mediaPath = "/newsletter/newsletter-image";
|
|
38
|
-
} else {
|
|
39
|
-
mediaPath = mediaPath.replace("/mms/", "/newsletter/newsletter-");
|
|
40
|
-
}
|
|
41
|
-
const url = `https://${hostname}${mediaPath}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`;
|
|
42
|
-
try {
|
|
43
|
-
if (maxContentLengthBytes && buffer.length > maxContentLengthBytes) {
|
|
44
|
-
throw new boom_1.Boom("Body too large", { statusCode: 413 });
|
|
45
|
-
}
|
|
46
|
-
const res = await axios_1.default.post(url, buffer, {
|
|
47
|
-
...options,
|
|
48
|
-
headers: {
|
|
49
|
-
"Content-Type": "application/octet-stream",
|
|
50
|
-
Origin: Defaults_1.DEFAULT_ORIGIN,
|
|
51
|
-
...(options.headers || {})
|
|
52
|
-
},
|
|
53
|
-
httpsAgent: fetchAgent,
|
|
54
|
-
responseType: "json",
|
|
55
|
-
maxBodyLength: Infinity,
|
|
56
|
-
maxContentLength: Infinity
|
|
57
|
-
});
|
|
58
|
-
const result = res.data;
|
|
59
|
-
if (result?.url || result?.direct_path) {
|
|
60
|
-
urls = {
|
|
61
|
-
mediaUrl: result.url,
|
|
62
|
-
directPath: result.direct_path
|
|
63
|
-
};
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
uploadInfo = await refreshMediaConn(true);
|
|
67
|
-
} catch (err) {
|
|
68
|
-
logger?.warn?.({ err }, `Newsletter upload failed on ${hostname}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (!urls) {
|
|
72
|
-
throw new boom_1.Boom("Newsletter media upload failed", { statusCode: 500 });
|
|
73
|
-
}
|
|
74
|
-
return urls;
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
exports.getWAUploadToServerNewsletter = getWAUploadToServerNewsletter;
|
|
78
|
-
|
|
79
|
-
async function prepareWAMessageMediaNewsletter(message, options) {
|
|
80
|
-
if (!options || typeof options.upload !== "function") {
|
|
81
|
-
throw new boom_1.Boom("upload function is required");
|
|
82
|
-
}
|
|
83
|
-
const mediaType = Object.keys(message || {})[0];
|
|
84
|
-
if (!mediaType) {
|
|
85
|
-
throw new boom_1.Boom("Invalid newsletter media");
|
|
86
|
-
}
|
|
87
|
-
const buffer = message[mediaType];
|
|
88
|
-
if (!Buffer.isBuffer(buffer)) {
|
|
89
|
-
throw new boom_1.Boom("Newsletter media must be Buffer");
|
|
90
|
-
}
|
|
91
|
-
const uploadData = getRawMediaUploadDataNewsletter(buffer);
|
|
92
|
-
const uploaded = await options.upload(buffer, {
|
|
93
|
-
mediaType,
|
|
94
|
-
fileEncSha256B64: uploadData.fileSha256.toString("base64"),
|
|
95
|
-
newsletter: true
|
|
96
|
-
});
|
|
97
|
-
const proto = {};
|
|
98
|
-
proto[`${mediaType}Message`] = {
|
|
99
|
-
url: uploaded.mediaUrl,
|
|
100
|
-
directPath: uploaded.directPath,
|
|
101
|
-
fileSha256: uploadData.fileSha256,
|
|
102
|
-
fileLength: uploadData.fileLength,
|
|
103
|
-
mimetype: options.mimetype
|
|
104
|
-
};
|
|
105
|
-
if (mediaType === "video") {
|
|
106
|
-
proto.videoMessage.ptv = true;
|
|
107
|
-
}
|
|
108
|
-
return WAProto_1.WAProto.Message.fromObject(proto);
|
|
109
|
-
}
|
|
110
|
-
exports.prepareWAMessageMediaNewsletter = prepareWAMessageMediaNewsletter;
|