n8n-nodes-aib 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -38,6 +38,11 @@ npm install https://app.aibdigitall.com/n8n-nodes-aib.tgz
38
38
  (Em Docker, o diretório é o volume de dados do n8n, ex.:
39
39
  `/home/node/.n8n/nodes` dentro do container.)
40
40
 
41
+ ## Novidades
42
+
43
+ - **0.8.0** — o campo *Conversa* (nó v2) virou seletor: **Da lista** mostra as conversas da conta com busca por nome/telefone (para um destino fixo, como a conversa do gestor que recebe alertas); **Por ID** continua servindo para `{{ $json.data.conversa_id }}` do gatilho.
44
+ - **0.7.2** — evento `followup.retomar` no gatilho (o passo "Agente escreve" do follow-up).
45
+
41
46
  ## Depois de instalar
42
47
 
43
48
  1. Credentials → **AIB Digital API** → URL + chave de agência
@@ -213,10 +213,38 @@ class AibDigital {
213
213
  default: "",
214
214
  required: true,
215
215
  displayOptions: {
216
- show: { operation: ["enviarMensagem", "buscarConversa", "listarMensagens", "moverEtapa", "mudarIa", "atribuirAtendente", "mudarEtiquetas"] },
216
+ show: { "@version": [1], operation: ["enviarMensagem", "buscarConversa", "listarMensagens", "moverEtapa", "mudarIa", "atribuirAtendente", "mudarEtiquetas"] },
217
217
  },
218
218
  description: "Vem do gatilho (data.conversa_id) ou de Listar conversas",
219
219
  },
220
+ {
221
+ // v2: escolher da lista (para um destino fixo, como a conversa do
222
+ // gestor que recebe alertas) ou por ID/expressão (a conversa do
223
+ // gatilho). É o que o nó do Chatwoot tinha e este não tinha.
224
+ displayName: "Conversa",
225
+ name: "conversaId",
226
+ type: "resourceLocator",
227
+ default: { mode: "id", value: "" },
228
+ required: true,
229
+ displayOptions: {
230
+ show: { "@version": [2], operation: ["enviarMensagem", "buscarConversa", "listarMensagens", "moverEtapa", "mudarIa", "atribuirAtendente", "mudarEtiquetas"] },
231
+ },
232
+ description: "Da lista: uma conversa fixa da conta (ex.: a do gestor). Por ID: normalmente {{ $json.data.conversa_id }} do gatilho.",
233
+ modes: [
234
+ {
235
+ displayName: "Da lista",
236
+ name: "list",
237
+ type: "list",
238
+ typeOptions: { searchListMethod: "buscarConversas", searchable: true },
239
+ },
240
+ {
241
+ displayName: "Por ID",
242
+ name: "id",
243
+ type: "string",
244
+ hint: "O UUID da conversa — do gatilho (data.conversa_id) ou de Listar conversas.",
245
+ },
246
+ ],
247
+ },
220
248
  {
221
249
  displayName: "Texto",
222
250
  name: "conteudo",
@@ -536,6 +564,35 @@ class AibDigital {
536
564
  return { results: [] };
537
565
  }
538
566
  },
567
+ async buscarConversas(filtro) {
568
+ const conta = contaDeLista(this);
569
+ try {
570
+ const res = await api(this, "GET", "/api/v1/conversas", undefined, {
571
+ ...(conta ? { conta } : {}),
572
+ ...(filtro ? { q: filtro } : {}),
573
+ limite: "100",
574
+ });
575
+ const conversas = (res?.conversas ?? []);
576
+ // Filtra aqui também: um AIB ainda sem o `q` na API devolve as
577
+ // 100 mais recentes, e a busca continua funcionando.
578
+ const alvo = (filtro ?? "").toLowerCase();
579
+ const digitos = alvo.replace(/\D/g, "");
580
+ return {
581
+ results: conversas.filter((c) => !alvo ||
582
+ (c.contato?.nome ?? "").toLowerCase().includes(alvo) ||
583
+ (digitos.length >= 3 && (c.contato?.telefone ?? "").replace(/\D/g, "").includes(digitos))).map((c) => {
584
+ const nome = c.contato?.nome || "(sem nome)";
585
+ const tel = c.contato?.telefone ? ` · ${c.contato.telefone}` : "";
586
+ const grupo = c.contato?.tipo === "grupo" ? " (grupo)" : "";
587
+ const fechada = c.status === "closed" ? " — encerrada" : "";
588
+ return { name: `${nome}${grupo}${tel}${fechada}`, value: c.id };
589
+ }),
590
+ };
591
+ }
592
+ catch {
593
+ return { results: [] };
594
+ }
595
+ },
539
596
  },
540
597
  loadOptions: {
541
598
  async getContas() {
@@ -621,7 +678,7 @@ class AibDigital {
621
678
  const qs = contaQs(this, i);
622
679
  let res;
623
680
  if (operation === "enviarMensagem") {
624
- const conversaId = this.getNodeParameter("conversaId", i);
681
+ const conversaId = idDe(this.getNodeParameter("conversaId", i));
625
682
  const conteudo = this.getNodeParameter("conteudo", i);
626
683
  const citadaId = this.getNodeParameter("citadaId", i, "");
627
684
  res = await api(this, "POST", `/api/v1/conversas/${conversaId}/mensagens`, { conteudo, citada_id: citadaId || null }, qs);
@@ -637,30 +694,30 @@ class AibDigital {
637
694
  });
638
695
  }
639
696
  else if (operation === "buscarConversa") {
640
- const conversaId = this.getNodeParameter("conversaId", i);
697
+ const conversaId = idDe(this.getNodeParameter("conversaId", i));
641
698
  res = await api(this, "GET", `/api/v1/conversas/${conversaId}`, undefined, qs);
642
699
  }
643
700
  else if (operation === "listarMensagens") {
644
- const conversaId = this.getNodeParameter("conversaId", i);
701
+ const conversaId = idDe(this.getNodeParameter("conversaId", i));
645
702
  res = await api(this, "GET", `/api/v1/conversas/${conversaId}/mensagens`, undefined, qs);
646
703
  }
647
704
  else if (operation === "moverEtapa") {
648
- const conversaId = this.getNodeParameter("conversaId", i);
705
+ const conversaId = idDe(this.getNodeParameter("conversaId", i));
649
706
  const etapaId = this.getNodeParameter("etapaId", i);
650
707
  res = await api(this, "POST", `/api/v1/conversas/${conversaId}/etapa`, { etapa_id: etapaId }, qs);
651
708
  }
652
709
  else if (operation === "mudarIa") {
653
- const conversaId = this.getNodeParameter("conversaId", i);
710
+ const conversaId = idDe(this.getNodeParameter("conversaId", i));
654
711
  const iaAtiva = this.getNodeParameter("iaAtiva", i);
655
712
  res = await api(this, "PATCH", `/api/v1/conversas/${conversaId}`, { ia_ativa: iaAtiva }, qs);
656
713
  }
657
714
  else if (operation === "atribuirAtendente") {
658
- const conversaId = this.getNodeParameter("conversaId", i);
715
+ const conversaId = idDe(this.getNodeParameter("conversaId", i));
659
716
  const atendenteId = this.getNodeParameter("atendenteId", i, "");
660
717
  res = await api(this, "PATCH", `/api/v1/conversas/${conversaId}`, { atendente_id: atendenteId || null }, qs);
661
718
  }
662
719
  else if (operation === "mudarEtiquetas") {
663
- const conversaId = this.getNodeParameter("conversaId", i);
720
+ const conversaId = idDe(this.getNodeParameter("conversaId", i));
664
721
  const separa = (v) => v.split(",").map((x) => x.trim()).filter(Boolean);
665
722
  res = await api(this, "PATCH", `/api/v1/conversas/${conversaId}`, {
666
723
  etiquetas: {
@@ -64,6 +64,7 @@ class AibDigitalTrigger {
64
64
  { name: "Conversa criada (lead novo)", value: "conversa.criada" },
65
65
  { name: "Mensagem enviada (via API)", value: "mensagem.enviada" },
66
66
  { name: "Card movido no funil", value: "conversa.etapa" },
67
+ { name: "Follow-up: agente deve retomar a conversa", value: "followup.retomar" },
67
68
  { name: "Conversa atualizada (IA/status)", value: "conversa.atualizada" },
68
69
  { name: "Resposta humana no painel (legado)", value: "message.outbound" },
69
70
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-aib",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Nós do Sistema AIB Digital para n8n: gatilho de mensagens do WhatsApp (via AIB Inbox) e ações — enviar mensagem, mover card no funil, pausar IA — escolhendo conta e caixa por dropdown.",
5
5
  "license": "MIT",
6
6
  "author": "AIB Digital",