@automagik/omni 2.260907.3 → 2.260907.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +3 -1
- package/dist/server/index.js +264 -41
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11260,6 +11260,8 @@ var init_types3 = __esm(() => {
|
|
|
11260
11260
|
"message.delivered",
|
|
11261
11261
|
"message.read",
|
|
11262
11262
|
"message.failed",
|
|
11263
|
+
"message.pinned",
|
|
11264
|
+
"message.unpinned",
|
|
11263
11265
|
"message.button_click",
|
|
11264
11266
|
"message.poll",
|
|
11265
11267
|
"message.poll_vote",
|
|
@@ -136390,7 +136392,7 @@ import { fileURLToPath } from "url";
|
|
|
136390
136392
|
// package.json
|
|
136391
136393
|
var package_default = {
|
|
136392
136394
|
name: "@automagik/omni",
|
|
136393
|
-
version: "2.260907.
|
|
136395
|
+
version: "2.260907.5",
|
|
136394
136396
|
repository: {
|
|
136395
136397
|
type: "git",
|
|
136396
136398
|
url: "git+https://github.com/automagik-dev/omni.git",
|
package/dist/server/index.js
CHANGED
|
@@ -139,6 +139,8 @@ var init_types2 = __esm(() => {
|
|
|
139
139
|
"message.delivered",
|
|
140
140
|
"message.read",
|
|
141
141
|
"message.failed",
|
|
142
|
+
"message.pinned",
|
|
143
|
+
"message.unpinned",
|
|
142
144
|
"message.button_click",
|
|
143
145
|
"message.poll",
|
|
144
146
|
"message.poll_vote",
|
|
@@ -44631,6 +44633,14 @@ class BaseChannelPlugin {
|
|
|
44631
44633
|
const { instanceId, ...payload } = params;
|
|
44632
44634
|
await this.publishEventInternal("reaction.removed", payload, instanceId);
|
|
44633
44635
|
}
|
|
44636
|
+
async emitMessagePinned(params) {
|
|
44637
|
+
const { instanceId, ...payload } = params;
|
|
44638
|
+
await this.publishEventInternal("message.pinned", payload, instanceId);
|
|
44639
|
+
}
|
|
44640
|
+
async emitMessageUnpinned(params) {
|
|
44641
|
+
const { instanceId, ...payload } = params;
|
|
44642
|
+
await this.publishEventInternal("message.unpinned", payload, instanceId);
|
|
44643
|
+
}
|
|
44634
44644
|
async emitButtonClick(params) {
|
|
44635
44645
|
const { instanceId, ...payload } = params;
|
|
44636
44646
|
await this.publishEventInternal("message.button_click", payload, instanceId);
|
|
@@ -250957,7 +250967,7 @@ var init_sentry_scrub = __esm(() => {
|
|
|
250957
250967
|
var require_package7 = __commonJS((exports, module) => {
|
|
250958
250968
|
module.exports = {
|
|
250959
250969
|
name: "@omni/api",
|
|
250960
|
-
version: "2.260907.
|
|
250970
|
+
version: "2.260907.5",
|
|
250961
250971
|
private: true,
|
|
250962
250972
|
type: "module",
|
|
250963
250973
|
exports: {
|
|
@@ -352230,6 +352240,23 @@ async function linkReplyTarget(services, chatId, messageId, replyToExternalId) {
|
|
|
352230
352240
|
});
|
|
352231
352241
|
}
|
|
352232
352242
|
}
|
|
352243
|
+
async function linkThreadRoot(services, chatId, messageId, messageExternalId, threadExternalId, repliedAt) {
|
|
352244
|
+
if (!threadExternalId || threadExternalId === messageExternalId)
|
|
352245
|
+
return;
|
|
352246
|
+
try {
|
|
352247
|
+
const rootMessageId = await services.messages.resolveReplyToMessage(chatId, threadExternalId);
|
|
352248
|
+
if (!rootMessageId)
|
|
352249
|
+
return;
|
|
352250
|
+
await services.messages.setThreadRoot(messageId, rootMessageId);
|
|
352251
|
+
await services.messages.recordThreadReply(rootMessageId, repliedAt);
|
|
352252
|
+
} catch (error3) {
|
|
352253
|
+
log90.debug("Could not link thread root", {
|
|
352254
|
+
chatId,
|
|
352255
|
+
threadExternalId,
|
|
352256
|
+
error: error3 instanceof Error ? error3.message : String(error3)
|
|
352257
|
+
});
|
|
352258
|
+
}
|
|
352259
|
+
}
|
|
352233
352260
|
async function handleMessageReceived(services, payload, metadata, eventTimestamp, trustedTenantId, identity) {
|
|
352234
352261
|
const channel5 = metadata.channelType ?? "whatsapp";
|
|
352235
352262
|
const isHistorySync = metadata.ingestMode === "history-sync";
|
|
@@ -352282,6 +352309,7 @@ async function handleMessageReceived(services, payload, metadata, eventTimestamp
|
|
|
352282
352309
|
if (created) {
|
|
352283
352310
|
log90.debug("Created message", { externalId: payload.externalId, chatId: chat2.id });
|
|
352284
352311
|
await linkReplyTarget(services, chat2.id, message2.id, payload.replyToId);
|
|
352312
|
+
await linkThreadRoot(services, chat2.id, message2.id, messageExternalId, truncate4(payload.threadId, 255), platformTimestamp ?? new Date(eventTimestamp));
|
|
352285
352313
|
}
|
|
352286
352314
|
await maybeRecordParticipantActivity(services, chat2.id, payload.from);
|
|
352287
352315
|
maybeUpdateRecency(services, metadata.instanceId, chat2.id, rawPayload, payload, platformTimestamp ?? new Date(eventTimestamp), trustedTenantId);
|
|
@@ -352306,6 +352334,29 @@ function logMessageReceivedError(payload, error3) {
|
|
|
352306
352334
|
longFields: Object.keys(longFields).length > 0 ? longFields : undefined
|
|
352307
352335
|
});
|
|
352308
352336
|
}
|
|
352337
|
+
async function handleMessagePinState(services, event, pinned) {
|
|
352338
|
+
const payload = event.payload;
|
|
352339
|
+
const metadata = event.metadata;
|
|
352340
|
+
if (!metadata.instanceId)
|
|
352341
|
+
return;
|
|
352342
|
+
const instanceId = metadata.instanceId;
|
|
352343
|
+
try {
|
|
352344
|
+
await runConsumerInTenantContext(services.db, event, async () => {
|
|
352345
|
+
const chat2 = await services.chats.findByExternalIdSmart(instanceId, payload.chatId);
|
|
352346
|
+
if (!chat2) {
|
|
352347
|
+
log90.debug("Chat not found for pin update", { chatId: payload.chatId });
|
|
352348
|
+
return;
|
|
352349
|
+
}
|
|
352350
|
+
await services.messages.setPinned(chat2.id, payload.messageId, pinned, payload.from);
|
|
352351
|
+
log90.debug("Updated message pin state", { chatId: chat2.id, messageId: payload.messageId, pinned });
|
|
352352
|
+
});
|
|
352353
|
+
} catch (error3) {
|
|
352354
|
+
log90.error("Failed to update pin state", {
|
|
352355
|
+
messageId: payload.messageId,
|
|
352356
|
+
error: String(error3)
|
|
352357
|
+
});
|
|
352358
|
+
}
|
|
352359
|
+
}
|
|
352309
352360
|
async function setupMessagePersistence(eventBus, services) {
|
|
352310
352361
|
try {
|
|
352311
352362
|
await eventBus.subscribe("message.received", async (event) => {
|
|
@@ -352382,6 +352433,9 @@ async function setupMessagePersistence(eventBus, services) {
|
|
|
352382
352433
|
replyToExternalId: truncate4(payload.replyToId, 255),
|
|
352383
352434
|
threadExternalId: truncate4(payload.threadId, 255)
|
|
352384
352435
|
});
|
|
352436
|
+
if (created2) {
|
|
352437
|
+
await linkThreadRoot(services, chat3.id, message3.id, messageExternalId, truncate4(payload.threadId, 255), new Date(event.timestamp));
|
|
352438
|
+
}
|
|
352385
352439
|
return { chat: chat3, message: message3, created: created2 };
|
|
352386
352440
|
});
|
|
352387
352441
|
if (created) {
|
|
@@ -352484,6 +352538,22 @@ async function setupMessagePersistence(eventBus, services) {
|
|
|
352484
352538
|
startFrom: "first",
|
|
352485
352539
|
concurrency: 10
|
|
352486
352540
|
});
|
|
352541
|
+
await eventBus.subscribe("message.pinned", (event) => handleMessagePinState(services, event, true), {
|
|
352542
|
+
durable: "message-persistence-pinned",
|
|
352543
|
+
queue: "message-persistence",
|
|
352544
|
+
maxRetries: 2,
|
|
352545
|
+
retryDelayMs: 500,
|
|
352546
|
+
startFrom: "first",
|
|
352547
|
+
concurrency: 10
|
|
352548
|
+
});
|
|
352549
|
+
await eventBus.subscribe("message.unpinned", (event) => handleMessagePinState(services, event, false), {
|
|
352550
|
+
durable: "message-persistence-unpinned",
|
|
352551
|
+
queue: "message-persistence",
|
|
352552
|
+
maxRetries: 2,
|
|
352553
|
+
retryDelayMs: 500,
|
|
352554
|
+
startFrom: "first",
|
|
352555
|
+
concurrency: 10
|
|
352556
|
+
});
|
|
352487
352557
|
await eventBus.subscribe("instance.connected", async (event) => {
|
|
352488
352558
|
const payload = event.payload;
|
|
352489
352559
|
const instanceId = payload.instanceId;
|
|
@@ -360570,6 +360640,16 @@ class MessageService {
|
|
|
360570
360640
|
async updateReplyToReference(id, replyToMessageId) {
|
|
360571
360641
|
await this.db.update(messages2).set({ replyToMessageId, updatedAt: new Date }).where(eq(messages2.id, id));
|
|
360572
360642
|
}
|
|
360643
|
+
async setThreadRoot(id, threadRootMessageId) {
|
|
360644
|
+
await this.db.update(messages2).set({ threadRootMessageId, updatedAt: new Date }).where(eq(messages2.id, id));
|
|
360645
|
+
}
|
|
360646
|
+
async recordThreadReply(rootMessageId, repliedAt) {
|
|
360647
|
+
await this.db.update(messages2).set({
|
|
360648
|
+
replyCount: sql`${messages2.replyCount} + 1`,
|
|
360649
|
+
latestReplyAt: sql`GREATEST(COALESCE(${messages2.latestReplyAt}, ${repliedAt}), ${repliedAt})`,
|
|
360650
|
+
updatedAt: new Date
|
|
360651
|
+
}).where(eq(messages2.id, rootMessageId));
|
|
360652
|
+
}
|
|
360573
360653
|
}
|
|
360574
360654
|
var MEDIA_BADGES2;
|
|
360575
360655
|
var init_messages3 = __esm(() => {
|
|
@@ -389339,11 +389419,23 @@ class AscFlowClient {
|
|
|
389339
389419
|
}
|
|
389340
389420
|
return response;
|
|
389341
389421
|
}
|
|
389342
|
-
rawPost(path, payload, token) {
|
|
389343
|
-
return this.rawRequest("POST", path, {}, payload, token);
|
|
389422
|
+
rawPost(path, payload, token, form = false) {
|
|
389423
|
+
return this.rawRequest("POST", path, {}, payload, token, form);
|
|
389344
389424
|
}
|
|
389345
|
-
async
|
|
389346
|
-
|
|
389425
|
+
async callForm(path, payload) {
|
|
389426
|
+
let response = await this.rawPost(path, payload, await this.getToken(), true);
|
|
389427
|
+
if (response.status === 401 && codErrorOf(response.body) === undefined) {
|
|
389428
|
+
response = await this.rawPost(path, payload, await this.getToken(true), true);
|
|
389429
|
+
}
|
|
389430
|
+
if (isPlatformOk(response))
|
|
389431
|
+
return response.body;
|
|
389432
|
+
const codError = codErrorOf(response.body);
|
|
389433
|
+
throw new AscFlowApiError(mapHttpStatusToAscFlowError(response.status, codError !== undefined), `ASC ${path} failed (HTTP ${response.status}${codError === undefined ? "" : `, cod_error ${codError}`})`, { httpStatus: response.status, operation: path, codError, raw: JSON.stringify(response.body).slice(0, 500) });
|
|
389434
|
+
}
|
|
389435
|
+
async rawRequest(method, path, query, payload, token, form = false) {
|
|
389436
|
+
const headers = {
|
|
389437
|
+
"content-type": form ? "application/x-www-form-urlencoded" : "application/json"
|
|
389438
|
+
};
|
|
389347
389439
|
if (token)
|
|
389348
389440
|
headers.authorization = `Bearer ${token}`;
|
|
389349
389441
|
const url = new URL(`${this.baseUrl}${path}`);
|
|
@@ -389354,7 +389446,7 @@ class AscFlowClient {
|
|
|
389354
389446
|
response = await fetch(url.toString(), {
|
|
389355
389447
|
method,
|
|
389356
389448
|
headers,
|
|
389357
|
-
...payload === undefined ? {} : { body: JSON.stringify(payload) },
|
|
389449
|
+
...payload === undefined ? {} : { body: form ? formEncode(payload) : JSON.stringify(payload) },
|
|
389358
389450
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
389359
389451
|
});
|
|
389360
389452
|
} catch (err2) {
|
|
@@ -389370,6 +389462,21 @@ class AscFlowClient {
|
|
|
389370
389462
|
return { status: response.status, body };
|
|
389371
389463
|
}
|
|
389372
389464
|
}
|
|
389465
|
+
function formEncode(payload) {
|
|
389466
|
+
const params = new URLSearchParams;
|
|
389467
|
+
const walk = (value, key) => {
|
|
389468
|
+
if (Array.isArray(value)) {
|
|
389469
|
+
value.forEach((item, i) => walk(item, `${key}[${i}]`));
|
|
389470
|
+
} else if (typeof value === "object" && value !== null) {
|
|
389471
|
+
for (const [k2, v2] of Object.entries(value))
|
|
389472
|
+
walk(v2, key ? `${key}[${k2}]` : k2);
|
|
389473
|
+
} else if (value !== undefined && value !== null) {
|
|
389474
|
+
params.set(key, String(value));
|
|
389475
|
+
}
|
|
389476
|
+
};
|
|
389477
|
+
walk(payload, "");
|
|
389478
|
+
return params.toString();
|
|
389479
|
+
}
|
|
389373
389480
|
|
|
389374
389481
|
// ../channel-asc-flow/src/utils/emoji.ts
|
|
389375
389482
|
var MARKER = /##([0-9a-f]{2,6}(?:-[0-9a-f]{2,6})*)##/gi;
|
|
@@ -389431,10 +389538,21 @@ function parseInboundTurn(body) {
|
|
|
389431
389538
|
codAtendimento,
|
|
389432
389539
|
text,
|
|
389433
389540
|
fromFallback: !typed,
|
|
389541
|
+
entradaDefasada: Boolean(typed) && Boolean(fallback) && typed !== fallback,
|
|
389434
389542
|
phone: firstString(body.phone, body.telefone),
|
|
389435
389543
|
...messageId ? { messageId } : {}
|
|
389436
389544
|
};
|
|
389437
389545
|
}
|
|
389546
|
+
async function isReenvioDoFlow(plugin2, instanceId, turn, logger5) {
|
|
389547
|
+
if (turn.entradaDefasada && plugin2.hasSeenCod(instanceId, turn.codAtendimento)) {
|
|
389548
|
+
logger5.info("[asc-flow] chatInput is behind message \u2014 the flow re-sent an old input", {
|
|
389549
|
+
instanceId,
|
|
389550
|
+
codAtendimento: turn.codAtendimento
|
|
389551
|
+
});
|
|
389552
|
+
return true;
|
|
389553
|
+
}
|
|
389554
|
+
return plugin2.isStaleFlowReplay(instanceId, turn);
|
|
389555
|
+
}
|
|
389438
389556
|
async function handleAscFlowWebhookRequest(request, plugin2, instanceId, verifyToken, dedupeCache) {
|
|
389439
389557
|
const logger5 = plugin2.getLogger();
|
|
389440
389558
|
if (request.method !== "POST") {
|
|
@@ -389485,7 +389603,7 @@ async function handleAscFlowWebhookRequest(request, plugin2, instanceId, verifyT
|
|
|
389485
389603
|
});
|
|
389486
389604
|
return pending();
|
|
389487
389605
|
}
|
|
389488
|
-
if (await plugin2
|
|
389606
|
+
if (await isReenvioDoFlow(plugin2, instanceId, turn, logger5)) {
|
|
389489
389607
|
return pending();
|
|
389490
389608
|
}
|
|
389491
389609
|
const isRedelivery = turn.messageId ? dedupeCache.isDuplicate(instanceId, turn.messageId, "asc-flow", logger5) : plugin2.isRedeliveryOfTurnInFlight(instanceId, turn);
|
|
@@ -389541,6 +389659,15 @@ function planHandoff(mode, meta, fallbackServico, logger5) {
|
|
|
389541
389659
|
}
|
|
389542
389660
|
return { transfer: { codServico, codPrioridade }, fields };
|
|
389543
389661
|
}
|
|
389662
|
+
var IDENTITY_FIELDS = [
|
|
389663
|
+
"nome_beneficiario_vq",
|
|
389664
|
+
"cpf_vq",
|
|
389665
|
+
"carteirinha_vq",
|
|
389666
|
+
"vinculo_vq",
|
|
389667
|
+
"plano_vq",
|
|
389668
|
+
"filial_vq"
|
|
389669
|
+
];
|
|
389670
|
+
var IDENTITY_MAX_LENGTH = 200;
|
|
389544
389671
|
function buildGenesysFields(read, logger5, mode) {
|
|
389545
389672
|
const fields = {};
|
|
389546
389673
|
const rawFila = read("handoffQueue", "fila_vq");
|
|
@@ -389566,6 +389693,12 @@ function buildGenesysFields(read, logger5, mode) {
|
|
|
389566
389693
|
if (motivo)
|
|
389567
389694
|
fields.motivo_transf_vq = motivo;
|
|
389568
389695
|
}
|
|
389696
|
+
for (const key of IDENTITY_FIELDS) {
|
|
389697
|
+
const raw = read(key);
|
|
389698
|
+
if (typeof raw !== "string")
|
|
389699
|
+
continue;
|
|
389700
|
+
fields[key] = raw.replace(/\s+/g, " ").trim().slice(0, IDENTITY_MAX_LENGTH);
|
|
389701
|
+
}
|
|
389569
389702
|
return fields;
|
|
389570
389703
|
}
|
|
389571
389704
|
|
|
@@ -389573,16 +389706,9 @@ function buildGenesysFields(read, logger5, mode) {
|
|
|
389573
389706
|
init_src2();
|
|
389574
389707
|
var MAX_OPTIONS = 10;
|
|
389575
389708
|
var MAX_BODY_TEXT = 1024;
|
|
389576
|
-
var
|
|
389577
|
-
var
|
|
389578
|
-
|
|
389579
|
-
const value = title.trim();
|
|
389580
|
-
if (value.length <= BUTTON_TITLE_MAX)
|
|
389581
|
-
return value;
|
|
389582
|
-
const head = value.slice(0, BUTTON_TITLE_MAX);
|
|
389583
|
-
const boundary = head.lastIndexOf(" ");
|
|
389584
|
-
return (boundary >= 8 ? head.slice(0, boundary) : head).trim();
|
|
389585
|
-
}
|
|
389709
|
+
var TIPO_LISTA = 1;
|
|
389710
|
+
var TIPO_BOTOES = 2;
|
|
389711
|
+
var LIST_BUTTON_LABEL = "Op\xE7\xF5es";
|
|
389586
389712
|
function foldTitle(value) {
|
|
389587
389713
|
return value.normalize("NFD").replace(/\p{Mn}/gu, "").toLocaleLowerCase().split(/\s+/).filter(Boolean).join(" ");
|
|
389588
389714
|
}
|
|
@@ -389595,37 +389721,50 @@ function titlesOf(interactive) {
|
|
|
389595
389721
|
const sections = action?.sections ?? [];
|
|
389596
389722
|
return (sections[0]?.rows ?? []).map((r) => r.title ?? "");
|
|
389597
389723
|
}
|
|
389598
|
-
function
|
|
389724
|
+
function splitBubbles(text) {
|
|
389725
|
+
return text.trim().split(/\n\s*\n/).map((b2) => b2.trim()).filter(Boolean);
|
|
389726
|
+
}
|
|
389727
|
+
function buildInteractive(body, buttons, listOptions = {}) {
|
|
389599
389728
|
const trimmed = body.trim();
|
|
389600
389729
|
if (!trimmed || trimmed.length > MAX_BODY_TEXT)
|
|
389601
389730
|
return null;
|
|
389602
389731
|
const replyButtons = (buttons ?? []).filter((b2) => !b2.url && b2.text?.trim());
|
|
389603
389732
|
if (replyButtons.length === 0 || replyButtons.length > MAX_OPTIONS)
|
|
389604
389733
|
return null;
|
|
389605
|
-
const plan = planInteractive(trimmed, replyButtons,
|
|
389734
|
+
const plan = planInteractive(trimmed, replyButtons, LIST_BUTTON_LABEL, listOptions);
|
|
389606
389735
|
if (!plan.interactive || plan.droppedRows > 0)
|
|
389607
389736
|
return null;
|
|
389608
389737
|
const type = plan.interactive.type;
|
|
389609
389738
|
if (type !== "button" && type !== "list")
|
|
389610
389739
|
return null;
|
|
389611
|
-
|
|
389612
|
-
let asButtons = type === "button";
|
|
389613
|
-
if (!asButtons && replyButtons.length <= MAX_BUTTONS) {
|
|
389614
|
-
titles = replyButtons.map((b2) => shortenTitle(b2.text ?? ""));
|
|
389615
|
-
asButtons = true;
|
|
389616
|
-
}
|
|
389740
|
+
const titles = titlesOf(plan.interactive);
|
|
389617
389741
|
if (titles.length !== replyButtons.length || titles.some((t) => !t))
|
|
389618
389742
|
return null;
|
|
389619
389743
|
if (new Set(titles.map(foldTitle)).size !== titles.length)
|
|
389620
389744
|
return null;
|
|
389745
|
+
if (type === "button") {
|
|
389746
|
+
return { tipo: TIPO_BOTOES, mensagem: trimmed, button: titles };
|
|
389747
|
+
}
|
|
389748
|
+
const action = plan.interactive.action;
|
|
389749
|
+
const sections = action?.sections ?? [];
|
|
389750
|
+
const rows = sections[0]?.rows ?? [];
|
|
389621
389751
|
return {
|
|
389622
|
-
|
|
389623
|
-
|
|
389752
|
+
tipo: TIPO_LISTA,
|
|
389753
|
+
mensagem: trimmed,
|
|
389754
|
+
list: {
|
|
389755
|
+
texto_botao: action?.button || LIST_BUTTON_LABEL,
|
|
389756
|
+
secao: [
|
|
389757
|
+
{
|
|
389758
|
+
texto: sections[0]?.title ?? "",
|
|
389759
|
+
linhas: rows.map((row) => ({
|
|
389760
|
+
texto: row.title ?? "",
|
|
389761
|
+
descricao: row.description ?? ""
|
|
389762
|
+
}))
|
|
389763
|
+
}
|
|
389764
|
+
]
|
|
389765
|
+
}
|
|
389624
389766
|
};
|
|
389625
389767
|
}
|
|
389626
|
-
function splitBubbles(text) {
|
|
389627
|
-
return text.trim().split(/\n\s*\n/).map((b2) => b2.trim()).filter(Boolean);
|
|
389628
|
-
}
|
|
389629
389768
|
|
|
389630
389769
|
// ../channel-asc-flow/src/utils/media.ts
|
|
389631
389770
|
init_src2();
|
|
@@ -389936,6 +390075,19 @@ function normalizeBaseUrl(raw) {
|
|
|
389936
390075
|
const trimmed = raw.trim().replace(/\/+$/, "");
|
|
389937
390076
|
return trimmed.endsWith(REST_PREFIX) ? trimmed : `${trimmed}${REST_PREFIX}`;
|
|
389938
390077
|
}
|
|
390078
|
+
function interactiveKindOf(params) {
|
|
390079
|
+
if (!params)
|
|
390080
|
+
return "text";
|
|
390081
|
+
return params.tipo === 2 ? "buttons" : "list";
|
|
390082
|
+
}
|
|
390083
|
+
function interactiveRowsOf(params) {
|
|
390084
|
+
if (!params)
|
|
390085
|
+
return 0;
|
|
390086
|
+
if (Array.isArray(params.button))
|
|
390087
|
+
return params.button.length;
|
|
390088
|
+
const list = params.list;
|
|
390089
|
+
return list?.secao?.[0]?.linhas?.length ?? 0;
|
|
390090
|
+
}
|
|
389939
390091
|
function buildReadyBody(turn) {
|
|
389940
390092
|
return {
|
|
389941
390093
|
pronto: 1,
|
|
@@ -389944,8 +390096,7 @@ function buildReadyBody(turn) {
|
|
|
389944
390096
|
bolhas: turn.bubbles,
|
|
389945
390097
|
fila_vq: "",
|
|
389946
390098
|
motivo_transf_vq: "",
|
|
389947
|
-
...turn.handoff ?? {}
|
|
389948
|
-
...turn.ura ?? {}
|
|
390099
|
+
...turn.handoff ?? {}
|
|
389949
390100
|
};
|
|
389950
390101
|
}
|
|
389951
390102
|
|
|
@@ -389998,7 +390149,8 @@ class AscFlowPlugin extends BaseChannelPlugin {
|
|
|
389998
390149
|
inFlight: new Map,
|
|
389999
390150
|
lastSweepAt: Date.now(),
|
|
390000
390151
|
seenCods: new Set,
|
|
390001
|
-
lastAnswered: new Map
|
|
390152
|
+
lastAnswered: new Map,
|
|
390153
|
+
destinos: new Map
|
|
390002
390154
|
});
|
|
390003
390155
|
await this.updateInstanceStatus(instanceId, config2, {
|
|
390004
390156
|
state: "connected",
|
|
@@ -390056,20 +390208,20 @@ class AscFlowPlugin extends BaseChannelPlugin {
|
|
|
390056
390208
|
const text = resolveOutboundText(turnMessage, this.logger);
|
|
390057
390209
|
const { rich, bubbles } = await this.prepareTurn(turnMessage, text);
|
|
390058
390210
|
const lastBubble = bubbles[bubbles.length - 1] ?? "";
|
|
390059
|
-
const
|
|
390211
|
+
const interativa = rich ? null : buildInteractive(lastBubble, content.buttons, listOptionsOf(content));
|
|
390060
390212
|
const { delivered } = await this.deliver(state, cod, {
|
|
390061
390213
|
text,
|
|
390062
390214
|
bubbles,
|
|
390063
390215
|
lastBubble,
|
|
390064
390216
|
rich,
|
|
390065
|
-
|
|
390217
|
+
interativa,
|
|
390066
390218
|
message: turnMessage
|
|
390067
390219
|
});
|
|
390068
390220
|
if (!delivered && !polling)
|
|
390069
390221
|
return this.refuseUndeliverable(instanceId, to, content.type);
|
|
390070
390222
|
const handoff = meta.isHandoff === true ? await this.runHandoff(state, instanceId, cod, meta, delivered ? "" : lastBubble) : null;
|
|
390071
390223
|
const handoffRefused = meta.isHandoff === true && handoff === null;
|
|
390072
|
-
this.resolveTurn(state, to, buildReadyBody({ delivered, lastBubble, bubbles, handoff
|
|
390224
|
+
this.resolveTurn(state, to, buildReadyBody({ delivered, lastBubble, bubbles, handoff }), answering, correlationId);
|
|
390073
390225
|
if (handoffRefused)
|
|
390074
390226
|
return this.refuseSend(instanceId, to, HANDOFF_REFUSED_ERROR);
|
|
390075
390227
|
if (correlationId)
|
|
@@ -390078,7 +390230,7 @@ class AscFlowPlugin extends BaseChannelPlugin {
|
|
|
390078
390230
|
await this.emitTurnSent(instanceId, turnMessage, messageId, {
|
|
390079
390231
|
cod,
|
|
390080
390232
|
bubbles: bubbles.length,
|
|
390081
|
-
|
|
390233
|
+
interativa,
|
|
390082
390234
|
delivered,
|
|
390083
390235
|
handoff: handoff !== null
|
|
390084
390236
|
});
|
|
@@ -390111,8 +390263,8 @@ class AscFlowPlugin extends BaseChannelPlugin {
|
|
|
390111
390263
|
ascFlow: {
|
|
390112
390264
|
codAtendimento: turn.cod,
|
|
390113
390265
|
bubbles: turn.bubbles,
|
|
390114
|
-
interactive: turn.
|
|
390115
|
-
|
|
390266
|
+
interactive: interactiveKindOf(turn.interativa),
|
|
390267
|
+
interactiveRows: interactiveRowsOf(turn.interativa),
|
|
390116
390268
|
viaMensagem: turn.delivered,
|
|
390117
390269
|
handoff: turn.handoff
|
|
390118
390270
|
}
|
|
@@ -390226,15 +390378,56 @@ class AscFlowPlugin extends BaseChannelPlugin {
|
|
|
390226
390378
|
const texto = turn.bubbles.length > 0 ? turn.bubbles : [OUTBOUND_MEDIA_FALLBACK_TEXT];
|
|
390227
390379
|
return { delivered: await this.pushBubbles(state, cod, texto) > 0 };
|
|
390228
390380
|
}
|
|
390229
|
-
if (turn.
|
|
390381
|
+
if (turn.interativa) {
|
|
390230
390382
|
await this.pushBubbles(state, cod, turn.bubbles.slice(0, -1));
|
|
390231
|
-
if (await this.
|
|
390383
|
+
if (await this.sendInterativa(state, cod, turn.interativa))
|
|
390232
390384
|
return { delivered: true };
|
|
390233
390385
|
return { delivered: await this.pushBubbles(state, cod, [turn.lastBubble]) > 0 };
|
|
390234
390386
|
}
|
|
390235
390387
|
const pushed = await this.pushBubbles(state, cod, turn.bubbles);
|
|
390236
390388
|
return { delivered: pushed > 0 };
|
|
390237
390389
|
}
|
|
390390
|
+
async sendInterativa(state, cod, params) {
|
|
390391
|
+
try {
|
|
390392
|
+
const destino = await this.resolveDestino(state, cod);
|
|
390393
|
+
if (!destino)
|
|
390394
|
+
return false;
|
|
390395
|
+
await state.client.callForm("/sendMsgInterativaAvancado", {
|
|
390396
|
+
cod_conta: destino.codConta,
|
|
390397
|
+
tipo_envio: 1,
|
|
390398
|
+
bol_incluir_atual: 1,
|
|
390399
|
+
contato: { telefone: destino.telefone },
|
|
390400
|
+
msg_interativa_parametros: params
|
|
390401
|
+
});
|
|
390402
|
+
return true;
|
|
390403
|
+
} catch (err2) {
|
|
390404
|
+
this.logger.warn("[asc-flow] interactive message refused \u2014 degrading to the numbered text", {
|
|
390405
|
+
cod,
|
|
390406
|
+
err: String(err2)
|
|
390407
|
+
});
|
|
390408
|
+
return false;
|
|
390409
|
+
}
|
|
390410
|
+
}
|
|
390411
|
+
async resolveDestino(state, cod) {
|
|
390412
|
+
const chave = String(cod);
|
|
390413
|
+
const cacheado = state.destinos.get(chave);
|
|
390414
|
+
if (cacheado)
|
|
390415
|
+
return cacheado;
|
|
390416
|
+
const { status, body } = await state.client.get("/atendimento", { codigo_atendimento: cod });
|
|
390417
|
+
if (status !== 200 || typeof body !== "object" || body === null)
|
|
390418
|
+
return null;
|
|
390419
|
+
const dados = body;
|
|
390420
|
+
const contato = dados.contato ?? {};
|
|
390421
|
+
const codConta = String(dados.id_conta ?? "").trim();
|
|
390422
|
+
const telefone = String(contato.telefone ?? "").trim();
|
|
390423
|
+
if (!codConta || !telefone) {
|
|
390424
|
+
this.logger.warn("[asc-flow] atendimento carries no account/phone \u2014 no interactive message for it", { cod });
|
|
390425
|
+
return null;
|
|
390426
|
+
}
|
|
390427
|
+
const destino = { codConta, telefone };
|
|
390428
|
+
state.destinos.set(chave, destino);
|
|
390429
|
+
return destino;
|
|
390430
|
+
}
|
|
390238
390431
|
async sendMensagem(state, cod, text, extra) {
|
|
390239
390432
|
try {
|
|
390240
390433
|
await state.client.call("/mensagem", {
|
|
@@ -397161,6 +397354,27 @@ function setupMessageHandlers2(app, instanceId, botUserId, callbacks, dmPolicyCo
|
|
|
397161
397354
|
logger5.info("Message handlers registered", { instanceId });
|
|
397162
397355
|
}
|
|
397163
397356
|
|
|
397357
|
+
// ../channel-slack/src/handlers/pins.ts
|
|
397358
|
+
function setupPinHandlers(app, instanceId, callbacks, logger5) {
|
|
397359
|
+
const handlePinEvent = (action) => async ({ event }) => {
|
|
397360
|
+
const evt = event;
|
|
397361
|
+
const item = evt.item;
|
|
397362
|
+
if (!item || item.type !== "message")
|
|
397363
|
+
return;
|
|
397364
|
+
const message2 = item.message;
|
|
397365
|
+
const channelId = item.channel ?? evt.channel_id ?? "";
|
|
397366
|
+
const messageTs = message2?.ts ?? "";
|
|
397367
|
+
if (!channelId || !messageTs)
|
|
397368
|
+
return;
|
|
397369
|
+
const userId = evt.user;
|
|
397370
|
+
logger5.debug(action === "pin" ? "Pin added" : "Pin removed", { instanceId, channelId, messageTs, userId });
|
|
397371
|
+
await callbacks.onPin(instanceId, messageTs, channelId, userId, action);
|
|
397372
|
+
};
|
|
397373
|
+
app.event("pin_added", handlePinEvent("pin"));
|
|
397374
|
+
app.event("pin_removed", handlePinEvent("unpin"));
|
|
397375
|
+
logger5.info("Pin handlers registered", { instanceId });
|
|
397376
|
+
}
|
|
397377
|
+
|
|
397164
397378
|
// ../channel-slack/src/handlers/reactions.ts
|
|
397165
397379
|
function setupReactionHandlers2(app, instanceId, botUserId, callbacks, logger5) {
|
|
397166
397380
|
const resolveBotUserId = () => typeof botUserId === "function" ? botUserId() : botUserId;
|
|
@@ -398849,6 +399063,15 @@ class SlackPlugin extends BaseChannelPlugin {
|
|
|
398849
399063
|
await this.handleReactionReceived(instId, messageId, chatId, userId, emoji, action);
|
|
398850
399064
|
}
|
|
398851
399065
|
}, this.logger);
|
|
399066
|
+
setupPinHandlers(connection.app, instanceId, {
|
|
399067
|
+
onPin: async (instId, messageId, chatId, userId, action) => {
|
|
399068
|
+
if (action === "pin") {
|
|
399069
|
+
await this.emitMessagePinned({ instanceId: instId, messageId, chatId, from: userId });
|
|
399070
|
+
} else {
|
|
399071
|
+
await this.emitMessageUnpinned({ instanceId: instId, messageId, chatId, from: userId });
|
|
399072
|
+
}
|
|
399073
|
+
}
|
|
399074
|
+
}, this.logger);
|
|
398852
399075
|
setupAgentSessionHandlers(connection.app, instanceId, {
|
|
398853
399076
|
onSessionStopped: async (instId, args) => {
|
|
398854
399077
|
await this.handleAgentSessionStopped(instId, connection, args);
|