@realvare/based 2.7.4 → 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
@@ -815,7 +815,19 @@ const makeMessagesRecvSocket = (config) => {
815
815
  await Promise.all([
816
816
  processingMutex.mutex(async () => {
817
817
  var _a, _b, _c, _d, _e, _f;
818
- 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
+
819
831
  // message failed to decrypt
820
832
  if (msg.messageStubType === WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT) {
821
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) {
@@ -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
  };
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.4",
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": "npm:@newfadel/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
+ }