@rexxhayanasi/elaina-baileys 1.2.0 → 1.2.1-rc.1

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.
@@ -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
- const jimp = (_jimp === null || _jimp === void 0 ? void 0 : _jimp.default) || _jimp;
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
- }
@@ -82,20 +82,20 @@ const prepareWAMessageMedia = async (message, options) => {
82
82
  media: message[mediaType]
83
83
  };
84
84
  delete uploadData[mediaType];
85
- // check if cacheable + generate cache key
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
- // generate the key
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
- // check for cache hit
98
+
99
99
  if (cacheableKey) {
100
100
  const mediaBuff = options.mediaCache.get(cacheableKey);
101
101
  if (mediaBuff) {
@@ -106,19 +106,85 @@ const prepareWAMessageMedia = async (message, options) => {
106
106
  return obj;
107
107
  }
108
108
  }
109
+
110
+ // --- [MULAI] LOGIKA KHUSUS NEWSLETTER (WHISKEYSOCKETS ADAPTATION) ---
111
+ const isNewsletter = !!options.jid && (0, WABinary_1.isJidNewsletter)(options.jid);
112
+
113
+ if (isNewsletter) {
114
+ logger === null || logger === void 0 ? void 0 : logger.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
115
+
116
+ // 1. Dapatkan file mentah (RAW) menggunakan fungsi yang baru kita buat di messages-media.js
117
+ const { filePath, fileSha256, fileLength } = await (0, messages_media_1.getRawMediaUploadData)(
118
+ uploadData.media,
119
+ options.mediaTypeOverride || mediaType,
120
+ logger
121
+ );
122
+
123
+ const fileSha256B64 = fileSha256.toString('base64');
124
+
125
+ // 2. Upload Stream Mentah
126
+ // Kita buat ReadStream dari filePath agar kompatibel dengan sistem upload Baileys v6
127
+ const streamToUpload = (0, fs_1.createReadStream)(filePath);
128
+
129
+ const { mediaUrl, directPath } = await options.upload(streamToUpload, {
130
+ fileEncSha256B64: fileSha256B64,
131
+ mediaType: mediaType,
132
+ timeoutMs: options.mediaUploadTimeoutMs
133
+ });
134
+
135
+ // Hapus file temp setelah upload selesai
136
+ await fs_1.promises.unlink(filePath);
137
+
138
+ // 3. Buat Objek Pesan
139
+ const obj = Types_1.WAProto.Message.fromObject({
140
+ [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
141
+ url: mediaUrl,
142
+ directPath,
143
+ fileSha256,
144
+ fileLength,
145
+ ...uploadData,
146
+ media: undefined
147
+ })
148
+ });
149
+
150
+ // 4. Ubah tipe pesan jadi PTV jika flag aktif
151
+ if (uploadData.ptv) {
152
+ obj.ptvMessage = obj.videoMessage;
153
+ delete obj.videoMessage;
154
+ }
155
+
156
+ // Handle sticker timestamp
157
+ if (obj.stickerMessage) {
158
+ obj.stickerMessage.stickerSentTs = Date.now();
159
+ }
160
+
161
+ if (cacheableKey) {
162
+ logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'set cache');
163
+ options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish());
164
+ }
165
+
166
+ return obj;
167
+ }
168
+ // --- [SELESAI] LOGIKA NEWSLETTER ---
169
+
170
+
171
+ // --- LOGIKA LAMA (E2E / CHAT BIASA) ---
109
172
  const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
110
173
  const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') &&
111
174
  (typeof uploadData['jpegThumbnail'] === 'undefined');
112
175
  const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
113
176
  const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
114
177
  const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
115
- const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
178
+
179
+ // Enkripsi standar
180
+ const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, } = await (0, messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
116
181
  logger,
117
182
  saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
118
183
  opts: options.options
119
184
  });
120
- // url safe Base64 encode the SHA256 hash of the body
121
- const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 !== null && fileEncSha256 !== void 0 ? fileEncSha256 : fileSha256).toString('base64');
185
+
186
+ const fileEncSha256B64 = (fileEncSha256 !== null && fileEncSha256 !== void 0 ? fileEncSha256 : fileSha256).toString('base64');
187
+
122
188
  const [{ mediaUrl, directPath, handle }] = await Promise.all([
123
189
  (async () => {
124
190
  const result = await options.upload(encWriteStream, { fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs });
@@ -171,6 +237,7 @@ const prepareWAMessageMedia = async (message, options) => {
171
237
  }
172
238
  }
173
239
  });
240
+
174
241
  const obj = Types_1.WAProto.Message.fromObject({
175
242
  [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
176
243
  url: handle ? undefined : mediaUrl,
@@ -184,10 +251,12 @@ const prepareWAMessageMedia = async (message, options) => {
184
251
  media: undefined
185
252
  })
186
253
  });
254
+
187
255
  if (uploadData.ptv) {
188
256
  obj.ptvMessage = obj.videoMessage;
189
257
  delete obj.videoMessage;
190
258
  }
259
+
191
260
  if (cacheableKey) {
192
261
  logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'set cache');
193
262
  options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rexxhayanasi/elaina-baileys",
3
- "version": "1.2.0",
3
+ "version": "1.2.1-rc.1",
4
4
  "description": "Custom Baileys WhatsApp API",
5
5
  "keywords": [
6
6
  "baileys",
@@ -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;