@violetix/baileys 0.5.5 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1530 -2009
- package/WAProto/index.d.ts +14030 -14586
- package/WAProto/index.js +58426 -88874
- package/lib/Defaults/index.d.ts +2 -7
- package/lib/Defaults/index.js +5 -20
- package/lib/Signal/Group/sender-key-message.js +19 -1
- package/lib/Signal/libsignal.js +82 -29
- package/lib/Signal/xeddsa-fast.js +114 -0
- package/lib/Socket/Client/types.js +6 -8
- package/lib/Socket/Client/websocket.js +3 -38
- package/lib/Socket/business.d.ts +0 -3
- package/lib/Socket/chats.d.ts +0 -3
- package/lib/Socket/chats.js +18 -45
- package/lib/Socket/communities.d.ts +0 -3
- package/lib/Socket/graphql.js +3 -7
- package/lib/Socket/groups.d.ts +0 -3
- package/lib/Socket/groups.js +3 -8
- package/lib/Socket/index.d.ts +15 -17
- package/lib/Socket/messages-recv.d.ts +0 -3
- package/lib/Socket/messages-recv.js +43 -127
- package/lib/Socket/messages-send.d.ts +0 -4
- package/lib/Socket/messages-send.js +63 -191
- package/lib/Socket/newsletter.d.ts +0 -3
- package/lib/Socket/newsletter.js +1 -2
- package/lib/Socket/newsletter.js.map +1 -1
- package/lib/Socket/socket.d.ts +0 -9
- package/lib/Socket/socket.js +53 -341
- package/lib/Store/make-in-memory-store.js +30 -41
- package/lib/Types/Auth.d.ts +2 -60
- package/lib/Types/Bussines.d.ts +2 -9
- package/lib/Types/Call.d.ts +2 -22
- package/lib/Types/Chat.d.ts +1 -2
- package/lib/Types/Contact.d.ts +2 -11
- package/lib/Types/Events.d.ts +2 -41
- package/lib/Types/GroupMetadata.d.ts +2 -36
- package/lib/Types/Message.d.ts +1 -11
- package/lib/Types/Product.d.ts +2 -5
- package/lib/Types/Signal.d.ts +2 -10
- package/lib/Types/Socket.d.ts +2 -33
- package/lib/Types/USync.d.ts +2 -9
- package/lib/Types/index.d.ts +1 -3
- package/lib/Utils/auth-utils.d.ts +2 -3
- package/lib/Utils/auth-utils.js +53 -37
- package/lib/Utils/business.js +11 -25
- package/lib/Utils/chat-utils.js +4 -6
- package/lib/Utils/decode-wa-message.js +2 -2
- package/lib/Utils/event-buffer.js +12 -21
- package/lib/Utils/generics.d.ts +5 -5
- package/lib/Utils/generics.js +7 -25
- package/lib/Utils/history.d.ts +1 -2
- package/lib/Utils/history.js +83 -137
- package/lib/Utils/index.d.ts +0 -4
- package/lib/Utils/index.js +0 -4
- package/lib/Utils/listener-guard.js +0 -2
- package/lib/Utils/message-retry-manager.js +0 -20
- package/lib/Utils/messages-media.d.ts +8 -39
- package/lib/Utils/messages-media.js +89 -218
- package/lib/Utils/messages.d.ts +0 -1
- package/lib/Utils/messages.js +36 -122
- package/lib/Utils/process-message.d.ts +0 -18
- package/lib/Utils/process-message.js +47 -99
- package/lib/Utils/rich-message-utils.js +4 -3
- package/lib/Utils/use-multi-file-auth-state.d.ts +3 -5
- package/lib/Utils/use-multi-file-auth-state.js +6 -27
- package/lib/Utils/use-single-file-auth-state.d.ts +1 -1
- package/lib/Utils/use-single-file-auth-state.js +3 -12
- package/lib/WABinary/types.d.ts +2 -6
- package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +3 -6
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +2 -3
- package/lib/WAUSync/USyncQuery.d.ts +1 -1
- package/lib/WAUSync/USyncQuery.js +4 -7
- package/package.json +107 -123
- package/lib/Utils/a2ui.d.ts +0 -50
- package/lib/Utils/a2ui.js +0 -168
- package/lib/Utils/anchor-guard.d.ts +0 -71
- package/lib/Utils/anchor-guard.js +0 -404
- package/lib/Utils/connection-manager.d.ts +0 -44
- package/lib/Utils/connection-manager.js +0 -258
- package/lib/Utils/ignore-key.d.ts +0 -51
- package/lib/Utils/ignore-key.js +0 -176
package/lib/Utils/messages.js
CHANGED
|
@@ -6,7 +6,6 @@ import { proto } from '../../WAProto/index.js';
|
|
|
6
6
|
import { CALL_AUDIO_PREFIX, CALL_VIDEO_PREFIX, DONATE_URL, LIBRARY_NAME, MEDIA_KEYS, URL_REGEX, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
|
|
7
7
|
import { AssociationType, ButtonHeaderType, ButtonType, CarouselCardType, ListType, ProtocolType, WAMessageStatus, WAProto } from '../Types/index.js';
|
|
8
8
|
import { isLidUser, isPnUser, isJidGroup, isJidNewsletter, isJidStatusBroadcast, jidNormalizedUser } from '../WABinary/index.js';
|
|
9
|
-
import { buildA2UIWidget } from './a2ui.js';
|
|
10
9
|
import { sha256 } from './crypto.js';
|
|
11
10
|
import { generateMessageIDV2, getKeyAuthor, unixTimestampSeconds } from './generics.js';
|
|
12
11
|
import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, getAudioWaveform, getImageProcessingLibrary, getRawMediaUploadData, getStream, toBuffer } from './messages-media.js';
|
|
@@ -50,7 +49,7 @@ export const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) =>
|
|
|
50
49
|
const assertColor = async (color) => {
|
|
51
50
|
let assertedColor;
|
|
52
51
|
if (typeof color === 'number') {
|
|
53
|
-
assertedColor = color
|
|
52
|
+
assertedColor = color > 0 ? color : 0xffffffff + Number(color) + 1;
|
|
54
53
|
}
|
|
55
54
|
else {
|
|
56
55
|
let hex = color.trim().replace('#', '');
|
|
@@ -58,18 +57,8 @@ const assertColor = async (color) => {
|
|
|
58
57
|
hex = 'FF' + hex.padStart(6, '0');
|
|
59
58
|
}
|
|
60
59
|
assertedColor = parseInt(hex, 16);
|
|
60
|
+
return assertedColor;
|
|
61
61
|
}
|
|
62
|
-
return assertedColor;
|
|
63
|
-
};
|
|
64
|
-
/**
|
|
65
|
-
* Option identifier for an image poll: WhatsApp hashes the option name, appends the base64
|
|
66
|
-
* media hash, and hashes that — `sha256(hex(sha256(name)) + base64(fileSha256))`. A vote carries
|
|
67
|
-
* this hash, not the name, so it has to match byte for byte.
|
|
68
|
-
*/
|
|
69
|
-
export const hashImagePollOption = (optionName, fileSha256) => {
|
|
70
|
-
const nameHash = sha256(Buffer.from(String(optionName), 'utf-8')).toString('hex');
|
|
71
|
-
const mediaHashB64 = fileSha256 ? Buffer.from(fileSha256).toString('base64') : '';
|
|
72
|
-
return sha256(Buffer.from(nameHash + mediaHashB64, 'utf-8')).toString('hex');
|
|
73
62
|
};
|
|
74
63
|
export const prepareWAMessageMedia = async (message, options) => {
|
|
75
64
|
const logger = options.logger;
|
|
@@ -88,12 +77,11 @@ export const prepareWAMessageMedia = async (message, options) => {
|
|
|
88
77
|
};
|
|
89
78
|
delete uploadData[mediaType];
|
|
90
79
|
// check if cacheable + generate cache key
|
|
91
|
-
const isNewsletter = !!options.jid && isJidNewsletter(options.jid);
|
|
92
80
|
const cacheableKey = typeof uploadData.media === 'object' &&
|
|
93
81
|
'url' in uploadData.media &&
|
|
94
82
|
!!uploadData.media.url &&
|
|
95
83
|
!!options.mediaCache &&
|
|
96
|
-
|
|
84
|
+
mediaType + ':' + uploadData.media.url.toString();
|
|
97
85
|
if (mediaType === 'document' && !uploadData.fileName) {
|
|
98
86
|
uploadData.fileName = 'file';
|
|
99
87
|
}
|
|
@@ -105,12 +93,12 @@ export const prepareWAMessageMedia = async (message, options) => {
|
|
|
105
93
|
if (mediaBuff) {
|
|
106
94
|
logger?.debug({ cacheableKey }, 'got media cache hit');
|
|
107
95
|
const obj = proto.Message.decode(mediaBuff);
|
|
108
|
-
|
|
109
|
-
const key = obj.ptvMessage ? 'ptvMessage' : `${mediaType}Message`;
|
|
96
|
+
const key = `${mediaType}Message`;
|
|
110
97
|
Object.assign(obj[key], { ...uploadData, media: undefined });
|
|
111
98
|
return obj;
|
|
112
99
|
}
|
|
113
100
|
}
|
|
101
|
+
const isNewsletter = !!options.jid && isJidNewsletter(options.jid);
|
|
114
102
|
if (isNewsletter) {
|
|
115
103
|
logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
|
|
116
104
|
const { filePath, fileSha256, fileLength } = await getRawMediaUploadData(uploadData.media, options.mediaTypeOverride || mediaType, logger);
|
|
@@ -151,9 +139,9 @@ export const prepareWAMessageMedia = async (message, options) => {
|
|
|
151
139
|
const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
|
|
152
140
|
const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && typeof uploadData['jpegThumbnail'] === 'undefined';
|
|
153
141
|
const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true && typeof uploadData.waveform === 'undefined';
|
|
154
|
-
const requiresAudioBackground = options.backgroundColor
|
|
142
|
+
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
|
|
155
143
|
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
|
|
156
|
-
const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength
|
|
144
|
+
const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength } = await encryptedStream(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
157
145
|
logger,
|
|
158
146
|
saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
|
|
159
147
|
opts: options.options
|
|
@@ -219,7 +207,6 @@ export const prepareWAMessageMedia = async (message, options) => {
|
|
|
219
207
|
fileSha256,
|
|
220
208
|
fileLength,
|
|
221
209
|
mediaKeyTimestamp: unixTimestampSeconds(),
|
|
222
|
-
...(streamingSidecar ? { streamingSidecar } : {}),
|
|
223
210
|
...uploadData,
|
|
224
211
|
media: undefined
|
|
225
212
|
})
|
|
@@ -259,7 +246,7 @@ const prepareProductMessage = async (message, options) => {
|
|
|
259
246
|
*/
|
|
260
247
|
// Lia@Changes 21-04-26 --- Enhanced prepareStickerPackMessage
|
|
261
248
|
const prepareStickerPackMessage = async (message, options) => {
|
|
262
|
-
const { cover, stickers = [], name = '📦 Sticker Pack', publisher = 'GitHub:
|
|
249
|
+
const { cover, stickers = [], name = '📦 Sticker Pack', publisher = 'GitHub: itsliaaa', description = '🏷️ itsliaaa/baileys' } = message;
|
|
263
250
|
if (stickers.length > 60) {
|
|
264
251
|
throw new Boom('Sticker pack exceeds the maximum limit of 60 stickers', { statusCode: 400 });
|
|
265
252
|
}
|
|
@@ -665,42 +652,46 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
665
652
|
thumbnailEncSha256: imageMessage.fileEncSha256
|
|
666
653
|
};
|
|
667
654
|
}
|
|
668
|
-
if (options.backgroundColor
|
|
655
|
+
if (options.backgroundColor) {
|
|
669
656
|
extContent.backgroundArgb = await assertColor(options.backgroundColor);
|
|
670
657
|
}
|
|
671
658
|
if (options.font) {
|
|
672
659
|
extContent.font = options.font;
|
|
673
660
|
}
|
|
674
|
-
if (options.textColorArgb
|
|
661
|
+
if (options.textColorArgb) {
|
|
675
662
|
extContent.textArgb = await assertColor(options.textColorArgb);
|
|
676
663
|
}
|
|
677
664
|
m.extendedTextMessage = extContent;
|
|
678
665
|
}
|
|
679
|
-
// Lia@Changes 08-09-26 --- Accept group status content as { groupStatusMessage | groupStatusMessageV2 | groupStatus: { text|image|video|audio } }
|
|
680
666
|
else if (hasNonNullishProperty(message, 'groupStatusMessage') ||
|
|
681
|
-
hasNonNullishProperty(message, 'groupStatusMessageV2')
|
|
682
|
-
|
|
683
|
-
|
|
667
|
+
hasNonNullishProperty(message, 'groupStatusMessageV2')) {
|
|
668
|
+
const inner = hasNonNullishProperty(message, 'groupStatusMessageV2')
|
|
669
|
+
? message.groupStatusMessageV2
|
|
670
|
+
: message.groupStatusMessage;
|
|
684
671
|
const innerMessage = inner?.message || inner;
|
|
685
672
|
if (!innerMessage || typeof innerMessage !== 'object') {
|
|
686
673
|
throw new Boom('Invalid group status message', { statusCode: 400 }); // Lia@Note 08-09-26 --- To avoid bug 👀
|
|
687
674
|
}
|
|
688
675
|
const { backgroundColor, font, color, ...contentBody } = innerMessage;
|
|
689
|
-
if (backgroundColor)
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
if (font !== undefined) {
|
|
693
|
-
options.font = font;
|
|
694
|
-
}
|
|
695
|
-
if (color) {
|
|
696
|
-
options.textColorArgb = color;
|
|
697
|
-
}
|
|
676
|
+
if (backgroundColor) options.backgroundColor = backgroundColor;
|
|
677
|
+
if (font !== undefined) options.font = font;
|
|
678
|
+
if (color) options.textColorArgb = color;
|
|
698
679
|
m = await generateWAMessageContent(contentBody, options);
|
|
699
680
|
if (!hasOptionalProperty(m, 'groupStatusMessageV2')) {
|
|
700
681
|
message.groupStatus = true; // Lia@Note 08-09-26 --- let the wrap below normalize it into groupStatusMessageV2
|
|
701
682
|
}
|
|
702
|
-
|
|
703
|
-
|
|
683
|
+
}
|
|
684
|
+
// Lia@Changes 08-09-26 --- Accept nested group status content { groupStatus: { text|image|video|audio } }
|
|
685
|
+
else if (hasNonNullishProperty(message, 'groupStatus') &&
|
|
686
|
+
message.groupStatus &&
|
|
687
|
+
typeof message.groupStatus === 'object') {
|
|
688
|
+
const { backgroundColor, font, color, ...contentBody } = message.groupStatus;
|
|
689
|
+
if (backgroundColor) options.backgroundColor = backgroundColor;
|
|
690
|
+
if (font !== undefined) options.font = font;
|
|
691
|
+
if (color) options.textColorArgb = color;
|
|
692
|
+
m = await generateWAMessageContent(contentBody, options);
|
|
693
|
+
if (!hasOptionalProperty(m, 'groupStatusMessageV2')) {
|
|
694
|
+
message.groupStatus = true;
|
|
704
695
|
}
|
|
705
696
|
}
|
|
706
697
|
else if (hasNonNullishProperty(message, 'contacts')) {
|
|
@@ -885,10 +876,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
885
876
|
selectableOptionsCount: 1
|
|
886
877
|
};
|
|
887
878
|
}
|
|
888
|
-
else if (message.poll.hideVoter || message.poll.canAddOption) {
|
|
889
|
-
// only poll v6 carries hideParticipantName / allowAddOption; older versions drop them
|
|
890
|
-
m.pollCreationMessageV6 = pollCreationMessage;
|
|
891
|
-
}
|
|
892
879
|
else if (message.poll.selectableCount === 1) {
|
|
893
880
|
//poll v3 is for single select polls
|
|
894
881
|
m.pollCreationMessageV3 = pollCreationMessage;
|
|
@@ -903,36 +890,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
903
890
|
messageSecret: message.poll.messageSecret || randomBytes(32)
|
|
904
891
|
};
|
|
905
892
|
}
|
|
906
|
-
// Image poll: the parent carries only the option names and their hashes. The images
|
|
907
|
-
// themselves travel as separate pollCreationOptionImageMessage children, associated back
|
|
908
|
-
// to this message by MEDIA_POLL — sendMessage sends those after the parent.
|
|
909
|
-
else if (hasNonNullishProperty(message, 'imagePoll')) {
|
|
910
|
-
if (!Array.isArray(message.imagePoll.options) || !message.imagePoll.options.length) {
|
|
911
|
-
throw new Boom('Invalid imagePoll options', { statusCode: 400 });
|
|
912
|
-
}
|
|
913
|
-
const selectableOptionsCount = message.imagePoll.selectableCount ?? 1;
|
|
914
|
-
if (selectableOptionsCount < 0 || selectableOptionsCount > message.imagePoll.options.length) {
|
|
915
|
-
throw new Boom(`imagePoll.selectableCount should be >= 0 and <= ${message.imagePoll.options.length}`, {
|
|
916
|
-
statusCode: 400
|
|
917
|
-
});
|
|
918
|
-
}
|
|
919
|
-
const missingHash = message.imagePoll.options.find(option => !option.optionHash);
|
|
920
|
-
if (missingHash) {
|
|
921
|
-
throw new Boom('imagePoll options must be prepared with hashImagePollOption; send via sendMessage instead of building the content by hand', { statusCode: 400 });
|
|
922
|
-
}
|
|
923
|
-
m.pollCreationMessageV3 = {
|
|
924
|
-
name: message.imagePoll.name,
|
|
925
|
-
selectableOptionsCount,
|
|
926
|
-
options: message.imagePoll.options.map(option => ({
|
|
927
|
-
optionName: option.optionName,
|
|
928
|
-
optionHash: option.optionHash
|
|
929
|
-
})),
|
|
930
|
-
pollContentType: proto.Message.PollContentType.IMAGE
|
|
931
|
-
};
|
|
932
|
-
m.messageContextInfo = {
|
|
933
|
-
messageSecret: message.imagePoll.messageSecret || randomBytes(32)
|
|
934
|
-
};
|
|
935
|
-
}
|
|
936
893
|
// Lia@Changes 08-02-26 --- Add poll result snapshot message
|
|
937
894
|
else if (hasNonNullishProperty(message, 'pollResult')) {
|
|
938
895
|
const pollResultSnapshotMessage = {
|
|
@@ -1036,12 +993,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1036
993
|
}
|
|
1037
994
|
};
|
|
1038
995
|
}
|
|
1039
|
-
// An A2UI widget has no base content of its own — the interactive chain below replaces `m`
|
|
1040
|
-
// wholesale. Without this it falls through to the media branch and is rejected as a media
|
|
1041
|
-
// message, so a widget would need a dummy `text` to send at all.
|
|
1042
|
-
else if (hasNonNullishProperty(message, 'a2ui')) {
|
|
1043
|
-
m = {};
|
|
1044
|
-
}
|
|
1045
996
|
else {
|
|
1046
997
|
m = await prepareWAMessageMedia(message, options);
|
|
1047
998
|
}
|
|
@@ -1165,31 +1116,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1165
1116
|
}
|
|
1166
1117
|
};
|
|
1167
1118
|
}
|
|
1168
|
-
// A2UI widget. `nativeFlowMessage` is always set, even empty: it is what the client keys the
|
|
1169
|
-
// interactive render off, and it is also what makes the socket attach the <biz> node.
|
|
1170
|
-
else if (hasNonNullishProperty(message, 'a2ui')) {
|
|
1171
|
-
const interactiveMessage = {
|
|
1172
|
-
bloksWidget: buildA2UIWidget(message.a2ui, {
|
|
1173
|
-
type: message.a2uiType,
|
|
1174
|
-
wrapped: message.a2uiWrapped !== false
|
|
1175
|
-
}),
|
|
1176
|
-
nativeFlowMessage: hasNonNullishProperty(message, 'nativeFlow')
|
|
1177
|
-
? prepareNativeFlowButtons(message)
|
|
1178
|
-
: { messageParamsJson: '' }
|
|
1179
|
-
};
|
|
1180
|
-
// singleScreen drops the surrounding bubble so the widget is the whole message
|
|
1181
|
-
if (!message.singleScreen) {
|
|
1182
|
-
interactiveMessage.header = { hasMediaAttachment: false };
|
|
1183
|
-
interactiveMessage.body = { text: message.text || '' };
|
|
1184
|
-
interactiveMessage.footer = { text: message.footer || '' };
|
|
1185
|
-
}
|
|
1186
|
-
m = {
|
|
1187
|
-
interactiveMessage,
|
|
1188
|
-
messageContextInfo: {
|
|
1189
|
-
messageSecret: message.messageSecret || randomBytes(32)
|
|
1190
|
-
}
|
|
1191
|
-
};
|
|
1192
|
-
}
|
|
1193
1119
|
else if (hasNonNullishProperty(message, 'nativeFlow')) {
|
|
1194
1120
|
const interactiveMessage = {
|
|
1195
1121
|
nativeFlowMessage: prepareNativeFlowButtons(message)
|
|
@@ -1547,17 +1473,10 @@ export const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1547
1473
|
// newsletters don't support ephemeral messages
|
|
1548
1474
|
!isNewsletter) {
|
|
1549
1475
|
/* @ts-ignore */
|
|
1550
|
-
// WA Web stamps the chat's disappearing-mode setting alongside the TTL; without it the
|
|
1551
|
-
// peer warns that the message will not disappear. Callers pass the setting timestamp
|
|
1552
|
-
// when they track it (there is no chat store here), the trigger defaults to CHAT_SETTING.
|
|
1553
1476
|
innerMessage[key].contextInfo = {
|
|
1554
1477
|
...(innerMessage[key].contextInfo || {}),
|
|
1555
|
-
expiration: options.ephemeralExpiration || WA_DEFAULT_EPHEMERAL
|
|
1556
|
-
|
|
1557
|
-
disappearingMode: {
|
|
1558
|
-
initiator: proto.DisappearingMode.Initiator.CHANGED_IN_CHAT,
|
|
1559
|
-
trigger: options.disappearingModeTrigger ?? proto.DisappearingMode.Trigger.CHAT_SETTING
|
|
1560
|
-
}
|
|
1478
|
+
expiration: options.ephemeralExpiration || WA_DEFAULT_EPHEMERAL
|
|
1479
|
+
//ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
|
|
1561
1480
|
};
|
|
1562
1481
|
}
|
|
1563
1482
|
// Lia@Changes 30-01-26 --- Add deviceListMetadata inside messageContextInfo for private chat
|
|
@@ -1743,12 +1662,9 @@ export const updateMessageWithEventResponse = (msg, update) => {
|
|
|
1743
1662
|
* @returns A list of options & their voters
|
|
1744
1663
|
*/
|
|
1745
1664
|
export function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
1746
|
-
message = normalizeMessageContent(message);
|
|
1747
1665
|
const opts = message?.pollCreationMessage?.options ||
|
|
1748
1666
|
message?.pollCreationMessageV2?.options ||
|
|
1749
1667
|
message?.pollCreationMessageV3?.options ||
|
|
1750
|
-
message?.pollCreationMessageV5?.options ||
|
|
1751
|
-
message?.pollCreationMessageV6?.options ||
|
|
1752
1668
|
[];
|
|
1753
1669
|
const voteHashMap = opts.reduce((acc, opt) => {
|
|
1754
1670
|
const hash = sha256(Buffer.from(opt.optionName || '')).toString();
|
|
@@ -1794,10 +1710,7 @@ export function getAggregateResponsesInEventMessage({ eventResponses }, meId) {
|
|
|
1794
1710
|
};
|
|
1795
1711
|
}
|
|
1796
1712
|
for (const update of eventResponses || []) {
|
|
1797
|
-
const
|
|
1798
|
-
const responseType = typeof response === 'number'
|
|
1799
|
-
? proto.Message.EventResponseMessage.EventResponseType[response]
|
|
1800
|
-
: response || 'UNKNOWN';
|
|
1713
|
+
const responseType = update.eventResponse || 'UNKNOWN';
|
|
1801
1714
|
if (responseType !== 'UNKNOWN' && responseMap[responseType]) {
|
|
1802
1715
|
responseMap[responseType].responders.push(getKeyAuthor(update.eventResponseMessageKey, meId));
|
|
1803
1716
|
}
|
|
@@ -1828,8 +1741,9 @@ const REUPLOAD_REQUIRED_STATUS = [410, 404];
|
|
|
1828
1741
|
*/
|
|
1829
1742
|
export const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
1830
1743
|
const result = await downloadMsg().catch(async (error) => {
|
|
1831
|
-
|
|
1832
|
-
|
|
1744
|
+
if (ctx &&
|
|
1745
|
+
typeof error?.status === 'number' && // treat errors with status as HTTP failures requiring reupload
|
|
1746
|
+
REUPLOAD_REQUIRED_STATUS.includes(error.status)) {
|
|
1833
1747
|
ctx.logger.info({ key: message.key }, 'sending reupload media request...');
|
|
1834
1748
|
// request reupload
|
|
1835
1749
|
message = await ctx.reuploadRequest(message);
|
|
@@ -1957,4 +1871,4 @@ export const shouldIncludeBizBinaryNode = (message) => !!(message.buttonsMessage
|
|
|
1957
1871
|
message.templateMessage ||
|
|
1958
1872
|
(message.interactiveMessage &&
|
|
1959
1873
|
message.interactiveMessage.nativeFlowMessage));
|
|
1960
|
-
//# sourceMappingURL=messages.js.map
|
|
1874
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -19,24 +19,6 @@ export function decryptPollVote({ encPayload, encIv }: {
|
|
|
19
19
|
* @param ctx additional info about the event required for decryption
|
|
20
20
|
* @returns event response message
|
|
21
21
|
*/
|
|
22
|
-
export function decryptPollVoteWithFallback(vote: {
|
|
23
|
-
encPayload: Uint8Array;
|
|
24
|
-
encIv: Uint8Array;
|
|
25
|
-
}, ctx: {
|
|
26
|
-
pollCreatorJids: (string | undefined | null)[];
|
|
27
|
-
voterJids: (string | undefined | null)[];
|
|
28
|
-
pollMsgId: string;
|
|
29
|
-
pollEncKey: Uint8Array;
|
|
30
|
-
}): proto.Message.PollVoteMessage;
|
|
31
|
-
export function decryptEventResponseWithFallback(response: {
|
|
32
|
-
encPayload: Uint8Array;
|
|
33
|
-
encIv: Uint8Array;
|
|
34
|
-
}, ctx: {
|
|
35
|
-
eventCreatorJids: (string | undefined | null)[];
|
|
36
|
-
responderJids: (string | undefined | null)[];
|
|
37
|
-
eventMsgId: string;
|
|
38
|
-
eventEncKey: Uint8Array;
|
|
39
|
-
}): proto.Message.EventResponseMessage;
|
|
40
22
|
export function decryptEventResponse({ encPayload, encIv }: {
|
|
41
23
|
encPayload: any;
|
|
42
24
|
encIv: any;
|
|
@@ -114,10 +114,7 @@ export const isRealMessage = (message) => {
|
|
|
114
114
|
hasSomeContent &&
|
|
115
115
|
!normalizedContent?.protocolMessage &&
|
|
116
116
|
!normalizedContent?.reactionMessage &&
|
|
117
|
-
!normalizedContent?.pollUpdateMessage
|
|
118
|
-
// edit envelopes and event responses are not new chat messages (unread/timestamp bump)
|
|
119
|
-
!normalizedContent?.secretEncryptedMessage &&
|
|
120
|
-
!normalizedContent?.encEventResponseMessage);
|
|
117
|
+
!normalizedContent?.pollUpdateMessage);
|
|
121
118
|
};
|
|
122
119
|
export const shouldIncrementChatUnread = (message) => !message.key.fromMe && !message.messageStubType;
|
|
123
120
|
/**
|
|
@@ -163,41 +160,6 @@ export function decryptPollVote({ encPayload, encIv }, { pollCreatorJid, pollMsg
|
|
|
163
160
|
return Buffer.from(txt);
|
|
164
161
|
}
|
|
165
162
|
}
|
|
166
|
-
const uniqueJids = (jids) => [...new Set(jids.filter(j => typeof j === 'string' && j.length > 0))];
|
|
167
|
-
/**
|
|
168
|
-
* Try every (creator, voter) pair until one decrypts. Voters derive the key from the creator
|
|
169
|
-
* JID in `pollCreationMessageKey` (LID after the addressing migration, PN before), while the
|
|
170
|
-
* poll secret may have been stored under the other form, so a single pair is not enough.
|
|
171
|
-
*/
|
|
172
|
-
export function decryptPollVoteWithFallback(vote, { pollCreatorJids, voterJids, pollMsgId, pollEncKey }) {
|
|
173
|
-
let lastErr;
|
|
174
|
-
for (const pollCreatorJid of uniqueJids(pollCreatorJids)) {
|
|
175
|
-
for (const voterJid of uniqueJids(voterJids)) {
|
|
176
|
-
try {
|
|
177
|
-
return decryptPollVote(vote, { pollCreatorJid, pollMsgId, pollEncKey, voterJid });
|
|
178
|
-
}
|
|
179
|
-
catch (err) {
|
|
180
|
-
lastErr = err;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
throw lastErr || new Boom('no jid candidates to decrypt poll vote', { statusCode: 400 });
|
|
185
|
-
}
|
|
186
|
-
/** Same candidate walk as {@link decryptPollVoteWithFallback} for event responses. */
|
|
187
|
-
export function decryptEventResponseWithFallback(response, { eventCreatorJids, responderJids, eventMsgId, eventEncKey }) {
|
|
188
|
-
let lastErr;
|
|
189
|
-
for (const eventCreatorJid of uniqueJids(eventCreatorJids)) {
|
|
190
|
-
for (const responderJid of uniqueJids(responderJids)) {
|
|
191
|
-
try {
|
|
192
|
-
return decryptEventResponse(response, { eventCreatorJid, eventMsgId, eventEncKey, responderJid });
|
|
193
|
-
}
|
|
194
|
-
catch (err) {
|
|
195
|
-
lastErr = err;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
throw lastErr || new Boom('no jid candidates to decrypt event response', { statusCode: 400 });
|
|
200
|
-
}
|
|
201
163
|
/**
|
|
202
164
|
* Decrypt an event response
|
|
203
165
|
* @param response encrypted event response
|
|
@@ -348,14 +310,14 @@ const processMessage = async (message, { shouldProcessHistoryMsg, placeholderRes
|
|
|
348
310
|
switch (protocolMsg.type) {
|
|
349
311
|
case proto.Message.ProtocolMessage.Type.HISTORY_SYNC_NOTIFICATION:
|
|
350
312
|
const histNotification = protocolMsg.historySyncNotification;
|
|
351
|
-
const process = shouldProcessHistoryMsg;
|
|
313
|
+
const process = false; // shouldProcessHistoryMsg; // FORCE DISABLED
|
|
352
314
|
const isLatest = !creds.processedHistoryMessages?.length;
|
|
353
315
|
logger?.info({
|
|
354
316
|
histNotification,
|
|
355
317
|
process,
|
|
356
318
|
id: message.key.id,
|
|
357
319
|
isLatest
|
|
358
|
-
}, 'got history notification');
|
|
320
|
+
}, 'got history notification (ignored by force)');
|
|
359
321
|
if (process) {
|
|
360
322
|
// TODO: investigate
|
|
361
323
|
if (histNotification.syncType !== proto.HistorySync.HistorySyncType.ON_DEMAND) {
|
|
@@ -535,34 +497,23 @@ const processMessage = async (message, { shouldProcessHistoryMsg, placeholderRes
|
|
|
535
497
|
if (eventMsg) {
|
|
536
498
|
try {
|
|
537
499
|
const meIdNormalised = jidNormalizedUser(meId);
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
const eventCreatorKey = jidNormalizedUser(creationMsgKey.participant || creationMsgKey.remoteJid);
|
|
542
|
-
const eventCreatorAlt = isLidUser(eventCreatorKey)
|
|
500
|
+
// all jids need to be PN
|
|
501
|
+
const eventCreatorKey = creationMsgKey.participant || creationMsgKey.remoteJid;
|
|
502
|
+
const eventCreatorPn = isLidUser(eventCreatorKey)
|
|
543
503
|
? await signalRepository.lidMapping.getPNForLID(eventCreatorKey)
|
|
544
|
-
:
|
|
545
|
-
const
|
|
546
|
-
const
|
|
547
|
-
? [meIdNormalised, meLidNormalised]
|
|
548
|
-
: isLidUser(eventCreatorKey)
|
|
549
|
-
? [eventCreatorAltNorm, eventCreatorKey]
|
|
550
|
-
: [eventCreatorKey, eventCreatorAltNorm];
|
|
551
|
-
const responderJids = [
|
|
552
|
-
getKeyAuthor(message.key, meIdNormalised),
|
|
553
|
-
jidNormalizedUser(message.key.participant || message.key.remoteJid || ''),
|
|
554
|
-
message.key.fromMe ? meLidNormalised : undefined
|
|
555
|
-
];
|
|
504
|
+
: eventCreatorKey;
|
|
505
|
+
const eventCreatorJid = getKeyAuthor({ remoteJid: jidNormalizedUser(eventCreatorPn), fromMe: meIdNormalised === eventCreatorPn }, meIdNormalised);
|
|
506
|
+
const responderJid = getKeyAuthor(message.key, meIdNormalised);
|
|
556
507
|
const eventEncKey = eventMsg?.messageContextInfo?.messageSecret;
|
|
557
508
|
if (!eventEncKey) {
|
|
558
509
|
logger?.warn({ creationMsgKey }, 'event response: missing messageSecret for decryption');
|
|
559
510
|
}
|
|
560
511
|
else {
|
|
561
|
-
const responseMsg =
|
|
512
|
+
const responseMsg = decryptEventResponse(encEventResponse, {
|
|
562
513
|
eventEncKey,
|
|
563
|
-
|
|
514
|
+
eventCreatorJid,
|
|
564
515
|
eventMsgId: creationMsgKey.id,
|
|
565
|
-
|
|
516
|
+
responderJid
|
|
566
517
|
});
|
|
567
518
|
const eventResponse = {
|
|
568
519
|
eventResponseMessageKey: message.key,
|
|
@@ -741,38 +692,28 @@ const processMessage = async (message, { shouldProcessHistoryMsg, placeholderRes
|
|
|
741
692
|
emitGroupRequestJoin(participant, action, method);
|
|
742
693
|
break;
|
|
743
694
|
}
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
//
|
|
748
|
-
|
|
749
|
-
const
|
|
750
|
-
if
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
695
|
+
} /* else if(content?.pollUpdateMessage) {
|
|
696
|
+
const creationMsgKey = content.pollUpdateMessage.pollCreationMessageKey!
|
|
697
|
+
// we need to fetch the poll creation message to get the poll enc key
|
|
698
|
+
// TODO: make standalone, remove getMessage reference
|
|
699
|
+
// TODO: Remove entirely
|
|
700
|
+
const pollMsg = await getMessage(creationMsgKey)
|
|
701
|
+
if(pollMsg) {
|
|
702
|
+
const meIdNormalised = jidNormalizedUser(meId)
|
|
703
|
+
const pollCreatorJid = getKeyAuthor(creationMsgKey, meIdNormalised)
|
|
704
|
+
const voterJid = getKeyAuthor(message.key, meIdNormalised)
|
|
705
|
+
const pollEncKey = pollMsg.messageContextInfo?.messageSecret!
|
|
706
|
+
|
|
754
707
|
try {
|
|
755
|
-
const
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
: [getKeyAuthor(creationMsgKey, meIdNormalised), creatorPrimary, creatorAlt ? jidNormalizedUser(creatorAlt) : undefined];
|
|
765
|
-
const voterJids = [
|
|
766
|
-
getKeyAuthor(message.key, meIdNormalised),
|
|
767
|
-
jidNormalizedUser(message.key.participant || message.key.remoteJid || ''),
|
|
768
|
-
message.key.fromMe ? meLidNormalised : undefined
|
|
769
|
-
];
|
|
770
|
-
const vote = decryptPollVoteWithFallback(content.pollUpdateMessage.vote, {
|
|
771
|
-
pollEncKey,
|
|
772
|
-
pollCreatorJids,
|
|
773
|
-
voterJids,
|
|
774
|
-
pollMsgId: creationMsgKey.id
|
|
775
|
-
});
|
|
708
|
+
const voteMsg = decryptPollVote(
|
|
709
|
+
content.pollUpdateMessage.vote!,
|
|
710
|
+
{
|
|
711
|
+
pollEncKey,
|
|
712
|
+
pollCreatorJid,
|
|
713
|
+
pollMsgId: creationMsgKey.id!,
|
|
714
|
+
voterJid,
|
|
715
|
+
}
|
|
716
|
+
)
|
|
776
717
|
ev.emit('messages.update', [
|
|
777
718
|
{
|
|
778
719
|
key: creationMsgKey,
|
|
@@ -780,19 +721,26 @@ const processMessage = async (message, { shouldProcessHistoryMsg, placeholderRes
|
|
|
780
721
|
pollUpdates: [
|
|
781
722
|
{
|
|
782
723
|
pollUpdateMessageKey: message.key,
|
|
783
|
-
vote,
|
|
784
|
-
senderTimestampMs:
|
|
724
|
+
vote: voteMsg,
|
|
725
|
+
senderTimestampMs: (content.pollUpdateMessage.senderTimestampMs! as Long).toNumber(),
|
|
785
726
|
}
|
|
786
727
|
]
|
|
787
728
|
}
|
|
788
729
|
}
|
|
789
|
-
])
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
|
|
730
|
+
])
|
|
731
|
+
} catch(err) {
|
|
732
|
+
logger?.warn(
|
|
733
|
+
{ err, creationMsgKey },
|
|
734
|
+
'failed to decrypt poll vote'
|
|
735
|
+
)
|
|
793
736
|
}
|
|
737
|
+
} else {
|
|
738
|
+
logger?.warn(
|
|
739
|
+
{ creationMsgKey },
|
|
740
|
+
'poll creation message not found, cannot decrypt update'
|
|
741
|
+
)
|
|
794
742
|
}
|
|
795
|
-
|
|
743
|
+
} */
|
|
796
744
|
if (Object.keys(chat).length > 1) {
|
|
797
745
|
ev.emit('chats.update', [chat]);
|
|
798
746
|
}
|
|
@@ -99,7 +99,7 @@ export const toUnified = (submessages, uuid) => ({
|
|
|
99
99
|
})
|
|
100
100
|
});
|
|
101
101
|
export const prepareRichResponseMessage = (content) => {
|
|
102
|
-
const { alignment, code, contentText, disclaimerText, footerText, headerText, imageText, inlineImage, inlineVideo, items, language
|
|
102
|
+
const { alignment, code, contentText, disclaimerText, footerText, headerText, imageText, inlineImage, inlineVideo, items, language, latex, links, noHeading, posts, products, suggested, richResponse, table, tapLinkUrl, title } = content;
|
|
103
103
|
let submessages = [];
|
|
104
104
|
if (Array.isArray(richResponse)) {
|
|
105
105
|
submessages = richResponse.map((submessage) => {
|
|
@@ -198,6 +198,7 @@ export const prepareRichResponseMessage = (content) => {
|
|
|
198
198
|
});
|
|
199
199
|
}
|
|
200
200
|
if (code) {
|
|
201
|
+
language ||= 'javascript';
|
|
201
202
|
submessages.push({
|
|
202
203
|
messageType: RichSubMessageType.CODE,
|
|
203
204
|
codeMetadata: {
|
|
@@ -236,7 +237,7 @@ export const prepareRichResponseMessage = (content) => {
|
|
|
236
237
|
submessages.push({
|
|
237
238
|
messageType: RichSubMessageType.LATEX,
|
|
238
239
|
latexMetadata: {
|
|
239
|
-
text
|
|
240
|
+
text,
|
|
240
241
|
expressions: latex
|
|
241
242
|
}
|
|
242
243
|
});
|
|
@@ -366,4 +367,4 @@ export const wrapToBotForwardedMessage = (richResponseMessage) => ({
|
|
|
366
367
|
message: { richResponseMessage }
|
|
367
368
|
}
|
|
368
369
|
});
|
|
369
|
-
//# sourceMappingURL=rich-message-utils.js.map
|
|
370
|
+
//# sourceMappingURL=rich-message-utils.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function useMultiFileAuthState(folder: any
|
|
1
|
+
export function useMultiFileAuthState(folder: any): Promise<{
|
|
2
2
|
state: {
|
|
3
3
|
creds: any;
|
|
4
4
|
keys: {
|
|
@@ -6,8 +6,6 @@ export function useMultiFileAuthState(folder: any, logger?: any): Promise<{
|
|
|
6
6
|
set: (data: any) => Promise<void>;
|
|
7
7
|
};
|
|
8
8
|
};
|
|
9
|
-
saveCreds: () =>
|
|
10
|
-
_flushCreds: () => Promise<void>;
|
|
11
|
-
_destroy: () => void;
|
|
9
|
+
saveCreds: () => Promise<any>;
|
|
12
10
|
}>;
|
|
13
|
-
//# sourceMappingURL=use-multi-file-auth-state.d.ts.map
|
|
11
|
+
//# sourceMappingURL=use-multi-file-auth-state.d.ts.map
|