@builderbot/provider-sherpa 1.3.15-alpha.153 → 1.3.15-alpha.18
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/dist/index.cjs +173 -17
- package/dist/index.mjs +173 -17
- package/dist/sherpa.d.ts +23 -0
- package/dist/sherpa.d.ts.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -4268,10 +4268,15 @@ const emptyDirSessions = async (pathBase) => new Promise((resolve, reject) => {
|
|
|
4268
4268
|
* @returns The cleaned number.
|
|
4269
4269
|
*/
|
|
4270
4270
|
const baileyCleanNumber = (number, full = false) => {
|
|
4271
|
+
if (!number || typeof number !== 'string') {
|
|
4272
|
+
return '';
|
|
4273
|
+
}
|
|
4271
4274
|
const regexGroup = /\@g.us\b/gm;
|
|
4272
4275
|
const exist = number.match(regexGroup);
|
|
4273
4276
|
if (exist)
|
|
4274
4277
|
return number;
|
|
4278
|
+
if (number.includes('@lid'))
|
|
4279
|
+
return number;
|
|
4275
4280
|
number = number.replace('@s.whatsapp.net', '').replace('+', '').replace(/\s/g, '');
|
|
4276
4281
|
number = !full ? `${number}@s.whatsapp.net` : number;
|
|
4277
4282
|
return number;
|
|
@@ -308802,8 +308807,9 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
308802
308807
|
fallBackAction: undefined,
|
|
308803
308808
|
};
|
|
308804
308809
|
this.reconnectAttempts = 0;
|
|
308805
|
-
this.maxReconnectAttempts =
|
|
308810
|
+
this.maxReconnectAttempts = 50;
|
|
308806
308811
|
this.reconnectDelay = 1000; // 1 segundo inicial
|
|
308812
|
+
this.badSessionCount = 0;
|
|
308807
308813
|
this.idsDuplicates = [];
|
|
308808
308814
|
this.mapSet = new Set();
|
|
308809
308815
|
this.indexHome = (req, res) => {
|
|
@@ -308855,9 +308861,37 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
308855
308861
|
this.initVendor().then((v) => this.listenOnEvents(v));
|
|
308856
308862
|
}
|
|
308857
308863
|
try {
|
|
308864
|
+
// Close previous socket to prevent leaked connections and event listeners
|
|
308865
|
+
if (this.vendor) {
|
|
308866
|
+
try {
|
|
308867
|
+
// Remove all event listeners by event type (whaileys requires event argument)
|
|
308868
|
+
const events = [
|
|
308869
|
+
'connection.update',
|
|
308870
|
+
'creds.update',
|
|
308871
|
+
'messages.upsert',
|
|
308872
|
+
'messages.update',
|
|
308873
|
+
'call',
|
|
308874
|
+
];
|
|
308875
|
+
events.forEach((event) => {
|
|
308876
|
+
try {
|
|
308877
|
+
this.vendor?.ev?.removeAllListeners(event);
|
|
308878
|
+
}
|
|
308879
|
+
catch {
|
|
308880
|
+
// Ignore if event doesn't exist
|
|
308881
|
+
}
|
|
308882
|
+
});
|
|
308883
|
+
this.vendor.ws?.close();
|
|
308884
|
+
this.vendor.end(undefined);
|
|
308885
|
+
}
|
|
308886
|
+
catch (e) {
|
|
308887
|
+
this.logger.log(`[${new Date().toISOString()}] Error closing previous socket:`, e);
|
|
308888
|
+
}
|
|
308889
|
+
this.vendor = undefined;
|
|
308890
|
+
}
|
|
308891
|
+
const waVersion = this.globalVendorArgs.version ?? [2, 3000, 1023223821];
|
|
308858
308892
|
const sock = makeWASocketOther({
|
|
308859
308893
|
logger: loggerSherpa,
|
|
308860
|
-
version:
|
|
308894
|
+
version: waVersion,
|
|
308861
308895
|
printQRInTerminal: false,
|
|
308862
308896
|
auth: {
|
|
308863
308897
|
creds: state.creds,
|
|
@@ -308870,9 +308904,9 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
308870
308904
|
getMessage: this.getMessage,
|
|
308871
308905
|
msgRetryCounterMap: {},
|
|
308872
308906
|
userDevicesCache: this.userDevicesCache,
|
|
308873
|
-
retryRequestDelayMs:
|
|
308907
|
+
retryRequestDelayMs: 2000, // Delay entre reintentos (2s para evitar rate-limit)
|
|
308874
308908
|
connectTimeoutMs: 60_000, // 1 minuto timeout conexión
|
|
308875
|
-
keepAliveIntervalMs:
|
|
308909
|
+
keepAliveIntervalMs: 15_000, // Keep alive cada 15 segundos (recomendado por comunidad)
|
|
308876
308910
|
qrTimeout: 40_000, // 40 segundos para QR
|
|
308877
308911
|
defaultQueryTimeoutMs: 60_000, // 1 minuto para queries
|
|
308878
308912
|
emitOwnEvents: false, // No emitir eventos propios
|
|
@@ -308889,13 +308923,15 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
308889
308923
|
if (this.globalVendorArgs.phoneNumber) {
|
|
308890
308924
|
const phoneNumberClean = bot.utils.removePlus(this.globalVendorArgs.phoneNumber);
|
|
308891
308925
|
await bot.utils.delay(2000);
|
|
308926
|
+
const code = await this.vendor.requestPairingCode(phoneNumberClean);
|
|
308892
308927
|
this.emit('require_action', {
|
|
308893
308928
|
title: '⚡⚡ ACTION REQUIRED ⚡⚡',
|
|
308894
308929
|
instructions: [
|
|
308895
308930
|
`Accept the WhatsApp notification from ${this.globalVendorArgs.phoneNumber} on your phone 👌`,
|
|
308931
|
+
`The pairing code is: ${code}`,
|
|
308896
308932
|
`Need help: https://link.codigoencasa.com/DISCORD`,
|
|
308897
308933
|
],
|
|
308898
|
-
payload: { qr: null },
|
|
308934
|
+
payload: { qr: null, code: code },
|
|
308899
308935
|
});
|
|
308900
308936
|
}
|
|
308901
308937
|
else {
|
|
@@ -308914,6 +308950,7 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
308914
308950
|
const reason = lastDisconnect?.error?.message;
|
|
308915
308951
|
/** Connection closed for various reasons */
|
|
308916
308952
|
if (connection === 'close') {
|
|
308953
|
+
this.stopHealthCheck();
|
|
308917
308954
|
this.logger.log(`[${new Date().toISOString()}] Connection closed. Status: ${statusCode}, Reason: ${reason}`);
|
|
308918
308955
|
// Check if device was removed
|
|
308919
308956
|
const errorData = lastDisconnect?.error?.data;
|
|
@@ -308930,6 +308967,7 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
308930
308967
|
`You can also check a log that has been created sherpa.log`,
|
|
308931
308968
|
`Need help: https://link.codigoencasa.com/DISCORD`,
|
|
308932
308969
|
]);
|
|
308970
|
+
return;
|
|
308933
308971
|
}
|
|
308934
308972
|
// Casos donde NO debemos reconectar
|
|
308935
308973
|
if (statusCode === libExports.DisconnectReason.loggedOut) {
|
|
@@ -308940,11 +308978,30 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
308940
308978
|
await this.delayedReconnect();
|
|
308941
308979
|
return;
|
|
308942
308980
|
}
|
|
308981
|
+
// badSession: try reconnecting first, but if it repeats too many times, clear session
|
|
308982
|
+
if (statusCode === libExports.DisconnectReason.badSession) {
|
|
308983
|
+
this.badSessionCount++;
|
|
308984
|
+
if (this.badSessionCount >= 3) {
|
|
308985
|
+
this.logger.log(`[${new Date().toISOString()}] Bad session repeated ${this.badSessionCount} times, clearing session...`);
|
|
308986
|
+
const PATH_BASE = require$$1.join(process.cwd(), `${this.globalVendorArgs.name}_sessions`);
|
|
308987
|
+
await emptyDirSessions(PATH_BASE);
|
|
308988
|
+
this.badSessionCount = 0;
|
|
308989
|
+
this.reconnectAttempts = 0;
|
|
308990
|
+
}
|
|
308991
|
+
await this.delayedReconnect();
|
|
308992
|
+
return;
|
|
308993
|
+
}
|
|
308943
308994
|
// Casos donde debemos reconectar con backoff
|
|
308944
308995
|
if (this.shouldReconnect(statusCode)) {
|
|
308945
308996
|
await this.delayedReconnect();
|
|
308946
308997
|
return;
|
|
308947
308998
|
}
|
|
308999
|
+
// If statusCode is undefined/unknown, attempt reconnect rather than dying
|
|
309000
|
+
if (statusCode === undefined || statusCode === null) {
|
|
309001
|
+
this.logger.log(`[${new Date().toISOString()}] Unknown disconnect (no status code), attempting reconnect...`);
|
|
309002
|
+
await this.delayedReconnect();
|
|
309003
|
+
return;
|
|
309004
|
+
}
|
|
308948
309005
|
// Casos críticos - emitir error
|
|
308949
309006
|
this.logger.log(`[${new Date().toISOString()}] Critical error, stopping reconnection attempts`);
|
|
308950
309007
|
this.emit('auth_failure', [
|
|
@@ -308959,6 +309016,8 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
308959
309016
|
this.logger.log(`[${new Date().toISOString()}] Connection opened successfully`);
|
|
308960
309017
|
this.reconnectAttempts = 0; // Reset counter on successful connection
|
|
308961
309018
|
this.reconnectDelay = 1000; // Reset delay
|
|
309019
|
+
this.badSessionCount = 0; // Reset bad session counter
|
|
309020
|
+
this.startHealthCheck();
|
|
308962
309021
|
const parseNumber = `${sock?.user?.id}`.split(':').shift();
|
|
308963
309022
|
const host = { ...sock?.user, phone: parseNumber };
|
|
308964
309023
|
this.globalVendorArgs.host = host;
|
|
@@ -309087,15 +309146,13 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
309087
309146
|
this.logger.log(`[${new Date().toISOString()}] Message received from phone, id=${messageCtx.requestId}`, messageCtx);
|
|
309088
309147
|
}
|
|
309089
309148
|
}
|
|
309090
|
-
//
|
|
309091
|
-
const
|
|
309092
|
-
const remoteJidAlt = messageCtx?.key?.remoteJidAlt;
|
|
309093
|
-
const fromParse = remoteJid?.includes('@lid') ? remoteJidAlt : remoteJid;
|
|
309149
|
+
// Extraer el número de teléfono del mensaje
|
|
309150
|
+
const from = this.extractFromFromMessage(messageCtx);
|
|
309094
309151
|
let payload = {
|
|
309095
309152
|
...messageCtx,
|
|
309096
309153
|
body: textToBody,
|
|
309097
309154
|
name: messageCtx?.pushName,
|
|
309098
|
-
from: baileyCleanNumber(
|
|
309155
|
+
from: baileyCleanNumber(from),
|
|
309099
309156
|
};
|
|
309100
309157
|
if (messageCtx.message?.locationMessage) {
|
|
309101
309158
|
const { degreesLatitude, degreesLongitude } = messageCtx.message.locationMessage;
|
|
@@ -309322,6 +309379,8 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
309322
309379
|
* @returns
|
|
309323
309380
|
*/
|
|
309324
309381
|
this.sendImage = async (number, filePath, text) => {
|
|
309382
|
+
if (!this.isVendorReady())
|
|
309383
|
+
throw new Error('Provider not connected. Cannot send image.');
|
|
309325
309384
|
const payload = {
|
|
309326
309385
|
image: { url: filePath },
|
|
309327
309386
|
caption: text,
|
|
@@ -309336,6 +309395,8 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
309336
309395
|
* @returns
|
|
309337
309396
|
*/
|
|
309338
309397
|
this.sendVideo = async (number, filePath, text) => {
|
|
309398
|
+
if (!this.isVendorReady())
|
|
309399
|
+
throw new Error('Provider not connected. Cannot send video.');
|
|
309339
309400
|
const payload = {
|
|
309340
309401
|
video: require$$0$7.readFileSync(filePath),
|
|
309341
309402
|
caption: text,
|
|
@@ -309352,6 +309413,8 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
309352
309413
|
* @example await sendMessage('+XXXXXXXXXXX', 'audio.mp3')
|
|
309353
309414
|
*/
|
|
309354
309415
|
this.sendAudio = async (number, audioUrl) => {
|
|
309416
|
+
if (!this.isVendorReady())
|
|
309417
|
+
throw new Error('Provider not connected. Cannot send audio.');
|
|
309355
309418
|
const payload = {
|
|
309356
309419
|
audio: { url: audioUrl },
|
|
309357
309420
|
ptt: true,
|
|
@@ -309365,6 +309428,8 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
309365
309428
|
* @returns
|
|
309366
309429
|
*/
|
|
309367
309430
|
this.sendText = async (number, message) => {
|
|
309431
|
+
if (!this.isVendorReady())
|
|
309432
|
+
throw new Error('Provider not connected. Cannot send text.');
|
|
309368
309433
|
const payload = { text: message };
|
|
309369
309434
|
return this.vendor.sendMessage(number, payload);
|
|
309370
309435
|
};
|
|
@@ -309375,6 +309440,8 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
309375
309440
|
* @example await sendMessage('+XXXXXXXXXXX', './document/file.pdf')
|
|
309376
309441
|
*/
|
|
309377
309442
|
this.sendFile = async (number, filePath, text) => {
|
|
309443
|
+
if (!this.isVendorReady())
|
|
309444
|
+
throw new Error('Provider not connected. Cannot send file.');
|
|
309378
309445
|
const mimeType = mime.lookup(filePath);
|
|
309379
309446
|
const fileName = require$$1.basename(filePath);
|
|
309380
309447
|
const payload = {
|
|
@@ -309395,6 +309462,8 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
309395
309462
|
* @example await sendMessage("+XXXXXXXXXXX", "Your Text", "Your Footer", [{"buttonId": "id", "buttonText": {"displayText": "Button"}, "type": 1}])
|
|
309396
309463
|
*/
|
|
309397
309464
|
this.sendButtons = async (number, text, buttons) => {
|
|
309465
|
+
if (!this.isVendorReady())
|
|
309466
|
+
throw new Error('Provider not connected. Cannot send buttons.');
|
|
309398
309467
|
this.emit('notice', {
|
|
309399
309468
|
title: 'DEPRECATED',
|
|
309400
309469
|
instructions: [
|
|
@@ -309594,7 +309663,7 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
309594
309663
|
}
|
|
309595
309664
|
setupPeriodicCleanup() {
|
|
309596
309665
|
// Limpiar duplicados cada 10 minutos para evitar memory leaks
|
|
309597
|
-
setInterval(() => {
|
|
309666
|
+
this.periodicCleanupInterval = setInterval(() => {
|
|
309598
309667
|
const maxSize = 1000;
|
|
309599
309668
|
if (this.idsDuplicates.length > maxSize) {
|
|
309600
309669
|
this.logger.log(`[${new Date().toISOString()}] Cleaning duplicates array: ${this.idsDuplicates.length} -> ${maxSize}`);
|
|
@@ -309609,6 +309678,11 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
309609
309678
|
}
|
|
309610
309679
|
cleanup() {
|
|
309611
309680
|
try {
|
|
309681
|
+
this.stopHealthCheck();
|
|
309682
|
+
if (this.periodicCleanupInterval) {
|
|
309683
|
+
clearInterval(this.periodicCleanupInterval);
|
|
309684
|
+
this.periodicCleanupInterval = undefined;
|
|
309685
|
+
}
|
|
309612
309686
|
if (this.msgRetryCounterCache) {
|
|
309613
309687
|
this.msgRetryCounterCache.close();
|
|
309614
309688
|
this.msgRetryCounterCache = undefined;
|
|
@@ -309642,6 +309716,86 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
309642
309716
|
.get('/', this.indexHome);
|
|
309643
309717
|
}
|
|
309644
309718
|
afterHttpServerInit() { }
|
|
309719
|
+
/**
|
|
309720
|
+
* Extrae el número de teléfono (from) de un mensaje
|
|
309721
|
+
* @param messageCtx - Contexto del mensaje
|
|
309722
|
+
* @returns El número de teléfono extraído
|
|
309723
|
+
*/
|
|
309724
|
+
extractFromFromMessage(messageCtx) {
|
|
309725
|
+
const remoteJid = messageCtx?.key?.remoteJid;
|
|
309726
|
+
const remoteJidAlt = messageCtx?.key?.remoteJidAlt;
|
|
309727
|
+
// Si remoteJid contiene @lid, usar remoteJidAlt si existe, sino extraer el número de remoteJid
|
|
309728
|
+
const fromParse = remoteJid?.includes('@lid') ? remoteJidAlt || remoteJid?.split('@')[0] : remoteJid;
|
|
309729
|
+
return fromParse;
|
|
309730
|
+
}
|
|
309731
|
+
/**
|
|
309732
|
+
* Returns true only when the underlying WebSocket is fully open (readyState === 1).
|
|
309733
|
+
* Used as a guard before any send call to avoid silent message loss during reconnects.
|
|
309734
|
+
*/
|
|
309735
|
+
isVendorReady() {
|
|
309736
|
+
return !!(this.vendor && this.vendor.ws?.readyState === 1);
|
|
309737
|
+
}
|
|
309738
|
+
/**
|
|
309739
|
+
* Starts a periodic health check that verifies the WebSocket connection is alive.
|
|
309740
|
+
* If the connection is detected as dead (zombie), it triggers a reconnect.
|
|
309741
|
+
* Also sends periodic presence updates as an application-level heartbeat
|
|
309742
|
+
* to prevent WhatsApp from considering the connection inactive.
|
|
309743
|
+
*/
|
|
309744
|
+
startHealthCheck() {
|
|
309745
|
+
this.stopHealthCheck();
|
|
309746
|
+
// WebSocket state check every 30 seconds
|
|
309747
|
+
this.healthCheckInterval = setInterval(() => {
|
|
309748
|
+
try {
|
|
309749
|
+
const sock = this.vendor;
|
|
309750
|
+
if (!sock)
|
|
309751
|
+
return;
|
|
309752
|
+
const wsState = sock?.ws?.readyState;
|
|
309753
|
+
// WebSocket.OPEN = 1, if it's not open and not connecting, connection is dead
|
|
309754
|
+
if (wsState !== undefined && wsState !== 1 && wsState !== 0) {
|
|
309755
|
+
this.logger.log(`[${new Date().toISOString()}] Health check: WebSocket dead (state=${wsState}), triggering reconnect...`);
|
|
309756
|
+
this.stopHealthCheck();
|
|
309757
|
+
this.delayedReconnect();
|
|
309758
|
+
}
|
|
309759
|
+
}
|
|
309760
|
+
catch (error) {
|
|
309761
|
+
this.logger.log(`[${new Date().toISOString()}] Health check error:`, error);
|
|
309762
|
+
}
|
|
309763
|
+
}, 30_000); // Check every 30 seconds
|
|
309764
|
+
// Presence update with random interval (3-8 min) to mimic human behavior
|
|
309765
|
+
const schedulePresenceHeartbeat = () => {
|
|
309766
|
+
// Guard: don't schedule if health check was stopped (prevents orphaned timers)
|
|
309767
|
+
if (!this.healthCheckInterval)
|
|
309768
|
+
return;
|
|
309769
|
+
const minDelay = 180_000; // 3 minutes
|
|
309770
|
+
const maxDelay = 480_000; // 8 minutes
|
|
309771
|
+
const randomDelay = minDelay + Math.floor(Math.random() * (maxDelay - minDelay));
|
|
309772
|
+
this.presenceInterval = setTimeout(async () => {
|
|
309773
|
+
try {
|
|
309774
|
+
const sock = this.vendor;
|
|
309775
|
+
if (!sock)
|
|
309776
|
+
return;
|
|
309777
|
+
await sock.sendPresenceUpdate('available');
|
|
309778
|
+
this.logger.log(`[${new Date().toISOString()}] Presence heartbeat sent (next in ~${Math.round(randomDelay / 60_000)}min)`);
|
|
309779
|
+
}
|
|
309780
|
+
catch (error) {
|
|
309781
|
+
this.logger.log(`[${new Date().toISOString()}] Presence heartbeat error:`, error);
|
|
309782
|
+
}
|
|
309783
|
+
// Schedule the next one with a new random delay
|
|
309784
|
+
schedulePresenceHeartbeat();
|
|
309785
|
+
}, randomDelay);
|
|
309786
|
+
};
|
|
309787
|
+
schedulePresenceHeartbeat();
|
|
309788
|
+
}
|
|
309789
|
+
stopHealthCheck() {
|
|
309790
|
+
if (this.healthCheckInterval) {
|
|
309791
|
+
clearInterval(this.healthCheckInterval);
|
|
309792
|
+
this.healthCheckInterval = undefined;
|
|
309793
|
+
}
|
|
309794
|
+
if (this.presenceInterval) {
|
|
309795
|
+
clearTimeout(this.presenceInterval);
|
|
309796
|
+
this.presenceInterval = undefined;
|
|
309797
|
+
}
|
|
309798
|
+
}
|
|
309645
309799
|
shouldReconnect(statusCode) {
|
|
309646
309800
|
// Lista de códigos donde SÍ debemos reconectar
|
|
309647
309801
|
const reconnectableCodes = [
|
|
@@ -309673,13 +309827,15 @@ class SherpaProvider extends bot.ProviderClass {
|
|
|
309673
309827
|
this.reconnectAttempts++;
|
|
309674
309828
|
const delay = Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1), 30000); // Max 30 segundos
|
|
309675
309829
|
this.logger.log(`[${new Date().toISOString()}] Reconnection attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts} in ${delay}ms`);
|
|
309676
|
-
setTimeout(
|
|
309677
|
-
|
|
309678
|
-
|
|
309679
|
-
|
|
309680
|
-
catch (error) {
|
|
309830
|
+
setTimeout(() => {
|
|
309831
|
+
this.initVendor()
|
|
309832
|
+
.then((v) => this.listenOnEvents(v))
|
|
309833
|
+
.catch((error) => {
|
|
309681
309834
|
this.logger.log(`[${new Date().toISOString()}] Reconnection failed:`, error);
|
|
309682
|
-
|
|
309835
|
+
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
309836
|
+
this.delayedReconnect();
|
|
309837
|
+
}
|
|
309838
|
+
});
|
|
309683
309839
|
}, delay);
|
|
309684
309840
|
}
|
|
309685
309841
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -4266,10 +4266,15 @@ const emptyDirSessions = async (pathBase) => new Promise((resolve, reject) => {
|
|
|
4266
4266
|
* @returns The cleaned number.
|
|
4267
4267
|
*/
|
|
4268
4268
|
const baileyCleanNumber = (number, full = false) => {
|
|
4269
|
+
if (!number || typeof number !== 'string') {
|
|
4270
|
+
return '';
|
|
4271
|
+
}
|
|
4269
4272
|
const regexGroup = /\@g.us\b/gm;
|
|
4270
4273
|
const exist = number.match(regexGroup);
|
|
4271
4274
|
if (exist)
|
|
4272
4275
|
return number;
|
|
4276
|
+
if (number.includes('@lid'))
|
|
4277
|
+
return number;
|
|
4273
4278
|
number = number.replace('@s.whatsapp.net', '').replace('+', '').replace(/\s/g, '');
|
|
4274
4279
|
number = !full ? `${number}@s.whatsapp.net` : number;
|
|
4275
4280
|
return number;
|
|
@@ -308800,8 +308805,9 @@ class SherpaProvider extends ProviderClass {
|
|
|
308800
308805
|
fallBackAction: undefined,
|
|
308801
308806
|
};
|
|
308802
308807
|
this.reconnectAttempts = 0;
|
|
308803
|
-
this.maxReconnectAttempts =
|
|
308808
|
+
this.maxReconnectAttempts = 50;
|
|
308804
308809
|
this.reconnectDelay = 1000; // 1 segundo inicial
|
|
308810
|
+
this.badSessionCount = 0;
|
|
308805
308811
|
this.idsDuplicates = [];
|
|
308806
308812
|
this.mapSet = new Set();
|
|
308807
308813
|
this.indexHome = (req, res) => {
|
|
@@ -308853,9 +308859,37 @@ class SherpaProvider extends ProviderClass {
|
|
|
308853
308859
|
this.initVendor().then((v) => this.listenOnEvents(v));
|
|
308854
308860
|
}
|
|
308855
308861
|
try {
|
|
308862
|
+
// Close previous socket to prevent leaked connections and event listeners
|
|
308863
|
+
if (this.vendor) {
|
|
308864
|
+
try {
|
|
308865
|
+
// Remove all event listeners by event type (whaileys requires event argument)
|
|
308866
|
+
const events = [
|
|
308867
|
+
'connection.update',
|
|
308868
|
+
'creds.update',
|
|
308869
|
+
'messages.upsert',
|
|
308870
|
+
'messages.update',
|
|
308871
|
+
'call',
|
|
308872
|
+
];
|
|
308873
|
+
events.forEach((event) => {
|
|
308874
|
+
try {
|
|
308875
|
+
this.vendor?.ev?.removeAllListeners(event);
|
|
308876
|
+
}
|
|
308877
|
+
catch {
|
|
308878
|
+
// Ignore if event doesn't exist
|
|
308879
|
+
}
|
|
308880
|
+
});
|
|
308881
|
+
this.vendor.ws?.close();
|
|
308882
|
+
this.vendor.end(undefined);
|
|
308883
|
+
}
|
|
308884
|
+
catch (e) {
|
|
308885
|
+
this.logger.log(`[${new Date().toISOString()}] Error closing previous socket:`, e);
|
|
308886
|
+
}
|
|
308887
|
+
this.vendor = undefined;
|
|
308888
|
+
}
|
|
308889
|
+
const waVersion = this.globalVendorArgs.version ?? [2, 3000, 1023223821];
|
|
308856
308890
|
const sock = makeWASocketOther({
|
|
308857
308891
|
logger: loggerSherpa,
|
|
308858
|
-
version:
|
|
308892
|
+
version: waVersion,
|
|
308859
308893
|
printQRInTerminal: false,
|
|
308860
308894
|
auth: {
|
|
308861
308895
|
creds: state.creds,
|
|
@@ -308868,9 +308902,9 @@ class SherpaProvider extends ProviderClass {
|
|
|
308868
308902
|
getMessage: this.getMessage,
|
|
308869
308903
|
msgRetryCounterMap: {},
|
|
308870
308904
|
userDevicesCache: this.userDevicesCache,
|
|
308871
|
-
retryRequestDelayMs:
|
|
308905
|
+
retryRequestDelayMs: 2000, // Delay entre reintentos (2s para evitar rate-limit)
|
|
308872
308906
|
connectTimeoutMs: 60_000, // 1 minuto timeout conexión
|
|
308873
|
-
keepAliveIntervalMs:
|
|
308907
|
+
keepAliveIntervalMs: 15_000, // Keep alive cada 15 segundos (recomendado por comunidad)
|
|
308874
308908
|
qrTimeout: 40_000, // 40 segundos para QR
|
|
308875
308909
|
defaultQueryTimeoutMs: 60_000, // 1 minuto para queries
|
|
308876
308910
|
emitOwnEvents: false, // No emitir eventos propios
|
|
@@ -308887,13 +308921,15 @@ class SherpaProvider extends ProviderClass {
|
|
|
308887
308921
|
if (this.globalVendorArgs.phoneNumber) {
|
|
308888
308922
|
const phoneNumberClean = utils$6.removePlus(this.globalVendorArgs.phoneNumber);
|
|
308889
308923
|
await utils$6.delay(2000);
|
|
308924
|
+
const code = await this.vendor.requestPairingCode(phoneNumberClean);
|
|
308890
308925
|
this.emit('require_action', {
|
|
308891
308926
|
title: '⚡⚡ ACTION REQUIRED ⚡⚡',
|
|
308892
308927
|
instructions: [
|
|
308893
308928
|
`Accept the WhatsApp notification from ${this.globalVendorArgs.phoneNumber} on your phone 👌`,
|
|
308929
|
+
`The pairing code is: ${code}`,
|
|
308894
308930
|
`Need help: https://link.codigoencasa.com/DISCORD`,
|
|
308895
308931
|
],
|
|
308896
|
-
payload: { qr: null },
|
|
308932
|
+
payload: { qr: null, code: code },
|
|
308897
308933
|
});
|
|
308898
308934
|
}
|
|
308899
308935
|
else {
|
|
@@ -308912,6 +308948,7 @@ class SherpaProvider extends ProviderClass {
|
|
|
308912
308948
|
const reason = lastDisconnect?.error?.message;
|
|
308913
308949
|
/** Connection closed for various reasons */
|
|
308914
308950
|
if (connection === 'close') {
|
|
308951
|
+
this.stopHealthCheck();
|
|
308915
308952
|
this.logger.log(`[${new Date().toISOString()}] Connection closed. Status: ${statusCode}, Reason: ${reason}`);
|
|
308916
308953
|
// Check if device was removed
|
|
308917
308954
|
const errorData = lastDisconnect?.error?.data;
|
|
@@ -308928,6 +308965,7 @@ class SherpaProvider extends ProviderClass {
|
|
|
308928
308965
|
`You can also check a log that has been created sherpa.log`,
|
|
308929
308966
|
`Need help: https://link.codigoencasa.com/DISCORD`,
|
|
308930
308967
|
]);
|
|
308968
|
+
return;
|
|
308931
308969
|
}
|
|
308932
308970
|
// Casos donde NO debemos reconectar
|
|
308933
308971
|
if (statusCode === libExports.DisconnectReason.loggedOut) {
|
|
@@ -308938,11 +308976,30 @@ class SherpaProvider extends ProviderClass {
|
|
|
308938
308976
|
await this.delayedReconnect();
|
|
308939
308977
|
return;
|
|
308940
308978
|
}
|
|
308979
|
+
// badSession: try reconnecting first, but if it repeats too many times, clear session
|
|
308980
|
+
if (statusCode === libExports.DisconnectReason.badSession) {
|
|
308981
|
+
this.badSessionCount++;
|
|
308982
|
+
if (this.badSessionCount >= 3) {
|
|
308983
|
+
this.logger.log(`[${new Date().toISOString()}] Bad session repeated ${this.badSessionCount} times, clearing session...`);
|
|
308984
|
+
const PATH_BASE = join(process.cwd(), `${this.globalVendorArgs.name}_sessions`);
|
|
308985
|
+
await emptyDirSessions(PATH_BASE);
|
|
308986
|
+
this.badSessionCount = 0;
|
|
308987
|
+
this.reconnectAttempts = 0;
|
|
308988
|
+
}
|
|
308989
|
+
await this.delayedReconnect();
|
|
308990
|
+
return;
|
|
308991
|
+
}
|
|
308941
308992
|
// Casos donde debemos reconectar con backoff
|
|
308942
308993
|
if (this.shouldReconnect(statusCode)) {
|
|
308943
308994
|
await this.delayedReconnect();
|
|
308944
308995
|
return;
|
|
308945
308996
|
}
|
|
308997
|
+
// If statusCode is undefined/unknown, attempt reconnect rather than dying
|
|
308998
|
+
if (statusCode === undefined || statusCode === null) {
|
|
308999
|
+
this.logger.log(`[${new Date().toISOString()}] Unknown disconnect (no status code), attempting reconnect...`);
|
|
309000
|
+
await this.delayedReconnect();
|
|
309001
|
+
return;
|
|
309002
|
+
}
|
|
308946
309003
|
// Casos críticos - emitir error
|
|
308947
309004
|
this.logger.log(`[${new Date().toISOString()}] Critical error, stopping reconnection attempts`);
|
|
308948
309005
|
this.emit('auth_failure', [
|
|
@@ -308957,6 +309014,8 @@ class SherpaProvider extends ProviderClass {
|
|
|
308957
309014
|
this.logger.log(`[${new Date().toISOString()}] Connection opened successfully`);
|
|
308958
309015
|
this.reconnectAttempts = 0; // Reset counter on successful connection
|
|
308959
309016
|
this.reconnectDelay = 1000; // Reset delay
|
|
309017
|
+
this.badSessionCount = 0; // Reset bad session counter
|
|
309018
|
+
this.startHealthCheck();
|
|
308960
309019
|
const parseNumber = `${sock?.user?.id}`.split(':').shift();
|
|
308961
309020
|
const host = { ...sock?.user, phone: parseNumber };
|
|
308962
309021
|
this.globalVendorArgs.host = host;
|
|
@@ -309085,15 +309144,13 @@ class SherpaProvider extends ProviderClass {
|
|
|
309085
309144
|
this.logger.log(`[${new Date().toISOString()}] Message received from phone, id=${messageCtx.requestId}`, messageCtx);
|
|
309086
309145
|
}
|
|
309087
309146
|
}
|
|
309088
|
-
//
|
|
309089
|
-
const
|
|
309090
|
-
const remoteJidAlt = messageCtx?.key?.remoteJidAlt;
|
|
309091
|
-
const fromParse = remoteJid?.includes('@lid') ? remoteJidAlt : remoteJid;
|
|
309147
|
+
// Extraer el número de teléfono del mensaje
|
|
309148
|
+
const from = this.extractFromFromMessage(messageCtx);
|
|
309092
309149
|
let payload = {
|
|
309093
309150
|
...messageCtx,
|
|
309094
309151
|
body: textToBody,
|
|
309095
309152
|
name: messageCtx?.pushName,
|
|
309096
|
-
from: baileyCleanNumber(
|
|
309153
|
+
from: baileyCleanNumber(from),
|
|
309097
309154
|
};
|
|
309098
309155
|
if (messageCtx.message?.locationMessage) {
|
|
309099
309156
|
const { degreesLatitude, degreesLongitude } = messageCtx.message.locationMessage;
|
|
@@ -309320,6 +309377,8 @@ class SherpaProvider extends ProviderClass {
|
|
|
309320
309377
|
* @returns
|
|
309321
309378
|
*/
|
|
309322
309379
|
this.sendImage = async (number, filePath, text) => {
|
|
309380
|
+
if (!this.isVendorReady())
|
|
309381
|
+
throw new Error('Provider not connected. Cannot send image.');
|
|
309323
309382
|
const payload = {
|
|
309324
309383
|
image: { url: filePath },
|
|
309325
309384
|
caption: text,
|
|
@@ -309334,6 +309393,8 @@ class SherpaProvider extends ProviderClass {
|
|
|
309334
309393
|
* @returns
|
|
309335
309394
|
*/
|
|
309336
309395
|
this.sendVideo = async (number, filePath, text) => {
|
|
309396
|
+
if (!this.isVendorReady())
|
|
309397
|
+
throw new Error('Provider not connected. Cannot send video.');
|
|
309337
309398
|
const payload = {
|
|
309338
309399
|
video: readFileSync(filePath),
|
|
309339
309400
|
caption: text,
|
|
@@ -309350,6 +309411,8 @@ class SherpaProvider extends ProviderClass {
|
|
|
309350
309411
|
* @example await sendMessage('+XXXXXXXXXXX', 'audio.mp3')
|
|
309351
309412
|
*/
|
|
309352
309413
|
this.sendAudio = async (number, audioUrl) => {
|
|
309414
|
+
if (!this.isVendorReady())
|
|
309415
|
+
throw new Error('Provider not connected. Cannot send audio.');
|
|
309353
309416
|
const payload = {
|
|
309354
309417
|
audio: { url: audioUrl },
|
|
309355
309418
|
ptt: true,
|
|
@@ -309363,6 +309426,8 @@ class SherpaProvider extends ProviderClass {
|
|
|
309363
309426
|
* @returns
|
|
309364
309427
|
*/
|
|
309365
309428
|
this.sendText = async (number, message) => {
|
|
309429
|
+
if (!this.isVendorReady())
|
|
309430
|
+
throw new Error('Provider not connected. Cannot send text.');
|
|
309366
309431
|
const payload = { text: message };
|
|
309367
309432
|
return this.vendor.sendMessage(number, payload);
|
|
309368
309433
|
};
|
|
@@ -309373,6 +309438,8 @@ class SherpaProvider extends ProviderClass {
|
|
|
309373
309438
|
* @example await sendMessage('+XXXXXXXXXXX', './document/file.pdf')
|
|
309374
309439
|
*/
|
|
309375
309440
|
this.sendFile = async (number, filePath, text) => {
|
|
309441
|
+
if (!this.isVendorReady())
|
|
309442
|
+
throw new Error('Provider not connected. Cannot send file.');
|
|
309376
309443
|
const mimeType = mime.lookup(filePath);
|
|
309377
309444
|
const fileName = basename(filePath);
|
|
309378
309445
|
const payload = {
|
|
@@ -309393,6 +309460,8 @@ class SherpaProvider extends ProviderClass {
|
|
|
309393
309460
|
* @example await sendMessage("+XXXXXXXXXXX", "Your Text", "Your Footer", [{"buttonId": "id", "buttonText": {"displayText": "Button"}, "type": 1}])
|
|
309394
309461
|
*/
|
|
309395
309462
|
this.sendButtons = async (number, text, buttons) => {
|
|
309463
|
+
if (!this.isVendorReady())
|
|
309464
|
+
throw new Error('Provider not connected. Cannot send buttons.');
|
|
309396
309465
|
this.emit('notice', {
|
|
309397
309466
|
title: 'DEPRECATED',
|
|
309398
309467
|
instructions: [
|
|
@@ -309592,7 +309661,7 @@ class SherpaProvider extends ProviderClass {
|
|
|
309592
309661
|
}
|
|
309593
309662
|
setupPeriodicCleanup() {
|
|
309594
309663
|
// Limpiar duplicados cada 10 minutos para evitar memory leaks
|
|
309595
|
-
setInterval(() => {
|
|
309664
|
+
this.periodicCleanupInterval = setInterval(() => {
|
|
309596
309665
|
const maxSize = 1000;
|
|
309597
309666
|
if (this.idsDuplicates.length > maxSize) {
|
|
309598
309667
|
this.logger.log(`[${new Date().toISOString()}] Cleaning duplicates array: ${this.idsDuplicates.length} -> ${maxSize}`);
|
|
@@ -309607,6 +309676,11 @@ class SherpaProvider extends ProviderClass {
|
|
|
309607
309676
|
}
|
|
309608
309677
|
cleanup() {
|
|
309609
309678
|
try {
|
|
309679
|
+
this.stopHealthCheck();
|
|
309680
|
+
if (this.periodicCleanupInterval) {
|
|
309681
|
+
clearInterval(this.periodicCleanupInterval);
|
|
309682
|
+
this.periodicCleanupInterval = undefined;
|
|
309683
|
+
}
|
|
309610
309684
|
if (this.msgRetryCounterCache) {
|
|
309611
309685
|
this.msgRetryCounterCache.close();
|
|
309612
309686
|
this.msgRetryCounterCache = undefined;
|
|
@@ -309640,6 +309714,86 @@ class SherpaProvider extends ProviderClass {
|
|
|
309640
309714
|
.get('/', this.indexHome);
|
|
309641
309715
|
}
|
|
309642
309716
|
afterHttpServerInit() { }
|
|
309717
|
+
/**
|
|
309718
|
+
* Extrae el número de teléfono (from) de un mensaje
|
|
309719
|
+
* @param messageCtx - Contexto del mensaje
|
|
309720
|
+
* @returns El número de teléfono extraído
|
|
309721
|
+
*/
|
|
309722
|
+
extractFromFromMessage(messageCtx) {
|
|
309723
|
+
const remoteJid = messageCtx?.key?.remoteJid;
|
|
309724
|
+
const remoteJidAlt = messageCtx?.key?.remoteJidAlt;
|
|
309725
|
+
// Si remoteJid contiene @lid, usar remoteJidAlt si existe, sino extraer el número de remoteJid
|
|
309726
|
+
const fromParse = remoteJid?.includes('@lid') ? remoteJidAlt || remoteJid?.split('@')[0] : remoteJid;
|
|
309727
|
+
return fromParse;
|
|
309728
|
+
}
|
|
309729
|
+
/**
|
|
309730
|
+
* Returns true only when the underlying WebSocket is fully open (readyState === 1).
|
|
309731
|
+
* Used as a guard before any send call to avoid silent message loss during reconnects.
|
|
309732
|
+
*/
|
|
309733
|
+
isVendorReady() {
|
|
309734
|
+
return !!(this.vendor && this.vendor.ws?.readyState === 1);
|
|
309735
|
+
}
|
|
309736
|
+
/**
|
|
309737
|
+
* Starts a periodic health check that verifies the WebSocket connection is alive.
|
|
309738
|
+
* If the connection is detected as dead (zombie), it triggers a reconnect.
|
|
309739
|
+
* Also sends periodic presence updates as an application-level heartbeat
|
|
309740
|
+
* to prevent WhatsApp from considering the connection inactive.
|
|
309741
|
+
*/
|
|
309742
|
+
startHealthCheck() {
|
|
309743
|
+
this.stopHealthCheck();
|
|
309744
|
+
// WebSocket state check every 30 seconds
|
|
309745
|
+
this.healthCheckInterval = setInterval(() => {
|
|
309746
|
+
try {
|
|
309747
|
+
const sock = this.vendor;
|
|
309748
|
+
if (!sock)
|
|
309749
|
+
return;
|
|
309750
|
+
const wsState = sock?.ws?.readyState;
|
|
309751
|
+
// WebSocket.OPEN = 1, if it's not open and not connecting, connection is dead
|
|
309752
|
+
if (wsState !== undefined && wsState !== 1 && wsState !== 0) {
|
|
309753
|
+
this.logger.log(`[${new Date().toISOString()}] Health check: WebSocket dead (state=${wsState}), triggering reconnect...`);
|
|
309754
|
+
this.stopHealthCheck();
|
|
309755
|
+
this.delayedReconnect();
|
|
309756
|
+
}
|
|
309757
|
+
}
|
|
309758
|
+
catch (error) {
|
|
309759
|
+
this.logger.log(`[${new Date().toISOString()}] Health check error:`, error);
|
|
309760
|
+
}
|
|
309761
|
+
}, 30_000); // Check every 30 seconds
|
|
309762
|
+
// Presence update with random interval (3-8 min) to mimic human behavior
|
|
309763
|
+
const schedulePresenceHeartbeat = () => {
|
|
309764
|
+
// Guard: don't schedule if health check was stopped (prevents orphaned timers)
|
|
309765
|
+
if (!this.healthCheckInterval)
|
|
309766
|
+
return;
|
|
309767
|
+
const minDelay = 180_000; // 3 minutes
|
|
309768
|
+
const maxDelay = 480_000; // 8 minutes
|
|
309769
|
+
const randomDelay = minDelay + Math.floor(Math.random() * (maxDelay - minDelay));
|
|
309770
|
+
this.presenceInterval = setTimeout(async () => {
|
|
309771
|
+
try {
|
|
309772
|
+
const sock = this.vendor;
|
|
309773
|
+
if (!sock)
|
|
309774
|
+
return;
|
|
309775
|
+
await sock.sendPresenceUpdate('available');
|
|
309776
|
+
this.logger.log(`[${new Date().toISOString()}] Presence heartbeat sent (next in ~${Math.round(randomDelay / 60_000)}min)`);
|
|
309777
|
+
}
|
|
309778
|
+
catch (error) {
|
|
309779
|
+
this.logger.log(`[${new Date().toISOString()}] Presence heartbeat error:`, error);
|
|
309780
|
+
}
|
|
309781
|
+
// Schedule the next one with a new random delay
|
|
309782
|
+
schedulePresenceHeartbeat();
|
|
309783
|
+
}, randomDelay);
|
|
309784
|
+
};
|
|
309785
|
+
schedulePresenceHeartbeat();
|
|
309786
|
+
}
|
|
309787
|
+
stopHealthCheck() {
|
|
309788
|
+
if (this.healthCheckInterval) {
|
|
309789
|
+
clearInterval(this.healthCheckInterval);
|
|
309790
|
+
this.healthCheckInterval = undefined;
|
|
309791
|
+
}
|
|
309792
|
+
if (this.presenceInterval) {
|
|
309793
|
+
clearTimeout(this.presenceInterval);
|
|
309794
|
+
this.presenceInterval = undefined;
|
|
309795
|
+
}
|
|
309796
|
+
}
|
|
309643
309797
|
shouldReconnect(statusCode) {
|
|
309644
309798
|
// Lista de códigos donde SÍ debemos reconectar
|
|
309645
309799
|
const reconnectableCodes = [
|
|
@@ -309671,13 +309825,15 @@ class SherpaProvider extends ProviderClass {
|
|
|
309671
309825
|
this.reconnectAttempts++;
|
|
309672
309826
|
const delay = Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1), 30000); // Max 30 segundos
|
|
309673
309827
|
this.logger.log(`[${new Date().toISOString()}] Reconnection attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts} in ${delay}ms`);
|
|
309674
|
-
setTimeout(
|
|
309675
|
-
|
|
309676
|
-
|
|
309677
|
-
|
|
309678
|
-
catch (error) {
|
|
309828
|
+
setTimeout(() => {
|
|
309829
|
+
this.initVendor()
|
|
309830
|
+
.then((v) => this.listenOnEvents(v))
|
|
309831
|
+
.catch((error) => {
|
|
309679
309832
|
this.logger.log(`[${new Date().toISOString()}] Reconnection failed:`, error);
|
|
309680
|
-
|
|
309833
|
+
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
309834
|
+
this.delayedReconnect();
|
|
309835
|
+
}
|
|
309836
|
+
});
|
|
309681
309837
|
}, delay);
|
|
309682
309838
|
}
|
|
309683
309839
|
}
|
package/dist/sherpa.d.ts
CHANGED
|
@@ -11,6 +11,10 @@ declare class SherpaProvider extends ProviderClass<WASocket> {
|
|
|
11
11
|
private reconnectAttempts;
|
|
12
12
|
private maxReconnectAttempts;
|
|
13
13
|
private reconnectDelay;
|
|
14
|
+
private healthCheckInterval?;
|
|
15
|
+
private presenceInterval?;
|
|
16
|
+
private periodicCleanupInterval?;
|
|
17
|
+
private badSessionCount;
|
|
14
18
|
msgRetryCounterCache?: NodeCache;
|
|
15
19
|
userDevicesCache?: NodeCache;
|
|
16
20
|
private logger;
|
|
@@ -50,6 +54,12 @@ declare class SherpaProvider extends ProviderClass<WASocket> {
|
|
|
50
54
|
flush(): Promise<void>;
|
|
51
55
|
processInBuffer(task: Promise<any>): any;
|
|
52
56
|
}>;
|
|
57
|
+
/**
|
|
58
|
+
* Extrae el número de teléfono (from) de un mensaje
|
|
59
|
+
* @param messageCtx - Contexto del mensaje
|
|
60
|
+
* @returns El número de teléfono extraído
|
|
61
|
+
*/
|
|
62
|
+
private extractFromFromMessage;
|
|
53
63
|
/**
|
|
54
64
|
* Map native events that the Provider class expects
|
|
55
65
|
* to have a standard set of events
|
|
@@ -96,6 +106,11 @@ declare class SherpaProvider extends ProviderClass<WASocket> {
|
|
|
96
106
|
* @example await sendMessage('+XXXXXXXXXXX', 'https://dominio.com/imagen.jpg' | 'img/imagen.jpg')
|
|
97
107
|
*/
|
|
98
108
|
sendMedia: (number: string, imageUrl: string, text: string) => Promise<proto.WebMessageInfo>;
|
|
109
|
+
/**
|
|
110
|
+
* Returns true only when the underlying WebSocket is fully open (readyState === 1).
|
|
111
|
+
* Used as a guard before any send call to avoid silent message loss during reconnects.
|
|
112
|
+
*/
|
|
113
|
+
private isVendorReady;
|
|
99
114
|
/**
|
|
100
115
|
* Enviar imagen
|
|
101
116
|
* @param {*} number
|
|
@@ -201,6 +216,14 @@ declare class SherpaProvider extends ProviderClass<WASocket> {
|
|
|
201
216
|
saveFile: (ctx: Partial<WAMessage & BotContext>, options?: {
|
|
202
217
|
path: string;
|
|
203
218
|
}) => Promise<string>;
|
|
219
|
+
/**
|
|
220
|
+
* Starts a periodic health check that verifies the WebSocket connection is alive.
|
|
221
|
+
* If the connection is detected as dead (zombie), it triggers a reconnect.
|
|
222
|
+
* Also sends periodic presence updates as an application-level heartbeat
|
|
223
|
+
* to prevent WhatsApp from considering the connection inactive.
|
|
224
|
+
*/
|
|
225
|
+
private startHealthCheck;
|
|
226
|
+
private stopHealthCheck;
|
|
204
227
|
private shouldReconnect;
|
|
205
228
|
private delayedReconnect;
|
|
206
229
|
}
|
package/dist/sherpa.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sherpa.d.ts","sourceRoot":"","sources":["../src/sherpa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAS,MAAM,iBAAiB,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAGjF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,IAAI,CAAA;AAI9C,OAAO,SAAS,MAAM,YAAY,CAAA;AAIlC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAK3D,OAAO,EAGH,eAAe,EACf,SAAS,EACT,QAAQ,EASR,KAAK,EAER,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,QAAQ,CAAA;AASpD,cAAM,cAAe,SAAQ,aAAa,CAAC,QAAQ,CAAC;IACzC,gBAAgB,EAAE,sBAAsB,CAgB9C;IAED,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,cAAc,CAAO;
|
|
1
|
+
{"version":3,"file":"sherpa.d.ts","sourceRoot":"","sources":["../src/sherpa.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,gBAAgB,GAAU,UAAU,MAAM,qBAM1C,CAAA;AACN;;;;;GAKG;AACH,QAAA,MAAM,iBAAiB,GAAI,QAAQ,MAAM,EAAE,OAAM,OAAe,KAAG,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,gBAAgB,GAAU,UAAU,MAAM,qBAM1C,CAAA;AACN;;;;;GAKG;AACH,QAAA,MAAM,iBAAiB,GAAI,QAAQ,MAAM,EAAE,OAAM,OAAe,KAAG,MAWlE,CAAA;AAED;;;;GAIG;AACH,QAAA,MAAM,mBAAmB,GAAU,QAAQ,MAAM,EAAE,OAAM,MAAiB,KAAG,OAAO,CAAC,IAAI,CAaxF,CAAA;AAED;;;;GAIG;AACH,QAAA,MAAM,mBAAmB,GAAI,WAAW,MAAM,KAAG,OAKhD,CAAA;AAGD,QAAA,MAAM,iBAAiB,WA9CY,MAAM,SAAQ,OAAO,KAAW,MA8CxB,CAAA;AAC3C,QAAA,MAAM,mBAAmB,WA7BkB,MAAM,SAAQ,MAAM,KAAc,OAAO,CAAC,IAAI,CA6B1C,CAAA;AAC/C,QAAA,MAAM,mBAAmB,cAVe,MAAM,KAAG,OAUF,CAAA;AAE/C,OAAO,EACH,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,GACtB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@builderbot/provider-sherpa",
|
|
3
|
-
"version": "1.3.15-alpha.
|
|
3
|
+
"version": "1.3.15-alpha.18",
|
|
4
4
|
"description": "Provider Sherpa for BuilderBot - WhatsApp integration using Whaileys",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"author": "Leifer Mendez <leifer33@gmail.com>",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"homepage": "https://github.com/codigoencasa/bot-whatsapp#readme",
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@builderbot/bot": "1.3.15-alpha.
|
|
41
|
+
"@builderbot/bot": "^1.3.15-alpha.18",
|
|
42
42
|
"@hapi/boom": "^10.0.1",
|
|
43
43
|
"@jest/globals": "^30.2.0",
|
|
44
44
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
@@ -80,5 +80,5 @@
|
|
|
80
80
|
"typescript": "^5.9.3",
|
|
81
81
|
"whaileys": "6.3.8"
|
|
82
82
|
},
|
|
83
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "b9d6c39d13049d0a2249609417a82dd1f4c20ccf"
|
|
84
84
|
}
|