@automagik/omni 2.260803.2 → 2.260804.1
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/db/drizzle/0047_rename_whatsapp_cloud_to_business.sql +35 -0
- package/db/drizzle/meta/_journal.json +7 -0
- package/dist/index.js +26 -26
- package/dist/sdk/client.d.ts +1 -1
- package/dist/sdk/client.d.ts.map +1 -1
- package/dist/sdk/types.generated.d.ts +33 -11
- package/dist/sdk/types.generated.d.ts.map +1 -1
- package/dist/server/index.js +300 -218
- package/package.json +2 -2
package/dist/server/index.js
CHANGED
|
@@ -23514,7 +23514,7 @@ var CHANNEL_TYPES, CONTENT_TYPES, DEBOUNCE_MODES, SPLIT_DELAY_MODES, RULE_TYPES;
|
|
|
23514
23514
|
var init_channel = __esm(() => {
|
|
23515
23515
|
CHANNEL_TYPES = [
|
|
23516
23516
|
"whatsapp-baileys",
|
|
23517
|
-
"whatsapp-
|
|
23517
|
+
"whatsapp-business",
|
|
23518
23518
|
"discord",
|
|
23519
23519
|
"slack",
|
|
23520
23520
|
"telegram",
|
|
@@ -24289,9 +24289,9 @@ var init_person = __esm(() => {
|
|
|
24289
24289
|
});
|
|
24290
24290
|
});
|
|
24291
24291
|
|
|
24292
|
-
// ../core/src/schemas/whatsapp-
|
|
24293
|
-
var MetaTemplateCategorySchema, MetaTemplateStatusSchema, MetaTemplateQualityScoreSchema, MetaTemplateHeaderComponentSchema, MetaTemplateBodyComponentSchema, MetaTemplateFooterComponentSchema, MetaTemplateButtonSchema, MetaTemplateButtonsComponentSchema, WhatsAppTemplateComponentSchema, InboundContextSchema, InboundMediaSchema, MetaInboundTextMessageSchema, MetaInboundMediaMessageSchema, MetaInboundLocationMessageSchema, MetaInboundContactsMessageSchema, MetaInboundReactionMessageSchema, MetaInboundInteractiveMessageSchema, MetaInboundButtonMessageSchema, MetaInboundMessageSchema, MetaWebhookStatusEntrySchema, MetaTemplateStatusUpdateSchema, MetaWebhookValueSchema, MetaWebhookChangeSchema, MetaWebhookEntrySchema, MetaWebhookPayloadSchema, EmbeddedSignupExchangeRequestSchema, EmbeddedSignupExchangeResponseSchema,
|
|
24294
|
-
var
|
|
24292
|
+
// ../core/src/schemas/whatsapp-business.ts
|
|
24293
|
+
var MetaTemplateCategorySchema, MetaTemplateStatusSchema, MetaTemplateQualityScoreSchema, MetaTemplateHeaderComponentSchema, MetaTemplateBodyComponentSchema, MetaTemplateFooterComponentSchema, MetaTemplateButtonSchema, MetaTemplateButtonsComponentSchema, WhatsAppTemplateComponentSchema, InboundContextSchema, InboundMediaSchema, MetaInboundTextMessageSchema, MetaInboundMediaMessageSchema, MetaInboundLocationMessageSchema, MetaInboundContactsMessageSchema, MetaInboundReactionMessageSchema, MetaInboundInteractiveMessageSchema, MetaInboundButtonMessageSchema, MetaInboundMessageSchema, MetaWebhookStatusEntrySchema, MetaTemplateStatusUpdateSchema, MetaWebhookValueSchema, MetaWebhookChangeSchema, MetaWebhookEntrySchema, MetaWebhookPayloadSchema, EmbeddedSignupExchangeRequestSchema, EmbeddedSignupExchangeResponseSchema, WhatsAppBusinessConnectRequestSchema, WhatsAppFlowSendSchema, WhatsAppBusinessRegisterRequestSchema, SendTemplateRequestSchema;
|
|
24294
|
+
var init_whatsapp_business = __esm(() => {
|
|
24295
24295
|
init_zod();
|
|
24296
24296
|
init_common();
|
|
24297
24297
|
MetaTemplateCategorySchema = exports_external.enum(["MARKETING", "UTILITY", "AUTHENTICATION"]);
|
|
@@ -24510,7 +24510,7 @@ var init_whatsapp_cloud = __esm(() => {
|
|
|
24510
24510
|
quality_rating: exports_external.string().optional()
|
|
24511
24511
|
}))
|
|
24512
24512
|
});
|
|
24513
|
-
|
|
24513
|
+
WhatsAppBusinessConnectRequestSchema = exports_external.object({
|
|
24514
24514
|
accessToken: exports_external.string().min(1).optional(),
|
|
24515
24515
|
exchangeHandle: exports_external.string().min(1).optional(),
|
|
24516
24516
|
phoneNumberId: exports_external.string().min(1),
|
|
@@ -24537,7 +24537,7 @@ var init_whatsapp_cloud = __esm(() => {
|
|
|
24537
24537
|
message: "Provide exactly one of flowId or flowName",
|
|
24538
24538
|
path: ["flowId"]
|
|
24539
24539
|
});
|
|
24540
|
-
|
|
24540
|
+
WhatsAppBusinessRegisterRequestSchema = exports_external.object({
|
|
24541
24541
|
pin: exports_external.string().regex(/^\d{6}$/, "PIN must be exactly 6 digits").optional()
|
|
24542
24542
|
});
|
|
24543
24543
|
SendTemplateRequestSchema = exports_external.object({
|
|
@@ -24730,7 +24730,7 @@ var init_whatsapp_flows = __esm(() => {
|
|
|
24730
24730
|
var HermesContactSchema, HermesWebhookPayloadSchema;
|
|
24731
24731
|
var init_hermes = __esm(() => {
|
|
24732
24732
|
init_zod();
|
|
24733
|
-
|
|
24733
|
+
init_whatsapp_business();
|
|
24734
24734
|
HermesContactSchema = exports_external.object({
|
|
24735
24735
|
profile: exports_external.object({ name: exports_external.string().optional() }).optional(),
|
|
24736
24736
|
wa_id: exports_external.string().optional()
|
|
@@ -24757,14 +24757,14 @@ var init_schemas = __esm(() => {
|
|
|
24757
24757
|
init_instance();
|
|
24758
24758
|
init_message();
|
|
24759
24759
|
init_person();
|
|
24760
|
-
|
|
24760
|
+
init_whatsapp_business();
|
|
24761
24761
|
init_whatsapp_flows();
|
|
24762
24762
|
init_hermes();
|
|
24763
24763
|
});
|
|
24764
24764
|
|
|
24765
|
-
// ../core/src/types/whatsapp-
|
|
24765
|
+
// ../core/src/types/whatsapp-business.ts
|
|
24766
24766
|
var META_TEMPLATE_CATEGORIES, META_TEMPLATE_STATUSES, META_TEMPLATE_QUALITY_SCORES;
|
|
24767
|
-
var
|
|
24767
|
+
var init_whatsapp_business2 = __esm(() => {
|
|
24768
24768
|
META_TEMPLATE_CATEGORIES = ["MARKETING", "UTILITY", "AUTHENTICATION"];
|
|
24769
24769
|
META_TEMPLATE_STATUSES = ["APPROVED", "PENDING", "REJECTED", "PAUSED", "DELETED"];
|
|
24770
24770
|
META_TEMPLATE_QUALITY_SCORES = ["GREEN", "YELLOW", "RED", "UNKNOWN"];
|
|
@@ -24781,7 +24781,7 @@ var SETTING_VALUE_TYPES;
|
|
|
24781
24781
|
var init_types5 = __esm(() => {
|
|
24782
24782
|
init_channel();
|
|
24783
24783
|
init_agent();
|
|
24784
|
-
|
|
24784
|
+
init_whatsapp_business2();
|
|
24785
24785
|
SETTING_VALUE_TYPES = ["string", "integer", "boolean", "json", "secret"];
|
|
24786
24786
|
});
|
|
24787
24787
|
|
|
@@ -30853,13 +30853,13 @@ var MESSAGING_WINDOW_MS, DEFAULT_TYPING_INDICATOR_MS = 2500, CHANNELS_WITH_MESSA
|
|
|
30853
30853
|
var init_capabilities2 = __esm(() => {
|
|
30854
30854
|
MESSAGING_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
30855
30855
|
CHANNELS_WITH_MESSAGING_WINDOW = new Set([
|
|
30856
|
-
"whatsapp-
|
|
30856
|
+
"whatsapp-business",
|
|
30857
30857
|
"hermes",
|
|
30858
30858
|
"twilio-whatsapp"
|
|
30859
30859
|
]);
|
|
30860
30860
|
CHANNELS_WITH_TYPING_INDICATOR = new Set([
|
|
30861
30861
|
"whatsapp-baileys",
|
|
30862
|
-
"whatsapp-
|
|
30862
|
+
"whatsapp-business",
|
|
30863
30863
|
"twilio-whatsapp",
|
|
30864
30864
|
"discord",
|
|
30865
30865
|
"slack",
|
|
@@ -36050,8 +36050,8 @@ __export(exports_src, {
|
|
|
36050
36050
|
agentStateKey: () => agentStateKey,
|
|
36051
36051
|
WhatsAppTemplateComponentSchema: () => WhatsAppTemplateComponentSchema,
|
|
36052
36052
|
WhatsAppFlowSendSchema: () => WhatsAppFlowSendSchema,
|
|
36053
|
-
|
|
36054
|
-
|
|
36053
|
+
WhatsAppBusinessRegisterRequestSchema: () => WhatsAppBusinessRegisterRequestSchema,
|
|
36054
|
+
WhatsAppBusinessConnectRequestSchema: () => WhatsAppBusinessConnectRequestSchema,
|
|
36055
36055
|
WebhookAgentProvider: () => WebhookAgentProvider,
|
|
36056
36056
|
ValidationError: () => ValidationError2,
|
|
36057
36057
|
UuidSchema: () => UuidSchema,
|
|
@@ -36803,11 +36803,11 @@ function startAck(plugin2, ackProvider, instanceId, chatId, messageId, channel2,
|
|
|
36803
36803
|
let removed = false;
|
|
36804
36804
|
if (ackProvider) {
|
|
36805
36805
|
ackProvider.ack(instanceId, chatId, messageId, emoji).catch(() => {
|
|
36806
|
-
if ((channel2 === "whatsapp" || channel2 === "whatsapp-baileys" || channel2 === "whatsapp-
|
|
36806
|
+
if ((channel2 === "whatsapp" || channel2 === "whatsapp-baileys" || channel2 === "whatsapp-business") && plugin2?.sendTyping) {
|
|
36807
36807
|
plugin2.sendTyping(instanceId, chatId, timeoutMs).catch(() => {});
|
|
36808
36808
|
}
|
|
36809
36809
|
});
|
|
36810
|
-
} else if ((channel2 === "whatsapp" || channel2 === "whatsapp-baileys" || channel2 === "whatsapp-
|
|
36810
|
+
} else if ((channel2 === "whatsapp" || channel2 === "whatsapp-baileys" || channel2 === "whatsapp-business") && plugin2?.sendTyping) {
|
|
36811
36811
|
plugin2.sendTyping(instanceId, chatId, timeoutMs).catch(() => {});
|
|
36812
36812
|
}
|
|
36813
36813
|
const timer = setTimeout(() => {
|
|
@@ -158277,11 +158277,11 @@ var init_audio_converter = __esm(() => {
|
|
|
158277
158277
|
};
|
|
158278
158278
|
});
|
|
158279
158279
|
|
|
158280
|
-
// ../channel-whatsapp-
|
|
158281
|
-
var
|
|
158280
|
+
// ../channel-whatsapp-business/src/capabilities.ts
|
|
158281
|
+
var WHATSAPP_BUSINESS_CAPABILITIES;
|
|
158282
158282
|
var init_capabilities3 = __esm(() => {
|
|
158283
158283
|
init_src2();
|
|
158284
|
-
|
|
158284
|
+
WHATSAPP_BUSINESS_CAPABILITIES = {
|
|
158285
158285
|
...DEFAULT_CAPABILITIES,
|
|
158286
158286
|
canSendText: true,
|
|
158287
158287
|
canSendMedia: true,
|
|
@@ -158333,7 +158333,7 @@ var init_capabilities3 = __esm(() => {
|
|
|
158333
158333
|
};
|
|
158334
158334
|
});
|
|
158335
158335
|
|
|
158336
|
-
// ../channel-whatsapp-
|
|
158336
|
+
// ../channel-whatsapp-business/src/utils/errors.ts
|
|
158337
158337
|
function isRetryable6(error) {
|
|
158338
158338
|
return error instanceof MetaApiError && error.retryable;
|
|
158339
158339
|
}
|
|
@@ -158391,7 +158391,7 @@ var init_errors3 = __esm(() => {
|
|
|
158391
158391
|
MetaApiError = class MetaApiError extends ChannelError {
|
|
158392
158392
|
channelCode;
|
|
158393
158393
|
constructor(code, message2, context2 = {}) {
|
|
158394
|
-
super(CORE_CODE_MAP6[code] ?? ERROR_CODES.UNKNOWN, message2, "whatsapp-
|
|
158394
|
+
super(CORE_CODE_MAP6[code] ?? ERROR_CODES.UNKNOWN, message2, "whatsapp-business", undefined, {
|
|
158395
158395
|
recoverable: RETRYABLE_CODES2.has(code),
|
|
158396
158396
|
context: { ...context2 }
|
|
158397
158397
|
});
|
|
@@ -158410,7 +158410,7 @@ var init_errors3 = __esm(() => {
|
|
|
158410
158410
|
OUTSIDE_24H_WINDOW_CODES = new Set([131047, 131051]);
|
|
158411
158411
|
});
|
|
158412
158412
|
|
|
158413
|
-
// ../channel-whatsapp-
|
|
158413
|
+
// ../channel-whatsapp-business/src/client.ts
|
|
158414
158414
|
function buildHeaderComponent(headerMedia) {
|
|
158415
158415
|
return { type: "header", parameters: [buildHeaderParameter(headerMedia)] };
|
|
158416
158416
|
}
|
|
@@ -158661,7 +158661,7 @@ var init_client3 = __esm(() => {
|
|
|
158661
158661
|
init_errors3();
|
|
158662
158662
|
});
|
|
158663
158663
|
|
|
158664
|
-
// ../channel-whatsapp-
|
|
158664
|
+
// ../channel-whatsapp-business/src/flows/resolver.ts
|
|
158665
158665
|
function buildFlowToken(flowRef) {
|
|
158666
158666
|
return `${FLOW_TOKEN_PREFIX}.${flowRef}.${crypto.randomUUID()}`;
|
|
158667
158667
|
}
|
|
@@ -158704,7 +158704,7 @@ function errorScreenResponse(ctx, message2) {
|
|
|
158704
158704
|
}
|
|
158705
158705
|
var FLOW_TOKEN_PREFIX = "omni";
|
|
158706
158706
|
|
|
158707
|
-
// ../channel-whatsapp-
|
|
158707
|
+
// ../channel-whatsapp-business/src/utils/flow-crypto.ts
|
|
158708
158708
|
function pemToDer(pem) {
|
|
158709
158709
|
const base64 = pem.replace(/-----(BEGIN|END)[A-Z ]+-----/g, "").replace(/\s+/g, "");
|
|
158710
158710
|
return b64decode(base64);
|
|
@@ -158781,7 +158781,7 @@ var init_flow_crypto = __esm(() => {
|
|
|
158781
158781
|
};
|
|
158782
158782
|
});
|
|
158783
158783
|
|
|
158784
|
-
// ../channel-whatsapp-
|
|
158784
|
+
// ../channel-whatsapp-business/src/utils/signature.ts
|
|
158785
158785
|
async function verifyMetaSignature(body, signatureHeader, appSecret) {
|
|
158786
158786
|
if (!signatureHeader || !appSecret)
|
|
158787
158787
|
return false;
|
|
@@ -158828,7 +158828,7 @@ function timingSafeEqualHex(a, b2) {
|
|
|
158828
158828
|
}
|
|
158829
158829
|
var SIGNATURE_PREFIX = "sha256=";
|
|
158830
158830
|
|
|
158831
|
-
// ../channel-whatsapp-
|
|
158831
|
+
// ../channel-whatsapp-business/src/handlers/flow-data.ts
|
|
158832
158832
|
function isEncryptedBody(parsed) {
|
|
158833
158833
|
return typeof parsed.encrypted_flow_data === "string" && typeof parsed.encrypted_aes_key === "string" && typeof parsed.initial_vector === "string";
|
|
158834
158834
|
}
|
|
@@ -158836,7 +158836,7 @@ async function intake(request, ctx) {
|
|
|
158836
158836
|
const rawBody = await request.text();
|
|
158837
158837
|
const signature = request.headers.get("x-hub-signature-256");
|
|
158838
158838
|
if (!ctx.appSecret || !signature || !await verifyMetaSignature(rawBody, signature, ctx.appSecret)) {
|
|
158839
|
-
ctx.logger.warn("[whatsapp-
|
|
158839
|
+
ctx.logger.warn("[whatsapp-business] flow data request failed signature verification", {
|
|
158840
158840
|
instanceId: ctx.instanceId,
|
|
158841
158841
|
hasSignature: Boolean(signature)
|
|
158842
158842
|
});
|
|
@@ -158858,7 +158858,7 @@ async function intake(request, ctx) {
|
|
|
158858
158858
|
const privateKey = await importFlowPrivateKey(ctx.privateKeyPem);
|
|
158859
158859
|
return { decrypted: await decryptFlowRequest(parsed, privateKey) };
|
|
158860
158860
|
} catch (err2) {
|
|
158861
|
-
ctx.logger.warn("[whatsapp-
|
|
158861
|
+
ctx.logger.warn("[whatsapp-business] flow data decrypt failed \u2014 responding 421", {
|
|
158862
158862
|
instanceId: ctx.instanceId,
|
|
158863
158863
|
error: err2 instanceof FlowDecryptError ? err2.message : String(err2)
|
|
158864
158864
|
});
|
|
@@ -158868,7 +158868,7 @@ async function intake(request, ctx) {
|
|
|
158868
158868
|
async function resolveScreen(ctx, resolveCtx) {
|
|
158869
158869
|
const resolver = ctx.registry.lookup(resolveCtx);
|
|
158870
158870
|
if (!resolver) {
|
|
158871
|
-
ctx.logger.warn("[whatsapp-
|
|
158871
|
+
ctx.logger.warn("[whatsapp-business] no flow resolver registered \u2014 responding with error screen", {
|
|
158872
158872
|
instanceId: ctx.instanceId,
|
|
158873
158873
|
flowRef: resolveCtx.flowRef
|
|
158874
158874
|
});
|
|
@@ -158880,7 +158880,7 @@ async function resolveScreen(ctx, resolveCtx) {
|
|
|
158880
158880
|
new Promise((_2, reject) => setTimeout(() => reject(new Error(`flow resolver timed out after ${RESOLVE_TIMEOUT_MS}ms`)), RESOLVE_TIMEOUT_MS))
|
|
158881
158881
|
]);
|
|
158882
158882
|
} catch (err2) {
|
|
158883
|
-
ctx.logger.error("[whatsapp-
|
|
158883
|
+
ctx.logger.error("[whatsapp-business] flow resolver failed", {
|
|
158884
158884
|
instanceId: ctx.instanceId,
|
|
158885
158885
|
flowRef: resolveCtx.flowRef,
|
|
158886
158886
|
action: resolveCtx.action,
|
|
@@ -158903,7 +158903,7 @@ async function publishExchangeEvent(ctx, resolveCtx, responseScreen, durationMs)
|
|
|
158903
158903
|
durationMs
|
|
158904
158904
|
});
|
|
158905
158905
|
} catch (err2) {
|
|
158906
|
-
ctx.logger.warn("[whatsapp-
|
|
158906
|
+
ctx.logger.warn("[whatsapp-business] flow.data_exchange event publish failed", {
|
|
158907
158907
|
instanceId: ctx.instanceId,
|
|
158908
158908
|
error: err2 instanceof Error ? err2.message : String(err2)
|
|
158909
158909
|
});
|
|
@@ -158923,7 +158923,7 @@ async function handleFlowDataRequest(request, ctx) {
|
|
|
158923
158923
|
}
|
|
158924
158924
|
const dataBag = payload.data ?? {};
|
|
158925
158925
|
if (dataBag.error != null || dataBag.error_message != null) {
|
|
158926
|
-
ctx.logger.warn("[whatsapp-
|
|
158926
|
+
ctx.logger.warn("[whatsapp-business] flow client error notification", {
|
|
158927
158927
|
instanceId: ctx.instanceId,
|
|
158928
158928
|
flowToken: payload.flow_token,
|
|
158929
158929
|
error: dataBag.error,
|
|
@@ -158945,7 +158945,7 @@ async function handleFlowDataRequest(request, ctx) {
|
|
|
158945
158945
|
const startedAt = performance.now();
|
|
158946
158946
|
const screenResponse = await resolveScreen(ctx, resolveCtx);
|
|
158947
158947
|
const durationMs = Math.round(performance.now() - startedAt);
|
|
158948
|
-
ctx.logger.info("[whatsapp-
|
|
158948
|
+
ctx.logger.info("[whatsapp-business] flow data exchange resolved", {
|
|
158949
158949
|
instanceId: ctx.instanceId,
|
|
158950
158950
|
flowRef: resolveCtx.flowRef,
|
|
158951
158951
|
action: resolveCtx.action,
|
|
@@ -164370,7 +164370,7 @@ var init_schema2 = __esm(() => {
|
|
|
164370
164370
|
init_pg_core();
|
|
164371
164371
|
channelTypes = [
|
|
164372
164372
|
"whatsapp-baileys",
|
|
164373
|
-
"whatsapp-
|
|
164373
|
+
"whatsapp-business",
|
|
164374
164374
|
"discord",
|
|
164375
164375
|
"slack",
|
|
164376
164376
|
"telegram",
|
|
@@ -170060,7 +170060,7 @@ var init_src5 = __esm(() => {
|
|
|
170060
170060
|
init_schema2();
|
|
170061
170061
|
});
|
|
170062
170062
|
|
|
170063
|
-
// ../channel-whatsapp-
|
|
170063
|
+
// ../channel-whatsapp-business/src/templates.ts
|
|
170064
170064
|
var exports_templates = {};
|
|
170065
170065
|
__export(exports_templates, {
|
|
170066
170066
|
uploadHeaderMedia: () => uploadHeaderMedia,
|
|
@@ -170300,7 +170300,7 @@ var init_templates2 = __esm(() => {
|
|
|
170300
170300
|
TEMPLATE_NAME_RE = /^[a-z0-9_]+$/;
|
|
170301
170301
|
});
|
|
170302
170302
|
|
|
170303
|
-
// ../channel-whatsapp-
|
|
170303
|
+
// ../channel-whatsapp-business/src/handlers/webhook.ts
|
|
170304
170304
|
function handleVerifyChallenge(request, verifyToken) {
|
|
170305
170305
|
const url = new URL(request.url);
|
|
170306
170306
|
const mode = url.searchParams.get("hub.mode");
|
|
@@ -170323,17 +170323,17 @@ async function handleMetaWebhook(request, plugin8, appSecret, verifyToken) {
|
|
|
170323
170323
|
try {
|
|
170324
170324
|
body = await request.text();
|
|
170325
170325
|
} catch (err2) {
|
|
170326
|
-
logger6.warn("[whatsapp-
|
|
170326
|
+
logger6.warn("[whatsapp-business] failed to read webhook body", { err: String(err2) });
|
|
170327
170327
|
return new Response("OK", { status: 200 });
|
|
170328
170328
|
}
|
|
170329
170329
|
if (body.length > MAX_BODY_BYTES2) {
|
|
170330
|
-
logger6.warn("[whatsapp-
|
|
170330
|
+
logger6.warn("[whatsapp-business] oversized webhook body rejected", { size: body.length });
|
|
170331
170331
|
return new Response("OK", { status: 200 });
|
|
170332
170332
|
}
|
|
170333
170333
|
const signature = request.headers.get("x-hub-signature-256");
|
|
170334
170334
|
const valid = await verifyMetaSignature(body, signature, appSecret);
|
|
170335
170335
|
if (!valid) {
|
|
170336
|
-
logger6.warn("[whatsapp-
|
|
170336
|
+
logger6.warn("[whatsapp-business] invalid X-Hub-Signature-256 \u2014 rejecting webhook", {
|
|
170337
170337
|
hasHeader: signature !== null
|
|
170338
170338
|
});
|
|
170339
170339
|
return new Response("Unauthorized", { status: 401 });
|
|
@@ -170342,12 +170342,12 @@ async function handleMetaWebhook(request, plugin8, appSecret, verifyToken) {
|
|
|
170342
170342
|
try {
|
|
170343
170343
|
parsedJson = JSON.parse(body);
|
|
170344
170344
|
} catch {
|
|
170345
|
-
logger6.warn("[whatsapp-
|
|
170345
|
+
logger6.warn("[whatsapp-business] webhook body is not valid JSON");
|
|
170346
170346
|
return new Response("OK", { status: 200 });
|
|
170347
170347
|
}
|
|
170348
170348
|
const validated = MetaWebhookPayloadSchema.safeParse(parsedJson);
|
|
170349
170349
|
if (!validated.success) {
|
|
170350
|
-
logger6.warn("[whatsapp-
|
|
170350
|
+
logger6.warn("[whatsapp-business] webhook payload failed schema validation", {
|
|
170351
170351
|
issues: validated.error.issues.slice(0, 5)
|
|
170352
170352
|
});
|
|
170353
170353
|
return new Response("OK", { status: 200 });
|
|
@@ -170373,7 +170373,7 @@ async function processChange(plugin8, change, entryId, logger6) {
|
|
|
170373
170373
|
return;
|
|
170374
170374
|
}
|
|
170375
170375
|
if (change.field !== "messages") {
|
|
170376
|
-
logger6.debug("[whatsapp-
|
|
170376
|
+
logger6.debug("[whatsapp-business] ignoring unsupported webhook field", { field: change.field });
|
|
170377
170377
|
return;
|
|
170378
170378
|
}
|
|
170379
170379
|
await processMessagesChange(plugin8, change, logger6);
|
|
@@ -170382,7 +170382,7 @@ async function processChannelAlert(plugin8, change, entryId, logger6) {
|
|
|
170382
170382
|
const value = change.value ?? {};
|
|
170383
170383
|
const matches = plugin8.findInstancesByWabaId(entryId);
|
|
170384
170384
|
if (matches.length === 0) {
|
|
170385
|
-
logger6.debug("[whatsapp-
|
|
170385
|
+
logger6.debug("[whatsapp-business] channel alert arrived with no matching WABA", {
|
|
170386
170386
|
field: change.field,
|
|
170387
170387
|
wabaId: entryId
|
|
170388
170388
|
});
|
|
@@ -170390,7 +170390,7 @@ async function processChannelAlert(plugin8, change, entryId, logger6) {
|
|
|
170390
170390
|
}
|
|
170391
170391
|
const alertType = change.field;
|
|
170392
170392
|
await Promise.all(matches.map(([instanceId]) => plugin8.handleChannelAlert(instanceId, alertType, value).catch((err2) => {
|
|
170393
|
-
logger6.warn("[whatsapp-
|
|
170393
|
+
logger6.warn("[whatsapp-business] failed to emit channel.alert", {
|
|
170394
170394
|
instanceId,
|
|
170395
170395
|
field: change.field,
|
|
170396
170396
|
err: String(err2)
|
|
@@ -170400,7 +170400,7 @@ async function processChannelAlert(plugin8, change, entryId, logger6) {
|
|
|
170400
170400
|
async function processTemplateStatusUpdate(plugin8, change, logger6) {
|
|
170401
170401
|
const parsed = MetaTemplateStatusUpdateSchema.safeParse(change.value);
|
|
170402
170402
|
if (!parsed.success) {
|
|
170403
|
-
logger6.warn("[whatsapp-
|
|
170403
|
+
logger6.warn("[whatsapp-business] template_status_update payload invalid", {
|
|
170404
170404
|
issues: parsed.error.issues.slice(0, 3)
|
|
170405
170405
|
});
|
|
170406
170406
|
return;
|
|
@@ -170410,7 +170410,7 @@ async function processTemplateStatusUpdate(plugin8, change, logger6) {
|
|
|
170410
170410
|
try {
|
|
170411
170411
|
await handleTemplateStatusUpdate2(getDb2(), parsed.data, plugin8);
|
|
170412
170412
|
} catch (err2) {
|
|
170413
|
-
logger6.warn("[whatsapp-
|
|
170413
|
+
logger6.warn("[whatsapp-business] failed to handle template status update", {
|
|
170414
170414
|
metaTemplateId: parsed.data.message_template_id,
|
|
170415
170415
|
err: String(err2)
|
|
170416
170416
|
});
|
|
@@ -170421,12 +170421,12 @@ async function processMessagesChange(plugin8, change, logger6) {
|
|
|
170421
170421
|
const metadata = value.metadata;
|
|
170422
170422
|
const phoneNumberId = metadata?.phone_number_id;
|
|
170423
170423
|
if (!phoneNumberId) {
|
|
170424
|
-
logger6.warn("[whatsapp-
|
|
170424
|
+
logger6.warn("[whatsapp-business] webhook change missing metadata.phone_number_id");
|
|
170425
170425
|
return;
|
|
170426
170426
|
}
|
|
170427
170427
|
const resolved = plugin8.findInstanceByPhoneNumberId(phoneNumberId);
|
|
170428
170428
|
if (!resolved) {
|
|
170429
|
-
logger6.warn("[whatsapp-
|
|
170429
|
+
logger6.warn("[whatsapp-business] no instance for phone_number_id \u2014 dropping change", {
|
|
170430
170430
|
phoneNumberId
|
|
170431
170431
|
});
|
|
170432
170432
|
return;
|
|
@@ -170446,7 +170446,7 @@ async function emitInboundMessages(plugin8, instanceId, messages4, contacts, ded
|
|
|
170446
170446
|
continue;
|
|
170447
170447
|
await plugin8.handleInboundMessage(instanceId, msg, contacts, dedupeCache);
|
|
170448
170448
|
} catch (err2) {
|
|
170449
|
-
logger6.warn("[whatsapp-
|
|
170449
|
+
logger6.warn("[whatsapp-business] failed to emit inbound message", {
|
|
170450
170450
|
instanceId,
|
|
170451
170451
|
err: String(err2)
|
|
170452
170452
|
});
|
|
@@ -170461,7 +170461,7 @@ async function emitStatusUpdates(plugin8, instanceId, statuses, logger6) {
|
|
|
170461
170461
|
continue;
|
|
170462
170462
|
await plugin8.handleStatusUpdate(instanceId, status);
|
|
170463
170463
|
} catch (err2) {
|
|
170464
|
-
logger6.warn("[whatsapp-
|
|
170464
|
+
logger6.warn("[whatsapp-business] failed to emit status event", {
|
|
170465
170465
|
instanceId,
|
|
170466
170466
|
err: String(err2)
|
|
170467
170467
|
});
|
|
@@ -170480,7 +170480,7 @@ var init_webhook = __esm(() => {
|
|
|
170480
170480
|
]);
|
|
170481
170481
|
});
|
|
170482
170482
|
|
|
170483
|
-
// ../channel-whatsapp-
|
|
170483
|
+
// ../channel-whatsapp-business/src/utils/identity.ts
|
|
170484
170484
|
function toMetaPhone(input) {
|
|
170485
170485
|
if (!input)
|
|
170486
170486
|
return "";
|
|
@@ -170495,7 +170495,7 @@ function phonesEqual(a, b3) {
|
|
|
170495
170495
|
return toMetaPhone(a) === toMetaPhone(b3);
|
|
170496
170496
|
}
|
|
170497
170497
|
|
|
170498
|
-
// ../channel-whatsapp-
|
|
170498
|
+
// ../channel-whatsapp-business/src/senders/text.ts
|
|
170499
170499
|
async function sendText3(client, to, text3, replyTo) {
|
|
170500
170500
|
const payload = {
|
|
170501
170501
|
messaging_product: "whatsapp",
|
|
@@ -170510,7 +170510,7 @@ async function sendText3(client, to, text3, replyTo) {
|
|
|
170510
170510
|
}
|
|
170511
170511
|
var init_text2 = () => {};
|
|
170512
170512
|
|
|
170513
|
-
// ../channel-whatsapp-
|
|
170513
|
+
// ../channel-whatsapp-business/src/senders/media.ts
|
|
170514
170514
|
function resolveMetaMediaType(mimeType) {
|
|
170515
170515
|
if (!mimeType)
|
|
170516
170516
|
return "document";
|
|
@@ -170546,7 +170546,7 @@ async function sendMedia3(client, to, mediaUrl, mimeType, caption, filename, rep
|
|
|
170546
170546
|
}
|
|
170547
170547
|
var init_media = () => {};
|
|
170548
170548
|
|
|
170549
|
-
// ../channel-whatsapp-
|
|
170549
|
+
// ../channel-whatsapp-business/src/senders/location.ts
|
|
170550
170550
|
async function sendLocation4(client, to, latitude, longitude, name, address, replyTo) {
|
|
170551
170551
|
const payload = {
|
|
170552
170552
|
messaging_product: "whatsapp",
|
|
@@ -170566,7 +170566,7 @@ async function sendLocation4(client, to, latitude, longitude, name, address, rep
|
|
|
170566
170566
|
}
|
|
170567
170567
|
var init_location = () => {};
|
|
170568
170568
|
|
|
170569
|
-
// ../channel-whatsapp-
|
|
170569
|
+
// ../channel-whatsapp-business/src/senders/contact.ts
|
|
170570
170570
|
function buildContactRecord2(input) {
|
|
170571
170571
|
const record = {
|
|
170572
170572
|
name: { formatted_name: input.name, first_name: input.name }
|
|
@@ -170599,7 +170599,7 @@ async function sendContact3(client, to, contacts, replyTo) {
|
|
|
170599
170599
|
}
|
|
170600
170600
|
var init_contact = () => {};
|
|
170601
170601
|
|
|
170602
|
-
// ../channel-whatsapp-
|
|
170602
|
+
// ../channel-whatsapp-business/src/senders/reaction.ts
|
|
170603
170603
|
async function sendReaction3(client, to, messageId, emoji) {
|
|
170604
170604
|
if (!messageId) {
|
|
170605
170605
|
throw new MetaApiError(MetaErrorCode.INVALID_REQUEST, "sendReaction requires a target messageId (wamid)", {
|
|
@@ -170619,7 +170619,7 @@ var init_reaction = __esm(() => {
|
|
|
170619
170619
|
init_errors3();
|
|
170620
170620
|
});
|
|
170621
170621
|
|
|
170622
|
-
// ../channel-whatsapp-
|
|
170622
|
+
// ../channel-whatsapp-business/src/senders/interactive.ts
|
|
170623
170623
|
function buttonId(btn, index2) {
|
|
170624
170624
|
return (btn.data ?? btn.text ?? `btn_${index2}`).slice(0, MAX_ID);
|
|
170625
170625
|
}
|
|
@@ -170731,7 +170731,7 @@ async function sendInteractive(client, to, bodyText, buttons, replyTo, listButto
|
|
|
170731
170731
|
var MAX_REPLY_BUTTONS = 3, MAX_LIST_ROWS = 10, MAX_BUTTON_TITLE = 20, MAX_ROW_TITLE = 24, MAX_ROW_DESCRIPTION = 72, MAX_SECTION_TITLE = 24, MAX_ID = 256, truncate2 = (s, max) => s.length <= max ? s : `${s.slice(0, max - 1)}\u2026`;
|
|
170732
170732
|
var init_interactive = () => {};
|
|
170733
170733
|
|
|
170734
|
-
// ../channel-whatsapp-
|
|
170734
|
+
// ../channel-whatsapp-business/src/senders/flow.ts
|
|
170735
170735
|
async function sendFlow(client, to, flow, replyTo) {
|
|
170736
170736
|
const flowRef = flow.flowId ?? flow.flowName ?? "unknown";
|
|
170737
170737
|
const flowToken = flow.flowToken ?? buildFlowToken(flowRef);
|
|
@@ -170769,7 +170769,7 @@ async function sendFlow(client, to, flow, replyTo) {
|
|
|
170769
170769
|
}
|
|
170770
170770
|
var init_flow = () => {};
|
|
170771
170771
|
|
|
170772
|
-
// ../channel-whatsapp-
|
|
170772
|
+
// ../channel-whatsapp-business/src/senders/template.ts
|
|
170773
170773
|
async function sendTemplate2(client, to, templateName, language, bodyParameters, headerMedia, buttonParameters, replyTo) {
|
|
170774
170774
|
const template = client.buildTemplatePayload({
|
|
170775
170775
|
name: templateName,
|
|
@@ -170791,7 +170791,7 @@ async function sendTemplate2(client, to, templateName, language, bodyParameters,
|
|
|
170791
170791
|
}
|
|
170792
170792
|
var init_template = () => {};
|
|
170793
170793
|
|
|
170794
|
-
// ../channel-whatsapp-
|
|
170794
|
+
// ../channel-whatsapp-business/src/senders/index.ts
|
|
170795
170795
|
var init_senders = __esm(() => {
|
|
170796
170796
|
init_text2();
|
|
170797
170797
|
init_media();
|
|
@@ -170803,7 +170803,7 @@ var init_senders = __esm(() => {
|
|
|
170803
170803
|
init_template();
|
|
170804
170804
|
});
|
|
170805
170805
|
|
|
170806
|
-
// ../channel-whatsapp-
|
|
170806
|
+
// ../channel-whatsapp-business/src/plugin.ts
|
|
170807
170807
|
async function dispatchOutbound2(client, message2, logger6) {
|
|
170808
170808
|
const { content, to, replyTo } = message2;
|
|
170809
170809
|
if (content.type === "text") {
|
|
@@ -170841,7 +170841,7 @@ async function dispatchOutbound2(client, message2, logger6) {
|
|
|
170841
170841
|
if (content.type === "flow") {
|
|
170842
170842
|
return dispatchOutboundFlow(client, message2);
|
|
170843
170843
|
}
|
|
170844
|
-
return { ok: false, error: `Unsupported content.type=${content.type} for whatsapp-
|
|
170844
|
+
return { ok: false, error: `Unsupported content.type=${content.type} for whatsapp-business` };
|
|
170845
170845
|
}
|
|
170846
170846
|
async function dispatchOutboundFlow(client, message2) {
|
|
170847
170847
|
const parsed = WhatsAppFlowSendSchema.safeParse(message2.metadata?.flow);
|
|
@@ -170864,7 +170864,7 @@ async function dispatchOutboundText(client, message2, logger6) {
|
|
|
170864
170864
|
}
|
|
170865
170865
|
const { response, droppedRows } = await sendInteractive(client, to, formatted, content.buttons, replyTo, content.list?.buttonLabel, { sectionTitle: content.list?.sectionTitle, forceList: content.list?.forceList });
|
|
170866
170866
|
if (droppedRows > 0) {
|
|
170867
|
-
logger6?.warn("[whatsapp-
|
|
170867
|
+
logger6?.warn("[whatsapp-business] interactive list capped at 10 rows \u2014 extra buttons dropped", { to, droppedRows });
|
|
170868
170868
|
}
|
|
170869
170869
|
return response;
|
|
170870
170870
|
}
|
|
@@ -171028,7 +171028,7 @@ function mapTemplateEventToStatus(event) {
|
|
|
171028
171028
|
return "PAUSED";
|
|
171029
171029
|
}
|
|
171030
171030
|
}
|
|
171031
|
-
var META_MEDIA_TYPES, downloadGuard7, MAX_TYPING_WAMID_CHATS = 1000,
|
|
171031
|
+
var META_MEDIA_TYPES, downloadGuard7, MAX_TYPING_WAMID_CHATS = 1000, WhatsAppBusinessPlugin, MEDIA_TYPE_MAP2;
|
|
171032
171032
|
var init_plugin = __esm(() => {
|
|
171033
171033
|
init_src2();
|
|
171034
171034
|
init_src();
|
|
@@ -171041,22 +171041,22 @@ var init_plugin = __esm(() => {
|
|
|
171041
171041
|
init_errors3();
|
|
171042
171042
|
META_MEDIA_TYPES = new Set(["image", "audio", "video", "document", "sticker"]);
|
|
171043
171043
|
downloadGuard7 = createDownloadGuard();
|
|
171044
|
-
|
|
171045
|
-
id = "whatsapp-
|
|
171046
|
-
name = "WhatsApp (Meta
|
|
171044
|
+
WhatsAppBusinessPlugin = class WhatsAppBusinessPlugin extends BaseChannelPlugin {
|
|
171045
|
+
id = "whatsapp-business";
|
|
171046
|
+
name = "WhatsApp Business API (Meta)";
|
|
171047
171047
|
version = "1.0.0";
|
|
171048
|
-
capabilities =
|
|
171049
|
-
|
|
171048
|
+
capabilities = WHATSAPP_BUSINESS_CAPABILITIES;
|
|
171049
|
+
waInstances = new Map;
|
|
171050
171050
|
byPhoneNumberId = new Map;
|
|
171051
171051
|
byWabaId = new Map;
|
|
171052
171052
|
async onInitialize(_context) {
|
|
171053
171053
|
this.logger.info("WhatsApp Cloud plugin initialized");
|
|
171054
171054
|
}
|
|
171055
171055
|
async onDestroy() {
|
|
171056
|
-
for (const [, state] of this.
|
|
171056
|
+
for (const [, state] of this.waInstances) {
|
|
171057
171057
|
state.dedupeCache.dispose();
|
|
171058
171058
|
}
|
|
171059
|
-
this.
|
|
171059
|
+
this.waInstances.clear();
|
|
171060
171060
|
this.byPhoneNumberId.clear();
|
|
171061
171061
|
this.byWabaId.clear();
|
|
171062
171062
|
this.logger.info("WhatsApp Cloud plugin destroyed");
|
|
@@ -171068,13 +171068,13 @@ var init_plugin = __esm(() => {
|
|
|
171068
171068
|
const phoneNumberId = creds.metaPhoneNumberId ?? opts.metaPhoneNumberId;
|
|
171069
171069
|
const wabaId = creds.metaWabaId ?? opts.metaWabaId;
|
|
171070
171070
|
if (!accessToken) {
|
|
171071
|
-
throw new MetaApiError(MetaErrorCode.AUTH_FAILED, "metaAccessToken is required to connect a whatsapp-
|
|
171071
|
+
throw new MetaApiError(MetaErrorCode.AUTH_FAILED, "metaAccessToken is required to connect a whatsapp-business instance");
|
|
171072
171072
|
}
|
|
171073
171073
|
if (!phoneNumberId) {
|
|
171074
|
-
throw new MetaApiError(MetaErrorCode.PHONE_NOT_FOUND, "metaPhoneNumberId is required to connect a whatsapp-
|
|
171074
|
+
throw new MetaApiError(MetaErrorCode.PHONE_NOT_FOUND, "metaPhoneNumberId is required to connect a whatsapp-business instance");
|
|
171075
171075
|
}
|
|
171076
171076
|
if (!wabaId) {
|
|
171077
|
-
throw new MetaApiError(MetaErrorCode.INVALID_REQUEST, "metaWabaId is required to connect a whatsapp-
|
|
171077
|
+
throw new MetaApiError(MetaErrorCode.INVALID_REQUEST, "metaWabaId is required to connect a whatsapp-business instance");
|
|
171078
171078
|
}
|
|
171079
171079
|
const apiVersion = creds.metaApiVersion ?? opts.metaApiVersion ?? "v25.0";
|
|
171080
171080
|
const appId = creds.metaAppId ?? opts.metaAppId;
|
|
@@ -171091,7 +171091,7 @@ var init_plugin = __esm(() => {
|
|
|
171091
171091
|
if (!reachable) {
|
|
171092
171092
|
throw new MetaApiError(MetaErrorCode.AUTH_FAILED, "Meta access token rejected or phone_number_id unreachable \u2014 check credentials", { operation: "connect" });
|
|
171093
171093
|
}
|
|
171094
|
-
const
|
|
171094
|
+
const businessConfig = {
|
|
171095
171095
|
accessToken,
|
|
171096
171096
|
phoneNumberId,
|
|
171097
171097
|
wabaId,
|
|
@@ -171103,7 +171103,7 @@ var init_plugin = __esm(() => {
|
|
|
171103
171103
|
};
|
|
171104
171104
|
const dedupeCache = createInboundDedupeCache();
|
|
171105
171105
|
const lastInboundWamid = new Map;
|
|
171106
|
-
this.
|
|
171106
|
+
this.waInstances.set(instanceId, { client, config: businessConfig, dedupeCache, lastInboundWamid });
|
|
171107
171107
|
this.byPhoneNumberId.set(phoneNumberId, instanceId);
|
|
171108
171108
|
let wabaSet = this.byWabaId.get(wabaId);
|
|
171109
171109
|
if (!wabaSet) {
|
|
@@ -171114,7 +171114,7 @@ var init_plugin = __esm(() => {
|
|
|
171114
171114
|
await this.updateInstanceStatus(instanceId, config2, {
|
|
171115
171115
|
state: "connected",
|
|
171116
171116
|
since: new Date,
|
|
171117
|
-
message: `Connected via
|
|
171117
|
+
message: `Connected via WhatsApp Business API (${connectionMethod})`
|
|
171118
171118
|
});
|
|
171119
171119
|
await this.emitInstanceConnected(instanceId, {
|
|
171120
171120
|
profileName: displayPhoneNumber ?? "WhatsApp Cloud",
|
|
@@ -171124,10 +171124,10 @@ var init_plugin = __esm(() => {
|
|
|
171124
171124
|
}
|
|
171125
171125
|
async disconnect(instanceId) {
|
|
171126
171126
|
this.logger.info("Disconnecting WhatsApp Cloud instance", { instanceId });
|
|
171127
|
-
const state = this.
|
|
171127
|
+
const state = this.waInstances.get(instanceId);
|
|
171128
171128
|
if (state) {
|
|
171129
171129
|
state.dedupeCache.dispose();
|
|
171130
|
-
this.
|
|
171130
|
+
this.waInstances.delete(instanceId);
|
|
171131
171131
|
this.byPhoneNumberId.delete(state.config.phoneNumberId);
|
|
171132
171132
|
const wabaSet = this.byWabaId.get(state.config.wabaId);
|
|
171133
171133
|
if (wabaSet) {
|
|
@@ -171144,7 +171144,7 @@ var init_plugin = __esm(() => {
|
|
|
171144
171144
|
await this.emitInstanceDisconnected(instanceId, "Manual disconnect");
|
|
171145
171145
|
}
|
|
171146
171146
|
async sendMessage(instanceId, message2) {
|
|
171147
|
-
const state = this.
|
|
171147
|
+
const state = this.waInstances.get(instanceId);
|
|
171148
171148
|
if (!state) {
|
|
171149
171149
|
return {
|
|
171150
171150
|
success: false,
|
|
@@ -171234,12 +171234,12 @@ var init_plugin = __esm(() => {
|
|
|
171234
171234
|
}
|
|
171235
171235
|
async getHealth(instanceId) {
|
|
171236
171236
|
const checks2 = [];
|
|
171237
|
-
const single = instanceId ? this.
|
|
171238
|
-
const states = instanceId ? single ? [[instanceId, single]] : [] : Array.from(this.
|
|
171237
|
+
const single = instanceId ? this.waInstances.get(instanceId) : undefined;
|
|
171238
|
+
const states = instanceId ? single ? [[instanceId, single]] : [] : Array.from(this.waInstances.entries());
|
|
171239
171239
|
for (const [id, state] of states) {
|
|
171240
171240
|
const ok2 = await state.client.ping();
|
|
171241
171241
|
checks2.push({
|
|
171242
|
-
name: `whatsapp-
|
|
171242
|
+
name: `whatsapp-business:${id}`,
|
|
171243
171243
|
status: ok2 ? "pass" : "fail",
|
|
171244
171244
|
message: ok2 ? `Phone ${state.config.phoneNumberId} reachable` : `Phone ${state.config.phoneNumberId} unreachable \u2014 token rejected or network error`
|
|
171245
171245
|
});
|
|
@@ -171264,12 +171264,12 @@ var init_plugin = __esm(() => {
|
|
|
171264
171264
|
async sendTyping(instanceId, chatId, duration) {
|
|
171265
171265
|
if (duration === 0)
|
|
171266
171266
|
return;
|
|
171267
|
-
const state = this.
|
|
171267
|
+
const state = this.waInstances.get(instanceId);
|
|
171268
171268
|
if (!state)
|
|
171269
171269
|
return;
|
|
171270
171270
|
const wamid = state.lastInboundWamid.get(toMetaPhone(chatId));
|
|
171271
171271
|
if (!wamid) {
|
|
171272
|
-
this.logger.debug("[whatsapp-
|
|
171272
|
+
this.logger.debug("[whatsapp-business] sendTyping skipped \u2014 no inbound wamid remembered for chat", {
|
|
171273
171273
|
instanceId,
|
|
171274
171274
|
chatId
|
|
171275
171275
|
});
|
|
@@ -171278,7 +171278,7 @@ var init_plugin = __esm(() => {
|
|
|
171278
171278
|
try {
|
|
171279
171279
|
await state.client.sendTypingIndicator(wamid);
|
|
171280
171280
|
} catch (err2) {
|
|
171281
|
-
this.logger.debug("[whatsapp-
|
|
171281
|
+
this.logger.debug("[whatsapp-business] sendTyping failed (best-effort, ignored)", {
|
|
171282
171282
|
instanceId,
|
|
171283
171283
|
chatId,
|
|
171284
171284
|
err: String(err2)
|
|
@@ -171286,7 +171286,7 @@ var init_plugin = __esm(() => {
|
|
|
171286
171286
|
}
|
|
171287
171287
|
}
|
|
171288
171288
|
rememberInboundWamid(instanceId, from, wamid) {
|
|
171289
|
-
const state = this.
|
|
171289
|
+
const state = this.waInstances.get(instanceId);
|
|
171290
171290
|
if (!state)
|
|
171291
171291
|
return;
|
|
171292
171292
|
const chatKey = toMetaPhone(from);
|
|
@@ -171305,14 +171305,14 @@ var init_plugin = __esm(() => {
|
|
|
171305
171305
|
downloadGuard7.checkSize(media.file_size, this.logger, {
|
|
171306
171306
|
instanceId,
|
|
171307
171307
|
url: media.url,
|
|
171308
|
-
channel: "whatsapp-
|
|
171308
|
+
channel: "whatsapp-business"
|
|
171309
171309
|
});
|
|
171310
171310
|
}
|
|
171311
171311
|
const bytes2 = await state.client.downloadMedia(media.url);
|
|
171312
171312
|
return { buffer: Buffer.from(bytes2), mimeType: media.mime_type };
|
|
171313
171313
|
}
|
|
171314
171314
|
requireInstanceState(instanceId, operation) {
|
|
171315
|
-
const state = this.
|
|
171315
|
+
const state = this.waInstances.get(instanceId);
|
|
171316
171316
|
if (!state) {
|
|
171317
171317
|
throw new MetaApiError(MetaErrorCode.NOT_CONNECTED, "WhatsApp Cloud instance not connected", {
|
|
171318
171318
|
operation
|
|
@@ -171321,16 +171321,16 @@ var init_plugin = __esm(() => {
|
|
|
171321
171321
|
return state;
|
|
171322
171322
|
}
|
|
171323
171323
|
getInstanceState(instanceId) {
|
|
171324
|
-
return this.
|
|
171324
|
+
return this.waInstances.get(instanceId);
|
|
171325
171325
|
}
|
|
171326
171326
|
getConnectedInstanceIds() {
|
|
171327
|
-
return Array.from(this.
|
|
171327
|
+
return Array.from(this.waInstances.keys());
|
|
171328
171328
|
}
|
|
171329
171329
|
findInstanceByPhoneNumberId(phoneNumberId) {
|
|
171330
171330
|
const id = this.byPhoneNumberId.get(phoneNumberId);
|
|
171331
171331
|
if (!id)
|
|
171332
171332
|
return;
|
|
171333
|
-
const state = this.
|
|
171333
|
+
const state = this.waInstances.get(id);
|
|
171334
171334
|
return state ? [id, state] : undefined;
|
|
171335
171335
|
}
|
|
171336
171336
|
findInstancesByWabaId(wabaId) {
|
|
@@ -171339,7 +171339,7 @@ var init_plugin = __esm(() => {
|
|
|
171339
171339
|
return [];
|
|
171340
171340
|
const matches = [];
|
|
171341
171341
|
for (const id of ids2) {
|
|
171342
|
-
const state = this.
|
|
171342
|
+
const state = this.waInstances.get(id);
|
|
171343
171343
|
if (state)
|
|
171344
171344
|
matches.push([id, state]);
|
|
171345
171345
|
}
|
|
@@ -171350,8 +171350,8 @@ var init_plugin = __esm(() => {
|
|
|
171350
171350
|
}
|
|
171351
171351
|
async handleInboundMessage(instanceId, msg, contacts, dedupeCache) {
|
|
171352
171352
|
const wamid = msg.id;
|
|
171353
|
-
if (dedupeCache.isDuplicate(instanceId, wamid, "whatsapp-
|
|
171354
|
-
this.logger.debug("[whatsapp-
|
|
171353
|
+
if (dedupeCache.isDuplicate(instanceId, wamid, "whatsapp-business", this.logger)) {
|
|
171354
|
+
this.logger.debug("[whatsapp-business] duplicate inbound dropped", { instanceId, wamid });
|
|
171355
171355
|
return false;
|
|
171356
171356
|
}
|
|
171357
171357
|
if (msg.type === "reaction") {
|
|
@@ -171361,7 +171361,7 @@ var init_plugin = __esm(() => {
|
|
|
171361
171361
|
this.rememberInboundWamid(instanceId, msg.from, wamid);
|
|
171362
171362
|
const content = extractInboundContent2(msg);
|
|
171363
171363
|
if (!content) {
|
|
171364
|
-
this.logger.warn("[whatsapp-
|
|
171364
|
+
this.logger.warn("[whatsapp-business] inbound message has no extractable content", {
|
|
171365
171365
|
instanceId,
|
|
171366
171366
|
wamid,
|
|
171367
171367
|
type: msg.type
|
|
@@ -171430,7 +171430,7 @@ var init_plugin = __esm(() => {
|
|
|
171430
171430
|
continue;
|
|
171431
171431
|
const sanitized = sanitizeMessage(value, this.logger, { instanceId, messageId: wamid });
|
|
171432
171432
|
if (!sanitized.ok) {
|
|
171433
|
-
this.logger.warn("[whatsapp-
|
|
171433
|
+
this.logger.warn("[whatsapp-business] inbound text rejected by sanitizer", {
|
|
171434
171434
|
instanceId,
|
|
171435
171435
|
wamid,
|
|
171436
171436
|
field,
|
|
@@ -171506,7 +171506,7 @@ var init_plugin = __esm(() => {
|
|
|
171506
171506
|
async handleTemplateStatusChanged(instanceId, update2, extras) {
|
|
171507
171507
|
const newStatus = mapTemplateEventToStatus(update2.event);
|
|
171508
171508
|
if (!newStatus) {
|
|
171509
|
-
this.logger.debug("[whatsapp-
|
|
171509
|
+
this.logger.debug("[whatsapp-business] unmapped template lifecycle event", {
|
|
171510
171510
|
instanceId,
|
|
171511
171511
|
event: update2.event,
|
|
171512
171512
|
metaTemplateId: update2.message_template_id
|
|
@@ -171539,7 +171539,7 @@ var init_plugin = __esm(() => {
|
|
|
171539
171539
|
};
|
|
171540
171540
|
});
|
|
171541
171541
|
|
|
171542
|
-
// ../channel-whatsapp-
|
|
171542
|
+
// ../channel-whatsapp-business/src/flows/demo-resolver.ts
|
|
171543
171543
|
function createDemoFlowResolver() {
|
|
171544
171544
|
return {
|
|
171545
171545
|
resolve(ctx) {
|
|
@@ -171566,7 +171566,7 @@ function createDemoFlowResolver() {
|
|
|
171566
171566
|
};
|
|
171567
171567
|
}
|
|
171568
171568
|
|
|
171569
|
-
// ../channel-whatsapp-
|
|
171569
|
+
// ../channel-whatsapp-business/src/oauth.ts
|
|
171570
171570
|
function graphBase(apiVersion = DEFAULT_META_API_VERSION) {
|
|
171571
171571
|
return `https://graph.facebook.com/${apiVersion}`;
|
|
171572
171572
|
}
|
|
@@ -171781,7 +171781,7 @@ var init_oauth = __esm(() => {
|
|
|
171781
171781
|
init_errors3();
|
|
171782
171782
|
});
|
|
171783
171783
|
|
|
171784
|
-
// ../channel-whatsapp-
|
|
171784
|
+
// ../channel-whatsapp-business/src/index.ts
|
|
171785
171785
|
var exports_src4 = {};
|
|
171786
171786
|
__export(exports_src4, {
|
|
171787
171787
|
uploadHeaderMedia: () => uploadHeaderMedia,
|
|
@@ -171807,8 +171807,8 @@ __export(exports_src4, {
|
|
|
171807
171807
|
createTemplate: () => createTemplate,
|
|
171808
171808
|
createDemoFlowResolver: () => createDemoFlowResolver,
|
|
171809
171809
|
buildFlowToken: () => buildFlowToken,
|
|
171810
|
-
|
|
171811
|
-
|
|
171810
|
+
WhatsAppBusinessPlugin: () => WhatsAppBusinessPlugin,
|
|
171811
|
+
WHATSAPP_BUSINESS_CAPABILITIES: () => WHATSAPP_BUSINESS_CAPABILITIES,
|
|
171812
171812
|
MetaWhatsAppClient: () => MetaWhatsAppClient,
|
|
171813
171813
|
MetaErrorCode: () => MetaErrorCode,
|
|
171814
171814
|
MetaApiError: () => MetaApiError,
|
|
@@ -171826,7 +171826,7 @@ var init_src6 = __esm(() => {
|
|
|
171826
171826
|
init_flow_crypto();
|
|
171827
171827
|
init_oauth();
|
|
171828
171828
|
init_errors3();
|
|
171829
|
-
plugin8 = new
|
|
171829
|
+
plugin8 = new WhatsAppBusinessPlugin;
|
|
171830
171830
|
src_default8 = plugin8;
|
|
171831
171831
|
});
|
|
171832
171832
|
|
|
@@ -242831,7 +242831,7 @@ var init_sentry_scrub = __esm(() => {
|
|
|
242831
242831
|
var require_package7 = __commonJS((exports, module) => {
|
|
242832
242832
|
module.exports = {
|
|
242833
242833
|
name: "@omni/api",
|
|
242834
|
-
version: "2.
|
|
242834
|
+
version: "2.260804.1",
|
|
242835
242835
|
type: "module",
|
|
242836
242836
|
exports: {
|
|
242837
242837
|
".": {
|
|
@@ -242864,7 +242864,7 @@ var require_package7 = __commonJS((exports, module) => {
|
|
|
242864
242864
|
"@hono/swagger-ui": "^0.4.1",
|
|
242865
242865
|
"@hono/zod-validator": "^0.4.3",
|
|
242866
242866
|
"@omni/channel-sdk": "workspace:*",
|
|
242867
|
-
"@omni/channel-whatsapp-
|
|
242867
|
+
"@omni/channel-whatsapp-business": "workspace:*",
|
|
242868
242868
|
"@omni/core": "workspace:*",
|
|
242869
242869
|
"@omni/db": "workspace:*",
|
|
242870
242870
|
"@omni/media-processing": "workspace:*",
|
|
@@ -293781,17 +293781,17 @@ var init_scopes = __esm(() => {
|
|
|
293781
293781
|
"POST /voice/leave": "voice:write",
|
|
293782
293782
|
"GET /voice/sessions": "voice:read",
|
|
293783
293783
|
"GET /voice/sessions/:id": "voice:read",
|
|
293784
|
-
"POST /instances/:id/whatsapp-
|
|
293785
|
-
"POST /instances/:id/whatsapp-
|
|
293786
|
-
"POST /instances/:id/whatsapp-
|
|
293787
|
-
"POST /instances/:id/whatsapp-
|
|
293788
|
-
"GET /instances/:id/whatsapp-
|
|
293789
|
-
"DELETE /instances/:id/whatsapp-
|
|
293790
|
-
"GET /instances/:id/whatsapp-
|
|
293791
|
-
"GET /instances/:id/whatsapp-
|
|
293792
|
-
"GET /instances/:id/whatsapp-
|
|
293793
|
-
"PUT /instances/:id/whatsapp-
|
|
293794
|
-
"POST /instances/:id/whatsapp-
|
|
293784
|
+
"POST /instances/:id/whatsapp-business/oauth/exchange": "instances:write",
|
|
293785
|
+
"POST /instances/:id/whatsapp-business/connect": "instances:write",
|
|
293786
|
+
"POST /instances/:id/whatsapp-business/register": "instances:write",
|
|
293787
|
+
"POST /instances/:id/whatsapp-business/subscribe-app": "instances:write",
|
|
293788
|
+
"GET /instances/:id/whatsapp-business/connection": "instances:read",
|
|
293789
|
+
"DELETE /instances/:id/whatsapp-business/connection": "instances:write",
|
|
293790
|
+
"GET /instances/:id/whatsapp-business/quality": "instances:read",
|
|
293791
|
+
"GET /instances/:id/whatsapp-business/analytics": "instances:read",
|
|
293792
|
+
"GET /instances/:id/whatsapp-business/profile": "instances:read",
|
|
293793
|
+
"PUT /instances/:id/whatsapp-business/profile": "instances:write",
|
|
293794
|
+
"POST /instances/:id/whatsapp-business/profile/photo": "instances:write",
|
|
293795
293795
|
"GET /instances/:id/whatsapp-flows": "instances:read",
|
|
293796
293796
|
"POST /instances/:id/whatsapp-flows": "instances:write",
|
|
293797
293797
|
"GET /instances/:id/whatsapp-flows/keys": "instances:read",
|
|
@@ -294310,19 +294310,39 @@ var init_route_ownership = __esm(() => {
|
|
|
294310
294310
|
justification: "Hermes (Mutant) gateway callback. Auth-exempt for Mutant's servers, which send no credential and no " + "signature \u2014 the Hermes API has no HMAC mechanism at all. Authenticity rests on two factors the handler " + "enforces: the per-instance path (an unguessable instance UUID, the Gupshup precedent) and a cross-check " + "of the payload media_id (the Hermes UUID of the WhatsApp line) against the hermes_media_id stored " + "server-side on that instance \u2014 a mismatch is dropped with a warn log. The tenant comes from the " + "server-side instance record addressed by the path, never from a body or header claim. Responses are " + "fixed 200 acks with no row data."
|
|
294311
294311
|
},
|
|
294312
294312
|
{
|
|
294313
|
-
route: "GET /api/v2/channels/whatsapp-
|
|
294313
|
+
route: "GET /api/v2/channels/whatsapp-business/webhook",
|
|
294314
294314
|
class: "public-by-contract",
|
|
294315
294315
|
justification: "Meta webhook verification challenge. Auth-exempt because Meta's servers send no credential; the handler " + "compares hub.verify_token against the server-held META_VERIFY_TOKEN and echoes back the hub.challenge " + "nonce Meta itself supplied. It reads no rows and reveals only whether the deployment-level verify token " + "matched \u2014 a configuration fact, not tenant data."
|
|
294316
294316
|
},
|
|
294317
294317
|
{
|
|
294318
|
-
route: "POST /api/v2/channels/whatsapp-
|
|
294318
|
+
route: "POST /api/v2/channels/whatsapp-business/webhook",
|
|
294319
294319
|
class: "public-by-contract",
|
|
294320
294320
|
justification: "Meta Cloud API callback. Auth-exempt for Meta's servers; authenticity is the X-Hub-Signature-256 HMAC the " + "plugin verifies against the server-held META_APP_SECRET over the raw body. The URL is global by Meta design " + "(one callback per app, no :instanceId segment) \u2014 the instance, and therefore the tenant, is resolved from " + "the server-side instance record matching the payload phone_number_id, never from a body or header tenant " + "claim. Responses are fixed acks (200/401) and carry no row data; unknown phone_number_id still acks 200 " + "so the surface is not a resource-existence oracle."
|
|
294321
294321
|
},
|
|
294322
294322
|
{
|
|
294323
|
-
route: "POST /api/v2/channels/whatsapp-
|
|
294323
|
+
route: "POST /api/v2/channels/whatsapp-business/flows/data/:instanceId",
|
|
294324
294324
|
class: "public-by-contract",
|
|
294325
294325
|
justification: "WhatsApp Flows data-exchange endpoint. Auth-exempt for Meta's servers; authenticity is double: the " + "X-Hub-Signature-256 HMAC verified against the server-held META_APP_SECRET over the raw body (432 on " + "mismatch), and RSA-OAEP payload encryption \u2014 only the private key registered for the :instanceId row can " + "decrypt the request (421 otherwise), so a forged path yields nothing. The tenant comes from the " + "server-side instance record addressed by the path (the Gupshup/Twilio per-instance precedent); the " + "private key is unsealed server-side via openCredentialField under that record\u2019s tenant. Responses are " + "AES-GCM-encrypted screen payloads readable only by the requesting WhatsApp client, or bare status codes " + "(404/421/427/432) that reveal no row data."
|
|
294326
|
+
},
|
|
294327
|
+
{
|
|
294328
|
+
route: "GET /api/v2/channels/whatsapp-cloud/webhook",
|
|
294329
|
+
class: "public-by-contract",
|
|
294330
|
+
justification: "Frozen legacy alias of GET /api/v2/channels/whatsapp-business/webhook (same handler reference, zero added " + "surface). See the canonical entry for the full contract justification."
|
|
294331
|
+
},
|
|
294332
|
+
{
|
|
294333
|
+
route: "POST /api/v2/channels/whatsapp-cloud/webhook",
|
|
294334
|
+
class: "public-by-contract",
|
|
294335
|
+
justification: "Frozen legacy alias of POST /api/v2/channels/whatsapp-business/webhook (same handler reference, zero added " + "surface). See the canonical entry for the full contract justification."
|
|
294336
|
+
},
|
|
294337
|
+
{
|
|
294338
|
+
route: "POST /api/v2/channels/whatsapp-cloud/flows/data/:instanceId",
|
|
294339
|
+
class: "public-by-contract",
|
|
294340
|
+
justification: "Frozen legacy alias of POST /api/v2/channels/whatsapp-business/flows/data/:instanceId (same handler " + "reference, zero added surface). Pre-rename flows carry this path in their Meta-side endpoint_uri."
|
|
294341
|
+
},
|
|
294342
|
+
{
|
|
294343
|
+
route: "ALL /api/v2/instances/:instanceId/whatsapp-cloud/*",
|
|
294344
|
+
class: "public-by-contract",
|
|
294345
|
+
justification: "Legacy REST alias: rewrites the path segment to /whatsapp-business/ and re-dispatches through the full " + "pipeline \u2014 the INNER canonical route enforces auth, scopes and ownership; this catch-all only rewrites the " + "URL and can serve nothing by itself. Kept permanently for pre-rename API consumers."
|
|
294326
294346
|
}
|
|
294327
294347
|
];
|
|
294328
294348
|
PLATFORM_ADMIN_JUSTIFICATION = "ADR-0005 platform tenant lifecycle. Requires a platform-class credential; a tenant-class credential " + "cannot reach this surface at all, and per-tenant data access from it goes through the same forced-RLS " + "boundary bound to ONE audited target tenant (platform-target-tenant.ts).";
|
|
@@ -294356,7 +294376,7 @@ var init_route_ownership = __esm(() => {
|
|
|
294356
294376
|
"DELETE /api/v2/instances/:id/block",
|
|
294357
294377
|
"DELETE /api/v2/instances/:id/guilds/:guildId/config",
|
|
294358
294378
|
"DELETE /api/v2/instances/:id/profile/picture",
|
|
294359
|
-
"DELETE /api/v2/instances/:id/whatsapp-
|
|
294379
|
+
"DELETE /api/v2/instances/:id/whatsapp-business/connection",
|
|
294360
294380
|
"DELETE /api/v2/instances/:id/whatsapp-templates/:templateId",
|
|
294361
294381
|
"DELETE /api/v2/instances/:instanceId/routes/:id",
|
|
294362
294382
|
"DELETE /api/v2/messages/:id",
|
|
@@ -294437,10 +294457,10 @@ var init_route_ownership = __esm(() => {
|
|
|
294437
294457
|
"GET /api/v2/instances/:id/sync",
|
|
294438
294458
|
"GET /api/v2/instances/:id/sync/:jobId",
|
|
294439
294459
|
"GET /api/v2/instances/:id/users/:userId/profile",
|
|
294440
|
-
"GET /api/v2/instances/:id/whatsapp-
|
|
294441
|
-
"GET /api/v2/instances/:id/whatsapp-
|
|
294442
|
-
"GET /api/v2/instances/:id/whatsapp-
|
|
294443
|
-
"GET /api/v2/instances/:id/whatsapp-
|
|
294460
|
+
"GET /api/v2/instances/:id/whatsapp-business/analytics",
|
|
294461
|
+
"GET /api/v2/instances/:id/whatsapp-business/connection",
|
|
294462
|
+
"GET /api/v2/instances/:id/whatsapp-business/profile",
|
|
294463
|
+
"GET /api/v2/instances/:id/whatsapp-business/quality",
|
|
294444
294464
|
"GET /api/v2/instances/:id/whatsapp-flows",
|
|
294445
294465
|
"GET /api/v2/instances/:id/whatsapp-flows/:flowId",
|
|
294446
294466
|
"GET /api/v2/instances/:id/whatsapp-flows/:flowId/preview",
|
|
@@ -294570,11 +294590,11 @@ var init_route_ownership = __esm(() => {
|
|
|
294570
294590
|
"POST /api/v2/instances/:id/resync",
|
|
294571
294591
|
"POST /api/v2/instances/:id/sync",
|
|
294572
294592
|
"POST /api/v2/instances/:id/sync/profile",
|
|
294573
|
-
"POST /api/v2/instances/:id/whatsapp-
|
|
294574
|
-
"POST /api/v2/instances/:id/whatsapp-
|
|
294575
|
-
"POST /api/v2/instances/:id/whatsapp-
|
|
294576
|
-
"POST /api/v2/instances/:id/whatsapp-
|
|
294577
|
-
"POST /api/v2/instances/:id/whatsapp-
|
|
294593
|
+
"POST /api/v2/instances/:id/whatsapp-business/connect",
|
|
294594
|
+
"POST /api/v2/instances/:id/whatsapp-business/oauth/exchange",
|
|
294595
|
+
"POST /api/v2/instances/:id/whatsapp-business/profile/photo",
|
|
294596
|
+
"POST /api/v2/instances/:id/whatsapp-business/register",
|
|
294597
|
+
"POST /api/v2/instances/:id/whatsapp-business/subscribe-app",
|
|
294578
294598
|
"POST /api/v2/instances/:id/whatsapp-flows",
|
|
294579
294599
|
"POST /api/v2/instances/:id/whatsapp-flows/:flowId/deprecate",
|
|
294580
294600
|
"POST /api/v2/instances/:id/whatsapp-flows/:flowId/publish",
|
|
@@ -294636,7 +294656,7 @@ var init_route_ownership = __esm(() => {
|
|
|
294636
294656
|
"PUT /api/v2/instances/:id/presence",
|
|
294637
294657
|
"PUT /api/v2/instances/:id/profile/name",
|
|
294638
294658
|
"PUT /api/v2/instances/:id/profile/picture",
|
|
294639
|
-
"PUT /api/v2/instances/:id/whatsapp-
|
|
294659
|
+
"PUT /api/v2/instances/:id/whatsapp-business/profile",
|
|
294640
294660
|
"PUT /api/v2/instances/:id/whatsapp-flows/:flowId",
|
|
294641
294661
|
"PUT /api/v2/instances/:id/profile/status",
|
|
294642
294662
|
"PUT /api/v2/payload-config/:eventType",
|
|
@@ -347453,7 +347473,7 @@ function channelToKhalSessionSegment(channel5) {
|
|
|
347453
347473
|
return;
|
|
347454
347474
|
if (channel5 === "whatsapp-gupshup")
|
|
347455
347475
|
return "gupshup";
|
|
347456
|
-
if (channel5 === "whatsapp-
|
|
347476
|
+
if (channel5 === "whatsapp-business")
|
|
347457
347477
|
return "whatsapp";
|
|
347458
347478
|
if (channel5 === "whatsapp-baileys")
|
|
347459
347479
|
return "whatsapp";
|
|
@@ -349246,7 +349266,7 @@ function whatsappChatType(chatId) {
|
|
|
349246
349266
|
return "dm";
|
|
349247
349267
|
}
|
|
349248
349268
|
function determineChatType(chatId, channel5, rawPayload) {
|
|
349249
|
-
if (channel5 === "whatsapp" || channel5 === "whatsapp-baileys" || channel5 === "whatsapp-
|
|
349269
|
+
if (channel5 === "whatsapp" || channel5 === "whatsapp-baileys" || channel5 === "whatsapp-business" || channel5 === "twilio-whatsapp") {
|
|
349250
349270
|
return whatsappChatType(chatId);
|
|
349251
349271
|
}
|
|
349252
349272
|
if (channel5 === "telegram") {
|
|
@@ -352290,7 +352310,7 @@ var init_agent_dispatcher = __esm(() => {
|
|
|
352290
352310
|
CHANNEL_MESSAGE_LIMITS = {
|
|
352291
352311
|
discord: 2000,
|
|
352292
352312
|
"whatsapp-baileys": 65536,
|
|
352293
|
-
"whatsapp-
|
|
352313
|
+
"whatsapp-business": 65536,
|
|
352294
352314
|
"twilio-whatsapp": 1600,
|
|
352295
352315
|
slack: 40000,
|
|
352296
352316
|
telegram: 4096
|
|
@@ -361143,7 +361163,7 @@ function registerWhatsappFlowsSchemas(registry4) {
|
|
|
361143
361163
|
}
|
|
361144
361164
|
},
|
|
361145
361165
|
400: {
|
|
361146
|
-
description: "Not a whatsapp-
|
|
361166
|
+
description: "Not a whatsapp-business instance / not connected",
|
|
361147
361167
|
content: { "application/json": { schema: ErrorSchema } }
|
|
361148
361168
|
}
|
|
361149
361169
|
}
|
|
@@ -365951,6 +365971,18 @@ function applyTwilioWhatsAppConnectionOptions(options, input) {
|
|
|
365951
365971
|
options.twilioValidateSignature = input.twilioValidateSignature;
|
|
365952
365972
|
}
|
|
365953
365973
|
}
|
|
365974
|
+
function applyHermesConnectionOptions(options, input) {
|
|
365975
|
+
if (input.hermesBaseUrl)
|
|
365976
|
+
options.hermesBaseUrl = input.hermesBaseUrl;
|
|
365977
|
+
if (input.hermesUsername)
|
|
365978
|
+
options.hermesUsername = input.hermesUsername;
|
|
365979
|
+
if (input.hermesPassword)
|
|
365980
|
+
options.hermesPassword = input.hermesPassword;
|
|
365981
|
+
if (input.hermesMediaId)
|
|
365982
|
+
options.hermesMediaId = input.hermesMediaId;
|
|
365983
|
+
if (input.hermesTemplateNamespace)
|
|
365984
|
+
options.hermesTemplateNamespace = input.hermesTemplateNamespace;
|
|
365985
|
+
}
|
|
365954
365986
|
function applyChannelSpecificConnectionOptions(options, input) {
|
|
365955
365987
|
switch (input.channel) {
|
|
365956
365988
|
case "telegram":
|
|
@@ -365965,6 +365997,9 @@ function applyChannelSpecificConnectionOptions(options, input) {
|
|
|
365965
365997
|
case "twilio-whatsapp":
|
|
365966
365998
|
applyTwilioWhatsAppConnectionOptions(options, input);
|
|
365967
365999
|
return;
|
|
366000
|
+
case "hermes":
|
|
366001
|
+
applyHermesConnectionOptions(options, input);
|
|
366002
|
+
return;
|
|
365968
366003
|
}
|
|
365969
366004
|
}
|
|
365970
366005
|
function buildInstanceConnectionOptions(input) {
|
|
@@ -366093,7 +366128,12 @@ function buildConnectConnectionOptions(instance4, body, forceNewQr) {
|
|
|
366093
366128
|
twilioMessagingServiceSid: body.twilioMessagingServiceSid ?? instance4.twilioMessagingServiceSid,
|
|
366094
366129
|
twilioStatusCallbackUrl: body.twilioStatusCallbackUrl ?? instance4.twilioStatusCallbackUrl,
|
|
366095
366130
|
twilioWebhookUrl: body.twilioWebhookUrl ?? instance4.twilioWebhookUrl,
|
|
366096
|
-
twilioValidateSignature: body.twilioValidateSignature ?? instance4.twilioValidateSignature
|
|
366131
|
+
twilioValidateSignature: body.twilioValidateSignature ?? instance4.twilioValidateSignature,
|
|
366132
|
+
hermesBaseUrl: body.hermesBaseUrl ?? instance4.hermesBaseUrl,
|
|
366133
|
+
hermesUsername: body.hermesUsername ?? instance4.hermesUsername,
|
|
366134
|
+
hermesPassword: body.hermesPassword ?? instance4.hermesPassword,
|
|
366135
|
+
hermesMediaId: body.hermesMediaId ?? instance4.hermesMediaId,
|
|
366136
|
+
hermesTemplateNamespace: body.hermesTemplateNamespace ?? instance4.hermesTemplateNamespace
|
|
366097
366137
|
});
|
|
366098
366138
|
}
|
|
366099
366139
|
function hydrateConnectionOptionsForInstance(plugin10, instance4, options) {
|
|
@@ -366115,17 +366155,28 @@ function buildConnectPersistUpdates(instance4, body) {
|
|
|
366115
366155
|
isActive: true,
|
|
366116
366156
|
...buildTokenPersistUpdates(instance4.channel, body)
|
|
366117
366157
|
};
|
|
366118
|
-
if (instance4.channel
|
|
366119
|
-
return
|
|
366120
|
-
|
|
366121
|
-
|
|
366122
|
-
|
|
366123
|
-
|
|
366124
|
-
|
|
366125
|
-
|
|
366126
|
-
|
|
366127
|
-
|
|
366128
|
-
}
|
|
366158
|
+
if (instance4.channel === "twilio-whatsapp") {
|
|
366159
|
+
return {
|
|
366160
|
+
...updates,
|
|
366161
|
+
twilioAccountSid: body.twilioAccountSid ?? instance4.twilioAccountSid,
|
|
366162
|
+
twilioFrom: body.twilioFrom ?? instance4.twilioFrom,
|
|
366163
|
+
twilioMessagingServiceSid: body.twilioMessagingServiceSid ?? instance4.twilioMessagingServiceSid,
|
|
366164
|
+
twilioStatusCallbackUrl: body.twilioStatusCallbackUrl ?? instance4.twilioStatusCallbackUrl,
|
|
366165
|
+
twilioWebhookUrl: body.twilioWebhookUrl ?? instance4.twilioWebhookUrl,
|
|
366166
|
+
twilioValidateSignature: body.twilioValidateSignature ?? instance4.twilioValidateSignature
|
|
366167
|
+
};
|
|
366168
|
+
}
|
|
366169
|
+
if (instance4.channel === "hermes") {
|
|
366170
|
+
return {
|
|
366171
|
+
...updates,
|
|
366172
|
+
hermesBaseUrl: body.hermesBaseUrl ?? instance4.hermesBaseUrl,
|
|
366173
|
+
hermesUsername: body.hermesUsername ?? instance4.hermesUsername,
|
|
366174
|
+
hermesPassword: body.hermesPassword ?? instance4.hermesPassword,
|
|
366175
|
+
hermesMediaId: body.hermesMediaId ?? instance4.hermesMediaId,
|
|
366176
|
+
hermesTemplateNamespace: body.hermesTemplateNamespace ?? instance4.hermesTemplateNamespace
|
|
366177
|
+
};
|
|
366178
|
+
}
|
|
366179
|
+
return updates;
|
|
366129
366180
|
}
|
|
366130
366181
|
async function validateMessageSyncPreconditions(services, instanceId, channel5, type, chatJids) {
|
|
366131
366182
|
if (chatJids?.length && !channel5.startsWith("whatsapp")) {
|
|
@@ -366304,6 +366355,11 @@ var init_instances3 = __esm(() => {
|
|
|
366304
366355
|
twilioStatusCallbackUrl: exports_external.string().optional().nullable().describe("Twilio outbound status callback URL"),
|
|
366305
366356
|
twilioWebhookUrl: exports_external.string().optional().nullable().describe("Public Twilio inbound webhook URL for signature validation"),
|
|
366306
366357
|
twilioValidateSignature: exports_external.boolean().default(true).describe("Validate X-Twilio-Signature on webhooks"),
|
|
366358
|
+
hermesBaseUrl: exports_external.string().optional().nullable().describe("Hermes API base URL (e.g. https://waap-api.h3rmes.com)"),
|
|
366359
|
+
hermesUsername: exports_external.string().optional().nullable().describe("Hermes account username"),
|
|
366360
|
+
hermesPassword: exports_external.string().optional().nullable().describe("Hermes account password"),
|
|
366361
|
+
hermesMediaId: exports_external.string().optional().nullable().describe("Hermes line UUID (media_id) \u2014 required on every send"),
|
|
366362
|
+
hermesTemplateNamespace: exports_external.string().optional().nullable().describe("Meta template namespace for HSM sends"),
|
|
366307
366363
|
readReceipts: exports_external.enum(["on", "off", "exclude-self"]).default("on").describe("Read receipt mode: on (default), off, or exclude-self (skip receipts for the instance own number)"),
|
|
366308
366364
|
groupHistorySize: exports_external.number().int().min(0).max(200).default(50).describe("Number of context messages to include when dispatching to agent. Groups use the full value; DMs are capped at 20. (0 = disabled, max 200)"),
|
|
366309
366365
|
markOnlineOnConnect: exports_external.boolean().default(true).describe("Mark the instance as online when connecting to WhatsApp (default: true). Set to false to preserve phone push notifications."),
|
|
@@ -366361,7 +366417,8 @@ var init_instances3 = __esm(() => {
|
|
|
366361
366417
|
"slackSigningSecret",
|
|
366362
366418
|
"gupshupAuthToken",
|
|
366363
366419
|
"webhookVerifyToken",
|
|
366364
|
-
"twilioAuthToken"
|
|
366420
|
+
"twilioAuthToken",
|
|
366421
|
+
"hermesPassword"
|
|
366365
366422
|
];
|
|
366366
366423
|
instancesRoutes.get("/", zValidator("query", listQuerySchema12), async (c) => {
|
|
366367
366424
|
const { channel: channel5, status, limit: limit2, cursor } = c.req.valid("query");
|
|
@@ -366391,7 +366448,7 @@ var init_instances3 = __esm(() => {
|
|
|
366391
366448
|
const loadedIds = new Set(loadedPlugins.map((p2) => p2.id));
|
|
366392
366449
|
const staticChannels = [
|
|
366393
366450
|
{
|
|
366394
|
-
id: "whatsapp-
|
|
366451
|
+
id: "whatsapp-business",
|
|
366395
366452
|
name: "WhatsApp Business Cloud",
|
|
366396
366453
|
description: "Official WhatsApp Business API",
|
|
366397
366454
|
loaded: false
|
|
@@ -366459,7 +366516,12 @@ var init_instances3 = __esm(() => {
|
|
|
366459
366516
|
twilioMessagingServiceSid: instance4.twilioMessagingServiceSid,
|
|
366460
366517
|
twilioStatusCallbackUrl: instance4.twilioStatusCallbackUrl,
|
|
366461
366518
|
twilioWebhookUrl: instance4.twilioWebhookUrl,
|
|
366462
|
-
twilioValidateSignature: instance4.twilioValidateSignature
|
|
366519
|
+
twilioValidateSignature: instance4.twilioValidateSignature,
|
|
366520
|
+
hermesBaseUrl: instance4.hermesBaseUrl,
|
|
366521
|
+
hermesUsername: instance4.hermesUsername,
|
|
366522
|
+
hermesPassword: instance4.hermesPassword,
|
|
366523
|
+
hermesMediaId: instance4.hermesMediaId,
|
|
366524
|
+
hermesTemplateNamespace: instance4.hermesTemplateNamespace
|
|
366463
366525
|
});
|
|
366464
366526
|
const createPlugin = getPluginFromRegistry(channelRegistry2, data.channel);
|
|
366465
366527
|
if (createPlugin && "loadGuildConfigs" in createPlugin && instance4.guildConfigOverrides) {
|
|
@@ -366638,6 +366700,11 @@ var init_instances3 = __esm(() => {
|
|
|
366638
366700
|
twilioStatusCallbackUrl: exports_external.string().optional().describe("Twilio outbound status callback URL"),
|
|
366639
366701
|
twilioWebhookUrl: exports_external.string().optional().describe("Public Twilio inbound webhook URL for signature validation"),
|
|
366640
366702
|
twilioValidateSignature: exports_external.boolean().optional().describe("Validate X-Twilio-Signature on webhooks"),
|
|
366703
|
+
hermesBaseUrl: exports_external.string().optional().describe("Hermes API base URL"),
|
|
366704
|
+
hermesUsername: exports_external.string().optional().describe("Hermes account username"),
|
|
366705
|
+
hermesPassword: exports_external.string().optional().describe("Hermes account password"),
|
|
366706
|
+
hermesMediaId: exports_external.string().optional().describe("Hermes line UUID (media_id)"),
|
|
366707
|
+
hermesTemplateNamespace: exports_external.string().optional().describe("Meta template namespace for HSM sends"),
|
|
366641
366708
|
whatsapp: exports_external.object({
|
|
366642
366709
|
syncFullHistory: exports_external.boolean().optional().describe("Sync full message history on connect (default: true)")
|
|
366643
366710
|
}).optional().describe("WhatsApp-specific connection options")
|
|
@@ -372214,7 +372281,7 @@ var init_templates3 = __esm(() => {
|
|
|
372214
372281
|
});
|
|
372215
372282
|
return c.json({ data: persisted.row }, persisted.created ? 201 : 200);
|
|
372216
372283
|
} catch (dbErr) {
|
|
372217
|
-
log118.error("[whatsapp-
|
|
372284
|
+
log118.error("[whatsapp-business] local template mirror failed after Meta create", {
|
|
372218
372285
|
instanceId,
|
|
372219
372286
|
metaTemplateId: result.id,
|
|
372220
372287
|
name: body.name,
|
|
@@ -372844,7 +372911,7 @@ var init_oauth_token_cache = __esm(() => {
|
|
|
372844
372911
|
store = new Map;
|
|
372845
372912
|
});
|
|
372846
372913
|
|
|
372847
|
-
// ../api/src/routes/v2/whatsapp-
|
|
372914
|
+
// ../api/src/routes/v2/whatsapp-business.ts
|
|
372848
372915
|
function readMetaAppEnv() {
|
|
372849
372916
|
return {
|
|
372850
372917
|
appId: process.env.META_APP_ID,
|
|
@@ -372852,14 +372919,14 @@ function readMetaAppEnv() {
|
|
|
372852
372919
|
apiVersion: process.env.META_GRAPH_API_VERSION ?? "v25.0"
|
|
372853
372920
|
};
|
|
372854
372921
|
}
|
|
372855
|
-
function
|
|
372856
|
-
if (instance4.channel !== "whatsapp-
|
|
372922
|
+
function ensureWhatsAppBusiness(instance4) {
|
|
372923
|
+
if (instance4.channel !== "whatsapp-business") {
|
|
372857
372924
|
return {
|
|
372858
372925
|
ok: false,
|
|
372859
372926
|
payload: {
|
|
372860
372927
|
error: {
|
|
372861
372928
|
code: "WRONG_CHANNEL",
|
|
372862
|
-
message: `Instance channel is "${instance4.channel}", expected "whatsapp-
|
|
372929
|
+
message: `Instance channel is "${instance4.channel}", expected "whatsapp-business"`
|
|
372863
372930
|
}
|
|
372864
372931
|
}
|
|
372865
372932
|
};
|
|
@@ -372895,8 +372962,8 @@ async function readProfilePhotoUpload(c) {
|
|
|
372895
372962
|
fileType: blob.type || "image/jpeg"
|
|
372896
372963
|
};
|
|
372897
372964
|
}
|
|
372898
|
-
var log119,
|
|
372899
|
-
var
|
|
372965
|
+
var log119, whatsappBusinessRoutes, instanceAccess4, analyticsQuerySchema2, updateProfileSchema;
|
|
372966
|
+
var init_whatsapp_business3 = __esm(() => {
|
|
372900
372967
|
init_dist6();
|
|
372901
372968
|
init_src6();
|
|
372902
372969
|
init_src();
|
|
@@ -372905,11 +372972,11 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
372905
372972
|
init_zod();
|
|
372906
372973
|
init_oauth_token_cache();
|
|
372907
372974
|
init_auth();
|
|
372908
|
-
log119 = createLogger("api:whatsapp-
|
|
372909
|
-
|
|
372975
|
+
log119 = createLogger("api:whatsapp-business");
|
|
372976
|
+
whatsappBusinessRoutes = new Hono2;
|
|
372910
372977
|
instanceAccess4 = requireInstanceAccess((c) => c.req.param("id") ?? "");
|
|
372911
|
-
|
|
372912
|
-
|
|
372978
|
+
whatsappBusinessRoutes.use("/:id/whatsapp-business/*", instanceAccess4);
|
|
372979
|
+
whatsappBusinessRoutes.post("/:id/whatsapp-business/oauth/exchange", zValidator("json", EmbeddedSignupExchangeRequestSchema), async (c) => {
|
|
372913
372980
|
const { code } = c.req.valid("json");
|
|
372914
372981
|
const { appId, appSecret, apiVersion } = readMetaAppEnv();
|
|
372915
372982
|
if (!appId || !appSecret) {
|
|
@@ -372935,14 +373002,14 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
372935
373002
|
return c.json({ error: { code: "OAUTH_EXCHANGE_FAILED", message: message2 } }, 400);
|
|
372936
373003
|
}
|
|
372937
373004
|
});
|
|
372938
|
-
|
|
373005
|
+
whatsappBusinessRoutes.post("/:id/whatsapp-business/connect", zValidator("json", WhatsAppBusinessConnectRequestSchema), async (c) => {
|
|
372939
373006
|
const id = c.req.param("id");
|
|
372940
373007
|
const body = c.req.valid("json");
|
|
372941
373008
|
const services = c.get("services");
|
|
372942
373009
|
const channelRegistry2 = c.get("channelRegistry");
|
|
372943
373010
|
const { apiVersion } = readMetaAppEnv();
|
|
372944
373011
|
const instance4 = await services.instances.getById(id);
|
|
372945
|
-
const guard =
|
|
373012
|
+
const guard = ensureWhatsAppBusiness(instance4);
|
|
372946
373013
|
if (!guard.ok)
|
|
372947
373014
|
return c.json(guard.payload, 400);
|
|
372948
373015
|
let accessToken;
|
|
@@ -372996,9 +373063,9 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
372996
373063
|
error: err2 instanceof Error ? err2.message : String(err2)
|
|
372997
373064
|
});
|
|
372998
373065
|
}
|
|
372999
|
-
const plugin10 = channelRegistry2?.get("whatsapp-
|
|
373066
|
+
const plugin10 = channelRegistry2?.get("whatsapp-business");
|
|
373000
373067
|
if (!plugin10) {
|
|
373001
|
-
return c.json({ error: { code: "PLUGIN_NOT_FOUND", message: "whatsapp-
|
|
373068
|
+
return c.json({ error: { code: "PLUGIN_NOT_FOUND", message: "whatsapp-business plugin not registered" } }, 500);
|
|
373002
373069
|
}
|
|
373003
373070
|
try {
|
|
373004
373071
|
await plugin10.connect(id, {
|
|
@@ -373017,7 +373084,7 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
373017
373084
|
});
|
|
373018
373085
|
} catch (err2) {
|
|
373019
373086
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
373020
|
-
log119.error("plugin.connect failed for whatsapp-
|
|
373087
|
+
log119.error("plugin.connect failed for whatsapp-business", { instanceId: id, error: message2 });
|
|
373021
373088
|
return c.json({ error: { code: "CONNECT_FAILED", message: message2 } }, 500);
|
|
373022
373089
|
}
|
|
373023
373090
|
return c.json({
|
|
@@ -373029,12 +373096,12 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
373029
373096
|
}
|
|
373030
373097
|
});
|
|
373031
373098
|
});
|
|
373032
|
-
|
|
373099
|
+
whatsappBusinessRoutes.post("/:id/whatsapp-business/register", zValidator("json", WhatsAppBusinessRegisterRequestSchema), async (c) => {
|
|
373033
373100
|
const id = c.req.param("id");
|
|
373034
373101
|
const services = c.get("services");
|
|
373035
373102
|
const { pin } = c.req.valid("json");
|
|
373036
373103
|
const instance4 = await services.instances.getById(id);
|
|
373037
|
-
const guard =
|
|
373104
|
+
const guard = ensureWhatsAppBusiness(instance4);
|
|
373038
373105
|
if (!guard.ok)
|
|
373039
373106
|
return c.json(guard.payload, 400);
|
|
373040
373107
|
if (!instance4.metaAccessToken || !instance4.metaPhoneNumberId) {
|
|
@@ -373049,11 +373116,11 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
373049
373116
|
return c.json({ error: { code: "REGISTER_FAILED", message: message2 } }, 500);
|
|
373050
373117
|
}
|
|
373051
373118
|
});
|
|
373052
|
-
|
|
373119
|
+
whatsappBusinessRoutes.post("/:id/whatsapp-business/subscribe-app", async (c) => {
|
|
373053
373120
|
const id = c.req.param("id");
|
|
373054
373121
|
const services = c.get("services");
|
|
373055
373122
|
const instance4 = await services.instances.getById(id);
|
|
373056
|
-
const guard =
|
|
373123
|
+
const guard = ensureWhatsAppBusiness(instance4);
|
|
373057
373124
|
if (!guard.ok)
|
|
373058
373125
|
return c.json(guard.payload, 400);
|
|
373059
373126
|
if (!instance4.metaAccessToken || !instance4.metaWabaId) {
|
|
@@ -373068,11 +373135,11 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
373068
373135
|
return c.json({ error: { code: "SUBSCRIBE_FAILED", message: message2 } }, 500);
|
|
373069
373136
|
}
|
|
373070
373137
|
});
|
|
373071
|
-
|
|
373138
|
+
whatsappBusinessRoutes.get("/:id/whatsapp-business/connection", async (c) => {
|
|
373072
373139
|
const id = c.req.param("id");
|
|
373073
373140
|
const services = c.get("services");
|
|
373074
373141
|
const instance4 = await services.instances.getById(id);
|
|
373075
|
-
const guard =
|
|
373142
|
+
const guard = ensureWhatsAppBusiness(instance4);
|
|
373076
373143
|
if (!guard.ok)
|
|
373077
373144
|
return c.json(guard.payload, 400);
|
|
373078
373145
|
return c.json({
|
|
@@ -373089,15 +373156,15 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
373089
373156
|
}
|
|
373090
373157
|
});
|
|
373091
373158
|
});
|
|
373092
|
-
|
|
373159
|
+
whatsappBusinessRoutes.delete("/:id/whatsapp-business/connection", async (c) => {
|
|
373093
373160
|
const id = c.req.param("id");
|
|
373094
373161
|
const services = c.get("services");
|
|
373095
373162
|
const channelRegistry2 = c.get("channelRegistry");
|
|
373096
373163
|
const instance4 = await services.instances.getById(id);
|
|
373097
|
-
const guard =
|
|
373164
|
+
const guard = ensureWhatsAppBusiness(instance4);
|
|
373098
373165
|
if (!guard.ok)
|
|
373099
373166
|
return c.json(guard.payload, 400);
|
|
373100
|
-
const plugin10 = channelRegistry2?.get("whatsapp-
|
|
373167
|
+
const plugin10 = channelRegistry2?.get("whatsapp-business");
|
|
373101
373168
|
if (plugin10) {
|
|
373102
373169
|
try {
|
|
373103
373170
|
await plugin10.disconnect(id);
|
|
@@ -373122,11 +373189,11 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
373122
373189
|
});
|
|
373123
373190
|
return c.json({ success: true });
|
|
373124
373191
|
});
|
|
373125
|
-
|
|
373192
|
+
whatsappBusinessRoutes.get("/:id/whatsapp-business/quality", async (c) => {
|
|
373126
373193
|
const id = c.req.param("id");
|
|
373127
373194
|
const services = c.get("services");
|
|
373128
373195
|
const instance4 = await services.instances.getById(id);
|
|
373129
|
-
const guard =
|
|
373196
|
+
const guard = ensureWhatsAppBusiness(instance4);
|
|
373130
373197
|
if (!guard.ok)
|
|
373131
373198
|
return c.json(guard.payload, 400);
|
|
373132
373199
|
const client = buildClientFromInstance(instance4);
|
|
@@ -373145,12 +373212,12 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
373145
373212
|
end: exports_external.coerce.number().int().optional().describe("Unix timestamp (seconds) \u2014 end of range"),
|
|
373146
373213
|
granularity: exports_external.enum(["HALF_HOUR", "DAY", "MONTH"]).default("DAY")
|
|
373147
373214
|
});
|
|
373148
|
-
|
|
373215
|
+
whatsappBusinessRoutes.get("/:id/whatsapp-business/analytics", zValidator("query", analyticsQuerySchema2), async (c) => {
|
|
373149
373216
|
const id = c.req.param("id");
|
|
373150
373217
|
const services = c.get("services");
|
|
373151
373218
|
const { start, end, granularity } = c.req.valid("query");
|
|
373152
373219
|
const instance4 = await services.instances.getById(id);
|
|
373153
|
-
const guard =
|
|
373220
|
+
const guard = ensureWhatsAppBusiness(instance4);
|
|
373154
373221
|
if (!guard.ok)
|
|
373155
373222
|
return c.json(guard.payload, 400);
|
|
373156
373223
|
if (!instance4.metaAccessToken || !instance4.metaWabaId) {
|
|
@@ -373183,11 +373250,11 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
373183
373250
|
return c.json({ error: { code: "ANALYTICS_FETCH_FAILED", message: message2 } }, 500);
|
|
373184
373251
|
}
|
|
373185
373252
|
});
|
|
373186
|
-
|
|
373253
|
+
whatsappBusinessRoutes.get("/:id/whatsapp-business/profile", async (c) => {
|
|
373187
373254
|
const id = c.req.param("id");
|
|
373188
373255
|
const services = c.get("services");
|
|
373189
373256
|
const instance4 = await services.instances.getById(id);
|
|
373190
|
-
const guard =
|
|
373257
|
+
const guard = ensureWhatsAppBusiness(instance4);
|
|
373191
373258
|
if (!guard.ok)
|
|
373192
373259
|
return c.json(guard.payload, 400);
|
|
373193
373260
|
const client = buildClientFromInstance(instance4);
|
|
@@ -373209,12 +373276,12 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
373209
373276
|
vertical: exports_external.string().optional(),
|
|
373210
373277
|
websites: exports_external.array(exports_external.string().url()).max(2).optional()
|
|
373211
373278
|
});
|
|
373212
|
-
|
|
373279
|
+
whatsappBusinessRoutes.put("/:id/whatsapp-business/profile", zValidator("json", updateProfileSchema), async (c) => {
|
|
373213
373280
|
const id = c.req.param("id");
|
|
373214
373281
|
const services = c.get("services");
|
|
373215
373282
|
const body = c.req.valid("json");
|
|
373216
373283
|
const instance4 = await services.instances.getById(id);
|
|
373217
|
-
const guard =
|
|
373284
|
+
const guard = ensureWhatsAppBusiness(instance4);
|
|
373218
373285
|
if (!guard.ok)
|
|
373219
373286
|
return c.json(guard.payload, 400);
|
|
373220
373287
|
const client = buildClientFromInstance(instance4);
|
|
@@ -373228,12 +373295,12 @@ var init_whatsapp_cloud3 = __esm(() => {
|
|
|
373228
373295
|
return c.json({ error: { code: "PROFILE_UPDATE_FAILED", message: message2 } }, 500);
|
|
373229
373296
|
}
|
|
373230
373297
|
});
|
|
373231
|
-
|
|
373298
|
+
whatsappBusinessRoutes.post("/:id/whatsapp-business/profile/photo", async (c) => {
|
|
373232
373299
|
const id = c.req.param("id");
|
|
373233
373300
|
const services = c.get("services");
|
|
373234
373301
|
const { appId: envAppId } = readMetaAppEnv();
|
|
373235
373302
|
const instance4 = await services.instances.getById(id);
|
|
373236
|
-
const guard =
|
|
373303
|
+
const guard = ensureWhatsAppBusiness(instance4);
|
|
373237
373304
|
if (!guard.ok)
|
|
373238
373305
|
return c.json(guard.payload, 400);
|
|
373239
373306
|
if (!instance4.metaAccessToken || !instance4.metaPhoneNumberId) {
|
|
@@ -373290,7 +373357,7 @@ function readMetaConfig2(instance4) {
|
|
|
373290
373357
|
}
|
|
373291
373358
|
async function resolveFlowsClient(services, instanceId) {
|
|
373292
373359
|
const instance4 = await services.instances.getById(instanceId);
|
|
373293
|
-
const guard =
|
|
373360
|
+
const guard = ensureWhatsAppBusiness(instance4);
|
|
373294
373361
|
if (!guard.ok)
|
|
373295
373362
|
return guard;
|
|
373296
373363
|
const cfg = readMetaConfig2(instance4);
|
|
@@ -373304,7 +373371,7 @@ function flowsDataEndpointUri(instanceId) {
|
|
|
373304
373371
|
const base2 = process.env.META_FLOWS_PUBLIC_BASE_URL?.replace(/\/+$/, "");
|
|
373305
373372
|
if (!base2)
|
|
373306
373373
|
return null;
|
|
373307
|
-
return `${base2}/api/v2/channels/whatsapp-
|
|
373374
|
+
return `${base2}/api/v2/channels/whatsapp-business/flows/data/${instanceId}`;
|
|
373308
373375
|
}
|
|
373309
373376
|
function flowJsonInvalid(issues) {
|
|
373310
373377
|
return {
|
|
@@ -373327,7 +373394,7 @@ var init_whatsapp_flows3 = __esm(() => {
|
|
|
373327
373394
|
init_zod();
|
|
373328
373395
|
init_auth();
|
|
373329
373396
|
init_sealed_credentials();
|
|
373330
|
-
|
|
373397
|
+
init_whatsapp_business3();
|
|
373331
373398
|
log120 = createLogger("routes:whatsapp-flows");
|
|
373332
373399
|
whatsappFlowsRoutes = new Hono2;
|
|
373333
373400
|
instanceAccess5 = requireInstanceAccess((c) => c.req.param("id") ?? "");
|
|
@@ -373557,12 +373624,12 @@ var init_whatsapp_flows3 = __esm(() => {
|
|
|
373557
373624
|
const services = c.get("services");
|
|
373558
373625
|
const channelRegistry2 = c.get("channelRegistry");
|
|
373559
373626
|
const instance4 = await services.instances.getById(instanceId);
|
|
373560
|
-
const guard =
|
|
373627
|
+
const guard = ensureWhatsAppBusiness(instance4);
|
|
373561
373628
|
if (!guard.ok)
|
|
373562
373629
|
return c.json(guard.payload, 400);
|
|
373563
|
-
const plugin10 = channelRegistry2?.get("whatsapp-
|
|
373630
|
+
const plugin10 = channelRegistry2?.get("whatsapp-business");
|
|
373564
373631
|
if (!plugin10) {
|
|
373565
|
-
return c.json(jsonError2("whatsapp-
|
|
373632
|
+
return c.json(jsonError2("whatsapp-business plugin not registered", "PLUGIN_NOT_FOUND"), 500);
|
|
373566
373633
|
}
|
|
373567
373634
|
const flowToken = flow.flowToken ?? buildFlowToken(flow.flowId ?? flow.flowName ?? "unknown");
|
|
373568
373635
|
const result = await plugin10.sendMessage(instanceId, {
|
|
@@ -373616,7 +373683,7 @@ var init_v2 = __esm(() => {
|
|
|
373616
373683
|
init_turns2();
|
|
373617
373684
|
init_voice2();
|
|
373618
373685
|
init_webhooks3();
|
|
373619
|
-
|
|
373686
|
+
init_whatsapp_business3();
|
|
373620
373687
|
init_whatsapp_flows3();
|
|
373621
373688
|
v2Routes = new Hono2;
|
|
373622
373689
|
v2Routes.route("/a2a", a2aRoutes);
|
|
@@ -373648,7 +373715,7 @@ var init_v2 = __esm(() => {
|
|
|
373648
373715
|
v2Routes.route("/voice", voiceRoutes);
|
|
373649
373716
|
v2Routes.route("/follow-up", followUpRoutes);
|
|
373650
373717
|
v2Routes.route("/handoffs", handoffsRoutes);
|
|
373651
|
-
v2Routes.route("/instances",
|
|
373718
|
+
v2Routes.route("/instances", whatsappBusinessRoutes);
|
|
373652
373719
|
v2Routes.route("/", templatesRoutes);
|
|
373653
373720
|
v2Routes.route("/", whatsappFlowsRoutes);
|
|
373654
373721
|
v2Routes.route("/", payloadsRoutes);
|
|
@@ -374018,41 +374085,34 @@ function createApp(db2, eventBus = null, channelRegistry2 = null) {
|
|
|
374018
374085
|
}
|
|
374019
374086
|
return plugin10.handleWebhook(c.req.raw);
|
|
374020
374087
|
});
|
|
374021
|
-
|
|
374088
|
+
const handleWhatsAppBusinessWebhook = async (c) => {
|
|
374022
374089
|
const channelRegistry3 = c.get("channelRegistry");
|
|
374023
374090
|
if (!channelRegistry3) {
|
|
374024
374091
|
return c.json({ error: { code: "NO_REGISTRY", message: "Channel registry not available" } }, 503);
|
|
374025
374092
|
}
|
|
374026
|
-
const plugin10 = channelRegistry3.get("whatsapp-
|
|
374093
|
+
const plugin10 = channelRegistry3.get("whatsapp-business");
|
|
374027
374094
|
if (!plugin10?.handleWebhook) {
|
|
374028
|
-
return c.json({ error: { code: "PLUGIN_NOT_FOUND", message: "WhatsApp
|
|
374095
|
+
return c.json({ error: { code: "PLUGIN_NOT_FOUND", message: "WhatsApp Business plugin not loaded" } }, 503);
|
|
374029
374096
|
}
|
|
374030
374097
|
return plugin10.handleWebhook(c.req.raw);
|
|
374031
|
-
}
|
|
374032
|
-
app.
|
|
374033
|
-
|
|
374034
|
-
|
|
374035
|
-
|
|
374036
|
-
|
|
374037
|
-
const plugin10 = channelRegistry3.get("whatsapp-cloud");
|
|
374038
|
-
if (!plugin10?.handleWebhook) {
|
|
374039
|
-
return c.json({ error: { code: "PLUGIN_NOT_FOUND", message: "WhatsApp Cloud plugin not loaded" } }, 503);
|
|
374040
|
-
}
|
|
374041
|
-
return plugin10.handleWebhook(c.req.raw);
|
|
374042
|
-
});
|
|
374043
|
-
app.post("/api/v2/channels/whatsapp-cloud/flows/data/:instanceId", async (c) => {
|
|
374098
|
+
};
|
|
374099
|
+
app.get("/api/v2/channels/whatsapp-business/webhook", handleWhatsAppBusinessWebhook);
|
|
374100
|
+
app.post("/api/v2/channels/whatsapp-business/webhook", handleWhatsAppBusinessWebhook);
|
|
374101
|
+
app.get("/api/v2/channels/whatsapp-cloud/webhook", handleWhatsAppBusinessWebhook);
|
|
374102
|
+
app.post("/api/v2/channels/whatsapp-cloud/webhook", handleWhatsAppBusinessWebhook);
|
|
374103
|
+
const handleWhatsAppFlowsData = async (c) => {
|
|
374044
374104
|
const channelRegistry3 = c.get("channelRegistry");
|
|
374045
374105
|
if (!channelRegistry3) {
|
|
374046
374106
|
return c.json({ error: { code: "NO_REGISTRY", message: "Channel registry not available" } }, 503);
|
|
374047
374107
|
}
|
|
374048
|
-
const plugin10 = channelRegistry3.get("whatsapp-
|
|
374108
|
+
const plugin10 = channelRegistry3.get("whatsapp-business");
|
|
374049
374109
|
if (!plugin10?.handleFlowData) {
|
|
374050
|
-
return c.json({ error: { code: "PLUGIN_NOT_FOUND", message: "WhatsApp
|
|
374110
|
+
return c.json({ error: { code: "PLUGIN_NOT_FOUND", message: "WhatsApp Business plugin not loaded" } }, 503);
|
|
374051
374111
|
}
|
|
374052
|
-
const instanceId = c.req.param("instanceId");
|
|
374112
|
+
const instanceId = c.req.param("instanceId") ?? "";
|
|
374053
374113
|
const services2 = c.get("services");
|
|
374054
374114
|
const instance4 = await services2.instances.getById(instanceId).catch(() => null);
|
|
374055
|
-
if (!instance4 || instance4.channel !== "whatsapp-
|
|
374115
|
+
if (!instance4 || instance4.channel !== "whatsapp-business") {
|
|
374056
374116
|
return c.json({ error: { code: "NOT_FOUND", message: "Unknown instance" } }, 404);
|
|
374057
374117
|
}
|
|
374058
374118
|
const db3 = c.get("db");
|
|
@@ -374063,6 +374123,13 @@ function createApp(db2, eventBus = null, channelRegistry2 = null) {
|
|
|
374063
374123
|
return c.body(null, 421);
|
|
374064
374124
|
}
|
|
374065
374125
|
return plugin10.handleFlowData(c.req.raw, { instanceId, privateKeyPem });
|
|
374126
|
+
};
|
|
374127
|
+
app.post("/api/v2/channels/whatsapp-business/flows/data/:instanceId", handleWhatsAppFlowsData);
|
|
374128
|
+
app.post("/api/v2/channels/whatsapp-cloud/flows/data/:instanceId", handleWhatsAppFlowsData);
|
|
374129
|
+
app.all("/api/v2/instances/:instanceId/whatsapp-cloud/*", (c) => {
|
|
374130
|
+
const url = new URL(c.req.url);
|
|
374131
|
+
url.pathname = url.pathname.replace("/whatsapp-cloud/", "/whatsapp-business/");
|
|
374132
|
+
return app.fetch(new Request(url.toString(), c.req.raw), c.env);
|
|
374066
374133
|
});
|
|
374067
374134
|
app.post("/api/v2/channels/twilio-whatsapp/:instanceId/webhook", async (c) => {
|
|
374068
374135
|
const channelRegistry3 = c.get("channelRegistry");
|
|
@@ -376120,12 +376187,27 @@ function buildInstanceConnectOptions(instance4) {
|
|
|
376120
376187
|
if (instance4.channel === "twilio-whatsapp") {
|
|
376121
376188
|
applyTwilioWhatsAppOptions(options, instance4);
|
|
376122
376189
|
}
|
|
376123
|
-
if (instance4.channel === "whatsapp-
|
|
376124
|
-
|
|
376190
|
+
if (instance4.channel === "whatsapp-business") {
|
|
376191
|
+
applyWhatsAppBusinessOptions(options, instance4);
|
|
376192
|
+
}
|
|
376193
|
+
if (instance4.channel === "hermes") {
|
|
376194
|
+
applyHermesOptions(options, instance4);
|
|
376125
376195
|
}
|
|
376126
376196
|
return options;
|
|
376127
376197
|
}
|
|
376128
|
-
function
|
|
376198
|
+
function applyHermesOptions(options, instance4) {
|
|
376199
|
+
if (instance4.hermesBaseUrl)
|
|
376200
|
+
options.hermesBaseUrl = instance4.hermesBaseUrl;
|
|
376201
|
+
if (instance4.hermesUsername)
|
|
376202
|
+
options.hermesUsername = instance4.hermesUsername;
|
|
376203
|
+
if (instance4.hermesPassword)
|
|
376204
|
+
options.hermesPassword = instance4.hermesPassword;
|
|
376205
|
+
if (instance4.hermesMediaId)
|
|
376206
|
+
options.hermesMediaId = instance4.hermesMediaId;
|
|
376207
|
+
if (instance4.hermesTemplateNamespace)
|
|
376208
|
+
options.hermesTemplateNamespace = instance4.hermesTemplateNamespace;
|
|
376209
|
+
}
|
|
376210
|
+
function applyWhatsAppBusinessOptions(options, instance4) {
|
|
376129
376211
|
if (instance4.metaAccessToken)
|
|
376130
376212
|
options.metaAccessToken = instance4.metaAccessToken;
|
|
376131
376213
|
if (instance4.metaPhoneNumberId)
|
|
@@ -377659,7 +377741,7 @@ async function initializeChannelPlugins(db3, eventBus) {
|
|
|
377659
377741
|
}
|
|
377660
377742
|
const flowsDemoInstance = process.env.META_FLOWS_DEMO_INSTANCE;
|
|
377661
377743
|
if (flowsDemoInstance) {
|
|
377662
|
-
const waCloud = result.registry.get("whatsapp-
|
|
377744
|
+
const waCloud = result.registry.get("whatsapp-business");
|
|
377663
377745
|
if (waCloud && "flowResolvers" in waCloud) {
|
|
377664
377746
|
const { createDemoFlowResolver: createDemoFlowResolver2 } = await Promise.resolve().then(() => (init_src6(), exports_src4));
|
|
377665
377747
|
waCloud.flowResolvers.registerInstanceDefault(flowsDemoInstance, createDemoFlowResolver2());
|