@realvare/based 2.7.3 → 2.7.5

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.
@@ -18,7 +18,7 @@ exports.WA_DEFAULT_EPHEMERAL = 7 * 24 * 60 * 60;
18
18
  exports.NOISE_MODE = 'Noise_XX_25519_AESGCM_SHA256\0\0\0\0';
19
19
  exports.DICT_VERSION = 3;
20
20
  exports.KEY_BUNDLE_TYPE = Buffer.from([5]);
21
- exports.NOISE_WA_HEADER = Buffer.from([87, 65, 6, exports.DICT_VERSION]); // last is "DICT_VERSION"
21
+ exports.NOISE_WA_HEADER = Buffer.from([87, 65, 6, exports.DICT_VERSION]); // last isambasedd "DICT_VERSION"
22
22
  /** from: https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url */
23
23
  exports.URL_REGEX = /https:\/\/(?![^:@\/\s]+:[^:@\/\s]+@)[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(:\d+)?(\/[^\s]*)?/g;
24
24
  exports.WA_CERT_DETAILS = {
@@ -53,13 +53,13 @@ exports.DEFAULT_CONNECTION_CONFIG = {
53
53
  shouldIgnoreJid: () => false,
54
54
  linkPreviewImageThumbnailWidth: 192,
55
55
  transactionOpts: { maxCommitRetries: 10, delayBetweenTriesMs: 3000 },
56
- generateHighQualityLinkPreview: false,
56
+ generateHighQualityLinkPreview: true,
57
57
  options: {},
58
58
  appStateMacVerification: {
59
59
  patch: false,
60
60
  snapshot: false,
61
61
  },
62
- countryCode: 'US',
62
+ countryCode: 'IT',
63
63
  getMessage: async () => undefined,
64
64
  cachedGroupMetadata: async () => undefined,
65
65
  makeSignalRepository: libsignal_1.makeLibSignalRepository
@@ -320,8 +320,8 @@ const extractGroupMetadata = (result) => {
320
320
  participants: (0, WABinary_1.getBinaryNodeChildren)(group, 'participant').map(({ attrs }) => {
321
321
  return {
322
322
  id: attrs.jid,
323
- jid: attrs.phone_number || attrs.jid,
324
- lid: attrs.lid || attrs.jid,
323
+ jid: attrs.phone_number || (0, WABinary_1.lidToJid)(attrs.jid),
324
+ lid: attrs.lid || ((0, WABinary_1.isLid)(attrs.jid) ? attrs.jid : undefined),
325
325
  admin: (attrs.type || null),
326
326
  };
327
327
  }),
@@ -35,6 +35,12 @@ const makeMessagesRecvSocket = (config) => {
35
35
  useClones: false
36
36
  });
37
37
  let sendActiveReceipts = false;
38
+ const resolveJid = (jid) => {
39
+ if (typeof jid === 'string' && jid.endsWith('@lid')) {
40
+ return (0, WABinary_1.lidToJid)(jid);
41
+ }
42
+ return jid;
43
+ };
38
44
  const sendMessageAck = async ({ tag, attrs, content }, errorCode) => {
39
45
  const stanza = {
40
46
  tag: 'ack',
@@ -354,22 +360,28 @@ const makeMessagesRecvSocket = (config) => {
354
360
  default:
355
361
  // console.log("BAILEYS-DEBUG:", JSON.stringify({ ...child, content: Buffer.isBuffer(child.content) ? child.content.toString() : child.content, participant }, null, 2))
356
362
  }
357
- // Resolve LIDs to real JIDs for all messageStubParameters
358
- if (msg.messageStubParameters) {
359
- const metadata = await groupMetadata(groupJid);
360
- msg.messageStubParameters = await Promise.all(msg.messageStubParameters.map(async (param) => {
361
- if (typeof param === 'string' && param.endsWith('@lid')) {
362
- const found = metadata.participants.find(p => p.id === param);
363
- return found?.jid || (0, WABinary_1.lidToJid)(param);
364
- }
365
- return param;
366
- }));
367
- }
368
- // Also resolve key.participant if needed
369
- if (msg.key?.participant && msg.key.participant.endsWith('@lid')) {
363
+ const needsResolving = (msg.messageStubParameters && msg.messageStubParameters.some(p => typeof p === 'string' && (0, WABinary_1.isLid)(p))) ||
364
+ (participant && (0, WABinary_1.isLid)(participant)) ||
365
+ (msg.key?.participant && (0, WABinary_1.isLid)(msg.key.participant));
366
+ if(needsResolving) {
370
367
  const metadata = await groupMetadata(groupJid);
371
- const found = metadata.participants.find(p => p.id === msg.key.participant);
372
- msg.key.participant = found?.jid || (0, WABinary_1.lidToJid)(msg.key.participant);
368
+ if (msg.messageStubParameters) {
369
+ msg.messageStubParameters = await Promise.all(msg.messageStubParameters.map(async (param) => {
370
+ if (typeof param === 'string' && (0, WABinary_1.isLid)(param)) {
371
+ const found = metadata.participants.find(p => p.id === param);
372
+ return found?.jid || (0, WABinary_1.lidToJid)(param);
373
+ }
374
+ return param;
375
+ }));
376
+ }
377
+ if(participant && (0, WABinary_1.isLid)(participant)) {
378
+ const found = metadata.participants.find(p => p.id === participant);
379
+ msg.participant = found?.jid || (0, WABinary_1.lidToJid)(participant);
380
+ }
381
+ if (msg.key?.participant && (0, WABinary_1.isLid)(msg.key.participant)) {
382
+ const found = metadata.participants.find(p => p.id === msg.key.participant);
383
+ msg.key.participant = found?.jid || (0, WABinary_1.lidToJid)(msg.key.participant);
384
+ }
373
385
  }
374
386
  };
375
387
  const handleNewsletterNotification = (id, node) => {
@@ -421,12 +433,12 @@ const makeMessagesRecvSocket = (config) => {
421
433
  const result = {};
422
434
  const [child] = (0, WABinary_1.getAllBinaryNodeChildren)(node);
423
435
  const nodeType = node.attrs.type;
424
- const from = (0, WABinary_1.jidNormalizedUser)(node.attrs.from);
436
+ const from = resolveJid((0, WABinary_1.jidNormalizedUser)(node.attrs.from));
425
437
  switch (nodeType) {
426
438
  case 'privacy_token':
427
439
  const tokenList = (0, WABinary_1.getBinaryNodeChildren)(child, 'token');
428
440
  for (const { attrs, content } of tokenList) {
429
- const jid = attrs.jid;
441
+ const jid = resolveJid(attrs.jid);
430
442
  ev.emit('chats.update', [
431
443
  {
432
444
  id: jid,
@@ -455,7 +467,7 @@ const makeMessagesRecvSocket = (config) => {
455
467
  case 'devices':
456
468
  const devices = (0, WABinary_1.getBinaryNodeChildren)(child, 'device');
457
469
  if ((0, WABinary_1.areJidsSameUser)(child.attrs.jid, authState.creds.me.id)) {
458
- const deviceJids = devices.map(d => d.attrs.jid);
470
+ const deviceJids = devices.map(d => resolveJid(d.attrs.jid));
459
471
  logger.info({ deviceJids }, 'got my own devices');
460
472
  }
461
473
  break;
@@ -470,7 +482,7 @@ const makeMessagesRecvSocket = (config) => {
470
482
  const setPicture = (0, WABinary_1.getBinaryNodeChild)(node, 'set');
471
483
  const delPicture = (0, WABinary_1.getBinaryNodeChild)(node, 'delete');
472
484
  ev.emit('contacts.update', [{
473
- id: from || ((_b = (_a = (setPicture || delPicture)) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b.hash) || '',
485
+ id: resolveJid(from) || ((_b = (_a = (setPicture || delPicture)) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b.hash) || '',
474
486
  imgUrl: setPicture ? 'changed' : 'removed'
475
487
  }]);
476
488
  if ((0, WABinary_1.isJidGroup)(from)) {
@@ -484,6 +496,15 @@ const makeMessagesRecvSocket = (config) => {
484
496
  ...result.key || {},
485
497
  participant: setPicture === null || setPicture === void 0 ? void 0 : setPicture.attrs.author
486
498
  };
499
+ const metadata = await groupMetadata(from);
500
+ if (result.participant && result.participant.endsWith('@lid')) {
501
+ const found = metadata.participants.find(p => p.id === result.participant);
502
+ result.participant = found?.jid || (0, WABinary_1.lidToJid)(result.participant);
503
+ }
504
+ if (result.key?.participant && result.key.participant.endsWith('@lid')) {
505
+ const found = metadata.participants.find(p => p.id === result.key.participant);
506
+ result.key.participant = found?.jid || (0, WABinary_1.lidToJid)(result.key.participant);
507
+ }
487
508
  }
488
509
  break;
489
510
  case 'account_sync':
@@ -504,7 +525,7 @@ const makeMessagesRecvSocket = (config) => {
504
525
  else if (child.tag === 'blocklist') {
505
526
  const blocklists = (0, WABinary_1.getBinaryNodeChildren)(child, 'item');
506
527
  for (const { attrs } of blocklists) {
507
- const blocklist = [attrs.jid];
528
+ const blocklist = [resolveJid(attrs.jid)];
508
529
  const type = (attrs.action === 'block') ? 'add' : 'remove';
509
530
  ev.emit('blocklist.update', { blocklist, type });
510
531
  }
@@ -635,14 +656,14 @@ const makeMessagesRecvSocket = (config) => {
635
656
  var _a, _b;
636
657
  const { attrs, content } = node;
637
658
  const isLid = attrs.from.includes('lid');
638
- const isNodeFromMe = (0, WABinary_1.areJidsSameUser)(attrs.participant || attrs.from, isLid ? (_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.lid : (_b = authState.creds.me) === null || _b === void 0 ? void 0 : _b.id);
639
- const remoteJid = !isNodeFromMe || (0, WABinary_1.isJidGroup)(attrs.from) ? attrs.from : attrs.recipient;
659
+ const isNodeFromMe = (0, WABinary_1.areJidsSameUser)(resolveJid(attrs.participant) || resolveJid(attrs.from), isLid ? (_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.lid : (_b = authState.creds.me) === null || _b === void 0 ? void 0 : _b.id);
660
+ const remoteJid = !isNodeFromMe || (0, WABinary_1.isJidGroup)(attrs.from) ? resolveJid(attrs.from) : attrs.recipient;
640
661
  const fromMe = !attrs.recipient || ((attrs.type === 'retry' || attrs.type === 'sender') && isNodeFromMe);
641
662
  const key = {
642
663
  remoteJid,
643
664
  id: '',
644
665
  fromMe,
645
- participant: attrs.participant
666
+ participant: resolveJid(attrs.participant)
646
667
  };
647
668
  if (shouldIgnoreJid(remoteJid) && remoteJid !== '@s.whatsapp.net') {
648
669
  logger.debug({ remoteJid }, 'ignoring receipt from jid');
@@ -670,7 +691,7 @@ const makeMessagesRecvSocket = (config) => {
670
691
  ev.emit('message-receipt.update', ids.map(id => ({
671
692
  key: { ...key, id },
672
693
  receipt: {
673
- userJid: (0, WABinary_1.jidNormalizedUser)(attrs.participant),
694
+ userJid: (0, WABinary_1.jidNormalizedUser)(resolveJid(attrs.participant)),
674
695
  [updateKey]: +attrs.t
675
696
  }
676
697
  })));
@@ -725,7 +746,7 @@ const makeMessagesRecvSocket = (config) => {
725
746
  }
726
747
  };
727
748
  const handleNotification = async (node) => {
728
- const remoteJid = node.attrs.from;
749
+ const remoteJid = resolveJid(node.attrs.from);
729
750
  if (shouldIgnoreJid(remoteJid) && remoteJid !== '@s.whatsapp.net') {
730
751
  logger.debug({ remoteJid, id: node.attrs.id }, 'ignored notification');
731
752
  await sendMessageAck(node);
@@ -737,15 +758,15 @@ const makeMessagesRecvSocket = (config) => {
737
758
  var _a;
738
759
  const msg = await processNotification(node);
739
760
  if (msg) {
740
- const fromMe = (0, WABinary_1.areJidsSameUser)(node.attrs.participant || remoteJid, authState.creds.me.id);
741
- msg.key = {
742
- remoteJid,
743
- fromMe,
744
- participant: node.attrs.participant,
745
- id: node.attrs.id,
746
- ...(msg.key || {})
747
- };
748
- (_a = msg.participant) !== null && _a !== void 0 ? _a : (msg.participant = node.attrs.participant);
761
+ const participant = msg.participant || resolveJid(node.attrs.participant);
762
+ const fromMe = (0, WABinary_1.areJidsSameUser)(participant || remoteJid, authState.creds.me.id);
763
+ const key = msg.key || {};
764
+ key.remoteJid = remoteJid;
765
+ key.fromMe = fromMe;
766
+ key.id = node.attrs.id;
767
+ key.participant = key.participant || participant;
768
+ msg.key = key;
769
+ msg.participant = participant;
749
770
  msg.messageTimestamp = +node.attrs.t;
750
771
  const fullMsg = WAProto_1.proto.WebMessageInfo.fromObject(msg);
751
772
  await upsertMessage(fullMsg, 'append');
@@ -794,7 +815,19 @@ const makeMessagesRecvSocket = (config) => {
794
815
  await Promise.all([
795
816
  processingMutex.mutex(async () => {
796
817
  var _a, _b, _c, _d, _e, _f;
797
- await decrypt();
818
+ try {
819
+ await decrypt();
820
+ } catch (error) {
821
+ if(error.message.includes('Bad MAC') || error.message.includes('No matching sessions')) {
822
+ logger.warn({ key: msg.key, jid: author, error: error.message }, 'Decryption failed, clearing session to recover');
823
+ const { SessionRecord } = require('../Signal');
824
+ await signalRepository.storeSession(author, new SessionRecord());
825
+ return sendMessageAck(node, Utils_1.NACK_REASONS.ParsingError);
826
+ }
827
+
828
+ throw error;
829
+ }
830
+
798
831
  // message failed to decrypt
799
832
  if (msg.messageStubType === WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT) {
800
833
  if (((_a = msg === null || msg === void 0 ? void 0 : msg.messageStubParameters) === null || _a === void 0 ? void 0 : _a[0]) === Utils_1.MISSING_KEYS_ERROR_TEXT) {
@@ -916,10 +949,10 @@ const makeMessagesRecvSocket = (config) => {
916
949
  const { attrs } = node;
917
950
  const [infoChild] = (0, WABinary_1.getAllBinaryNodeChildren)(node);
918
951
  const callId = infoChild.attrs['call-id'];
919
- const from = infoChild.attrs.from || infoChild.attrs['call-creator'];
952
+ const from = resolveJid(infoChild.attrs.from || infoChild.attrs['call-creator']);
920
953
  const status = (0, Utils_1.getCallStatusFromNode)(infoChild);
921
954
  const call = {
922
- chatId: attrs.from,
955
+ chatId: resolveJid(attrs.from),
923
956
  from,
924
957
  id: callId,
925
958
  date: new Date(+attrs.t * 1000),
@@ -929,7 +962,7 @@ const makeMessagesRecvSocket = (config) => {
929
962
  if (status === 'offer') {
930
963
  call.isVideo = !!(0, WABinary_1.getBinaryNodeChild)(infoChild, 'video');
931
964
  call.isGroup = infoChild.attrs.type === 'group' || !!infoChild.attrs['group-jid'];
932
- call.groupJid = infoChild.attrs['group-jid'];
965
+ call.groupJid = resolveJid(infoChild.attrs['group-jid']);
933
966
  callOfferCache.set(call.id, call);
934
967
  }
935
968
  const existingCall = callOfferCache.get(call.id);
@@ -1055,7 +1088,6 @@ const makeMessagesRecvSocket = (config) => {
1055
1088
  .catch(error => onUnexpectedError(error, 'handling bad ack'));
1056
1089
  });
1057
1090
  ev.on('call', ([call]) => {
1058
- // missed call + group call notification message generation
1059
1091
  if (call.status === 'timeout' || (call.status === 'offer' && call.isGroup)) {
1060
1092
  const msg = {
1061
1093
  key: {
@@ -1093,20 +1125,17 @@ const makeMessagesRecvSocket = (config) => {
1093
1125
  } else if (connection === 'open') {
1094
1126
  sendActiveReceipts = true;
1095
1127
  }
1096
- // Update sendActiveReceipts based on connection status
1097
1128
  if (typeof update.isOnline !== 'undefined') {
1098
1129
  sendActiveReceipts = update.isOnline;
1099
1130
  logger.trace(`sendActiveReceipts set to "${sendActiveReceipts}"`);
1100
1131
  }
1101
1132
  });
1102
- // Enhanced retry logic for stuck pending messages with anti-ban delays
1103
1133
  ev.on('messages.update', (updates) => {
1104
1134
  const config = (0, performance_config_1.getPerformanceConfig)();
1105
1135
  updates.forEach(update => {
1106
1136
  if (update.update.status === WAProto_1.proto.WebMessageInfo.Status.PENDING &&
1107
- Date.now() - (update.update.timestamp || 0) > 30000) { // 30 seconds
1137
+ Date.now() - (update.update.timestamp || 0) > 30000) {
1108
1138
  logger.debug({ key: update.key }, 'retrying stuck pending message with anti-ban delay');
1109
- // Apply anti-ban delay before retry
1110
1139
  setTimeout(async () => {
1111
1140
  try {
1112
1141
  const msg = await getMessage(update.key);
@@ -26,7 +26,11 @@ const makeMessagesSocket = (config) => {
26
26
  });
27
27
 
28
28
  // Initialize rate limiter for anti-ban protection
29
- const rateLimiter = new rate_limiter_1.default(1); // 1 message per second default
29
+ const messagesSendRate = config.messagesSendRate || 1;
30
+ if(messagesSendRate > 5) {
31
+ logger.warn(`messagesSendRate is set to a high value (${messagesSendRate}), this may increase the risk of getting banned. Recommended value is <= 3`);
32
+ }
33
+ const rateLimiter = new rate_limiter_1.default(messagesSendRate);
30
34
  let mediaConn;
31
35
  const refreshMediaConn = async (forceGet = false) => {
32
36
  const media = await mediaConn;
@@ -857,6 +861,7 @@ const makeMessagesSocket = (config) => {
857
861
  throw new boom_1.Boom('Sticker data not found for sticker: ' + JSON.stringify(sticker), { statusCode: 400 });
858
862
  }
859
863
  const stickerContent = { sticker: stickerData };
864
+ let mediaHandle;
860
865
  const stickerMsg = await (0, Utils_1.generateWAMessage)(jid, stickerContent, {
861
866
  logger,
862
867
  userJid,
@@ -1041,11 +1046,9 @@ const makeMessagesSocket = (config) => {
1041
1046
  return message;
1042
1047
  },
1043
1048
  sendMessage: async (jid, content, options = {}) => {
1044
- var _a, _b, _c;
1045
- const userJid = authState.creds.me.id;
1046
-
1049
+ var _a;
1047
1050
  // Handle admin-only messages by sending private messages to each admin
1048
- if (content.contextInfo?.isAdminOnly && (0, WABinary_1.isJidGroup)(jid)) {
1051
+ if (((_a = content.contextInfo) === null || _a === void 0 ? void 0 : _a.isAdminOnly) && (0, WABinary_1.isJidGroup)(jid)) {
1049
1052
  try {
1050
1053
  // Get group metadata to find admins
1051
1054
  const metadata = await sock.groupMetadata(jid);
@@ -1091,319 +1094,7 @@ const makeMessagesSocket = (config) => {
1091
1094
  throw error;
1092
1095
  }
1093
1096
  }
1094
-
1095
- if (!options.ephemeralExpiration) {
1096
- if ((0, WABinary_1.isJidGroup)(jid)) {
1097
- const groups = await sock.groupQuery(jid, 'get', [{
1098
- tag: 'query',
1099
- attrs: {
1100
- request: 'interactive'
1101
- }
1102
- }]);
1103
- const metadata = (0, WABinary_1.getBinaryNodeChild)(groups, 'group');
1104
- const expiration = ((_b = (_a = (0, WABinary_1.getBinaryNodeChild)(metadata, 'ephemeral')) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b.expiration) || 0;
1105
- options.ephemeralExpiration = expiration;
1106
- }
1107
- }
1108
- if (typeof content === 'object' &&
1109
- 'disappearingMessagesInChat' in content &&
1110
- typeof content['disappearingMessagesInChat'] !== 'undefined' &&
1111
- (0, WABinary_1.isJidGroup)(jid)) {
1112
- const { disappearingMessagesInChat } = content;
1113
- const value = typeof disappearingMessagesInChat === 'boolean' ?
1114
- (disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
1115
- disappearingMessagesInChat;
1116
- await groupToggleEphemeral(jid, value);
1117
- }
1118
- if (typeof content === 'object' && 'album' in content && content.album) {
1119
- const { album, caption } = content;
1120
- if (caption && !album[0].caption) {
1121
- album[0].caption = caption;
1122
- }
1123
- let mediaHandle;
1124
- let mediaMsg;
1125
- const albumMsg = (0, Utils_1.generateWAMessageFromContent)(jid, {
1126
- albumMessage: {
1127
- expectedImageCount: album.filter(item => 'image' in item).length,
1128
- expectedVideoCount: album.filter(item => 'video' in item).length
1129
- }
1130
- }, { userJid, ...options });
1131
- await relayMessage(jid, albumMsg.message, {
1132
- messageId: albumMsg.key.id
1133
- });
1134
- for (const i in album) {
1135
- const media = album[i];
1136
- if ('image' in media) {
1137
- mediaMsg = await (0, Utils_1.generateWAMessage)(jid, {
1138
- image: media.image,
1139
- ...(media.caption ? { caption: media.caption } : {}),
1140
- ...options
1141
- }, {
1142
- userJid,
1143
- upload: async (readStream, opts) => {
1144
- const up = await waUploadToServer(readStream, { ...opts, newsletter: (0, WABinary_1.isJidNewsletter)(jid) });
1145
- mediaHandle = up.handle;
1146
- return up;
1147
- },
1148
- ...options,
1149
- });
1150
- }
1151
- else if ('video' in media) {
1152
- mediaMsg = await (0, Utils_1.generateWAMessage)(jid, {
1153
- video: media.video,
1154
- ...(media.caption ? { caption: media.caption } : {}),
1155
- ...(media.gifPlayback !== undefined ? { gifPlayback: media.gifPlayback } : {}),
1156
- ...options
1157
- }, {
1158
- userJid,
1159
- upload: async (readStream, opts) => {
1160
- const up = await waUploadToServer(readStream, { ...opts, newsletter: (0, WABinary_1.isJidNewsletter)(jid) });
1161
- mediaHandle = up.handle;
1162
- return up;
1163
- },
1164
- ...options,
1165
- });
1166
- }
1167
- else if ('url' in media) {
1168
- // Assume URL is an image if not specified
1169
- mediaMsg = await (0, Utils_1.generateWAMessage)(jid, {
1170
- image: media.url,
1171
- ...(media.caption ? { caption: media.caption } : {}),
1172
- ...options
1173
- }, {
1174
- userJid,
1175
- upload: async (readStream, opts) => {
1176
- const up = await waUploadToServer(readStream, { ...opts, newsletter: (0, WABinary_1.isJidNewsletter)(jid) });
1177
- mediaHandle = up.handle;
1178
- return up;
1179
- },
1180
- ...options,
1181
- });
1182
- }
1183
- if (mediaMsg) {
1184
- mediaMsg.message.messageContextInfo = {
1185
- messageSecret: (0, crypto_1.randomBytes)(32),
1186
- messageAssociation: {
1187
- associationType: 1,
1188
- parentMessageKey: albumMsg.key
1189
- }
1190
- };
1191
- await relayMessage(jid, mediaMsg.message, {
1192
- messageId: mediaMsg.key.id
1193
- });
1194
- await new Promise(resolve => setTimeout(resolve, 800));
1195
- }
1196
- }
1197
- return albumMsg;
1198
- }
1199
- else if (typeof content === 'object' && 'stickerPack' in content && content.stickerPack) {
1200
- // Send sticker pack metadata first, then each sticker associated with it
1201
- const { stickerPack } = content;
1202
- const stickers = stickerPack.stickers || [];
1203
- if (!Array.isArray(stickers) || stickers.length === 0) {
1204
- throw new boom_1.Boom('stickerPack requires at least one sticker', { statusCode: 400 });
1205
- }
1206
-
1207
- // Prepare cover thumbnail if provided
1208
- let thumbnailDirectPath;
1209
- let thumbnailEncSha256;
1210
- let thumbnailSha256;
1211
- let thumbnailHeight;
1212
- let thumbnailWidth;
1213
- if (stickerPack.cover) {
1214
- try {
1215
- const thumbMsg = await (0, Utils_1.prepareWAMessageMedia)({ image: stickerPack.cover }, {
1216
- logger,
1217
- userJid,
1218
- upload: async (readStream, opts) => {
1219
- const up = await waUploadToServer(readStream, { ...opts, newsletter: (0, WABinary_1.isJidNewsletter)(jid) });
1220
- return up;
1221
- },
1222
- mediaCache: config.mediaCache,
1223
- options: config.options,
1224
- messageId: (0, Utils_1.generateMessageIDV2)((_c = sock.user) === null || _c === void 0 ? void 0 : _c.id),
1225
- ...options,
1226
- });
1227
- if (thumbMsg.imageMessage) {
1228
- thumbnailDirectPath = thumbMsg.imageMessage.directPath;
1229
- thumbnailEncSha256 = thumbMsg.imageMessage.fileEncSha256;
1230
- thumbnailSha256 = thumbMsg.imageMessage.fileSha256;
1231
- thumbnailHeight = thumbMsg.imageMessage.height;
1232
- thumbnailWidth = thumbMsg.imageMessage.width;
1233
- }
1234
- }
1235
- catch (err) {
1236
- logger === null || logger === void 0 ? void 0 : logger.warn({ err }, 'failed to prepare stickerPack cover');
1237
- }
1238
- }
1239
-
1240
- // Map stickers metadata to proto-friendly shape
1241
- const protoStickers = stickers.map((s, idx) => ({
1242
- fileName: s.fileName || `sticker_${idx}.webp`,
1243
- isAnimated: !!s.isAnimated,
1244
- emojis: Array.isArray(s.emojis) ? s.emojis : (s.emojis ? [s.emojis] : []),
1245
- accessibilityLabel: s.accessibilityLabel,
1246
- isLottie: !!s.isLottie,
1247
- mimetype: s.mimetype || 'image/webp'
1248
- }));
1249
-
1250
- const stickerPackObj = {
1251
- name: stickerPack.name,
1252
- publisher: stickerPack.publisher,
1253
- packDescription: stickerPack.description,
1254
- stickers: protoStickers,
1255
- thumbnailDirectPath,
1256
- thumbnailEncSha256,
1257
- thumbnailSha256,
1258
- thumbnailHeight,
1259
- thumbnailWidth,
1260
- };
1261
-
1262
- // Create and send the pack metadata message
1263
- const contentForSend = { stickerPackMessage: WAProto_1.proto.Message.StickerPackMessage.fromObject(stickerPackObj) };
1264
- const packMsg = (0, Utils_1.generateWAMessageFromContent)(jid, contentForSend, {
1265
- userJid,
1266
- upload: waUploadToServer,
1267
- mediaCache: config.mediaCache,
1268
- options: config.options,
1269
- messageId: (0, Utils_1.generateMessageIDV2)((_c = sock.user) === null || _c === void 0 ? void 0 : _c.id),
1270
- ...options,
1271
- });
1272
- await relayMessage(jid, packMsg.message, { messageId: packMsg.key.id });
1273
-
1274
- // Send each sticker associated with the pack
1275
- let lastMsg = packMsg;
1276
- for (const sticker of stickers) {
1277
- const stickerData = sticker.sticker || sticker.data || sticker.buffer || sticker.image || sticker.url || sticker;
1278
- if (!stickerData) {
1279
- throw new boom_1.Boom('Sticker data not found for sticker: ' + JSON.stringify(sticker), { statusCode: 400 });
1280
- }
1281
- const stickerContent = { sticker: stickerData };
1282
- const stickerMsg = await (0, Utils_1.generateWAMessage)(jid, stickerContent, {
1283
- logger,
1284
- userJid,
1285
- upload: async (readStream, opts) => {
1286
- const up = await waUploadToServer(readStream, { ...opts, newsletter: (0, WABinary_1.isJidNewsletter)(jid) });
1287
- return up;
1288
- },
1289
- mediaCache: config.mediaCache,
1290
- options: config.options,
1291
- messageId: (0, Utils_1.generateMessageIDV2)((_c = sock.user) === null || _c === void 0 ? void 0 : _c.id),
1292
- ...options,
1293
- });
1294
- // Associate sticker with the pack message
1295
- stickerMsg.message.messageContextInfo = {
1296
- messageSecret: (0, crypto_1.randomBytes)(32),
1297
- messageAssociation: {
1298
- associationType: 1,
1299
- parentMessageKey: packMsg.key
1300
- }
1301
- };
1302
- await relayMessage(jid, stickerMsg.message, { messageId: stickerMsg.key.id });
1303
- lastMsg = stickerMsg;
1304
- // Add delay between stickers to avoid rate limiting
1305
- await new Promise(resolve => setTimeout(resolve, 800));
1306
- }
1307
- return lastMsg;
1308
- }
1309
- else {
1310
- let mediaHandle;
1311
- const fullMsg = await (0, Utils_1.generateWAMessage)(jid, content, {
1312
- logger,
1313
- userJid,
1314
- getUrlInfo: text => (0, link_preview_1.getUrlInfo)(text, {
1315
- thumbnailWidth: linkPreviewImageThumbnailWidth,
1316
- fetchOpts: {
1317
- timeout: 3000,
1318
- ...axiosOptions || {}
1319
- },
1320
- logger,
1321
- uploadImage: generateHighQualityLinkPreview
1322
- ? waUploadToServer
1323
- : undefined
1324
- }),
1325
- getProfilePicUrl: sock.profilePictureUrl,
1326
- upload: async (readStream, opts) => {
1327
- const up = await waUploadToServer(readStream, { ...opts, newsletter: (0, WABinary_1.isJidNewsletter)(jid) });
1328
- mediaHandle = up.handle;
1329
- return up;
1330
- },
1331
- mediaCache: config.mediaCache,
1332
- options: config.options,
1333
- messageId: (0, Utils_1.generateMessageIDV2)((_c = sock.user) === null || _c === void 0 ? void 0 : _c.id),
1334
- ...options,
1335
- });
1336
- const isDeleteMsg = 'delete' in content && !!content.delete;
1337
- const isEditMsg = 'edit' in content && !!content.edit;
1338
- const isPinMsg = 'pin' in content && !!content.pin;
1339
- const isKeepMsg = 'keep' in content && content.keep;
1340
- const isPollMessage = 'poll' in content && !!content.poll;
1341
- const isAiMsg = options.ai === true;
1342
- const additionalAttributes = {};
1343
- const additionalNodes = [];
1344
- // required for delete
1345
- if (isDeleteMsg) {
1346
- // if the chat is a group, and I am not the author, then delete the message as an admin
1347
- if (((0, WABinary_1.isJidGroup)(content.delete.remoteJid) && !content.delete.fromMe) || (0, WABinary_1.isJidNewsletter)(jid)) {
1348
- additionalAttributes.edit = '8';
1349
- }
1350
- else {
1351
- additionalAttributes.edit = '7';
1352
- }
1353
- // required for edit message
1354
- }
1355
- else if (isEditMsg) {
1356
- additionalAttributes.edit = (0, WABinary_1.isJidNewsletter)(jid) ? '3' : '1';
1357
- // required for pin message
1358
- }
1359
- else if (isPinMsg) {
1360
- additionalAttributes.edit = '2';
1361
- // required for keep message
1362
- }
1363
- else if (isKeepMsg) {
1364
- additionalAttributes.edit = '6';
1365
- // required for polling message
1366
- }
1367
- else if (isPollMessage) {
1368
- additionalNodes.push({
1369
- tag: 'meta',
1370
- attrs: {
1371
- polltype: 'creation'
1372
- },
1373
- });
1374
- // required to display AI icon on message
1375
- }
1376
- else if (isAiMsg) {
1377
- additionalNodes.push({
1378
- attrs: {
1379
- biz_bot: '1'
1380
- },
1381
- tag: "bot"
1382
- });
1383
- }
1384
- if (mediaHandle) {
1385
- additionalAttributes['media_id'] = mediaHandle;
1386
- }
1387
- if ('cachedGroupMetadata' in options) {
1388
- console.warn('cachedGroupMetadata in sendMessage are deprecated, now cachedGroupMetadata is part of the socket config.');
1389
- }
1390
- // Add AI context if needed
1391
- if (isAiMsg) {
1392
- fullMsg.message.messageContextInfo = {
1393
- ...fullMsg.message.messageContextInfo,
1394
- biz_bot: '1'
1395
- };
1396
- }
1397
-
1398
-
1399
- await rateLimiter.add(() => relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, additionalAttributes, additionalNodes: isAiMsg ? additionalNodes : options.additionalNodes, statusJidList: options.statusJidList }));
1400
- if (config.emitOwnEvents) {
1401
- process.nextTick(() => {
1402
- processingMutex.mutex(() => (upsertMessage(fullMsg, 'append')));
1403
- });
1404
- }
1405
- return fullMsg;
1406
- }
1097
+ return rateLimiter.add(() => sendMessageInternal(jid, content, options));
1407
1098
  }
1408
1099
  };
1409
1100
  };
@@ -125,4 +125,8 @@ export type SocketConfig = {
125
125
  * The number of messages to fetch at a time when interacting with newsletters
126
126
  */
127
127
  newsletterPageSize?: number;
128
+ /** Rate limit for sending messages per second. Defaults to 1. Set to a higher value for faster sending, but this may increase the risk of getting ur number banned. */
129
+ messagesSendRate?: number;
130
+ /** Adds a random delay to message sending to simulate human behavior. Defaults to true. Set to false for faster sending, but this may increase the risk of getting blocked. */
131
+ humanizeMessages?: boolean;
128
132
  };
@@ -1194,49 +1194,4 @@ const assertMediaContent = (content) => {
1194
1194
  return mediaContent;
1195
1195
  };
1196
1196
  exports.assertMediaContent = assertMediaContent;
1197
- const getNormalizedJid = (jid) => {
1198
- if (!jid) return jid;
1199
- return (0, WABinary_1.jidNormalizedUser)(jid);
1200
- };
1201
- exports.getNormalizedJid = getNormalizedJid;
1202
-
1203
- const isLidFormat = (jid) => {
1204
- return (0, WABinary_1.isLidUser)(jid);
1205
- };
1206
- exports.isLidFormat = isLidFormat;
1207
1197
 
1208
- // Legacy compatibility functions - deprecated, use native APIs
1209
- const toJid = (id) => {
1210
- console.warn('toJid is deprecated. Use getNormalizedJid instead.');
1211
- return getNormalizedJid(id);
1212
- };
1213
- exports.toJid = toJid;
1214
-
1215
- const getSenderLid = (message) => {
1216
- const sender = message?.key?.participant || message?.key?.remoteJid;
1217
- if (!sender) return null;
1218
-
1219
- const normalized = getNormalizedJid(sender);
1220
- return {
1221
- jid: sender,
1222
- lid: normalized,
1223
- isValid: true,
1224
- user: (0, WABinary_1.jidDecode)(normalized)?.user || 'unknown'
1225
- };
1226
- };
1227
- exports.getSenderLid = getSenderLid;
1228
-
1229
- const validateJid = (jid) => {
1230
- console.warn('validateJid is deprecated. Use native Baileys validation.');
1231
- if (!jid || typeof jid !== 'string') {
1232
- return { isValid: false, error: 'Invalid JID: must be a non-empty string' };
1233
- }
1234
-
1235
- try {
1236
- const decoded = (0, WABinary_1.jidDecode)(jid);
1237
- return { isValid: !!decoded };
1238
- } catch {
1239
- return { isValid: false, error: 'Invalid JID format' };
1240
- }
1241
- };
1242
- exports.validateJid = validateJid;
package/lib/WAM/encode.js CHANGED
@@ -7,7 +7,7 @@ const encodeWAM = (binaryInfo) => {
7
7
  binaryInfo.buffer = [];
8
8
  encodeWAMHeader(binaryInfo);
9
9
  encodeEvents(binaryInfo);
10
- console.log(binaryInfo.buffer);
10
+
11
11
  const totalSize = binaryInfo.buffer
12
12
  .map((a) => a.length)
13
13
  .reduce((a, b) => a + b);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@realvare/based",
3
- "version": "2.7.3",
3
+ "version": "2.7.5",
4
4
  "description": "whatsapp api by sam",
5
5
  "keywords": [
6
6
  "baileys",
@@ -12,9 +12,9 @@
12
12
  "multi-device",
13
13
  "based"
14
14
  ],
15
- "homepage": "https://github.com/realvare/based.git",
15
+ "homepage": "git+https://github.com/realvare/based.git",
16
16
  "repository": {
17
- "url": "https://github.com/realvare/based.git"
17
+ "url": "git+https://github.com/realvare/based.git"
18
18
  },
19
19
  "license": "MIT",
20
20
  "author": "realvare",
@@ -52,7 +52,7 @@
52
52
  "gradient-string": "^2.0.2",
53
53
  "jimp": "^1.6.0",
54
54
  "libphonenumber-js": "^1.12.31",
55
- "libsignal": "github:whiskeysockets/libsignal-node",
55
+ "libsignal": "github:realvare/libsignal",
56
56
  "lodash": "^4.17.21",
57
57
  "music-metadata": "^11.7.0",
58
58
  "pino": "^10.1.0",
@@ -68,7 +68,7 @@
68
68
  "@types/sharp": "^0.32.0",
69
69
  "@types/ws": "^8.5.10",
70
70
  "conventional-changelog-cli": "^2.2.2",
71
- "eslint": "^8.57.0",
71
+ "eslint": "^9.0.0",
72
72
  "jest": "^29.7.0",
73
73
  "jimp": "^1.6.0",
74
74
  "json": "^11.0.0",
@@ -79,8 +79,8 @@
79
79
  "sharp": "^0.33.5",
80
80
  "ts-jest": "^29.1.2",
81
81
  "ts-node": "^10.9.2",
82
- "typedoc": "^0.25.12",
83
- "typescript": "^5.9.3"
82
+ "typedoc": "^0.27.0",
83
+ "typescript": "^5.8.0"
84
84
  },
85
85
  "peerDependencies": {
86
86
  "audio-decode": "^2.1.3",
@@ -106,4 +106,4 @@
106
106
  "engines": {
107
107
  "node": ">=20.0.0"
108
108
  }
109
- }
109
+ }