@areumtecnologia/wasockets 2.0.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1987 -1649
- package/lib/Client/Builders/Buttons.js +127 -0
- package/lib/Client/Builders/EventBuilder.js +122 -0
- package/lib/Client/Builders/InteractiveMessage.js +150 -0
- package/lib/Client/Builders/Lists.js +78 -0
- package/lib/Client/Builders/PollBuilder.js +84 -0
- package/lib/Client/Builders/index.js +21 -0
- package/lib/Client/Constants.js +54 -0
- package/lib/Client/Context/CallContext.js +96 -0
- package/lib/Client/Context/MediaObject.js +155 -0
- package/lib/Client/Context/MessageContext.js +146 -0
- package/lib/Client/Modules/BusinessManager.js +155 -0
- package/lib/Client/Modules/ChannelManager.js +144 -0
- package/lib/Client/Modules/ChatManager.js +113 -0
- package/lib/Client/Modules/CommunityManager.js +136 -0
- package/lib/Client/Modules/GroupManager.js +194 -0
- package/lib/Client/Modules/LabelManager.js +123 -0
- package/lib/Client/Modules/MessageManager.js +198 -0
- package/lib/Client/Modules/PresenceManager.js +68 -0
- package/lib/Client/Modules/PrivacyManager.js +98 -0
- package/lib/Client/Modules/ProfileManager.js +92 -0
- package/lib/Client/Modules/UserManager.js +92 -0
- package/lib/Client/Modules/VoipManager.js +117 -0
- package/lib/Client/Modules/index.js +29 -0
- package/lib/Client/Normalizers/EventNormalizer.js +82 -0
- package/lib/Client/Normalizers/JidNormalizer.js +93 -0
- package/lib/Client/Normalizers/MessageNormalizer.js +134 -0
- package/lib/Client/WaClient.js +438 -0
- package/lib/Client/index.d.ts +464 -0
- package/lib/Client/index.js +76 -0
- package/lib/Defaults/baileys-version.json +1 -1
- package/lib/Defaults/connection.js +14 -1
- package/lib/Socket/index.js +51 -48
- package/lib/Socket/messages-recv.js +74 -13
- package/lib/Socket/messages-send.js +50 -25
- package/lib/Socket/socket.js +13 -0
- package/lib/Socket/voip.js +123 -0
- package/lib/Store/make-cache-manager-store.js +14 -5
- package/lib/Types/index.d.ts +4 -0
- package/lib/Utils/auth-utils.js +16 -1
- package/lib/Utils/browser-utils.js +6 -2
- package/lib/Utils/generics.js +47 -8
- package/lib/Utils/index.d.ts +1 -0
- package/lib/Utils/messages-media.js +44 -21
- package/lib/Utils/pre-key-manager.js +16 -1
- package/lib/Utils/validate-connection.js +10 -11
- package/lib/VoIP/VoIPCrypto.js +150 -0
- package/lib/VoIP/VoIPManager.js +469 -0
- package/lib/VoIP/VoIPMediaEngine.js +224 -0
- package/lib/VoIP/VoIPProtocol.js +354 -0
- package/lib/VoIP/VoIPRelayTransport.js +173 -0
- package/lib/VoIP/VoIPSession.js +314 -0
- package/lib/VoIP/assets/wasm/loader.js +5 -0
- package/lib/VoIP/assets/wasm/whatsapp.wasm +0 -0
- package/lib/VoIP/assets/wasm/worker-modules.js +305 -0
- package/lib/VoIP/engine/audio-feeder.d.mts +15 -0
- package/lib/VoIP/engine/audio-feeder.mjs +243 -0
- package/lib/VoIP/engine/index.d.mts +91 -0
- package/lib/VoIP/engine/index.mjs +1683 -0
- package/lib/VoIP/engine/relay-transport.d.mts +43 -0
- package/lib/VoIP/engine/relay-transport.mjs +607 -0
- package/lib/VoIP/engine/signaling.d.mts +44 -0
- package/lib/VoIP/engine/signaling.mjs +893 -0
- package/lib/VoIP/engine/types.d.mts +183 -0
- package/lib/VoIP/engine/types.mjs +17 -0
- package/lib/VoIP/engine/wasm-engine.d.mts +103 -0
- package/lib/VoIP/engine/wasm-engine.mjs +1397 -0
- package/lib/VoIP/engine/worker-bootstrap.mjs +1049 -0
- package/lib/VoIP/index.js +51 -0
- package/lib/VoIP/utils/audio.d.ts +28 -0
- package/lib/VoIP/utils/audio.js +148 -0
- package/lib/WABinary/generic-utils.js +22 -6
- package/lib/index.d.ts +382 -274
- package/lib/index.js +5 -0
- package/package.json +51 -49
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true })
|
|
4
|
+
|
|
5
|
+
const EventEmitter = require("events")
|
|
6
|
+
const { join } = require("path")
|
|
7
|
+
const { default: makeWASocket } = require("../Socket")
|
|
8
|
+
const { useMultiFileAuthState } = require("../Utils/use-multi-file-auth-state")
|
|
9
|
+
const { shouldReconnect, getReconnectDelay } = require("../Utils/reconnect")
|
|
10
|
+
const { Events, ConnectionStatus } = require("./Constants")
|
|
11
|
+
const { JidNormalizer } = require("./Normalizers/JidNormalizer")
|
|
12
|
+
const { EventNormalizer } = require("./Normalizers/EventNormalizer")
|
|
13
|
+
const {
|
|
14
|
+
MessageManager,
|
|
15
|
+
GroupManager,
|
|
16
|
+
ChannelManager,
|
|
17
|
+
PresenceManager,
|
|
18
|
+
ProfileManager,
|
|
19
|
+
PrivacyManager,
|
|
20
|
+
UserManager,
|
|
21
|
+
ChatManager,
|
|
22
|
+
VoipManager,
|
|
23
|
+
BusinessManager,
|
|
24
|
+
CommunityManager,
|
|
25
|
+
LabelManager
|
|
26
|
+
} = require("./Modules")
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* WaClient - High-Level Unified WhatsApp Client
|
|
30
|
+
*/
|
|
31
|
+
class WaClient extends EventEmitter {
|
|
32
|
+
/**
|
|
33
|
+
* @param {Object} [options={}]
|
|
34
|
+
* @param {string} [options.sessionName='default']
|
|
35
|
+
* @param {string} [options.dataPath='./sessions']
|
|
36
|
+
* @param {Object} [options.auth] - Optional custom auth { state, saveCreds }
|
|
37
|
+
* @param {string} [options.phoneNumber] - Phone number to authenticate via Pairing Code
|
|
38
|
+
* @param {boolean} [options.printQRInTerminal=true]
|
|
39
|
+
* @param {boolean} [options.restartOnClose=true]
|
|
40
|
+
* @param {number} [options.maxReconnectAttempts=15]
|
|
41
|
+
* @param {boolean} [options.syncFullHistory=false]
|
|
42
|
+
* @param {boolean} [options.markOnlineOnConnect=true]
|
|
43
|
+
* @param {Object} [options.socketOptions={}] - Raw socket configuration overrides
|
|
44
|
+
* @param {any} [options.logger]
|
|
45
|
+
*/
|
|
46
|
+
constructor(options = {}) {
|
|
47
|
+
super()
|
|
48
|
+
|
|
49
|
+
this.options = {
|
|
50
|
+
sessionName: 'default',
|
|
51
|
+
dataPath: './sessions',
|
|
52
|
+
printQRInTerminal: true,
|
|
53
|
+
restartOnClose: true,
|
|
54
|
+
maxReconnectAttempts: 15,
|
|
55
|
+
syncFullHistory: false,
|
|
56
|
+
markOnlineOnConnect: true,
|
|
57
|
+
socketOptions: {},
|
|
58
|
+
...options
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this.status = ConnectionStatus.IDLE
|
|
62
|
+
this.sock = null
|
|
63
|
+
this.authState = null
|
|
64
|
+
this.saveCreds = null
|
|
65
|
+
this.reconnectAttempts = 0
|
|
66
|
+
this._reconnectTimer = null
|
|
67
|
+
this._isDestroyed = false
|
|
68
|
+
|
|
69
|
+
// Specialized Domain Managers
|
|
70
|
+
this.messages = new MessageManager(this)
|
|
71
|
+
this.groups = new GroupManager(this)
|
|
72
|
+
this.channels = new ChannelManager(this)
|
|
73
|
+
this.presence = new PresenceManager(this)
|
|
74
|
+
this.profile = new ProfileManager(this)
|
|
75
|
+
this.privacy = new PrivacyManager(this)
|
|
76
|
+
this.users = new UserManager(this)
|
|
77
|
+
this.chat = new ChatManager(this)
|
|
78
|
+
this.voip = new VoipManager(this)
|
|
79
|
+
this.business = new BusinessManager(this)
|
|
80
|
+
this.communities = new CommunityManager(this)
|
|
81
|
+
this.labels = new LabelManager(this)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Connects to WhatsApp
|
|
86
|
+
* @returns {Promise<this>}
|
|
87
|
+
*/
|
|
88
|
+
async connect() {
|
|
89
|
+
if (this._isDestroyed) {
|
|
90
|
+
throw new Error('WaClient instance was destroyed. Create a new instance.')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
this._clearReconnectTimer()
|
|
94
|
+
this._setStatus(ConnectionStatus.INITIALIZING)
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
// 1. Initialize or load auth state
|
|
98
|
+
if (this.options.auth?.state && this.options.auth?.saveCreds) {
|
|
99
|
+
this.authState = this.options.auth.state
|
|
100
|
+
this.saveCreds = this.options.auth.saveCreds
|
|
101
|
+
} else {
|
|
102
|
+
const sessionFolder = join(this.options.dataPath, this.options.sessionName)
|
|
103
|
+
const { state, saveCreds } = await useMultiFileAuthState(sessionFolder)
|
|
104
|
+
this.authState = state
|
|
105
|
+
this.saveCreds = saveCreds
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
this._setStatus(ConnectionStatus.CONNECTING)
|
|
109
|
+
|
|
110
|
+
// 2. Configure and create underlying socket
|
|
111
|
+
const hasPhoneNumber = Boolean(this.options.phoneNumber)
|
|
112
|
+
const socketConfig = {
|
|
113
|
+
auth: this.authState,
|
|
114
|
+
printQRInTerminal: hasPhoneNumber ? false : this.options.printQRInTerminal,
|
|
115
|
+
syncFullHistory: this.options.syncFullHistory,
|
|
116
|
+
markOnlineOnConnect: this.options.markOnlineOnConnect,
|
|
117
|
+
logger: this.options.logger,
|
|
118
|
+
...this.options.socketOptions
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.sock = makeWASocket(socketConfig)
|
|
122
|
+
|
|
123
|
+
// 3. Set up credentials persistence
|
|
124
|
+
this.sock.ev.on('creds.update', async () => {
|
|
125
|
+
if (typeof this.saveCreds === 'function') {
|
|
126
|
+
try {
|
|
127
|
+
await this.saveCreds()
|
|
128
|
+
} catch (err) {
|
|
129
|
+
this.emit(Events.ERROR, err)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
// 4. Set up connection lifecycle
|
|
135
|
+
this._setupConnectionLifecycle()
|
|
136
|
+
|
|
137
|
+
// 5. Bind normalized events (messages, contacts, presence)
|
|
138
|
+
EventNormalizer.bindSocketEvents(this)
|
|
139
|
+
|
|
140
|
+
// 6. Handle pairing code if configured
|
|
141
|
+
if (hasPhoneNumber && !this.sock.authState.creds.registered) {
|
|
142
|
+
this._handlePairingCode(this.options.phoneNumber)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return this
|
|
146
|
+
} catch (error) {
|
|
147
|
+
this._setStatus(ConnectionStatus.DISCONNECTED)
|
|
148
|
+
this.emit(Events.ERROR, error)
|
|
149
|
+
throw error
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Sets up low-level connection listeners
|
|
155
|
+
* @private
|
|
156
|
+
*/
|
|
157
|
+
_setupConnectionLifecycle() {
|
|
158
|
+
this.sock.ev.on('connection.update', async (update) => {
|
|
159
|
+
const { connection, lastDisconnect, qr } = update
|
|
160
|
+
|
|
161
|
+
// QR Code issued
|
|
162
|
+
if (qr) {
|
|
163
|
+
this._setStatus(ConnectionStatus.QR_READY)
|
|
164
|
+
this.emit(Events.QR_CODE, { qr })
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Connection successfully established
|
|
168
|
+
if (connection === 'open') {
|
|
169
|
+
this.reconnectAttempts = 0
|
|
170
|
+
this._setStatus(ConnectionStatus.CONNECTED)
|
|
171
|
+
this.emit(Events.CONNECTED, { user: this.sock.user })
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Connection closed or dropped
|
|
175
|
+
if (connection === 'close') {
|
|
176
|
+
const error = lastDisconnect?.error
|
|
177
|
+
const canReconnect = shouldReconnect(error)
|
|
178
|
+
|
|
179
|
+
if (!canReconnect) {
|
|
180
|
+
this._setStatus(ConnectionStatus.LOGGED_OUT)
|
|
181
|
+
this.emit(Events.LOGGED_OUT, { error })
|
|
182
|
+
} else if (this.options.restartOnClose && !this._isDestroyed) {
|
|
183
|
+
this._scheduleReconnect(error)
|
|
184
|
+
} else {
|
|
185
|
+
this._setStatus(ConnectionStatus.DISCONNECTED)
|
|
186
|
+
this.emit(Events.DISCONNECTED, { error, willReconnect: false })
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Handles pairing code requests
|
|
194
|
+
* @private
|
|
195
|
+
*/
|
|
196
|
+
_handlePairingCode(phoneNumber) {
|
|
197
|
+
const cleanNumber = JidNormalizer.toPhoneNumber(phoneNumber)
|
|
198
|
+
if (!cleanNumber) return
|
|
199
|
+
|
|
200
|
+
const attemptPairing = async (retryCount = 0) => {
|
|
201
|
+
if (this._isDestroyed || !this.sock || this.sock.authState.creds.registered) return
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
this._setStatus(ConnectionStatus.PAIRING_READY)
|
|
205
|
+
const code = await this.sock.requestPairingCode(cleanNumber)
|
|
206
|
+
this.emit(Events.PAIRING_CODE, { code })
|
|
207
|
+
} catch (err) {
|
|
208
|
+
if (retryCount < 3 && !this._isDestroyed) {
|
|
209
|
+
setTimeout(() => attemptPairing(retryCount + 1), 3000)
|
|
210
|
+
} else {
|
|
211
|
+
this.emit(Events.ERROR, err)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Slight delay to ensure socket handshake allows pairing node
|
|
217
|
+
setTimeout(() => attemptPairing(0), 2000)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Schedules reconnection with exponential backoff and jitter
|
|
222
|
+
* @private
|
|
223
|
+
*/
|
|
224
|
+
_scheduleReconnect(error) {
|
|
225
|
+
if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
|
|
226
|
+
this._setStatus(ConnectionStatus.DISCONNECTED)
|
|
227
|
+
this.emit(Events.DISCONNECTED, {
|
|
228
|
+
error,
|
|
229
|
+
willReconnect: false,
|
|
230
|
+
reason: 'Max reconnect attempts exceeded'
|
|
231
|
+
})
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
this.reconnectAttempts++
|
|
236
|
+
const delayMs = getReconnectDelay(this.reconnectAttempts, {
|
|
237
|
+
statusCode: error?.output?.statusCode || error?.statusCode
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
this._setStatus(ConnectionStatus.RECONNECTING)
|
|
241
|
+
this.emit(Events.DISCONNECTED, {
|
|
242
|
+
error,
|
|
243
|
+
willReconnect: true,
|
|
244
|
+
attempt: this.reconnectAttempts,
|
|
245
|
+
delayMs
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
this._clearReconnectTimer()
|
|
249
|
+
this._reconnectTimer = setTimeout(() => {
|
|
250
|
+
if (!this._isDestroyed) {
|
|
251
|
+
this.connect().catch((err) => {
|
|
252
|
+
this.emit(Events.ERROR, err)
|
|
253
|
+
})
|
|
254
|
+
}
|
|
255
|
+
}, delayMs)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Updates internal status and emits STATUS_CHANGE event
|
|
260
|
+
* @private
|
|
261
|
+
*/
|
|
262
|
+
_setStatus(newStatus) {
|
|
263
|
+
const previousStatus = this.status
|
|
264
|
+
if (previousStatus === newStatus) return
|
|
265
|
+
|
|
266
|
+
this.status = newStatus
|
|
267
|
+
this.emit(Events.STATUS_CHANGE, {
|
|
268
|
+
current: newStatus,
|
|
269
|
+
previous: previousStatus
|
|
270
|
+
})
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
_clearReconnectTimer() {
|
|
274
|
+
if (this._reconnectTimer) {
|
|
275
|
+
clearTimeout(this._reconnectTimer)
|
|
276
|
+
this._reconnectTimer = null
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Sends a message to a recipient
|
|
282
|
+
* @param {string} jid - Destination phone number or JID
|
|
283
|
+
* @param {Object} content - Message content object
|
|
284
|
+
* @param {Object} [options={}] - Additional options (quoted, etc.)
|
|
285
|
+
*/
|
|
286
|
+
async sendMessage(jid, content, options = {}) {
|
|
287
|
+
if (!this.sock) {
|
|
288
|
+
throw new Error('Cannot send message: socket is not connected.')
|
|
289
|
+
}
|
|
290
|
+
const targetJid = JidNormalizer.toJid(jid)
|
|
291
|
+
return this.sock.sendMessage(targetJid, content, options)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Sends an interactive message, buttons, list or card
|
|
296
|
+
* @param {string} jid
|
|
297
|
+
* @param {Object|InteractiveMessage} interactiveOrBuilder
|
|
298
|
+
* @param {Object} [options={}]
|
|
299
|
+
*/
|
|
300
|
+
async sendInteractive(jid, interactiveOrBuilder, options = {}) {
|
|
301
|
+
const payload = typeof interactiveOrBuilder?.build === 'function'
|
|
302
|
+
? interactiveOrBuilder.build()
|
|
303
|
+
: interactiveOrBuilder
|
|
304
|
+
return this.sendMessage(jid, payload, options)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Sends a poll to a user or group
|
|
309
|
+
* @param {string} jid
|
|
310
|
+
* @param {Object|PollBuilder} pollOrBuilder
|
|
311
|
+
* @param {Object} [options={}]
|
|
312
|
+
*/
|
|
313
|
+
async sendPoll(jid, pollOrBuilder, options = {}) {
|
|
314
|
+
const payload = typeof pollOrBuilder?.build === 'function'
|
|
315
|
+
? pollOrBuilder.build()
|
|
316
|
+
: pollOrBuilder
|
|
317
|
+
return this.sendMessage(jid, payload, options)
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Sends a group event invitation
|
|
322
|
+
* @param {string} jid
|
|
323
|
+
* @param {Object|EventBuilder} eventOrBuilder
|
|
324
|
+
* @param {Object} [options={}]
|
|
325
|
+
*/
|
|
326
|
+
async sendEvent(jid, eventOrBuilder, options = {}) {
|
|
327
|
+
const payload = typeof eventOrBuilder?.build === 'function'
|
|
328
|
+
? eventOrBuilder.build()
|
|
329
|
+
: eventOrBuilder
|
|
330
|
+
return this.sendMessage(jid, payload, options)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Starts typing (composing) state
|
|
335
|
+
* @param {string} jid
|
|
336
|
+
* @returns {{ stop: () => Promise<void> }}
|
|
337
|
+
*/
|
|
338
|
+
startTyping(jid) {
|
|
339
|
+
const targetJid = JidNormalizer.toJid(jid)
|
|
340
|
+
if (this.sock?.sendPresenceUpdate) {
|
|
341
|
+
this.sock.sendPresenceUpdate('composing', targetJid).catch(() => {})
|
|
342
|
+
}
|
|
343
|
+
return {
|
|
344
|
+
stop: async () => {
|
|
345
|
+
if (this.sock?.sendPresenceUpdate) {
|
|
346
|
+
await this.sock.sendPresenceUpdate('paused', targetJid).catch(() => {})
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Starts voice recording state
|
|
354
|
+
* @param {string} jid
|
|
355
|
+
* @returns {{ stop: () => Promise<void> }}
|
|
356
|
+
*/
|
|
357
|
+
startRecording(jid) {
|
|
358
|
+
const targetJid = JidNormalizer.toJid(jid)
|
|
359
|
+
if (this.sock?.sendPresenceUpdate) {
|
|
360
|
+
this.sock.sendPresenceUpdate('recording', targetJid).catch(() => {})
|
|
361
|
+
}
|
|
362
|
+
return {
|
|
363
|
+
stop: async () => {
|
|
364
|
+
if (this.sock?.sendPresenceUpdate) {
|
|
365
|
+
await this.sock.sendPresenceUpdate('paused', targetJid).catch(() => {})
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Verifies if a phone number or JID exists on WhatsApp
|
|
373
|
+
* @param {string} jidOrNumber
|
|
374
|
+
* @returns {Promise<{ exists: boolean, jid: string } | null>}
|
|
375
|
+
*/
|
|
376
|
+
async isOnWhatsApp(jidOrNumber) {
|
|
377
|
+
if (!this.sock?.onWhatsApp) {
|
|
378
|
+
throw new Error('Socket is not connected.')
|
|
379
|
+
}
|
|
380
|
+
const cleanNumber = JidNormalizer.toPhoneNumber(jidOrNumber) || jidOrNumber
|
|
381
|
+
const results = await this.sock.onWhatsApp(cleanNumber)
|
|
382
|
+
if (Array.isArray(results) && results.length > 0) {
|
|
383
|
+
return {
|
|
384
|
+
exists: Boolean(results[0]?.exists),
|
|
385
|
+
jid: results[0]?.jid || ''
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return null
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Closes the connection gracefully without deleting credentials
|
|
393
|
+
*/
|
|
394
|
+
async disconnect() {
|
|
395
|
+
this._isDestroyed = true
|
|
396
|
+
this._clearReconnectTimer()
|
|
397
|
+
this._setStatus(ConnectionStatus.DISCONNECTED)
|
|
398
|
+
if (this.sock) {
|
|
399
|
+
this.sock.end(undefined)
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Logs out from WhatsApp and revokes device credentials
|
|
405
|
+
*/
|
|
406
|
+
async logout() {
|
|
407
|
+
this._isDestroyed = true
|
|
408
|
+
this._clearReconnectTimer()
|
|
409
|
+
this._setStatus(ConnectionStatus.LOGGED_OUT)
|
|
410
|
+
if (this.sock) {
|
|
411
|
+
await this.sock.logout('WaClient Intentional Logout')
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* The authenticated user profile or null
|
|
417
|
+
*/
|
|
418
|
+
get user() {
|
|
419
|
+
return this.sock?.user || null
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* True if currently connected and open
|
|
424
|
+
*/
|
|
425
|
+
get isConnected() {
|
|
426
|
+
return this.status === ConnectionStatus.CONNECTED
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Direct access to underlying low-level socket
|
|
431
|
+
*/
|
|
432
|
+
get rawSocket() {
|
|
433
|
+
return this.sock
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
exports.WaClient = WaClient
|
|
438
|
+
exports.default = WaClient
|