@builderbot/provider-sherpa 1.3.15-alpha.9 → 1.4.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/dist/index.cjs CHANGED
@@ -4275,6 +4275,8 @@ const baileyCleanNumber = (number, full = false) => {
4275
4275
  const exist = number.match(regexGroup);
4276
4276
  if (exist)
4277
4277
  return number;
4278
+ if (number.includes('@lid'))
4279
+ return number;
4278
4280
  number = number.replace('@s.whatsapp.net', '').replace('+', '').replace(/\s/g, '');
4279
4281
  number = !full ? `${number}@s.whatsapp.net` : number;
4280
4282
  return number;
@@ -308805,8 +308807,9 @@ class SherpaProvider extends bot.ProviderClass {
308805
308807
  fallBackAction: undefined,
308806
308808
  };
308807
308809
  this.reconnectAttempts = 0;
308808
- this.maxReconnectAttempts = 10;
308810
+ this.maxReconnectAttempts = 50;
308809
308811
  this.reconnectDelay = 1000; // 1 segundo inicial
308812
+ this.badSessionCount = 0;
308810
308813
  this.idsDuplicates = [];
308811
308814
  this.mapSet = new Set();
308812
308815
  this.indexHome = (req, res) => {
@@ -308858,9 +308861,37 @@ class SherpaProvider extends bot.ProviderClass {
308858
308861
  this.initVendor().then((v) => this.listenOnEvents(v));
308859
308862
  }
308860
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];
308861
308892
  const sock = makeWASocketOther({
308862
308893
  logger: loggerSherpa,
308863
- version: [2, 3000, 1023223821],
308894
+ version: waVersion,
308864
308895
  printQRInTerminal: false,
308865
308896
  auth: {
308866
308897
  creds: state.creds,
@@ -308873,9 +308904,9 @@ class SherpaProvider extends bot.ProviderClass {
308873
308904
  getMessage: this.getMessage,
308874
308905
  msgRetryCounterMap: {},
308875
308906
  userDevicesCache: this.userDevicesCache,
308876
- retryRequestDelayMs: 1000, // Mayor delay entre reintentos
308907
+ retryRequestDelayMs: 2000, // Delay entre reintentos (2s para evitar rate-limit)
308877
308908
  connectTimeoutMs: 60_000, // 1 minuto timeout conexión
308878
- keepAliveIntervalMs: 10_000, // Keep alive cada 10 segundos
308909
+ keepAliveIntervalMs: 15_000, // Keep alive cada 15 segundos (recomendado por comunidad)
308879
308910
  qrTimeout: 40_000, // 40 segundos para QR
308880
308911
  defaultQueryTimeoutMs: 60_000, // 1 minuto para queries
308881
308912
  emitOwnEvents: false, // No emitir eventos propios
@@ -308919,6 +308950,7 @@ class SherpaProvider extends bot.ProviderClass {
308919
308950
  const reason = lastDisconnect?.error?.message;
308920
308951
  /** Connection closed for various reasons */
308921
308952
  if (connection === 'close') {
308953
+ this.stopHealthCheck();
308922
308954
  this.logger.log(`[${new Date().toISOString()}] Connection closed. Status: ${statusCode}, Reason: ${reason}`);
308923
308955
  // Check if device was removed
308924
308956
  const errorData = lastDisconnect?.error?.data;
@@ -308935,6 +308967,7 @@ class SherpaProvider extends bot.ProviderClass {
308935
308967
  `You can also check a log that has been created sherpa.log`,
308936
308968
  `Need help: https://link.codigoencasa.com/DISCORD`,
308937
308969
  ]);
308970
+ return;
308938
308971
  }
308939
308972
  // Casos donde NO debemos reconectar
308940
308973
  if (statusCode === libExports.DisconnectReason.loggedOut) {
@@ -308945,11 +308978,30 @@ class SherpaProvider extends bot.ProviderClass {
308945
308978
  await this.delayedReconnect();
308946
308979
  return;
308947
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
+ }
308948
308994
  // Casos donde debemos reconectar con backoff
308949
308995
  if (this.shouldReconnect(statusCode)) {
308950
308996
  await this.delayedReconnect();
308951
308997
  return;
308952
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
+ }
308953
309005
  // Casos críticos - emitir error
308954
309006
  this.logger.log(`[${new Date().toISOString()}] Critical error, stopping reconnection attempts`);
308955
309007
  this.emit('auth_failure', [
@@ -308964,6 +309016,8 @@ class SherpaProvider extends bot.ProviderClass {
308964
309016
  this.logger.log(`[${new Date().toISOString()}] Connection opened successfully`);
308965
309017
  this.reconnectAttempts = 0; // Reset counter on successful connection
308966
309018
  this.reconnectDelay = 1000; // Reset delay
309019
+ this.badSessionCount = 0; // Reset bad session counter
309020
+ this.startHealthCheck();
308967
309021
  const parseNumber = `${sock?.user?.id}`.split(':').shift();
308968
309022
  const host = { ...sock?.user, phone: parseNumber };
308969
309023
  this.globalVendorArgs.host = host;
@@ -309325,6 +309379,8 @@ class SherpaProvider extends bot.ProviderClass {
309325
309379
  * @returns
309326
309380
  */
309327
309381
  this.sendImage = async (number, filePath, text) => {
309382
+ if (!this.isVendorReady())
309383
+ throw new Error('Provider not connected. Cannot send image.');
309328
309384
  const payload = {
309329
309385
  image: { url: filePath },
309330
309386
  caption: text,
@@ -309339,6 +309395,8 @@ class SherpaProvider extends bot.ProviderClass {
309339
309395
  * @returns
309340
309396
  */
309341
309397
  this.sendVideo = async (number, filePath, text) => {
309398
+ if (!this.isVendorReady())
309399
+ throw new Error('Provider not connected. Cannot send video.');
309342
309400
  const payload = {
309343
309401
  video: require$$0$7.readFileSync(filePath),
309344
309402
  caption: text,
@@ -309355,6 +309413,8 @@ class SherpaProvider extends bot.ProviderClass {
309355
309413
  * @example await sendMessage('+XXXXXXXXXXX', 'audio.mp3')
309356
309414
  */
309357
309415
  this.sendAudio = async (number, audioUrl) => {
309416
+ if (!this.isVendorReady())
309417
+ throw new Error('Provider not connected. Cannot send audio.');
309358
309418
  const payload = {
309359
309419
  audio: { url: audioUrl },
309360
309420
  ptt: true,
@@ -309368,6 +309428,8 @@ class SherpaProvider extends bot.ProviderClass {
309368
309428
  * @returns
309369
309429
  */
309370
309430
  this.sendText = async (number, message) => {
309431
+ if (!this.isVendorReady())
309432
+ throw new Error('Provider not connected. Cannot send text.');
309371
309433
  const payload = { text: message };
309372
309434
  return this.vendor.sendMessage(number, payload);
309373
309435
  };
@@ -309378,6 +309440,8 @@ class SherpaProvider extends bot.ProviderClass {
309378
309440
  * @example await sendMessage('+XXXXXXXXXXX', './document/file.pdf')
309379
309441
  */
309380
309442
  this.sendFile = async (number, filePath, text) => {
309443
+ if (!this.isVendorReady())
309444
+ throw new Error('Provider not connected. Cannot send file.');
309381
309445
  const mimeType = mime.lookup(filePath);
309382
309446
  const fileName = require$$1.basename(filePath);
309383
309447
  const payload = {
@@ -309398,6 +309462,8 @@ class SherpaProvider extends bot.ProviderClass {
309398
309462
  * @example await sendMessage("+XXXXXXXXXXX", "Your Text", "Your Footer", [{"buttonId": "id", "buttonText": {"displayText": "Button"}, "type": 1}])
309399
309463
  */
309400
309464
  this.sendButtons = async (number, text, buttons) => {
309465
+ if (!this.isVendorReady())
309466
+ throw new Error('Provider not connected. Cannot send buttons.');
309401
309467
  this.emit('notice', {
309402
309468
  title: 'DEPRECATED',
309403
309469
  instructions: [
@@ -309597,7 +309663,7 @@ class SherpaProvider extends bot.ProviderClass {
309597
309663
  }
309598
309664
  setupPeriodicCleanup() {
309599
309665
  // Limpiar duplicados cada 10 minutos para evitar memory leaks
309600
- setInterval(() => {
309666
+ this.periodicCleanupInterval = setInterval(() => {
309601
309667
  const maxSize = 1000;
309602
309668
  if (this.idsDuplicates.length > maxSize) {
309603
309669
  this.logger.log(`[${new Date().toISOString()}] Cleaning duplicates array: ${this.idsDuplicates.length} -> ${maxSize}`);
@@ -309612,6 +309678,11 @@ class SherpaProvider extends bot.ProviderClass {
309612
309678
  }
309613
309679
  cleanup() {
309614
309680
  try {
309681
+ this.stopHealthCheck();
309682
+ if (this.periodicCleanupInterval) {
309683
+ clearInterval(this.periodicCleanupInterval);
309684
+ this.periodicCleanupInterval = undefined;
309685
+ }
309615
309686
  if (this.msgRetryCounterCache) {
309616
309687
  this.msgRetryCounterCache.close();
309617
309688
  this.msgRetryCounterCache = undefined;
@@ -309657,6 +309728,74 @@ class SherpaProvider extends bot.ProviderClass {
309657
309728
  const fromParse = remoteJid?.includes('@lid') ? remoteJidAlt || remoteJid?.split('@')[0] : remoteJid;
309658
309729
  return fromParse;
309659
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
+ }
309660
309799
  shouldReconnect(statusCode) {
309661
309800
  // Lista de códigos donde SÍ debemos reconectar
309662
309801
  const reconnectableCodes = [
@@ -309688,13 +309827,15 @@ class SherpaProvider extends bot.ProviderClass {
309688
309827
  this.reconnectAttempts++;
309689
309828
  const delay = Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1), 30000); // Max 30 segundos
309690
309829
  this.logger.log(`[${new Date().toISOString()}] Reconnection attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts} in ${delay}ms`);
309691
- setTimeout(async () => {
309692
- try {
309693
- this.initVendor().then((v) => this.listenOnEvents(v));
309694
- }
309695
- catch (error) {
309830
+ setTimeout(() => {
309831
+ this.initVendor()
309832
+ .then((v) => this.listenOnEvents(v))
309833
+ .catch((error) => {
309696
309834
  this.logger.log(`[${new Date().toISOString()}] Reconnection failed:`, error);
309697
- }
309835
+ if (this.reconnectAttempts < this.maxReconnectAttempts) {
309836
+ this.delayedReconnect();
309837
+ }
309838
+ });
309698
309839
  }, delay);
309699
309840
  }
309700
309841
  }
package/dist/index.mjs CHANGED
@@ -4273,6 +4273,8 @@ const baileyCleanNumber = (number, full = false) => {
4273
4273
  const exist = number.match(regexGroup);
4274
4274
  if (exist)
4275
4275
  return number;
4276
+ if (number.includes('@lid'))
4277
+ return number;
4276
4278
  number = number.replace('@s.whatsapp.net', '').replace('+', '').replace(/\s/g, '');
4277
4279
  number = !full ? `${number}@s.whatsapp.net` : number;
4278
4280
  return number;
@@ -308803,8 +308805,9 @@ class SherpaProvider extends ProviderClass {
308803
308805
  fallBackAction: undefined,
308804
308806
  };
308805
308807
  this.reconnectAttempts = 0;
308806
- this.maxReconnectAttempts = 10;
308808
+ this.maxReconnectAttempts = 50;
308807
308809
  this.reconnectDelay = 1000; // 1 segundo inicial
308810
+ this.badSessionCount = 0;
308808
308811
  this.idsDuplicates = [];
308809
308812
  this.mapSet = new Set();
308810
308813
  this.indexHome = (req, res) => {
@@ -308856,9 +308859,37 @@ class SherpaProvider extends ProviderClass {
308856
308859
  this.initVendor().then((v) => this.listenOnEvents(v));
308857
308860
  }
308858
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];
308859
308890
  const sock = makeWASocketOther({
308860
308891
  logger: loggerSherpa,
308861
- version: [2, 3000, 1023223821],
308892
+ version: waVersion,
308862
308893
  printQRInTerminal: false,
308863
308894
  auth: {
308864
308895
  creds: state.creds,
@@ -308871,9 +308902,9 @@ class SherpaProvider extends ProviderClass {
308871
308902
  getMessage: this.getMessage,
308872
308903
  msgRetryCounterMap: {},
308873
308904
  userDevicesCache: this.userDevicesCache,
308874
- retryRequestDelayMs: 1000, // Mayor delay entre reintentos
308905
+ retryRequestDelayMs: 2000, // Delay entre reintentos (2s para evitar rate-limit)
308875
308906
  connectTimeoutMs: 60_000, // 1 minuto timeout conexión
308876
- keepAliveIntervalMs: 10_000, // Keep alive cada 10 segundos
308907
+ keepAliveIntervalMs: 15_000, // Keep alive cada 15 segundos (recomendado por comunidad)
308877
308908
  qrTimeout: 40_000, // 40 segundos para QR
308878
308909
  defaultQueryTimeoutMs: 60_000, // 1 minuto para queries
308879
308910
  emitOwnEvents: false, // No emitir eventos propios
@@ -308917,6 +308948,7 @@ class SherpaProvider extends ProviderClass {
308917
308948
  const reason = lastDisconnect?.error?.message;
308918
308949
  /** Connection closed for various reasons */
308919
308950
  if (connection === 'close') {
308951
+ this.stopHealthCheck();
308920
308952
  this.logger.log(`[${new Date().toISOString()}] Connection closed. Status: ${statusCode}, Reason: ${reason}`);
308921
308953
  // Check if device was removed
308922
308954
  const errorData = lastDisconnect?.error?.data;
@@ -308933,6 +308965,7 @@ class SherpaProvider extends ProviderClass {
308933
308965
  `You can also check a log that has been created sherpa.log`,
308934
308966
  `Need help: https://link.codigoencasa.com/DISCORD`,
308935
308967
  ]);
308968
+ return;
308936
308969
  }
308937
308970
  // Casos donde NO debemos reconectar
308938
308971
  if (statusCode === libExports.DisconnectReason.loggedOut) {
@@ -308943,11 +308976,30 @@ class SherpaProvider extends ProviderClass {
308943
308976
  await this.delayedReconnect();
308944
308977
  return;
308945
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
+ }
308946
308992
  // Casos donde debemos reconectar con backoff
308947
308993
  if (this.shouldReconnect(statusCode)) {
308948
308994
  await this.delayedReconnect();
308949
308995
  return;
308950
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
+ }
308951
309003
  // Casos críticos - emitir error
308952
309004
  this.logger.log(`[${new Date().toISOString()}] Critical error, stopping reconnection attempts`);
308953
309005
  this.emit('auth_failure', [
@@ -308962,6 +309014,8 @@ class SherpaProvider extends ProviderClass {
308962
309014
  this.logger.log(`[${new Date().toISOString()}] Connection opened successfully`);
308963
309015
  this.reconnectAttempts = 0; // Reset counter on successful connection
308964
309016
  this.reconnectDelay = 1000; // Reset delay
309017
+ this.badSessionCount = 0; // Reset bad session counter
309018
+ this.startHealthCheck();
308965
309019
  const parseNumber = `${sock?.user?.id}`.split(':').shift();
308966
309020
  const host = { ...sock?.user, phone: parseNumber };
308967
309021
  this.globalVendorArgs.host = host;
@@ -309323,6 +309377,8 @@ class SherpaProvider extends ProviderClass {
309323
309377
  * @returns
309324
309378
  */
309325
309379
  this.sendImage = async (number, filePath, text) => {
309380
+ if (!this.isVendorReady())
309381
+ throw new Error('Provider not connected. Cannot send image.');
309326
309382
  const payload = {
309327
309383
  image: { url: filePath },
309328
309384
  caption: text,
@@ -309337,6 +309393,8 @@ class SherpaProvider extends ProviderClass {
309337
309393
  * @returns
309338
309394
  */
309339
309395
  this.sendVideo = async (number, filePath, text) => {
309396
+ if (!this.isVendorReady())
309397
+ throw new Error('Provider not connected. Cannot send video.');
309340
309398
  const payload = {
309341
309399
  video: readFileSync(filePath),
309342
309400
  caption: text,
@@ -309353,6 +309411,8 @@ class SherpaProvider extends ProviderClass {
309353
309411
  * @example await sendMessage('+XXXXXXXXXXX', 'audio.mp3')
309354
309412
  */
309355
309413
  this.sendAudio = async (number, audioUrl) => {
309414
+ if (!this.isVendorReady())
309415
+ throw new Error('Provider not connected. Cannot send audio.');
309356
309416
  const payload = {
309357
309417
  audio: { url: audioUrl },
309358
309418
  ptt: true,
@@ -309366,6 +309426,8 @@ class SherpaProvider extends ProviderClass {
309366
309426
  * @returns
309367
309427
  */
309368
309428
  this.sendText = async (number, message) => {
309429
+ if (!this.isVendorReady())
309430
+ throw new Error('Provider not connected. Cannot send text.');
309369
309431
  const payload = { text: message };
309370
309432
  return this.vendor.sendMessage(number, payload);
309371
309433
  };
@@ -309376,6 +309438,8 @@ class SherpaProvider extends ProviderClass {
309376
309438
  * @example await sendMessage('+XXXXXXXXXXX', './document/file.pdf')
309377
309439
  */
309378
309440
  this.sendFile = async (number, filePath, text) => {
309441
+ if (!this.isVendorReady())
309442
+ throw new Error('Provider not connected. Cannot send file.');
309379
309443
  const mimeType = mime.lookup(filePath);
309380
309444
  const fileName = basename(filePath);
309381
309445
  const payload = {
@@ -309396,6 +309460,8 @@ class SherpaProvider extends ProviderClass {
309396
309460
  * @example await sendMessage("+XXXXXXXXXXX", "Your Text", "Your Footer", [{"buttonId": "id", "buttonText": {"displayText": "Button"}, "type": 1}])
309397
309461
  */
309398
309462
  this.sendButtons = async (number, text, buttons) => {
309463
+ if (!this.isVendorReady())
309464
+ throw new Error('Provider not connected. Cannot send buttons.');
309399
309465
  this.emit('notice', {
309400
309466
  title: 'DEPRECATED',
309401
309467
  instructions: [
@@ -309595,7 +309661,7 @@ class SherpaProvider extends ProviderClass {
309595
309661
  }
309596
309662
  setupPeriodicCleanup() {
309597
309663
  // Limpiar duplicados cada 10 minutos para evitar memory leaks
309598
- setInterval(() => {
309664
+ this.periodicCleanupInterval = setInterval(() => {
309599
309665
  const maxSize = 1000;
309600
309666
  if (this.idsDuplicates.length > maxSize) {
309601
309667
  this.logger.log(`[${new Date().toISOString()}] Cleaning duplicates array: ${this.idsDuplicates.length} -> ${maxSize}`);
@@ -309610,6 +309676,11 @@ class SherpaProvider extends ProviderClass {
309610
309676
  }
309611
309677
  cleanup() {
309612
309678
  try {
309679
+ this.stopHealthCheck();
309680
+ if (this.periodicCleanupInterval) {
309681
+ clearInterval(this.periodicCleanupInterval);
309682
+ this.periodicCleanupInterval = undefined;
309683
+ }
309613
309684
  if (this.msgRetryCounterCache) {
309614
309685
  this.msgRetryCounterCache.close();
309615
309686
  this.msgRetryCounterCache = undefined;
@@ -309655,6 +309726,74 @@ class SherpaProvider extends ProviderClass {
309655
309726
  const fromParse = remoteJid?.includes('@lid') ? remoteJidAlt || remoteJid?.split('@')[0] : remoteJid;
309656
309727
  return fromParse;
309657
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
+ }
309658
309797
  shouldReconnect(statusCode) {
309659
309798
  // Lista de códigos donde SÍ debemos reconectar
309660
309799
  const reconnectableCodes = [
@@ -309686,13 +309825,15 @@ class SherpaProvider extends ProviderClass {
309686
309825
  this.reconnectAttempts++;
309687
309826
  const delay = Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1), 30000); // Max 30 segundos
309688
309827
  this.logger.log(`[${new Date().toISOString()}] Reconnection attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts} in ${delay}ms`);
309689
- setTimeout(async () => {
309690
- try {
309691
- this.initVendor().then((v) => this.listenOnEvents(v));
309692
- }
309693
- catch (error) {
309828
+ setTimeout(() => {
309829
+ this.initVendor()
309830
+ .then((v) => this.listenOnEvents(v))
309831
+ .catch((error) => {
309694
309832
  this.logger.log(`[${new Date().toISOString()}] Reconnection failed:`, error);
309695
- }
309833
+ if (this.reconnectAttempts < this.maxReconnectAttempts) {
309834
+ this.delayedReconnect();
309835
+ }
309836
+ });
309696
309837
  }, delay);
309697
309838
  }
309698
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;
@@ -102,6 +106,11 @@ declare class SherpaProvider extends ProviderClass<WASocket> {
102
106
  * @example await sendMessage('+XXXXXXXXXXX', 'https://dominio.com/imagen.jpg' | 'img/imagen.jpg')
103
107
  */
104
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;
105
114
  /**
106
115
  * Enviar imagen
107
116
  * @param {*} number
@@ -207,6 +216,14 @@ declare class SherpaProvider extends ProviderClass<WASocket> {
207
216
  saveFile: (ctx: Partial<WAMessage & BotContext>, options?: {
208
217
  path: string;
209
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;
210
227
  private shouldReconnect;
211
228
  private delayedReconnect;
212
229
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sherpa.d.ts","sourceRoot":"","sources":["../src/sherpa.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sherpa.d.ts","sourceRoot":"","sources":["../src/sherpa.ts"],"names":[],"mappings":"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"}
@@ -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,MAUlE,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,WA7CY,MAAM,SAAQ,OAAO,KAAW,MA6CxB,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"}
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.9",
3
+ "version": "1.4.0",
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.9",
41
+ "@builderbot/bot": "^1.4.0",
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": "fc5c6e392fd67ac26c8ac532447b495f11f142a7"
83
+ "gitHead": "219d5d17d93a0b98656659f9c31355e8fb07318c"
84
84
  }