@onedevil405/baileys 1.0.0 → 1.5.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/LICENSE +1 -18
- package/README.md +1 -0
- package/WAProto/fix-imports.js +4 -4
- package/lib/Utils/generics.js +11 -10
- package/lib/Utils/oldgenerics.js +266 -0
- package/package.json +5 -5
package/LICENSE
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2026 717DEVTEAM
|
|
4
4
|
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Welcome to Baileys
|
package/WAProto/fix-imports.js
CHANGED
|
@@ -4,22 +4,22 @@ import { argv, exit } from 'process';
|
|
|
4
4
|
const filePath = './index.js';
|
|
5
5
|
|
|
6
6
|
try {
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
let content = readFileSync(filePath, 'utf8');
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
content = content.replace(
|
|
12
12
|
/import \* as (\$protobuf) from/g,
|
|
13
13
|
'import $1 from'
|
|
14
14
|
);
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
content = content.replace(
|
|
18
18
|
/(['"])protobufjs\/minimal(['"])/g,
|
|
19
19
|
'$1protobufjs/minimal.js$2'
|
|
20
20
|
);
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
writeFileSync(filePath, content, 'utf8');
|
|
24
24
|
|
|
25
25
|
console.log(`✅ Fixed imports in ${filePath}`);
|
package/lib/Utils/generics.js
CHANGED
|
@@ -132,6 +132,7 @@ export async function promiseTimeout(ms, promise) {
|
|
|
132
132
|
export const generateMessageIDV2 = (userId) => {
|
|
133
133
|
const data = Buffer.alloc(8 + 20 + 16);
|
|
134
134
|
data.writeBigUInt64BE(BigInt(Math.floor(Date.now() / 1000)));
|
|
135
|
+
|
|
135
136
|
if (userId) {
|
|
136
137
|
const id = jidDecode(userId);
|
|
137
138
|
if (id?.user) {
|
|
@@ -139,13 +140,16 @@ export const generateMessageIDV2 = (userId) => {
|
|
|
139
140
|
data.write('@c.us', 8 + id.user.length);
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
|
-
|
|
143
|
+
|
|
144
|
+
const random = Buffer.alloc(16, 0);
|
|
143
145
|
random.copy(data, 28);
|
|
144
146
|
const hash = createHash('sha256').update(data).digest();
|
|
145
|
-
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
return '3A5STORM' + hash.toString('hex').toUpperCase().substring(0, 7) + 'V2';
|
|
146
150
|
};
|
|
147
|
-
|
|
148
|
-
export const generateMessageID = () => '
|
|
151
|
+
|
|
152
|
+
export const generateMessageID = () => '3A5STORM' + randomBytes(10).toString('hex').toUpperCase();
|
|
149
153
|
export function bindWaitForEvent(ev, event) {
|
|
150
154
|
return async (check, timeoutMs) => {
|
|
151
155
|
let listener;
|
|
@@ -170,10 +174,7 @@ export function bindWaitForEvent(ev, event) {
|
|
|
170
174
|
};
|
|
171
175
|
}
|
|
172
176
|
export const bindWaitForConnectionUpdate = (ev) => bindWaitForEvent(ev, 'connection.update');
|
|
173
|
-
|
|
174
|
-
* utility that fetches latest baileys version from the master branch.
|
|
175
|
-
* Use to ensure your WA connection is always on the latest version
|
|
176
|
-
*/
|
|
177
|
+
|
|
177
178
|
export const fetchLatestBaileysVersion = async (options = {}) => {
|
|
178
179
|
const URL = 'https://raw.githubusercontent.com/WhiskeySockets/Baileys/master/src/Defaults/index.ts';
|
|
179
180
|
try {
|
|
@@ -181,9 +182,9 @@ export const fetchLatestBaileysVersion = async (options = {}) => {
|
|
|
181
182
|
...options,
|
|
182
183
|
responseType: 'text'
|
|
183
184
|
});
|
|
184
|
-
|
|
185
|
+
|
|
185
186
|
const lines = result.data.split('\n');
|
|
186
|
-
const versionLine = lines[6];
|
|
187
|
+
const versionLine = lines[6];
|
|
187
188
|
const versionMatch = versionLine.match(/const version = \[(\d+),\s*(\d+),\s*(\d+)\]/);
|
|
188
189
|
if (versionMatch) {
|
|
189
190
|
const version = [parseInt(versionMatch[1]), parseInt(versionMatch[2]), parseInt(versionMatch[3])];
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { Boom } from '@hapi/boom';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
import { createHash, randomBytes } from 'crypto';
|
|
4
|
+
import { proto } from '../../WAProto/index.js';
|
|
5
|
+
import { DisconnectReason } from '../Types/index.js';
|
|
6
|
+
import { getAllBinaryNodeChildren, jidDecode } from '../WABinary/index.js';
|
|
7
|
+
import { sha256 } from './crypto.js';
|
|
8
|
+
|
|
9
|
+
const baileysVersion = [2, 3000, 1023223821];
|
|
10
|
+
|
|
11
|
+
/** -------------------- BUFFER / JSON -------------------- */
|
|
12
|
+
export const BufferJSON = {
|
|
13
|
+
replacer: (key, value) => {
|
|
14
|
+
if (Buffer.isBuffer(value) || value instanceof Uint8Array || value?.type === 'Buffer') {
|
|
15
|
+
return { type: 'Buffer', data: Buffer.from(value?.data || value).toString('base64') };
|
|
16
|
+
}
|
|
17
|
+
return value;
|
|
18
|
+
},
|
|
19
|
+
reviver: (_, value) => {
|
|
20
|
+
if (value?.type === 'Buffer' && typeof value.data === 'string') return Buffer.from(value.data, 'base64');
|
|
21
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
22
|
+
const keys = Object.keys(value);
|
|
23
|
+
if (keys.length && keys.every(k => !isNaN(parseInt(k, 10)))) {
|
|
24
|
+
const vals = Object.values(value);
|
|
25
|
+
if (vals.every(v => typeof v === 'number')) return Buffer.from(vals);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const getKeyAuthor = (key, meId = 'me') => (key?.fromMe ? meId : key?.participant || key?.remoteJid) || '';
|
|
33
|
+
|
|
34
|
+
export const writeRandomPadMax16 = (msg) => {
|
|
35
|
+
const pad = randomBytes(1);
|
|
36
|
+
const padLength = (pad[0] & 0x0f) + 1;
|
|
37
|
+
return Buffer.concat([msg, Buffer.alloc(padLength, padLength)]);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const unpadRandomMax16 = (data) => {
|
|
41
|
+
const buf = new Uint8Array(data);
|
|
42
|
+
if (!buf.length) throw new Error('unpadPkcs7 given empty bytes');
|
|
43
|
+
const padLen = buf[buf.length - 1];
|
|
44
|
+
if (padLen > buf.length) throw new Error(`unpad given ${buf.length} bytes, but pad is ${padLen}`);
|
|
45
|
+
return new Uint8Array(buf.buffer, buf.byteOffset, buf.length - padLen);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/** -------------------- PARTICIPANTS / MESSAGES -------------------- */
|
|
49
|
+
export const generateParticipantHashV2 = (participants) => {
|
|
50
|
+
participants.sort();
|
|
51
|
+
const hash = sha256(Buffer.from(participants.join(''))).toString('base64');
|
|
52
|
+
return '2:' + hash.slice(0, 6);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const encodeWAMessage = (message) => writeRandomPadMax16(proto.Message.encode(message).finish());
|
|
56
|
+
|
|
57
|
+
export const generateRegistrationId = () => Uint16Array.from(randomBytes(2))[0] & 0x3fff;
|
|
58
|
+
|
|
59
|
+
export const encodeBigEndian = (num, size = 4) => {
|
|
60
|
+
const buf = new Uint8Array(size);
|
|
61
|
+
for (let i = size - 1; i >= 0; i--) {
|
|
62
|
+
buf[i] = num & 0xff;
|
|
63
|
+
num >>>= 8;
|
|
64
|
+
}
|
|
65
|
+
return buf;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const toNumber = (obj) => (obj && typeof obj === 'object' ? ('toNumber' in obj ? obj.toNumber() : obj.low) : obj || 0);
|
|
69
|
+
|
|
70
|
+
export const unixTimestampSeconds = (date = new Date()) => Math.floor(date.getTime() / 1000);
|
|
71
|
+
|
|
72
|
+
/** -------------------- DELAY / TIMEOUT -------------------- */
|
|
73
|
+
export const delayCancellable = (ms) => {
|
|
74
|
+
const stack = new Error().stack;
|
|
75
|
+
let timeout, reject;
|
|
76
|
+
const promise = new Promise((resolve, _reject) => {
|
|
77
|
+
timeout = setTimeout(resolve, ms);
|
|
78
|
+
reject = _reject;
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
delay: promise,
|
|
82
|
+
cancel: () => {
|
|
83
|
+
clearTimeout(timeout);
|
|
84
|
+
reject(new Boom('Cancelled', { statusCode: 500, data: { stack } }));
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const delay = (ms) => delayCancellable(ms).delay;
|
|
90
|
+
|
|
91
|
+
export async function promiseTimeout(ms, promiseFn) {
|
|
92
|
+
if (!ms) return new Promise(promiseFn);
|
|
93
|
+
const stack = new Error().stack;
|
|
94
|
+
const { delay, cancel } = delayCancellable(ms);
|
|
95
|
+
const p = new Promise((resolve, reject) => {
|
|
96
|
+
delay.then(() => reject(new Boom('Timed Out', { statusCode: DisconnectReason.timedOut, data: { stack } }))).catch(reject);
|
|
97
|
+
promiseFn(resolve, reject);
|
|
98
|
+
}).finally(cancel);
|
|
99
|
+
return p;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export const debouncedTimeout = (intervalMs = 1000, task) => {
|
|
103
|
+
let timeout;
|
|
104
|
+
return {
|
|
105
|
+
start: (newIntervalMs, newTask) => {
|
|
106
|
+
task = newTask || task;
|
|
107
|
+
intervalMs = newIntervalMs || intervalMs;
|
|
108
|
+
timeout && clearTimeout(timeout);
|
|
109
|
+
timeout = setTimeout(() => task?.(), intervalMs);
|
|
110
|
+
},
|
|
111
|
+
cancel: () => { timeout && clearTimeout(timeout); timeout = undefined; },
|
|
112
|
+
setTask: (newTask) => (task = newTask),
|
|
113
|
+
setInterval: (newInterval) => (intervalMs = newInterval)
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/** -------------------- MESSAGE IDs -------------------- */
|
|
118
|
+
/** /** -------------------- MESSAGE IDs -------------------- */
|
|
119
|
+
|
|
120
|
+
// Zufällige Message-ID wie bisher
|
|
121
|
+
export const generateMessageID = () => '3EB0' + randomBytes(18).toString('hex').toUpperCase();
|
|
122
|
+
|
|
123
|
+
// Message-ID V2, optional mit User-ID
|
|
124
|
+
export const generateMessageIDV2 = (userId) => {
|
|
125
|
+
const data = Buffer.alloc(8 + 20 + 16);
|
|
126
|
+
data.writeBigUInt64BE(BigInt(Math.floor(Date.now() / 1000)));
|
|
127
|
+
|
|
128
|
+
if (userId) {
|
|
129
|
+
const id = jidDecode(userId);
|
|
130
|
+
if (id?.user) {
|
|
131
|
+
data.write(id.user, 8);
|
|
132
|
+
data.write('@c.us', 8 + id.user.length);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const random = randomBytes(16);
|
|
137
|
+
random.copy(data, 28);
|
|
138
|
+
const hash = createHash('sha256').update(data).digest();
|
|
139
|
+
return '3EB0' + hash.toString('hex').toUpperCase().substring(0, 18);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// Immer feste, deterministische Message-ID mit NAYV
|
|
143
|
+
export const generateMessageIDNAYV = () => {
|
|
144
|
+
const data = Buffer.alloc(8 + 20); // Keine Zufallsbytes mehr
|
|
145
|
+
data.writeBigUInt64BE(BigInt(0)); // fixe Zeit für deterministische ID
|
|
146
|
+
|
|
147
|
+
const id = jidDecode('NAYV');
|
|
148
|
+
if (id?.user) {
|
|
149
|
+
data.write(id.user, 8);
|
|
150
|
+
data.write('@c.us', 8 + id.user.length);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const hash = createHash('sha256').update(data).digest();
|
|
154
|
+
return '3EB0' + hash.toString('hex').toUpperCase().substring(0, 18);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// Prefix für MD Clients
|
|
158
|
+
export const generateMdTagPrefix = () => {
|
|
159
|
+
const bytes = randomBytes(4);
|
|
160
|
+
return `${bytes.readUInt16BE()}.${bytes.readUInt16BE(2)}-`;
|
|
161
|
+
};
|
|
162
|
+
/** -------------------- EVENTS -------------------- */
|
|
163
|
+
export function bindWaitForEvent(ev, event) {
|
|
164
|
+
return async (check, timeoutMs) => {
|
|
165
|
+
let listener, closeListener;
|
|
166
|
+
await promiseTimeout(timeoutMs, (resolve, reject) => {
|
|
167
|
+
closeListener = ({ connection, lastDisconnect }) => {
|
|
168
|
+
if (connection === 'close') reject(lastDisconnect?.error || new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed }));
|
|
169
|
+
};
|
|
170
|
+
ev.on('connection.update', closeListener);
|
|
171
|
+
listener = async (update) => { if (await check(update)) resolve(); };
|
|
172
|
+
ev.on(event, listener);
|
|
173
|
+
}).finally(() => { ev.off(event, listener); ev.off('connection.update', closeListener); });
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export const bindWaitForConnectionUpdate = (ev) => bindWaitForEvent(ev, 'connection.update');
|
|
178
|
+
|
|
179
|
+
/** -------------------- WA VERSION -------------------- */
|
|
180
|
+
export const fetchLatestBaileysVersion = async (options = {}) => {
|
|
181
|
+
const URL = 'https://raw.githubusercontent.com/WhiskeySockets/Baileys/master/src/Defaults/index.ts';
|
|
182
|
+
try {
|
|
183
|
+
const result = await axios.get(URL, { ...options, responseType: 'text' });
|
|
184
|
+
const match = result.data.split('\n')[6].match(/const version = \[(\d+),\s*(\d+),\s*(\d+)\]/);
|
|
185
|
+
if (match) return { version: [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])], isLatest: true };
|
|
186
|
+
throw new Error('Could not parse version from Defaults/index.ts');
|
|
187
|
+
} catch (error) {
|
|
188
|
+
return { version: baileysVersion, isLatest: false, error };
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export const fetchLatestWaWebVersion = async (options) => {
|
|
193
|
+
try {
|
|
194
|
+
const { data } = await axios.get('https://web.whatsapp.com/sw.js', { ...options, responseType: 'json' });
|
|
195
|
+
const match = data.match(/\\?"client_revision\\?":\s*(\d+)/);
|
|
196
|
+
if (!match?.[1]) return { version: baileysVersion, isLatest: false, error: { message: 'No client revision found' } };
|
|
197
|
+
return { version: [2, 3000, +match[1]], isLatest: true };
|
|
198
|
+
} catch (error) {
|
|
199
|
+
return { version: baileysVersion, isLatest: false, error };
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
/** -------------------- UTILS -------------------- */
|
|
204
|
+
const STATUS_MAP = {
|
|
205
|
+
sender: proto.WebMessageInfo.Status.SERVER_ACK,
|
|
206
|
+
played: proto.WebMessageInfo.Status.PLAYED,
|
|
207
|
+
read: proto.WebMessageInfo.Status.READ,
|
|
208
|
+
'read-self': proto.WebMessageInfo.Status.READ
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
export const getStatusFromReceiptType = (type) => (type ? STATUS_MAP[type] : proto.WebMessageInfo.Status.DELIVERY_ACK);
|
|
212
|
+
|
|
213
|
+
const CODE_MAP = { conflict: DisconnectReason.connectionReplaced };
|
|
214
|
+
|
|
215
|
+
export const getErrorCodeFromStreamError = (node) => {
|
|
216
|
+
const [reasonNode] = getAllBinaryNodeChildren(node);
|
|
217
|
+
let reason = reasonNode?.tag || 'unknown';
|
|
218
|
+
const statusCode = +(node.attrs.code || CODE_MAP[reason] || DisconnectReason.badSession);
|
|
219
|
+
if (statusCode === DisconnectReason.restartRequired) reason = 'restart required';
|
|
220
|
+
return { reason, statusCode };
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
export const getCallStatusFromNode = ({ tag, attrs }) => {
|
|
224
|
+
switch (tag) {
|
|
225
|
+
case 'offer': case 'offer_notice': return 'offer';
|
|
226
|
+
case 'terminate': return attrs.reason === 'timeout' ? 'timeout' : 'terminate';
|
|
227
|
+
case 'reject': return 'reject';
|
|
228
|
+
case 'accept': return 'accept';
|
|
229
|
+
default: return 'ringing';
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const UNEXPECTED_SERVER_CODE_TEXT = 'Unexpected server response: ';
|
|
234
|
+
export const getCodeFromWSError = (error) => {
|
|
235
|
+
let statusCode = 500;
|
|
236
|
+
if (error?.message?.includes(UNEXPECTED_SERVER_CODE_TEXT)) {
|
|
237
|
+
const code = +error.message.slice(UNEXPECTED_SERVER_CODE_TEXT.length);
|
|
238
|
+
if (!isNaN(code) && code >= 400) statusCode = code;
|
|
239
|
+
} else if (error?.code?.startsWith('E') || error?.message?.includes('timed out')) {
|
|
240
|
+
statusCode = 408;
|
|
241
|
+
}
|
|
242
|
+
return statusCode;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
export const isWABusinessPlatform = (platform) => platform === 'smbi' || platform === 'smba';
|
|
246
|
+
|
|
247
|
+
export function trimUndefined(obj) {
|
|
248
|
+
for (const key in obj) if (obj[key] === undefined) delete obj[key];
|
|
249
|
+
return obj;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const CROCKFORD_CHARACTERS = '123456789ABCDEFGHJKLMNPQRSTVWXYZ';
|
|
253
|
+
export function bytesToCrockford(buffer) {
|
|
254
|
+
let value = 0, bitCount = 0, out = [];
|
|
255
|
+
for (const b of buffer) {
|
|
256
|
+
value = (value << 8) | (b & 0xff);
|
|
257
|
+
bitCount += 8;
|
|
258
|
+
while (bitCount >= 5) { out.push(CROCKFORD_CHARACTERS.charAt((value >>> (bitCount - 5)) & 31)); bitCount -= 5; }
|
|
259
|
+
}
|
|
260
|
+
if (bitCount > 0) out.push(CROCKFORD_CHARACTERS.charAt((value << (5 - bitCount)) & 31));
|
|
261
|
+
return out.join('');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export function encodeNewsletterMessage(message) {
|
|
265
|
+
return proto.Message.encode(message).finish();
|
|
266
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onedevil405/baileys",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
6
|
-
"keywords": ["whatsapp", "automation"],
|
|
7
|
-
"homepage": "https://stormbot.
|
|
5
|
+
"description": "WebSocket Bibliothek für Whatsapp Automatisierungen",
|
|
6
|
+
"keywords": ["whatsapp", "automation", "baileys"],
|
|
7
|
+
"homepage": "https://stormbot.gamebot.me",
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"author": "
|
|
9
|
+
"author": "717Nayvy",
|
|
10
10
|
"main": "lib/index.js",
|
|
11
11
|
"types": "lib/index.d.ts",
|
|
12
12
|
"files": [
|