@celestial-community/baileys 0.0.1-security → 1.0.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.
Potentially problematic release.
This version of @celestial-community/baileys might be problematic. Click here for more details.
- package/WAProto/index.js +138933 -0
- package/engine-requirements.js +10 -0
- package/lib/Defaults/baileys-version.json +7 -0
- package/lib/Defaults/index.js +157 -0
- package/lib/Defaults/phonenumber-mcc.json +223 -0
- package/lib/Signal/Group/ciphertext-message.js +15 -0
- package/lib/Signal/Group/group-session-builder.js +94 -0
- package/lib/Signal/Group/group_cipher.js +118 -0
- package/lib/Signal/Group/index.js +138 -0
- package/lib/Signal/Group/keyhelper.js +75 -0
- package/lib/Signal/Group/queue-job.js +54 -0
- package/lib/Signal/Group/sender-chain-key.js +39 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +71 -0
- package/lib/Signal/Group/sender-key-message.js +76 -0
- package/lib/Signal/Group/sender-key-name.js +50 -0
- package/lib/Signal/Group/sender-key-record.js +65 -0
- package/lib/Signal/Group/sender-key-state.js +114 -0
- package/lib/Signal/Group/sender-message-key.js +33 -0
- package/lib/Signal/libsignal.js +204 -0
- package/lib/Signal/lid-mapping.js +267 -0
- package/lib/Socket/Client/abstract-socket-client.js +13 -0
- package/lib/Socket/Client/index.js +32 -0
- package/lib/Socket/Client/mobile-socket-client.js +82 -0
- package/lib/Socket/Client/web-socket-client.js +89 -0
- package/lib/Socket/Denzy-ZeroDay.js +805 -0
- package/lib/Socket/business.js +279 -0
- package/lib/Socket/chats.js +1169 -0
- package/lib/Socket/community.d.ts +120 -0
- package/lib/Socket/community.js +388 -0
- package/lib/Socket/graphql.js +1122 -0
- package/lib/Socket/groups.js +345 -0
- package/lib/Socket/index.js +22 -0
- package/lib/Socket/interop.js +265 -0
- package/lib/Socket/lid-mapping.js +111 -0
- package/lib/Socket/messages-recv.js +1385 -0
- package/lib/Socket/messages-send.js +956 -0
- package/lib/Socket/mex.js +69 -0
- package/lib/Socket/newsletter.js +424 -0
- package/lib/Socket/privacy.js +229 -0
- package/lib/Socket/registration.js +190 -0
- package/lib/Socket/socket.js +783 -0
- package/lib/Socket/username.d.ts +185 -0
- package/lib/Socket/username.js +168 -0
- package/lib/Socket/usync.js +80 -0
- package/lib/Store/index.js +14 -0
- package/lib/Store/keyed-db.js +158 -0
- package/lib/Store/make-cache-manager-store.js +88 -0
- package/lib/Store/make-in-memory-store.js +484 -0
- package/lib/Store/make-ordered-dictionary.js +78 -0
- package/lib/Store/object-repository.js +27 -0
- package/lib/Types/Auth.js +2 -0
- package/lib/Types/Call.js +2 -0
- package/lib/Types/Chat.js +10 -0
- package/lib/Types/Contact.js +2 -0
- package/lib/Types/Events.js +2 -0
- package/lib/Types/GroupMetadata.js +2 -0
- package/lib/Types/Label.js +27 -0
- package/lib/Types/LabelAssociation.js +9 -0
- package/lib/Types/Message.js +14 -0
- package/lib/Types/MexUpdates.js +19 -0
- package/lib/Types/Newsletter.js +38 -0
- package/lib/Types/Product.js +2 -0
- package/lib/Types/RichType.js +30 -0
- package/lib/Types/Signal.js +2 -0
- package/lib/Types/Socket.js +2 -0
- package/lib/Types/State.js +2 -0
- package/lib/Types/USync.js +2 -0
- package/lib/Types/index.js +58 -0
- package/lib/Utils/anti-ban.js +339 -0
- package/lib/Utils/anti-delete.d.ts +158 -0
- package/lib/Utils/anti-delete.js +293 -0
- package/lib/Utils/antiban-presets.js +91 -0
- package/lib/Utils/antiban-profiles.js +43 -0
- package/lib/Utils/auth-utils.js +210 -0
- package/lib/Utils/baileys-event-stream.js +66 -0
- package/lib/Utils/browser-utils.js +52 -0
- package/lib/Utils/business.js +261 -0
- package/lib/Utils/chat-control.d.ts +113 -0
- package/lib/Utils/chat-control.js +230 -0
- package/lib/Utils/chat-utils.js +922 -0
- package/lib/Utils/companion-reg-client-utils.js +37 -0
- package/lib/Utils/contact-graph-warmer.js +208 -0
- package/lib/Utils/crypto.js +196 -0
- package/lib/Utils/decode-wa-message.js +208 -0
- package/lib/Utils/delivery-tracker.js +110 -0
- package/lib/Utils/device-fingerprint.js +135 -0
- package/lib/Utils/event-buffer.js +531 -0
- package/lib/Utils/generics.js +571 -0
- package/lib/Utils/group-operation-guard.js +147 -0
- package/lib/Utils/health-monitor.js +207 -0
- package/lib/Utils/history.js +122 -0
- package/lib/Utils/human-entropy.js +226 -0
- package/lib/Utils/identity-change-handler.js +72 -0
- package/lib/Utils/index.js +83 -0
- package/lib/Utils/interactive-message.d.ts +139 -0
- package/lib/Utils/interactive-message.js +273 -0
- package/lib/Utils/legitimacy-signal-injector.js +180 -0
- package/lib/Utils/link-preview.js +106 -0
- package/lib/Utils/logger.d.ts +13 -0
- package/lib/Utils/logger.js +9 -0
- package/lib/Utils/lt-hash.js +54 -0
- package/lib/Utils/make-mutex.js +41 -0
- package/lib/Utils/message-composer.d.ts +106 -0
- package/lib/Utils/message-composer.js +721 -0
- package/lib/Utils/message-retry-manager.d.ts +88 -0
- package/lib/Utils/message-retry-manager.js +160 -0
- package/lib/Utils/message-search.d.ts +52 -0
- package/lib/Utils/message-search.js +226 -0
- package/lib/Utils/messages-media.js +899 -0
- package/lib/Utils/messages.js +2698 -0
- package/lib/Utils/noise-handler.js +175 -0
- package/lib/Utils/offline-node-processor.js +45 -0
- package/lib/Utils/pre-key-manager.js +131 -0
- package/lib/Utils/presence-choreographer.js +438 -0
- package/lib/Utils/process-message.js +423 -0
- package/lib/Utils/rate-limiter.js +232 -0
- package/lib/Utils/reconnect-throttle.js +157 -0
- package/lib/Utils/reply-ratio-guard.js +137 -0
- package/lib/Utils/reporting-utils.js +307 -0
- package/lib/Utils/retry-reason-tracker.js +140 -0
- package/lib/Utils/rich-message-utils.d.ts +48 -0
- package/lib/Utils/rich-message-utils.js +400 -0
- package/lib/Utils/rich-response-utils.js +461 -0
- package/lib/Utils/scheduling.d.ts +135 -0
- package/lib/Utils/scheduling.js +246 -0
- package/lib/Utils/session-fingerprint.js +226 -0
- package/lib/Utils/session-stability.js +224 -0
- package/lib/Utils/signal.js +188 -0
- package/lib/Utils/stanza-ack.js +38 -0
- package/lib/Utils/state-manager.js +91 -0
- package/lib/Utils/status-posting.d.ts +81 -0
- package/lib/Utils/status-posting.js +187 -0
- package/lib/Utils/stealth-connect.js +124 -0
- package/lib/Utils/sync-action-utils.js +55 -0
- package/lib/Utils/tc-token-utils.js +171 -0
- package/lib/Utils/templates.d.ts +54 -0
- package/lib/Utils/templates.js +244 -0
- package/lib/Utils/timelock-guard.js +162 -0
- package/lib/Utils/use-mongo-file-auth-state.d.ts +6 -0
- package/lib/Utils/use-mongo-file-auth-state.js +81 -0
- package/lib/Utils/use-multi-file-auth-state.js +125 -0
- package/lib/Utils/use-single-file-auth-state.d.ts +13 -0
- package/lib/Utils/use-single-file-auth-state.js +86 -0
- package/lib/Utils/use-sqlite-auth-state.js +187 -0
- package/lib/Utils/vCard.d.ts +71 -0
- package/lib/Utils/vCard.js +196 -0
- package/lib/Utils/validate-connection.js +253 -0
- package/lib/Utils/warmup.js +154 -0
- package/lib/WABinary/constants.js +1303 -0
- package/lib/WABinary/decode.js +270 -0
- package/lib/WABinary/encode.js +279 -0
- package/lib/WABinary/generic-utils.js +223 -0
- package/lib/WABinary/index.js +34 -0
- package/lib/WABinary/jid-utils.js +84 -0
- package/lib/WABinary/types.js +2 -0
- package/lib/WAM/BinaryInfo.js +13 -0
- package/lib/WAM/constants.js +15254 -0
- package/lib/WAM/encode.js +149 -0
- package/lib/WAM/index.js +32 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +37 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +71 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +32 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +49 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +23 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +58 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
- package/lib/WAUSync/Protocols/index.js +34 -0
- package/lib/WAUSync/USyncQuery.js +99 -0
- package/lib/WAUSync/USyncUser.js +26 -0
- package/lib/WAUSync/USyncUsernameProtocol.d.ts +9 -0
- package/lib/WAUSync/USyncUsernameProtocol.js +37 -0
- package/lib/WAUSync/index.js +32 -0
- package/lib/index.js +59 -0
- package/package.json +105 -5
- package/README.md +0 -5
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true })
|
|
3
|
+
exports.SenderMessageKey = void 0
|
|
4
|
+
const crypto_1 = require('libsignal/src/crypto')
|
|
5
|
+
class SenderMessageKey {
|
|
6
|
+
constructor(iteration, seed) {
|
|
7
|
+
const derivative = (0, crypto_1.deriveSecrets)(
|
|
8
|
+
seed,
|
|
9
|
+
Buffer.alloc(32),
|
|
10
|
+
Buffer.from('WhisperGroup')
|
|
11
|
+
)
|
|
12
|
+
const keys = new Uint8Array(32)
|
|
13
|
+
keys.set(new Uint8Array(derivative[0].slice(16)))
|
|
14
|
+
keys.set(new Uint8Array(derivative[1].slice(0, 16)), 16)
|
|
15
|
+
this.iv = Buffer.from(derivative[0].slice(0, 16))
|
|
16
|
+
this.cipherKey = Buffer.from(keys.buffer)
|
|
17
|
+
this.iteration = iteration
|
|
18
|
+
this.seed = seed
|
|
19
|
+
}
|
|
20
|
+
getIteration() {
|
|
21
|
+
return this.iteration
|
|
22
|
+
}
|
|
23
|
+
getIv() {
|
|
24
|
+
return this.iv
|
|
25
|
+
}
|
|
26
|
+
getCipherKey() {
|
|
27
|
+
return this.cipherKey
|
|
28
|
+
}
|
|
29
|
+
getSeed() {
|
|
30
|
+
return this.seed
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.SenderMessageKey = SenderMessageKey
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
var __createBinding =
|
|
3
|
+
(this && this.__createBinding) ||
|
|
4
|
+
(Object.create
|
|
5
|
+
? function (o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k)
|
|
8
|
+
if (!desc || ('get' in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function () {
|
|
12
|
+
return m[k]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc)
|
|
17
|
+
}
|
|
18
|
+
: function (o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k
|
|
20
|
+
o[k2] = m[k]
|
|
21
|
+
})
|
|
22
|
+
var __setModuleDefault =
|
|
23
|
+
(this && this.__setModuleDefault) ||
|
|
24
|
+
(Object.create
|
|
25
|
+
? function (o, v) {
|
|
26
|
+
Object.defineProperty(o, 'default', { enumerable: true, value: v })
|
|
27
|
+
}
|
|
28
|
+
: function (o, v) {
|
|
29
|
+
o['default'] = v
|
|
30
|
+
})
|
|
31
|
+
var __importStar =
|
|
32
|
+
(this && this.__importStar) ||
|
|
33
|
+
(function () {
|
|
34
|
+
var ownKeys = function (o) {
|
|
35
|
+
ownKeys =
|
|
36
|
+
Object.getOwnPropertyNames ||
|
|
37
|
+
function (o) {
|
|
38
|
+
var ar = []
|
|
39
|
+
for (var k in o)
|
|
40
|
+
if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k
|
|
41
|
+
return ar
|
|
42
|
+
}
|
|
43
|
+
return ownKeys(o)
|
|
44
|
+
}
|
|
45
|
+
return function (mod) {
|
|
46
|
+
if (mod && mod.__esModule) return mod
|
|
47
|
+
var result = {}
|
|
48
|
+
if (mod != null)
|
|
49
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++)
|
|
50
|
+
if (k[i] !== 'default') __createBinding(result, mod, k[i])
|
|
51
|
+
__setModuleDefault(result, mod)
|
|
52
|
+
return result
|
|
53
|
+
}
|
|
54
|
+
})()
|
|
55
|
+
Object.defineProperty(exports, '__esModule', { value: true })
|
|
56
|
+
exports.makeLibSignalRepository = makeLibSignalRepository
|
|
57
|
+
const libsignal = __importStar(require('libsignal'))
|
|
58
|
+
const Utils_1 = require('../Utils')
|
|
59
|
+
const WABinary_1 = require('../WABinary')
|
|
60
|
+
const sender_key_name_1 = require('./Group/sender-key-name')
|
|
61
|
+
const sender_key_record_1 = require('./Group/sender-key-record')
|
|
62
|
+
const Group_1 = require('./Group')
|
|
63
|
+
function makeLibSignalRepository(auth) {
|
|
64
|
+
const storage = signalStorage(auth)
|
|
65
|
+
return {
|
|
66
|
+
decryptGroupMessage({ group, authorJid, msg }) {
|
|
67
|
+
const senderName = jidToSignalSenderKeyName(group, authorJid)
|
|
68
|
+
const cipher = new Group_1.GroupCipher(storage, senderName)
|
|
69
|
+
return cipher.decrypt(msg)
|
|
70
|
+
},
|
|
71
|
+
async processSenderKeyDistributionMessage({ item, authorJid }) {
|
|
72
|
+
const builder = new Group_1.GroupSessionBuilder(storage)
|
|
73
|
+
if (!item.groupId) {
|
|
74
|
+
throw new Error('Group ID is required for sender key distribution message')
|
|
75
|
+
}
|
|
76
|
+
const senderName = jidToSignalSenderKeyName(item.groupId, authorJid)
|
|
77
|
+
const senderMsg = new Group_1.SenderKeyDistributionMessage(
|
|
78
|
+
null,
|
|
79
|
+
null,
|
|
80
|
+
null,
|
|
81
|
+
null,
|
|
82
|
+
item.axolotlSenderKeyDistributionMessage
|
|
83
|
+
)
|
|
84
|
+
const senderNameStr = senderName.toString()
|
|
85
|
+
const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [
|
|
86
|
+
senderNameStr
|
|
87
|
+
])
|
|
88
|
+
if (!senderKey) {
|
|
89
|
+
await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord())
|
|
90
|
+
}
|
|
91
|
+
await builder.process(senderName, senderMsg)
|
|
92
|
+
},
|
|
93
|
+
async decryptMessage({ jid, type, ciphertext }) {
|
|
94
|
+
const addr = jidToSignalProtocolAddress(jid)
|
|
95
|
+
const session = new libsignal.SessionCipher(storage, addr)
|
|
96
|
+
let result
|
|
97
|
+
switch (type) {
|
|
98
|
+
case 'pkmsg':
|
|
99
|
+
result = await session.decryptPreKeyWhisperMessage(ciphertext)
|
|
100
|
+
break
|
|
101
|
+
case 'msg':
|
|
102
|
+
result = await session.decryptWhisperMessage(ciphertext)
|
|
103
|
+
break
|
|
104
|
+
default:
|
|
105
|
+
throw new Error(`Unknown message type: ${type}`)
|
|
106
|
+
}
|
|
107
|
+
return result
|
|
108
|
+
},
|
|
109
|
+
async encryptMessage({ jid, data }) {
|
|
110
|
+
const addr = jidToSignalProtocolAddress(jid)
|
|
111
|
+
const cipher = new libsignal.SessionCipher(storage, addr)
|
|
112
|
+
const { type: sigType, body } = await cipher.encrypt(data)
|
|
113
|
+
const type = sigType === 3 ? 'pkmsg' : 'msg'
|
|
114
|
+
return { type, ciphertext: Buffer.from(body, 'binary') }
|
|
115
|
+
},
|
|
116
|
+
async encryptGroupMessage({ group, meId, data }) {
|
|
117
|
+
const senderName = jidToSignalSenderKeyName(group, meId)
|
|
118
|
+
const builder = new Group_1.GroupSessionBuilder(storage)
|
|
119
|
+
const senderNameStr = senderName.toString()
|
|
120
|
+
const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [
|
|
121
|
+
senderNameStr
|
|
122
|
+
])
|
|
123
|
+
if (!senderKey) {
|
|
124
|
+
await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord())
|
|
125
|
+
}
|
|
126
|
+
const senderKeyDistributionMessage = await builder.create(senderName)
|
|
127
|
+
const session = new Group_1.GroupCipher(storage, senderName)
|
|
128
|
+
const ciphertext = await session.encrypt(data)
|
|
129
|
+
return {
|
|
130
|
+
ciphertext,
|
|
131
|
+
senderKeyDistributionMessage: senderKeyDistributionMessage.serialize()
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
async injectE2ESession({ jid, session }) {
|
|
135
|
+
const cipher = new libsignal.SessionBuilder(storage, jidToSignalProtocolAddress(jid))
|
|
136
|
+
await cipher.initOutgoing(session)
|
|
137
|
+
},
|
|
138
|
+
jidToSignalProtocolAddress(jid) {
|
|
139
|
+
return jidToSignalProtocolAddress(jid).toString()
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const jidToSignalProtocolAddress = (jid) => {
|
|
144
|
+
const { user, device } = (0, WABinary_1.jidDecode)(jid)
|
|
145
|
+
return new libsignal.ProtocolAddress(user, device || 0)
|
|
146
|
+
}
|
|
147
|
+
const jidToSignalSenderKeyName = (group, user) => {
|
|
148
|
+
return new sender_key_name_1.SenderKeyName(group, jidToSignalProtocolAddress(user))
|
|
149
|
+
}
|
|
150
|
+
function signalStorage({ creds, keys }) {
|
|
151
|
+
return {
|
|
152
|
+
loadSession: async (id) => {
|
|
153
|
+
const { [id]: sess } = await keys.get('session', [id])
|
|
154
|
+
if (sess) {
|
|
155
|
+
return libsignal.SessionRecord.deserialize(sess)
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
storeSession: async (id, session) => {
|
|
159
|
+
await keys.set({ session: { [id]: session.serialize() } })
|
|
160
|
+
},
|
|
161
|
+
isTrustedIdentity: () => {
|
|
162
|
+
return true
|
|
163
|
+
},
|
|
164
|
+
loadPreKey: async (id) => {
|
|
165
|
+
const keyId = id.toString()
|
|
166
|
+
const { [keyId]: key } = await keys.get('pre-key', [keyId])
|
|
167
|
+
if (key) {
|
|
168
|
+
return {
|
|
169
|
+
privKey: Buffer.from(key.private),
|
|
170
|
+
pubKey: Buffer.from(key.public)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
removePreKey: (id) => keys.set({ 'pre-key': { [id]: null } }),
|
|
175
|
+
loadSignedPreKey: () => {
|
|
176
|
+
const key = creds.signedPreKey
|
|
177
|
+
return {
|
|
178
|
+
privKey: Buffer.from(key.keyPair.private),
|
|
179
|
+
pubKey: Buffer.from(key.keyPair.public)
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
loadSenderKey: async (senderKeyName) => {
|
|
183
|
+
const keyId = senderKeyName.toString()
|
|
184
|
+
const { [keyId]: key } = await keys.get('sender-key', [keyId])
|
|
185
|
+
if (key) {
|
|
186
|
+
return sender_key_record_1.SenderKeyRecord.deserialize(key)
|
|
187
|
+
}
|
|
188
|
+
return new sender_key_record_1.SenderKeyRecord()
|
|
189
|
+
},
|
|
190
|
+
storeSenderKey: async (senderKeyName, key) => {
|
|
191
|
+
const keyId = senderKeyName.toString()
|
|
192
|
+
const serialized = JSON.stringify(key.serialize())
|
|
193
|
+
await keys.set({ 'sender-key': { [keyId]: Buffer.from(serialized, 'utf-8') } })
|
|
194
|
+
},
|
|
195
|
+
getOurRegistrationId: () => creds.registrationId,
|
|
196
|
+
getOurIdentity: () => {
|
|
197
|
+
const { signedIdentityKey } = creds
|
|
198
|
+
return {
|
|
199
|
+
privKey: Buffer.from(signedIdentityKey.private),
|
|
200
|
+
pubKey: (0, Utils_1.generateSignalPubKey)(signedIdentityKey.public)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true })
|
|
3
|
+
exports.LIDMappingStore = void 0
|
|
4
|
+
|
|
5
|
+
const WABinary_1 = require('../WABinary/jid-utils')
|
|
6
|
+
|
|
7
|
+
const CACHE_TTL_MS = 3 * 24 * 60 * 60 * 1000
|
|
8
|
+
const CACHE_MAX_ENTRIES = 5000
|
|
9
|
+
|
|
10
|
+
const isPnJid = (jid) => typeof jid === 'string' && jid.endsWith('@s.whatsapp.net')
|
|
11
|
+
const isLidJid = (jid) => typeof jid === 'string' && jid.endsWith('@lid')
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Small TTL + size capped cache (keeps this module free of extra dependencies)
|
|
15
|
+
*/
|
|
16
|
+
class TtlCache {
|
|
17
|
+
constructor(ttl, max) {
|
|
18
|
+
this.ttl = ttl
|
|
19
|
+
this.max = max
|
|
20
|
+
this.map = new Map()
|
|
21
|
+
}
|
|
22
|
+
get(key) {
|
|
23
|
+
const hit = this.map.get(key)
|
|
24
|
+
if (!hit) return undefined
|
|
25
|
+
if (hit.exp < Date.now()) {
|
|
26
|
+
this.map.delete(key)
|
|
27
|
+
return undefined
|
|
28
|
+
}
|
|
29
|
+
hit.exp = Date.now() + this.ttl
|
|
30
|
+
return hit.value
|
|
31
|
+
}
|
|
32
|
+
set(key, value) {
|
|
33
|
+
if (this.map.size >= this.max) {
|
|
34
|
+
const oldest = this.map.keys().next().value
|
|
35
|
+
this.map.delete(oldest)
|
|
36
|
+
}
|
|
37
|
+
this.map.set(key, { value, exp: Date.now() + this.ttl })
|
|
38
|
+
}
|
|
39
|
+
clear() {
|
|
40
|
+
this.map.clear()
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Stores PN <-> LID user mappings in the auth key store ('lid-mapping').
|
|
46
|
+
* Purely additive: nothing in the decode / send / session path depends on it.
|
|
47
|
+
*/
|
|
48
|
+
class LIDMappingStore {
|
|
49
|
+
/**
|
|
50
|
+
* @param keys SignalKeyStore (with transaction capability)
|
|
51
|
+
* @param logger pino logger
|
|
52
|
+
* @param pnToLIDFunc optional (jids: string[]) => Promise<{ pn, lid }[]> used when a mapping is unknown
|
|
53
|
+
*/
|
|
54
|
+
constructor(keys, logger, pnToLIDFunc) {
|
|
55
|
+
this.keys = keys
|
|
56
|
+
this.logger = logger
|
|
57
|
+
this.pnToLIDFunc = pnToLIDFunc
|
|
58
|
+
this.cache = new TtlCache(CACHE_TTL_MS, CACHE_MAX_ENTRIES)
|
|
59
|
+
this.inflightLID = new Map()
|
|
60
|
+
this.inflightPN = new Map()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Store one or more { lid, pn } pairs. Invalid pairs are skipped, never thrown. */
|
|
64
|
+
async storeLIDPNMappings(pairs) {
|
|
65
|
+
if (!Array.isArray(pairs) || pairs.length === 0) return
|
|
66
|
+
|
|
67
|
+
const valid = []
|
|
68
|
+
for (const { lid, pn } of pairs) {
|
|
69
|
+
if (!((isLidJid(lid) && isPnJid(pn)) || (isPnJid(lid) && isLidJid(pn)))) {
|
|
70
|
+
this.logger?.warn?.(`Invalid LID-PN mapping: ${lid}, ${pn}`)
|
|
71
|
+
continue
|
|
72
|
+
}
|
|
73
|
+
const lidDecoded = (0, WABinary_1.jidDecode)(isLidJid(lid) ? lid : pn)
|
|
74
|
+
const pnDecoded = (0, WABinary_1.jidDecode)(isPnJid(pn) ? pn : lid)
|
|
75
|
+
if (!lidDecoded || !pnDecoded) continue
|
|
76
|
+
valid.push({ pnUser: pnDecoded.user, lidUser: lidDecoded.user })
|
|
77
|
+
}
|
|
78
|
+
if (valid.length === 0) return
|
|
79
|
+
|
|
80
|
+
const missing = []
|
|
81
|
+
const known = new Map()
|
|
82
|
+
for (const { pnUser } of valid) {
|
|
83
|
+
const cached = this.cache.get(`pn:${pnUser}`)
|
|
84
|
+
if (cached) known.set(pnUser, cached)
|
|
85
|
+
else missing.push(pnUser)
|
|
86
|
+
}
|
|
87
|
+
if (missing.length) {
|
|
88
|
+
const stored = await this.keys.get('lid-mapping', [...new Set(missing)])
|
|
89
|
+
for (const pnUser of new Set(missing)) {
|
|
90
|
+
const lidUser = stored?.[pnUser]
|
|
91
|
+
if (lidUser) {
|
|
92
|
+
known.set(pnUser, lidUser)
|
|
93
|
+
this.cache.set(`pn:${pnUser}`, lidUser)
|
|
94
|
+
this.cache.set(`lid:${lidUser}`, pnUser)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const batch = {}
|
|
100
|
+
const toCache = []
|
|
101
|
+
for (const { pnUser, lidUser } of valid) {
|
|
102
|
+
if (known.get(pnUser) === lidUser) continue
|
|
103
|
+
batch[pnUser] = lidUser
|
|
104
|
+
batch[`${lidUser}_reverse`] = pnUser
|
|
105
|
+
toCache.push([pnUser, lidUser])
|
|
106
|
+
}
|
|
107
|
+
if (Object.keys(batch).length === 0) return
|
|
108
|
+
|
|
109
|
+
await this.keys.transaction(async () => {
|
|
110
|
+
await this.keys.set({ 'lid-mapping': batch })
|
|
111
|
+
}, 'lid-mapping')
|
|
112
|
+
|
|
113
|
+
for (const [pnUser, lidUser] of toCache) {
|
|
114
|
+
this.cache.set(`pn:${pnUser}`, lidUser)
|
|
115
|
+
this.cache.set(`lid:${lidUser}`, pnUser)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async getLIDForPN(pn) {
|
|
120
|
+
const res = await this.getLIDsForPNs([pn])
|
|
121
|
+
return (res && res[0] && res[0].lid) || null
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async getLIDsForPNs(pns) {
|
|
125
|
+
if (!Array.isArray(pns) || pns.length === 0) return null
|
|
126
|
+
const cacheKey = [...new Set(pns)].sort().join(',')
|
|
127
|
+
const inflight = this.inflightLID.get(cacheKey)
|
|
128
|
+
if (inflight) return inflight
|
|
129
|
+
const promise = this._getLIDsForPNs(pns)
|
|
130
|
+
this.inflightLID.set(cacheKey, promise)
|
|
131
|
+
try {
|
|
132
|
+
return await promise
|
|
133
|
+
} finally {
|
|
134
|
+
this.inflightLID.delete(cacheKey)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async _getLIDsForPNs(pns) {
|
|
139
|
+
const out = {}
|
|
140
|
+
const pending = []
|
|
141
|
+
const usyncFetch = new Map()
|
|
142
|
+
|
|
143
|
+
const resolve = (pn, decoded, lidUser) => {
|
|
144
|
+
if (!lidUser) return false
|
|
145
|
+
const device = decoded.device ? `:${decoded.device}` : ''
|
|
146
|
+
out[pn] = { lid: `${lidUser}${device}@lid`, pn }
|
|
147
|
+
return true
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
for (const pn of pns) {
|
|
151
|
+
if (!isPnJid(pn)) continue
|
|
152
|
+
const decoded = (0, WABinary_1.jidDecode)(pn)
|
|
153
|
+
if (!decoded) continue
|
|
154
|
+
const cached = this.cache.get(`pn:${decoded.user}`)
|
|
155
|
+
if (cached) resolve(pn, decoded, cached)
|
|
156
|
+
else pending.push({ pn, decoded })
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (pending.length) {
|
|
160
|
+
const users = [...new Set(pending.map((p) => p.decoded.user))]
|
|
161
|
+
const stored = await this.keys.get('lid-mapping', users)
|
|
162
|
+
for (const user of users) {
|
|
163
|
+
const lidUser = stored?.[user]
|
|
164
|
+
if (lidUser && typeof lidUser === 'string') {
|
|
165
|
+
this.cache.set(`pn:${user}`, lidUser)
|
|
166
|
+
this.cache.set(`lid:${lidUser}`, user)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
for (const { pn, decoded } of pending) {
|
|
170
|
+
const cached = this.cache.get(`pn:${decoded.user}`)
|
|
171
|
+
if (cached) {
|
|
172
|
+
resolve(pn, decoded, cached)
|
|
173
|
+
} else {
|
|
174
|
+
const normalized = (0, WABinary_1.jidNormalizedUser)(pn)
|
|
175
|
+
if (!usyncFetch.has(normalized)) usyncFetch.set(normalized, [])
|
|
176
|
+
usyncFetch.get(normalized).push(decoded.device || 0)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (usyncFetch.size > 0 && this.pnToLIDFunc) {
|
|
182
|
+
try {
|
|
183
|
+
const result = await this.pnToLIDFunc([...usyncFetch.keys()])
|
|
184
|
+
if (result && result.length) {
|
|
185
|
+
await this.storeLIDPNMappings(result)
|
|
186
|
+
for (const pair of result) {
|
|
187
|
+
const pnDecoded = (0, WABinary_1.jidDecode)(pair.pn)
|
|
188
|
+
const lidDecoded = (0, WABinary_1.jidDecode)(pair.lid)
|
|
189
|
+
if (!pnDecoded || !lidDecoded) continue
|
|
190
|
+
for (const device of usyncFetch.get(pair.pn) || [0]) {
|
|
191
|
+
const suffix = device ? `:${device}` : ''
|
|
192
|
+
const pnJid = `${pnDecoded.user}${suffix}@s.whatsapp.net`
|
|
193
|
+
out[pnJid] = { lid: `${lidDecoded.user}${suffix}@lid`, pn: pnJid }
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
} catch (err) {
|
|
198
|
+
// lookup is best effort, never break the caller
|
|
199
|
+
this.logger?.warn?.({ err }, 'LID lookup via usync failed')
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const values = Object.values(out)
|
|
204
|
+
return values.length ? values : null
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async getPNForLID(lid) {
|
|
208
|
+
const res = await this.getPNsForLIDs([lid])
|
|
209
|
+
return (res && res[0] && res[0].pn) || null
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async getPNsForLIDs(lids) {
|
|
213
|
+
if (!Array.isArray(lids) || lids.length === 0) return null
|
|
214
|
+
const cacheKey = [...new Set(lids)].sort().join(',')
|
|
215
|
+
const inflight = this.inflightPN.get(cacheKey)
|
|
216
|
+
if (inflight) return inflight
|
|
217
|
+
const promise = this._getPNsForLIDs(lids)
|
|
218
|
+
this.inflightPN.set(cacheKey, promise)
|
|
219
|
+
try {
|
|
220
|
+
return await promise
|
|
221
|
+
} finally {
|
|
222
|
+
this.inflightPN.delete(cacheKey)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async _getPNsForLIDs(lids) {
|
|
227
|
+
const out = {}
|
|
228
|
+
const pending = []
|
|
229
|
+
|
|
230
|
+
const resolve = (lid, decoded, pnUser) => {
|
|
231
|
+
if (!pnUser || typeof pnUser !== 'string') return false
|
|
232
|
+
const device = decoded.device ? `:${decoded.device}` : ''
|
|
233
|
+
out[lid] = { lid, pn: `${pnUser}${device}@s.whatsapp.net` }
|
|
234
|
+
return true
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
for (const lid of lids) {
|
|
238
|
+
if (!isLidJid(lid)) continue
|
|
239
|
+
const decoded = (0, WABinary_1.jidDecode)(lid)
|
|
240
|
+
if (!decoded) continue
|
|
241
|
+
const cached = this.cache.get(`lid:${decoded.user}`)
|
|
242
|
+
if (cached) resolve(lid, decoded, cached)
|
|
243
|
+
else pending.push({ lid, decoded })
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (pending.length) {
|
|
247
|
+
const reverseKeys = [...new Set(pending.map((p) => `${p.decoded.user}_reverse`))]
|
|
248
|
+
const stored = await this.keys.get('lid-mapping', reverseKeys)
|
|
249
|
+
for (const { lid, decoded } of pending) {
|
|
250
|
+
const pnUser = stored?.[`${decoded.user}_reverse`]
|
|
251
|
+
if (pnUser && typeof pnUser === 'string') {
|
|
252
|
+
this.cache.set(`lid:${decoded.user}`, pnUser)
|
|
253
|
+
this.cache.set(`pn:${pnUser}`, decoded.user)
|
|
254
|
+
resolve(lid, decoded, pnUser)
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const values = Object.values(out)
|
|
260
|
+
return values.length ? values : null
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
close() {
|
|
264
|
+
this.cache.clear()
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
exports.LIDMappingStore = LIDMappingStore
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true })
|
|
3
|
+
exports.AbstractSocketClient = void 0
|
|
4
|
+
const events_1 = require('events')
|
|
5
|
+
class AbstractSocketClient extends events_1.EventEmitter {
|
|
6
|
+
constructor(url, config) {
|
|
7
|
+
super()
|
|
8
|
+
this.url = url
|
|
9
|
+
this.config = config
|
|
10
|
+
this.setMaxListeners(0)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.AbstractSocketClient = AbstractSocketClient
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
var __createBinding =
|
|
3
|
+
(this && this.__createBinding) ||
|
|
4
|
+
(Object.create
|
|
5
|
+
? function (o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k)
|
|
8
|
+
if (!desc || ('get' in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function () {
|
|
12
|
+
return m[k]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc)
|
|
17
|
+
}
|
|
18
|
+
: function (o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k
|
|
20
|
+
o[k2] = m[k]
|
|
21
|
+
})
|
|
22
|
+
var __exportStar =
|
|
23
|
+
(this && this.__exportStar) ||
|
|
24
|
+
function (m, exports) {
|
|
25
|
+
for (var p in m)
|
|
26
|
+
if (p !== 'default' && !Object.prototype.hasOwnProperty.call(exports, p))
|
|
27
|
+
__createBinding(exports, m, p)
|
|
28
|
+
}
|
|
29
|
+
Object.defineProperty(exports, '__esModule', { value: true })
|
|
30
|
+
__exportStar(require('./abstract-socket-client'), exports)
|
|
31
|
+
__exportStar(require('./mobile-socket-client'), exports)
|
|
32
|
+
__exportStar(require('./web-socket-client'), exports)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true })
|
|
3
|
+
exports.MobileSocketClient = void 0
|
|
4
|
+
const net_1 = require('net')
|
|
5
|
+
const abstract_socket_client_1 = require('./abstract-socket-client')
|
|
6
|
+
class MobileSocketClient extends abstract_socket_client_1.AbstractSocketClient {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments)
|
|
9
|
+
this.socket = null
|
|
10
|
+
}
|
|
11
|
+
get isOpen() {
|
|
12
|
+
var _a
|
|
13
|
+
return ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === 'open'
|
|
14
|
+
}
|
|
15
|
+
get isClosed() {
|
|
16
|
+
var _a
|
|
17
|
+
return (
|
|
18
|
+
this.socket === null ||
|
|
19
|
+
((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === 'closed'
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
get isClosing() {
|
|
23
|
+
var _a
|
|
24
|
+
return (
|
|
25
|
+
this.socket === null ||
|
|
26
|
+
((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === 'closed'
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
get isConnecting() {
|
|
30
|
+
var _a
|
|
31
|
+
return ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === 'opening'
|
|
32
|
+
}
|
|
33
|
+
async connect() {
|
|
34
|
+
var _a
|
|
35
|
+
if (this.socket) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
if (this.config.agent) {
|
|
39
|
+
throw new Error('There are not support for proxy agent for mobile connection')
|
|
40
|
+
} else {
|
|
41
|
+
this.socket = (0, net_1.connect)({
|
|
42
|
+
host: this.url.hostname,
|
|
43
|
+
port: Number(this.url.port) || 443
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
this.socket.setMaxListeners(0)
|
|
47
|
+
const events = [
|
|
48
|
+
'close',
|
|
49
|
+
'connect',
|
|
50
|
+
'data',
|
|
51
|
+
'drain',
|
|
52
|
+
'end',
|
|
53
|
+
'error',
|
|
54
|
+
'lookup',
|
|
55
|
+
'ready',
|
|
56
|
+
'timeout'
|
|
57
|
+
]
|
|
58
|
+
for (const event of events) {
|
|
59
|
+
;(_a = this.socket) === null || _a === void 0
|
|
60
|
+
? void 0
|
|
61
|
+
: _a.on(event, (...args) => this.emit(event, ...args))
|
|
62
|
+
}
|
|
63
|
+
this.socket.on('data', (...args) => this.emit('message', ...args))
|
|
64
|
+
this.socket.on('ready', (...args) => this.emit('open', ...args))
|
|
65
|
+
}
|
|
66
|
+
async close() {
|
|
67
|
+
if (!this.socket) {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
this.socket.end(resolve)
|
|
72
|
+
this.socket = null
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
send(str, cb) {
|
|
76
|
+
if (this.socket === null) {
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
return this.socket.write(str, undefined, cb)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.MobileSocketClient = MobileSocketClient
|