@badzz88/baileys 8.5.7 → 8.5.9
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 +337 -1055
- package/WAProto/WAProto.proto +284 -264
- package/WAProto/index.js +5 -5
- package/engine-requirements.js +7 -15
- package/lib/Defaults/index.js +130 -187
- package/lib/Signal/Group/ciphertext-message.js +11 -14
- package/lib/Signal/Group/group-session-builder.js +29 -91
- package/lib/Signal/Group/group_cipher.js +81 -88
- package/lib/Signal/Group/index.js +12 -136
- package/lib/Signal/Group/keyhelper.js +15 -70
- package/lib/Signal/Group/sender-chain-key.js +25 -31
- package/lib/Signal/Group/sender-key-distribution-message.js +62 -65
- package/lib/Signal/Group/sender-key-message.js +65 -68
- package/lib/Signal/Group/sender-key-name.js +41 -43
- package/lib/Signal/Group/sender-key-record.js +40 -43
- package/lib/Signal/Group/sender-key-state.js +83 -96
- package/lib/Signal/Group/sender-message-key.js +25 -29
- package/lib/Signal/libsignal.js +425 -453
- package/lib/Signal/lid-mapping.js +276 -259
- package/lib/Socket/Client/index.js +3 -30
- package/lib/Socket/Client/types.js +10 -12
- package/lib/Socket/Client/websocket.js +53 -61
- package/lib/Socket/business.js +379 -422
- package/lib/Socket/chats.js +1193 -1816
- package/lib/Socket/communities.js +431 -549
- package/lib/Socket/graphql.js +672 -612
- package/lib/Socket/groups.js +374 -764
- package/lib/Socket/index.js +17 -38
- package/lib/Socket/interop.js +417 -503
- package/lib/Socket/messages-recv.js +1915 -2441
- package/lib/Socket/messages-send.js +1213 -1630
- package/lib/Socket/mex.js +9 -15
- package/lib/Socket/newsletter.js +746 -808
- package/lib/Socket/privacy.js +310 -441
- package/lib/Socket/socket.js +1025 -1022
- package/lib/Socket/username.js +8 -15
- package/lib/Store/index.js +10 -36
- package/lib/Store/make-cache-manager-store.js +80 -85
- package/lib/Store/make-in-memory-store.js +231 -591
- package/lib/Store/make-ordered-dictionary.js +72 -78
- package/lib/Store/object-repository.js +28 -25
- package/lib/Types/Auth.js +2 -38
- package/lib/Types/Bussines.js +2 -2
- package/lib/Types/Call.js +2 -2
- package/lib/Types/Chat.js +8 -4
- package/lib/Types/Contact.js +2 -2
- package/lib/Types/Events.js +2 -2
- package/lib/Types/GroupMetadata.js +2 -2
- package/lib/Types/Label.js +24 -26
- package/lib/Types/LabelAssociation.js +6 -8
- package/lib/Types/Message.js +11 -95
- package/lib/Types/Mex.js +111 -112
- package/lib/Types/Product.js +2 -2
- package/lib/Types/Signal.js +2 -2
- package/lib/Types/Socket.js +3 -2
- package/lib/Types/State.js +56 -70
- package/lib/Types/USync.js +2 -2
- package/lib/Types/index.js +26 -55
- package/lib/Utils/auth-utils.js +288 -292
- package/lib/Utils/browser-utils.js +47 -113
- package/lib/Utils/business.js +224 -240
- package/lib/Utils/chat-utils.js +869 -1205
- package/lib/Utils/companion-reg-client-utils.js +34 -41
- package/lib/Utils/crypto.js +107 -144
- package/lib/Utils/decode-wa-message.js +308 -518
- package/lib/Utils/event-buffer.js +611 -596
- package/lib/Utils/generics.js +355 -515
- package/lib/Utils/history.js +134 -244
- package/lib/Utils/identity-change-handler.js +49 -51
- package/lib/Utils/index.js +23 -57
- package/lib/Utils/link-preview.js +77 -135
- package/lib/Utils/logger.js +3 -9
- package/lib/Utils/lt-hash.js +6 -37
- package/lib/Utils/make-mutex.js +33 -36
- package/lib/Utils/message-composer.js +233 -439
- package/lib/Utils/message-retry-manager.js +260 -265
- package/lib/Utils/messages-media.js +829 -855
- package/lib/Utils/messages.js +961 -2528
- package/lib/Utils/noise-handler.js +200 -195
- package/lib/Utils/offline-node-processor.js +33 -35
- package/lib/Utils/pre-key-manager.js +102 -103
- package/lib/Utils/process-message.js +560 -978
- package/lib/Utils/reporting-utils.js +253 -257
- package/lib/Utils/signal.js +195 -218
- package/lib/Utils/stanza-ack.js +29 -31
- package/lib/Utils/sticker.js +109 -144
- package/lib/Utils/sync-action-utils.js +45 -50
- package/lib/Utils/tc-token-utils.js +139 -137
- package/lib/Utils/use-multi-file-auth-state.js +109 -109
- package/lib/Utils/validate-connection.js +202 -218
- package/lib/WABinary/constants.js +1299 -1302
- package/lib/WABinary/decode.js +262 -343
- package/lib/WABinary/encode.js +4 -12
- package/lib/WABinary/generic-utils.js +187 -223
- package/lib/WABinary/index.js +6 -33
- package/lib/WABinary/jid-utils.js +88 -351
- package/lib/WABinary/types.js +2 -2
- package/lib/WAM/BinaryInfo.js +9 -12
- package/lib/WAM/constants.js +22853 -39486
- package/lib/WAM/encode.js +140 -132
- package/lib/WAM/index.js +4 -31
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +21 -23
- package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +9 -9
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +7 -7
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +10 -10
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +7 -7
- package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +11 -12
- package/lib/WAUSync/Protocols/USyncLIDProtocol.js +4 -5
- package/lib/WAUSync/Protocols/USyncPictureProtocol.js +7 -7
- package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +7 -8
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +7 -7
- package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +8 -8
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +7 -7
- package/lib/WAUSync/Protocols/index.js +12 -39
- package/lib/WAUSync/USyncQuery.js +67 -49
- package/lib/WAUSync/USyncUser.js +11 -5
- package/lib/WAUSync/index.js +3 -31
- package/lib/index.js +15 -48
- package/package.json +129 -99
- package/LICENSE +0 -21
- package/lib/Defaults/phonenumber-mcc.json +0 -223
- package/lib/Socket/aigroups.js +0 -240
- package/lib/Socket/interactive-handler.js +0 -522
- package/lib/Socket/managed-account.js +0 -183
- package/lib/Socket/registration.js +0 -427
- package/lib/Socket/text-router.js +0 -83
- package/lib/Types/Newsletter.js +0 -121
- package/lib/Utils/command-loader.d.ts +0 -31
- package/lib/Utils/command-loader.js +0 -100
- package/lib/Utils/consumer-application.js +0 -107
- package/lib/Utils/curve25519-js.js +0 -275
- package/lib/Utils/group-history.js +0 -60
- package/lib/Utils/jid-display-normalization.js +0 -218
- package/lib/Utils/meta-ai-msmsg.js +0 -262
- package/lib/Utils/native-bridge.js +0 -82
- package/lib/Utils/session-pool.d.ts +0 -16
- package/lib/Utils/session-pool.js +0 -94
- package/lib/Utils/sticker.d.ts +0 -17
- package/lib/Utils/view-once-cache.d.ts +0 -9
- package/lib/Utils/view-once-cache.js +0 -79
- package/lib/Utils/voip-rekey.js +0 -22
- package/lib/antiban.js +0 -4637
package/lib/Utils/generics.js
CHANGED
|
@@ -1,563 +1,403 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const WABinary_1 = require('../WABinary')
|
|
54
|
-
const crypto_2 = require('./crypto')
|
|
55
|
-
exports.BufferJSON = {
|
|
56
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
57
|
-
replacer: (k, value) => {
|
|
58
|
-
if (Buffer.isBuffer(value) || value instanceof Uint8Array || value?.type === 'Buffer') {
|
|
59
|
-
return { type: 'Buffer', data: Buffer.from(value?.data || value).toString('base64') }
|
|
60
|
-
}
|
|
61
|
-
return value
|
|
62
|
-
},
|
|
63
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
64
|
-
reviver: (_, value) => {
|
|
65
|
-
if (typeof value === 'object' && value !== null && value.type === 'Buffer' && typeof value.data === 'string') {
|
|
66
|
-
return Buffer.from(value.data, 'base64')
|
|
67
|
-
}
|
|
68
|
-
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
69
|
-
const keys = Object.keys(value)
|
|
70
|
-
if (keys.length > 0 && keys.every(k => !isNaN(parseInt(k, 10)))) {
|
|
71
|
-
const values = Object.values(value)
|
|
72
|
-
if (values.every(v => typeof v === 'number')) {
|
|
73
|
-
return Buffer.from(values)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return value
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
const getKeyAuthor = (key, meId = 'me') =>
|
|
81
|
-
(key?.fromMe ? meId : key?.participantAlt || key?.remoteJidAlt || key?.participant || key?.remoteJid) || ''
|
|
82
|
-
exports.getKeyAuthor = getKeyAuthor
|
|
83
|
-
const isStringNullOrEmpty = value =>
|
|
84
|
-
// eslint-disable-next-line eqeqeq
|
|
85
|
-
value == null || value === ''
|
|
86
|
-
exports.isStringNullOrEmpty = isStringNullOrEmpty
|
|
87
|
-
const writeRandomPadMax16 = msg => {
|
|
88
|
-
const pad = (0, crypto_1.randomBytes)(1)
|
|
89
|
-
const padLength = (pad[0] & 0x0f) + 1
|
|
90
|
-
return Buffer.concat([msg, Buffer.alloc(padLength, padLength)])
|
|
91
|
-
}
|
|
92
|
-
exports.writeRandomPadMax16 = writeRandomPadMax16
|
|
93
|
-
const unpadRandomMax16 = e => {
|
|
94
|
-
const t = new Uint8Array(e)
|
|
95
|
-
if (0 === t.length) {
|
|
96
|
-
throw new Error('unpadPkcs7 given empty bytes')
|
|
97
|
-
}
|
|
98
|
-
var r = t[t.length - 1]
|
|
99
|
-
if (r > t.length) {
|
|
100
|
-
throw new Error(`unpad given ${t.length} bytes, but pad is ${r}`)
|
|
101
|
-
}
|
|
102
|
-
return new Uint8Array(t.buffer, t.byteOffset, t.length - r)
|
|
103
|
-
}
|
|
104
|
-
exports.unpadRandomMax16 = unpadRandomMax16
|
|
1
|
+
import { Boom } from '@hapi/boom';
|
|
2
|
+
import { createHash, randomBytes } from 'crypto';
|
|
3
|
+
import { proto } from '../../WAProto/index.js';
|
|
4
|
+
const baileysVersion = [2, 3000, 1035194821];
|
|
5
|
+
import { DisconnectReason } from '../Types/index.js';
|
|
6
|
+
import { getAllBinaryNodeChildren, jidDecode } from '../WABinary/index.js';
|
|
7
|
+
import { sha256 } from './crypto.js';
|
|
8
|
+
export const BufferJSON = {
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
replacer: (k, value) => {
|
|
11
|
+
if (Buffer.isBuffer(value) || value instanceof Uint8Array || value?.type === 'Buffer') {
|
|
12
|
+
return { type: 'Buffer', data: Buffer.from(value?.data || value).toString('base64') };
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
},
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
reviver: (_, value) => {
|
|
18
|
+
if (typeof value === 'object' && value !== null && value.type === 'Buffer' && typeof value.data === 'string') {
|
|
19
|
+
return Buffer.from(value.data, 'base64');
|
|
20
|
+
}
|
|
21
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
22
|
+
const keys = Object.keys(value);
|
|
23
|
+
if (keys.length > 0 && keys.every(k => !isNaN(parseInt(k, 10)))) {
|
|
24
|
+
const values = Object.values(value);
|
|
25
|
+
if (values.every(v => typeof v === 'number')) {
|
|
26
|
+
return Buffer.from(values);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
export const getKeyAuthor = (key, meId = 'me') => (key?.fromMe ? meId : key?.participantAlt || key?.remoteJidAlt || key?.participant || key?.remoteJid) || '';
|
|
34
|
+
export const isStringNullOrEmpty = (value) =>
|
|
35
|
+
// eslint-disable-next-line eqeqeq
|
|
36
|
+
value == null || value === '';
|
|
37
|
+
export const writeRandomPadMax16 = (msg) => {
|
|
38
|
+
const pad = randomBytes(1);
|
|
39
|
+
const padLength = (pad[0] & 0x0f) + 1;
|
|
40
|
+
return Buffer.concat([msg, Buffer.alloc(padLength, padLength)]);
|
|
41
|
+
};
|
|
42
|
+
export const unpadRandomMax16 = (e) => {
|
|
43
|
+
const t = new Uint8Array(e);
|
|
44
|
+
if (0 === t.length) {
|
|
45
|
+
throw new Error('unpadPkcs7 given empty bytes');
|
|
46
|
+
}
|
|
47
|
+
var r = t[t.length - 1];
|
|
48
|
+
if (r > t.length) {
|
|
49
|
+
throw new Error(`unpad given ${t.length} bytes, but pad is ${r}`);
|
|
50
|
+
}
|
|
51
|
+
return new Uint8Array(t.buffer, t.byteOffset, t.length - r);
|
|
52
|
+
};
|
|
105
53
|
// code is inspired by whatsmeow
|
|
106
|
-
const generateParticipantHashV2 = participants => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return a
|
|
126
|
-
}
|
|
127
|
-
exports.encodeBigEndian = encodeBigEndian
|
|
128
|
-
const toNumber = t => (typeof t === 'object' && t ? ('toNumber' in t ? t.toNumber() : t.low) : t || 0)
|
|
129
|
-
exports.toNumber = toNumber
|
|
54
|
+
export const generateParticipantHashV2 = (participants) => {
|
|
55
|
+
participants.sort();
|
|
56
|
+
const sha256Hash = sha256(Buffer.from(participants.join(''))).toString('base64');
|
|
57
|
+
return '2:' + sha256Hash.slice(0, 6);
|
|
58
|
+
};
|
|
59
|
+
export const encodeWAMessage = (message) => writeRandomPadMax16(proto.Message.encode(message).finish());
|
|
60
|
+
export const generateRegistrationId = () => {
|
|
61
|
+
return Uint16Array.from(randomBytes(2))[0] & 16383;
|
|
62
|
+
};
|
|
63
|
+
export const encodeBigEndian = (e, t = 4) => {
|
|
64
|
+
let r = e;
|
|
65
|
+
const a = new Uint8Array(t);
|
|
66
|
+
for (let i = t - 1; i >= 0; i--) {
|
|
67
|
+
a[i] = 255 & r;
|
|
68
|
+
r >>>= 8;
|
|
69
|
+
}
|
|
70
|
+
return a;
|
|
71
|
+
};
|
|
72
|
+
export const toNumber = (t) => typeof t === 'object' && t ? ('toNumber' in t ? t.toNumber() : t.low) : t || 0;
|
|
130
73
|
/** unix timestamp of a date in seconds */
|
|
131
|
-
const unixTimestampSeconds = (date = new Date()) => Math.floor(date.getTime() / 1000)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
data: {
|
|
189
|
-
stack
|
|
190
|
-
}
|
|
191
|
-
})
|
|
192
|
-
)
|
|
193
|
-
)
|
|
194
|
-
.catch(err => reject(err))
|
|
195
|
-
promise(resolve, reject)
|
|
196
|
-
}).finally(cancel)
|
|
197
|
-
return p
|
|
74
|
+
export const unixTimestampSeconds = (date = new Date()) => Math.floor(date.getTime() / 1000);
|
|
75
|
+
export const debouncedTimeout = (intervalMs = 1000, task) => {
|
|
76
|
+
let timeout;
|
|
77
|
+
return {
|
|
78
|
+
start: (newIntervalMs, newTask) => {
|
|
79
|
+
task = newTask || task;
|
|
80
|
+
intervalMs = newIntervalMs || intervalMs;
|
|
81
|
+
timeout && clearTimeout(timeout);
|
|
82
|
+
timeout = setTimeout(() => task?.(), intervalMs);
|
|
83
|
+
},
|
|
84
|
+
cancel: () => {
|
|
85
|
+
timeout && clearTimeout(timeout);
|
|
86
|
+
timeout = undefined;
|
|
87
|
+
},
|
|
88
|
+
setTask: (newTask) => (task = newTask),
|
|
89
|
+
setInterval: (newInterval) => (intervalMs = newInterval)
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
export const delay = (ms) => delayCancellable(ms).delay;
|
|
93
|
+
export const delayCancellable = (ms) => {
|
|
94
|
+
const stack = new Error().stack;
|
|
95
|
+
let timeout;
|
|
96
|
+
let reject;
|
|
97
|
+
const delay = new Promise((resolve, _reject) => {
|
|
98
|
+
timeout = setTimeout(resolve, ms);
|
|
99
|
+
reject = _reject;
|
|
100
|
+
});
|
|
101
|
+
const cancel = () => {
|
|
102
|
+
clearTimeout(timeout);
|
|
103
|
+
reject(new Boom('Cancelled', {
|
|
104
|
+
statusCode: 500,
|
|
105
|
+
data: {
|
|
106
|
+
stack
|
|
107
|
+
}
|
|
108
|
+
}));
|
|
109
|
+
};
|
|
110
|
+
return { delay, cancel };
|
|
111
|
+
};
|
|
112
|
+
export async function promiseTimeout(ms, promise) {
|
|
113
|
+
if (!ms) {
|
|
114
|
+
return new Promise(promise);
|
|
115
|
+
}
|
|
116
|
+
const stack = new Error().stack;
|
|
117
|
+
// Create a promise that rejects in <ms> milliseconds
|
|
118
|
+
const { delay, cancel } = delayCancellable(ms);
|
|
119
|
+
const p = new Promise((resolve, reject) => {
|
|
120
|
+
delay
|
|
121
|
+
.then(() => reject(new Boom('Timed Out', {
|
|
122
|
+
statusCode: DisconnectReason.timedOut,
|
|
123
|
+
data: {
|
|
124
|
+
stack
|
|
125
|
+
}
|
|
126
|
+
})))
|
|
127
|
+
.catch(err => reject(err));
|
|
128
|
+
promise(resolve, reject);
|
|
129
|
+
}).finally(cancel);
|
|
130
|
+
return p;
|
|
198
131
|
}
|
|
199
132
|
// inspired from whatsmeow code
|
|
200
133
|
// https://github.com/tulir/whatsmeow/blob/64bc969fbe78d31ae0dd443b8d4c80a5d026d07a/send.go#L42
|
|
201
|
-
const generateMessageIDV2 = (userId) => {
|
|
134
|
+
export const generateMessageIDV2 = (userId) => {
|
|
202
135
|
const data = Buffer.alloc(8 + 20 + 16);
|
|
203
136
|
data.writeBigUInt64BE(BigInt(Math.floor(Date.now() / 1000)));
|
|
204
137
|
if (userId) {
|
|
205
|
-
const id =
|
|
138
|
+
const id = jidDecode(userId);
|
|
206
139
|
if (id?.user) {
|
|
207
140
|
data.write(id.user, 8);
|
|
208
141
|
data.write('@c.us', 8 + id.user.length);
|
|
209
142
|
}
|
|
210
143
|
}
|
|
211
|
-
const random =
|
|
144
|
+
const random = randomBytes(16);
|
|
212
145
|
random.copy(data, 28);
|
|
213
|
-
const hash =
|
|
214
|
-
return '
|
|
146
|
+
const hash = createHash('sha256').update(data).digest();
|
|
147
|
+
return 'VINNXSYNC-' + hash.toString('hex').toUpperCase().substring(0, 18);
|
|
215
148
|
};
|
|
216
|
-
|
|
217
|
-
const
|
|
149
|
+
// generate a random ID to attach to a message
|
|
150
|
+
export const generateMessageID = () => 'VINNXSYNC-' + randomBytes(18).toString('hex').toUpperCase();
|
|
151
|
+
export function bindWaitForEvent(ev, event) {
|
|
152
|
+
return async (check, timeoutMs) => {
|
|
153
|
+
let listener;
|
|
154
|
+
let closeListener;
|
|
155
|
+
await promiseTimeout(timeoutMs, (resolve, reject) => {
|
|
156
|
+
closeListener = ({ connection, lastDisconnect }) => {
|
|
157
|
+
if (connection === 'close') {
|
|
158
|
+
reject(lastDisconnect?.error || new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed }));
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
ev.on('connection.update', closeListener);
|
|
162
|
+
listener = async (update) => {
|
|
163
|
+
if (await check(update)) {
|
|
164
|
+
resolve();
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
ev.on(event, listener);
|
|
168
|
+
}).finally(() => {
|
|
169
|
+
ev.off(event, listener);
|
|
170
|
+
ev.off('connection.update', closeListener);
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
export const generateIOSMessageID = () => {
|
|
218
175
|
const prefix = '3A';
|
|
219
|
-
const random =
|
|
176
|
+
const random = randomBytes(9.5); // 19 hex chars = 9.5 bytes
|
|
220
177
|
return (prefix + random.toString('hex')).toUpperCase().substring(0, 21);
|
|
221
178
|
};
|
|
222
|
-
|
|
223
|
-
const generateAndroMessageID = () => {
|
|
179
|
+
export const generateAndroMessageID = () => {
|
|
224
180
|
const prefix = '3A';
|
|
225
|
-
const random =
|
|
181
|
+
const random = randomBytes(16); // 32 hex chars = 16 bytes
|
|
226
182
|
return (random.toString('hex')).toUpperCase().substring(0, 21);
|
|
227
183
|
};
|
|
228
|
-
|
|
229
|
-
// generate a random ID to attach to a message
|
|
230
|
-
const generateMessageID = () => 'XZCYYX-' + (0, crypto_1.randomBytes)(18).toString('hex').toUpperCase()
|
|
231
|
-
exports.generateMessageID = generateMessageID
|
|
232
|
-
function bindWaitForEvent(ev, event) {
|
|
233
|
-
return async (check, timeoutMs) => {
|
|
234
|
-
let listener
|
|
235
|
-
let closeListener
|
|
236
|
-
await promiseTimeout(timeoutMs, (resolve, reject) => {
|
|
237
|
-
closeListener = ({ connection, lastDisconnect }) => {
|
|
238
|
-
if (connection === 'close') {
|
|
239
|
-
reject(
|
|
240
|
-
lastDisconnect?.error ||
|
|
241
|
-
new boom_1.Boom('Connection Closed', { statusCode: Types_1.DisconnectReason.connectionClosed })
|
|
242
|
-
)
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
ev.on('connection.update', closeListener)
|
|
246
|
-
listener = async update => {
|
|
247
|
-
if (await check(update)) {
|
|
248
|
-
resolve()
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
ev.on(event, listener)
|
|
252
|
-
}).finally(() => {
|
|
253
|
-
ev.off(event, listener)
|
|
254
|
-
ev.off('connection.update', closeListener)
|
|
255
|
-
})
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
const bindWaitForConnectionUpdate = ev => bindWaitForEvent(ev, 'connection.update')
|
|
259
|
-
exports.bindWaitForConnectionUpdate = bindWaitForConnectionUpdate
|
|
184
|
+
export const bindWaitForConnectionUpdate = (ev) => bindWaitForEvent(ev, 'connection.update');
|
|
260
185
|
/**
|
|
261
186
|
* utility that fetches latest baileys version from the master branch.
|
|
262
187
|
* Use to ensure your WA connection is always on the latest version
|
|
263
188
|
*/
|
|
264
|
-
const fetchLatestBaileysVersion = async (options = {}) => {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
299
|
-
exports.fetchLatestBaileysVersion = fetchLatestBaileysVersion
|
|
189
|
+
export const fetchLatestBaileysVersion = async (options = {}) => {
|
|
190
|
+
const URL = 'https://raw.githubusercontent.com/WhiskeySockets/Baileys/master/src/Defaults/index.ts';
|
|
191
|
+
try {
|
|
192
|
+
const response = await fetch(URL, {
|
|
193
|
+
dispatcher: options.dispatcher,
|
|
194
|
+
method: 'GET',
|
|
195
|
+
headers: options.headers
|
|
196
|
+
});
|
|
197
|
+
if (!response.ok) {
|
|
198
|
+
throw new Boom(`Failed to fetch latest Baileys version: ${response.statusText}`, { statusCode: response.status });
|
|
199
|
+
}
|
|
200
|
+
const text = await response.text();
|
|
201
|
+
// Extract version from line 7 (const version = [...])
|
|
202
|
+
const lines = text.split('\n');
|
|
203
|
+
const versionLine = lines[6]; // Line 7 (0-indexed)
|
|
204
|
+
const versionMatch = versionLine.match(/const version = \[(\d+),\s*(\d+),\s*(\d+)\]/);
|
|
205
|
+
if (versionMatch) {
|
|
206
|
+
const version = [parseInt(versionMatch[1]), parseInt(versionMatch[2]), parseInt(versionMatch[3])];
|
|
207
|
+
return {
|
|
208
|
+
version,
|
|
209
|
+
isLatest: true
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
throw new Error('Could not parse version from Defaults/index.ts');
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
return {
|
|
218
|
+
version: baileysVersion,
|
|
219
|
+
isLatest: false,
|
|
220
|
+
error
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
};
|
|
300
224
|
/**
|
|
301
225
|
* A utility that fetches the latest web version of whatsapp.
|
|
302
226
|
* Use to ensure your WA connection is always on the latest version
|
|
303
227
|
*/
|
|
304
|
-
const fetchLatestWaWebVersion = async (options = {}) => {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
346
|
-
exports.fetchLatestWaWebVersion = fetchLatestWaWebVersion
|
|
228
|
+
export const fetchLatestWaWebVersion = async (options = {}) => {
|
|
229
|
+
try {
|
|
230
|
+
// Absolute minimal headers required to bypass anti-bot detection
|
|
231
|
+
const defaultHeaders = {
|
|
232
|
+
'sec-fetch-site': 'none',
|
|
233
|
+
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
|
|
234
|
+
};
|
|
235
|
+
const headers = { ...defaultHeaders, ...options.headers };
|
|
236
|
+
const response = await fetch('https://web.whatsapp.com/sw.js', {
|
|
237
|
+
...options,
|
|
238
|
+
method: 'GET',
|
|
239
|
+
headers
|
|
240
|
+
});
|
|
241
|
+
if (!response.ok) {
|
|
242
|
+
throw new Boom(`Failed to fetch sw.js: ${response.statusText}`, { statusCode: response.status });
|
|
243
|
+
}
|
|
244
|
+
const data = await response.text();
|
|
245
|
+
const regex = /\\?"client_revision\\?":\s*(\d+)/;
|
|
246
|
+
const match = data.match(regex);
|
|
247
|
+
if (!match?.[1]) {
|
|
248
|
+
return {
|
|
249
|
+
version: baileysVersion,
|
|
250
|
+
isLatest: false,
|
|
251
|
+
error: {
|
|
252
|
+
message: 'Could not find client revision in the fetched content'
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
const clientRevision = match[1];
|
|
257
|
+
return {
|
|
258
|
+
version: [2, 3000, +clientRevision],
|
|
259
|
+
isLatest: true
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
return {
|
|
264
|
+
version: baileysVersion,
|
|
265
|
+
isLatest: false,
|
|
266
|
+
error
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
};
|
|
347
270
|
/** unique message tag prefix for MD clients */
|
|
348
|
-
const generateMdTagPrefix = () => {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
}
|
|
352
|
-
exports.generateMdTagPrefix = generateMdTagPrefix
|
|
271
|
+
export const generateMdTagPrefix = () => {
|
|
272
|
+
const bytes = randomBytes(4);
|
|
273
|
+
return `${bytes.readUInt16BE()}.${bytes.readUInt16BE(2)}-`;
|
|
274
|
+
};
|
|
353
275
|
const STATUS_MAP = {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
276
|
+
sender: proto.WebMessageInfo.Status.SERVER_ACK,
|
|
277
|
+
played: proto.WebMessageInfo.Status.PLAYED,
|
|
278
|
+
read: proto.WebMessageInfo.Status.READ,
|
|
279
|
+
'read-self': proto.WebMessageInfo.Status.READ
|
|
280
|
+
};
|
|
359
281
|
/**
|
|
360
282
|
* Given a type of receipt, returns what the new status of the message should be
|
|
361
283
|
* @param type type from receipt
|
|
362
284
|
*/
|
|
363
|
-
const getStatusFromReceiptType = type => {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
exports.getStatusFromReceiptType = getStatusFromReceiptType
|
|
285
|
+
export const getStatusFromReceiptType = (type) => {
|
|
286
|
+
const status = STATUS_MAP[type];
|
|
287
|
+
if (typeof type === 'undefined') {
|
|
288
|
+
return proto.WebMessageInfo.Status.DELIVERY_ACK;
|
|
289
|
+
}
|
|
290
|
+
return status;
|
|
291
|
+
};
|
|
371
292
|
const CODE_MAP = {
|
|
372
|
-
|
|
373
|
-
}
|
|
293
|
+
conflict: DisconnectReason.connectionReplaced
|
|
294
|
+
};
|
|
374
295
|
/**
|
|
375
296
|
* Stream errors generally provide a reason, map that to a baileys DisconnectReason
|
|
376
297
|
* @param reason the string reason given, eg. "conflict"
|
|
377
298
|
*/
|
|
378
|
-
const getErrorCodeFromStreamError = node => {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
299
|
+
export const getErrorCodeFromStreamError = (node) => {
|
|
300
|
+
const [reasonNode] = getAllBinaryNodeChildren(node);
|
|
301
|
+
let reason = reasonNode?.tag || 'unknown';
|
|
302
|
+
const statusCode = +(node.attrs.code || CODE_MAP[reason] || DisconnectReason.badSession);
|
|
303
|
+
if (statusCode === DisconnectReason.restartRequired) {
|
|
304
|
+
reason = 'restart required';
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
reason,
|
|
308
|
+
statusCode
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
export const getCallStatusFromNode = ({ tag, attrs }) => {
|
|
312
|
+
let status;
|
|
313
|
+
switch (tag) {
|
|
314
|
+
case 'offer':
|
|
315
|
+
case 'offer_notice':
|
|
316
|
+
status = 'offer';
|
|
317
|
+
break;
|
|
318
|
+
case 'terminate':
|
|
319
|
+
if (attrs.reason === 'timeout') {
|
|
320
|
+
status = 'timeout';
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
//fired when accepted/rejected/timeout/caller hangs up
|
|
324
|
+
status = 'terminate';
|
|
325
|
+
}
|
|
326
|
+
break;
|
|
327
|
+
case 'preaccept':
|
|
328
|
+
status = 'preaccept';
|
|
329
|
+
break;
|
|
330
|
+
case 'transport':
|
|
331
|
+
status = 'transport';
|
|
332
|
+
break;
|
|
333
|
+
case 'relaylatency':
|
|
334
|
+
status = 'relaylatency';
|
|
335
|
+
break;
|
|
336
|
+
case 'reject':
|
|
337
|
+
status = 'reject';
|
|
338
|
+
break;
|
|
339
|
+
case 'accept':
|
|
340
|
+
status = 'accept';
|
|
341
|
+
break;
|
|
342
|
+
default:
|
|
343
|
+
status = 'ringing';
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
return status;
|
|
347
|
+
};
|
|
348
|
+
const UNEXPECTED_SERVER_CODE_TEXT = 'Unexpected server response: ';
|
|
349
|
+
export const getCodeFromWSError = (error) => {
|
|
350
|
+
let statusCode = 500;
|
|
351
|
+
if (error?.message?.includes(UNEXPECTED_SERVER_CODE_TEXT)) {
|
|
352
|
+
const code = +error?.message.slice(UNEXPECTED_SERVER_CODE_TEXT.length);
|
|
353
|
+
if (!Number.isNaN(code) && code >= 400) {
|
|
354
|
+
statusCode = code;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
else if (
|
|
358
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
359
|
+
error?.code?.startsWith('E') ||
|
|
360
|
+
error?.message?.includes('timed out')) {
|
|
361
|
+
// handle ETIMEOUT, ENOTFOUND etc
|
|
362
|
+
statusCode = 408;
|
|
363
|
+
}
|
|
364
|
+
return statusCode;
|
|
365
|
+
};
|
|
438
366
|
/**
|
|
439
367
|
* Is the given platform WA business
|
|
440
368
|
* @param platform AuthenticationCreds.platform
|
|
441
369
|
*/
|
|
442
|
-
const isWABusinessPlatform = platform => {
|
|
443
|
-
|
|
444
|
-
}
|
|
445
|
-
exports.isWABusinessPlatform = isWABusinessPlatform
|
|
370
|
+
export const isWABusinessPlatform = (platform) => {
|
|
371
|
+
return platform === 'smbi' || platform === 'smba';
|
|
372
|
+
};
|
|
446
373
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
447
|
-
function trimUndefined(obj) {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
}
|
|
455
|
-
const CROCKFORD_CHARACTERS = '123456789ABCDEFGHJKLMNPQRSTVWXYZ'
|
|
456
|
-
function bytesToCrockford(buffer) {
|
|
457
|
-
let value = 0
|
|
458
|
-
let bitCount = 0
|
|
459
|
-
const crockford = []
|
|
460
|
-
for (const element of buffer) {
|
|
461
|
-
value = (value << 8) | (element & 0xff)
|
|
462
|
-
bitCount += 8
|
|
463
|
-
while (bitCount >= 5) {
|
|
464
|
-
crockford.push(CROCKFORD_CHARACTERS.charAt((value >>> (bitCount - 5)) & 31))
|
|
465
|
-
bitCount -= 5
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
if (bitCount > 0) {
|
|
469
|
-
crockford.push(CROCKFORD_CHARACTERS.charAt((value << (5 - bitCount)) & 31))
|
|
470
|
-
}
|
|
471
|
-
return crockford.join('')
|
|
472
|
-
}
|
|
473
|
-
function encodeNewsletterMessage(message) {
|
|
474
|
-
return index_js_1.proto.Message.encode(message).finish()
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
/**
|
|
478
|
-
* Add human-like jitter to a base delay
|
|
479
|
-
* @param baseMs base delay in milliseconds
|
|
480
|
-
* @param varianceFraction fraction of baseMs to use as variance (0–1), default 0.3
|
|
481
|
-
*/
|
|
482
|
-
const jitterDelay = (baseMs, varianceFraction = 0.3) => {
|
|
483
|
-
const variance = baseMs * varianceFraction
|
|
484
|
-
return baseMs + (Math.random() * 2 - 1) * variance
|
|
485
|
-
}
|
|
486
|
-
exports.jitterDelay = jitterDelay
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* Compute exponential backoff delay for a given attempt number (0-based)
|
|
490
|
-
* @param attempt attempt index (0 = first retry)
|
|
491
|
-
* @param baseMs starting delay in ms (default 500)
|
|
492
|
-
* @param maxMs maximum delay cap in ms (default 30000)
|
|
493
|
-
*/
|
|
494
|
-
const exponentialBackoff = (attempt, baseMs = 500, maxMs = 30000) => {
|
|
495
|
-
return Math.min(baseMs * Math.pow(2, attempt), maxMs)
|
|
374
|
+
export function trimUndefined(obj) {
|
|
375
|
+
for (const key in obj) {
|
|
376
|
+
if (typeof obj[key] === 'undefined') {
|
|
377
|
+
delete obj[key];
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return obj;
|
|
496
381
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
/** Compute HMAC-SHA-256 of data with key, returns Buffer */
|
|
516
|
-
const hmacSha256 = (data, key) => (0, crypto_1.createHmac)('sha256', key).update(data).digest()
|
|
517
|
-
exports.hmacSha256 = hmacSha256
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
* Normalize and deduplicate an array of JIDs
|
|
521
|
-
*/
|
|
522
|
-
const normalizeJidBatch = (jids, normalizer) => {
|
|
523
|
-
const seen = new Set()
|
|
524
|
-
const result = []
|
|
525
|
-
for (const jid of jids) {
|
|
526
|
-
if (!jid) continue
|
|
527
|
-
const normalized = normalizer ? normalizer(jid) : jid
|
|
528
|
-
if (!seen.has(normalized)) {
|
|
529
|
-
seen.add(normalized)
|
|
530
|
-
result.push(normalized)
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
return result
|
|
382
|
+
const CROCKFORD_CHARACTERS = '123456789ABCDEFGHJKLMNPQRSTVWXYZ';
|
|
383
|
+
export function bytesToCrockford(buffer) {
|
|
384
|
+
let value = 0;
|
|
385
|
+
let bitCount = 0;
|
|
386
|
+
const crockford = [];
|
|
387
|
+
for (const element of buffer) {
|
|
388
|
+
value = (value << 8) | (element & 0xff);
|
|
389
|
+
bitCount += 8;
|
|
390
|
+
while (bitCount >= 5) {
|
|
391
|
+
crockford.push(CROCKFORD_CHARACTERS.charAt((value >>> (bitCount - 5)) & 31));
|
|
392
|
+
bitCount -= 5;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (bitCount > 0) {
|
|
396
|
+
crockford.push(CROCKFORD_CHARACTERS.charAt((value << (5 - bitCount)) & 31));
|
|
397
|
+
}
|
|
398
|
+
return crockford.join('');
|
|
534
399
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
/**
|
|
538
|
-
* Sleep for a given number of milliseconds, returns a cancellable promise
|
|
539
|
-
*/
|
|
540
|
-
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
|
541
|
-
exports.sleep = sleep
|
|
542
|
-
|
|
543
|
-
/**
|
|
544
|
-
* Run an async function with retry using exponential backoff
|
|
545
|
-
* @param fn async function to retry
|
|
546
|
-
* @param maxAttempts maximum number of attempts
|
|
547
|
-
* @param baseDelayMs base delay between retries
|
|
548
|
-
*/
|
|
549
|
-
const withRetry = async (fn, maxAttempts = 3, baseDelayMs = 500) => {
|
|
550
|
-
let lastErr
|
|
551
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
552
|
-
try {
|
|
553
|
-
return await fn()
|
|
554
|
-
} catch (err) {
|
|
555
|
-
lastErr = err
|
|
556
|
-
if (i < maxAttempts - 1) {
|
|
557
|
-
await sleep(exponentialBackoff(i, baseDelayMs))
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
throw lastErr
|
|
400
|
+
export function encodeNewsletterMessage(message) {
|
|
401
|
+
return proto.Message.encode(message).finish();
|
|
562
402
|
}
|
|
563
|
-
|
|
403
|
+
//# sourceMappingURL=generics.js.map
|