@nexustechpro/baileys 2.0.5 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/WAProto/index.js +22 -18
- package/lib/Defaults/baileys-version.json +1 -1
- package/lib/Defaults/index.js +7 -6
- package/lib/Signal/libsignal.js +65 -50
- package/lib/Socket/chats.js +64 -57
- package/lib/Socket/index.js +2 -3
- package/lib/Socket/messages-recv.js +227 -41
- package/lib/Socket/messages-send.js +79 -117
- package/lib/Socket/nexus-handler.js +325 -90
- package/lib/Socket/registration.js +50 -33
- package/lib/Socket/socket.js +232 -69
- package/lib/Types/Newsletter.js +37 -29
- package/lib/Types/State.js +43 -0
- package/lib/Utils/auth-utils.js +2 -2
- package/lib/Utils/chat-utils.js +48 -16
- package/lib/Utils/companion-reg-client-utils.js +34 -0
- package/lib/Utils/decode-wa-message.js +40 -8
- package/lib/Utils/generics.js +5 -7
- package/lib/Utils/index.js +4 -0
- package/lib/Utils/link-preview.js +10 -0
- package/lib/Utils/messages-media.js +426 -382
- package/lib/Utils/messages.js +602 -487
- package/lib/Utils/process-message.js +53 -35
- package/lib/Utils/reporting-utils.js +155 -0
- package/lib/Utils/signal.js +134 -104
- package/lib/Utils/sync-action-utils.js +33 -0
- package/lib/Utils/tc-token-utils.js +162 -0
- package/lib/WABinary/constants.js +6 -0
- package/lib/WABinary/index.js +1 -0
- package/lib/index.js +2 -3
- package/package.json +6 -4
package/WAProto/index.js
CHANGED
|
@@ -12,14 +12,18 @@ function longToString(value, unsigned) {
|
|
|
12
12
|
if (typeof value === "number") {
|
|
13
13
|
return String(value);
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
// Fast path: convert Long {low, high} directly via native BigInt
|
|
16
|
+
// BigInt.toString() is a native C++ operation, much faster than Long's pure JS division loops
|
|
17
|
+
if (value && typeof value.low === "number" && typeof value.high === "number") {
|
|
18
|
+
const lo = BigInt(value.low >>> 0);
|
|
19
|
+
const hi = BigInt(value.high >>> 0);
|
|
20
|
+
const combined = (hi << 32n) | lo;
|
|
21
|
+
if (!unsigned && value.high < 0) {
|
|
22
|
+
return (combined - (1n << 64n)).toString();
|
|
23
|
+
}
|
|
24
|
+
return combined.toString();
|
|
17
25
|
}
|
|
18
|
-
|
|
19
|
-
const prepared = unsigned && normalized && typeof normalized.toUnsigned === "function"
|
|
20
|
-
? normalized.toUnsigned()
|
|
21
|
-
: normalized;
|
|
22
|
-
return prepared.toString();
|
|
26
|
+
return String(value);
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
function longToNumber(value, unsigned) {
|
|
@@ -27,19 +31,19 @@ function longToNumber(value, unsigned) {
|
|
|
27
31
|
return value;
|
|
28
32
|
}
|
|
29
33
|
if (typeof value === "string") {
|
|
30
|
-
const numeric = Number(value);
|
|
31
|
-
return numeric;
|
|
32
|
-
}
|
|
33
|
-
if (!$util.Long) {
|
|
34
34
|
return Number(value);
|
|
35
35
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
// Fast path: convert Long {low, high} directly via native BigInt
|
|
37
|
+
if (value && typeof value.low === "number" && typeof value.high === "number") {
|
|
38
|
+
const lo = BigInt(value.low >>> 0);
|
|
39
|
+
const hi = BigInt(value.high >>> 0);
|
|
40
|
+
const combined = (hi << 32n) | lo;
|
|
41
|
+
if (!unsigned && value.high < 0) {
|
|
42
|
+
return Number(combined - (1n << 64n));
|
|
43
|
+
}
|
|
44
|
+
return Number(combined);
|
|
45
|
+
}
|
|
46
|
+
return Number(value);
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
export const proto = $root.proto = (() => {
|
package/lib/Defaults/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import logger from '../Utils/logger.js';
|
|
|
7
7
|
const require = createRequire(import.meta.url);
|
|
8
8
|
const PHONENUMBER_MCC = require('./phonenumber-mcc.json');
|
|
9
9
|
export { PHONENUMBER_MCC };
|
|
10
|
-
const version = [2, 3000,
|
|
10
|
+
const version = [2, 3000, 1040069233];
|
|
11
11
|
|
|
12
12
|
export const UNAUTHORIZED_CODES = [401, 403, 419];
|
|
13
13
|
|
|
@@ -55,19 +55,20 @@ export const PROCESSABLE_HISTORY_TYPES = [
|
|
|
55
55
|
];
|
|
56
56
|
export const MOBILE_ENDPOINT = 'g.whatsapp.net';
|
|
57
57
|
export const MOBILE_PORT = 443;
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
const WA_VERSION_HASH = createHash('md5').update(WA_VERSION).digest('hex');
|
|
61
|
-
|
|
58
|
+
export const WA_VERSION = '2.2413.51'
|
|
59
|
+
export const WA_VERSION_HASH = createHash('md5').update(WA_VERSION).digest('hex');
|
|
62
60
|
export const MOBILE_TOKEN = Buffer.from('0a1mLfGUIBVrMKF1RdvLI5lkRBvof6vn0fD2QRSM' + WA_VERSION_HASH);
|
|
63
61
|
export const MOBILE_REGISTRATION_ENDPOINT = 'https://v.whatsapp.net/v2';
|
|
64
62
|
export const MOBILE_USERAGENT = `WhatsApp/${WA_VERSION} iOS/17.5.1 Device/Apple-iPhone_13`;
|
|
65
|
-
|
|
63
|
+
export const GRAPHQL_ENDPOINT = 'https://graph.whatsapp.com/graphql'
|
|
64
|
+
export const GRAPHQL_ACCESS_TOKEN = 'WA|1015890928915437|3201f239340c1c8ec6262a6dad04200e'
|
|
65
|
+
export const GRAPHQL_BAN_STATUS_DOC_ID = '25573756098908502'
|
|
66
66
|
export const REGISTRATION_PUBLIC_KEY = Buffer.from([
|
|
67
67
|
5, 142, 140, 15, 116, 195, 235, 197, 215, 166, 134, 92, 108, 60, 132, 56, 86, 176, 97, 33, 204, 232, 234, 119, 77,
|
|
68
68
|
34, 251, 111, 18, 37, 18, 48, 45,
|
|
69
69
|
]);
|
|
70
70
|
|
|
71
|
+
|
|
71
72
|
export const PROTOCOL_VERSION = [5, 2];
|
|
72
73
|
export const MOBILE_NOISE_HEADER = Buffer.concat([Buffer.from('WA'), Buffer.from(PROTOCOL_VERSION)]);
|
|
73
74
|
|
package/lib/Signal/libsignal.js
CHANGED
|
@@ -25,7 +25,7 @@ const jidToAddr = (jid) => {
|
|
|
25
25
|
|
|
26
26
|
const jidToSenderKeyName = (group, user) => new SenderKeyName(group, jidToAddr(user))
|
|
27
27
|
|
|
28
|
-
const v2Key = (addr) => `${addr}:v2`
|
|
28
|
+
const v2Key = (addr) => `${addr}:v2`
|
|
29
29
|
|
|
30
30
|
// ─── Identity Extraction ──────────────────────────────────────────────────────
|
|
31
31
|
|
|
@@ -56,7 +56,6 @@ function extractIdentityFromPkmsg(ciphertext) {
|
|
|
56
56
|
|
|
57
57
|
// ─── Buffer Utils ─────────────────────────────────────────────────────────────
|
|
58
58
|
|
|
59
|
-
// universal deserializer — handles all shapes written by any previous version
|
|
60
59
|
const toBuffer = (raw) => {
|
|
61
60
|
if (!raw) return null
|
|
62
61
|
if (raw instanceof Uint8Array) return raw
|
|
@@ -68,7 +67,6 @@ const toBuffer = (raw) => {
|
|
|
68
67
|
return null
|
|
69
68
|
}
|
|
70
69
|
|
|
71
|
-
// detects old libsignal JS JSON format — not deserializable by whatsapp-rust-bridge
|
|
72
70
|
const isOldJson = (raw) => {
|
|
73
71
|
if (!raw || raw instanceof Uint8Array || Buffer.isBuffer(raw)) return false
|
|
74
72
|
if (typeof raw === 'object') return 'version' in raw || '_sessions' in raw
|
|
@@ -97,6 +95,28 @@ export function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
|
|
|
97
95
|
return txn(() => new GroupSessionBuilder(storage).process(senderName, senderMsg), item.groupId)
|
|
98
96
|
},
|
|
99
97
|
|
|
98
|
+
async encryptGroupMessage({ group, meId, data }) {
|
|
99
|
+
const senderName = jidToSenderKeyName(group, meId)
|
|
100
|
+
const skdm = await new GroupSessionBuilder(storage).create(senderName)
|
|
101
|
+
const plaintext = data instanceof Uint8Array && data.constructor === Uint8Array
|
|
102
|
+
? data
|
|
103
|
+
: new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
|
|
104
|
+
const ciphertext = await new GroupCipher(storage, group, jidToAddr(meId)).encrypt(plaintext)
|
|
105
|
+
return { ciphertext, senderKeyDistributionMessage: skdm.serialize() }
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
async getSenderKeyDistributionMessage({ group, meId }) {
|
|
109
|
+
const senderName = jidToSenderKeyName(group, meId)
|
|
110
|
+
const skdm = await new GroupSessionBuilder(storage).create(senderName)
|
|
111
|
+
return skdm.serialize()
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
async hasSenderKey({ group, meId }) {
|
|
115
|
+
const name = jidToSenderKeyName(group, meId).toString()
|
|
116
|
+
const { [name]: key } = await parsedKeys.get('sender-key', [name])
|
|
117
|
+
return !!toBuffer(key)
|
|
118
|
+
},
|
|
119
|
+
|
|
100
120
|
async decryptMessage({ jid, type, ciphertext }) {
|
|
101
121
|
const addr = jidToAddr(jid)
|
|
102
122
|
const cipher = new SessionCipher(storage, addr)
|
|
@@ -107,15 +127,14 @@ export function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
|
|
|
107
127
|
if (changed) logger?.info?.({ jid }, '[Signal] Identity key changed, session cleared')
|
|
108
128
|
}
|
|
109
129
|
}
|
|
110
|
-
const doDecrypt = (c, t) => {
|
|
111
|
-
if (t === 'pkmsg') return c.decryptPreKeyWhisperMessage(ciphertext)
|
|
112
|
-
if (t === 'msg') return c.decryptWhisperMessage(ciphertext)
|
|
113
|
-
throw new Error(`Unknown type: ${t}`)
|
|
114
|
-
}
|
|
115
130
|
try {
|
|
116
|
-
return await txn(() =>
|
|
131
|
+
return await txn(() => {
|
|
132
|
+
if (type === 'pkmsg') return cipher.decryptPreKeyWhisperMessage(ciphertext)
|
|
133
|
+
if (type === 'msg') return cipher.decryptWhisperMessage(ciphertext)
|
|
134
|
+
throw new Error(`Unknown type: ${type}`)
|
|
135
|
+
}, jid)
|
|
117
136
|
} catch (e) {
|
|
118
|
-
if (e?.message?.includes('DuplicatedMessage')) { logger?.debug?.({ jid }, '[Signal] Duplicate message ignored
|
|
137
|
+
if (e?.message?.includes('DuplicatedMessage')) { logger?.debug?.({ jid }, '[Signal] Duplicate message ignored'); return null }
|
|
119
138
|
throw e
|
|
120
139
|
}
|
|
121
140
|
},
|
|
@@ -127,14 +146,6 @@ export function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
|
|
|
127
146
|
}, jid)
|
|
128
147
|
},
|
|
129
148
|
|
|
130
|
-
encryptGroupMessage({ group, meId, data }) {
|
|
131
|
-
return txn(async () => {
|
|
132
|
-
const senderName = jidToSenderKeyName(group, meId)
|
|
133
|
-
const senderKeyDistributionMessage = await new GroupSessionBuilder(storage).create(senderName)
|
|
134
|
-
return { ciphertext: await new GroupCipher(storage, group, jidToAddr(meId)).encrypt(data), senderKeyDistributionMessage: senderKeyDistributionMessage.serialize() }
|
|
135
|
-
}, group)
|
|
136
|
-
},
|
|
137
|
-
|
|
138
149
|
injectE2ESession({ jid, session }) {
|
|
139
150
|
return txn(() => new SessionBuilder(storage, jidToAddr(jid)).processPreKeyBundle(session), jid)
|
|
140
151
|
},
|
|
@@ -147,7 +158,7 @@ export function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
|
|
|
147
158
|
try {
|
|
148
159
|
const addr = jidToAddr(jid).toString()
|
|
149
160
|
const batch = await migrateIndexKey(parsedKeys, 'session')
|
|
150
|
-
const raw = toBuffer(batch[v2Key(addr)]) || toBuffer(batch[addr])
|
|
161
|
+
const raw = toBuffer(batch[v2Key(addr)]) || toBuffer(batch[addr])
|
|
151
162
|
if (!raw || isOldJson(raw)) return { exists: false, reason: 'no session' }
|
|
152
163
|
const sess = SessionRecord.deserialize(raw)
|
|
153
164
|
if (!sess.haveOpenSession()) return { exists: false, reason: 'no open session' }
|
|
@@ -160,7 +171,7 @@ export function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
|
|
|
160
171
|
return txn(async () => {
|
|
161
172
|
const batch = await migrateIndexKey(parsedKeys, 'session')
|
|
162
173
|
for (const jid of jids) { const addr = jidToAddr(jid).toString(); delete batch[addr]; delete batch[v2Key(addr)] }
|
|
163
|
-
await parsedKeys.set({ session: {
|
|
174
|
+
await parsedKeys.set({ session: { index: batch } })
|
|
164
175
|
}, `del-${jids.length}`)
|
|
165
176
|
},
|
|
166
177
|
|
|
@@ -185,55 +196,44 @@ export function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
|
|
|
185
196
|
for (const { jid } of deviceJids) {
|
|
186
197
|
const pnAddr = jidToAddr(jid).toString()
|
|
187
198
|
const lidAddr = jidToAddr(transferDevice(jid, toJid)).toString()
|
|
188
|
-
const raw = toBuffer(updated[v2Key(pnAddr)]) || toBuffer(updated[pnAddr])
|
|
199
|
+
const raw = toBuffer(updated[v2Key(pnAddr)]) || toBuffer(updated[pnAddr])
|
|
189
200
|
if (!raw || isOldJson(raw)) continue
|
|
190
201
|
const sess = SessionRecord.deserialize(raw)
|
|
191
202
|
if (!sess.haveOpenSession()) continue
|
|
192
203
|
updated[v2Key(lidAddr)] = sess.serialize()
|
|
193
|
-
updated[lidAddr] = { version: 'v1', _sessions: {} }
|
|
204
|
+
updated[lidAddr] = { version: 'v1', _sessions: {} }
|
|
194
205
|
delete updated[v2Key(pnAddr)]
|
|
195
206
|
delete updated[pnAddr]
|
|
196
207
|
migrated++
|
|
197
208
|
migratedCache.set(`${user}.${jidDecode(jid).device || 0}`, true)
|
|
198
209
|
}
|
|
199
|
-
if (migrated > 0) await parsedKeys.set({ session: {
|
|
210
|
+
if (migrated > 0) await parsedKeys.set({ session: { index: updated } })
|
|
200
211
|
return { migrated, skipped: deviceJids.length - migrated, total: deviceJids.length }
|
|
201
212
|
}, `migrate-${deviceJids.length}`)
|
|
202
213
|
},
|
|
203
214
|
|
|
204
|
-
// Batch-migrate all PN-addressed sessions to their LID equivalents.
|
|
205
|
-
// Called once on CB:success before offline messages are processed — one read, one remap, one write.
|
|
206
215
|
async migrateAllPNSessionsToLID() {
|
|
207
216
|
return txn(async () => {
|
|
208
217
|
const sessionBatch = await migrateIndexKey(parsedKeys, 'session')
|
|
209
218
|
const sessionKeys = Object.keys(sessionBatch)
|
|
210
219
|
if (!sessionKeys.length) return 0
|
|
211
|
-
|
|
212
|
-
// collect plain (non-v2) PN-domain keys only — v2 slots are handled via their plain counterpart
|
|
213
220
|
const pnAddrs = sessionKeys.filter(addr => {
|
|
214
|
-
if (addr.endsWith(':v2')) return false
|
|
215
|
-
|
|
216
|
-
const [deviceId] = addr.split('.')
|
|
217
|
-
const [, dt] = deviceId.split('_')
|
|
221
|
+
if (addr.endsWith(':v2') || !addr.includes('.')) return false
|
|
222
|
+
const [, dt] = addr.split('.')[0].split('_')
|
|
218
223
|
const domainType = parseInt(dt || '0')
|
|
219
224
|
return domainType === WAJIDDomains.WHATSAPP || domainType === WAJIDDomains.HOSTED
|
|
220
225
|
})
|
|
221
226
|
if (!pnAddrs.length) return 0
|
|
222
|
-
|
|
223
|
-
// batch-fetch LID mappings directly from key store — same format storeLIDPNMappings writes
|
|
224
227
|
const pnUserSet = new Set(pnAddrs.map(addr => addr.split('.')[0].split('_')[0]))
|
|
225
228
|
const stored = await parsedKeys.get('lid-mapping', [...pnUserSet])
|
|
226
|
-
|
|
227
229
|
const pnToLidUserMap = new Map()
|
|
228
230
|
for (const pnUser of pnUserSet) {
|
|
229
231
|
const lidUser = stored[pnUser]
|
|
230
232
|
if (lidUser && typeof lidUser === 'string') pnToLidUserMap.set(pnUser, lidUser)
|
|
231
233
|
}
|
|
232
234
|
if (!pnToLidUserMap.size) return 0
|
|
233
|
-
|
|
234
235
|
let migrated = 0
|
|
235
236
|
const updated = { ...sessionBatch }
|
|
236
|
-
|
|
237
237
|
for (const addr of pnAddrs) {
|
|
238
238
|
const [deviceId, device] = addr.split('.')
|
|
239
239
|
const [user, dt] = deviceId.split('_')
|
|
@@ -242,25 +242,34 @@ export function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
|
|
|
242
242
|
if (!lidUser) continue
|
|
243
243
|
const lidDomainType = domainType === WAJIDDomains.HOSTED ? WAJIDDomains.HOSTED_LID : WAJIDDomains.LID
|
|
244
244
|
const lidAddr = `${lidUser}_${lidDomainType}.${device}`
|
|
245
|
-
if (updated[v2Key(lidAddr)]) continue
|
|
246
|
-
const raw = toBuffer(updated[v2Key(addr)]) || toBuffer(updated[addr])
|
|
245
|
+
if (updated[v2Key(lidAddr)]) continue
|
|
246
|
+
const raw = toBuffer(updated[v2Key(addr)]) || toBuffer(updated[addr])
|
|
247
247
|
if (!raw || isOldJson(raw)) continue
|
|
248
248
|
const sess = SessionRecord.deserialize(raw)
|
|
249
249
|
if (!sess.haveOpenSession()) continue
|
|
250
250
|
updated[v2Key(lidAddr)] = sess.serialize()
|
|
251
|
-
updated[lidAddr] = { version: 'v1', _sessions: {} }
|
|
251
|
+
updated[lidAddr] = { version: 'v1', _sessions: {} }
|
|
252
252
|
delete updated[v2Key(addr)]
|
|
253
253
|
delete updated[addr]
|
|
254
254
|
migrated++
|
|
255
255
|
migratedCache.set(`${user}.${device}`, true)
|
|
256
256
|
}
|
|
257
|
-
|
|
258
257
|
if (migrated > 0) {
|
|
259
|
-
await parsedKeys.set({ session: {
|
|
258
|
+
await parsedKeys.set({ session: { index: updated } })
|
|
260
259
|
logger?.info?.({ migrated, totalPN: pnAddrs.length, mappingsFound: pnToLidUserMap.size }, '[Signal] Batch-migrated PN sessions to LID on connect')
|
|
261
260
|
}
|
|
262
261
|
return migrated
|
|
263
262
|
}, 'migrate-all-pn-to-lid')
|
|
263
|
+
},
|
|
264
|
+
|
|
265
|
+
deleteSenderKey(group, authorJid) {
|
|
266
|
+
const senderName = jidToSenderKeyName(group, authorJid).toString()
|
|
267
|
+
return parsedKeys.set({ 'sender-key': { [senderName]: null } })
|
|
268
|
+
},
|
|
269
|
+
|
|
270
|
+
close() {
|
|
271
|
+
migratedCache.clear()
|
|
272
|
+
lidMapping.close?.()
|
|
264
273
|
}
|
|
265
274
|
}
|
|
266
275
|
}
|
|
@@ -268,7 +277,7 @@ export function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
|
|
|
268
277
|
// ─── Storage Adapter ──────────────────────────────────────────────────────────
|
|
269
278
|
|
|
270
279
|
function signalStorage({ creds, keys }, lidMapping, logger) {
|
|
271
|
-
const lidCache = new LRUCache({ max: 500, ttl: 5 * 60 * 1000 })
|
|
280
|
+
const lidCache = new LRUCache({ max: 500, ttl: 5 * 60 * 1000 })
|
|
272
281
|
|
|
273
282
|
const resolveLID = async (id) => {
|
|
274
283
|
if (!id.includes('.')) return id
|
|
@@ -286,7 +295,7 @@ function signalStorage({ creds, keys }, lidMapping, logger) {
|
|
|
286
295
|
}
|
|
287
296
|
|
|
288
297
|
const getIndex = () => migrateIndexKey(keys, 'session')
|
|
289
|
-
const setIndex = (batch) => keys.set({ session: {
|
|
298
|
+
const setIndex = (batch) => keys.set({ session: { index: batch } })
|
|
290
299
|
|
|
291
300
|
return {
|
|
292
301
|
loadSession: async (id) => {
|
|
@@ -300,7 +309,7 @@ function signalStorage({ creds, keys }, lidMapping, logger) {
|
|
|
300
309
|
if (buf) return buf
|
|
301
310
|
}
|
|
302
311
|
const plain = batch[addr]
|
|
303
|
-
if (!plain || isOldJson(plain)) {
|
|
312
|
+
if (!plain || isOldJson(plain)) {
|
|
304
313
|
if (plain) logger?.debug?.(`[Signal] Old JSON session for ${addr}, will fresh handshake`)
|
|
305
314
|
return null
|
|
306
315
|
}
|
|
@@ -311,8 +320,8 @@ function signalStorage({ creds, keys }, lidMapping, logger) {
|
|
|
311
320
|
storeSession: async (id, session) => {
|
|
312
321
|
const addr = await resolveLID(id)
|
|
313
322
|
const batch = await getIndex()
|
|
314
|
-
batch[v2Key(addr)] = session.serialize()
|
|
315
|
-
batch[addr] = { version: 'v1', _sessions: {} }
|
|
323
|
+
batch[v2Key(addr)] = session.serialize()
|
|
324
|
+
batch[addr] = { version: 'v1', _sessions: {} }
|
|
316
325
|
await setIndex(batch)
|
|
317
326
|
},
|
|
318
327
|
|
|
@@ -352,7 +361,11 @@ function signalStorage({ creds, keys }, lidMapping, logger) {
|
|
|
352
361
|
|
|
353
362
|
loadSignedPreKey: () => {
|
|
354
363
|
const { signedPreKey: key } = creds
|
|
355
|
-
return {
|
|
364
|
+
return {
|
|
365
|
+
keyId: key.keyId,
|
|
366
|
+
keyPair: { pubKey: new Uint8Array(Buffer.from(key.keyPair.public)), privKey: new Uint8Array(Buffer.from(key.keyPair.private)) },
|
|
367
|
+
signature: new Uint8Array(Buffer.from(key.signature))
|
|
368
|
+
}
|
|
356
369
|
},
|
|
357
370
|
|
|
358
371
|
loadSenderKey: async (keyId) => {
|
|
@@ -365,15 +378,17 @@ function signalStorage({ creds, keys }, lidMapping, logger) {
|
|
|
365
378
|
|
|
366
379
|
storeSenderKey: async (keyId, record) => {
|
|
367
380
|
const id = keyId.toString()
|
|
368
|
-
|
|
369
|
-
await keys.set({ 'sender-key': { [id]: bytes } })
|
|
381
|
+
await keys.set({ 'sender-key': { [id]: Buffer.from(record) } })
|
|
370
382
|
},
|
|
371
383
|
|
|
372
384
|
getOurRegistrationId: () => creds.registrationId,
|
|
373
385
|
|
|
374
386
|
getOurIdentity: () => {
|
|
375
387
|
const { signedIdentityKey } = creds
|
|
376
|
-
return {
|
|
388
|
+
return {
|
|
389
|
+
pubKey: new Uint8Array(generateSignalPubKey(Buffer.from(signedIdentityKey.public))),
|
|
390
|
+
privKey: new Uint8Array(Buffer.from(signedIdentityKey.private))
|
|
391
|
+
}
|
|
377
392
|
}
|
|
378
393
|
}
|
|
379
394
|
}
|
package/lib/Socket/chats.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import NodeCache from '@cacheable/node-cache'
|
|
2
2
|
import { Boom } from '@hapi/boom'
|
|
3
3
|
import { proto } from '../../WAProto/index.js'
|
|
4
|
-
import { DEFAULT_CACHE_TTLS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js'
|
|
4
|
+
import { DEFAULT_CACHE_TTLS, PROCESSABLE_HISTORY_TYPES, PHONENUMBER_MCC, MOBILE_TOKEN, MOBILE_USERAGENT, MOBILE_REGISTRATION_ENDPOINT } from '../Defaults/index.js'
|
|
5
5
|
import { ALL_WA_PATCH_NAMES } from '../Types/index.js'
|
|
6
6
|
import { SyncState } from '../Types/State.js'
|
|
7
7
|
import {
|
|
@@ -25,7 +25,8 @@ import {
|
|
|
25
25
|
jidDecode,
|
|
26
26
|
jidNormalizedUser,
|
|
27
27
|
reduceBinaryNodeToDictionary,
|
|
28
|
-
S_WHATSAPP_NET
|
|
28
|
+
S_WHATSAPP_NET,
|
|
29
|
+
VIOLATION_TYPES
|
|
29
30
|
} from '../WABinary/index.js'
|
|
30
31
|
import { USyncQuery, USyncUser } from '../WAUSync/index.js'
|
|
31
32
|
import { makeSocket } from './socket.js'
|
|
@@ -217,60 +218,6 @@ export const makeChatsSocket = (config) => {
|
|
|
217
218
|
)
|
|
218
219
|
}
|
|
219
220
|
|
|
220
|
-
const checkStatusWA = async (phoneNumber) => {
|
|
221
|
-
if (!phoneNumber) throw new Error('enter number')
|
|
222
|
-
|
|
223
|
-
let resultData = { isBanned: false, isNeedOfficialWa: false, number: phoneNumber }
|
|
224
|
-
|
|
225
|
-
let formattedNumber = phoneNumber.startsWith('+') ? phoneNumber : '+' + phoneNumber
|
|
226
|
-
|
|
227
|
-
const { parsePhoneNumber } = await import('libphonenumber-js')
|
|
228
|
-
const parsedNumber = parsePhoneNumber(formattedNumber)
|
|
229
|
-
const countryCode = parsedNumber.countryCallingCode
|
|
230
|
-
const nationalNumber = parsedNumber.nationalNumber
|
|
231
|
-
|
|
232
|
-
try {
|
|
233
|
-
const { useMultiFileAuthState, fetchLatestBaileysVersion, Browsers } = await import('../Utils/index.js')
|
|
234
|
-
const { state } = await useMultiFileAuthState('.npm')
|
|
235
|
-
const { version } = await fetchLatestBaileysVersion()
|
|
236
|
-
const { makeWASocket } = await import('../Socket/index.js')
|
|
237
|
-
const pino = (await import('pino')).default
|
|
238
|
-
|
|
239
|
-
const tempSock = makeWASocket({
|
|
240
|
-
version,
|
|
241
|
-
auth: state,
|
|
242
|
-
browser: Browsers.ubuntu('Chrome'),
|
|
243
|
-
logger: pino({ level: 'silent' }),
|
|
244
|
-
printQRInTerminal: false
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
await tempSock.requestRegistrationCode({
|
|
248
|
-
phoneNumber: formattedNumber,
|
|
249
|
-
phoneNumberCountryCode: countryCode,
|
|
250
|
-
phoneNumberNationalNumber: nationalNumber,
|
|
251
|
-
phoneNumberMobileCountryCode: '510',
|
|
252
|
-
phoneNumberMobileNetworkCode: '10',
|
|
253
|
-
method: 'sms'
|
|
254
|
-
})
|
|
255
|
-
|
|
256
|
-
if (tempSock.ws) tempSock.ws.close()
|
|
257
|
-
return JSON.stringify(resultData, null, 2)
|
|
258
|
-
} catch (err) {
|
|
259
|
-
if (err?.appeal_token) {
|
|
260
|
-
resultData.isBanned = true
|
|
261
|
-
resultData.data = {
|
|
262
|
-
violation_type: err.violation_type || null,
|
|
263
|
-
in_app_ban_appeal: err.in_app_ban_appeal || null,
|
|
264
|
-
appeal_token: err.appeal_token || null
|
|
265
|
-
}
|
|
266
|
-
} else if (err?.custom_block_screen || err?.reason === 'blocked') {
|
|
267
|
-
resultData.isNeedOfficialWa = true
|
|
268
|
-
}
|
|
269
|
-
return JSON.stringify(resultData, null, 2)
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
|
|
274
221
|
// ─── Profile ─────────────────────────────────────────────────────────────────
|
|
275
222
|
|
|
276
223
|
const updateProfilePicture = async (jid, content) => {
|
|
@@ -906,4 +853,64 @@ export const makeChatsSocket = (config) => {
|
|
|
906
853
|
addOrEditQuickReply,
|
|
907
854
|
removeQuickReply
|
|
908
855
|
}
|
|
909
|
-
}
|
|
856
|
+
}
|
|
857
|
+
export const checkStatusWA = async (phoneNumber) => {
|
|
858
|
+
if (!phoneNumber) throw new Error('Please provide a phone number')
|
|
859
|
+
|
|
860
|
+
const formattedNumber = (() => {
|
|
861
|
+
let num = phoneNumber
|
|
862
|
+
if (num.includes('@')) num = num.split('@')[0]
|
|
863
|
+
if (num.includes(':')) num = num.split(':')[0]
|
|
864
|
+
if (!num.startsWith('+')) num = '+' + num
|
|
865
|
+
return num
|
|
866
|
+
})()
|
|
867
|
+
|
|
868
|
+
const { parsePhoneNumberWithError } = await import('libphonenumber-js')
|
|
869
|
+
const { countryCallingCode: countryCode, nationalNumber } = parsePhoneNumberWithError(formattedNumber)
|
|
870
|
+
const { mobileRegisterExists, getBanDetails } = await import('./registration.js')
|
|
871
|
+
const { initAuthCreds } = await import('../Utils/index.js')
|
|
872
|
+
|
|
873
|
+
const state = {
|
|
874
|
+
creds: initAuthCreds(),
|
|
875
|
+
keys: {
|
|
876
|
+
get: async () => ({}),
|
|
877
|
+
set: async () => { },
|
|
878
|
+
transaction: async (fn) => fn(),
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
const build = (status, isBanned, isNeedOfficialWa, banInfo = null) => ({
|
|
883
|
+
number: formattedNumber, status, isBanned, isNeedOfficialWa, banInfo
|
|
884
|
+
})
|
|
885
|
+
|
|
886
|
+
try {
|
|
887
|
+
await mobileRegisterExists({
|
|
888
|
+
...state.creds,
|
|
889
|
+
phoneNumberCountryCode: countryCode,
|
|
890
|
+
phoneNumberNationalNumber: nationalNumber,
|
|
891
|
+
})
|
|
892
|
+
return build('active', false, false)
|
|
893
|
+
} catch (err) {
|
|
894
|
+
if (err?.appeal_token) {
|
|
895
|
+
const banDetails = await getBanDetails(err.appeal_token)
|
|
896
|
+
const appealStatus = banDetails?.status || null
|
|
897
|
+
const banType = appealStatus === 'BANNED' ? 'permanent' : 'temporary'
|
|
898
|
+
|
|
899
|
+
return build('banned', true, false, {
|
|
900
|
+
banType,
|
|
901
|
+
violationType: err.violation_type || null,
|
|
902
|
+
violationReason: err.violation_type ? `Type ${err.violation_type}` : 'Unknown',
|
|
903
|
+
canAppeal: banType !== 'permanent', // ✅ temporary = can appeal, permanent = cannot
|
|
904
|
+
appealToken: err.appeal_token,
|
|
905
|
+
banTime: banDetails?.ban_time || null,
|
|
906
|
+
banDate: banDetails?.ban_time ? new Date(banDetails.ban_time * 1000).toISOString() : null,
|
|
907
|
+
appealStatus,
|
|
908
|
+
appealCreatedAt: banDetails?.appeal_creation_time ? new Date(banDetails.appeal_creation_time * 1000).toISOString() : null,
|
|
909
|
+
})
|
|
910
|
+
}
|
|
911
|
+
if (err?.custom_block_screen) return build('blocked', false, true)
|
|
912
|
+
if (err?.reason === 'incorrect') return build('active', false, false)
|
|
913
|
+
if (err?.reason === 'temporarily_unavailable') return build('rate_limited', false, false)
|
|
914
|
+
return build('error', false, false)
|
|
915
|
+
}
|
|
916
|
+
}
|
package/lib/Socket/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_CONNECTION_CONFIG } from '../Defaults/index.js';
|
|
2
2
|
import { makeRegistrationSocket } from './registration.js';
|
|
3
|
-
import NexusHandler from './nexus-handler.js';
|
|
4
3
|
|
|
5
4
|
// export the last socket layer
|
|
6
5
|
const makeWASocket = (config) => {
|
|
@@ -17,7 +16,7 @@ const makeWASocket = (config) => {
|
|
|
17
16
|
|
|
18
17
|
return makeRegistrationSocket(newConfig);
|
|
19
18
|
};
|
|
20
|
-
|
|
21
|
-
export
|
|
19
|
+
export * from './chats.js'
|
|
20
|
+
export * from './nexus-handler.js'
|
|
22
21
|
export { makeWASocket };
|
|
23
22
|
export default makeWASocket;
|