@whanext/core 0.17.0 → 0.18.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/CHANGELOG.md +31 -0
- package/CONTRIBUTING.md +3 -3
- package/MIGRATING_TO_ZAPO.md +73 -0
- package/README.md +10 -8
- package/dist/index.d.ts +2 -1
- package/dist/index.js +733 -606
- package/dist/index.js.map +1 -1
- package/package.json +12 -3
package/dist/index.js
CHANGED
|
@@ -2297,96 +2297,36 @@ var Browser = /* @__PURE__ */ ((Browser2) => {
|
|
|
2297
2297
|
return Browser2;
|
|
2298
2298
|
})(Browser || {});
|
|
2299
2299
|
|
|
2300
|
-
// src/provider/
|
|
2300
|
+
// src/provider/zapo/zapo-provider.ts
|
|
2301
|
+
import { mkdir } from "fs/promises";
|
|
2302
|
+
import { join } from "path";
|
|
2303
|
+
import { createMediaProcessor } from "@zapo-js/media-utils";
|
|
2304
|
+
import { createSqliteStore } from "@zapo-js/store-sqlite";
|
|
2301
2305
|
import {
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
isJidGroup,
|
|
2307
|
-
makeWASocket,
|
|
2308
|
-
proto,
|
|
2309
|
-
useMultiFileAuthState
|
|
2310
|
-
} from "@whiskeysockets/baileys";
|
|
2306
|
+
WaClient,
|
|
2307
|
+
createStore,
|
|
2308
|
+
proto
|
|
2309
|
+
} from "zapo-js";
|
|
2311
2310
|
|
|
2312
|
-
// src/provider/
|
|
2313
|
-
function
|
|
2314
|
-
return {
|
|
2315
|
-
level: logger.level,
|
|
2316
|
-
child(context) {
|
|
2317
|
-
const name = typeof context.class === "string" ? context.class : "internal";
|
|
2318
|
-
return createBaileysLogger(logger.child(name));
|
|
2319
|
-
},
|
|
2320
|
-
trace(value, message) {
|
|
2321
|
-
logger.debug(resolveMessage(value, message, "Provider trace"), safeContext(value));
|
|
2322
|
-
},
|
|
2323
|
-
debug(value, message) {
|
|
2324
|
-
logger.debug(resolveMessage(value, message, "Provider debug"), safeContext(value));
|
|
2325
|
-
},
|
|
2326
|
-
info(value, message) {
|
|
2327
|
-
logger.debug(resolveMessage(value, message, "Provider info"), safeContext(value));
|
|
2328
|
-
},
|
|
2329
|
-
warn(value, message) {
|
|
2330
|
-
logger.warn(resolveMessage(value, message, "Provider warning"), safeContext(value));
|
|
2331
|
-
},
|
|
2332
|
-
error(value, message) {
|
|
2333
|
-
logger.error(resolveMessage(value, message, "Provider error"), safeContext(value));
|
|
2334
|
-
}
|
|
2335
|
-
};
|
|
2336
|
-
}
|
|
2337
|
-
function resolveMessage(value, message, fallback) {
|
|
2338
|
-
if (message) {
|
|
2339
|
-
return message;
|
|
2340
|
-
}
|
|
2341
|
-
return typeof value === "string" ? value : fallback;
|
|
2342
|
-
}
|
|
2343
|
-
function safeContext(value) {
|
|
2344
|
-
if (value instanceof Error) {
|
|
2345
|
-
return { error: value };
|
|
2346
|
-
}
|
|
2347
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2348
|
-
return {};
|
|
2349
|
-
}
|
|
2350
|
-
const source = value;
|
|
2351
|
-
const allowed = [
|
|
2352
|
-
"location",
|
|
2353
|
-
"reason",
|
|
2354
|
-
"status",
|
|
2355
|
-
"statusCode",
|
|
2356
|
-
"type"
|
|
2357
|
-
];
|
|
2358
|
-
return Object.fromEntries(
|
|
2359
|
-
allowed.filter((key) => source[key] !== void 0).map((key) => [key, source[key]])
|
|
2360
|
-
);
|
|
2361
|
-
}
|
|
2362
|
-
|
|
2363
|
-
// src/provider/baileys/normalize-message.ts
|
|
2364
|
-
import {
|
|
2365
|
-
extractMessageContent,
|
|
2366
|
-
getContentType,
|
|
2367
|
-
normalizeMessageContent
|
|
2368
|
-
} from "@whiskeysockets/baileys";
|
|
2369
|
-
function unwrapMessageContent(input) {
|
|
2311
|
+
// src/provider/zapo/normalize-message.ts
|
|
2312
|
+
function unwrapZapoMessageContent(input) {
|
|
2370
2313
|
if (!input) return void 0;
|
|
2371
|
-
const
|
|
2372
|
-
|
|
2373
|
-
if (!content) return void 0;
|
|
2374
|
-
const nested = content.ephemeralMessage?.message ?? content.viewOnceMessage?.message ?? content.viewOnceMessageV2?.message ?? content.viewOnceMessageV2Extension?.message;
|
|
2375
|
-
return nested ? unwrapMessageContent(nested) : content;
|
|
2314
|
+
const nested = input.ephemeralMessage?.message ?? input.viewOnceMessage?.message ?? input.viewOnceMessageV2?.message ?? input.deviceSentMessage?.message ?? input.documentWithCaptionMessage?.message;
|
|
2315
|
+
return nested ? unwrapZapoMessageContent(nested) : input;
|
|
2376
2316
|
}
|
|
2377
|
-
function
|
|
2317
|
+
function isZapoViewOnceContent(input) {
|
|
2378
2318
|
if (!input) return false;
|
|
2379
|
-
if (input.viewOnceMessage?.message || input.viewOnceMessageV2?.message
|
|
2319
|
+
if (input.viewOnceMessage?.message || input.viewOnceMessageV2?.message) {
|
|
2380
2320
|
return true;
|
|
2381
2321
|
}
|
|
2382
|
-
return
|
|
2322
|
+
return isZapoViewOnceContent(input.ephemeralMessage?.message);
|
|
2383
2323
|
}
|
|
2384
|
-
function
|
|
2385
|
-
const
|
|
2386
|
-
const
|
|
2324
|
+
function extractQuotedZapoMessage(input) {
|
|
2325
|
+
const event = input;
|
|
2326
|
+
const chatId = event.key.remoteJid;
|
|
2327
|
+
const content = unwrapZapoMessageContent(event.message);
|
|
2387
2328
|
if (!chatId || !content) return void 0;
|
|
2388
|
-
const
|
|
2389
|
-
const node = type ? content[type] : void 0;
|
|
2329
|
+
const node = contentNode(content);
|
|
2390
2330
|
const context = getContextInfo(node);
|
|
2391
2331
|
if (!context?.stanzaId || !context.quotedMessage) return void 0;
|
|
2392
2332
|
return {
|
|
@@ -2399,26 +2339,25 @@ function extractQuotedBaileysMessage(input) {
|
|
|
2399
2339
|
message: context.quotedMessage
|
|
2400
2340
|
};
|
|
2401
2341
|
}
|
|
2402
|
-
function
|
|
2403
|
-
const
|
|
2404
|
-
const
|
|
2405
|
-
|
|
2342
|
+
function normalizeZapoMessage(input) {
|
|
2343
|
+
const event = input;
|
|
2344
|
+
const chatId = event.key.remoteJid;
|
|
2345
|
+
const id = event.key.id;
|
|
2346
|
+
if (!chatId || !id || !event.message) {
|
|
2406
2347
|
return void 0;
|
|
2407
2348
|
}
|
|
2408
|
-
const content =
|
|
2349
|
+
const content = unwrapZapoMessageContent(event.message);
|
|
2409
2350
|
if (!content) {
|
|
2410
2351
|
return void 0;
|
|
2411
2352
|
}
|
|
2412
|
-
const type =
|
|
2413
|
-
const node = type ? content[type] : void 0;
|
|
2353
|
+
const { type, node } = contentNode(content);
|
|
2414
2354
|
const context = getContextInfo(node);
|
|
2415
|
-
const isPrivateIncoming = !chatId.endsWith("@g.us") &&
|
|
2416
|
-
const remoteJidAlt = input.key.remoteJidAlt;
|
|
2355
|
+
const isPrivateIncoming = !chatId.endsWith("@g.us") && event.key.fromMe !== true;
|
|
2417
2356
|
const senderIds = uniqueIdentities([
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
isPrivateIncoming ? remoteJidAlt : void 0,
|
|
2357
|
+
event.key.participant,
|
|
2358
|
+
event.key.participantAlt,
|
|
2359
|
+
event.key.senderUsername?.includes("@") ? event.key.senderUsername : void 0,
|
|
2360
|
+
isPrivateIncoming ? event.key.remoteJidAlt : void 0,
|
|
2422
2361
|
isPrivateIncoming ? chatId : void 0
|
|
2423
2362
|
]);
|
|
2424
2363
|
const senderJid = senderIds.find((identity) => identity.endsWith("@s.whatsapp.net") || identity.endsWith("@c.us"));
|
|
@@ -2427,10 +2366,11 @@ function normalizeBaileysMessage(input) {
|
|
|
2427
2366
|
const sender = new User({
|
|
2428
2367
|
id: senderId,
|
|
2429
2368
|
identities: senderIds.length > 0 ? senderIds : [senderId],
|
|
2430
|
-
...
|
|
2369
|
+
...event.pushName ? { name: event.pushName } : {}
|
|
2431
2370
|
});
|
|
2432
|
-
const
|
|
2433
|
-
const
|
|
2371
|
+
const mentionedIds = [...context?.mentionedJid ?? []];
|
|
2372
|
+
const mentionedUsers = mentionedIds.map((identity) => User.fromIdentities([identity]));
|
|
2373
|
+
const viewOnce = isZapoViewOnceContent(event.message);
|
|
2434
2374
|
const media = getMedia(type, node, viewOnce);
|
|
2435
2375
|
const contentKind = getContentKind(type);
|
|
2436
2376
|
const text = getText(content);
|
|
@@ -2443,10 +2383,10 @@ function normalizeBaileysMessage(input) {
|
|
|
2443
2383
|
senderId,
|
|
2444
2384
|
senderIds: senderIds.length > 0 ? senderIds : [senderId],
|
|
2445
2385
|
sender,
|
|
2446
|
-
keys:
|
|
2447
|
-
mentions:
|
|
2386
|
+
keys: normalizeZapoKey(event.key),
|
|
2387
|
+
mentions: mentionedIds,
|
|
2448
2388
|
mentionedUsers,
|
|
2449
|
-
timestamp: toDate(
|
|
2389
|
+
timestamp: toDate(event.timestampSeconds),
|
|
2450
2390
|
isGroup: chatId.endsWith("@g.us"),
|
|
2451
2391
|
isReply: quoted !== void 0,
|
|
2452
2392
|
isViewOnce: media?.viewOnce ?? false,
|
|
@@ -2464,6 +2404,45 @@ function normalizeBaileysMessage(input) {
|
|
|
2464
2404
|
if (quoted !== void 0) message.quoted = quoted;
|
|
2465
2405
|
return message;
|
|
2466
2406
|
}
|
|
2407
|
+
function normalizeZapoKey(key) {
|
|
2408
|
+
const normalized = {
|
|
2409
|
+
id: key.id ?? "",
|
|
2410
|
+
chatId: key.remoteJid ?? "",
|
|
2411
|
+
fromMe: key.fromMe ?? false
|
|
2412
|
+
};
|
|
2413
|
+
const participantId = key.participant ?? key.participantAlt;
|
|
2414
|
+
if (participantId !== null && participantId !== void 0) {
|
|
2415
|
+
normalized.participantId = participantId;
|
|
2416
|
+
}
|
|
2417
|
+
return normalized;
|
|
2418
|
+
}
|
|
2419
|
+
function contentNode(content) {
|
|
2420
|
+
const order = [
|
|
2421
|
+
"conversation",
|
|
2422
|
+
"extendedTextMessage",
|
|
2423
|
+
"imageMessage",
|
|
2424
|
+
"videoMessage",
|
|
2425
|
+
"audioMessage",
|
|
2426
|
+
"documentMessage",
|
|
2427
|
+
"stickerMessage",
|
|
2428
|
+
"locationMessage",
|
|
2429
|
+
"liveLocationMessage",
|
|
2430
|
+
"contactMessage",
|
|
2431
|
+
"contactsArrayMessage",
|
|
2432
|
+
"buttonsResponseMessage",
|
|
2433
|
+
"listResponseMessage",
|
|
2434
|
+
"templateButtonReplyMessage",
|
|
2435
|
+
"pollCreationMessage",
|
|
2436
|
+
"pollCreationMessageV2",
|
|
2437
|
+
"pollCreationMessageV3",
|
|
2438
|
+
"pollCreationMessageV5",
|
|
2439
|
+
"productMessage",
|
|
2440
|
+
"orderMessage",
|
|
2441
|
+
"interactiveResponseMessage"
|
|
2442
|
+
];
|
|
2443
|
+
const type = order.find((key) => content[key] !== null && content[key] !== void 0);
|
|
2444
|
+
return { type, node: type ? content[type] : void 0 };
|
|
2445
|
+
}
|
|
2467
2446
|
function getContentKind(type) {
|
|
2468
2447
|
switch (String(type ?? "")) {
|
|
2469
2448
|
case "conversation":
|
|
@@ -2471,6 +2450,7 @@ function getContentKind(type) {
|
|
|
2471
2450
|
case "buttonsResponseMessage":
|
|
2472
2451
|
case "listResponseMessage":
|
|
2473
2452
|
case "templateButtonReplyMessage":
|
|
2453
|
+
case "interactiveResponseMessage":
|
|
2474
2454
|
return "text";
|
|
2475
2455
|
case "imageMessage":
|
|
2476
2456
|
return "image";
|
|
@@ -2479,7 +2459,6 @@ function getContentKind(type) {
|
|
|
2479
2459
|
case "audioMessage":
|
|
2480
2460
|
return "audio";
|
|
2481
2461
|
case "documentMessage":
|
|
2482
|
-
case "documentWithCaptionMessage":
|
|
2483
2462
|
return "document";
|
|
2484
2463
|
case "stickerMessage":
|
|
2485
2464
|
return "sticker";
|
|
@@ -2492,6 +2471,7 @@ function getContentKind(type) {
|
|
|
2492
2471
|
case "pollCreationMessage":
|
|
2493
2472
|
case "pollCreationMessageV2":
|
|
2494
2473
|
case "pollCreationMessageV3":
|
|
2474
|
+
case "pollCreationMessageV5":
|
|
2495
2475
|
return "poll";
|
|
2496
2476
|
case "productMessage":
|
|
2497
2477
|
case "orderMessage":
|
|
@@ -2500,20 +2480,8 @@ function getContentKind(type) {
|
|
|
2500
2480
|
return "unknown";
|
|
2501
2481
|
}
|
|
2502
2482
|
}
|
|
2503
|
-
function normalizeKey(key) {
|
|
2504
|
-
const normalized = {
|
|
2505
|
-
id: key.id ?? "",
|
|
2506
|
-
chatId: key.remoteJid ?? "",
|
|
2507
|
-
fromMe: key.fromMe ?? false
|
|
2508
|
-
};
|
|
2509
|
-
const participantId = key.participant ?? key.participantAlt;
|
|
2510
|
-
if (participantId !== null && participantId !== void 0) {
|
|
2511
|
-
normalized.participantId = participantId;
|
|
2512
|
-
}
|
|
2513
|
-
return normalized;
|
|
2514
|
-
}
|
|
2515
2483
|
function getText(content) {
|
|
2516
|
-
return content.conversation ?? content.extendedTextMessage?.text ?? content.buttonsResponseMessage?.selectedDisplayText ?? content.listResponseMessage?.title ?? void 0;
|
|
2484
|
+
return content.conversation ?? content.extendedTextMessage?.text ?? content.buttonsResponseMessage?.selectedDisplayText ?? content.listResponseMessage?.title ?? content.templateButtonReplyMessage?.selectedDisplayText ?? void 0;
|
|
2517
2485
|
}
|
|
2518
2486
|
function getCaption(content) {
|
|
2519
2487
|
return content.imageMessage?.caption ?? content.videoMessage?.caption ?? content.documentMessage?.caption ?? void 0;
|
|
@@ -2522,9 +2490,9 @@ function getContextInfo(node) {
|
|
|
2522
2490
|
if (typeof node !== "object" || node === null || !("contextInfo" in node)) {
|
|
2523
2491
|
return void 0;
|
|
2524
2492
|
}
|
|
2525
|
-
return node.contextInfo;
|
|
2493
|
+
return node.contextInfo ?? void 0;
|
|
2526
2494
|
}
|
|
2527
|
-
function getMedia(type, node,
|
|
2495
|
+
function getMedia(type, node, wrapperViewOnce) {
|
|
2528
2496
|
const mapping = {
|
|
2529
2497
|
imageMessage: "image",
|
|
2530
2498
|
videoMessage: "video",
|
|
@@ -2539,134 +2507,112 @@ function getMedia(type, node, keyViewOnce) {
|
|
|
2539
2507
|
const value = node;
|
|
2540
2508
|
const media = {
|
|
2541
2509
|
kind,
|
|
2542
|
-
viewOnce:
|
|
2510
|
+
viewOnce: wrapperViewOnce || value.viewOnce === true
|
|
2543
2511
|
};
|
|
2544
2512
|
if (value.mimetype) media.mimetype = value.mimetype;
|
|
2545
2513
|
if (value.fileName) media.fileName = value.fileName;
|
|
2546
|
-
|
|
2514
|
+
const seconds = toNumber(value.seconds);
|
|
2515
|
+
if (seconds !== void 0) media.seconds = seconds;
|
|
2547
2516
|
return media;
|
|
2548
2517
|
}
|
|
2549
2518
|
function getQuoted(context, chatId) {
|
|
2550
|
-
if (!context?.stanzaId)
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
const
|
|
2554
|
-
const
|
|
2555
|
-
const
|
|
2556
|
-
const
|
|
2557
|
-
const node = type && content ? content[type] : void 0;
|
|
2558
|
-
const media = getMedia(type, node, quotedIsViewOnce);
|
|
2559
|
-
const result = {
|
|
2519
|
+
if (!context?.stanzaId || !context.quotedMessage) return void 0;
|
|
2520
|
+
const content = unwrapZapoMessageContent(context.quotedMessage);
|
|
2521
|
+
if (!content) return void 0;
|
|
2522
|
+
const { type, node } = contentNode(content);
|
|
2523
|
+
const media = getMedia(type, node, isZapoViewOnceContent(context.quotedMessage));
|
|
2524
|
+
const senderId = context.participant ?? void 0;
|
|
2525
|
+
const quoted = {
|
|
2560
2526
|
key: {
|
|
2561
2527
|
id: context.stanzaId,
|
|
2562
2528
|
chatId: context.remoteJid ?? chatId,
|
|
2563
|
-
fromMe: false
|
|
2529
|
+
fromMe: false,
|
|
2530
|
+
...senderId ? { participantId: senderId } : {}
|
|
2564
2531
|
},
|
|
2565
2532
|
hasMedia: media !== void 0,
|
|
2566
|
-
isViewOnce: media?.viewOnce ??
|
|
2533
|
+
isViewOnce: media?.viewOnce ?? false,
|
|
2534
|
+
contentKind: getContentKind(type)
|
|
2567
2535
|
};
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
}
|
|
2574
|
-
if (
|
|
2575
|
-
|
|
2576
|
-
result.sender = User.fromIdentities([context.participant]);
|
|
2577
|
-
result.key.participantId = context.participant;
|
|
2578
|
-
}
|
|
2579
|
-
if (content) {
|
|
2580
|
-
const text = getText(content) ?? getCaption(content);
|
|
2581
|
-
if (text !== void 0) result.text = text;
|
|
2582
|
-
}
|
|
2583
|
-
return result;
|
|
2536
|
+
const text = getText(content) ?? getCaption(content);
|
|
2537
|
+
if (text !== void 0) quoted.text = text;
|
|
2538
|
+
if (senderId !== void 0) {
|
|
2539
|
+
quoted.senderId = senderId;
|
|
2540
|
+
quoted.sender = User.fromIdentities([senderId]);
|
|
2541
|
+
}
|
|
2542
|
+
if (media !== void 0) quoted.media = media;
|
|
2543
|
+
return quoted;
|
|
2584
2544
|
}
|
|
2585
2545
|
function toDate(value) {
|
|
2586
|
-
const seconds = value
|
|
2546
|
+
const seconds = toNumber(value) ?? Math.floor(Date.now() / 1e3);
|
|
2587
2547
|
return new Date(seconds * 1e3);
|
|
2588
2548
|
}
|
|
2549
|
+
function toNumber(value) {
|
|
2550
|
+
if (typeof value === "number") return value;
|
|
2551
|
+
if (value?.toNumber) return value.toNumber();
|
|
2552
|
+
if (typeof value?.low === "number") return value.low;
|
|
2553
|
+
return void 0;
|
|
2554
|
+
}
|
|
2589
2555
|
|
|
2590
|
-
// src/provider/
|
|
2591
|
-
var
|
|
2556
|
+
// src/provider/zapo/zapo-provider.ts
|
|
2557
|
+
var ZapoProvider = class {
|
|
2592
2558
|
#options;
|
|
2593
2559
|
#events = new TypedEventEmitter();
|
|
2594
2560
|
#logger;
|
|
2595
2561
|
#messageStore = /* @__PURE__ */ new Map();
|
|
2596
2562
|
#messageCacheSize;
|
|
2597
|
-
#
|
|
2598
|
-
#
|
|
2599
|
-
#groupMetadataGenerations = /* @__PURE__ */ new Map();
|
|
2600
|
-
#groupMetadataCacheEnabled;
|
|
2601
|
-
#groupMetadataCacheTtlMs;
|
|
2602
|
-
#groupMetadataCacheSize;
|
|
2603
|
-
#socket;
|
|
2604
|
-
#saveCredentials;
|
|
2605
|
-
#saveQueue = Promise.resolve();
|
|
2563
|
+
#client;
|
|
2564
|
+
#voip;
|
|
2606
2565
|
#intentionalClose = false;
|
|
2607
2566
|
#reconnectAttempt = 0;
|
|
2608
2567
|
#reconnectTimer;
|
|
2609
|
-
#
|
|
2568
|
+
#connectPromise;
|
|
2569
|
+
#pairingRequired = false;
|
|
2570
|
+
#connected = false;
|
|
2571
|
+
#connectedAtSeconds = 0;
|
|
2572
|
+
#pairingReady = Promise.resolve();
|
|
2573
|
+
#resolvePairingReady;
|
|
2610
2574
|
constructor(options) {
|
|
2611
2575
|
this.#options = options;
|
|
2612
2576
|
this.#logger = options.logger ?? new Logger("silent");
|
|
2613
2577
|
this.#messageCacheSize = Math.max(1, options.messageCacheSize ?? 1e3);
|
|
2614
|
-
this.#groupMetadataCacheEnabled = options.groupMetadataCache?.enabled !== false;
|
|
2615
|
-
this.#groupMetadataCacheTtlMs = Math.max(1, options.groupMetadataCache?.ttlMs ?? 3e5);
|
|
2616
|
-
this.#groupMetadataCacheSize = Math.max(1, options.groupMetadataCache?.maxEntries ?? 1e3);
|
|
2617
2578
|
}
|
|
2618
2579
|
on(event, listener) {
|
|
2619
2580
|
return this.#events.on(event, listener);
|
|
2620
2581
|
}
|
|
2621
2582
|
async connect() {
|
|
2622
|
-
|
|
2583
|
+
this.#intentionalClose = false;
|
|
2584
|
+
const client = await this.#ensureClient();
|
|
2585
|
+
if (this.#connected || this.#connectPromise) {
|
|
2623
2586
|
return;
|
|
2624
2587
|
}
|
|
2625
|
-
this.#
|
|
2588
|
+
this.#preparePairingGate();
|
|
2626
2589
|
await this.#events.emit("connection", {
|
|
2627
2590
|
state: this.#reconnectAttempt > 0 ? "reconnecting" : "connecting",
|
|
2628
2591
|
attempt: this.#reconnectAttempt
|
|
2629
2592
|
});
|
|
2630
|
-
|
|
2631
|
-
const { state, saveCreds } = await useMultiFileAuthState(this.#options.auth);
|
|
2632
|
-
this.#registered = state.creds.registered;
|
|
2633
|
-
this.#saveCredentials = saveCreds;
|
|
2634
|
-
const socket = makeWASocket({
|
|
2635
|
-
auth: state,
|
|
2636
|
-
browser: this.#browserDescription(),
|
|
2637
|
-
logger: createBaileysLogger(this.#logger.child("baileys")),
|
|
2638
|
-
markOnlineOnConnect: false,
|
|
2639
|
-
enableAutoSessionRecreation: true,
|
|
2640
|
-
enableRecentMessageCache: true,
|
|
2641
|
-
cachedGroupMetadata: async (jid) => this.#getGroupMetadata(jid),
|
|
2642
|
-
getMessage: async (key) => this.#messageStore.get(this.#messageStoreKey(key))?.message ?? void 0
|
|
2643
|
-
});
|
|
2644
|
-
this.#socket = socket;
|
|
2645
|
-
this.#bind(socket);
|
|
2646
|
-
} catch (error) {
|
|
2647
|
-
this.#socket = void 0;
|
|
2648
|
-
throw new WhaNextError("CONNECTION_FAILED", "Could not start the WhatsApp connection.", {
|
|
2649
|
-
cause: error,
|
|
2650
|
-
recoverable: true
|
|
2651
|
-
});
|
|
2652
|
-
}
|
|
2593
|
+
this.#startConnect(client);
|
|
2653
2594
|
}
|
|
2654
2595
|
async disconnect() {
|
|
2655
2596
|
this.#intentionalClose = true;
|
|
2656
|
-
if (this.#reconnectTimer)
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2597
|
+
if (this.#reconnectTimer) {
|
|
2598
|
+
clearTimeout(this.#reconnectTimer);
|
|
2599
|
+
this.#reconnectTimer = void 0;
|
|
2600
|
+
}
|
|
2601
|
+
const client = this.#client;
|
|
2602
|
+
this.#connectPromise = void 0;
|
|
2603
|
+
if (client) {
|
|
2604
|
+
await client.disconnect();
|
|
2605
|
+
} else {
|
|
2606
|
+
await this.#events.emit("connection", { state: "closed" });
|
|
2661
2607
|
}
|
|
2662
|
-
|
|
2608
|
+
this.#connected = false;
|
|
2663
2609
|
}
|
|
2664
2610
|
getCurrentUserIds() {
|
|
2665
|
-
const
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2611
|
+
const credentials = this.#client?.getCredentials();
|
|
2612
|
+
return uniqueIdentities([
|
|
2613
|
+
credentials?.meJid,
|
|
2614
|
+
credentials?.meLid
|
|
2615
|
+
]);
|
|
2670
2616
|
}
|
|
2671
2617
|
async requestPairingCode(phone) {
|
|
2672
2618
|
const normalized = phone.replace(/\D/g, "");
|
|
@@ -2676,34 +2622,28 @@ var BaileysProvider = class {
|
|
|
2676
2622
|
"The phone number must include its country code."
|
|
2677
2623
|
);
|
|
2678
2624
|
}
|
|
2679
|
-
|
|
2625
|
+
const client = await this.#ensureClient();
|
|
2626
|
+
if (client.getCredentials()?.meJid) {
|
|
2680
2627
|
return "";
|
|
2681
2628
|
}
|
|
2682
|
-
|
|
2629
|
+
if (!this.#connectPromise && !this.#connected) {
|
|
2630
|
+
await this.connect();
|
|
2631
|
+
}
|
|
2683
2632
|
try {
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
"The WhatsApp
|
|
2689
|
-
{
|
|
2690
|
-
recoverable: true
|
|
2691
|
-
}
|
|
2633
|
+
if (!this.#pairingRequired) {
|
|
2634
|
+
await this.#withTimeout(
|
|
2635
|
+
this.#pairingReady,
|
|
2636
|
+
6e4,
|
|
2637
|
+
"The WhatsApp pairing challenge was not received in time."
|
|
2692
2638
|
);
|
|
2693
2639
|
}
|
|
2694
|
-
return await
|
|
2640
|
+
return await client.auth.requestPairingCode(normalized);
|
|
2695
2641
|
} catch (error) {
|
|
2696
|
-
if (error instanceof WhaNextError)
|
|
2697
|
-
throw error;
|
|
2698
|
-
}
|
|
2642
|
+
if (error instanceof WhaNextError) throw error;
|
|
2699
2643
|
throw new WhaNextError(
|
|
2700
2644
|
"CONNECTION_FAILED",
|
|
2701
2645
|
"Could not request the pairing code after the authentication challenge.",
|
|
2702
|
-
{
|
|
2703
|
-
cause: error,
|
|
2704
|
-
context: { statusCode: this.#statusCode(error) },
|
|
2705
|
-
recoverable: this.#statusCode(error) === DisconnectReason.connectionClosed
|
|
2706
|
-
}
|
|
2646
|
+
{ cause: error, recoverable: true }
|
|
2707
2647
|
);
|
|
2708
2648
|
}
|
|
2709
2649
|
}
|
|
@@ -2711,18 +2651,17 @@ var BaileysProvider = class {
|
|
|
2711
2651
|
if ("buttons" in content) {
|
|
2712
2652
|
return this.#sendButtons(chatId, content, replyTo);
|
|
2713
2653
|
}
|
|
2714
|
-
const
|
|
2715
|
-
const
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
}
|
|
2720
|
-
}
|
|
2721
|
-
|
|
2722
|
-
return this.#sent(result);
|
|
2654
|
+
const client = this.#requireClient();
|
|
2655
|
+
const { value, mentions, viewOnce } = await this.#toContent(content);
|
|
2656
|
+
const result = await client.message.send(chatId, value, {
|
|
2657
|
+
...replyTo ? { quote: this.#toZapoKey(replyTo) } : {},
|
|
2658
|
+
...mentions.length > 0 ? { mentions } : {},
|
|
2659
|
+
...viewOnce !== void 0 ? { viewOnce } : {}
|
|
2660
|
+
});
|
|
2661
|
+
return this.#sent(result, chatId);
|
|
2723
2662
|
}
|
|
2724
2663
|
async repostMessage(source, chatId, options = {}) {
|
|
2725
|
-
const original = this.#
|
|
2664
|
+
const original = this.#findStoredMessage(this.#toZapoKey(source));
|
|
2726
2665
|
if (!original?.message) {
|
|
2727
2666
|
throw new WhaNextError(
|
|
2728
2667
|
"MESSAGE_NOT_FOUND",
|
|
@@ -2733,24 +2672,26 @@ var BaileysProvider = class {
|
|
|
2733
2672
|
}
|
|
2734
2673
|
);
|
|
2735
2674
|
}
|
|
2736
|
-
const
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2675
|
+
const result = await this.#requireClient().message.send(
|
|
2676
|
+
chatId,
|
|
2677
|
+
original.message,
|
|
2678
|
+
{
|
|
2679
|
+
forward: true,
|
|
2680
|
+
...options.mentions && options.mentions.length > 0 ? { mentions: this.#mentions(options.mentions) } : {}
|
|
2681
|
+
}
|
|
2682
|
+
);
|
|
2683
|
+
return this.#sent(result, chatId);
|
|
2742
2684
|
}
|
|
2743
2685
|
async reactToMessage(key, emoji) {
|
|
2744
|
-
const result = await this.#
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
}
|
|
2686
|
+
const result = await this.#requireClient().message.send(key.chatId, {
|
|
2687
|
+
type: "reaction",
|
|
2688
|
+
emoji: emoji ?? "",
|
|
2689
|
+
target: this.#toZapoKey(key)
|
|
2749
2690
|
});
|
|
2750
|
-
return this.#sent(result);
|
|
2691
|
+
return this.#sent(result, key.chatId);
|
|
2751
2692
|
}
|
|
2752
2693
|
async downloadMedia(key) {
|
|
2753
|
-
const message = this.#
|
|
2694
|
+
const message = this.#findStoredMessage(this.#toZapoKey(key));
|
|
2754
2695
|
if (!message?.message) {
|
|
2755
2696
|
throw new WhaNextError(
|
|
2756
2697
|
"MEDIA_NOT_AVAILABLE",
|
|
@@ -2758,54 +2699,75 @@ var BaileysProvider = class {
|
|
|
2758
2699
|
{ recoverable: true }
|
|
2759
2700
|
);
|
|
2760
2701
|
}
|
|
2761
|
-
const
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2702
|
+
const normalized = normalizeZapoMessage(message);
|
|
2703
|
+
if (!normalized?.media) {
|
|
2704
|
+
throw new WhaNextError(
|
|
2705
|
+
"MEDIA_NOT_AVAILABLE",
|
|
2706
|
+
"The selected message does not contain media."
|
|
2707
|
+
);
|
|
2708
|
+
}
|
|
2709
|
+
try {
|
|
2710
|
+
const bytes = await this.#requireClient().message.downloadBytes(
|
|
2711
|
+
message
|
|
2712
|
+
);
|
|
2713
|
+
return {
|
|
2714
|
+
data: Buffer.from(bytes),
|
|
2715
|
+
kind: normalized.media.kind,
|
|
2716
|
+
...normalized.media.mimetype ? { mimetype: normalized.media.mimetype } : {},
|
|
2717
|
+
...normalized.media.fileName ? { fileName: normalized.media.fileName } : {}
|
|
2718
|
+
};
|
|
2719
|
+
} catch (error) {
|
|
2720
|
+
throw new WhaNextError(
|
|
2721
|
+
"MEDIA_NOT_AVAILABLE",
|
|
2722
|
+
"WhatsApp could not download the selected media.",
|
|
2723
|
+
{ cause: error, recoverable: true }
|
|
2724
|
+
);
|
|
2768
2725
|
}
|
|
2769
|
-
return {
|
|
2770
|
-
data,
|
|
2771
|
-
kind: media.kind,
|
|
2772
|
-
...media.mimetype ? { mimetype: media.mimetype } : {},
|
|
2773
|
-
...media.fileName ? { fileName: media.fileName } : {}
|
|
2774
|
-
};
|
|
2775
2726
|
}
|
|
2776
2727
|
async editMessage(key, content) {
|
|
2777
|
-
const result = await this.#
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2728
|
+
const result = await this.#requireClient().message.send(
|
|
2729
|
+
key.chatId,
|
|
2730
|
+
content,
|
|
2731
|
+
{ editKey: this.#toZapoKey(key) }
|
|
2732
|
+
);
|
|
2733
|
+
return this.#sent(result, key.chatId);
|
|
2782
2734
|
}
|
|
2783
2735
|
async deleteMessage(key) {
|
|
2784
|
-
await this.#
|
|
2736
|
+
await this.#requireClient().message.send(key.chatId, {
|
|
2737
|
+
type: "revoke",
|
|
2738
|
+
target: this.#toZapoKey(key)
|
|
2739
|
+
});
|
|
2785
2740
|
}
|
|
2786
2741
|
async getGroup(groupId) {
|
|
2787
|
-
const metadata = await this.#
|
|
2742
|
+
const metadata = await this.#requireClient().group.queryGroupMetadata(groupId);
|
|
2743
|
+
const participants = [...metadata.participants ?? []];
|
|
2744
|
+
const addressingMode = metadata.addressingMode === "lid" || participants.some((participant) => (participant.jid ?? participant.id ?? "").endsWith("@lid")) ? "lid" : "pn";
|
|
2788
2745
|
return {
|
|
2789
|
-
id: metadata.id,
|
|
2790
|
-
subject: metadata.subject,
|
|
2746
|
+
id: metadata.jid ?? metadata.id ?? groupId,
|
|
2747
|
+
subject: metadata.subject ?? "",
|
|
2791
2748
|
access: metadata.announce ? "closed" : "open",
|
|
2792
|
-
addressingMode
|
|
2749
|
+
addressingMode,
|
|
2793
2750
|
fetchedAt: /* @__PURE__ */ new Date(),
|
|
2794
|
-
participants:
|
|
2795
|
-
id
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2751
|
+
participants: participants.map((participant) => {
|
|
2752
|
+
const id = participant.jid ?? participant.id ?? participant.lid ?? participant.phoneNumber ?? "";
|
|
2753
|
+
return {
|
|
2754
|
+
id,
|
|
2755
|
+
...participant.lid ? { lid: participant.lid } : {},
|
|
2756
|
+
...participant.phoneNumber ? { phoneNumber: participant.phoneNumber } : {},
|
|
2757
|
+
role: participant.isSuperAdmin || participant.admin === "superadmin" ? "owner" : participant.isAdmin || participant.admin === "admin" ? "admin" : "member"
|
|
2758
|
+
};
|
|
2759
|
+
})
|
|
2800
2760
|
};
|
|
2801
2761
|
}
|
|
2802
2762
|
async setGroupAccess(groupId, access) {
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2763
|
+
await this.#requireClient().group.setSetting(
|
|
2764
|
+
groupId,
|
|
2765
|
+
"announcement",
|
|
2766
|
+
access === "closed"
|
|
2767
|
+
);
|
|
2806
2768
|
}
|
|
2807
2769
|
async getGroupInviteCode(groupId) {
|
|
2808
|
-
const code = await this.#
|
|
2770
|
+
const code = await this.#requireClient().group.queryInviteCode(groupId);
|
|
2809
2771
|
if (!code) {
|
|
2810
2772
|
throw new WhaNextError(
|
|
2811
2773
|
"PROVIDER_ERROR",
|
|
@@ -2815,151 +2777,299 @@ var BaileysProvider = class {
|
|
|
2815
2777
|
return code;
|
|
2816
2778
|
}
|
|
2817
2779
|
async revokeGroupInvite(groupId) {
|
|
2818
|
-
const
|
|
2819
|
-
if (!code) {
|
|
2780
|
+
const result = await this.#requireClient().group.revokeInvite(groupId);
|
|
2781
|
+
if (!result.code) {
|
|
2820
2782
|
throw new WhaNextError(
|
|
2821
2783
|
"PROVIDER_ERROR",
|
|
2822
2784
|
"WhatsApp did not return a new group invite code."
|
|
2823
2785
|
);
|
|
2824
2786
|
}
|
|
2825
|
-
return code;
|
|
2787
|
+
return result.code;
|
|
2826
2788
|
}
|
|
2827
2789
|
async setMessagePin(groupId, key, pinned) {
|
|
2828
|
-
await this.#
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2790
|
+
await this.#requireClient().message.send(groupId, pinned ? {
|
|
2791
|
+
type: "pin",
|
|
2792
|
+
target: this.#toZapoKey(key),
|
|
2793
|
+
durationSecs: 604800
|
|
2794
|
+
} : {
|
|
2795
|
+
type: "unpin",
|
|
2796
|
+
target: this.#toZapoKey(key)
|
|
2832
2797
|
});
|
|
2833
2798
|
}
|
|
2834
2799
|
async updateParticipant(groupId, memberId, action) {
|
|
2835
|
-
const
|
|
2836
|
-
|
|
2837
|
-
const
|
|
2800
|
+
const group = this.#requireClient().group;
|
|
2801
|
+
const results = action === "remove" ? await group.removeParticipants(groupId, [memberId]) : action === "promote" ? await group.promoteParticipants(groupId, [memberId]) : await group.demoteParticipants(groupId, [memberId]);
|
|
2802
|
+
const result = results[0];
|
|
2803
|
+
const success = result?.status === "ok";
|
|
2804
|
+
const status = success ? "200" : String(result?.code ?? result?.status ?? "unknown");
|
|
2838
2805
|
return {
|
|
2839
|
-
success
|
|
2806
|
+
success,
|
|
2840
2807
|
status,
|
|
2841
2808
|
...result?.jid ? { memberId: result.jid } : {}
|
|
2842
2809
|
};
|
|
2843
2810
|
}
|
|
2844
2811
|
async setPresence(chatId, state) {
|
|
2845
|
-
const
|
|
2846
|
-
const presence =
|
|
2847
|
-
await
|
|
2812
|
+
const value = state === "typing" ? "composing" : state === "recording" ? "recording" : "paused";
|
|
2813
|
+
const presence = this.#requireClient().presence;
|
|
2814
|
+
await presence.sendChatstate(chatId, { state: value });
|
|
2848
2815
|
}
|
|
2849
|
-
async rejectCall(callId,
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2816
|
+
async rejectCall(callId, _from) {
|
|
2817
|
+
this.#requireClient();
|
|
2818
|
+
if (!this.#voip) {
|
|
2819
|
+
throw new WhaNextError(
|
|
2820
|
+
"PROVIDER_ERROR",
|
|
2821
|
+
"WhatsApp call support is unavailable because the Zapo VoIP plugin could not be loaded.",
|
|
2822
|
+
{ recoverable: true }
|
|
2823
|
+
);
|
|
2824
|
+
}
|
|
2825
|
+
await this.#voip.rejectCall(callId);
|
|
2826
|
+
}
|
|
2827
|
+
async #ensureClient() {
|
|
2828
|
+
if (this.#client) return this.#client;
|
|
2829
|
+
await mkdir(this.#options.auth, { recursive: true });
|
|
2830
|
+
const store = createStore({
|
|
2831
|
+
backends: {
|
|
2832
|
+
sqlite: createSqliteStore({
|
|
2833
|
+
path: join(this.#options.auth, "state.sqlite"),
|
|
2834
|
+
driver: "auto"
|
|
2835
|
+
})
|
|
2836
|
+
},
|
|
2837
|
+
providers: {
|
|
2838
|
+
auth: "sqlite",
|
|
2839
|
+
signal: "sqlite",
|
|
2840
|
+
preKey: "sqlite",
|
|
2841
|
+
session: "sqlite",
|
|
2842
|
+
identity: "sqlite",
|
|
2843
|
+
senderKey: "sqlite",
|
|
2844
|
+
appState: "sqlite",
|
|
2845
|
+
privacyToken: "sqlite",
|
|
2846
|
+
messages: "none",
|
|
2847
|
+
threads: "none",
|
|
2848
|
+
contacts: "none"
|
|
2849
|
+
},
|
|
2850
|
+
cacheProviders: {
|
|
2851
|
+
messageSecret: "sqlite"
|
|
2856
2852
|
}
|
|
2857
|
-
this.#saveQueue = this.#saveQueue.then(() => this.#saveCredentials?.()).then(() => void 0);
|
|
2858
2853
|
});
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2854
|
+
const plugins = [];
|
|
2855
|
+
try {
|
|
2856
|
+
const { voipPlugin } = await import("@zapo-js/voip");
|
|
2857
|
+
plugins.push(voipPlugin({ logLevel: "warn" }));
|
|
2858
|
+
} catch (error) {
|
|
2859
|
+
this.#logger.warn("Zapo VoIP support is unavailable; call events and rejection are disabled.", {
|
|
2860
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2861
|
+
});
|
|
2862
|
+
}
|
|
2863
|
+
const client = new WaClient({
|
|
2864
|
+
store,
|
|
2865
|
+
sessionId: this.#options.sessionId ?? "default",
|
|
2866
|
+
markOnlineOnConnect: false,
|
|
2867
|
+
deviceBrowser: this.#deviceBrowser(),
|
|
2868
|
+
deviceOsDisplayName: this.#deviceOsDisplayName(),
|
|
2869
|
+
history: { enabled: false },
|
|
2870
|
+
addons: {
|
|
2871
|
+
autoDecrypt: true,
|
|
2872
|
+
persistAllSecrets: true
|
|
2873
|
+
},
|
|
2874
|
+
media: { processor: createMediaProcessor() },
|
|
2875
|
+
plugins
|
|
2876
|
+
}, new WhaNextZapoLogger(this.#logger));
|
|
2877
|
+
this.#client = client;
|
|
2878
|
+
this.#voip = client.voip;
|
|
2879
|
+
this.#bind(client);
|
|
2880
|
+
return client;
|
|
2881
|
+
}
|
|
2882
|
+
#bind(client) {
|
|
2883
|
+
client.on("auth_pairing_required", () => {
|
|
2884
|
+
this.#pairingRequired = true;
|
|
2885
|
+
this.#resolvePairingReady?.();
|
|
2886
|
+
this.#resolvePairingReady = void 0;
|
|
2868
2887
|
});
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
if (!key.id || !key.remoteJid) continue;
|
|
2872
|
-
const stored = this.#messageStore.get(this.#messageStoreKey(key));
|
|
2873
|
-
if (update.message === null) {
|
|
2874
|
-
const message2 = stored ? normalizeBaileysMessage(stored) : void 0;
|
|
2875
|
-
const deletionKey = update.key;
|
|
2876
|
-
const deletedByMe = deletionKey?.fromMe === true;
|
|
2877
|
-
const deletedById = deletionKey?.participant ?? deletionKey?.participantAlt ?? (deletedByMe ? this.#socket?.user?.id : deletionKey?.remoteJid ?? void 0);
|
|
2878
|
-
void this.#events.emit("messageDeleted", {
|
|
2879
|
-
key: message2?.keys ?? normalizeKey(key),
|
|
2880
|
-
...message2 ? { message: message2 } : {},
|
|
2881
|
-
deletedByMe,
|
|
2882
|
-
...deletedById ? { deletedById } : {},
|
|
2883
|
-
deletedAt: /* @__PURE__ */ new Date()
|
|
2884
|
-
});
|
|
2885
|
-
continue;
|
|
2886
|
-
}
|
|
2887
|
-
if (!update.message?.editedMessage?.message) continue;
|
|
2888
|
-
const editedRaw = {
|
|
2889
|
-
...stored ?? {},
|
|
2890
|
-
key: {
|
|
2891
|
-
...stored?.key ?? {},
|
|
2892
|
-
...key
|
|
2893
|
-
},
|
|
2894
|
-
message: update.message,
|
|
2895
|
-
messageTimestamp: update.messageTimestamp ?? stored?.messageTimestamp ?? Math.floor(Date.now() / 1e3)
|
|
2896
|
-
};
|
|
2897
|
-
const previous = stored ? normalizeBaileysMessage(stored) : void 0;
|
|
2898
|
-
const message = normalizeBaileysMessage(editedRaw);
|
|
2899
|
-
if (!message) continue;
|
|
2900
|
-
this.#remember(editedRaw);
|
|
2901
|
-
const editedByMe = key.fromMe === true;
|
|
2902
|
-
const editedById = key.participant ?? key.participantAlt ?? (editedByMe ? this.#socket?.user?.id : key.remoteJid ?? void 0);
|
|
2903
|
-
void this.#events.emit("messageEdited", {
|
|
2904
|
-
key: message.keys,
|
|
2905
|
-
...previous ? { previous } : {},
|
|
2906
|
-
message,
|
|
2907
|
-
editedByMe,
|
|
2908
|
-
...editedById ? { editedById } : {},
|
|
2909
|
-
editedAt: message.timestamp
|
|
2910
|
-
});
|
|
2911
|
-
}
|
|
2888
|
+
client.on("auth_paired", () => {
|
|
2889
|
+
this.#pairingRequired = false;
|
|
2912
2890
|
});
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
if (group.id) {
|
|
2916
|
-
this.#invalidateGroupMetadata(group.id);
|
|
2917
|
-
void this.#events.emit("groupChanged", { groupId: group.id });
|
|
2918
|
-
}
|
|
2919
|
-
}
|
|
2891
|
+
client.on("message", (event) => {
|
|
2892
|
+
this.#handleMessage(event);
|
|
2920
2893
|
});
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2894
|
+
client.on("message_send", (event) => {
|
|
2895
|
+
if (!event.id || !event.message) return;
|
|
2896
|
+
this.#remember({
|
|
2897
|
+
key: {
|
|
2898
|
+
id: event.id,
|
|
2899
|
+
remoteJid: event.to,
|
|
2900
|
+
fromMe: true
|
|
2901
|
+
},
|
|
2902
|
+
message: event.message,
|
|
2903
|
+
timestampSeconds: Math.floor(Date.now() / 1e3)
|
|
2904
|
+
});
|
|
2927
2905
|
});
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
void this.#events.emit("call", this.#normalizeCall(call));
|
|
2931
|
-
}
|
|
2906
|
+
client.on("message_protocol", (event) => {
|
|
2907
|
+
this.#handleProtocolEvent(event);
|
|
2932
2908
|
});
|
|
2933
|
-
|
|
2934
|
-
|
|
2909
|
+
client.on("group", (event) => {
|
|
2910
|
+
this.#handleGroupEvent(event);
|
|
2911
|
+
});
|
|
2912
|
+
if (this.#voip) {
|
|
2913
|
+
const voipClient = client;
|
|
2914
|
+
voipClient.on("voip_call_incoming", (event) => {
|
|
2915
|
+
const call = this.#normalizeVoipCall(event, "offer");
|
|
2916
|
+
if (call) void this.#events.emit("call", call);
|
|
2917
|
+
});
|
|
2918
|
+
voipClient.on("voip_call_state", (event) => {
|
|
2919
|
+
if (event.stateData?.state === "ended") return;
|
|
2920
|
+
const call = this.#normalizeVoipCall(event);
|
|
2921
|
+
if (call && call.status !== "offer") void this.#events.emit("call", call);
|
|
2922
|
+
});
|
|
2923
|
+
voipClient.on("voip_call_ended", (event) => {
|
|
2924
|
+
const call = this.#normalizeVoipCall(
|
|
2925
|
+
event,
|
|
2926
|
+
this.#callEndStatus(event.stateData?.endReason)
|
|
2927
|
+
);
|
|
2928
|
+
if (call) void this.#events.emit("call", call);
|
|
2929
|
+
});
|
|
2930
|
+
}
|
|
2931
|
+
client.on("connection", (event) => {
|
|
2932
|
+
void this.#handleConnectionEvent(client, event);
|
|
2935
2933
|
});
|
|
2936
2934
|
}
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
if (
|
|
2935
|
+
#handleMessage(event) {
|
|
2936
|
+
const stored = event;
|
|
2937
|
+
if (this.#isOfflineMessage(stored)) {
|
|
2938
|
+
this.#logger.debug("Ignored message queued before the current connection.", {
|
|
2939
|
+
messageId: stored.key.id ?? void 0,
|
|
2940
|
+
chatId: stored.key.remoteJid ?? void 0,
|
|
2941
|
+
timestampSeconds: stored.timestampSeconds ?? void 0
|
|
2942
|
+
});
|
|
2943
|
+
return;
|
|
2944
|
+
}
|
|
2945
|
+
if (stored.key?.id && stored.message) this.#remember(stored);
|
|
2946
|
+
const quoted = extractQuotedZapoMessage(event);
|
|
2947
|
+
if (quoted) {
|
|
2948
|
+
const quotedStored = quoted;
|
|
2949
|
+
if (quotedStored.key?.id && quotedStored.message) this.#remember(quotedStored);
|
|
2950
|
+
}
|
|
2951
|
+
const message = normalizeZapoMessage(event);
|
|
2952
|
+
if (message) void this.#events.emit("message", message);
|
|
2953
|
+
}
|
|
2954
|
+
#handleProtocolEvent(event) {
|
|
2955
|
+
const protocol = event.protocolMessage ?? event.message?.protocolMessage;
|
|
2956
|
+
if (!protocol) return;
|
|
2957
|
+
const protocolKey = protocol.key;
|
|
2958
|
+
if (!protocolKey?.id) return;
|
|
2959
|
+
const remoteJid = protocolKey.remoteJid ?? event.key.remoteJid;
|
|
2960
|
+
const participant = protocolKey.participant ?? event.key.participant;
|
|
2961
|
+
const participantAlt = protocolKey.participantAlt ?? event.key.participantAlt;
|
|
2962
|
+
const target = {
|
|
2963
|
+
...protocolKey,
|
|
2964
|
+
...remoteJid !== void 0 ? { remoteJid } : {},
|
|
2965
|
+
...participant !== void 0 ? { participant } : {},
|
|
2966
|
+
...participantAlt !== void 0 ? { participantAlt } : {}
|
|
2967
|
+
};
|
|
2968
|
+
if (!target.remoteJid) return;
|
|
2969
|
+
const stored = this.#findStoredMessage(target);
|
|
2970
|
+
const type = protocol?.type;
|
|
2971
|
+
if (type === proto.Message.ProtocolMessage.Type.REVOKE) {
|
|
2972
|
+
const previous2 = stored ? normalizeZapoMessage(stored) : void 0;
|
|
2973
|
+
const deletedByMe = event.key.fromMe === true;
|
|
2974
|
+
const deletedById = event.key.participant ?? event.key.participantAlt ?? (deletedByMe ? this.getCurrentUserIds()[0] : event.key.remoteJid ?? void 0);
|
|
2975
|
+
void this.#events.emit("messageDeleted", {
|
|
2976
|
+
key: previous2?.keys ?? normalizeZapoKey(target),
|
|
2977
|
+
...previous2 ? { message: previous2 } : {},
|
|
2978
|
+
deletedByMe,
|
|
2979
|
+
...deletedById ? { deletedById } : {},
|
|
2980
|
+
deletedAt: /* @__PURE__ */ new Date()
|
|
2981
|
+
});
|
|
2982
|
+
return;
|
|
2983
|
+
}
|
|
2984
|
+
if (type !== proto.Message.ProtocolMessage.Type.MESSAGE_EDIT || !protocol.editedMessage) {
|
|
2985
|
+
return;
|
|
2986
|
+
}
|
|
2987
|
+
const pushName = event.pushName ?? stored?.pushName;
|
|
2988
|
+
const edited = {
|
|
2989
|
+
...stored ?? {},
|
|
2990
|
+
key: {
|
|
2991
|
+
...stored?.key ?? {},
|
|
2992
|
+
...target
|
|
2993
|
+
},
|
|
2994
|
+
message: protocol.editedMessage,
|
|
2995
|
+
timestampSeconds: toSeconds(protocol.timestampMs) ?? event.timestampSeconds ?? stored?.timestampSeconds ?? Math.floor(Date.now() / 1e3),
|
|
2996
|
+
...pushName !== void 0 ? { pushName } : {}
|
|
2997
|
+
};
|
|
2998
|
+
const message = normalizeZapoMessage(edited);
|
|
2999
|
+
if (!message) return;
|
|
3000
|
+
const previous = stored ? normalizeZapoMessage(stored) : void 0;
|
|
3001
|
+
this.#remember(edited);
|
|
3002
|
+
const editedByMe = event.key.fromMe === true;
|
|
3003
|
+
const editedById = event.key.participant ?? event.key.participantAlt ?? (editedByMe ? this.getCurrentUserIds()[0] : event.key.remoteJid ?? void 0);
|
|
3004
|
+
void this.#events.emit("messageEdited", {
|
|
3005
|
+
key: message.keys,
|
|
3006
|
+
...previous ? { previous } : {},
|
|
3007
|
+
message,
|
|
3008
|
+
editedByMe,
|
|
3009
|
+
...editedById ? { editedById } : {},
|
|
3010
|
+
editedAt: message.timestamp
|
|
3011
|
+
});
|
|
3012
|
+
}
|
|
3013
|
+
#handleGroupEvent(event) {
|
|
3014
|
+
const groupId = event.groupJid;
|
|
3015
|
+
if (!groupId) return;
|
|
3016
|
+
const action = this.#groupAction(event.action);
|
|
3017
|
+
const participantIds = this.#groupParticipantIds(event);
|
|
3018
|
+
if (action && participantIds.length > 0) {
|
|
3019
|
+
const authorId = event.authorJid;
|
|
3020
|
+
const change = {
|
|
3021
|
+
groupId,
|
|
3022
|
+
action,
|
|
3023
|
+
participantIds,
|
|
3024
|
+
...authorId ? { authorId } : {}
|
|
3025
|
+
};
|
|
3026
|
+
void this.#events.emit("groupParticipantsChanged", change);
|
|
3027
|
+
}
|
|
3028
|
+
void this.#events.emit("groupChanged", { groupId });
|
|
3029
|
+
}
|
|
3030
|
+
async #handleConnectionEvent(client, event) {
|
|
3031
|
+
if (client !== this.#client) return;
|
|
3032
|
+
if (event.status === "open") {
|
|
3033
|
+
this.#connectPromise = void 0;
|
|
3034
|
+
this.#connected = true;
|
|
3035
|
+
this.#connectedAtSeconds = Math.floor(Date.now() / 1e3);
|
|
2940
3036
|
this.#reconnectAttempt = 0;
|
|
2941
3037
|
await this.#events.emit("connection", { state: "connected" });
|
|
2942
3038
|
return;
|
|
2943
3039
|
}
|
|
2944
|
-
|
|
3040
|
+
this.#connectPromise = void 0;
|
|
3041
|
+
this.#connected = false;
|
|
3042
|
+
const error = event.reason instanceof Error ? event.reason : event.reason ? new Error(String(event.reason)) : void 0;
|
|
3043
|
+
if (this.#intentionalClose || event.isLogout) {
|
|
2945
3044
|
await this.#events.emit("connection", {
|
|
2946
|
-
state: "
|
|
2947
|
-
|
|
3045
|
+
state: "closed",
|
|
3046
|
+
...error ? { error } : {}
|
|
2948
3047
|
});
|
|
2949
3048
|
return;
|
|
2950
3049
|
}
|
|
2951
|
-
this.#socket = void 0;
|
|
2952
|
-
if (this.#intentionalClose || this.#isTerminal(error)) {
|
|
2953
|
-
await this.#events.emit("connection", { state: "closed", ...error ? { error } : {} });
|
|
2954
|
-
return;
|
|
2955
|
-
}
|
|
2956
3050
|
await this.#scheduleReconnect(error);
|
|
2957
3051
|
}
|
|
3052
|
+
#startConnect(client) {
|
|
3053
|
+
const promise = client.connect();
|
|
3054
|
+
this.#connectPromise = promise;
|
|
3055
|
+
void promise.catch(async (error) => {
|
|
3056
|
+
if (this.#connectPromise !== promise) return;
|
|
3057
|
+
this.#connectPromise = void 0;
|
|
3058
|
+
if (this.#intentionalClose) return;
|
|
3059
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
3060
|
+
this.#logger.warn("WhatsApp connection attempt failed.", { error: normalized });
|
|
3061
|
+
await this.#scheduleReconnect(normalized);
|
|
3062
|
+
});
|
|
3063
|
+
}
|
|
2958
3064
|
async #scheduleReconnect(error) {
|
|
3065
|
+
if (this.#reconnectTimer) return;
|
|
2959
3066
|
const options = this.#options.reconnect;
|
|
2960
3067
|
const maxAttempts = options?.maxAttempts ?? 10;
|
|
2961
3068
|
if (options?.enabled === false || this.#reconnectAttempt >= maxAttempts) {
|
|
2962
|
-
await this.#events.emit("connection", {
|
|
3069
|
+
await this.#events.emit("connection", {
|
|
3070
|
+
state: "closed",
|
|
3071
|
+
...error ? { error } : {}
|
|
3072
|
+
});
|
|
2963
3073
|
return;
|
|
2964
3074
|
}
|
|
2965
3075
|
this.#reconnectAttempt += 1;
|
|
@@ -2971,184 +3081,120 @@ var BaileysProvider = class {
|
|
|
2971
3081
|
const initial = options?.initialDelayMs ?? 1e3;
|
|
2972
3082
|
const maximum = options?.maxDelayMs ?? 3e4;
|
|
2973
3083
|
const delay = Math.min(maximum, initial * 2 ** (this.#reconnectAttempt - 1));
|
|
2974
|
-
this.#reconnectTimer = setTimeout(
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
);
|
|
2978
|
-
}
|
|
2979
|
-
#browserDescription() {
|
|
2980
|
-
if (this.#options.browser === "macos" /* MacOS */) return Browsers.macOS("Safari");
|
|
2981
|
-
if (this.#options.browser === "ubuntu" /* Ubuntu */) return Browsers.ubuntu("Chrome");
|
|
2982
|
-
return Browsers.windows("Brave");
|
|
2983
|
-
}
|
|
2984
|
-
#isTerminal(error) {
|
|
2985
|
-
const statusCode = this.#statusCode(error);
|
|
2986
|
-
return statusCode === DisconnectReason.loggedOut || statusCode === DisconnectReason.badSession || statusCode === DisconnectReason.connectionReplaced;
|
|
2987
|
-
}
|
|
2988
|
-
#statusCode(error) {
|
|
2989
|
-
return error?.output?.statusCode;
|
|
2990
|
-
}
|
|
2991
|
-
#requireSocket() {
|
|
2992
|
-
if (!this.#socket) {
|
|
2993
|
-
throw new WhaNextError(
|
|
2994
|
-
"CONNECTION_CLOSED",
|
|
2995
|
-
"WhatsApp is not connected.",
|
|
2996
|
-
{ recoverable: true }
|
|
2997
|
-
);
|
|
2998
|
-
}
|
|
2999
|
-
return this.#socket;
|
|
3084
|
+
this.#reconnectTimer = setTimeout(() => {
|
|
3085
|
+
this.#reconnectTimer = void 0;
|
|
3086
|
+
void this.connect();
|
|
3087
|
+
}, delay + Math.floor(Math.random() * 250));
|
|
3000
3088
|
}
|
|
3001
3089
|
async #sendButtons(chatId, content, replyTo) {
|
|
3002
|
-
const
|
|
3003
|
-
const
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
}
|
|
3010
|
-
const interactiveMessage = proto.Message.InteractiveMessage.create({
|
|
3011
|
-
...content.title !== void 0 ? {
|
|
3012
|
-
header: {
|
|
3013
|
-
title: content.title,
|
|
3014
|
-
hasMediaAttachment: false
|
|
3015
|
-
}
|
|
3016
|
-
} : {},
|
|
3017
|
-
body: { text: content.text },
|
|
3018
|
-
...content.footer !== void 0 ? { footer: { text: content.footer } } : {},
|
|
3019
|
-
...content.mentions && content.mentions.length > 0 ? {
|
|
3020
|
-
contextInfo: {
|
|
3021
|
-
mentionedJid: this.#mentions(content.mentions)
|
|
3022
|
-
}
|
|
3023
|
-
} : {},
|
|
3024
|
-
nativeFlowMessage: {
|
|
3025
|
-
buttons: content.buttons.map((button) => {
|
|
3026
|
-
if (button.type === "copy") {
|
|
3027
|
-
return {
|
|
3028
|
-
name: "cta_copy",
|
|
3029
|
-
buttonParamsJson: JSON.stringify({
|
|
3030
|
-
display_text: button.label,
|
|
3031
|
-
copy_code: button.code
|
|
3032
|
-
})
|
|
3033
|
-
};
|
|
3090
|
+
const mentions = content.mentions ? this.#mentions(content.mentions) : [];
|
|
3091
|
+
const raw = {
|
|
3092
|
+
interactiveMessage: {
|
|
3093
|
+
...content.title !== void 0 ? {
|
|
3094
|
+
header: {
|
|
3095
|
+
title: content.title,
|
|
3096
|
+
hasMediaAttachment: false
|
|
3034
3097
|
}
|
|
3035
|
-
|
|
3098
|
+
} : {},
|
|
3099
|
+
body: { text: content.text },
|
|
3100
|
+
...content.footer !== void 0 ? { footer: { text: content.footer } } : {},
|
|
3101
|
+
...mentions.length > 0 ? { contextInfo: { mentionedJid: mentions } } : {},
|
|
3102
|
+
nativeFlowMessage: {
|
|
3103
|
+
buttons: content.buttons.map((button) => button.type === "copy" ? {
|
|
3104
|
+
name: "cta_copy",
|
|
3105
|
+
buttonParamsJson: JSON.stringify({
|
|
3106
|
+
display_text: button.label,
|
|
3107
|
+
copy_code: button.code
|
|
3108
|
+
})
|
|
3109
|
+
} : {
|
|
3036
3110
|
name: "cta_url",
|
|
3037
3111
|
buttonParamsJson: JSON.stringify({
|
|
3038
3112
|
display_text: button.label,
|
|
3039
3113
|
url: button.url,
|
|
3040
3114
|
merchant_url: button.url
|
|
3041
3115
|
})
|
|
3042
|
-
}
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
messageVersion: 1
|
|
3046
|
-
}
|
|
3047
|
-
});
|
|
3048
|
-
const quoted = replyTo ? {
|
|
3049
|
-
key: this.#toWaKey(replyTo),
|
|
3050
|
-
message: { conversation: "" }
|
|
3051
|
-
} : void 0;
|
|
3052
|
-
const generated = generateWAMessageFromContent(
|
|
3053
|
-
chatId,
|
|
3054
|
-
{ interactiveMessage },
|
|
3055
|
-
{
|
|
3056
|
-
userJid,
|
|
3057
|
-
...quoted ? { quoted } : {}
|
|
3058
|
-
}
|
|
3059
|
-
);
|
|
3060
|
-
const messageId = generated.key.id;
|
|
3061
|
-
if (!generated.message || !messageId) {
|
|
3062
|
-
throw new WhaNextError(
|
|
3063
|
-
"PROVIDER_ERROR",
|
|
3064
|
-
"WhatsApp could not generate the interactive message."
|
|
3065
|
-
);
|
|
3066
|
-
}
|
|
3067
|
-
await socket.relayMessage(chatId, generated.message, {
|
|
3068
|
-
messageId,
|
|
3069
|
-
additionalNodes: this.#interactiveRelayNodes(chatId)
|
|
3070
|
-
});
|
|
3071
|
-
return this.#sent(generated);
|
|
3072
|
-
}
|
|
3073
|
-
#interactiveRelayNodes(chatId) {
|
|
3074
|
-
const bizNode = {
|
|
3075
|
-
tag: "biz",
|
|
3076
|
-
attrs: {
|
|
3077
|
-
actual_actors: "2",
|
|
3078
|
-
host_storage: "2",
|
|
3079
|
-
privacy_mode_ts: (Math.floor(Date.now() / 1e3) - 77980457).toString()
|
|
3080
|
-
},
|
|
3081
|
-
content: [
|
|
3082
|
-
{
|
|
3083
|
-
tag: "interactive",
|
|
3084
|
-
attrs: { type: "native_flow", v: "1" },
|
|
3085
|
-
content: [
|
|
3086
|
-
{
|
|
3087
|
-
tag: "native_flow",
|
|
3088
|
-
attrs: { v: "9", name: "mixed" }
|
|
3089
|
-
}
|
|
3090
|
-
]
|
|
3091
|
-
},
|
|
3092
|
-
{
|
|
3093
|
-
tag: "quality_control",
|
|
3094
|
-
attrs: { source_type: "third_party" }
|
|
3116
|
+
}),
|
|
3117
|
+
messageParamsJson: "{}",
|
|
3118
|
+
messageVersion: 1
|
|
3095
3119
|
}
|
|
3096
|
-
|
|
3120
|
+
}
|
|
3097
3121
|
};
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
bizNode
|
|
3104
|
-
];
|
|
3122
|
+
const result = await this.#requireClient().message.send(chatId, raw, {
|
|
3123
|
+
...replyTo ? { quote: this.#toZapoKey(replyTo) } : {},
|
|
3124
|
+
...mentions.length > 0 ? { mentions } : {}
|
|
3125
|
+
});
|
|
3126
|
+
return this.#sent(result, chatId);
|
|
3105
3127
|
}
|
|
3106
|
-
#toContent(content) {
|
|
3128
|
+
async #toContent(content) {
|
|
3107
3129
|
if ("text" in content) {
|
|
3108
3130
|
return {
|
|
3109
|
-
text: content.text,
|
|
3110
|
-
|
|
3131
|
+
value: { type: "text", text: content.text },
|
|
3132
|
+
mentions: content.mentions ? this.#mentions(content.mentions) : []
|
|
3111
3133
|
};
|
|
3112
3134
|
}
|
|
3113
3135
|
if ("image" in content) {
|
|
3114
3136
|
return {
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3137
|
+
value: {
|
|
3138
|
+
type: "image",
|
|
3139
|
+
media: await this.#media(content.image),
|
|
3140
|
+
...content.caption !== void 0 ? { caption: content.caption } : {}
|
|
3141
|
+
},
|
|
3142
|
+
mentions: content.mentions ? this.#mentions(content.mentions) : [],
|
|
3118
3143
|
...content.viewOnce !== void 0 ? { viewOnce: content.viewOnce } : {}
|
|
3119
3144
|
};
|
|
3120
3145
|
}
|
|
3121
3146
|
if ("video" in content) {
|
|
3122
3147
|
return {
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3148
|
+
value: {
|
|
3149
|
+
type: "video",
|
|
3150
|
+
media: await this.#media(content.video),
|
|
3151
|
+
...content.caption !== void 0 ? { caption: content.caption } : {},
|
|
3152
|
+
...content.gif !== void 0 ? { gifPlayback: content.gif } : {}
|
|
3153
|
+
},
|
|
3154
|
+
mentions: content.mentions ? this.#mentions(content.mentions) : [],
|
|
3155
|
+
...content.viewOnce !== void 0 ? { viewOnce: content.viewOnce } : {}
|
|
3128
3156
|
};
|
|
3129
3157
|
}
|
|
3130
3158
|
if ("sticker" in content) {
|
|
3131
|
-
return {
|
|
3159
|
+
return {
|
|
3160
|
+
value: {
|
|
3161
|
+
type: "sticker",
|
|
3162
|
+
media: await this.#media(content.sticker),
|
|
3163
|
+
mimetype: "image/webp"
|
|
3164
|
+
},
|
|
3165
|
+
mentions: []
|
|
3166
|
+
};
|
|
3132
3167
|
}
|
|
3133
3168
|
return {
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3169
|
+
value: {
|
|
3170
|
+
type: "audio",
|
|
3171
|
+
media: await this.#media(content.audio),
|
|
3172
|
+
...content.mimetype ? { mimetype: content.mimetype } : {},
|
|
3173
|
+
...content.voice !== void 0 ? { ptt: content.voice } : {}
|
|
3174
|
+
},
|
|
3175
|
+
mentions: []
|
|
3137
3176
|
};
|
|
3138
3177
|
}
|
|
3139
|
-
#media(source) {
|
|
3140
|
-
if (source instanceof Uint8Array)
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
if (
|
|
3144
|
-
|
|
3178
|
+
async #media(source) {
|
|
3179
|
+
if (source instanceof Uint8Array) return source;
|
|
3180
|
+
if ("path" in source) return source.path;
|
|
3181
|
+
const response = await fetch(source.url);
|
|
3182
|
+
if (!response.ok) {
|
|
3183
|
+
throw new WhaNextError(
|
|
3184
|
+
"PROVIDER_ERROR",
|
|
3185
|
+
"Could not download the remote media source.",
|
|
3186
|
+
{
|
|
3187
|
+
context: { status: response.status },
|
|
3188
|
+
recoverable: response.status >= 500
|
|
3189
|
+
}
|
|
3190
|
+
);
|
|
3145
3191
|
}
|
|
3146
|
-
return
|
|
3192
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
3147
3193
|
}
|
|
3148
3194
|
#mentions(mentions) {
|
|
3149
3195
|
return mentions.map((mention) => typeof mention === "string" ? mention : mention.mentionId);
|
|
3150
3196
|
}
|
|
3151
|
-
#
|
|
3197
|
+
#toZapoKey(key) {
|
|
3152
3198
|
return {
|
|
3153
3199
|
id: key.id,
|
|
3154
3200
|
remoteJid: key.chatId,
|
|
@@ -3156,48 +3202,87 @@ var BaileysProvider = class {
|
|
|
3156
3202
|
...key.participantId ? { participant: key.participantId } : {}
|
|
3157
3203
|
};
|
|
3158
3204
|
}
|
|
3159
|
-
#sent(
|
|
3160
|
-
if (!
|
|
3161
|
-
throw new WhaNextError(
|
|
3205
|
+
#sent(result, chatId) {
|
|
3206
|
+
if (!result.id) {
|
|
3207
|
+
throw new WhaNextError(
|
|
3208
|
+
"PROVIDER_ERROR",
|
|
3209
|
+
"WhatsApp did not confirm the sent message."
|
|
3210
|
+
);
|
|
3162
3211
|
}
|
|
3163
|
-
if (message.message) this.#remember(message);
|
|
3164
3212
|
return {
|
|
3165
|
-
id:
|
|
3166
|
-
chatId
|
|
3167
|
-
keys:
|
|
3213
|
+
id: result.id,
|
|
3214
|
+
chatId,
|
|
3215
|
+
keys: {
|
|
3216
|
+
id: result.id,
|
|
3217
|
+
chatId,
|
|
3218
|
+
fromMe: true
|
|
3219
|
+
},
|
|
3168
3220
|
timestamp: /* @__PURE__ */ new Date()
|
|
3169
3221
|
};
|
|
3170
3222
|
}
|
|
3171
|
-
#
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
status: this.#callStatus(call.status),
|
|
3177
|
-
isVideo: Boolean(call.isVideo),
|
|
3178
|
-
isGroup: Boolean(call.isGroup),
|
|
3179
|
-
date: call.date ?? /* @__PURE__ */ new Date()
|
|
3180
|
-
};
|
|
3181
|
-
}
|
|
3182
|
-
#groupParticipantsChanged(change) {
|
|
3183
|
-
const participantIds = change.participants.map((participant) => participant.id).filter((id) => Boolean(id));
|
|
3223
|
+
#normalizeVoipCall(event, forcedStatus) {
|
|
3224
|
+
const id = event.callId;
|
|
3225
|
+
const from = event.callerPn ?? event.peerJid ?? event.callCreator;
|
|
3226
|
+
const chatId = event.groupJid ?? event.peerJid ?? from;
|
|
3227
|
+
if (!id || !from || !chatId) return void 0;
|
|
3184
3228
|
return {
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3229
|
+
id,
|
|
3230
|
+
chatId,
|
|
3231
|
+
from,
|
|
3232
|
+
status: forcedStatus ?? this.#callStatus(event.stateData?.state),
|
|
3233
|
+
isVideo: event.mediaType === "video",
|
|
3234
|
+
isGroup: Boolean(event.groupJid),
|
|
3235
|
+
date: event.createdAt ?? /* @__PURE__ */ new Date()
|
|
3189
3236
|
};
|
|
3190
3237
|
}
|
|
3191
3238
|
#callStatus(status) {
|
|
3192
|
-
|
|
3193
|
-
"offer"
|
|
3194
|
-
"
|
|
3195
|
-
|
|
3196
|
-
"
|
|
3197
|
-
"
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3239
|
+
switch (status?.toLowerCase()) {
|
|
3240
|
+
case "offer":
|
|
3241
|
+
case "initiating":
|
|
3242
|
+
return "offer";
|
|
3243
|
+
case "ringing":
|
|
3244
|
+
case "incoming_ringing":
|
|
3245
|
+
return "ringing";
|
|
3246
|
+
case "preaccept":
|
|
3247
|
+
case "connecting":
|
|
3248
|
+
return "preaccept";
|
|
3249
|
+
case "accept":
|
|
3250
|
+
case "accepted":
|
|
3251
|
+
case "active":
|
|
3252
|
+
return "accept";
|
|
3253
|
+
case "reject":
|
|
3254
|
+
case "rejected":
|
|
3255
|
+
case "terminate":
|
|
3256
|
+
case "terminated":
|
|
3257
|
+
case "ended":
|
|
3258
|
+
return "reject";
|
|
3259
|
+
default:
|
|
3260
|
+
return "timeout";
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
#callEndStatus(reason) {
|
|
3264
|
+
return reason?.toLowerCase() === "timeout" ? "timeout" : "reject";
|
|
3265
|
+
}
|
|
3266
|
+
#groupAction(action) {
|
|
3267
|
+
const value = action?.toLowerCase() ?? "";
|
|
3268
|
+
if (value.includes("promote")) return "promote";
|
|
3269
|
+
if (value.includes("demote")) return "demote";
|
|
3270
|
+
if (value.includes("remove") || value.includes("leave")) return "remove";
|
|
3271
|
+
if (value.includes("add") || value.includes("join")) return "add";
|
|
3272
|
+
if (value.includes("participant") || value.includes("modify")) return "modify";
|
|
3273
|
+
return void 0;
|
|
3274
|
+
}
|
|
3275
|
+
#groupParticipantIds(event) {
|
|
3276
|
+
return uniqueIdentities((event.participants ?? []).map((participant) => participant.jid ?? participant.lidJid ?? participant.phoneJid));
|
|
3277
|
+
}
|
|
3278
|
+
#findStoredMessage(key) {
|
|
3279
|
+
const direct = this.#messageStore.get(this.#messageStoreKey(key));
|
|
3280
|
+
if (direct) return direct;
|
|
3281
|
+
if (!key.id) return void 0;
|
|
3282
|
+
for (const message of this.#messageStore.values()) {
|
|
3283
|
+
if (message.key.id === key.id) return message;
|
|
3284
|
+
}
|
|
3285
|
+
return void 0;
|
|
3201
3286
|
}
|
|
3202
3287
|
#remember(message) {
|
|
3203
3288
|
const key = this.#messageStoreKey(message.key);
|
|
@@ -3208,70 +3293,112 @@ var BaileysProvider = class {
|
|
|
3208
3293
|
if (oldest) this.#messageStore.delete(oldest);
|
|
3209
3294
|
}
|
|
3210
3295
|
}
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3296
|
+
#messageStoreKey(key) {
|
|
3297
|
+
return `${key.remoteJid ?? ""}:${key.id ?? ""}:${key.participant ?? key.participantAlt ?? ""}`;
|
|
3298
|
+
}
|
|
3299
|
+
#isOfflineMessage(message) {
|
|
3300
|
+
if (this.#options.processOfflineMessages === true) return false;
|
|
3301
|
+
if (message.offline === true) return true;
|
|
3302
|
+
if (!this.#connectedAtSeconds || message.timestampSeconds == null) return false;
|
|
3303
|
+
const timestamp = toSeconds(message.timestampSeconds);
|
|
3304
|
+
if (timestamp === void 0) return false;
|
|
3305
|
+
return timestamp < this.#connectedAtSeconds - 3;
|
|
3306
|
+
}
|
|
3307
|
+
#preparePairingGate() {
|
|
3308
|
+
this.#pairingRequired = false;
|
|
3309
|
+
this.#pairingReady = new Promise((resolve3) => {
|
|
3310
|
+
this.#resolvePairingReady = resolve3;
|
|
3311
|
+
});
|
|
3312
|
+
}
|
|
3313
|
+
#deviceBrowser() {
|
|
3314
|
+
return this.#options.browser === "macos" /* MacOS */ ? "safari" : "chrome";
|
|
3315
|
+
}
|
|
3316
|
+
#deviceOsDisplayName() {
|
|
3317
|
+
if (this.#options.browser === "macos" /* MacOS */) return "macOS";
|
|
3318
|
+
if (this.#options.browser === "ubuntu" /* Ubuntu */) return "Ubuntu";
|
|
3319
|
+
return "Windows";
|
|
3320
|
+
}
|
|
3321
|
+
#requireClient() {
|
|
3322
|
+
const client = this.#client;
|
|
3323
|
+
if (!client || !this.#connected) {
|
|
3324
|
+
throw new WhaNextError(
|
|
3325
|
+
"CONNECTION_CLOSED",
|
|
3326
|
+
"WhatsApp is not connected.",
|
|
3327
|
+
{ recoverable: true }
|
|
3328
|
+
);
|
|
3329
|
+
}
|
|
3330
|
+
return client;
|
|
3331
|
+
}
|
|
3332
|
+
async #withTimeout(promise, timeoutMs, message) {
|
|
3333
|
+
let timer;
|
|
3227
3334
|
try {
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3335
|
+
return await Promise.race([
|
|
3336
|
+
promise,
|
|
3337
|
+
new Promise((_, reject) => {
|
|
3338
|
+
timer = setTimeout(() => {
|
|
3339
|
+
reject(new WhaNextError(
|
|
3340
|
+
"CONNECTION_FAILED",
|
|
3341
|
+
message,
|
|
3342
|
+
{ recoverable: true }
|
|
3343
|
+
));
|
|
3344
|
+
}, timeoutMs);
|
|
3345
|
+
})
|
|
3346
|
+
]);
|
|
3233
3347
|
} finally {
|
|
3234
|
-
if (
|
|
3235
|
-
this.#groupMetadataRequests.delete(groupId);
|
|
3236
|
-
}
|
|
3348
|
+
if (timer) clearTimeout(timer);
|
|
3237
3349
|
}
|
|
3238
3350
|
}
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
if (oldest === void 0) return;
|
|
3249
|
-
this.#groupMetadataCache.delete(oldest);
|
|
3250
|
-
}
|
|
3351
|
+
};
|
|
3352
|
+
var WhaNextZapoLogger = class _WhaNextZapoLogger {
|
|
3353
|
+
level;
|
|
3354
|
+
#logger;
|
|
3355
|
+
#context;
|
|
3356
|
+
constructor(logger, context = {}) {
|
|
3357
|
+
this.#logger = logger;
|
|
3358
|
+
this.#context = context;
|
|
3359
|
+
this.level = logger.level === "debug" ? "debug" : logger.level === "warn" ? "warn" : logger.level === "error" || logger.level === "silent" ? "error" : "info";
|
|
3251
3360
|
}
|
|
3252
|
-
|
|
3253
|
-
this.#
|
|
3254
|
-
const generation = this.#groupMetadataGenerations.get(groupId) ?? 0;
|
|
3255
|
-
this.#groupMetadataGenerations.set(groupId, generation + 1);
|
|
3361
|
+
trace(message, context) {
|
|
3362
|
+
this.#logger.debug(message, this.#merge(context));
|
|
3256
3363
|
}
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3364
|
+
debug(message, context) {
|
|
3365
|
+
this.#logger.debug(message, this.#merge(context));
|
|
3366
|
+
}
|
|
3367
|
+
info(message, context) {
|
|
3368
|
+
this.#logger.info(message, this.#merge(context));
|
|
3369
|
+
}
|
|
3370
|
+
warn(message, context) {
|
|
3371
|
+
this.#logger.warn(message, this.#merge(context));
|
|
3372
|
+
}
|
|
3373
|
+
error(message, context) {
|
|
3374
|
+
this.#logger.error(message, this.#merge(context));
|
|
3375
|
+
}
|
|
3376
|
+
child(bindings) {
|
|
3377
|
+
return new _WhaNextZapoLogger(this.#logger, {
|
|
3378
|
+
...this.#context,
|
|
3379
|
+
...bindings
|
|
3380
|
+
});
|
|
3381
|
+
}
|
|
3382
|
+
#merge(context) {
|
|
3383
|
+
return context ? { ...this.#context, ...context } : this.#context;
|
|
3260
3384
|
}
|
|
3261
3385
|
};
|
|
3386
|
+
function toSeconds(value) {
|
|
3387
|
+
const raw = typeof value === "number" ? value : value?.toNumber ? value.toNumber() : value?.low;
|
|
3388
|
+
if (raw === void 0) return void 0;
|
|
3389
|
+
return raw > 1e10 ? Math.floor(raw / 1e3) : raw;
|
|
3390
|
+
}
|
|
3262
3391
|
|
|
3263
3392
|
// src/app/create.ts
|
|
3264
3393
|
async function create(options = {}) {
|
|
3265
3394
|
const logger = new Logger(options.logger);
|
|
3266
|
-
const provider = options.provider ?? new
|
|
3395
|
+
const provider = options.provider ?? new ZapoProvider({
|
|
3267
3396
|
auth: options.auth ?? "./session",
|
|
3268
3397
|
browser: options.browser ?? "windows" /* Windows */,
|
|
3269
3398
|
logger: logger.child("provider"),
|
|
3399
|
+
...options.accountId ? { sessionId: options.accountId } : {},
|
|
3270
3400
|
...options.messageCacheSize !== void 0 ? { messageCacheSize: options.messageCacheSize } : {},
|
|
3271
|
-
|
|
3272
|
-
...options.cache?.groupTtlMs !== void 0 ? { ttlMs: options.cache.groupTtlMs } : {},
|
|
3273
|
-
...options.cache?.memoryMaxEntries !== void 0 ? { maxEntries: options.cache.memoryMaxEntries } : {}
|
|
3274
|
-
},
|
|
3401
|
+
...options.processOfflineMessages !== void 0 ? { processOfflineMessages: options.processOfflineMessages } : {},
|
|
3275
3402
|
...options.reconnect ? { reconnect: options.reconnect } : {}
|
|
3276
3403
|
});
|
|
3277
3404
|
return new WhaNextApp(provider, {
|
|
@@ -3287,7 +3414,7 @@ async function create(options = {}) {
|
|
|
3287
3414
|
|
|
3288
3415
|
// src/app/multi-app.ts
|
|
3289
3416
|
import {
|
|
3290
|
-
join,
|
|
3417
|
+
join as join2,
|
|
3291
3418
|
resolve as resolve2
|
|
3292
3419
|
} from "path";
|
|
3293
3420
|
var MultiCommandRouter = class {
|
|
@@ -3433,7 +3560,7 @@ async function createMulti(options) {
|
|
|
3433
3560
|
}
|
|
3434
3561
|
normalizedIds.add(normalizedId);
|
|
3435
3562
|
if (account.provider === void 0) {
|
|
3436
|
-
const authPath = resolve2(account.auth ??
|
|
3563
|
+
const authPath = resolve2(account.auth ?? join2(authRoot, account.id));
|
|
3437
3564
|
if (authPaths.has(authPath)) {
|
|
3438
3565
|
throw new WhaNextError(
|
|
3439
3566
|
"ARGUMENT_INVALID",
|
|
@@ -3454,13 +3581,13 @@ async function createMulti(options) {
|
|
|
3454
3581
|
if (merged.mute?.enabled === true && merged.mute.store === void 0 && merged.mute.database === void 0) {
|
|
3455
3582
|
merged.mute = {
|
|
3456
3583
|
...merged.mute,
|
|
3457
|
-
database:
|
|
3584
|
+
database: join2("./data", `whanext-${id}.sqlite`)
|
|
3458
3585
|
};
|
|
3459
3586
|
}
|
|
3460
3587
|
const app = await create({
|
|
3461
3588
|
...merged,
|
|
3462
3589
|
accountId: id,
|
|
3463
|
-
auth: overrides.auth ??
|
|
3590
|
+
auth: overrides.auth ?? join2(authRoot, id)
|
|
3464
3591
|
});
|
|
3465
3592
|
apps.set(id, app);
|
|
3466
3593
|
}
|