jagproject 26.3.22 → 26.3.25
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/WAProto/GenerateStatics.sh +3 -4
- package/WAProto/WAProto.proto +1215 -511
- package/WAProto/fix-imports.js +73 -0
- package/WAProto/index.d.ts +14017 -0
- package/WAProto/index.js +64857 -145167
- package/engine-requirements.js +4 -7
- package/lib/Defaults/index.d.ts +74 -0
- package/lib/Defaults/index.js +51 -33
- package/lib/Defaults/phonenumber-mcc.json +223 -0
- package/lib/Defaults/wileys-version.json +2 -2
- package/lib/Signal/Group/ciphertext-message.d.ts +10 -0
- package/lib/Signal/Group/group-session-builder.d.ts +15 -0
- package/lib/Signal/Group/group-session-builder.js +5 -3
- package/lib/Signal/Group/group_cipher.d.ts +17 -0
- package/lib/Signal/Group/group_cipher.js +35 -46
- package/lib/Signal/Group/index.d.ts +12 -0
- package/lib/Signal/Group/index.js +21 -21
- package/lib/Signal/Group/keyhelper.d.ts +11 -0
- package/lib/Signal/Group/keyhelper.js +2 -2
- package/lib/Signal/Group/sender-chain-key.d.ts +14 -0
- package/lib/Signal/Group/sender-chain-key.js +5 -10
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +17 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +7 -7
- package/lib/Signal/Group/sender-key-message.d.ts +19 -0
- package/lib/Signal/Group/sender-key-message.js +8 -8
- package/lib/Signal/Group/sender-key-name.d.ts +18 -0
- package/lib/Signal/Group/sender-key-record.d.ts +31 -0
- package/lib/Signal/Group/sender-key-record.js +7 -16
- package/lib/Signal/Group/sender-key-state.d.ts +39 -0
- package/lib/Signal/Group/sender-key-state.js +25 -37
- package/lib/Signal/Group/sender-message-key.d.ts +12 -0
- package/lib/Signal/Group/sender-message-key.js +2 -2
- package/lib/Signal/libsignal.d.ts +5 -0
- package/lib/Signal/libsignal.js +358 -54
- package/lib/Signal/lid-mapping.d.ts +19 -0
- package/lib/Signal/lid-mapping.js +274 -0
- package/lib/Socket/Client/index.d.ts +3 -0
- package/lib/Socket/Client/index.js +2 -2
- package/lib/Socket/Client/types.d.ts +16 -0
- package/lib/Socket/Client/types.js +1 -0
- package/lib/Socket/Client/websocket.d.ts +13 -0
- package/lib/Socket/Client/websocket.js +18 -30
- package/lib/Socket/business.d.ts +202 -0
- package/lib/Socket/business.js +160 -38
- package/lib/Socket/chats.d.ts +111 -0
- package/lib/Socket/chats.js +497 -314
- package/lib/Socket/communities.d.ts +258 -0
- package/lib/Socket/communities.js +438 -0
- package/lib/Socket/community.js +333 -0
- package/lib/Socket/groups.d.ts +150 -0
- package/lib/Socket/groups.js +229 -91
- package/lib/Socket/index.d.ts +245 -0
- package/lib/Socket/index.js +9 -6
- package/lib/Socket/messages-recv.d.ts +187 -0
- package/lib/Socket/messages-recv.js +1105 -501
- package/lib/Socket/messages-send.d.ts +183 -0
- package/lib/Socket/messages-send.js +1184 -501
- package/lib/Socket/mex.d.ts +3 -0
- package/lib/Socket/mex.js +45 -0
- package/lib/Socket/newsletter.d.ts +160 -0
- package/lib/Socket/newsletter.js +227 -200
- package/lib/Socket/socket.d.ts +55 -0
- package/lib/Socket/socket.js +507 -206
- package/lib/Socket/usync.js +6 -6
- package/lib/Store/index.js +17 -5
- package/lib/Store/make-cache-manager-store.js +83 -0
- package/lib/Store/make-in-memory-store.js +48 -89
- package/lib/Store/make-ordered-dictionary.js +1 -1
- package/lib/Types/Auth.d.ts +116 -0
- package/lib/Types/Bussines.d.ts +25 -0
- package/lib/Types/Bussines.js +2 -0
- package/lib/Types/Call.d.ts +15 -0
- package/lib/Types/Chat.d.ts +123 -0
- package/lib/Types/Chat.js +7 -1
- package/lib/Types/Contact.d.ts +24 -0
- package/lib/Types/Events.d.ts +237 -0
- package/lib/Types/Events.js +1 -0
- package/lib/Types/GroupMetadata.d.ts +67 -0
- package/lib/Types/Label.d.ts +47 -0
- package/lib/Types/Label.js +1 -3
- package/lib/Types/LabelAssociation.d.ts +30 -0
- package/lib/Types/LabelAssociation.js +1 -3
- package/lib/Types/Message.d.ts +305 -0
- package/lib/Types/Message.js +9 -5
- package/lib/Types/MexUpdates.js +11 -0
- package/lib/Types/Newsletter.d.ts +135 -0
- package/lib/Types/Newsletter.js +36 -11
- package/lib/Types/Product.d.ts +79 -0
- package/lib/Types/Signal.d.ts +76 -0
- package/lib/Types/Signal.js +1 -0
- package/lib/Types/Socket.d.ts +133 -0
- package/lib/Types/Socket.js +1 -0
- package/lib/Types/State.d.ts +39 -0
- package/lib/Types/State.js +12 -0
- package/lib/Types/USync.d.ts +26 -0
- package/lib/Types/USync.js +1 -0
- package/lib/Types/index.d.ts +65 -0
- package/lib/Types/index.js +14 -14
- package/lib/Utils/audioToBuffer.js +31 -0
- package/lib/Utils/auth-utils.d.ts +19 -0
- package/lib/Utils/auth-utils.js +222 -123
- package/lib/Utils/baileys-event-stream.js +60 -0
- package/lib/Utils/browser-utils.d.ts +4 -0
- package/lib/Utils/browser-utils.js +38 -29
- package/lib/Utils/business.d.ts +23 -0
- package/lib/Utils/business.js +54 -48
- package/lib/Utils/chat-utils.d.ts +70 -0
- package/lib/Utils/chat-utils.js +284 -189
- package/lib/Utils/crypto.d.ts +37 -0
- package/lib/Utils/crypto.js +16 -41
- package/lib/Utils/decode-wa-message.d.ts +48 -0
- package/lib/Utils/decode-wa-message.js +128 -48
- package/lib/Utils/event-buffer.d.ts +34 -0
- package/lib/Utils/event-buffer.js +124 -62
- package/lib/Utils/generics.d.ts +91 -0
- package/lib/Utils/generics.js +154 -138
- package/lib/Utils/history.d.ts +22 -0
- package/lib/Utils/history.js +77 -34
- package/lib/Utils/identity-change-handler.d.ts +37 -0
- package/lib/Utils/identity-change-handler.js +54 -0
- package/lib/Utils/index.d.ts +22 -0
- package/lib/Utils/index.js +32 -19
- package/lib/Utils/link-preview.d.ts +21 -0
- package/lib/Utils/link-preview.js +12 -17
- package/lib/Utils/logger.d.ts +13 -0
- package/lib/Utils/lt-hash.d.ts +8 -0
- package/lib/Utils/lt-hash.js +2 -43
- package/lib/Utils/make-mutex.d.ts +9 -0
- package/lib/Utils/make-mutex.js +21 -27
- package/lib/Utils/message-retry-manager.d.ts +110 -0
- package/lib/Utils/message-retry-manager.js +143 -45
- package/lib/Utils/messages-media.d.ts +130 -0
- package/lib/Utils/messages-media.js +429 -502
- package/lib/Utils/messages-newsletter.d.ts +84 -0
- package/lib/Utils/messages-newsletter.js +295 -0
- package/lib/Utils/messages.d.ts +92 -0
- package/lib/Utils/messages.js +1099 -400
- package/lib/Utils/noise-handler.d.ts +20 -0
- package/lib/Utils/noise-handler.js +145 -91
- package/lib/Utils/pre-key-manager.d.ts +28 -0
- package/lib/Utils/pre-key-manager.js +112 -0
- package/lib/Utils/process-message.d.ts +60 -0
- package/lib/Utils/process-message.js +316 -184
- package/lib/Utils/reporting-utils.d.ts +11 -0
- package/lib/Utils/reporting-utils.js +262 -0
- package/lib/Utils/resolve-jid.d.ts +43 -0
- package/lib/Utils/resolve-jid.js +95 -0
- package/lib/Utils/serial-task-queue.js +29 -0
- package/lib/Utils/signal.d.ts +34 -0
- package/lib/Utils/signal.js +56 -39
- package/lib/Utils/streamToBuffer.js +17 -0
- package/lib/Utils/sync-action-utils.d.ts +19 -0
- package/lib/Utils/sync-action-utils.js +52 -0
- package/lib/Utils/tc-token-utils.d.ts +12 -0
- package/lib/Utils/tc-token-utils.js +20 -0
- package/lib/Utils/use-mongo-file-auth-state.js +71 -0
- package/lib/Utils/use-multi-file-auth-state.d.ts +13 -0
- package/lib/Utils/use-multi-file-auth-state.js +11 -12
- package/lib/Utils/use-single-file-auth-state.js +73 -0
- package/lib/Utils/validate-connection.d.ts +11 -0
- package/lib/Utils/validate-connection.js +59 -82
- package/lib/Utils/wileys-event-stream.js +1 -61
- package/lib/WABinary/constants.d.ts +28 -0
- package/lib/WABinary/decode.d.ts +7 -0
- package/lib/WABinary/decode.js +39 -4
- package/lib/WABinary/encode.d.ts +3 -0
- package/lib/WABinary/encode.js +17 -11
- package/lib/WABinary/generic-utils.d.ts +15 -0
- package/lib/WABinary/generic-utils.js +46 -18
- package/lib/WABinary/index.d.ts +6 -0
- package/lib/WABinary/index.js +9 -5
- package/lib/WABinary/jid-utils.d.ts +48 -0
- package/lib/WABinary/jid-utils.js +67 -37
- package/lib/WABinary/types.d.ts +19 -0
- package/lib/WABinary/types.js +34 -0
- package/lib/WAM/BinaryInfo.d.ts +9 -0
- package/lib/WAM/constants.d.ts +40 -0
- package/lib/WAM/constants.js +19183 -11678
- package/lib/WAM/encode.d.ts +3 -0
- package/lib/WAM/encode.js +15 -17
- package/lib/WAM/index.d.ts +4 -0
- package/lib/WAM/index.js +3 -3
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +6 -6
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +23 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +9 -9
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +13 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +6 -6
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +13 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +7 -8
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +26 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +18 -17
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +11 -3
- package/lib/WAUSync/Protocols/index.d.ts +5 -0
- package/lib/WAUSync/Protocols/index.js +6 -4
- package/lib/WAUSync/USyncQuery.d.ts +29 -0
- package/lib/WAUSync/USyncQuery.js +38 -30
- package/lib/WAUSync/USyncUser.d.ts +13 -0
- package/lib/WAUSync/index.d.ts +4 -0
- package/lib/WAUSync/index.js +3 -3
- package/lib/index.d.ts +12 -0
- package/lib/index.js +3 -5
- package/package.json +10 -6
- package/readme.md +97 -0
- package/LICENSE +0 -21
package/lib/Utils/messages.js
CHANGED
|
@@ -1,43 +1,164 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
5
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.assertMediaContent = exports.downloadMediaMessage = exports.aggregateMessageKeysNotFromMe = 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;
|
|
36
|
+
exports.getQuotedMsg = exports.prepareAlbumMessageContent = exports.patchMessageForMdIfRequired = exports.assertMediaContent = exports.downloadMediaMessage = exports.aggregateMessageKeysNotFromMe = exports.updateMessageWithEventResponse = exports.updateMessageWithPollUpdate = exports.updateMessageWithReaction = exports.updateMessageWithReceipt = exports.getDevice = exports.extractMessageContent = exports.normalizeMessageContent = exports.getMediaTypeFromContentType = exports.getContentType = exports.generateWAMessage = exports.generateWAMessageFromContent = exports.generateWAMessageContent = exports.hasNonNullishProperty = exports.generateForwardMessageContent = exports.prepareDisappearingMessageSettingContent = exports.prepareWAMessageMedia = exports.generateLinkPreviewIfRequired = exports.extractUrlFromText = void 0;
|
|
7
37
|
exports.getAggregateVotesInPollMessage = getAggregateVotesInPollMessage;
|
|
38
|
+
exports.getAggregateResponsesInEventMessage = getAggregateResponsesInEventMessage;
|
|
8
39
|
const boom_1 = require("@hapi/boom");
|
|
9
|
-
const axios_1 = __importDefault(require("axios"));
|
|
10
40
|
const crypto_1 = require("crypto");
|
|
11
41
|
const fs_1 = require("fs");
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
42
|
+
const index_js_1 = require("../../WAProto/index.js");
|
|
43
|
+
const index_js_2 = require("../Defaults/index.js");
|
|
44
|
+
const index_js_3 = require("../Types/index.js");
|
|
45
|
+
const index_js_4 = require("../WABinary/index.js");
|
|
46
|
+
const crypto_js_1 = require("./crypto.js");
|
|
47
|
+
const generics_js_1 = require("./generics.js");
|
|
48
|
+
const messages_media_js_1 = require("./messages-media.js");
|
|
49
|
+
const _require = require;
|
|
50
|
+
const reporting_utils_js_1 = require("./reporting-utils.js");
|
|
19
51
|
const MIMETYPE_MAP = {
|
|
20
52
|
image: 'image/jpeg',
|
|
21
53
|
video: 'video/mp4',
|
|
22
54
|
document: 'application/pdf',
|
|
23
55
|
audio: 'audio/ogg; codecs=opus',
|
|
24
56
|
sticker: 'image/webp',
|
|
25
|
-
'product-catalog-image': 'image/jpeg'
|
|
57
|
+
'product-catalog-image': 'image/jpeg'
|
|
58
|
+
};
|
|
59
|
+
/** Map ekstensi audio ke mimetype */
|
|
60
|
+
const AUDIO_MIMETYPE_MAP = {
|
|
61
|
+
ogg: 'audio/ogg; codecs=opus',
|
|
62
|
+
oga: 'audio/ogg; codecs=opus',
|
|
63
|
+
opus: 'audio/ogg; codecs=opus',
|
|
64
|
+
mp3: 'audio/mpeg',
|
|
65
|
+
mpeg: 'audio/mpeg',
|
|
66
|
+
mp4: 'audio/mp4',
|
|
67
|
+
m4a: 'audio/mp4',
|
|
68
|
+
aac: 'audio/aac',
|
|
69
|
+
wav: 'audio/wav',
|
|
70
|
+
wave: 'audio/wav',
|
|
71
|
+
flac: 'audio/flac',
|
|
72
|
+
webm: 'audio/webm',
|
|
73
|
+
amr: 'audio/amr',
|
|
74
|
+
'3gp': 'audio/3gpp',
|
|
75
|
+
'3gpp': 'audio/3gpp',
|
|
76
|
+
wma: 'audio/x-ms-wma',
|
|
77
|
+
caf: 'audio/x-caf',
|
|
78
|
+
aiff: 'audio/aiff',
|
|
79
|
+
aif: 'audio/aiff',
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Deteksi mimetype audio dari magic bytes buffer.
|
|
83
|
+
* Return null jika tidak dikenali.
|
|
84
|
+
*/
|
|
85
|
+
const detectAudioMimetypeFromBuffer = (buf) => {
|
|
86
|
+
if (!buf || buf.length < 12)
|
|
87
|
+
return null;
|
|
88
|
+
// OGG
|
|
89
|
+
if (buf[0] === 0x4F && buf[1] === 0x67 && buf[2] === 0x67 && buf[3] === 0x53)
|
|
90
|
+
return 'audio/ogg; codecs=opus';
|
|
91
|
+
// MP3 (ID3 tag atau sync bits)
|
|
92
|
+
if ((buf[0] === 0x49 && buf[1] === 0x44 && buf[2] === 0x33) ||
|
|
93
|
+
(buf[0] === 0xFF && (buf[1] & 0xE0) === 0xE0))
|
|
94
|
+
return 'audio/mpeg';
|
|
95
|
+
// MP4/M4A (ftyp box)
|
|
96
|
+
if (buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70)
|
|
97
|
+
return 'audio/mp4';
|
|
98
|
+
// RIFF/WAV
|
|
99
|
+
if (buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 &&
|
|
100
|
+
buf[8] === 0x57 && buf[9] === 0x41 && buf[10] === 0x56 && buf[11] === 0x45)
|
|
101
|
+
return 'audio/wav';
|
|
102
|
+
// FLAC
|
|
103
|
+
if (buf[0] === 0x66 && buf[1] === 0x4C && buf[2] === 0x61 && buf[3] === 0x43)
|
|
104
|
+
return 'audio/flac';
|
|
105
|
+
// WEBM/MKV
|
|
106
|
+
if (buf[0] === 0x1A && buf[1] === 0x45 && buf[2] === 0xDF && buf[3] === 0xA3)
|
|
107
|
+
return 'audio/webm';
|
|
108
|
+
// AMR
|
|
109
|
+
if (buf[0] === 0x23 && buf[1] === 0x21 && buf[2] === 0x41 && buf[3] === 0x4D &&
|
|
110
|
+
buf[4] === 0x52)
|
|
111
|
+
return 'audio/amr';
|
|
112
|
+
return null;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Deteksi mimetype audio secara otomatis dari media input.
|
|
116
|
+
* Cek: 1) ekstensi URL/path, 2) magic bytes buffer, 3) fallback ke ogg/opus.
|
|
117
|
+
*/
|
|
118
|
+
const detectAudioMimetype = async (media) => {
|
|
119
|
+
// Cek ekstensi dari URL atau path string
|
|
120
|
+
if (typeof media === 'string' || (media && typeof media === 'object' && 'url' in media)) {
|
|
121
|
+
const urlStr = typeof media === 'string' ? media : media.url?.toString?.() ?? '';
|
|
122
|
+
// Ambil path tanpa query string, lalu cari semua ekstensi
|
|
123
|
+
const pathOnly = urlStr.split('?')[0];
|
|
124
|
+
// Cek ekstensi terakhir (.m4a, .mp3, dst)
|
|
125
|
+
const extMatch = pathOnly.match(/\.([a-zA-Z0-9]{2,5})(?:[^/]*)?$/);
|
|
126
|
+
if (extMatch) {
|
|
127
|
+
const ext = extMatch[1].toLowerCase();
|
|
128
|
+
if (AUDIO_MIMETYPE_MAP[ext])
|
|
129
|
+
return AUDIO_MIMETYPE_MAP[ext];
|
|
130
|
+
}
|
|
131
|
+
// Fallback: scan semua segmen path untuk ekstensi audio yang dikenal
|
|
132
|
+
// Contoh: ".plus.aac.ep.m4a" → cek tiap segment dari belakang
|
|
133
|
+
const segments = pathOnly.split('.');
|
|
134
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
135
|
+
const seg = segments[i].toLowerCase().split('/')[0].split('?')[0];
|
|
136
|
+
if (AUDIO_MIMETYPE_MAP[seg])
|
|
137
|
+
return AUDIO_MIMETYPE_MAP[seg];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Cek magic bytes jika Buffer
|
|
141
|
+
if (Buffer.isBuffer(media)) {
|
|
142
|
+
const detected = detectAudioMimetypeFromBuffer(media);
|
|
143
|
+
if (detected)
|
|
144
|
+
return detected;
|
|
145
|
+
}
|
|
146
|
+
// Fallback: default ogg/opus
|
|
147
|
+
return MIMETYPE_MAP.audio;
|
|
26
148
|
};
|
|
27
149
|
const MessageTypeProto = {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
150
|
+
image: index_js_3.WAProto.Message.ImageMessage,
|
|
151
|
+
video: index_js_3.WAProto.Message.VideoMessage,
|
|
152
|
+
audio: index_js_3.WAProto.Message.AudioMessage,
|
|
153
|
+
sticker: index_js_3.WAProto.Message.StickerMessage,
|
|
154
|
+
document: index_js_3.WAProto.Message.DocumentMessage
|
|
33
155
|
};
|
|
34
|
-
const ButtonType = WAProto_1.proto.Message.ButtonsMessage.HeaderType;
|
|
35
156
|
/**
|
|
36
157
|
* Uses a regex to test whether the string contains a URL, and returns the URL if it does.
|
|
37
158
|
* @param text eg. hello https://google.com
|
|
38
159
|
* @returns the URL, eg. https://google.com
|
|
39
160
|
*/
|
|
40
|
-
const extractUrlFromText = (text) =>
|
|
161
|
+
const extractUrlFromText = (text) => text.match(index_js_2.URL_REGEX)?.[0];
|
|
41
162
|
exports.extractUrlFromText = extractUrlFromText;
|
|
42
163
|
const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
|
|
43
164
|
const url = (0, exports.extractUrlFromText)(text);
|
|
@@ -46,8 +167,9 @@ const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
|
|
|
46
167
|
const urlInfo = await getUrlInfo(url);
|
|
47
168
|
return urlInfo;
|
|
48
169
|
}
|
|
49
|
-
catch (error) {
|
|
50
|
-
|
|
170
|
+
catch (error) {
|
|
171
|
+
// ignore if fails
|
|
172
|
+
logger?.warn({ trace: error.stack }, 'url generation failed');
|
|
51
173
|
}
|
|
52
174
|
}
|
|
53
175
|
};
|
|
@@ -69,7 +191,7 @@ const assertColor = async (color) => {
|
|
|
69
191
|
const prepareWAMessageMedia = async (message, options) => {
|
|
70
192
|
const logger = options.logger;
|
|
71
193
|
let mediaType;
|
|
72
|
-
for (const key of
|
|
194
|
+
for (const key of index_js_2.MEDIA_KEYS) {
|
|
73
195
|
if (key in message) {
|
|
74
196
|
mediaType = key;
|
|
75
197
|
}
|
|
@@ -84,113 +206,144 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
84
206
|
delete uploadData[mediaType];
|
|
85
207
|
// check if cacheable + generate cache key
|
|
86
208
|
const cacheableKey = typeof uploadData.media === 'object' &&
|
|
87
|
-
|
|
209
|
+
'url' in uploadData.media &&
|
|
88
210
|
!!uploadData.media.url &&
|
|
89
|
-
!!options.mediaCache &&
|
|
90
|
-
|
|
91
|
-
mediaType + ':' + uploadData.media.url.toString());
|
|
211
|
+
!!options.mediaCache &&
|
|
212
|
+
mediaType + ':' + uploadData.media.url.toString();
|
|
92
213
|
if (mediaType === 'document' && !uploadData.fileName) {
|
|
93
214
|
uploadData.fileName = 'file';
|
|
94
215
|
}
|
|
95
216
|
if (!uploadData.mimetype) {
|
|
96
217
|
uploadData.mimetype = MIMETYPE_MAP[mediaType];
|
|
97
218
|
}
|
|
98
|
-
// check for cache hit
|
|
99
219
|
if (cacheableKey) {
|
|
100
|
-
const mediaBuff = options.mediaCache.get(cacheableKey);
|
|
220
|
+
const mediaBuff = await options.mediaCache.get(cacheableKey);
|
|
101
221
|
if (mediaBuff) {
|
|
102
|
-
logger
|
|
103
|
-
const obj =
|
|
222
|
+
logger?.debug({ cacheableKey }, 'got media cache hit');
|
|
223
|
+
const obj = index_js_1.proto.Message.decode(mediaBuff);
|
|
104
224
|
const key = `${mediaType}Message`;
|
|
105
225
|
Object.assign(obj[key], { ...uploadData, media: undefined });
|
|
106
226
|
return obj;
|
|
107
227
|
}
|
|
108
228
|
}
|
|
229
|
+
const isNewsletter = !!options.jid && (0, index_js_4.isJidNewsletter)(options.jid);
|
|
230
|
+
if (isNewsletter)
|
|
231
|
+
options.newsletter = true;
|
|
109
232
|
const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
|
|
110
|
-
const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') &&
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
233
|
+
const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && typeof uploadData['jpegThumbnail'] === 'undefined';
|
|
234
|
+
const requiresWaveformProcessing = mediaType === 'audio' && (uploadData.ptt === true || !!options.backgroundColor);
|
|
235
|
+
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio';
|
|
236
|
+
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation || requiresWaveformProcessing;
|
|
237
|
+
let streamResult;
|
|
238
|
+
try {
|
|
239
|
+
streamResult = await (options.newsletter ? messages_media_js_1.prepareStream : messages_media_js_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
240
|
+
logger,
|
|
241
|
+
saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
|
|
242
|
+
opts: options.options,
|
|
243
|
+
isPtt: uploadData.ptt,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
catch (streamErr) {
|
|
247
|
+
throw streamErr;
|
|
248
|
+
}
|
|
249
|
+
const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath } = streamResult;
|
|
250
|
+
const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 ?? fileSha256).toString('base64');
|
|
251
|
+
const [{ mediaUrl, directPath, handle: uploadHandle }] = await Promise.all([
|
|
123
252
|
(async () => {
|
|
124
|
-
const result = await options.upload(encWriteStream, {
|
|
125
|
-
|
|
253
|
+
const result = await options.upload(encWriteStream, {
|
|
254
|
+
fileEncSha256B64,
|
|
255
|
+
mediaType,
|
|
256
|
+
timeoutMs: options.mediaUploadTimeoutMs,
|
|
257
|
+
newsletter: !!options.newsletter
|
|
258
|
+
});
|
|
126
259
|
return result;
|
|
127
260
|
})(),
|
|
128
261
|
(async () => {
|
|
129
262
|
try {
|
|
130
263
|
if (requiresThumbnailComputation) {
|
|
131
|
-
const { thumbnail, originalImageDimensions } = await (0,
|
|
264
|
+
const { thumbnail, originalImageDimensions } = await (0, messages_media_js_1.generateThumbnail)(bodyPath, mediaType, options);
|
|
132
265
|
uploadData.jpegThumbnail = thumbnail;
|
|
133
266
|
if (!uploadData.width && originalImageDimensions) {
|
|
134
267
|
uploadData.width = originalImageDimensions.width;
|
|
135
268
|
uploadData.height = originalImageDimensions.height;
|
|
136
|
-
logger
|
|
269
|
+
logger?.debug('set dimensions');
|
|
137
270
|
}
|
|
138
|
-
logger
|
|
271
|
+
logger?.debug('generated thumbnail');
|
|
139
272
|
}
|
|
140
273
|
if (requiresDurationComputation) {
|
|
141
|
-
|
|
142
|
-
|
|
274
|
+
try {
|
|
275
|
+
if (bodyPath) {
|
|
276
|
+
uploadData.seconds = await (0, messages_media_js_1.getAudioDuration)(bodyPath, uploadData.mimetype);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
catch (err) {
|
|
280
|
+
uploadData.seconds = 0;
|
|
281
|
+
}
|
|
282
|
+
// Pastikan seconds valid — NaN/undefined bikin WhatsApp tampilkan Loading...
|
|
283
|
+
if (typeof uploadData.seconds !== 'number' || isNaN(uploadData.seconds)) {
|
|
284
|
+
uploadData.seconds = 0;
|
|
285
|
+
}
|
|
286
|
+
logger?.debug('computed audio duration');
|
|
143
287
|
}
|
|
144
288
|
if (requiresWaveformProcessing) {
|
|
145
|
-
|
|
146
|
-
|
|
289
|
+
try {
|
|
290
|
+
uploadData.waveform = await (0, messages_media_js_1.getAudioWaveform)(bodyPath || encWriteStream, logger);
|
|
291
|
+
}
|
|
292
|
+
catch (err) {
|
|
293
|
+
}
|
|
294
|
+
if (!uploadData.waveform) {
|
|
295
|
+
uploadData.waveform = new Uint8Array([0, 99, 0, 99, 0, 99, 0, 99, 88, 99, 0, 99, 0, 55, 0, 99, 0, 99, 0, 99, 0, 99, 0, 99, 88, 99, 0, 99, 0, 55, 0, 99]);
|
|
296
|
+
}
|
|
147
297
|
}
|
|
148
298
|
if (requiresAudioBackground) {
|
|
149
299
|
uploadData.backgroundArgb = await assertColor(options.backgroundColor);
|
|
150
|
-
logger
|
|
300
|
+
logger?.debug('computed backgroundColor audio status');
|
|
151
301
|
}
|
|
152
302
|
}
|
|
153
303
|
catch (error) {
|
|
154
|
-
logger
|
|
304
|
+
logger?.warn({ trace: error.stack }, 'failed to obtain extra info');
|
|
155
305
|
}
|
|
156
|
-
})()
|
|
157
|
-
])
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
// remove tmp files
|
|
163
|
-
if (didSaveToTmpPath && bodyPath) {
|
|
164
|
-
try {
|
|
165
|
-
await fs_1.promises.access(bodyPath);
|
|
166
|
-
await fs_1.promises.unlink(bodyPath);
|
|
167
|
-
logger === null || logger === void 0 ? void 0 : logger.debug('removed tmp file');
|
|
306
|
+
})()
|
|
307
|
+
]).finally(async () => {
|
|
308
|
+
try {
|
|
309
|
+
if (!Buffer.isBuffer(encWriteStream)) {
|
|
310
|
+
encWriteStream.destroy?.();
|
|
168
311
|
}
|
|
169
|
-
|
|
170
|
-
|
|
312
|
+
if (didSaveToTmpPath && bodyPath) {
|
|
313
|
+
await fs_1.promises.unlink(bodyPath).catch(() => { });
|
|
171
314
|
}
|
|
172
315
|
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
logger?.warn('failed to remove tmp file');
|
|
318
|
+
}
|
|
173
319
|
});
|
|
174
|
-
const obj =
|
|
320
|
+
const obj = index_js_3.WAProto.Message.fromObject({
|
|
175
321
|
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
176
|
-
url:
|
|
322
|
+
url: uploadHandle ? undefined : mediaUrl,
|
|
177
323
|
directPath,
|
|
178
324
|
mediaKey: mediaKey,
|
|
179
325
|
fileEncSha256: fileEncSha256,
|
|
180
326
|
fileSha256,
|
|
181
327
|
fileLength,
|
|
182
|
-
mediaKeyTimestamp:
|
|
328
|
+
mediaKeyTimestamp: uploadHandle ? undefined : (0, generics_js_1.unixTimestampSeconds)(),
|
|
183
329
|
...uploadData,
|
|
184
|
-
media: undefined
|
|
330
|
+
media: undefined,
|
|
331
|
+
...(options?.contextInfo ? { contextInfo: options.contextInfo } : {})
|
|
185
332
|
})
|
|
186
333
|
});
|
|
187
334
|
if (uploadData.ptv) {
|
|
188
335
|
obj.ptvMessage = obj.videoMessage;
|
|
189
336
|
delete obj.videoMessage;
|
|
190
337
|
}
|
|
338
|
+
// Attach uploadHandle so sendMessage can use it as media_id
|
|
339
|
+
if (uploadHandle) {
|
|
340
|
+
obj._uploadHandle = uploadHandle;
|
|
341
|
+
}
|
|
342
|
+
if (mediaType === 'audio') {
|
|
343
|
+
}
|
|
191
344
|
if (cacheableKey) {
|
|
192
|
-
logger
|
|
193
|
-
options.mediaCache.set(cacheableKey,
|
|
345
|
+
logger?.debug({ cacheableKey }, 'set cache');
|
|
346
|
+
await options.mediaCache.set(cacheableKey, index_js_3.WAProto.Message.encode(obj).finish());
|
|
194
347
|
}
|
|
195
348
|
return obj;
|
|
196
349
|
};
|
|
@@ -201,13 +354,13 @@ const prepareDisappearingMessageSettingContent = (ephemeralExpiration) => {
|
|
|
201
354
|
ephemeralMessage: {
|
|
202
355
|
message: {
|
|
203
356
|
protocolMessage: {
|
|
204
|
-
type:
|
|
357
|
+
type: index_js_3.WAProto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
|
|
205
358
|
ephemeralExpiration
|
|
206
359
|
}
|
|
207
360
|
}
|
|
208
361
|
}
|
|
209
362
|
};
|
|
210
|
-
return
|
|
363
|
+
return index_js_3.WAProto.Message.fromObject(content);
|
|
211
364
|
};
|
|
212
365
|
exports.prepareDisappearingMessageSettingContent = prepareDisappearingMessageSettingContent;
|
|
213
366
|
/**
|
|
@@ -216,36 +369,46 @@ exports.prepareDisappearingMessageSettingContent = prepareDisappearingMessageSet
|
|
|
216
369
|
* @param options.forceForward will show the message as forwarded even if it is from you
|
|
217
370
|
*/
|
|
218
371
|
const generateForwardMessageContent = (message, forceForward) => {
|
|
219
|
-
var _a;
|
|
220
372
|
let content = message.message;
|
|
221
373
|
if (!content) {
|
|
222
374
|
throw new boom_1.Boom('no content in message', { statusCode: 400 });
|
|
223
375
|
}
|
|
224
376
|
// hacky copy
|
|
225
377
|
content = (0, exports.normalizeMessageContent)(content);
|
|
226
|
-
content =
|
|
378
|
+
content = index_js_1.proto.Message.decode(index_js_1.proto.Message.encode(content).finish());
|
|
227
379
|
let key = Object.keys(content)[0];
|
|
228
|
-
let score =
|
|
380
|
+
let score = content?.[key]?.contextInfo?.forwardingScore || 0;
|
|
229
381
|
score += message.key.fromMe && !forceForward ? 0 : 1;
|
|
230
382
|
if (key === 'conversation') {
|
|
231
383
|
content.extendedTextMessage = { text: content[key] };
|
|
232
384
|
delete content.conversation;
|
|
233
385
|
key = 'extendedTextMessage';
|
|
234
386
|
}
|
|
387
|
+
const key_ = content?.[key];
|
|
235
388
|
if (score > 0) {
|
|
236
|
-
|
|
389
|
+
key_.contextInfo = { forwardingScore: score, isForwarded: true };
|
|
237
390
|
}
|
|
238
391
|
else {
|
|
239
|
-
|
|
392
|
+
key_.contextInfo = {};
|
|
240
393
|
}
|
|
241
394
|
return content;
|
|
242
395
|
};
|
|
243
396
|
exports.generateForwardMessageContent = generateForwardMessageContent;
|
|
397
|
+
const hasNonNullishProperty = (message, key) => {
|
|
398
|
+
return (typeof message === 'object' &&
|
|
399
|
+
message !== null &&
|
|
400
|
+
key in message &&
|
|
401
|
+
message[key] !== null &&
|
|
402
|
+
message[key] !== undefined);
|
|
403
|
+
};
|
|
404
|
+
exports.hasNonNullishProperty = hasNonNullishProperty;
|
|
405
|
+
function hasOptionalProperty(obj, key) {
|
|
406
|
+
return typeof obj === 'object' && obj !== null && key in obj && obj[key] !== null;
|
|
407
|
+
}
|
|
244
408
|
const generateWAMessageContent = async (message, options) => {
|
|
245
|
-
var _a, _b
|
|
246
|
-
var _p, _q;
|
|
409
|
+
var _a, _b;
|
|
247
410
|
let m = {};
|
|
248
|
-
if ('text'
|
|
411
|
+
if ((0, exports.hasNonNullishProperty)(message, 'text')) {
|
|
249
412
|
const extContent = { text: message.text };
|
|
250
413
|
let urlInfo = message.linkPreview;
|
|
251
414
|
if (typeof urlInfo === 'undefined') {
|
|
@@ -276,43 +439,57 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
276
439
|
}
|
|
277
440
|
m.extendedTextMessage = extContent;
|
|
278
441
|
}
|
|
279
|
-
else if ('contacts'
|
|
442
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'contacts')) {
|
|
280
443
|
const contactLen = message.contacts.contacts.length;
|
|
281
444
|
if (!contactLen) {
|
|
282
445
|
throw new boom_1.Boom('require atleast 1 contact', { statusCode: 400 });
|
|
283
446
|
}
|
|
284
447
|
if (contactLen === 1) {
|
|
285
|
-
m.contactMessage =
|
|
448
|
+
m.contactMessage = index_js_3.WAProto.Message.ContactMessage.create(message.contacts.contacts[0]);
|
|
286
449
|
}
|
|
287
450
|
else {
|
|
288
|
-
m.contactsArrayMessage =
|
|
451
|
+
m.contactsArrayMessage = index_js_3.WAProto.Message.ContactsArrayMessage.create(message.contacts);
|
|
289
452
|
}
|
|
290
453
|
}
|
|
291
|
-
else if ('location'
|
|
292
|
-
|
|
454
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'location')) {
|
|
455
|
+
if (message.live) {
|
|
456
|
+
m.liveLocationMessage = index_js_3.WAProto.Message.LiveLocationMessage.create(message.location);
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
m.locationMessage = index_js_3.WAProto.Message.LocationMessage.create(message.location);
|
|
460
|
+
}
|
|
461
|
+
const locType = message.live ? 'liveLocationMessage' : 'locationMessage';
|
|
462
|
+
if (m[locType]) {
|
|
463
|
+
m[locType].contextInfo = {
|
|
464
|
+
...(message.contextInfo || {}),
|
|
465
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
466
|
+
};
|
|
467
|
+
}
|
|
293
468
|
}
|
|
294
|
-
else if ('react'
|
|
469
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'react')) {
|
|
295
470
|
if (!message.react.senderTimestampMs) {
|
|
296
471
|
message.react.senderTimestampMs = Date.now();
|
|
297
472
|
}
|
|
298
|
-
m.reactionMessage =
|
|
473
|
+
m.reactionMessage = index_js_3.WAProto.Message.ReactionMessage.create(message.react);
|
|
299
474
|
}
|
|
300
|
-
else if ('delete'
|
|
475
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'delete')) {
|
|
301
476
|
m.protocolMessage = {
|
|
302
477
|
key: message.delete,
|
|
303
|
-
type:
|
|
478
|
+
type: index_js_3.WAProto.Message.ProtocolMessage.Type.REVOKE
|
|
304
479
|
};
|
|
305
480
|
}
|
|
306
|
-
else if ('forward'
|
|
481
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'forward')) {
|
|
307
482
|
m = (0, exports.generateForwardMessageContent)(message.forward, message.force);
|
|
308
483
|
}
|
|
309
|
-
else if ('disappearingMessagesInChat'
|
|
310
|
-
const exp = typeof message.disappearingMessagesInChat === 'boolean'
|
|
311
|
-
|
|
312
|
-
|
|
484
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'disappearingMessagesInChat')) {
|
|
485
|
+
const exp = typeof message.disappearingMessagesInChat === 'boolean'
|
|
486
|
+
? message.disappearingMessagesInChat
|
|
487
|
+
? index_js_2.WA_DEFAULT_EPHEMERAL
|
|
488
|
+
: 0
|
|
489
|
+
: message.disappearingMessagesInChat;
|
|
313
490
|
m = (0, exports.prepareDisappearingMessageSettingContent)(exp);
|
|
314
491
|
}
|
|
315
|
-
else if ('groupInvite'
|
|
492
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'groupInvite')) {
|
|
316
493
|
m.groupInviteMessage = {};
|
|
317
494
|
m.groupInviteMessage.inviteCode = message.groupInvite.inviteCode;
|
|
318
495
|
m.groupInviteMessage.inviteExpiration = message.groupInvite.inviteExpiration;
|
|
@@ -324,110 +501,207 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
324
501
|
if (options.getProfilePicUrl) {
|
|
325
502
|
const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
|
|
326
503
|
if (pfpUrl) {
|
|
327
|
-
const resp = await
|
|
328
|
-
if (resp.
|
|
329
|
-
|
|
504
|
+
const resp = await fetch(pfpUrl, { method: 'GET', dispatcher: options?.options?.dispatcher });
|
|
505
|
+
if (resp.ok) {
|
|
506
|
+
const buf = Buffer.from(await resp.arrayBuffer());
|
|
507
|
+
m.groupInviteMessage.jpegThumbnail = buf;
|
|
330
508
|
}
|
|
331
509
|
}
|
|
332
510
|
}
|
|
333
511
|
}
|
|
334
|
-
else if ('pin'
|
|
512
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'pin')) {
|
|
335
513
|
m.pinInChatMessage = {};
|
|
336
514
|
m.messageContextInfo = {};
|
|
337
|
-
m.pinInChatMessage.key = message.pin;
|
|
338
|
-
m.pinInChatMessage.type = message.type;
|
|
339
|
-
m.pinInChatMessage.senderTimestampMs = Date.now();
|
|
340
|
-
m.messageContextInfo.messageAddOnDurationInSecs = message.type === 1 ? message.time || 86400 : 0;
|
|
515
|
+
m.pinInChatMessage.key = message.pin.key;
|
|
516
|
+
m.pinInChatMessage.type = message.pin?.type || 1;
|
|
517
|
+
m.pinInChatMessage.senderTimestampMs = message.pin?.time || Date.now();
|
|
518
|
+
m.messageContextInfo.messageAddOnDurationInSecs = message.pin.type === 1 ? message.pin.time || 86400 : 0;
|
|
519
|
+
m.messageContextInfo.messageAddOnExpiryType = index_js_1.proto.MessageContextInfo.MessageAddonExpiryType.STATIC;
|
|
341
520
|
}
|
|
342
|
-
else if ('keep'
|
|
521
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'keep')) {
|
|
343
522
|
m.keepInChatMessage = {};
|
|
344
|
-
m.keepInChatMessage.key = message.keep;
|
|
345
|
-
m.keepInChatMessage.keepType = message.type;
|
|
346
|
-
m.keepInChatMessage.timestampMs = Date.now();
|
|
347
|
-
}
|
|
348
|
-
else if ('call'
|
|
349
|
-
m = {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
523
|
+
m.keepInChatMessage.key = message.keep.key;
|
|
524
|
+
m.keepInChatMessage.keepType = message.keep?.type || 1;
|
|
525
|
+
m.keepInChatMessage.timestampMs = message.keep?.time || Date.now();
|
|
526
|
+
}
|
|
527
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'call')) {
|
|
528
|
+
m.scheduledCallCreationMessage = {};
|
|
529
|
+
m.scheduledCallCreationMessage.scheduledTimestampMs = message.call?.time || Date.now();
|
|
530
|
+
m.scheduledCallCreationMessage.callType = message.call?.type || 1;
|
|
531
|
+
m.scheduledCallCreationMessage.title = message.call?.name || 'Call Creation';
|
|
532
|
+
m.scheduledCallCreationMessage.contextInfo = {
|
|
533
|
+
...(message.contextInfo || {}),
|
|
534
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
355
535
|
};
|
|
356
536
|
}
|
|
357
|
-
else if ('paymentInvite'
|
|
358
|
-
m.
|
|
359
|
-
|
|
360
|
-
|
|
537
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'paymentInvite')) {
|
|
538
|
+
m.messageContextInfo = {};
|
|
539
|
+
m.paymentInviteMessage = {};
|
|
540
|
+
m.paymentInviteMessage.expiryTimestamp = message.paymentInvite?.expiry || 0;
|
|
541
|
+
m.paymentInviteMessage.serviceType = message.paymentInvite?.type || 2;
|
|
542
|
+
m.paymentInviteMessage.contextInfo = {
|
|
543
|
+
...(message.contextInfo || {}),
|
|
544
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
361
545
|
};
|
|
362
546
|
}
|
|
363
|
-
else if ('buttonReply'
|
|
547
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'buttonReply')) {
|
|
364
548
|
switch (message.type) {
|
|
549
|
+
case 'list':
|
|
550
|
+
m.listResponseMessage = {
|
|
551
|
+
title: message.buttonReply.title,
|
|
552
|
+
description: message.buttonReply.description,
|
|
553
|
+
singleSelectReply: {
|
|
554
|
+
selectedRowId: message.buttonReply.rowId
|
|
555
|
+
},
|
|
556
|
+
listType: index_js_1.proto.Message.ListResponseMessage.ListType.SINGLE_SELECT
|
|
557
|
+
};
|
|
558
|
+
break;
|
|
365
559
|
case 'template':
|
|
366
560
|
m.templateButtonReplyMessage = {
|
|
367
561
|
selectedDisplayText: message.buttonReply.displayText,
|
|
368
562
|
selectedId: message.buttonReply.id,
|
|
369
|
-
selectedIndex: message.buttonReply.index
|
|
563
|
+
selectedIndex: message.buttonReply.index
|
|
370
564
|
};
|
|
371
565
|
break;
|
|
372
566
|
case 'plain':
|
|
373
567
|
m.buttonsResponseMessage = {
|
|
374
568
|
selectedButtonId: message.buttonReply.id,
|
|
375
569
|
selectedDisplayText: message.buttonReply.displayText,
|
|
376
|
-
type:
|
|
570
|
+
type: index_js_1.proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
|
|
571
|
+
};
|
|
572
|
+
break;
|
|
573
|
+
case 'interactive':
|
|
574
|
+
m.interactiveResponseMessage = {
|
|
575
|
+
body: {
|
|
576
|
+
text: message.buttonReply.displayText,
|
|
577
|
+
format: index_js_1.proto.Message.InteractiveResponseMessage.Body.Format.EXTENSIONS_1
|
|
578
|
+
},
|
|
579
|
+
nativeFlowResponseMessage: {
|
|
580
|
+
name: message.buttonReply.nativeFlows.name,
|
|
581
|
+
paramsJson: message.buttonReply.nativeFlows.paramsJson,
|
|
582
|
+
version: message.buttonReply.nativeFlows.version
|
|
583
|
+
}
|
|
377
584
|
};
|
|
378
585
|
break;
|
|
379
586
|
}
|
|
380
587
|
}
|
|
381
|
-
else if (
|
|
588
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'album')) {
|
|
589
|
+
const imageMessages = message.album.filter(item => 'image' in item);
|
|
590
|
+
const videoMessages = message.album.filter(item => 'video' in item);
|
|
591
|
+
m.albumMessage = index_js_3.WAProto.Message.AlbumMessage.fromObject({
|
|
592
|
+
expectedImageCount: imageMessages.length,
|
|
593
|
+
expectedVideoCount: videoMessages.length
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'order')) {
|
|
597
|
+
m.orderMessage = index_js_3.WAProto.Message.OrderMessage.fromObject(message.order);
|
|
598
|
+
m.orderMessage.contextInfo = {
|
|
599
|
+
...(message.contextInfo || {}),
|
|
600
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'payment')) {
|
|
604
|
+
const requestPaymentMessage = {
|
|
605
|
+
amount: {
|
|
606
|
+
currencyCode: message.payment?.currency || 'IDR',
|
|
607
|
+
offset: message.payment?.offset || 0,
|
|
608
|
+
value: message.payment?.amount || 999999999
|
|
609
|
+
},
|
|
610
|
+
expiryTimestamp: message.payment?.expiry || 0,
|
|
611
|
+
amount1000: (message.payment?.amount || 999999999) * 1000,
|
|
612
|
+
currencyCodeIso4217: message.payment?.currency || 'IDR',
|
|
613
|
+
requestFrom: message.payment?.from || '0@s.whatsapp.net',
|
|
614
|
+
noteMessage: {
|
|
615
|
+
extendedTextMessage: {
|
|
616
|
+
text: message.payment?.note || 'Notes'
|
|
617
|
+
}
|
|
618
|
+
},
|
|
619
|
+
background: {
|
|
620
|
+
placeholderArgb: message.payment?.image?.placeholderArgb || 4278190080,
|
|
621
|
+
textArgb: message.payment?.image?.textArgb || 4294967295,
|
|
622
|
+
subtextArgb: message.payment?.image?.subtextArgb || 4294967295,
|
|
623
|
+
type: 1
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
requestPaymentMessage.noteMessage.extendedTextMessage.contextInfo = {
|
|
627
|
+
...(message.contextInfo || {}),
|
|
628
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
629
|
+
};
|
|
630
|
+
m.requestPaymentMessage = requestPaymentMessage;
|
|
631
|
+
}
|
|
632
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'pollResult')) {
|
|
633
|
+
if (!Array.isArray(message.pollResult.values)) {
|
|
634
|
+
throw new boom_1.Boom('Invalid pollResult values', { statusCode: 400 });
|
|
635
|
+
}
|
|
636
|
+
const pollResultSnapshotMessage = {
|
|
637
|
+
name: message.pollResult.name,
|
|
638
|
+
pollVotes: message.pollResult.values.map(([optionName, optionVoteCount]) => ({
|
|
639
|
+
optionName,
|
|
640
|
+
optionVoteCount
|
|
641
|
+
}))
|
|
642
|
+
};
|
|
643
|
+
pollResultSnapshotMessage.contextInfo = {
|
|
644
|
+
...(message.contextInfo || {}),
|
|
645
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
646
|
+
};
|
|
647
|
+
m.pollResultSnapshotMessage = pollResultSnapshotMessage;
|
|
648
|
+
}
|
|
649
|
+
else if (hasOptionalProperty(message, 'ptv') && message.ptv) {
|
|
382
650
|
const { videoMessage } = await (0, exports.prepareWAMessageMedia)({ video: message.video }, options);
|
|
383
651
|
m.ptvMessage = videoMessage;
|
|
384
652
|
}
|
|
385
|
-
else if ('product'
|
|
653
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'product')) {
|
|
386
654
|
const { imageMessage } = await (0, exports.prepareWAMessageMedia)({ image: message.product.productImage }, options);
|
|
387
|
-
m.productMessage =
|
|
655
|
+
m.productMessage = index_js_3.WAProto.Message.ProductMessage.create({
|
|
388
656
|
...message,
|
|
389
657
|
product: {
|
|
390
658
|
...message.product,
|
|
391
|
-
productImage: imageMessage
|
|
659
|
+
productImage: imageMessage
|
|
392
660
|
}
|
|
393
661
|
});
|
|
394
662
|
}
|
|
395
|
-
else if ('
|
|
396
|
-
m.orderMessage = Types_1.WAProto.Message.OrderMessage.fromObject({
|
|
397
|
-
orderId: message.order.id,
|
|
398
|
-
thumbnail: message.order.thumbnail,
|
|
399
|
-
itemCount: message.order.itemCount,
|
|
400
|
-
status: message.order.status,
|
|
401
|
-
surface: message.order.surface,
|
|
402
|
-
orderTitle: message.order.title,
|
|
403
|
-
message: message.order.text,
|
|
404
|
-
sellerJid: message.order.seller,
|
|
405
|
-
token: message.order.token,
|
|
406
|
-
totalAmount1000: message.order.amount,
|
|
407
|
-
totalCurrencyCode: message.order.currency
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
else if ('listReply' in message) {
|
|
663
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'listReply')) {
|
|
411
664
|
m.listResponseMessage = { ...message.listReply };
|
|
412
665
|
}
|
|
413
|
-
else if ('
|
|
414
|
-
|
|
415
|
-
|
|
666
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'event')) {
|
|
667
|
+
m.eventMessage = {};
|
|
668
|
+
const startTime = Math.floor(message.event.startDate.getTime() / 1000);
|
|
669
|
+
if (message.event.call && options.getCallLink) {
|
|
670
|
+
const token = await options.getCallLink(message.event.call, { startTime });
|
|
671
|
+
m.eventMessage.joinLink = (message.event.call === 'audio' ? index_js_2.CALL_AUDIO_PREFIX : index_js_2.CALL_VIDEO_PREFIX) + token;
|
|
672
|
+
}
|
|
673
|
+
m.messageContextInfo = {
|
|
674
|
+
// encKey
|
|
675
|
+
messageSecret: message.event.messageSecret || (0, crypto_1.randomBytes)(32)
|
|
676
|
+
};
|
|
677
|
+
m.eventMessage.name = message.event.name;
|
|
678
|
+
m.eventMessage.description = message.event.description;
|
|
679
|
+
m.eventMessage.startTime = startTime;
|
|
680
|
+
m.eventMessage.endTime = message.event.endDate ? message.event.endDate.getTime() / 1000 : undefined;
|
|
681
|
+
m.eventMessage.isCanceled = message.event.isCancelled ?? false;
|
|
682
|
+
m.eventMessage.extraGuestsAllowed = message.event.extraGuestsAllowed;
|
|
683
|
+
m.eventMessage.isScheduleCall = message.event.isScheduleCall ?? false;
|
|
684
|
+
m.eventMessage.location = message.event.location;
|
|
685
|
+
}
|
|
686
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'poll')) {
|
|
687
|
+
(_a = message.poll).selectableCount || (_a.selectableCount = 0);
|
|
688
|
+
(_b = message.poll).toAnnouncementGroup || (_b.toAnnouncementGroup = false);
|
|
416
689
|
if (!Array.isArray(message.poll.values)) {
|
|
417
690
|
throw new boom_1.Boom('Invalid poll values', { statusCode: 400 });
|
|
418
691
|
}
|
|
419
|
-
if (message.poll.selectableCount < 0
|
|
420
|
-
|
|
421
|
-
|
|
692
|
+
if (message.poll.selectableCount < 0 || message.poll.selectableCount > message.poll.values.length) {
|
|
693
|
+
throw new boom_1.Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, {
|
|
694
|
+
statusCode: 400
|
|
695
|
+
});
|
|
422
696
|
}
|
|
423
697
|
m.messageContextInfo = {
|
|
424
698
|
// encKey
|
|
425
|
-
messageSecret: message.poll.messageSecret || (0, crypto_1.randomBytes)(32)
|
|
699
|
+
messageSecret: message.poll.messageSecret || (0, crypto_1.randomBytes)(32)
|
|
426
700
|
};
|
|
427
701
|
const pollCreationMessage = {
|
|
428
702
|
name: message.poll.name,
|
|
429
703
|
selectableOptionsCount: message.poll.selectableCount,
|
|
430
|
-
options: message.poll.values.map(optionName => ({ optionName }))
|
|
704
|
+
options: message.poll.values.map(optionName => ({ optionName }))
|
|
431
705
|
};
|
|
432
706
|
if (message.poll.toAnnouncementGroup) {
|
|
433
707
|
// poll v2 is for community announcement groups (single select and multiple)
|
|
@@ -435,7 +709,7 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
435
709
|
}
|
|
436
710
|
else {
|
|
437
711
|
if (message.poll.selectableCount === 1) {
|
|
438
|
-
//
|
|
712
|
+
//poll v3 is for single select polls
|
|
439
713
|
m.pollCreationMessageV3 = pollCreationMessage;
|
|
440
714
|
}
|
|
441
715
|
else {
|
|
@@ -444,169 +718,340 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
444
718
|
}
|
|
445
719
|
}
|
|
446
720
|
}
|
|
447
|
-
else if ('
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
else if ('inviteAdmin' in message) {
|
|
454
|
-
m.newsletterAdminInviteMessage = {};
|
|
455
|
-
m.newsletterAdminInviteMessage.inviteExpiration = message.inviteAdmin.inviteExpiration;
|
|
456
|
-
m.newsletterAdminInviteMessage.caption = message.inviteAdmin.text;
|
|
457
|
-
m.newsletterAdminInviteMessage.newsletterJid = message.inviteAdmin.jid;
|
|
458
|
-
m.newsletterAdminInviteMessage.newsletterName = message.inviteAdmin.subject;
|
|
459
|
-
m.newsletterAdminInviteMessage.jpegThumbnail = message.inviteAdmin.thumbnail;
|
|
460
|
-
}
|
|
461
|
-
else if ('requestPayment' in message) {
|
|
462
|
-
const sticker = ((_c = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _c === void 0 ? void 0 : _c.sticker) ?
|
|
463
|
-
await (0, exports.prepareWAMessageMedia)({ sticker: (_d = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _d === void 0 ? void 0 : _d.sticker, ...options }, options)
|
|
464
|
-
: null;
|
|
465
|
-
let notes = {};
|
|
466
|
-
if ((_e = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _e === void 0 ? void 0 : _e.sticker) {
|
|
467
|
-
notes = {
|
|
468
|
-
stickerMessage: {
|
|
469
|
-
...sticker === null || sticker === void 0 ? void 0 : sticker.stickerMessage,
|
|
470
|
-
contextInfo: (_f = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _f === void 0 ? void 0 : _f.contextInfo
|
|
471
|
-
}
|
|
472
|
-
};
|
|
721
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'stickerPack')) {
|
|
722
|
+
const { zip } = _require('fflate');
|
|
723
|
+
const { stickers, cover, name, publisher, packId, description } = message.stickerPack;
|
|
724
|
+
// ── Validasi jumlah sticker ───────────────────────────────────────────
|
|
725
|
+
if (stickers.length > 60) {
|
|
726
|
+
throw new boom_1.Boom('Sticker pack exceeds the maximum limit of 60 stickers', { statusCode: 400 });
|
|
473
727
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
728
|
+
if (stickers.length === 0) {
|
|
729
|
+
throw new boom_1.Boom('Sticker pack must contain at least one sticker', { statusCode: 400 });
|
|
730
|
+
}
|
|
731
|
+
const stickerPackId = packId || (0, generics_js_1.generateMessageIDV2)();
|
|
732
|
+
const [_sharp, _jimp] = await Promise.all([Promise.resolve().then(() => __importStar(require('sharp'))).catch(() => null), Promise.resolve().then(() => __importStar(require('jimp'))).catch(() => null)]);
|
|
733
|
+
const lib = _sharp ? { sharp: _sharp } : _jimp ? { jimp: _jimp } : null;
|
|
734
|
+
if (!lib)
|
|
735
|
+
throw new boom_1.Boom('No image processing library available (install sharp or jimp)');
|
|
736
|
+
// ── Helper: deteksi WebP dari magic bytes ─────────────────────────────
|
|
737
|
+
const isWebPBuffer = (buf) => (buf.length >= 12 &&
|
|
738
|
+
buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 &&
|
|
739
|
+
buf[8] === 0x57 && buf[9] === 0x45 && buf[10] === 0x42 && buf[11] === 0x50);
|
|
740
|
+
// ── Helper: deteksi animasi WebP (VP8X/ANIM/ANMF chunks) ─────────────
|
|
741
|
+
const isAnimatedWebP = (buf) => {
|
|
742
|
+
if (!isWebPBuffer(buf))
|
|
743
|
+
return false;
|
|
744
|
+
let offset = 12;
|
|
745
|
+
while (offset < buf.length - 8) {
|
|
746
|
+
const fourCC = buf.toString('ascii', offset, offset + 4);
|
|
747
|
+
const chunkSize = buf.readUInt32LE(offset + 4);
|
|
748
|
+
if (fourCC === 'VP8X') {
|
|
749
|
+
const flagsOffset = offset + 8;
|
|
750
|
+
if (flagsOffset < buf.length && (buf[flagsOffset] & 0x02))
|
|
751
|
+
return true;
|
|
752
|
+
}
|
|
753
|
+
else if (fourCC === 'ANIM' || fourCC === 'ANMF') {
|
|
754
|
+
return true;
|
|
479
755
|
}
|
|
756
|
+
offset += 8 + chunkSize + (chunkSize % 2);
|
|
757
|
+
}
|
|
758
|
+
return false;
|
|
759
|
+
};
|
|
760
|
+
// ── Step 1: proses & zip semua sticker ────────────────────────────────
|
|
761
|
+
const stickerData = {};
|
|
762
|
+
const stickerPromises = stickers.map(async (s, i) => {
|
|
763
|
+
const { stream } = await (0, messages_media_js_1.getStream)(s.data || s.sticker);
|
|
764
|
+
const buffer = await (0, messages_media_js_1.toBuffer)(stream);
|
|
765
|
+
let webpBuffer;
|
|
766
|
+
let isAnimated = false;
|
|
767
|
+
if (isWebPBuffer(buffer)) {
|
|
768
|
+
webpBuffer = buffer;
|
|
769
|
+
isAnimated = isAnimatedWebP(buffer);
|
|
770
|
+
}
|
|
771
|
+
else if ('sharp' in lib && lib.sharp) {
|
|
772
|
+
webpBuffer = await lib.sharp.default(buffer).webp().toBuffer();
|
|
773
|
+
}
|
|
774
|
+
else {
|
|
775
|
+
throw new boom_1.Boom('No image processing library (sharp) available for converting sticker to WebP. ' +
|
|
776
|
+
'Either install sharp or provide stickers in WebP format.');
|
|
777
|
+
}
|
|
778
|
+
if (webpBuffer.length > 1024 * 1024) {
|
|
779
|
+
throw new boom_1.Boom(`Sticker at index ${i} exceeds the 1MB size limit`, { statusCode: 400 });
|
|
780
|
+
}
|
|
781
|
+
const hash = (0, crypto_js_1.sha256)(webpBuffer).toString('base64').replace(/\//g, '-');
|
|
782
|
+
const fileName = `${hash}.webp`;
|
|
783
|
+
stickerData[fileName] = [new Uint8Array(webpBuffer), { level: 0 }];
|
|
784
|
+
return {
|
|
785
|
+
fileName,
|
|
786
|
+
mimetype: 'image/webp',
|
|
787
|
+
isAnimated,
|
|
788
|
+
emojis: s.emojis || [],
|
|
789
|
+
accessibilityLabel: s.accessibilityLabel || ''
|
|
480
790
|
};
|
|
791
|
+
});
|
|
792
|
+
const stickerMetadata = await Promise.all(stickerPromises);
|
|
793
|
+
// ── Step 2: proses cover & masukkan ke dalam ZIP ──────────────────────
|
|
794
|
+
const trayIconFileName = `${stickerPackId}.webp`;
|
|
795
|
+
const coverBuffer = await (0, messages_media_js_1.toBuffer)((await (0, messages_media_js_1.getStream)(cover)).stream);
|
|
796
|
+
let coverWebpBuffer;
|
|
797
|
+
if (isWebPBuffer(coverBuffer)) {
|
|
798
|
+
coverWebpBuffer = coverBuffer;
|
|
799
|
+
}
|
|
800
|
+
else if ('sharp' in lib && lib.sharp) {
|
|
801
|
+
coverWebpBuffer = await lib.sharp.default(coverBuffer).webp().toBuffer();
|
|
481
802
|
}
|
|
482
803
|
else {
|
|
483
|
-
throw new boom_1.Boom('
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
804
|
+
throw new boom_1.Boom('No image processing library (sharp) available for converting cover to WebP. ' +
|
|
805
|
+
'Either install sharp or provide cover in WebP format.');
|
|
806
|
+
}
|
|
807
|
+
stickerData[trayIconFileName] = [new Uint8Array(coverWebpBuffer), { level: 0 }];
|
|
808
|
+
// ── Step 3: buat ZIP buffer ───────────────────────────────────────────
|
|
809
|
+
const zipBuffer = await new Promise((resolve, reject) => {
|
|
810
|
+
zip(stickerData, (err, data) => {
|
|
811
|
+
if (err)
|
|
812
|
+
reject(err);
|
|
813
|
+
else
|
|
814
|
+
resolve(Buffer.from(data));
|
|
815
|
+
});
|
|
816
|
+
});
|
|
817
|
+
// ── Step 4: encrypt ZIP (generate random mediaKey) ────────────────────
|
|
818
|
+
const stickerPackUpload = await (0, messages_media_js_1.encryptedStream)(zipBuffer, 'sticker-pack', {
|
|
819
|
+
logger: options.logger,
|
|
820
|
+
opts: options.options
|
|
492
821
|
});
|
|
822
|
+
// ── Step 5: upload ZIP ────────────────────────────────────────────────
|
|
823
|
+
const stickerPackUploadResult = await options.upload(stickerPackUpload.encWriteStream, {
|
|
824
|
+
fileEncSha256B64: stickerPackUpload.fileEncSha256.toString('base64'),
|
|
825
|
+
mediaType: 'sticker-pack',
|
|
826
|
+
timeoutMs: options.mediaUploadTimeoutMs
|
|
827
|
+
});
|
|
828
|
+
// ── Step 6: build stickerPackMessage ──────────────────────────────────
|
|
829
|
+
m.stickerPackMessage = {
|
|
830
|
+
name,
|
|
831
|
+
publisher,
|
|
832
|
+
stickerPackId,
|
|
833
|
+
packDescription: description,
|
|
834
|
+
stickerPackOrigin: index_js_3.WAProto.Message.StickerPackMessage.StickerPackOrigin.THIRD_PARTY,
|
|
835
|
+
stickerPackSize: zipBuffer.length,
|
|
836
|
+
stickers: stickerMetadata,
|
|
837
|
+
fileSha256: stickerPackUpload.fileSha256,
|
|
838
|
+
fileEncSha256: stickerPackUpload.fileEncSha256,
|
|
839
|
+
mediaKey: stickerPackUpload.mediaKey,
|
|
840
|
+
directPath: stickerPackUploadResult.directPath,
|
|
841
|
+
fileLength: stickerPackUpload.fileLength,
|
|
842
|
+
mediaKeyTimestamp: (0, generics_js_1.unixTimestampSeconds)(),
|
|
843
|
+
trayIconFileName
|
|
844
|
+
};
|
|
845
|
+
// ── Step 7: generate & upload thumbnail (pakai mediaKey yang sama) ────
|
|
846
|
+
try {
|
|
847
|
+
let thumbnailBuffer;
|
|
848
|
+
if ('sharp' in lib && lib.sharp) {
|
|
849
|
+
thumbnailBuffer = await lib.sharp.default(coverBuffer).resize(252, 252).jpeg().toBuffer();
|
|
850
|
+
}
|
|
851
|
+
else if ('jimp' in lib && lib.jimp) {
|
|
852
|
+
const jimpImage = await (lib.jimp.Jimp || lib.jimp.default).read(coverBuffer);
|
|
853
|
+
thumbnailBuffer = await jimpImage.resize({ w: 252, h: 252 }).getBuffer('image/jpeg');
|
|
854
|
+
}
|
|
855
|
+
else {
|
|
856
|
+
throw new Error('No image processing library available for thumbnail generation');
|
|
857
|
+
}
|
|
858
|
+
if (!thumbnailBuffer || thumbnailBuffer.length === 0) {
|
|
859
|
+
throw new Error('Failed to generate thumbnail buffer');
|
|
860
|
+
}
|
|
861
|
+
const thumbUpload = await (0, messages_media_js_1.encryptedStream)(thumbnailBuffer, 'thumbnail-sticker-pack', {
|
|
862
|
+
logger: options.logger,
|
|
863
|
+
opts: options.options,
|
|
864
|
+
mediaKey: stickerPackUpload.mediaKey
|
|
865
|
+
});
|
|
866
|
+
const thumbUploadResult = await options.upload(thumbUpload.encWriteStream, {
|
|
867
|
+
fileEncSha256B64: thumbUpload.fileEncSha256.toString('base64'),
|
|
868
|
+
mediaType: 'thumbnail-sticker-pack',
|
|
869
|
+
timeoutMs: options.mediaUploadTimeoutMs
|
|
870
|
+
});
|
|
871
|
+
Object.assign(m.stickerPackMessage, {
|
|
872
|
+
thumbnailDirectPath: thumbUploadResult.directPath,
|
|
873
|
+
thumbnailSha256: thumbUpload.fileSha256,
|
|
874
|
+
thumbnailEncSha256: thumbUpload.fileEncSha256,
|
|
875
|
+
thumbnailHeight: 252,
|
|
876
|
+
thumbnailWidth: 252,
|
|
877
|
+
imageDataHash: (0, crypto_js_1.sha256)(thumbnailBuffer).toString('base64')
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
catch (e) {
|
|
881
|
+
options.logger?.warn?.(`Thumbnail generation failed: ${e}`);
|
|
882
|
+
}
|
|
883
|
+
m.stickerPackMessage.contextInfo = {
|
|
884
|
+
...(message.contextInfo || {}),
|
|
885
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
886
|
+
};
|
|
493
887
|
}
|
|
494
|
-
else if ('
|
|
888
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'adminInvite')) {
|
|
889
|
+
m.newsletterAdminInviteMessage = {};
|
|
890
|
+
m.newsletterAdminInviteMessage.newsletterJid = message.adminInvite.jid;
|
|
891
|
+
m.newsletterAdminInviteMessage.newsletterName = message.adminInvite.name;
|
|
892
|
+
m.newsletterAdminInviteMessage.caption = message.adminInvite.caption;
|
|
893
|
+
m.newsletterAdminInviteMessage.inviteExpiration = message.adminInvite.expiration;
|
|
894
|
+
if (message.adminInvite.jpegThumbnail) {
|
|
895
|
+
m.newsletterAdminInviteMessage.jpegThumbnail = message.adminInvite.jpegThumbnail;
|
|
896
|
+
}
|
|
897
|
+
else if (options.getProfilePicUrl) {
|
|
898
|
+
try {
|
|
899
|
+
const pfpUrl = await options.getProfilePicUrl(message.adminInvite.jid);
|
|
900
|
+
if (pfpUrl) {
|
|
901
|
+
const { thumbnail } = await (0, messages_media_js_1.generateThumbnail)(pfpUrl, 'image');
|
|
902
|
+
m.newsletterAdminInviteMessage.jpegThumbnail = thumbnail;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
catch (_) { }
|
|
906
|
+
}
|
|
907
|
+
m.newsletterAdminInviteMessage.contextInfo = {
|
|
908
|
+
...(message.contextInfo || {}),
|
|
909
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'sharePhoneNumber')) {
|
|
495
913
|
m.protocolMessage = {
|
|
496
|
-
type:
|
|
914
|
+
type: index_js_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
|
|
497
915
|
};
|
|
498
916
|
}
|
|
499
|
-
else if ('requestPhoneNumber'
|
|
917
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'requestPhoneNumber')) {
|
|
500
918
|
m.requestPhoneNumberMessage = {};
|
|
501
919
|
}
|
|
502
|
-
else if ('
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
920
|
+
else if ((0, exports.hasNonNullishProperty)(message, 'limitSharing')) {
|
|
921
|
+
m.protocolMessage = {
|
|
922
|
+
type: index_js_1.proto.Message.ProtocolMessage.Type.LIMIT_SHARING,
|
|
923
|
+
limitSharing: {
|
|
924
|
+
sharingLimited: message.limitSharing === true,
|
|
925
|
+
trigger: 1,
|
|
926
|
+
limitSharingSettingTimestamp: Date.now(),
|
|
927
|
+
initiatedByMe: true
|
|
928
|
+
}
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
else if ('interactiveMessage' in message && !!message.interactiveMessage) {
|
|
932
|
+
// ── Passthrough interactiveMessage raw object ──────────────────────
|
|
933
|
+
// Must be BEFORE the else block to avoid hitting prepareWAMessageMedia
|
|
934
|
+
// which throws 'Invalid media type' for interactiveMessage keys.
|
|
935
|
+
m = { interactiveMessage: message.interactiveMessage };
|
|
509
936
|
}
|
|
510
937
|
else {
|
|
511
938
|
m = await (0, exports.prepareWAMessageMedia)(message, options);
|
|
512
939
|
}
|
|
513
|
-
if ('
|
|
940
|
+
if ('sections' in message && !!message.sections) {
|
|
941
|
+
const listMessage = {
|
|
942
|
+
title: message.title,
|
|
943
|
+
buttonText: message.buttonText,
|
|
944
|
+
footerText: message.footer,
|
|
945
|
+
description: message.text,
|
|
946
|
+
sections: message.sections,
|
|
947
|
+
listType: index_js_1.proto.Message.ListMessage.ListType.SINGLE_SELECT
|
|
948
|
+
};
|
|
949
|
+
listMessage.contextInfo = {
|
|
950
|
+
...(message.contextInfo || {}),
|
|
951
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
952
|
+
};
|
|
953
|
+
m = { listMessage };
|
|
954
|
+
}
|
|
955
|
+
else if ('productList' in message && !!message.productList) {
|
|
956
|
+
const thumbnail = message.thumbnail ? await (0, messages_media_js_1.generateThumbnail)(message.thumbnail, 'image') : null;
|
|
957
|
+
const listMessage = {
|
|
958
|
+
title: message.title,
|
|
959
|
+
buttonText: message.buttonText,
|
|
960
|
+
footerText: message.footer,
|
|
961
|
+
description: message.text,
|
|
962
|
+
productListInfo: {
|
|
963
|
+
productSections: message.productList,
|
|
964
|
+
headerImage: {
|
|
965
|
+
productId: message.productList[0].products[0].productId,
|
|
966
|
+
jpegThumbnail: thumbnail?.thumbnail || null
|
|
967
|
+
},
|
|
968
|
+
businessOwnerJid: message.businessOwnerJid
|
|
969
|
+
},
|
|
970
|
+
listType: index_js_1.proto.Message.ListMessage.ListType.PRODUCT_LIST
|
|
971
|
+
};
|
|
972
|
+
listMessage.contextInfo = {
|
|
973
|
+
...(message.contextInfo || {}),
|
|
974
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
975
|
+
};
|
|
976
|
+
m = { listMessage };
|
|
977
|
+
}
|
|
978
|
+
else if ('buttons' in message && !!message.buttons) {
|
|
514
979
|
const buttonsMessage = {
|
|
515
|
-
buttons: message.buttons.map(b => ({ ...b, type:
|
|
980
|
+
buttons: message.buttons.map(b => ({ ...b, type: index_js_1.proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
|
|
516
981
|
};
|
|
517
982
|
if ('text' in message) {
|
|
518
983
|
buttonsMessage.contentText = message.text;
|
|
519
|
-
buttonsMessage.headerType =
|
|
984
|
+
buttonsMessage.headerType = index_js_1.proto.Message.ButtonsMessage.HeaderType.EMPTY;
|
|
520
985
|
}
|
|
521
986
|
else {
|
|
522
987
|
if ('caption' in message) {
|
|
523
988
|
buttonsMessage.contentText = message.caption;
|
|
524
989
|
}
|
|
525
990
|
const type = Object.keys(m)[0].replace('Message', '').toUpperCase();
|
|
526
|
-
buttonsMessage.headerType =
|
|
991
|
+
buttonsMessage.headerType = index_js_1.proto.Message.ButtonsMessage.HeaderType[type];
|
|
527
992
|
Object.assign(buttonsMessage, m);
|
|
528
993
|
}
|
|
529
|
-
if ('title' in message && !!message.title) {
|
|
530
|
-
buttonsMessage.text = message.title,
|
|
531
|
-
buttonsMessage.headerType = ButtonType.TEXT;
|
|
532
|
-
}
|
|
533
994
|
if ('footer' in message && !!message.footer) {
|
|
534
995
|
buttonsMessage.footerText = message.footer;
|
|
535
996
|
}
|
|
536
|
-
if ('
|
|
537
|
-
buttonsMessage.
|
|
538
|
-
|
|
539
|
-
if ('mentions' in message && !!message.mentions) {
|
|
540
|
-
buttonsMessage.contextInfo = { mentionedJid: message.mentions };
|
|
997
|
+
if ('title' in message && !!message.title) {
|
|
998
|
+
buttonsMessage.text = message.title;
|
|
999
|
+
buttonsMessage.headerType = index_js_1.proto.Message.ButtonsMessage.HeaderType.TEXT;
|
|
541
1000
|
}
|
|
1001
|
+
buttonsMessage.contextInfo = {
|
|
1002
|
+
...(message.contextInfo || {}),
|
|
1003
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
1004
|
+
};
|
|
542
1005
|
m = { buttonsMessage };
|
|
543
1006
|
}
|
|
544
1007
|
else if ('templateButtons' in message && !!message.templateButtons) {
|
|
545
|
-
const
|
|
546
|
-
hydratedButtons: message.
|
|
1008
|
+
const hydratedTemplate = {
|
|
1009
|
+
hydratedButtons: message.templateButtons
|
|
547
1010
|
};
|
|
548
1011
|
if ('text' in message) {
|
|
549
|
-
|
|
1012
|
+
hydratedTemplate.hydratedContentText = message.text;
|
|
550
1013
|
}
|
|
551
1014
|
else {
|
|
552
1015
|
if ('caption' in message) {
|
|
553
|
-
|
|
1016
|
+
hydratedTemplate.hydratedContentText = message.caption;
|
|
554
1017
|
}
|
|
555
|
-
Object.assign(
|
|
1018
|
+
Object.assign(hydratedTemplate, m);
|
|
556
1019
|
}
|
|
557
1020
|
if ('footer' in message && !!message.footer) {
|
|
558
|
-
|
|
1021
|
+
hydratedTemplate.hydratedFooterText = message.footer;
|
|
559
1022
|
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
hydratedTemplate: msg
|
|
564
|
-
}
|
|
565
|
-
};
|
|
566
|
-
}
|
|
567
|
-
if ('sections' in message && !!message.sections) {
|
|
568
|
-
const listMessage = {
|
|
569
|
-
sections: message.sections,
|
|
570
|
-
buttonText: message.buttonText,
|
|
571
|
-
title: message.title,
|
|
572
|
-
footerText: message.footer,
|
|
573
|
-
description: message.text,
|
|
574
|
-
listType: WAProto_1.proto.Message.ListMessage.ListType.SINGLE_SELECT
|
|
1023
|
+
hydratedTemplate.contextInfo = {
|
|
1024
|
+
...(message.contextInfo || {}),
|
|
1025
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
575
1026
|
};
|
|
576
|
-
m = {
|
|
1027
|
+
m = { templateMessage: { fourRowTemplate: hydratedTemplate, hydratedTemplate } };
|
|
577
1028
|
}
|
|
578
|
-
if ('interactiveButtons' in message && !!message.interactiveButtons) {
|
|
1029
|
+
else if ('interactiveButtons' in message && !!message.interactiveButtons) {
|
|
579
1030
|
const interactiveMessage = {
|
|
580
|
-
nativeFlowMessage:
|
|
1031
|
+
nativeFlowMessage: index_js_1.proto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
|
|
581
1032
|
buttons: message.interactiveButtons,
|
|
582
1033
|
})
|
|
583
1034
|
};
|
|
584
1035
|
if ('text' in message) {
|
|
585
|
-
interactiveMessage.body = {
|
|
586
|
-
text: message.text
|
|
587
|
-
};
|
|
1036
|
+
interactiveMessage.body = { text: message.text };
|
|
588
1037
|
}
|
|
589
1038
|
else if ('caption' in message) {
|
|
590
|
-
interactiveMessage.body = {
|
|
591
|
-
text: message.caption
|
|
592
|
-
};
|
|
1039
|
+
interactiveMessage.body = { text: message.caption };
|
|
593
1040
|
interactiveMessage.header = {
|
|
594
1041
|
title: message.title,
|
|
595
1042
|
subtitle: message.subtitle,
|
|
596
|
-
hasMediaAttachment:
|
|
1043
|
+
hasMediaAttachment: message?.media ?? false,
|
|
597
1044
|
};
|
|
598
1045
|
Object.assign(interactiveMessage.header, m);
|
|
599
1046
|
}
|
|
600
1047
|
if ('footer' in message && !!message.footer) {
|
|
601
|
-
interactiveMessage.footer = {
|
|
602
|
-
text: message.footer
|
|
603
|
-
};
|
|
1048
|
+
interactiveMessage.footer = { text: message.footer };
|
|
604
1049
|
}
|
|
605
1050
|
if ('title' in message && !!message.title) {
|
|
606
1051
|
interactiveMessage.header = {
|
|
607
1052
|
title: message.title,
|
|
608
1053
|
subtitle: message.subtitle,
|
|
609
|
-
hasMediaAttachment:
|
|
1054
|
+
hasMediaAttachment: message?.media ?? false,
|
|
610
1055
|
};
|
|
611
1056
|
Object.assign(interactiveMessage.header, m);
|
|
612
1057
|
}
|
|
@@ -618,39 +1063,33 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
618
1063
|
}
|
|
619
1064
|
m = { interactiveMessage };
|
|
620
1065
|
}
|
|
621
|
-
if ('shop' in message && !!message.shop) {
|
|
1066
|
+
else if ('shop' in message && !!message.shop) {
|
|
622
1067
|
const interactiveMessage = {
|
|
623
|
-
shopStorefrontMessage:
|
|
1068
|
+
shopStorefrontMessage: index_js_1.proto.Message.InteractiveMessage.ShopMessage.fromObject({
|
|
624
1069
|
surface: message.shop,
|
|
625
1070
|
id: message.id
|
|
626
1071
|
})
|
|
627
1072
|
};
|
|
628
1073
|
if ('text' in message) {
|
|
629
|
-
interactiveMessage.body = {
|
|
630
|
-
text: message.text
|
|
631
|
-
};
|
|
1074
|
+
interactiveMessage.body = { text: message.text };
|
|
632
1075
|
}
|
|
633
1076
|
else if ('caption' in message) {
|
|
634
|
-
interactiveMessage.body = {
|
|
635
|
-
text: message.caption
|
|
636
|
-
};
|
|
1077
|
+
interactiveMessage.body = { text: message.caption };
|
|
637
1078
|
interactiveMessage.header = {
|
|
638
1079
|
title: message.title,
|
|
639
1080
|
subtitle: message.subtitle,
|
|
640
|
-
hasMediaAttachment:
|
|
1081
|
+
hasMediaAttachment: message?.media ?? false,
|
|
641
1082
|
};
|
|
642
1083
|
Object.assign(interactiveMessage.header, m);
|
|
643
1084
|
}
|
|
644
1085
|
if ('footer' in message && !!message.footer) {
|
|
645
|
-
interactiveMessage.footer = {
|
|
646
|
-
text: message.footer
|
|
647
|
-
};
|
|
1086
|
+
interactiveMessage.footer = { text: message.footer };
|
|
648
1087
|
}
|
|
649
1088
|
if ('title' in message && !!message.title) {
|
|
650
1089
|
interactiveMessage.header = {
|
|
651
1090
|
title: message.title,
|
|
652
1091
|
subtitle: message.subtitle,
|
|
653
|
-
hasMediaAttachment:
|
|
1092
|
+
hasMediaAttachment: message?.media ?? false,
|
|
654
1093
|
};
|
|
655
1094
|
Object.assign(interactiveMessage.header, m);
|
|
656
1095
|
}
|
|
@@ -662,30 +1101,143 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
662
1101
|
}
|
|
663
1102
|
m = { interactiveMessage };
|
|
664
1103
|
}
|
|
665
|
-
if ('
|
|
666
|
-
|
|
1104
|
+
else if ('collection' in message && !!message.collection) {
|
|
1105
|
+
const interactiveMessage = {
|
|
1106
|
+
collectionMessage: {
|
|
1107
|
+
bizJid: message.collection.bizJid,
|
|
1108
|
+
id: message.collection.id,
|
|
1109
|
+
messageVersion: message?.collection?.version
|
|
1110
|
+
}
|
|
1111
|
+
};
|
|
1112
|
+
if ('text' in message) {
|
|
1113
|
+
interactiveMessage.body = { text: message.text };
|
|
1114
|
+
interactiveMessage.header = {
|
|
1115
|
+
title: message.title,
|
|
1116
|
+
subtitle: message.subtitle,
|
|
1117
|
+
hasMediaAttachment: false
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
else {
|
|
1121
|
+
if ('caption' in message) {
|
|
1122
|
+
interactiveMessage.body = { text: message.caption };
|
|
1123
|
+
interactiveMessage.header = {
|
|
1124
|
+
title: message.title,
|
|
1125
|
+
subtitle: message.subtitle,
|
|
1126
|
+
hasMediaAttachment: message.hasMediaAttachment ? message.hasMediaAttachment : false,
|
|
1127
|
+
...Object.assign(interactiveMessage, m)
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
if ('footer' in message && !!message.footer) {
|
|
1132
|
+
interactiveMessage.footer = { text: message.footer };
|
|
1133
|
+
}
|
|
1134
|
+
interactiveMessage.contextInfo = {
|
|
1135
|
+
...(message.contextInfo || {}),
|
|
1136
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
1137
|
+
};
|
|
1138
|
+
m = { interactiveMessage };
|
|
667
1139
|
}
|
|
668
|
-
if ('
|
|
669
|
-
const
|
|
670
|
-
|
|
671
|
-
|
|
1140
|
+
else if ('cards' in message && !!message.cards) {
|
|
1141
|
+
const slides = await Promise.all(message.cards.map(async (slide) => {
|
|
1142
|
+
const { image, video, product, title, body, footer, buttons } = slide;
|
|
1143
|
+
let header;
|
|
1144
|
+
if (product) {
|
|
1145
|
+
const { imageMessage } = await (0, exports.prepareWAMessageMedia)({ image: product.productImage, ...options }, options);
|
|
1146
|
+
header = {
|
|
1147
|
+
productMessage: {
|
|
1148
|
+
product: {
|
|
1149
|
+
...product,
|
|
1150
|
+
productImage: imageMessage,
|
|
1151
|
+
},
|
|
1152
|
+
...slide
|
|
1153
|
+
}
|
|
1154
|
+
};
|
|
1155
|
+
}
|
|
1156
|
+
else if (image) {
|
|
1157
|
+
header = await (0, exports.prepareWAMessageMedia)({ image: image, ...options }, options);
|
|
1158
|
+
}
|
|
1159
|
+
else if (video) {
|
|
1160
|
+
header = await (0, exports.prepareWAMessageMedia)({ video: video, ...options }, options);
|
|
1161
|
+
}
|
|
1162
|
+
return {
|
|
1163
|
+
header: {
|
|
1164
|
+
title,
|
|
1165
|
+
hasMediaAttachment: true,
|
|
1166
|
+
...header
|
|
1167
|
+
},
|
|
1168
|
+
body: { text: body },
|
|
1169
|
+
footer: { text: footer },
|
|
1170
|
+
nativeFlowMessage: { buttons }
|
|
1171
|
+
};
|
|
1172
|
+
}));
|
|
1173
|
+
const interactiveMessage = {
|
|
1174
|
+
carouselMessage: { cards: slides }
|
|
1175
|
+
};
|
|
1176
|
+
if ('text' in message) {
|
|
1177
|
+
interactiveMessage.body = { text: message.text };
|
|
1178
|
+
interactiveMessage.header = {
|
|
1179
|
+
title: message.title,
|
|
1180
|
+
subtitle: message.subtitle,
|
|
1181
|
+
hasMediaAttachment: false
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
if ('footer' in message && !!message.footer) {
|
|
1185
|
+
interactiveMessage.footer = { text: message.footer };
|
|
1186
|
+
}
|
|
1187
|
+
interactiveMessage.contextInfo = {
|
|
1188
|
+
...(message.contextInfo || {}),
|
|
1189
|
+
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
1190
|
+
};
|
|
1191
|
+
m = { interactiveMessage };
|
|
1192
|
+
}
|
|
1193
|
+
if (hasOptionalProperty(message, 'ephemeral') && !!message.ephemeral) {
|
|
1194
|
+
m = { ephemeralMessage: { message: m } };
|
|
1195
|
+
}
|
|
1196
|
+
if (hasOptionalProperty(message, 'viewOnce') && !!message.viewOnce) {
|
|
1197
|
+
m = { viewOnceMessageV2: { message: m } };
|
|
1198
|
+
}
|
|
1199
|
+
if (hasOptionalProperty(message, 'viewOnceExt') && !!message.viewOnceExt) {
|
|
1200
|
+
m = { viewOnceMessageV2Extension: { message: m } };
|
|
1201
|
+
}
|
|
1202
|
+
if (hasOptionalProperty(message, 'mentions') && message.mentions?.length) {
|
|
1203
|
+
const messageType = Object.keys(m)[0];
|
|
1204
|
+
const key = m[messageType];
|
|
1205
|
+
if ('contextInfo' in key && !!key.contextInfo) {
|
|
1206
|
+
key.contextInfo.mentionedJid = message.mentions;
|
|
1207
|
+
}
|
|
1208
|
+
else if (key) {
|
|
1209
|
+
key.contextInfo = {
|
|
1210
|
+
mentionedJid: message.mentions
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
672
1213
|
}
|
|
673
|
-
if ('edit'
|
|
1214
|
+
if (hasOptionalProperty(message, 'edit')) {
|
|
674
1215
|
m = {
|
|
675
1216
|
protocolMessage: {
|
|
676
1217
|
key: message.edit,
|
|
677
1218
|
editedMessage: m,
|
|
678
1219
|
timestampMs: Date.now(),
|
|
679
|
-
type:
|
|
1220
|
+
type: index_js_3.WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT
|
|
680
1221
|
}
|
|
681
1222
|
};
|
|
682
1223
|
}
|
|
683
|
-
if ('contextInfo'
|
|
684
|
-
const
|
|
685
|
-
|
|
686
|
-
|
|
1224
|
+
if (hasOptionalProperty(message, 'contextInfo') && !!message.contextInfo) {
|
|
1225
|
+
const messageType = Object.keys(m)[0];
|
|
1226
|
+
const key = m[messageType];
|
|
1227
|
+
if ('contextInfo' in key && !!key.contextInfo) {
|
|
1228
|
+
key.contextInfo = { ...key.contextInfo, ...message.contextInfo };
|
|
1229
|
+
}
|
|
1230
|
+
else if (key) {
|
|
1231
|
+
key.contextInfo = message.contextInfo;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
if ((0, reporting_utils_js_1.shouldIncludeReportingToken)(m) && !options.newsletter) {
|
|
1235
|
+
m.messageContextInfo = m.messageContextInfo || {};
|
|
1236
|
+
if (!m.messageContextInfo.messageSecret) {
|
|
1237
|
+
m.messageContextInfo.messageSecret = (0, crypto_1.randomBytes)(32);
|
|
1238
|
+
}
|
|
687
1239
|
}
|
|
688
|
-
return
|
|
1240
|
+
return index_js_3.WAProto.Message.create(m);
|
|
689
1241
|
};
|
|
690
1242
|
exports.generateWAMessageContent = generateWAMessageContent;
|
|
691
1243
|
const generateWAMessageFromContent = (jid, message, options) => {
|
|
@@ -696,68 +1248,72 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
696
1248
|
}
|
|
697
1249
|
const innerMessage = (0, exports.normalizeMessageContent)(message);
|
|
698
1250
|
const key = (0, exports.getContentType)(innerMessage);
|
|
699
|
-
const timestamp = (0,
|
|
1251
|
+
const timestamp = (0, generics_js_1.unixTimestampSeconds)(options.timestamp);
|
|
700
1252
|
const { quoted, userJid } = options;
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
1253
|
+
if (quoted && !(0, index_js_4.isJidNewsletter)(jid)) {
|
|
1254
|
+
const participant = quoted.key.fromMe
|
|
1255
|
+
? userJid // TODO: Add support for LIDs
|
|
1256
|
+
: quoted.participant || quoted.key.participant || quoted.key.remoteJid;
|
|
704
1257
|
let quotedMsg = (0, exports.normalizeMessageContent)(quoted.message);
|
|
705
1258
|
const msgType = (0, exports.getContentType)(quotedMsg);
|
|
706
1259
|
// strip any redundant properties
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
1260
|
+
quotedMsg = index_js_1.proto.Message.create({ [msgType]: quotedMsg[msgType] });
|
|
1261
|
+
const quotedContent = quotedMsg[msgType];
|
|
1262
|
+
if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
|
|
1263
|
+
delete quotedContent.contextInfo;
|
|
1264
|
+
}
|
|
1265
|
+
const contextInfo = ('contextInfo' in innerMessage[key] && innerMessage[key]?.contextInfo) || {};
|
|
1266
|
+
contextInfo.participant = (0, index_js_4.jidNormalizedUser)(participant);
|
|
1267
|
+
contextInfo.stanzaId = quoted.key.id;
|
|
1268
|
+
contextInfo.quotedMessage = quotedMsg;
|
|
1269
|
+
// if a participant is quoted, then it must be a group
|
|
1270
|
+
// hence, remoteJid of group must also be entered
|
|
1271
|
+
if (jid !== quoted.key.remoteJid) {
|
|
1272
|
+
contextInfo.remoteJid = quoted.key.remoteJid;
|
|
1273
|
+
}
|
|
1274
|
+
if (contextInfo && innerMessage[key]) {
|
|
1275
|
+
/* @ts-ignore */
|
|
722
1276
|
innerMessage[key].contextInfo = contextInfo;
|
|
723
1277
|
}
|
|
724
1278
|
}
|
|
725
1279
|
if (
|
|
726
1280
|
// if we want to send a disappearing message
|
|
727
|
-
!!
|
|
1281
|
+
!!options?.ephemeralExpiration &&
|
|
728
1282
|
// and it's not a protocol message -- delete, toggle disappear message
|
|
729
1283
|
key !== 'protocolMessage' &&
|
|
730
1284
|
// already not converted to disappearing message
|
|
731
1285
|
key !== 'ephemeralMessage' &&
|
|
732
|
-
//
|
|
733
|
-
!(0,
|
|
1286
|
+
// newsletters don't support ephemeral messages
|
|
1287
|
+
!(0, index_js_4.isJidNewsletter)(jid)) {
|
|
1288
|
+
/* @ts-ignore */
|
|
734
1289
|
innerMessage[key].contextInfo = {
|
|
735
1290
|
...(innerMessage[key].contextInfo || {}),
|
|
736
|
-
expiration: options.ephemeralExpiration ||
|
|
1291
|
+
expiration: options.ephemeralExpiration || index_js_2.WA_DEFAULT_EPHEMERAL
|
|
737
1292
|
//ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
|
|
738
1293
|
};
|
|
739
1294
|
}
|
|
740
|
-
message =
|
|
1295
|
+
message = index_js_3.WAProto.Message.create(message);
|
|
741
1296
|
const messageJSON = {
|
|
742
1297
|
key: {
|
|
743
1298
|
remoteJid: jid,
|
|
744
1299
|
fromMe: true,
|
|
745
|
-
id:
|
|
1300
|
+
id: options?.messageId || (0, generics_js_1.generateMessageIDV2)()
|
|
746
1301
|
},
|
|
747
1302
|
message: message,
|
|
748
1303
|
messageTimestamp: timestamp,
|
|
749
1304
|
messageStubParameters: [],
|
|
750
|
-
participant: (0,
|
|
751
|
-
status:
|
|
1305
|
+
participant: (0, index_js_4.isJidGroup)(jid) || (0, index_js_4.isJidStatusBroadcast)(jid) ? userJid : undefined, // TODO: Add support for LIDs
|
|
1306
|
+
status: index_js_3.WAMessageStatus.PENDING
|
|
752
1307
|
};
|
|
753
|
-
return
|
|
1308
|
+
return index_js_3.WAProto.WebMessageInfo.fromObject(messageJSON);
|
|
754
1309
|
};
|
|
755
1310
|
exports.generateWAMessageFromContent = generateWAMessageFromContent;
|
|
756
1311
|
const generateWAMessage = async (jid, content, options) => {
|
|
757
|
-
var _a;
|
|
758
1312
|
// ensure msg ID is with every log
|
|
759
|
-
options.logger =
|
|
760
|
-
|
|
1313
|
+
options.logger = options?.logger?.child({ msgId: options.messageId });
|
|
1314
|
+
// Pass jid + newsletter flag to generateWAMessageContent (like wiley)
|
|
1315
|
+
const _isNewsletter = typeof jid === 'string' && jid.endsWith('@newsletter');
|
|
1316
|
+
return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, { newsletter: _isNewsletter, ...options, jid }), options);
|
|
761
1317
|
};
|
|
762
1318
|
exports.generateWAMessage = generateWAMessage;
|
|
763
1319
|
/** Get the key to access the true type of content */
|
|
@@ -769,6 +1325,22 @@ const getContentType = (content) => {
|
|
|
769
1325
|
}
|
|
770
1326
|
};
|
|
771
1327
|
exports.getContentType = getContentType;
|
|
1328
|
+
/**
|
|
1329
|
+
* Maps a message content type key to its MediaType string.
|
|
1330
|
+
* Handles ptvMessage → 'ptv', audioMessage ptt → 'ptt', etc.
|
|
1331
|
+
*/
|
|
1332
|
+
const getMediaTypeFromContentType = (contentType, content) => {
|
|
1333
|
+
if (!contentType)
|
|
1334
|
+
return undefined;
|
|
1335
|
+
if (contentType === 'ptvMessage')
|
|
1336
|
+
return 'ptv';
|
|
1337
|
+
if (contentType === 'audioMessage' && content?.[contentType]?.ptt)
|
|
1338
|
+
return 'ptt';
|
|
1339
|
+
if (contentType === 'videoMessage' && content?.[contentType]?.gifPlayback)
|
|
1340
|
+
return 'gif';
|
|
1341
|
+
return contentType.replace('Message', '');
|
|
1342
|
+
};
|
|
1343
|
+
exports.getMediaTypeFromContentType = getMediaTypeFromContentType;
|
|
772
1344
|
/**
|
|
773
1345
|
* Normalizes ephemeral, view once messages to regular message content
|
|
774
1346
|
* Eg. image messages in ephemeral messages, in view once messages etc.
|
|
@@ -789,29 +1361,15 @@ const normalizeMessageContent = (content) => {
|
|
|
789
1361
|
}
|
|
790
1362
|
return content;
|
|
791
1363
|
function getFutureProofMessage(message) {
|
|
792
|
-
return (
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|| (message === null || message === void 0 ? void 0 : message.eventCoverImage)
|
|
802
|
-
|| (message === null || message === void 0 ? void 0 : message.statusMentionMessage)
|
|
803
|
-
|| (message === null || message === void 0 ? void 0 : message.pollCreationOptionImageMessage)
|
|
804
|
-
|| (message === null || message === void 0 ? void 0 : message.associatedChildMessage)
|
|
805
|
-
|| (message === null || message === void 0 ? void 0 : message.groupStatusMentionMessage)
|
|
806
|
-
|| (message === null || message === void 0 ? void 0 : message.pollCreationMessageV4)
|
|
807
|
-
|| (message === null || message === void 0 ? void 0 : message.pollCreationMessageV5)
|
|
808
|
-
|| (message === null || message === void 0 ? void 0 : message.statusAddYours)
|
|
809
|
-
|| (message === null || message === void 0 ? void 0 : message.groupStatusMessage)
|
|
810
|
-
|| (message === null || message === void 0 ? void 0 : message.limitSharingMessage)
|
|
811
|
-
|| (message === null || message === void 0 ? void 0 : message.botTaskMessage)
|
|
812
|
-
|| (message === null || message === void 0 ? void 0 : message.questionMessage)
|
|
813
|
-
|| (message === null || message === void 0 ? void 0 : message.groupStatusMessageV2)
|
|
814
|
-
|| (message === null || message === void 0 ? void 0 : message.botForwardedMessage));
|
|
1364
|
+
return (message?.ephemeralMessage ||
|
|
1365
|
+
message?.viewOnceMessage ||
|
|
1366
|
+
message?.documentWithCaptionMessage ||
|
|
1367
|
+
message?.viewOnceMessageV2 ||
|
|
1368
|
+
message?.viewOnceMessageV2Extension ||
|
|
1369
|
+
message?.editedMessage ||
|
|
1370
|
+
message?.associatedChildMessage ||
|
|
1371
|
+
message?.groupStatusMessage ||
|
|
1372
|
+
message?.groupStatusMessageV2);
|
|
815
1373
|
}
|
|
816
1374
|
};
|
|
817
1375
|
exports.normalizeMessageContent = normalizeMessageContent;
|
|
@@ -820,7 +1378,6 @@ exports.normalizeMessageContent = normalizeMessageContent;
|
|
|
820
1378
|
* Eg. extracts the inner message from a disappearing message/view once message
|
|
821
1379
|
*/
|
|
822
1380
|
const extractMessageContent = (content) => {
|
|
823
|
-
var _a, _b, _c, _d, _e, _f;
|
|
824
1381
|
const extractFromTemplateMessage = (msg) => {
|
|
825
1382
|
if (msg.imageMessage) {
|
|
826
1383
|
return { imageMessage: msg.imageMessage };
|
|
@@ -836,24 +1393,22 @@ const extractMessageContent = (content) => {
|
|
|
836
1393
|
}
|
|
837
1394
|
else {
|
|
838
1395
|
return {
|
|
839
|
-
conversation: 'contentText' in msg
|
|
840
|
-
? msg.contentText
|
|
841
|
-
: ('hydratedContentText' in msg ? msg.hydratedContentText : '')
|
|
1396
|
+
conversation: 'contentText' in msg ? msg.contentText : 'hydratedContentText' in msg ? msg.hydratedContentText : ''
|
|
842
1397
|
};
|
|
843
1398
|
}
|
|
844
1399
|
};
|
|
845
1400
|
content = (0, exports.normalizeMessageContent)(content);
|
|
846
|
-
if (content
|
|
1401
|
+
if (content?.buttonsMessage) {
|
|
847
1402
|
return extractFromTemplateMessage(content.buttonsMessage);
|
|
848
1403
|
}
|
|
849
|
-
if (
|
|
850
|
-
return extractFromTemplateMessage(
|
|
1404
|
+
if (content?.templateMessage?.hydratedFourRowTemplate) {
|
|
1405
|
+
return extractFromTemplateMessage(content?.templateMessage?.hydratedFourRowTemplate);
|
|
851
1406
|
}
|
|
852
|
-
if (
|
|
853
|
-
return extractFromTemplateMessage(
|
|
1407
|
+
if (content?.templateMessage?.hydratedTemplate) {
|
|
1408
|
+
return extractFromTemplateMessage(content?.templateMessage?.hydratedTemplate);
|
|
854
1409
|
}
|
|
855
|
-
if (
|
|
856
|
-
return extractFromTemplateMessage(
|
|
1410
|
+
if (content?.templateMessage?.fourRowTemplate) {
|
|
1411
|
+
return extractFromTemplateMessage(content?.templateMessage?.fourRowTemplate);
|
|
857
1412
|
}
|
|
858
1413
|
return content;
|
|
859
1414
|
};
|
|
@@ -861,11 +1416,15 @@ exports.extractMessageContent = extractMessageContent;
|
|
|
861
1416
|
/**
|
|
862
1417
|
* Returns the device predicted by message ID
|
|
863
1418
|
*/
|
|
864
|
-
const getDevice = (id) => /^3A.{18}$/.test(id)
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
1419
|
+
const getDevice = (id) => /^3A.{18}$/.test(id)
|
|
1420
|
+
? 'ios'
|
|
1421
|
+
: /^3E.{20}$/.test(id)
|
|
1422
|
+
? 'web'
|
|
1423
|
+
: /^(.{21}|.{32})$/.test(id)
|
|
1424
|
+
? 'android'
|
|
1425
|
+
: /^(3F|.{18}$)/.test(id)
|
|
1426
|
+
? 'desktop'
|
|
1427
|
+
: 'unknown';
|
|
869
1428
|
exports.getDevice = getDevice;
|
|
870
1429
|
/** Upserts a receipt in the message */
|
|
871
1430
|
const updateMessageWithReceipt = (msg, receipt) => {
|
|
@@ -881,9 +1440,8 @@ const updateMessageWithReceipt = (msg, receipt) => {
|
|
|
881
1440
|
exports.updateMessageWithReceipt = updateMessageWithReceipt;
|
|
882
1441
|
/** Update the message with a new reaction */
|
|
883
1442
|
const updateMessageWithReaction = (msg, reaction) => {
|
|
884
|
-
const authorID = (0,
|
|
885
|
-
const reactions = (msg.reactions || [])
|
|
886
|
-
.filter(r => (0, generics_1.getKeyAuthor)(r.key) !== authorID);
|
|
1443
|
+
const authorID = (0, generics_js_1.getKeyAuthor)(reaction.key);
|
|
1444
|
+
const reactions = (msg.reactions || []).filter(r => (0, generics_js_1.getKeyAuthor)(r.key) !== authorID);
|
|
887
1445
|
reaction.text = reaction.text || '';
|
|
888
1446
|
reactions.push(reaction);
|
|
889
1447
|
msg.reactions = reactions;
|
|
@@ -891,16 +1449,22 @@ const updateMessageWithReaction = (msg, reaction) => {
|
|
|
891
1449
|
exports.updateMessageWithReaction = updateMessageWithReaction;
|
|
892
1450
|
/** Update the message with a new poll update */
|
|
893
1451
|
const updateMessageWithPollUpdate = (msg, update) => {
|
|
894
|
-
|
|
895
|
-
const
|
|
896
|
-
|
|
897
|
-
.filter(r => (0, generics_1.getKeyAuthor)(r.pollUpdateMessageKey) !== authorID);
|
|
898
|
-
if ((_b = (_a = update.vote) === null || _a === void 0 ? void 0 : _a.selectedOptions) === null || _b === void 0 ? void 0 : _b.length) {
|
|
1452
|
+
const authorID = (0, generics_js_1.getKeyAuthor)(update.pollUpdateMessageKey);
|
|
1453
|
+
const reactions = (msg.pollUpdates || []).filter(r => (0, generics_js_1.getKeyAuthor)(r.pollUpdateMessageKey) !== authorID);
|
|
1454
|
+
if (update.vote?.selectedOptions?.length) {
|
|
899
1455
|
reactions.push(update);
|
|
900
1456
|
}
|
|
901
1457
|
msg.pollUpdates = reactions;
|
|
902
1458
|
};
|
|
903
1459
|
exports.updateMessageWithPollUpdate = updateMessageWithPollUpdate;
|
|
1460
|
+
/** Update the message with a new event response */
|
|
1461
|
+
const updateMessageWithEventResponse = (msg, update) => {
|
|
1462
|
+
const authorID = (0, generics_js_1.getKeyAuthor)(update.eventResponseMessageKey);
|
|
1463
|
+
const responses = (msg.eventResponses || []).filter(r => (0, generics_js_1.getKeyAuthor)(r.eventResponseMessageKey) !== authorID);
|
|
1464
|
+
responses.push(update);
|
|
1465
|
+
msg.eventResponses = responses;
|
|
1466
|
+
};
|
|
1467
|
+
exports.updateMessageWithEventResponse = updateMessageWithEventResponse;
|
|
904
1468
|
/**
|
|
905
1469
|
* Aggregates all poll updates in a poll.
|
|
906
1470
|
* @param msg the poll creation message
|
|
@@ -908,10 +1472,12 @@ exports.updateMessageWithPollUpdate = updateMessageWithPollUpdate;
|
|
|
908
1472
|
* @returns A list of options & their voters
|
|
909
1473
|
*/
|
|
910
1474
|
function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
911
|
-
|
|
912
|
-
|
|
1475
|
+
const opts = message?.pollCreationMessage?.options ||
|
|
1476
|
+
message?.pollCreationMessageV2?.options ||
|
|
1477
|
+
message?.pollCreationMessageV3?.options ||
|
|
1478
|
+
[];
|
|
913
1479
|
const voteHashMap = opts.reduce((acc, opt) => {
|
|
914
|
-
const hash = (0,
|
|
1480
|
+
const hash = (0, crypto_js_1.sha256)(Buffer.from(opt.optionName || '')).toString();
|
|
915
1481
|
acc[hash] = {
|
|
916
1482
|
name: opt.optionName || '',
|
|
917
1483
|
voters: []
|
|
@@ -933,11 +1499,34 @@ function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
|
933
1499
|
};
|
|
934
1500
|
data = voteHashMap[hash];
|
|
935
1501
|
}
|
|
936
|
-
voteHashMap[hash].voters.push((0,
|
|
1502
|
+
voteHashMap[hash].voters.push((0, generics_js_1.getKeyAuthor)(update.pollUpdateMessageKey, meId));
|
|
937
1503
|
}
|
|
938
1504
|
}
|
|
939
1505
|
return Object.values(voteHashMap);
|
|
940
1506
|
}
|
|
1507
|
+
/**
|
|
1508
|
+
* Aggregates all event responses in an event message.
|
|
1509
|
+
* @param msg the event creation message
|
|
1510
|
+
* @param meId your jid
|
|
1511
|
+
* @returns A list of response types & their responders
|
|
1512
|
+
*/
|
|
1513
|
+
function getAggregateResponsesInEventMessage({ eventResponses }, meId) {
|
|
1514
|
+
const responseTypes = ['GOING', 'NOT_GOING', 'MAYBE'];
|
|
1515
|
+
const responseMap = {};
|
|
1516
|
+
for (const type of responseTypes) {
|
|
1517
|
+
responseMap[type] = {
|
|
1518
|
+
response: type,
|
|
1519
|
+
responders: []
|
|
1520
|
+
};
|
|
1521
|
+
}
|
|
1522
|
+
for (const update of eventResponses || []) {
|
|
1523
|
+
const responseType = update.eventResponse || 'UNKNOWN';
|
|
1524
|
+
if (responseType !== 'UNKNOWN' && responseMap[responseType]) {
|
|
1525
|
+
responseMap[responseType].responders.push((0, generics_js_1.getKeyAuthor)(update.eventResponseMessageKey, meId));
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
return Object.values(responseMap);
|
|
1529
|
+
}
|
|
941
1530
|
/** Given a list of message keys, aggregates them by chat & sender. Useful for sending read receipts in bulk */
|
|
942
1531
|
const aggregateMessageKeysNotFromMe = (keys) => {
|
|
943
1532
|
const keyMap = {};
|
|
@@ -962,20 +1551,15 @@ const REUPLOAD_REQUIRED_STATUS = [410, 404];
|
|
|
962
1551
|
* Downloads the given message. Throws an error if it's not a media message
|
|
963
1552
|
*/
|
|
964
1553
|
const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
965
|
-
const result = await downloadMsg()
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
message = await ctx.reuploadRequest(message);
|
|
975
|
-
const result = await downloadMsg();
|
|
976
|
-
return result;
|
|
977
|
-
}
|
|
978
|
-
}
|
|
1554
|
+
const result = await downloadMsg().catch(async (error) => {
|
|
1555
|
+
if (ctx &&
|
|
1556
|
+
typeof error?.status === 'number' && // treat errors with status as HTTP failures requiring reupload
|
|
1557
|
+
REUPLOAD_REQUIRED_STATUS.includes(error.status)) {
|
|
1558
|
+
ctx.logger.info({ key: message.key }, 'sending reupload media request...');
|
|
1559
|
+
// request reupload
|
|
1560
|
+
message = await ctx.reuploadRequest(message);
|
|
1561
|
+
const result = await downloadMsg();
|
|
1562
|
+
return result;
|
|
979
1563
|
}
|
|
980
1564
|
throw error;
|
|
981
1565
|
});
|
|
@@ -986,7 +1570,7 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
|
986
1570
|
throw new boom_1.Boom('No message present', { statusCode: 400, data: message });
|
|
987
1571
|
}
|
|
988
1572
|
const contentType = (0, exports.getContentType)(mContent);
|
|
989
|
-
let mediaType =
|
|
1573
|
+
let mediaType = (0, exports.getMediaTypeFromContentType)(contentType, mContent);
|
|
990
1574
|
const media = mContent[contentType];
|
|
991
1575
|
if (!media || typeof media !== 'object' || (!('url' in media) && !('thumbnailDirectPath' in media))) {
|
|
992
1576
|
throw new boom_1.Boom(`"${contentType}" message is not a media message`);
|
|
@@ -1002,7 +1586,7 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
|
1002
1586
|
else {
|
|
1003
1587
|
download = media;
|
|
1004
1588
|
}
|
|
1005
|
-
const stream = await (0,
|
|
1589
|
+
const stream = await (0, messages_media_js_1.downloadContentFromMessage)(download, mediaType, options);
|
|
1006
1590
|
if (type === 'buffer') {
|
|
1007
1591
|
const bufferArray = [];
|
|
1008
1592
|
for await (const chunk of stream) {
|
|
@@ -1017,33 +1601,148 @@ exports.downloadMediaMessage = downloadMediaMessage;
|
|
|
1017
1601
|
/** Checks whether the given message is a media message; if it is returns the inner content */
|
|
1018
1602
|
const assertMediaContent = (content) => {
|
|
1019
1603
|
content = (0, exports.extractMessageContent)(content);
|
|
1020
|
-
const mediaContent =
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1604
|
+
const mediaContent = content?.documentMessage ||
|
|
1605
|
+
content?.imageMessage ||
|
|
1606
|
+
content?.videoMessage ||
|
|
1607
|
+
content?.audioMessage ||
|
|
1608
|
+
content?.stickerMessage;
|
|
1025
1609
|
if (!mediaContent) {
|
|
1026
1610
|
throw new boom_1.Boom('given message is not a media message', { statusCode: 400, data: content });
|
|
1027
1611
|
}
|
|
1028
1612
|
return mediaContent;
|
|
1029
1613
|
};
|
|
1030
1614
|
exports.assertMediaContent = assertMediaContent;
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1615
|
+
const patchMessageForMdIfRequired = (message) => {
|
|
1616
|
+
if (message?.buttonsMessage ||
|
|
1617
|
+
message?.templateMessage ||
|
|
1618
|
+
message?.listMessage ||
|
|
1619
|
+
message?.interactiveMessage?.nativeFlowMessage) {
|
|
1620
|
+
message = {
|
|
1621
|
+
viewOnceMessageV2Extension: {
|
|
1622
|
+
message: {
|
|
1623
|
+
messageContextInfo: {
|
|
1624
|
+
deviceListMetadataVersion: 2,
|
|
1625
|
+
deviceListMetadata: {}
|
|
1626
|
+
},
|
|
1627
|
+
...message
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
};
|
|
1631
|
+
}
|
|
1632
|
+
return message;
|
|
1040
1633
|
};
|
|
1041
|
-
exports.
|
|
1042
|
-
const
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
const
|
|
1046
|
-
|
|
1047
|
-
|
|
1634
|
+
exports.patchMessageForMdIfRequired = patchMessageForMdIfRequired;
|
|
1635
|
+
const prepareAlbumMessageContent = async (jid, albums, options) => {
|
|
1636
|
+
let mediaHandle;
|
|
1637
|
+
let mediaMsg;
|
|
1638
|
+
const message = [];
|
|
1639
|
+
const albumMsg = (0, exports.generateWAMessageFromContent)(jid, {
|
|
1640
|
+
albumMessage: {
|
|
1641
|
+
expectedImageCount: albums.filter(item => 'image' in item).length,
|
|
1642
|
+
expectedVideoCount: albums.filter(item => 'video' in item).length
|
|
1643
|
+
}
|
|
1644
|
+
}, options);
|
|
1645
|
+
await options.sock.relayMessage(jid, albumMsg.message, { messageId: albumMsg.key.id });
|
|
1646
|
+
for (const i in albums) {
|
|
1647
|
+
const media = albums[i];
|
|
1648
|
+
if ('image' in media) {
|
|
1649
|
+
mediaMsg = await (0, exports.generateWAMessage)(jid, { image: media.image, ...media, ...options }, {
|
|
1650
|
+
userJid: options.userJid,
|
|
1651
|
+
upload: async (encFilePath, opts) => {
|
|
1652
|
+
const up = await options.sock.waUploadToServer(encFilePath, { ...opts, newsletter: (0, index_js_4.isJidNewsletter)(jid) });
|
|
1653
|
+
mediaHandle = up.handle;
|
|
1654
|
+
return up;
|
|
1655
|
+
},
|
|
1656
|
+
...options
|
|
1657
|
+
});
|
|
1658
|
+
}
|
|
1659
|
+
else if ('video' in media) {
|
|
1660
|
+
mediaMsg = await (0, exports.generateWAMessage)(jid, { video: media.video, ...media, ...options }, {
|
|
1661
|
+
userJid: options.userJid,
|
|
1662
|
+
upload: async (encFilePath, opts) => {
|
|
1663
|
+
const up = await options.sock.waUploadToServer(encFilePath, { ...opts, newsletter: (0, index_js_4.isJidNewsletter)(jid) });
|
|
1664
|
+
mediaHandle = up.handle;
|
|
1665
|
+
return up;
|
|
1666
|
+
},
|
|
1667
|
+
...options
|
|
1668
|
+
});
|
|
1669
|
+
}
|
|
1670
|
+
if (mediaMsg) {
|
|
1671
|
+
mediaMsg.message.messageContextInfo = {
|
|
1672
|
+
messageSecret: (0, crypto_1.randomBytes)(32),
|
|
1673
|
+
messageAssociation: {
|
|
1674
|
+
associationType: 1,
|
|
1675
|
+
parentMessageKey: albumMsg.key
|
|
1676
|
+
}
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
message.push(mediaMsg);
|
|
1680
|
+
}
|
|
1681
|
+
return message;
|
|
1682
|
+
};
|
|
1683
|
+
exports.prepareAlbumMessageContent = prepareAlbumMessageContent;
|
|
1684
|
+
/**
|
|
1685
|
+
* Ekstrak quoted message dari contextInfo pesan.
|
|
1686
|
+
* Return object yang sudah dinormalisasi, termasuk debug info LID/PN.
|
|
1687
|
+
*
|
|
1688
|
+
* @param {object} msg - WAMessage object dari event messages.upsert
|
|
1689
|
+
* @param {object} [options]
|
|
1690
|
+
* @param {boolean} [options.debug] - jika true, log info ke console
|
|
1691
|
+
* @returns {object|null} quoted message info atau null jika tidak ada
|
|
1692
|
+
*/
|
|
1693
|
+
const getQuotedMsg = (msg, options = {}) => {
|
|
1694
|
+
const { debug = false } = options;
|
|
1695
|
+
const msgContent = (0, exports.normalizeMessageContent)(msg?.message);
|
|
1696
|
+
if (!msgContent)
|
|
1697
|
+
return null;
|
|
1698
|
+
const msgType = (0, exports.getContentType)(msgContent);
|
|
1699
|
+
if (!msgType)
|
|
1700
|
+
return null;
|
|
1701
|
+
const innerMsg = msgContent[msgType];
|
|
1702
|
+
if (!innerMsg)
|
|
1703
|
+
return null;
|
|
1704
|
+
const contextInfo = innerMsg.contextInfo;
|
|
1705
|
+
if (!contextInfo?.stanzaId || !contextInfo?.quotedMessage)
|
|
1706
|
+
return null;
|
|
1707
|
+
// Normalisasi participant (sender quoted message)
|
|
1708
|
+
const participant = contextInfo.participant || msg.key?.participant || msg.key?.remoteJid || '';
|
|
1709
|
+
// Normalisasi mentionedJid di quoted message
|
|
1710
|
+
const quotedMsgContent = (0, exports.normalizeMessageContent)(contextInfo.quotedMessage);
|
|
1711
|
+
const quotedMsgType = (0, exports.getContentType)(quotedMsgContent);
|
|
1712
|
+
const quotedInnerMsg = quotedMsgType ? quotedMsgContent?.[quotedMsgType] : null;
|
|
1713
|
+
const quotedMentionedJid = quotedInnerMsg?.contextInfo?.mentionedJid || [];
|
|
1714
|
+
const quotedText = quotedInnerMsg?.text || quotedInnerMsg?.caption || quotedInnerMsg?.conversation || '';
|
|
1715
|
+
const result = {
|
|
1716
|
+
key: {
|
|
1717
|
+
id: contextInfo.stanzaId,
|
|
1718
|
+
remoteJid: contextInfo.remoteJid || msg.key?.remoteJid || '',
|
|
1719
|
+
participant: participant,
|
|
1720
|
+
fromMe: false
|
|
1721
|
+
},
|
|
1722
|
+
message: contextInfo.quotedMessage,
|
|
1723
|
+
participant,
|
|
1724
|
+
sender: participant,
|
|
1725
|
+
text: quotedText,
|
|
1726
|
+
type: quotedMsgType || '',
|
|
1727
|
+
mentionedJid: quotedMentionedJid,
|
|
1728
|
+
// Debug info
|
|
1729
|
+
_rawContextInfo: debug ? contextInfo : undefined
|
|
1730
|
+
};
|
|
1731
|
+
if (debug) {
|
|
1732
|
+
const hasLidInText = typeof quotedText === 'string' && /@\d{13,20}/.test(quotedText);
|
|
1733
|
+
const hasLidInMentioned = quotedMentionedJid.some(j => j?.endsWith('@lid'));
|
|
1734
|
+
const hasLidParticipant = participant?.endsWith('@lid');
|
|
1735
|
+
console.log('[getQuotedMsg DEBUG]', JSON.stringify({
|
|
1736
|
+
stanzaId: contextInfo.stanzaId,
|
|
1737
|
+
participant,
|
|
1738
|
+
participantIsLid: hasLidParticipant,
|
|
1739
|
+
quotedText,
|
|
1740
|
+
textHasLid: hasLidInText,
|
|
1741
|
+
mentionedJid: quotedMentionedJid,
|
|
1742
|
+
mentionedHasLid: hasLidInMentioned,
|
|
1743
|
+
quotedMsgType
|
|
1744
|
+
}, null, 2));
|
|
1745
|
+
}
|
|
1746
|
+
return result;
|
|
1048
1747
|
};
|
|
1049
|
-
exports.
|
|
1748
|
+
exports.getQuotedMsg = getQuotedMsg;
|