@ubedsockets/baileys 1.6.4 → 1.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Socket/Client/index.d.ts +3 -0
- package/lib/Socket/Client/index.d.ts.map +1 -0
- package/lib/Socket/Client/index.js +3 -18
- package/lib/Socket/Client/index.js.map +1 -0
- package/lib/Socket/Client/types.d.ts +16 -0
- package/lib/Socket/Client/types.d.ts.map +1 -0
- package/lib/Socket/Client/types.js +4 -6
- package/lib/Socket/Client/types.js.map +1 -0
- package/lib/Socket/Client/websocket.d.ts +13 -0
- package/lib/Socket/Client/websocket.d.ts.map +1 -0
- package/lib/Socket/Client/websocket.js +21 -78
- package/lib/Socket/Client/websocket.js.map +1 -0
- package/lib/Socket/business.d.ts +217 -0
- package/lib/Socket/business.d.ts.map +1 -0
- package/lib/Socket/business.js +162 -43
- package/lib/Socket/business.js.map +1 -0
- package/lib/Socket/chats.d.ts +124 -0
- package/lib/Socket/chats.d.ts.map +1 -0
- package/lib/Socket/chats.js +571 -249
- package/lib/Socket/chats.js.map +1 -0
- package/lib/Socket/communities.d.ts +273 -0
- package/lib/Socket/communities.d.ts.map +1 -0
- package/lib/Socket/communities.js +431 -0
- package/lib/Socket/communities.js.map +1 -0
- package/lib/Socket/groups.d.ts +161 -0
- package/lib/Socket/groups.d.ts.map +1 -0
- package/lib/Socket/groups.js +114 -99
- package/lib/Socket/groups.js.map +1 -0
- package/lib/Socket/index.d.ts +260 -0
- package/lib/Socket/index.d.ts.map +1 -0
- package/lib/Socket/index.js +11 -9
- package/lib/Socket/index.js.map +1 -0
- package/lib/Socket/messages-recv.d.ts +203 -0
- package/lib/Socket/messages-recv.d.ts.map +1 -0
- package/lib/Socket/messages-recv.js +1277 -559
- package/lib/Socket/messages-recv.js.map +1 -0
- package/lib/Socket/messages-send.d.ts +199 -0
- package/lib/Socket/messages-send.d.ts.map +1 -0
- package/lib/Socket/messages-send.js +674 -669
- package/lib/Socket/messages-send.js.map +1 -0
- package/lib/Socket/mex.d.ts +3 -0
- package/lib/Socket/mex.d.ts.map +1 -0
- package/lib/Socket/mex.js +42 -0
- package/lib/Socket/mex.js.map +1 -0
- package/lib/Socket/newsletter.d.ts +170 -0
- package/lib/Socket/newsletter.d.ts.map +1 -0
- package/lib/Socket/newsletter.js +149 -286
- package/lib/Socket/newsletter.js.map +1 -0
- package/lib/Socket/socket.d.ts +59 -0
- package/lib/Socket/socket.d.ts.map +1 -0
- package/lib/Socket/socket.js.map +1 -0
- package/lib/Utils/auth-utils.d.ts +24 -0
- package/lib/Utils/auth-utils.d.ts.map +1 -0
- package/lib/Utils/auth-utils.js +239 -136
- package/lib/Utils/auth-utils.js.map +1 -0
- package/lib/Utils/browser-utils.d.ts +4 -0
- package/lib/Utils/browser-utils.d.ts.map +1 -0
- package/lib/Utils/browser-utils.js +28 -0
- package/lib/Utils/browser-utils.js.map +1 -0
- package/lib/Utils/business.d.ts +23 -0
- package/lib/Utils/business.d.ts.map +1 -0
- package/lib/Utils/business.js +66 -69
- package/lib/Utils/business.js.map +1 -0
- package/lib/Utils/chat-utils.d.ts +100 -0
- package/lib/Utils/chat-utils.d.ts.map +1 -0
- package/lib/Utils/chat-utils.js +380 -238
- package/lib/Utils/chat-utils.js.map +1 -0
- package/lib/Utils/companion-reg-client-utils.d.ts +17 -0
- package/lib/Utils/companion-reg-client-utils.d.ts.map +1 -0
- package/lib/Utils/companion-reg-client-utils.js +35 -0
- package/lib/Utils/companion-reg-client-utils.js.map +1 -0
- package/lib/Utils/crypto.d.ts +37 -0
- package/lib/Utils/crypto.d.ts.map +1 -0
- package/lib/Utils/crypto.js +56 -127
- package/lib/Utils/crypto.js.map +1 -0
- package/lib/Utils/decode-wa-message.d.ts +66 -0
- package/lib/Utils/decode-wa-message.d.ts.map +1 -0
- package/lib/Utils/decode-wa-message.js +173 -63
- package/lib/Utils/decode-wa-message.js.map +1 -0
- package/lib/Utils/event-buffer.d.ts +36 -0
- package/lib/Utils/event-buffer.d.ts.map +1 -0
- package/lib/Utils/event-buffer.js +174 -70
- package/lib/Utils/event-buffer.js.map +1 -0
- package/lib/Utils/generics.d.ts +91 -0
- package/lib/Utils/generics.d.ts.map +1 -0
- package/lib/Utils/generics.js +159 -207
- package/lib/Utils/generics.js.map +1 -0
- package/lib/Utils/history.d.ts +24 -0
- package/lib/Utils/history.d.ts.map +1 -0
- package/lib/Utils/history.js +93 -53
- package/lib/Utils/history.js.map +1 -0
- package/lib/Utils/identity-change-handler.d.ts +44 -0
- package/lib/Utils/identity-change-handler.d.ts.map +1 -0
- package/lib/Utils/identity-change-handler.js +50 -0
- package/lib/Utils/identity-change-handler.js.map +1 -0
- package/lib/Utils/index.d.ts +22 -0
- package/lib/Utils/index.d.ts.map +1 -0
- package/lib/Utils/index.js +22 -33
- package/lib/Utils/index.js.map +1 -0
- package/lib/Utils/link-preview.d.ts +21 -0
- package/lib/Utils/link-preview.d.ts.map +1 -0
- package/lib/Utils/link-preview.js +17 -58
- package/lib/Utils/link-preview.js.map +1 -0
- package/lib/Utils/logger.d.ts +12 -0
- package/lib/Utils/logger.d.ts.map +1 -0
- package/lib/Utils/logger.js +3 -7
- package/lib/Utils/logger.js.map +1 -0
- package/lib/Utils/lt-hash.d.ts +8 -0
- package/lib/Utils/lt-hash.d.ts.map +1 -0
- package/lib/Utils/lt-hash.js +3 -46
- package/lib/Utils/lt-hash.js.map +1 -0
- package/lib/Utils/make-mutex.d.ts +9 -0
- package/lib/Utils/make-mutex.d.ts.map +1 -0
- package/lib/Utils/make-mutex.js +24 -34
- package/lib/Utils/make-mutex.js.map +1 -0
- package/lib/Utils/message-retry-manager.d.ts +115 -0
- package/lib/Utils/message-retry-manager.d.ts.map +1 -0
- package/lib/Utils/message-retry-manager.js +265 -0
- package/lib/Utils/message-retry-manager.js.map +1 -0
- package/lib/Utils/messages-media.d.ts +133 -0
- package/lib/Utils/messages-media.d.ts.map +1 -0
- package/lib/Utils/messages-media.js +483 -744
- package/lib/Utils/messages-media.js.map +1 -0
- package/lib/Utils/messages.d.ts +91 -0
- package/lib/Utils/messages.d.ts.map +1 -0
- package/lib/Utils/messages.js +411 -621
- package/lib/Utils/messages.js.map +1 -0
- package/lib/Utils/noise-handler.d.ts +20 -0
- package/lib/Utils/noise-handler.d.ts.map +1 -0
- package/lib/Utils/noise-handler.js +149 -99
- package/lib/Utils/noise-handler.js.map +1 -0
- package/lib/Utils/offline-node-processor.d.ts +17 -0
- package/lib/Utils/offline-node-processor.d.ts.map +1 -0
- package/lib/Utils/offline-node-processor.js +40 -0
- package/lib/Utils/offline-node-processor.js.map +1 -0
- package/lib/Utils/pre-key-manager.d.ts +28 -0
- package/lib/Utils/pre-key-manager.d.ts.map +1 -0
- package/lib/Utils/pre-key-manager.js +106 -0
- package/lib/Utils/pre-key-manager.js.map +1 -0
- package/lib/Utils/process-message.d.ts +60 -0
- package/lib/Utils/process-message.d.ts.map +1 -0
- package/lib/Utils/process-message.js +459 -150
- package/lib/Utils/process-message.js.map +1 -0
- package/lib/Utils/reporting-utils.d.ts +11 -0
- package/lib/Utils/reporting-utils.d.ts.map +1 -0
- package/lib/Utils/reporting-utils.js +258 -0
- package/lib/Utils/reporting-utils.js.map +1 -0
- package/lib/Utils/signal.d.ts +47 -0
- package/lib/Utils/signal.d.ts.map +1 -0
- package/lib/Utils/signal.js +112 -73
- package/lib/Utils/signal.js.map +1 -0
- package/lib/Utils/stanza-ack.d.ts +11 -0
- package/lib/Utils/stanza-ack.d.ts.map +1 -0
- package/lib/Utils/stanza-ack.js +38 -0
- package/lib/Utils/stanza-ack.js.map +1 -0
- package/lib/Utils/sync-action-utils.d.ts +19 -0
- package/lib/Utils/sync-action-utils.d.ts.map +1 -0
- package/lib/Utils/sync-action-utils.js +49 -0
- package/lib/Utils/sync-action-utils.js.map +1 -0
- package/lib/Utils/tc-token-utils.d.ts +37 -0
- package/lib/Utils/tc-token-utils.d.ts.map +1 -0
- package/lib/Utils/tc-token-utils.js +163 -0
- package/lib/Utils/tc-token-utils.js.map +1 -0
- package/lib/Utils/use-multi-file-auth-state.d.ts +13 -0
- package/lib/Utils/use-multi-file-auth-state.d.ts.map +1 -0
- package/lib/Utils/use-multi-file-auth-state.js +23 -27
- package/lib/Utils/use-multi-file-auth-state.js.map +1 -0
- package/lib/Utils/validate-connection.d.ts +11 -0
- package/lib/Utils/validate-connection.d.ts.map +1 -0
- package/lib/Utils/validate-connection.js +74 -104
- package/lib/Utils/validate-connection.js.map +1 -0
- package/package.json +1 -1
package/lib/Utils/messages.js
CHANGED
|
@@ -1,75 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
exports.extractMessageContent =
|
|
14
|
-
exports.normalizeMessageContent =
|
|
15
|
-
exports.getContentType =
|
|
16
|
-
exports.generateWAMessage =
|
|
17
|
-
exports.generateWAMessageFromContent =
|
|
18
|
-
exports.generateWAMessageContent =
|
|
19
|
-
exports.generateForwardMessageContent =
|
|
20
|
-
exports.prepareDisappearingMessageSettingContent =
|
|
21
|
-
exports.prepareWAMessageMedia =
|
|
22
|
-
exports.generateLinkPreviewIfRequired =
|
|
23
|
-
exports.extractUrlFromText = void 0;
|
|
24
|
-
exports.getAggregateVotesInPollMessage = getAggregateVotesInPollMessage;
|
|
25
|
-
|
|
26
|
-
const boom_1 = require("@hapi/boom");
|
|
27
|
-
const axios_1 = __importDefault(require("axios"));
|
|
28
|
-
const crypto_1 = require("crypto");
|
|
29
|
-
const fs_1 = require("fs");
|
|
30
|
-
const WAProto_1 = require("../../WAProto");
|
|
31
|
-
const Defaults_1 = require("../Defaults");
|
|
32
|
-
const Types_1 = require("../Types");
|
|
33
|
-
const WABinary_1 = require("../WABinary");
|
|
34
|
-
const crypto_2 = require("./crypto");
|
|
35
|
-
const generics_1 = require("./generics");
|
|
36
|
-
const messages_media_1 = require("./messages-media");
|
|
1
|
+
import { Boom } from '@hapi/boom';
|
|
2
|
+
import { randomBytes } from 'crypto';
|
|
3
|
+
import { promises as fs } from 'fs';
|
|
4
|
+
import {} from 'stream';
|
|
5
|
+
import { proto } from '../../WAProto/index.js';
|
|
6
|
+
import { CALL_AUDIO_PREFIX, CALL_VIDEO_PREFIX, MEDIA_KEYS, URL_REGEX, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
|
|
7
|
+
import { WAMessageStatus, WAProto } from '../Types/index.js';
|
|
8
|
+
import { isJidGroup, isJidNewsletter, isJidStatusBroadcast, jidNormalizedUser } from '../WABinary/index.js';
|
|
9
|
+
import { sha256 } from './crypto.js';
|
|
10
|
+
import { generateMessageIDV2, getKeyAuthor, unixTimestampSeconds } from './generics.js';
|
|
11
|
+
import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, getAudioWaveform, getRawMediaUploadData } from './messages-media.js';
|
|
12
|
+
import { shouldIncludeReportingToken } from './reporting-utils.js';
|
|
37
13
|
const MIMETYPE_MAP = {
|
|
38
14
|
image: 'image/jpeg',
|
|
39
15
|
video: 'video/mp4',
|
|
40
16
|
document: 'application/pdf',
|
|
41
17
|
audio: 'audio/ogg; codecs=opus',
|
|
42
18
|
sticker: 'image/webp',
|
|
43
|
-
'product-catalog-image': 'image/jpeg'
|
|
19
|
+
'product-catalog-image': 'image/jpeg'
|
|
44
20
|
};
|
|
45
21
|
const MessageTypeProto = {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
22
|
+
image: WAProto.Message.ImageMessage,
|
|
23
|
+
video: WAProto.Message.VideoMessage,
|
|
24
|
+
audio: WAProto.Message.AudioMessage,
|
|
25
|
+
sticker: WAProto.Message.StickerMessage,
|
|
26
|
+
document: WAProto.Message.DocumentMessage
|
|
51
27
|
};
|
|
52
|
-
const ButtonType = WAProto_1.proto.Message.ButtonsMessage.HeaderType;
|
|
53
28
|
/**
|
|
54
29
|
* Uses a regex to test whether the string contains a URL, and returns the URL if it does.
|
|
55
30
|
* @param text eg. hello https://google.com
|
|
56
31
|
* @returns the URL, eg. https://google.com
|
|
57
32
|
*/
|
|
58
|
-
const extractUrlFromText = (text) =>
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
const url = (0, exports.extractUrlFromText)(text);
|
|
33
|
+
export const extractUrlFromText = (text) => text.match(URL_REGEX)?.[0];
|
|
34
|
+
export const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
|
|
35
|
+
const url = extractUrlFromText(text);
|
|
62
36
|
if (!!getUrlInfo && url) {
|
|
63
37
|
try {
|
|
64
38
|
const urlInfo = await getUrlInfo(url);
|
|
65
39
|
return urlInfo;
|
|
66
40
|
}
|
|
67
|
-
catch (error) {
|
|
68
|
-
|
|
41
|
+
catch (error) {
|
|
42
|
+
// ignore if fails
|
|
43
|
+
logger?.warn({ trace: error.stack }, 'url generation failed');
|
|
69
44
|
}
|
|
70
45
|
}
|
|
71
46
|
};
|
|
72
|
-
exports.generateLinkPreviewIfRequired = generateLinkPreviewIfRequired;
|
|
73
47
|
const assertColor = async (color) => {
|
|
74
48
|
let assertedColor;
|
|
75
49
|
if (typeof color === 'number') {
|
|
@@ -84,92 +58,104 @@ const assertColor = async (color) => {
|
|
|
84
58
|
return assertedColor;
|
|
85
59
|
}
|
|
86
60
|
};
|
|
87
|
-
const prepareWAMessageMedia = async (message, options) => {
|
|
61
|
+
export const prepareWAMessageMedia = async (message, options) => {
|
|
88
62
|
const logger = options.logger;
|
|
89
63
|
let mediaType;
|
|
90
|
-
for (const key of
|
|
64
|
+
for (const key of MEDIA_KEYS) {
|
|
91
65
|
if (key in message) {
|
|
92
66
|
mediaType = key;
|
|
93
67
|
}
|
|
94
68
|
}
|
|
95
69
|
if (!mediaType) {
|
|
96
|
-
throw new
|
|
70
|
+
throw new Boom('Invalid media type', { statusCode: 400 });
|
|
97
71
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
72
|
const uploadData = {
|
|
101
73
|
...message,
|
|
102
74
|
media: message[mediaType]
|
|
103
75
|
};
|
|
104
|
-
|
|
105
76
|
delete uploadData[mediaType];
|
|
106
|
-
|
|
77
|
+
// check if cacheable + generate cache key
|
|
107
78
|
const cacheableKey = typeof uploadData.media === 'object' &&
|
|
108
|
-
|
|
79
|
+
'url' in uploadData.media &&
|
|
109
80
|
!!uploadData.media.url &&
|
|
110
81
|
!!options.mediaCache &&
|
|
111
82
|
mediaType + ':' + uploadData.media.url.toString();
|
|
112
|
-
|
|
113
83
|
if (mediaType === 'document' && !uploadData.fileName) {
|
|
114
84
|
uploadData.fileName = 'file';
|
|
115
85
|
}
|
|
116
|
-
|
|
117
86
|
if (!uploadData.mimetype) {
|
|
118
87
|
uploadData.mimetype = MIMETYPE_MAP[mediaType];
|
|
119
88
|
}
|
|
120
|
-
|
|
121
89
|
if (cacheableKey) {
|
|
122
|
-
const mediaBuff = options.mediaCache.get(cacheableKey);
|
|
90
|
+
const mediaBuff = await options.mediaCache.get(cacheableKey);
|
|
123
91
|
if (mediaBuff) {
|
|
124
92
|
logger?.debug({ cacheableKey }, 'got media cache hit');
|
|
125
|
-
const obj =
|
|
93
|
+
const obj = proto.Message.decode(mediaBuff);
|
|
126
94
|
const key = `${mediaType}Message`;
|
|
127
95
|
Object.assign(obj[key], { ...uploadData, media: undefined });
|
|
128
96
|
return obj;
|
|
129
97
|
}
|
|
130
98
|
}
|
|
131
|
-
|
|
99
|
+
const isNewsletter = !!options.jid && isJidNewsletter(options.jid);
|
|
100
|
+
if (isNewsletter) {
|
|
101
|
+
logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
|
|
102
|
+
const { filePath, fileSha256, fileLength } = await getRawMediaUploadData(uploadData.media, options.mediaTypeOverride || mediaType, logger);
|
|
103
|
+
const fileSha256B64 = fileSha256.toString('base64');
|
|
104
|
+
const { mediaUrl, directPath } = await options.upload(filePath, {
|
|
105
|
+
fileEncSha256B64: fileSha256B64,
|
|
106
|
+
mediaType: mediaType,
|
|
107
|
+
timeoutMs: options.mediaUploadTimeoutMs
|
|
108
|
+
});
|
|
109
|
+
await fs.unlink(filePath);
|
|
110
|
+
const obj = WAProto.Message.fromObject({
|
|
111
|
+
// todo: add more support here
|
|
112
|
+
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
113
|
+
url: mediaUrl,
|
|
114
|
+
directPath,
|
|
115
|
+
fileSha256,
|
|
116
|
+
fileLength,
|
|
117
|
+
...uploadData,
|
|
118
|
+
media: undefined
|
|
119
|
+
})
|
|
120
|
+
});
|
|
121
|
+
if (uploadData.ptv) {
|
|
122
|
+
obj.ptvMessage = obj.videoMessage;
|
|
123
|
+
delete obj.videoMessage;
|
|
124
|
+
}
|
|
125
|
+
if (obj.stickerMessage) {
|
|
126
|
+
obj.stickerMessage.stickerSentTs = Date.now();
|
|
127
|
+
}
|
|
128
|
+
if (cacheableKey) {
|
|
129
|
+
logger?.debug({ cacheableKey }, 'set cache');
|
|
130
|
+
await options.mediaCache.set(cacheableKey, WAProto.Message.encode(obj).finish());
|
|
131
|
+
}
|
|
132
|
+
return obj;
|
|
133
|
+
}
|
|
132
134
|
const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
|
|
133
|
-
const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') &&
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
// MODIFIED BY VYZEN
|
|
137
|
-
const requiresWaveformProcessing = mediaType === 'audio' && (uploadData.ptt === true || !!options.backgroundColor);
|
|
138
|
-
// MODIFIED BY VYZEN
|
|
139
|
-
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio';
|
|
140
|
-
|
|
135
|
+
const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && typeof uploadData['jpegThumbnail'] === 'undefined';
|
|
136
|
+
const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true && typeof uploadData.waveform === 'undefined';
|
|
137
|
+
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
|
|
141
138
|
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
|
|
150
|
-
opts: options.options,
|
|
151
|
-
isPtt: uploadData.ptt,
|
|
152
|
-
forceOpus: (mediaType === 'audio' && uploadData.mimetype && uploadData.mimetype.includes('opus')),
|
|
153
|
-
convertVideo: (mediaType === 'video')
|
|
154
|
-
}
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
if (mediaType === 'audio' && opusConverted) {
|
|
158
|
-
uploadData.mimetype = 'audio/ogg; codecs=opus';
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 ?? fileSha256).toString('base64');
|
|
162
|
-
|
|
163
|
-
const [{ mediaUrl, directPath, handle }] = await Promise.all([
|
|
139
|
+
const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength } = await encryptedStream(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
140
|
+
logger,
|
|
141
|
+
saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
|
|
142
|
+
opts: options.options
|
|
143
|
+
});
|
|
144
|
+
const fileEncSha256B64 = fileEncSha256.toString('base64');
|
|
145
|
+
const [{ mediaUrl, directPath }] = await Promise.all([
|
|
164
146
|
(async () => {
|
|
165
|
-
const result = await options.upload(
|
|
147
|
+
const result = await options.upload(encFilePath, {
|
|
148
|
+
fileEncSha256B64,
|
|
149
|
+
mediaType,
|
|
150
|
+
timeoutMs: options.mediaUploadTimeoutMs
|
|
151
|
+
});
|
|
166
152
|
logger?.debug({ mediaType, cacheableKey }, 'uploaded media');
|
|
167
153
|
return result;
|
|
168
154
|
})(),
|
|
169
155
|
(async () => {
|
|
170
156
|
try {
|
|
171
157
|
if (requiresThumbnailComputation) {
|
|
172
|
-
const { thumbnail, originalImageDimensions } = await
|
|
158
|
+
const { thumbnail, originalImageDimensions } = await generateThumbnail(originalFilePath, mediaType, options);
|
|
173
159
|
uploadData.jpegThumbnail = thumbnail;
|
|
174
160
|
if (!uploadData.width && originalImageDimensions) {
|
|
175
161
|
uploadData.width = originalImageDimensions.width;
|
|
@@ -179,131 +165,119 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
179
165
|
logger?.debug('generated thumbnail');
|
|
180
166
|
}
|
|
181
167
|
if (requiresDurationComputation) {
|
|
182
|
-
uploadData.seconds = await
|
|
168
|
+
uploadData.seconds = await getAudioDuration(originalFilePath);
|
|
183
169
|
logger?.debug('computed audio duration');
|
|
184
170
|
}
|
|
185
|
-
|
|
186
|
-
// MODIFIED BY VYZEN
|
|
187
171
|
if (requiresWaveformProcessing) {
|
|
188
|
-
|
|
189
|
-
uploadData.waveform = await messages_media_1.getAudioWaveform(bodyPath, logger);
|
|
190
|
-
} catch (err) {
|
|
191
|
-
logger?.warn('Failed to generate waveform, using fallback');
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (!uploadData.waveform) {
|
|
195
|
-
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]);
|
|
196
|
-
}
|
|
172
|
+
uploadData.waveform = await getAudioWaveform(originalFilePath, logger);
|
|
197
173
|
logger?.debug('processed waveform');
|
|
198
174
|
}
|
|
199
|
-
|
|
200
175
|
if (requiresAudioBackground) {
|
|
201
176
|
uploadData.backgroundArgb = await assertColor(options.backgroundColor);
|
|
202
177
|
logger?.debug('computed backgroundColor audio status');
|
|
203
178
|
}
|
|
204
|
-
} catch (error) {
|
|
205
|
-
logger?.warn({ trace: error.stack }, 'failed to obtain extra info');
|
|
206
179
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
.finally(async () => {
|
|
210
|
-
if (!Buffer.isBuffer(encWriteStream)) {
|
|
211
|
-
encWriteStream.destroy();
|
|
180
|
+
catch (error) {
|
|
181
|
+
logger?.warn({ trace: error.stack }, 'failed to obtain extra info');
|
|
212
182
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
logger?.warn('failed to remove tmp file');
|
|
220
|
-
}
|
|
183
|
+
})()
|
|
184
|
+
]).finally(async () => {
|
|
185
|
+
try {
|
|
186
|
+
await fs.unlink(encFilePath);
|
|
187
|
+
if (originalFilePath) {
|
|
188
|
+
await fs.unlink(originalFilePath);
|
|
221
189
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
190
|
+
logger?.debug('removed tmp files');
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
logger?.warn('failed to remove tmp file');
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
const obj = WAProto.Message.fromObject({
|
|
225
197
|
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
226
|
-
url:
|
|
198
|
+
url: mediaUrl,
|
|
227
199
|
directPath,
|
|
228
|
-
mediaKey
|
|
229
|
-
fileEncSha256
|
|
200
|
+
mediaKey,
|
|
201
|
+
fileEncSha256,
|
|
230
202
|
fileSha256,
|
|
231
203
|
fileLength,
|
|
232
|
-
mediaKeyTimestamp:
|
|
204
|
+
mediaKeyTimestamp: unixTimestampSeconds(),
|
|
233
205
|
...uploadData,
|
|
234
206
|
media: undefined
|
|
235
207
|
})
|
|
236
208
|
});
|
|
237
|
-
|
|
238
209
|
if (uploadData.ptv) {
|
|
239
210
|
obj.ptvMessage = obj.videoMessage;
|
|
240
211
|
delete obj.videoMessage;
|
|
241
212
|
}
|
|
242
|
-
|
|
243
213
|
if (cacheableKey) {
|
|
244
214
|
logger?.debug({ cacheableKey }, 'set cache');
|
|
245
|
-
options.mediaCache.set(cacheableKey,
|
|
215
|
+
await options.mediaCache.set(cacheableKey, WAProto.Message.encode(obj).finish());
|
|
246
216
|
}
|
|
247
|
-
|
|
248
217
|
return obj;
|
|
249
218
|
};
|
|
250
|
-
|
|
251
|
-
exports.prepareWAMessageMedia = prepareWAMessageMedia;
|
|
252
|
-
const prepareDisappearingMessageSettingContent = (ephemeralExpiration) => {
|
|
219
|
+
export const prepareDisappearingMessageSettingContent = (ephemeralExpiration) => {
|
|
253
220
|
ephemeralExpiration = ephemeralExpiration || 0;
|
|
254
221
|
const content = {
|
|
255
222
|
ephemeralMessage: {
|
|
256
223
|
message: {
|
|
257
224
|
protocolMessage: {
|
|
258
|
-
type:
|
|
225
|
+
type: WAProto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
|
|
259
226
|
ephemeralExpiration
|
|
260
227
|
}
|
|
261
228
|
}
|
|
262
229
|
}
|
|
263
230
|
};
|
|
264
|
-
return
|
|
231
|
+
return WAProto.Message.fromObject(content);
|
|
265
232
|
};
|
|
266
|
-
exports.prepareDisappearingMessageSettingContent = prepareDisappearingMessageSettingContent;
|
|
267
233
|
/**
|
|
268
234
|
* Generate forwarded message content like WA does
|
|
269
235
|
* @param message the message to forward
|
|
270
236
|
* @param options.forceForward will show the message as forwarded even if it is from you
|
|
271
237
|
*/
|
|
272
|
-
const generateForwardMessageContent = (message, forceForward) => {
|
|
273
|
-
var _a;
|
|
238
|
+
export const generateForwardMessageContent = (message, forceForward) => {
|
|
274
239
|
let content = message.message;
|
|
275
240
|
if (!content) {
|
|
276
|
-
throw new
|
|
241
|
+
throw new Boom('no content in message', { statusCode: 400 });
|
|
277
242
|
}
|
|
278
|
-
|
|
279
|
-
content =
|
|
280
|
-
content =
|
|
243
|
+
// hacky copy
|
|
244
|
+
content = normalizeMessageContent(content);
|
|
245
|
+
content = proto.Message.decode(proto.Message.encode(content).finish());
|
|
281
246
|
let key = Object.keys(content)[0];
|
|
282
|
-
let score =
|
|
247
|
+
let score = content?.[key]?.contextInfo?.forwardingScore || 0;
|
|
283
248
|
score += message.key.fromMe && !forceForward ? 0 : 1;
|
|
284
249
|
if (key === 'conversation') {
|
|
285
250
|
content.extendedTextMessage = { text: content[key] };
|
|
286
251
|
delete content.conversation;
|
|
287
252
|
key = 'extendedTextMessage';
|
|
288
253
|
}
|
|
254
|
+
const key_ = content?.[key];
|
|
289
255
|
if (score > 0) {
|
|
290
|
-
|
|
256
|
+
key_.contextInfo = { forwardingScore: score, isForwarded: true };
|
|
291
257
|
}
|
|
292
258
|
else {
|
|
293
|
-
|
|
259
|
+
key_.contextInfo = {};
|
|
294
260
|
}
|
|
295
261
|
return content;
|
|
296
262
|
};
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
263
|
+
export const hasNonNullishProperty = (message, key) => {
|
|
264
|
+
return (typeof message === 'object' &&
|
|
265
|
+
message !== null &&
|
|
266
|
+
key in message &&
|
|
267
|
+
message[key] !== null &&
|
|
268
|
+
message[key] !== undefined);
|
|
269
|
+
};
|
|
270
|
+
function hasOptionalProperty(obj, key) {
|
|
271
|
+
return typeof obj === 'object' && obj !== null && key in obj && obj[key] !== null;
|
|
272
|
+
}
|
|
273
|
+
export const generateWAMessageContent = async (message, options) => {
|
|
274
|
+
var _a, _b;
|
|
301
275
|
let m = {};
|
|
302
|
-
if ('text'
|
|
276
|
+
if (hasNonNullishProperty(message, 'text')) {
|
|
303
277
|
const extContent = { text: message.text };
|
|
304
278
|
let urlInfo = message.linkPreview;
|
|
305
279
|
if (typeof urlInfo === 'undefined') {
|
|
306
|
-
urlInfo = await
|
|
280
|
+
urlInfo = await generateLinkPreviewIfRequired(message.text, options.getUrlInfo, options.logger);
|
|
307
281
|
}
|
|
308
282
|
if (urlInfo) {
|
|
309
283
|
extContent.matchedText = urlInfo['matched-text'];
|
|
@@ -330,62 +304,65 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
330
304
|
}
|
|
331
305
|
m.extendedTextMessage = extContent;
|
|
332
306
|
}
|
|
333
|
-
else if ('contacts'
|
|
307
|
+
else if (hasNonNullishProperty(message, 'contacts')) {
|
|
334
308
|
const contactLen = message.contacts.contacts.length;
|
|
335
309
|
if (!contactLen) {
|
|
336
|
-
throw new
|
|
310
|
+
throw new Boom('require atleast 1 contact', { statusCode: 400 });
|
|
337
311
|
}
|
|
338
312
|
if (contactLen === 1) {
|
|
339
|
-
m.contactMessage =
|
|
313
|
+
m.contactMessage = WAProto.Message.ContactMessage.create(message.contacts.contacts[0]);
|
|
340
314
|
}
|
|
341
315
|
else {
|
|
342
|
-
m.contactsArrayMessage =
|
|
316
|
+
m.contactsArrayMessage = WAProto.Message.ContactsArrayMessage.create(message.contacts);
|
|
343
317
|
}
|
|
344
318
|
}
|
|
345
|
-
else if ('location'
|
|
346
|
-
m.locationMessage =
|
|
319
|
+
else if (hasNonNullishProperty(message, 'location')) {
|
|
320
|
+
m.locationMessage = WAProto.Message.LocationMessage.create(message.location);
|
|
347
321
|
}
|
|
348
|
-
else if ('react'
|
|
322
|
+
else if (hasNonNullishProperty(message, 'react')) {
|
|
349
323
|
if (!message.react.senderTimestampMs) {
|
|
350
324
|
message.react.senderTimestampMs = Date.now();
|
|
351
325
|
}
|
|
352
|
-
m.reactionMessage =
|
|
326
|
+
m.reactionMessage = WAProto.Message.ReactionMessage.create(message.react);
|
|
353
327
|
}
|
|
354
|
-
else if ('delete'
|
|
328
|
+
else if (hasNonNullishProperty(message, 'delete')) {
|
|
355
329
|
m.protocolMessage = {
|
|
356
330
|
key: message.delete,
|
|
357
|
-
type:
|
|
331
|
+
type: WAProto.Message.ProtocolMessage.Type.REVOKE
|
|
358
332
|
};
|
|
359
333
|
}
|
|
360
|
-
else if ('forward'
|
|
361
|
-
m =
|
|
334
|
+
else if (hasNonNullishProperty(message, 'forward')) {
|
|
335
|
+
m = generateForwardMessageContent(message.forward, message.force);
|
|
362
336
|
}
|
|
363
|
-
else if ('disappearingMessagesInChat'
|
|
364
|
-
const exp = typeof message.disappearingMessagesInChat === 'boolean'
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
337
|
+
else if (hasNonNullishProperty(message, 'disappearingMessagesInChat')) {
|
|
338
|
+
const exp = typeof message.disappearingMessagesInChat === 'boolean'
|
|
339
|
+
? message.disappearingMessagesInChat
|
|
340
|
+
? WA_DEFAULT_EPHEMERAL
|
|
341
|
+
: 0
|
|
342
|
+
: message.disappearingMessagesInChat;
|
|
343
|
+
m = prepareDisappearingMessageSettingContent(exp);
|
|
368
344
|
}
|
|
369
|
-
else if ('groupInvite'
|
|
345
|
+
else if (hasNonNullishProperty(message, 'groupInvite')) {
|
|
370
346
|
m.groupInviteMessage = {};
|
|
371
347
|
m.groupInviteMessage.inviteCode = message.groupInvite.inviteCode;
|
|
372
348
|
m.groupInviteMessage.inviteExpiration = message.groupInvite.inviteExpiration;
|
|
373
349
|
m.groupInviteMessage.caption = message.groupInvite.text;
|
|
374
350
|
m.groupInviteMessage.groupJid = message.groupInvite.jid;
|
|
375
351
|
m.groupInviteMessage.groupName = message.groupInvite.subject;
|
|
376
|
-
|
|
377
|
-
|
|
352
|
+
//TODO: use built-in interface and get disappearing mode info etc.
|
|
353
|
+
//TODO: cache / use store!?
|
|
378
354
|
if (options.getProfilePicUrl) {
|
|
379
355
|
const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
|
|
380
356
|
if (pfpUrl) {
|
|
381
|
-
const resp = await
|
|
382
|
-
if (resp.
|
|
383
|
-
|
|
357
|
+
const resp = await fetch(pfpUrl, { method: 'GET', dispatcher: options?.options?.dispatcher });
|
|
358
|
+
if (resp.ok) {
|
|
359
|
+
const buf = Buffer.from(await resp.arrayBuffer());
|
|
360
|
+
m.groupInviteMessage.jpegThumbnail = buf;
|
|
384
361
|
}
|
|
385
362
|
}
|
|
386
363
|
}
|
|
387
364
|
}
|
|
388
|
-
else if ('pin'
|
|
365
|
+
else if (hasNonNullishProperty(message, 'pin')) {
|
|
389
366
|
m.pinInChatMessage = {};
|
|
390
367
|
m.messageContextInfo = {};
|
|
391
368
|
m.pinInChatMessage.key = message.pin;
|
|
@@ -393,447 +370,276 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
393
370
|
m.pinInChatMessage.senderTimestampMs = Date.now();
|
|
394
371
|
m.messageContextInfo.messageAddOnDurationInSecs = message.type === 1 ? message.time || 86400 : 0;
|
|
395
372
|
}
|
|
396
|
-
else if ('
|
|
397
|
-
m.keepInChatMessage = {};
|
|
398
|
-
m.keepInChatMessage.key = message.keep;
|
|
399
|
-
m.keepInChatMessage.keepType = message.type;
|
|
400
|
-
m.keepInChatMessage.timestampMs = Date.now();
|
|
401
|
-
}
|
|
402
|
-
else if ('call' in message) {
|
|
403
|
-
m = {
|
|
404
|
-
scheduledCallCreationMessage: {
|
|
405
|
-
scheduledTimestampMs: (_a = message.call.time) !== null && _a !== void 0 ? _a : Date.now(),
|
|
406
|
-
callType: (_b = message.call.type) !== null && _b !== void 0 ? _b : 1,
|
|
407
|
-
title: message.call.title
|
|
408
|
-
}
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
else if ('paymentInvite' in message) {
|
|
412
|
-
m.paymentInviteMessage = {
|
|
413
|
-
serviceType: message.paymentInvite.type,
|
|
414
|
-
expiryTimestamp: message.paymentInvite.expiry
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
else if ('buttonReply' in message) {
|
|
373
|
+
else if (hasNonNullishProperty(message, 'buttonReply')) {
|
|
418
374
|
switch (message.type) {
|
|
419
375
|
case 'template':
|
|
420
376
|
m.templateButtonReplyMessage = {
|
|
421
377
|
selectedDisplayText: message.buttonReply.displayText,
|
|
422
378
|
selectedId: message.buttonReply.id,
|
|
423
|
-
selectedIndex: message.buttonReply.index
|
|
379
|
+
selectedIndex: message.buttonReply.index
|
|
424
380
|
};
|
|
425
381
|
break;
|
|
426
382
|
case 'plain':
|
|
427
383
|
m.buttonsResponseMessage = {
|
|
428
384
|
selectedButtonId: message.buttonReply.id,
|
|
429
385
|
selectedDisplayText: message.buttonReply.displayText,
|
|
430
|
-
type:
|
|
386
|
+
type: proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
|
|
431
387
|
};
|
|
432
388
|
break;
|
|
433
389
|
}
|
|
434
390
|
}
|
|
435
|
-
else if ('ptv'
|
|
436
|
-
const { videoMessage } = await
|
|
391
|
+
else if (hasOptionalProperty(message, 'ptv') && message.ptv) {
|
|
392
|
+
const { videoMessage } = await prepareWAMessageMedia({ video: message.video }, options);
|
|
437
393
|
m.ptvMessage = videoMessage;
|
|
438
394
|
}
|
|
439
|
-
else if ('product'
|
|
440
|
-
const { imageMessage } = await
|
|
441
|
-
m.productMessage =
|
|
395
|
+
else if (hasNonNullishProperty(message, 'product')) {
|
|
396
|
+
const { imageMessage } = await prepareWAMessageMedia({ image: message.product.productImage }, options);
|
|
397
|
+
m.productMessage = WAProto.Message.ProductMessage.create({
|
|
442
398
|
...message,
|
|
443
399
|
product: {
|
|
444
400
|
...message.product,
|
|
445
|
-
productImage: imageMessage
|
|
401
|
+
productImage: imageMessage
|
|
446
402
|
}
|
|
447
403
|
});
|
|
448
404
|
}
|
|
449
|
-
else if ('
|
|
450
|
-
m.orderMessage = Types_1.WAProto.Message.OrderMessage.fromObject({
|
|
451
|
-
orderId: message.order.id,
|
|
452
|
-
thumbnail: message.order.thumbnail,
|
|
453
|
-
itemCount: message.order.itemCount,
|
|
454
|
-
status: message.order.status,
|
|
455
|
-
surface: message.order.surface,
|
|
456
|
-
orderTitle: message.order.title,
|
|
457
|
-
message: message.order.text,
|
|
458
|
-
sellerJid: message.order.seller,
|
|
459
|
-
token: message.order.token,
|
|
460
|
-
totalAmount1000: message.order.amount,
|
|
461
|
-
totalCurrencyCode: message.order.currency
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
else if ('listReply' in message) {
|
|
405
|
+
else if (hasNonNullishProperty(message, 'listReply')) {
|
|
465
406
|
m.listResponseMessage = { ...message.listReply };
|
|
466
407
|
}
|
|
467
|
-
else if ('
|
|
468
|
-
|
|
469
|
-
|
|
408
|
+
else if (hasNonNullishProperty(message, 'event')) {
|
|
409
|
+
m.eventMessage = {};
|
|
410
|
+
const startTime = Math.floor(message.event.startDate.getTime() / 1000);
|
|
411
|
+
if (message.event.call && options.getCallLink) {
|
|
412
|
+
const token = await options.getCallLink(message.event.call, { startTime });
|
|
413
|
+
m.eventMessage.joinLink = (message.event.call === 'audio' ? CALL_AUDIO_PREFIX : CALL_VIDEO_PREFIX) + token;
|
|
414
|
+
}
|
|
415
|
+
m.messageContextInfo = {
|
|
416
|
+
// encKey
|
|
417
|
+
messageSecret: message.event.messageSecret || randomBytes(32)
|
|
418
|
+
};
|
|
419
|
+
m.eventMessage.name = message.event.name;
|
|
420
|
+
m.eventMessage.description = message.event.description;
|
|
421
|
+
m.eventMessage.startTime = startTime;
|
|
422
|
+
m.eventMessage.endTime = message.event.endDate ? message.event.endDate.getTime() / 1000 : undefined;
|
|
423
|
+
m.eventMessage.isCanceled = message.event.isCancelled ?? false;
|
|
424
|
+
m.eventMessage.extraGuestsAllowed = message.event.extraGuestsAllowed;
|
|
425
|
+
m.eventMessage.isScheduleCall = message.event.isScheduleCall ?? false;
|
|
426
|
+
m.eventMessage.location = message.event.location;
|
|
427
|
+
}
|
|
428
|
+
else if (hasNonNullishProperty(message, 'poll')) {
|
|
429
|
+
(_a = message.poll).selectableCount || (_a.selectableCount = 0);
|
|
430
|
+
(_b = message.poll).toAnnouncementGroup || (_b.toAnnouncementGroup = false);
|
|
470
431
|
if (!Array.isArray(message.poll.values)) {
|
|
471
|
-
throw new
|
|
432
|
+
throw new Boom('Invalid poll values', { statusCode: 400 });
|
|
472
433
|
}
|
|
473
|
-
if (message.poll.selectableCount < 0
|
|
474
|
-
|
|
475
|
-
|
|
434
|
+
if (message.poll.selectableCount < 0 || message.poll.selectableCount > message.poll.values.length) {
|
|
435
|
+
throw new Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, {
|
|
436
|
+
statusCode: 400
|
|
437
|
+
});
|
|
476
438
|
}
|
|
477
439
|
m.messageContextInfo = {
|
|
478
|
-
|
|
479
|
-
messageSecret: message.poll.messageSecret ||
|
|
440
|
+
// encKey
|
|
441
|
+
messageSecret: message.poll.messageSecret || randomBytes(32)
|
|
480
442
|
};
|
|
481
443
|
const pollCreationMessage = {
|
|
482
444
|
name: message.poll.name,
|
|
483
445
|
selectableOptionsCount: message.poll.selectableCount,
|
|
484
|
-
options: message.poll.values.map(optionName => ({ optionName }))
|
|
446
|
+
options: message.poll.values.map(optionName => ({ optionName }))
|
|
485
447
|
};
|
|
486
448
|
if (message.poll.toAnnouncementGroup) {
|
|
487
|
-
|
|
449
|
+
// poll v2 is for community announcement groups (single select and multiple)
|
|
488
450
|
m.pollCreationMessageV2 = pollCreationMessage;
|
|
489
451
|
}
|
|
490
452
|
else {
|
|
491
453
|
if (message.poll.selectableCount === 1) {
|
|
492
|
-
|
|
454
|
+
//poll v3 is for single select polls
|
|
493
455
|
m.pollCreationMessageV3 = pollCreationMessage;
|
|
494
456
|
}
|
|
495
457
|
else {
|
|
496
|
-
|
|
458
|
+
// poll for multiple choice polls
|
|
497
459
|
m.pollCreationMessage = pollCreationMessage;
|
|
498
460
|
}
|
|
499
461
|
}
|
|
500
462
|
}
|
|
501
|
-
else if ('
|
|
502
|
-
m.
|
|
503
|
-
|
|
463
|
+
else if (hasNonNullishProperty(message, 'album')) {
|
|
464
|
+
m.albumMessage = {
|
|
465
|
+
expectedImageCount: message.album.expectedImageCount,
|
|
466
|
+
expectedVideoCount: message.album.expectedVideoCount
|
|
504
467
|
};
|
|
505
|
-
m.eventMessage = { ...message.event };
|
|
506
468
|
}
|
|
507
|
-
else if ('
|
|
508
|
-
m.newsletterAdminInviteMessage = {};
|
|
509
|
-
m.newsletterAdminInviteMessage.inviteExpiration = message.inviteAdmin.inviteExpiration;
|
|
510
|
-
m.newsletterAdminInviteMessage.caption = message.inviteAdmin.text;
|
|
511
|
-
m.newsletterAdminInviteMessage.newsletterJid = message.inviteAdmin.jid;
|
|
512
|
-
m.newsletterAdminInviteMessage.newsletterName = message.inviteAdmin.subject;
|
|
513
|
-
m.newsletterAdminInviteMessage.jpegThumbnail = message.inviteAdmin.thumbnail;
|
|
514
|
-
}
|
|
515
|
-
else if ('requestPayment' in message) {
|
|
516
|
-
const sticker = ((_c = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _c === void 0 ? void 0 : _c.sticker) ?
|
|
517
|
-
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)
|
|
518
|
-
: null;
|
|
519
|
-
let notes = {};
|
|
520
|
-
if ((_e = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _e === void 0 ? void 0 : _e.sticker) {
|
|
521
|
-
notes = {
|
|
522
|
-
stickerMessage: {
|
|
523
|
-
...sticker === null || sticker === void 0 ? void 0 : sticker.stickerMessage,
|
|
524
|
-
contextInfo: (_f = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _f === void 0 ? void 0 : _f.contextInfo
|
|
525
|
-
}
|
|
526
|
-
};
|
|
527
|
-
}
|
|
528
|
-
else if (message.requestPayment.note) {
|
|
529
|
-
notes = {
|
|
530
|
-
extendedTextMessage: {
|
|
531
|
-
text: message.requestPayment.note,
|
|
532
|
-
contextInfo: (_g = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _g === void 0 ? void 0 : _g.contextInfo,
|
|
533
|
-
}
|
|
534
|
-
};
|
|
535
|
-
}
|
|
536
|
-
else {
|
|
537
|
-
throw new boom_1.Boom('Invalid media type', { statusCode: 400 });
|
|
538
|
-
}
|
|
539
|
-
m.requestPaymentMessage = Types_1.WAProto.Message.RequestPaymentMessage.fromObject({
|
|
540
|
-
expiryTimestamp: message.requestPayment.expiry,
|
|
541
|
-
amount1000: message.requestPayment.amount,
|
|
542
|
-
currencyCodeIso4217: message.requestPayment.currency,
|
|
543
|
-
requestFrom: message.requestPayment.from,
|
|
544
|
-
noteMessage: { ...notes },
|
|
545
|
-
background: (_h = message.requestPayment.background) !== null && _h !== void 0 ? _h : null,
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
else if ('sharePhoneNumber' in message) {
|
|
469
|
+
else if (hasNonNullishProperty(message, 'sharePhoneNumber')) {
|
|
549
470
|
m.protocolMessage = {
|
|
550
|
-
type:
|
|
471
|
+
type: proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
|
|
551
472
|
};
|
|
552
473
|
}
|
|
553
|
-
else if ('requestPhoneNumber'
|
|
474
|
+
else if (hasNonNullishProperty(message, 'requestPhoneNumber')) {
|
|
554
475
|
m.requestPhoneNumberMessage = {};
|
|
555
476
|
}
|
|
556
|
-
else if ('
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
477
|
+
else if (hasNonNullishProperty(message, 'limitSharing')) {
|
|
478
|
+
m.protocolMessage = {
|
|
479
|
+
type: proto.Message.ProtocolMessage.Type.LIMIT_SHARING,
|
|
480
|
+
limitSharing: {
|
|
481
|
+
sharingLimited: message.limitSharing === true,
|
|
482
|
+
trigger: 1,
|
|
483
|
+
limitSharingSettingTimestamp: Date.now(),
|
|
484
|
+
initiatedByMe: true
|
|
485
|
+
}
|
|
486
|
+
};
|
|
563
487
|
}
|
|
564
488
|
else {
|
|
565
|
-
m = await
|
|
489
|
+
m = await prepareWAMessageMedia(message, options);
|
|
566
490
|
}
|
|
567
|
-
if ('
|
|
568
|
-
|
|
569
|
-
buttons: message.buttons.map(b => ({ ...b, type: WAProto_1.proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
|
|
570
|
-
};
|
|
571
|
-
if ('text' in message) {
|
|
572
|
-
buttonsMessage.contentText = message.text;
|
|
573
|
-
buttonsMessage.headerType = ButtonType.EMPTY;
|
|
574
|
-
}
|
|
575
|
-
else {
|
|
576
|
-
if ('caption' in message) {
|
|
577
|
-
buttonsMessage.contentText = message.caption;
|
|
578
|
-
}
|
|
579
|
-
const type = Object.keys(m)[0].replace('Message', '').toUpperCase();
|
|
580
|
-
buttonsMessage.headerType = ButtonType[type];
|
|
581
|
-
Object.assign(buttonsMessage, m);
|
|
582
|
-
}
|
|
583
|
-
if ('title' in message && !!message.title) {
|
|
584
|
-
buttonsMessage.text = message.title,
|
|
585
|
-
buttonsMessage.headerType = ButtonType.TEXT;
|
|
586
|
-
}
|
|
587
|
-
if ('footer' in message && !!message.footer) {
|
|
588
|
-
buttonsMessage.footerText = message.footer;
|
|
589
|
-
}
|
|
590
|
-
if ('contextInfo' in message && !!message.contextInfo) {
|
|
591
|
-
buttonsMessage.contextInfo = message.contextInfo;
|
|
592
|
-
}
|
|
593
|
-
if ('mentions' in message && !!message.mentions) {
|
|
594
|
-
buttonsMessage.contextInfo = { mentionedJid: message.mentions };
|
|
595
|
-
}
|
|
596
|
-
m = { buttonsMessage };
|
|
491
|
+
if (hasOptionalProperty(message, 'viewOnce') && !!message.viewOnce) {
|
|
492
|
+
m = { viewOnceMessage: { message: m } };
|
|
597
493
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
if ('
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
if ('caption' in message) {
|
|
607
|
-
msg.hydratedContentText = message.caption;
|
|
494
|
+
if ((hasOptionalProperty(message, 'mentions') && message.mentions?.length) ||
|
|
495
|
+
(hasOptionalProperty(message, 'mentionAll') && message.mentionAll)) {
|
|
496
|
+
const messageType = Object.keys(m)[0];
|
|
497
|
+
const key = m[messageType];
|
|
498
|
+
if (key && 'contextInfo' in key) {
|
|
499
|
+
key.contextInfo = key.contextInfo || {};
|
|
500
|
+
if (message.mentions?.length) {
|
|
501
|
+
key.contextInfo.mentionedJid = message.mentions;
|
|
608
502
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
if ('footer' in message && !!message.footer) {
|
|
612
|
-
msg.hydratedFooterText = message.footer;
|
|
613
|
-
}
|
|
614
|
-
m = {
|
|
615
|
-
templateMessage: {
|
|
616
|
-
fourRowTemplate: msg,
|
|
617
|
-
hydratedTemplate: msg
|
|
503
|
+
if (message.mentionAll) {
|
|
504
|
+
key.contextInfo.nonJidMentions = 1;
|
|
618
505
|
}
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
if ('sections' in message && !!message.sections) {
|
|
622
|
-
const listMessage = {
|
|
623
|
-
sections: message.sections,
|
|
624
|
-
buttonText: message.buttonText,
|
|
625
|
-
title: message.title,
|
|
626
|
-
footerText: message.footer,
|
|
627
|
-
description: message.text,
|
|
628
|
-
listType: WAProto_1.proto.Message.ListMessage.ListType.SINGLE_SELECT
|
|
629
|
-
};
|
|
630
|
-
m = { listMessage };
|
|
631
|
-
}
|
|
632
|
-
if ('interactiveButtons' in message && !!message.interactiveButtons) {
|
|
633
|
-
const interactiveMessage = {
|
|
634
|
-
nativeFlowMessage: Types_1.WAProto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
|
|
635
|
-
buttons: message.interactiveButtons,
|
|
636
|
-
})
|
|
637
|
-
};
|
|
638
|
-
if ('text' in message) {
|
|
639
|
-
interactiveMessage.body = {
|
|
640
|
-
text: message.text
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
else if ('caption' in message) {
|
|
644
|
-
interactiveMessage.body = {
|
|
645
|
-
text: message.caption
|
|
646
|
-
};
|
|
647
|
-
interactiveMessage.header = {
|
|
648
|
-
title: message.title,
|
|
649
|
-
subtitle: message.subtitle,
|
|
650
|
-
hasMediaAttachment: (_j = message === null || message === void 0 ? void 0 : message.media) !== null && _j !== void 0 ? _j : false,
|
|
651
|
-
};
|
|
652
|
-
Object.assign(interactiveMessage.header, m);
|
|
653
|
-
}
|
|
654
|
-
if ('footer' in message && !!message.footer) {
|
|
655
|
-
interactiveMessage.footer = {
|
|
656
|
-
text: message.footer
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
if ('title' in message && !!message.title) {
|
|
660
|
-
interactiveMessage.header = {
|
|
661
|
-
title: message.title,
|
|
662
|
-
subtitle: message.subtitle,
|
|
663
|
-
hasMediaAttachment: (_k = message === null || message === void 0 ? void 0 : message.media) !== null && _k !== void 0 ? _k : false,
|
|
664
|
-
};
|
|
665
|
-
Object.assign(interactiveMessage.header, m);
|
|
666
|
-
}
|
|
667
|
-
if ('contextInfo' in message && !!message.contextInfo) {
|
|
668
|
-
interactiveMessage.contextInfo = message.contextInfo;
|
|
669
|
-
}
|
|
670
|
-
if ('mentions' in message && !!message.mentions) {
|
|
671
|
-
interactiveMessage.contextInfo = { mentionedJid: message.mentions };
|
|
672
|
-
}
|
|
673
|
-
m = { interactiveMessage };
|
|
674
|
-
}
|
|
675
|
-
if ('shop' in message && !!message.shop) {
|
|
676
|
-
const interactiveMessage = {
|
|
677
|
-
shopStorefrontMessage: Types_1.WAProto.Message.InteractiveMessage.ShopMessage.fromObject({
|
|
678
|
-
surface: message.shop,
|
|
679
|
-
id: message.id
|
|
680
|
-
})
|
|
681
|
-
};
|
|
682
|
-
if ('text' in message) {
|
|
683
|
-
interactiveMessage.body = {
|
|
684
|
-
text: message.text
|
|
685
|
-
};
|
|
686
|
-
}
|
|
687
|
-
else if ('caption' in message) {
|
|
688
|
-
interactiveMessage.body = {
|
|
689
|
-
text: message.caption
|
|
690
|
-
};
|
|
691
|
-
interactiveMessage.header = {
|
|
692
|
-
title: message.title,
|
|
693
|
-
subtitle: message.subtitle,
|
|
694
|
-
hasMediaAttachment: (_l = message === null || message === void 0 ? void 0 : message.media) !== null && _l !== void 0 ? _l : false,
|
|
695
|
-
};
|
|
696
|
-
Object.assign(interactiveMessage.header, m);
|
|
697
|
-
}
|
|
698
|
-
if ('footer' in message && !!message.footer) {
|
|
699
|
-
interactiveMessage.footer = {
|
|
700
|
-
text: message.footer
|
|
701
|
-
};
|
|
702
506
|
}
|
|
703
|
-
if (
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
hasMediaAttachment: (_m = message === null || message === void 0 ? void 0 : message.media) !== null && _m !== void 0 ? _m : false,
|
|
507
|
+
else if (key) {
|
|
508
|
+
key.contextInfo = {
|
|
509
|
+
mentionedJid: message.mentions,
|
|
510
|
+
nonJidMentions: message.mentionAll ? 1 : 0
|
|
708
511
|
};
|
|
709
|
-
Object.assign(interactiveMessage.header, m);
|
|
710
|
-
}
|
|
711
|
-
if ('contextInfo' in message && !!message.contextInfo) {
|
|
712
|
-
interactiveMessage.contextInfo = message.contextInfo;
|
|
713
512
|
}
|
|
714
|
-
if ('mentions' in message && !!message.mentions) {
|
|
715
|
-
interactiveMessage.contextInfo = { mentionedJid: message.mentions };
|
|
716
|
-
}
|
|
717
|
-
m = { interactiveMessage };
|
|
718
|
-
}
|
|
719
|
-
if ('viewOnce' in message && !!message.viewOnce) {
|
|
720
|
-
m = { viewOnceMessage: { message: m } };
|
|
721
|
-
}
|
|
722
|
-
if ('mentions' in message && ((_o = message.mentions) === null || _o === void 0 ? void 0 : _o.length)) {
|
|
723
|
-
const [messageType] = Object.keys(m);
|
|
724
|
-
m[messageType].contextInfo = m[messageType] || {};
|
|
725
|
-
m[messageType].contextInfo.mentionedJid = message.mentions;
|
|
726
513
|
}
|
|
727
|
-
if ('edit'
|
|
514
|
+
if (hasOptionalProperty(message, 'edit')) {
|
|
728
515
|
m = {
|
|
729
516
|
protocolMessage: {
|
|
730
517
|
key: message.edit,
|
|
731
518
|
editedMessage: m,
|
|
732
519
|
timestampMs: Date.now(),
|
|
733
|
-
type:
|
|
520
|
+
type: WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
if (hasOptionalProperty(message, 'contextInfo') && !!message.contextInfo) {
|
|
525
|
+
const messageType = Object.keys(m)[0];
|
|
526
|
+
const key = m[messageType];
|
|
527
|
+
if ('contextInfo' in key && !!key.contextInfo) {
|
|
528
|
+
key.contextInfo = { ...key.contextInfo, ...message.contextInfo };
|
|
529
|
+
}
|
|
530
|
+
else if (key) {
|
|
531
|
+
key.contextInfo = message.contextInfo;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
if (hasOptionalProperty(message, 'albumParentKey') && !!message.albumParentKey) {
|
|
535
|
+
m.messageContextInfo = {
|
|
536
|
+
...m.messageContextInfo,
|
|
537
|
+
messageAssociation: {
|
|
538
|
+
associationType: WAProto.MessageAssociation.AssociationType.MEDIA_ALBUM,
|
|
539
|
+
parentMessageKey: message.albumParentKey
|
|
734
540
|
}
|
|
735
541
|
};
|
|
736
542
|
}
|
|
737
|
-
if (
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
543
|
+
if (shouldIncludeReportingToken(m)) {
|
|
544
|
+
m.messageContextInfo = m.messageContextInfo || {};
|
|
545
|
+
if (!m.messageContextInfo.messageSecret) {
|
|
546
|
+
m.messageContextInfo.messageSecret = randomBytes(32);
|
|
547
|
+
}
|
|
741
548
|
}
|
|
742
|
-
return
|
|
549
|
+
return WAProto.Message.create(m);
|
|
743
550
|
};
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
551
|
+
export const generateWAMessageFromContent = (jid, message, options) => {
|
|
552
|
+
// set timestamp to now
|
|
553
|
+
// if not specified
|
|
748
554
|
if (!options.timestamp) {
|
|
749
555
|
options.timestamp = new Date();
|
|
750
556
|
}
|
|
751
|
-
const innerMessage =
|
|
752
|
-
const key =
|
|
753
|
-
const timestamp =
|
|
557
|
+
const innerMessage = normalizeMessageContent(message);
|
|
558
|
+
const key = getContentType(innerMessage);
|
|
559
|
+
const timestamp = unixTimestampSeconds(options.timestamp);
|
|
754
560
|
const { quoted, userJid } = options;
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
561
|
+
if (quoted && !isJidNewsletter(jid)) {
|
|
562
|
+
const participant = quoted.key.fromMe
|
|
563
|
+
? userJid // TODO: Add support for LIDs
|
|
564
|
+
: quoted.participant || quoted.key.participant || quoted.key.remoteJid;
|
|
565
|
+
let quotedMsg = normalizeMessageContent(quoted.message);
|
|
566
|
+
const msgType = getContentType(quotedMsg);
|
|
567
|
+
// strip any redundant properties
|
|
568
|
+
quotedMsg = proto.Message.create({ [msgType]: quotedMsg[msgType] });
|
|
569
|
+
const quotedContent = quotedMsg[msgType];
|
|
570
|
+
if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
|
|
571
|
+
delete quotedContent.contextInfo;
|
|
572
|
+
}
|
|
573
|
+
const contextInfo = ('contextInfo' in innerMessage[key] && innerMessage[key]?.contextInfo) || {};
|
|
574
|
+
contextInfo.participant = jidNormalizedUser(participant);
|
|
575
|
+
contextInfo.stanzaId = quoted.key.id;
|
|
576
|
+
contextInfo.quotedMessage = quotedMsg;
|
|
577
|
+
// if a participant is quoted, then it must be a group
|
|
578
|
+
// hence, remoteJid of group must also be entered
|
|
579
|
+
if (jid !== quoted.key.remoteJid) {
|
|
580
|
+
contextInfo.remoteJid = quoted.key.remoteJid;
|
|
581
|
+
}
|
|
582
|
+
if (contextInfo && innerMessage[key]) {
|
|
583
|
+
/* @ts-ignore */
|
|
776
584
|
innerMessage[key].contextInfo = contextInfo;
|
|
777
585
|
}
|
|
778
586
|
}
|
|
779
587
|
if (
|
|
780
|
-
|
|
781
|
-
!!
|
|
782
|
-
|
|
588
|
+
// if we want to send a disappearing message
|
|
589
|
+
!!options?.ephemeralExpiration &&
|
|
590
|
+
// and it's not a protocol message -- delete, toggle disappear message
|
|
783
591
|
key !== 'protocolMessage' &&
|
|
784
|
-
|
|
592
|
+
// already not converted to disappearing message
|
|
785
593
|
key !== 'ephemeralMessage' &&
|
|
786
|
-
|
|
787
|
-
!
|
|
594
|
+
// newsletters don't support ephemeral messages
|
|
595
|
+
!isJidNewsletter(jid)) {
|
|
596
|
+
/* @ts-ignore */
|
|
788
597
|
innerMessage[key].contextInfo = {
|
|
789
598
|
...(innerMessage[key].contextInfo || {}),
|
|
790
|
-
expiration: options.ephemeralExpiration ||
|
|
599
|
+
expiration: options.ephemeralExpiration || WA_DEFAULT_EPHEMERAL
|
|
791
600
|
//ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
|
|
792
601
|
};
|
|
793
602
|
}
|
|
794
|
-
message =
|
|
603
|
+
message = WAProto.Message.create(message);
|
|
795
604
|
const messageJSON = {
|
|
796
605
|
key: {
|
|
797
606
|
remoteJid: jid,
|
|
798
607
|
fromMe: true,
|
|
799
|
-
id:
|
|
608
|
+
id: options?.messageId || generateMessageIDV2()
|
|
800
609
|
},
|
|
801
610
|
message: message,
|
|
802
611
|
messageTimestamp: timestamp,
|
|
803
612
|
messageStubParameters: [],
|
|
804
|
-
participant:
|
|
805
|
-
status:
|
|
613
|
+
participant: isJidGroup(jid) || isJidStatusBroadcast(jid) ? userJid : undefined, // TODO: Add support for LIDs
|
|
614
|
+
status: WAMessageStatus.PENDING
|
|
806
615
|
};
|
|
807
|
-
return
|
|
616
|
+
return WAProto.WebMessageInfo.fromObject(messageJSON);
|
|
808
617
|
};
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, { newsletter: (0, WABinary_1.isJidNewsletter)(jid), ...options }), options);
|
|
618
|
+
export const generateWAMessage = async (jid, content, options) => {
|
|
619
|
+
// ensure msg ID is with every log
|
|
620
|
+
options.logger = options?.logger?.child({ msgId: options.messageId });
|
|
621
|
+
// Pass jid in the options to generateWAMessageContent
|
|
622
|
+
return generateWAMessageFromContent(jid, await generateWAMessageContent(content, { ...options, jid }), options);
|
|
815
623
|
};
|
|
816
|
-
exports.generateWAMessage = generateWAMessage;
|
|
817
624
|
/** Get the key to access the true type of content */
|
|
818
|
-
const getContentType = (content) => {
|
|
625
|
+
export const getContentType = (content) => {
|
|
819
626
|
if (content) {
|
|
820
627
|
const keys = Object.keys(content);
|
|
821
628
|
const key = keys.find(k => (k === 'conversation' || k.includes('Message')) && k !== 'senderKeyDistributionMessage');
|
|
822
629
|
return key;
|
|
823
630
|
}
|
|
824
631
|
};
|
|
825
|
-
exports.getContentType = getContentType;
|
|
826
632
|
/**
|
|
827
633
|
* Normalizes ephemeral, view once messages to regular message content
|
|
828
634
|
* Eg. image messages in ephemeral messages, in view once messages etc.
|
|
829
635
|
* @param content
|
|
830
636
|
* @returns
|
|
831
637
|
*/
|
|
832
|
-
const normalizeMessageContent = (content) => {
|
|
638
|
+
export const normalizeMessageContent = (content) => {
|
|
833
639
|
if (!content) {
|
|
834
640
|
return undefined;
|
|
835
641
|
}
|
|
836
|
-
|
|
642
|
+
// set max iterations to prevent an infinite loop
|
|
837
643
|
for (let i = 0; i < 5; i++) {
|
|
838
644
|
const inner = getFutureProofMessage(content);
|
|
839
645
|
if (!inner) {
|
|
@@ -843,38 +649,22 @@ const normalizeMessageContent = (content) => {
|
|
|
843
649
|
}
|
|
844
650
|
return content;
|
|
845
651
|
function getFutureProofMessage(message) {
|
|
846
|
-
return (
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|| (message === null || message === void 0 ? void 0 : message.eventCoverImage)
|
|
856
|
-
|| (message === null || message === void 0 ? void 0 : message.statusMentionMessage)
|
|
857
|
-
|| (message === null || message === void 0 ? void 0 : message.pollCreationOptionImageMessage)
|
|
858
|
-
|| (message === null || message === void 0 ? void 0 : message.associatedChildMessage)
|
|
859
|
-
|| (message === null || message === void 0 ? void 0 : message.groupStatusMentionMessage)
|
|
860
|
-
|| (message === null || message === void 0 ? void 0 : message.pollCreationMessageV4)
|
|
861
|
-
|| (message === null || message === void 0 ? void 0 : message.pollCreationMessageV5)
|
|
862
|
-
|| (message === null || message === void 0 ? void 0 : message.statusAddYours)
|
|
863
|
-
|| (message === null || message === void 0 ? void 0 : message.groupStatusMessage)
|
|
864
|
-
|| (message === null || message === void 0 ? void 0 : message.limitSharingMessage)
|
|
865
|
-
|| (message === null || message === void 0 ? void 0 : message.botTaskMessage)
|
|
866
|
-
|| (message === null || message === void 0 ? void 0 : message.questionMessage)
|
|
867
|
-
|| (message === null || message === void 0 ? void 0 : message.groupStatusMessageV2)
|
|
868
|
-
|| (message === null || message === void 0 ? void 0 : message.botForwardedMessage));
|
|
652
|
+
return (message?.ephemeralMessage ||
|
|
653
|
+
message?.viewOnceMessage ||
|
|
654
|
+
message?.documentWithCaptionMessage ||
|
|
655
|
+
message?.viewOnceMessageV2 ||
|
|
656
|
+
message?.viewOnceMessageV2Extension ||
|
|
657
|
+
message?.editedMessage ||
|
|
658
|
+
message?.associatedChildMessage ||
|
|
659
|
+
message?.groupStatusMessage ||
|
|
660
|
+
message?.groupStatusMessageV2);
|
|
869
661
|
}
|
|
870
662
|
};
|
|
871
|
-
exports.normalizeMessageContent = normalizeMessageContent;
|
|
872
663
|
/**
|
|
873
664
|
* Extract the true message content from a message
|
|
874
665
|
* Eg. extracts the inner message from a disappearing message/view once message
|
|
875
666
|
*/
|
|
876
|
-
const extractMessageContent = (content) => {
|
|
877
|
-
var _a, _b, _c, _d, _e, _f;
|
|
667
|
+
export const extractMessageContent = (content) => {
|
|
878
668
|
const extractFromTemplateMessage = (msg) => {
|
|
879
669
|
if (msg.imageMessage) {
|
|
880
670
|
return { imageMessage: msg.imageMessage };
|
|
@@ -890,39 +680,39 @@ const extractMessageContent = (content) => {
|
|
|
890
680
|
}
|
|
891
681
|
else {
|
|
892
682
|
return {
|
|
893
|
-
conversation: 'contentText' in msg
|
|
894
|
-
? msg.contentText
|
|
895
|
-
: ('hydratedContentText' in msg ? msg.hydratedContentText : '')
|
|
683
|
+
conversation: 'contentText' in msg ? msg.contentText : 'hydratedContentText' in msg ? msg.hydratedContentText : ''
|
|
896
684
|
};
|
|
897
685
|
}
|
|
898
686
|
};
|
|
899
|
-
content =
|
|
900
|
-
if (content
|
|
687
|
+
content = normalizeMessageContent(content);
|
|
688
|
+
if (content?.buttonsMessage) {
|
|
901
689
|
return extractFromTemplateMessage(content.buttonsMessage);
|
|
902
690
|
}
|
|
903
|
-
if (
|
|
904
|
-
return extractFromTemplateMessage(
|
|
691
|
+
if (content?.templateMessage?.hydratedFourRowTemplate) {
|
|
692
|
+
return extractFromTemplateMessage(content?.templateMessage?.hydratedFourRowTemplate);
|
|
905
693
|
}
|
|
906
|
-
if (
|
|
907
|
-
return extractFromTemplateMessage(
|
|
694
|
+
if (content?.templateMessage?.hydratedTemplate) {
|
|
695
|
+
return extractFromTemplateMessage(content?.templateMessage?.hydratedTemplate);
|
|
908
696
|
}
|
|
909
|
-
if (
|
|
910
|
-
return extractFromTemplateMessage(
|
|
697
|
+
if (content?.templateMessage?.fourRowTemplate) {
|
|
698
|
+
return extractFromTemplateMessage(content?.templateMessage?.fourRowTemplate);
|
|
911
699
|
}
|
|
912
700
|
return content;
|
|
913
701
|
};
|
|
914
|
-
exports.extractMessageContent = extractMessageContent;
|
|
915
702
|
/**
|
|
916
703
|
* Returns the device predicted by message ID
|
|
917
704
|
*/
|
|
918
|
-
const getDevice = (id) => /^3A.{18}$/.test(id)
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
705
|
+
export const getDevice = (id) => /^3A.{18}$/.test(id)
|
|
706
|
+
? 'ios'
|
|
707
|
+
: /^3E.{20}$/.test(id)
|
|
708
|
+
? 'web'
|
|
709
|
+
: /^(.{21}|.{32})$/.test(id)
|
|
710
|
+
? 'android'
|
|
711
|
+
: /^(3F|.{18}$)/.test(id)
|
|
712
|
+
? 'desktop'
|
|
713
|
+
: 'unknown';
|
|
924
714
|
/** Upserts a receipt in the message */
|
|
925
|
-
const updateMessageWithReceipt = (msg, receipt) => {
|
|
715
|
+
export const updateMessageWithReceipt = (msg, receipt) => {
|
|
926
716
|
msg.userReceipt = msg.userReceipt || [];
|
|
927
717
|
const recp = msg.userReceipt.find(m => m.userJid === receipt.userJid);
|
|
928
718
|
if (recp) {
|
|
@@ -932,40 +722,43 @@ const updateMessageWithReceipt = (msg, receipt) => {
|
|
|
932
722
|
msg.userReceipt.push(receipt);
|
|
933
723
|
}
|
|
934
724
|
};
|
|
935
|
-
exports.updateMessageWithReceipt = updateMessageWithReceipt;
|
|
936
725
|
/** Update the message with a new reaction */
|
|
937
|
-
const updateMessageWithReaction = (msg, reaction) => {
|
|
938
|
-
const authorID =
|
|
939
|
-
const reactions = (msg.reactions || [])
|
|
940
|
-
.filter(r => (0, generics_1.getKeyAuthor)(r.key) !== authorID);
|
|
726
|
+
export const updateMessageWithReaction = (msg, reaction) => {
|
|
727
|
+
const authorID = getKeyAuthor(reaction.key);
|
|
728
|
+
const reactions = (msg.reactions || []).filter(r => getKeyAuthor(r.key) !== authorID);
|
|
941
729
|
reaction.text = reaction.text || '';
|
|
942
730
|
reactions.push(reaction);
|
|
943
731
|
msg.reactions = reactions;
|
|
944
732
|
};
|
|
945
|
-
exports.updateMessageWithReaction = updateMessageWithReaction;
|
|
946
733
|
/** Update the message with a new poll update */
|
|
947
|
-
const updateMessageWithPollUpdate = (msg, update) => {
|
|
948
|
-
|
|
949
|
-
const
|
|
950
|
-
|
|
951
|
-
.filter(r => (0, generics_1.getKeyAuthor)(r.pollUpdateMessageKey) !== authorID);
|
|
952
|
-
if ((_b = (_a = update.vote) === null || _a === void 0 ? void 0 : _a.selectedOptions) === null || _b === void 0 ? void 0 : _b.length) {
|
|
734
|
+
export const updateMessageWithPollUpdate = (msg, update) => {
|
|
735
|
+
const authorID = getKeyAuthor(update.pollUpdateMessageKey);
|
|
736
|
+
const reactions = (msg.pollUpdates || []).filter(r => getKeyAuthor(r.pollUpdateMessageKey) !== authorID);
|
|
737
|
+
if (update.vote?.selectedOptions?.length) {
|
|
953
738
|
reactions.push(update);
|
|
954
739
|
}
|
|
955
740
|
msg.pollUpdates = reactions;
|
|
956
741
|
};
|
|
957
|
-
|
|
742
|
+
/** Update the message with a new event response */
|
|
743
|
+
export const updateMessageWithEventResponse = (msg, update) => {
|
|
744
|
+
const authorID = getKeyAuthor(update.eventResponseMessageKey);
|
|
745
|
+
const responses = (msg.eventResponses || []).filter(r => getKeyAuthor(r.eventResponseMessageKey) !== authorID);
|
|
746
|
+
responses.push(update);
|
|
747
|
+
msg.eventResponses = responses;
|
|
748
|
+
};
|
|
958
749
|
/**
|
|
959
750
|
* Aggregates all poll updates in a poll.
|
|
960
751
|
* @param msg the poll creation message
|
|
961
752
|
* @param meId your jid
|
|
962
753
|
* @returns A list of options & their voters
|
|
963
754
|
*/
|
|
964
|
-
function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
965
|
-
|
|
966
|
-
|
|
755
|
+
export function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
756
|
+
const opts = message?.pollCreationMessage?.options ||
|
|
757
|
+
message?.pollCreationMessageV2?.options ||
|
|
758
|
+
message?.pollCreationMessageV3?.options ||
|
|
759
|
+
[];
|
|
967
760
|
const voteHashMap = opts.reduce((acc, opt) => {
|
|
968
|
-
const hash =
|
|
761
|
+
const hash = sha256(Buffer.from(opt.optionName || '')).toString();
|
|
969
762
|
acc[hash] = {
|
|
970
763
|
name: opt.optionName || '',
|
|
971
764
|
voters: []
|
|
@@ -987,13 +780,36 @@ function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
|
987
780
|
};
|
|
988
781
|
data = voteHashMap[hash];
|
|
989
782
|
}
|
|
990
|
-
voteHashMap[hash].voters.push(
|
|
783
|
+
voteHashMap[hash].voters.push(getKeyAuthor(update.pollUpdateMessageKey, meId));
|
|
991
784
|
}
|
|
992
785
|
}
|
|
993
786
|
return Object.values(voteHashMap);
|
|
994
787
|
}
|
|
788
|
+
/**
|
|
789
|
+
* Aggregates all event responses in an event message.
|
|
790
|
+
* @param msg the event creation message
|
|
791
|
+
* @param meId your jid
|
|
792
|
+
* @returns A list of response types & their responders
|
|
793
|
+
*/
|
|
794
|
+
export function getAggregateResponsesInEventMessage({ eventResponses }, meId) {
|
|
795
|
+
const responseTypes = ['GOING', 'NOT_GOING', 'MAYBE'];
|
|
796
|
+
const responseMap = {};
|
|
797
|
+
for (const type of responseTypes) {
|
|
798
|
+
responseMap[type] = {
|
|
799
|
+
response: type,
|
|
800
|
+
responders: []
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
for (const update of eventResponses || []) {
|
|
804
|
+
const responseType = update.eventResponse || 'UNKNOWN';
|
|
805
|
+
if (responseType !== 'UNKNOWN' && responseMap[responseType]) {
|
|
806
|
+
responseMap[responseType].responders.push(getKeyAuthor(update.eventResponseMessageKey, meId));
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
return Object.values(responseMap);
|
|
810
|
+
}
|
|
995
811
|
/** Given a list of message keys, aggregates them by chat & sender. Useful for sending read receipts in bulk */
|
|
996
|
-
const aggregateMessageKeysNotFromMe = (keys) => {
|
|
812
|
+
export const aggregateMessageKeysNotFromMe = (keys) => {
|
|
997
813
|
const keyMap = {};
|
|
998
814
|
for (const { remoteJid, id, participant, fromMe } of keys) {
|
|
999
815
|
if (!fromMe) {
|
|
@@ -1010,40 +826,34 @@ const aggregateMessageKeysNotFromMe = (keys) => {
|
|
|
1010
826
|
}
|
|
1011
827
|
return Object.values(keyMap);
|
|
1012
828
|
};
|
|
1013
|
-
exports.aggregateMessageKeysNotFromMe = aggregateMessageKeysNotFromMe;
|
|
1014
829
|
const REUPLOAD_REQUIRED_STATUS = [410, 404];
|
|
1015
830
|
/**
|
|
1016
831
|
* Downloads the given message. Throws an error if it's not a media message
|
|
1017
832
|
*/
|
|
1018
|
-
const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
1019
|
-
const result = await downloadMsg()
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
message = await ctx.reuploadRequest(message);
|
|
1029
|
-
const result = await downloadMsg();
|
|
1030
|
-
return result;
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
833
|
+
export const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
834
|
+
const result = await downloadMsg().catch(async (error) => {
|
|
835
|
+
if (ctx &&
|
|
836
|
+
typeof error?.status === 'number' && // treat errors with status as HTTP failures requiring reupload
|
|
837
|
+
REUPLOAD_REQUIRED_STATUS.includes(error.status)) {
|
|
838
|
+
ctx.logger.info({ key: message.key }, 'sending reupload media request...');
|
|
839
|
+
// request reupload
|
|
840
|
+
message = await ctx.reuploadRequest(message);
|
|
841
|
+
const result = await downloadMsg();
|
|
842
|
+
return result;
|
|
1033
843
|
}
|
|
1034
844
|
throw error;
|
|
1035
845
|
});
|
|
1036
846
|
return result;
|
|
1037
847
|
async function downloadMsg() {
|
|
1038
|
-
const mContent =
|
|
848
|
+
const mContent = extractMessageContent(message.message);
|
|
1039
849
|
if (!mContent) {
|
|
1040
|
-
throw new
|
|
850
|
+
throw new Boom('No message present', { statusCode: 400, data: message });
|
|
1041
851
|
}
|
|
1042
|
-
const contentType =
|
|
1043
|
-
let mediaType = contentType
|
|
852
|
+
const contentType = getContentType(mContent);
|
|
853
|
+
let mediaType = contentType?.replace('Message', '');
|
|
1044
854
|
const media = mContent[contentType];
|
|
1045
855
|
if (!media || typeof media !== 'object' || (!('url' in media) && !('thumbnailDirectPath' in media))) {
|
|
1046
|
-
throw new
|
|
856
|
+
throw new Boom(`"${contentType}" message is not a media message`);
|
|
1047
857
|
}
|
|
1048
858
|
let download;
|
|
1049
859
|
if ('thumbnailDirectPath' in media && !('url' in media)) {
|
|
@@ -1056,7 +866,7 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
|
1056
866
|
else {
|
|
1057
867
|
download = media;
|
|
1058
868
|
}
|
|
1059
|
-
const stream = await
|
|
869
|
+
const stream = await downloadContentFromMessage(download, mediaType, options);
|
|
1060
870
|
if (type === 'buffer') {
|
|
1061
871
|
const bufferArray = [];
|
|
1062
872
|
for await (const chunk of stream) {
|
|
@@ -1067,37 +877,17 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
|
1067
877
|
return stream;
|
|
1068
878
|
}
|
|
1069
879
|
};
|
|
1070
|
-
exports.downloadMediaMessage = downloadMediaMessage;
|
|
1071
880
|
/** Checks whether the given message is a media message; if it is returns the inner content */
|
|
1072
|
-
const assertMediaContent = (content) => {
|
|
1073
|
-
content =
|
|
1074
|
-
const mediaContent =
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
881
|
+
export const assertMediaContent = (content) => {
|
|
882
|
+
content = extractMessageContent(content);
|
|
883
|
+
const mediaContent = content?.documentMessage ||
|
|
884
|
+
content?.imageMessage ||
|
|
885
|
+
content?.videoMessage ||
|
|
886
|
+
content?.audioMessage ||
|
|
887
|
+
content?.stickerMessage;
|
|
1079
888
|
if (!mediaContent) {
|
|
1080
|
-
throw new
|
|
889
|
+
throw new Boom('given message is not a media message', { statusCode: 400, data: content });
|
|
1081
890
|
}
|
|
1082
891
|
return mediaContent;
|
|
1083
892
|
};
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
const toJid = (id) => {
|
|
1087
|
-
if (!id)
|
|
1088
|
-
return '';
|
|
1089
|
-
if (id.endsWith('@lid'))
|
|
1090
|
-
return id.replace('@lid', '@s.whatsapp.net');
|
|
1091
|
-
if (id.includes('@'))
|
|
1092
|
-
return id;
|
|
1093
|
-
return `${id}@s.whatsapp.net`;
|
|
1094
|
-
};
|
|
1095
|
-
exports.toJid = toJid;
|
|
1096
|
-
const getSenderLid = (message) => {
|
|
1097
|
-
const sender = message.key.participant || message.key.remoteJid;
|
|
1098
|
-
const user = (0, WABinary_1.jidDecode)(sender)?.user || '';
|
|
1099
|
-
const lid = (0, WABinary_1.jidEncode)(user, 'lid');
|
|
1100
|
-
console.log('sender lid:', lid);
|
|
1101
|
-
return { jid: sender, lid };
|
|
1102
|
-
};
|
|
1103
|
-
exports.getSenderLid = getSenderLid;
|
|
893
|
+
//# sourceMappingURL=messages.js.map
|