diff --git a/README.md b/README.md index d06a9e5..729fa1a 100644 --- a/README.md +++ b/README.md @@ -1,191 +1,268 @@ -Evolution API +![image](https://github.com/user-attachments/assets/813b7b34-377c-42e8-9f1a-12e27e682c7f)


-Este Community Nodes é uma solução 100% gratuita, criada com o intuito de simplificar e auxiliar toda a comunidade a integrar e utilizar ao máximo os principais recursos oferecidos pela Evolution API v2 em seus projetos. Desenvolvido por OrionDesign.

-🚨 Obs: Ainda em desenvolvimento🚨
+Este Community Nodes é uma solução 100% gratuita, criada com o intuito de simplificar e auxiliar toda a comunidade a integrar e utilizar ao máximo os principais recursos oferecidos pela Evolution API v2.2+ em seus projetos no N8N. Desenvolvido por OrionDesign. +

+
+ +
+ Dynamic JSON Badge +
+
+

+

+ ”SetupOrion”      + ”SetupOrion”      + ”SetupOrion”

-

-

📌 Recurso: Instancia

-Este recurso oferece acesso a todas as principais funcionalidades relacionadas às instâncias da Evolution API. Com ele, você pode realizar diversas operações essenciais, como criar uma nova instância, conectar-se a ela, buscar informações, definir comportamentos personalizados, monitorar presença, reiniciar e até mesmo excluir instâncias de maneira simples e eficiente.

-Segue a lista das funções relacionadas:
-
- Criar Instancia - - O nó "Criar Instância", assim como proprio nome já diz, cria uma nova instância na Evolution API. Você pode configurar o **Nome da Instância**, escolher a **API Key** e o **Número** para geração do "pairingCode", e ainda ajustar diversas opções adicionais, como **Comportamento**, **Proxy**, **Webhook**, **RabbitMQ**, e a integração com **Chatwoot.** Essa flexibilidade permite que à criação da instância seja adaptada a diferentes cenários e necessidades. +

-> Obs: Esta função funciona apenas se estiver usando a `Global API Key` nas credenciais da Evolution API. `ApiKey de instancia` **não** tem poder para criar novas instancias. +

⚙️ Requisitos

+Para utilizar o nosso **Community Node**, é necessário atender aos seguintes requisitos: +- **N8N** na versão **1.54.4** ou superior +- **Evolution API** na versão **2.2.0** ou superior -| Campo | Descrição | Obrigatório | -|----------|----------|----------| -| Nome Da Instância | Nome que será atribuido a instancia | ✅ | -| Apikey Para Instancia | ApiKey (token) que será utilizado para consumir api desta instancia | ❌ | -| Número Do WhatsApp | Numero que será utilizado para se conectar na instancia, usado para gerar o "pairingCode" | ❌ | -| Opções | Configurações e Integrações que podem ser adicionadas a instancia no momento de sua crição | ❌ | +

-Como já descrito, existe o campo de Opções, do qual você pode adicionar novas integrações a sua instancia, veja abaixo mais detalhes sobre cada opção: +

📌 Recursos Disponíveis

+

Instância

+🖥️ Este recurso oferece acesso completo às principais funcionalidades relacionadas às instâncias da Evolution API. Ele permite realizar operações essenciais, como criar novas instâncias, conectar-se a elas, obter informações detalhadas, personalizar comportamentos, monitorar presença, reiniciar e até mesmo excluir instâncias de forma prática e eficiente. +
- 👉🏽 Comportamento - Aqui você pode definir como vai ser o comportamento da instancia: - - | Campo | Descrição | Obrigatório | - |----------|----------|----------| - | Rejeitar Ligações | Rejeitar automaticamente todas as ligações recebidas no Whatsapp | ❌ | - | Mensagem Ao Rejeitar | Mensagem que será enviada automaticamente após rejeitar uma ligação | ❌ | - | Ignorar Grupos | Não receber as mensagens de grupos na API | ❌ | - | Sempre Online | Deixar o Status sempre como Online | ❌ | - | Ler Mensagens | Todas as mensagens serão marcadas como lidas automaticamente, assim que recebidas | ❌ | - | Ler Status | Os Status dos contatos salvos irão chegar na API | ❌ | - | Sincronizar Histórico | Sincronizar todo o histórico de mensagens na API | ❌ | - -
-
- 👉🏽 Proxy - Defina um Proxy para ser usado na instancia: - - | Campo | Descrição | Obrigatório | - |----------|----------|----------| - | Host do Proxy | Endereço ip/url do Proxy | ✅ | - | Porta Do Proxy | Porta do seu Proxy | ✅ | - | Protocolo Do Proxy | Protocolo Http (para IP ou URL sem SSL) ou Https (para URL com SSL) | ✅ | - | Usuário Do Proxy | Usuario do Proxy | ✅ | - | Senha Do Proxy | Senha do Proxy | ✅ | - -
-
- 👉🏽 Webhook - Ative um endereço para consumir o Webhook a partir de eventos da Evolution API - - | Campo | Descrição | Obrigatório | - |----------|----------|----------| - | Url Do Webhook | Url que será enviado os eventos da Evolution API | ✅ | - | Webhook Por Eventos | Cria uma rota para cada evento adicionando o nome do evento no final da URL | ✅ | - | Base64 No Webhook | Envie os dados do base64 das mídias no webhook | ✅ | - | Eventos | Eventos que vai disparar o webhook | ✅ | - -
-
- 👉🏽 RabbitMQ - Sem informações ainda. - -
-
- 👉🏽 Chatwoot - Sem informações ainda. - + Lista de operações +
+    ✅ Criar Instancia +
+
+    ✅ Gerar Qr-Code +
+
+    ✅ Buscar Instancia +
+
+    ✅ Definir Comportamento +
+
+    ✅ Definir Presença +
+
+    ✅ Definir Proxy +
+
+    ✅ Buscar Proxy +
+
+    ✅ Desconectar WhatsApp +
+
+    ✅ Deletar Instancia +
-

- -
-
- Conectar Instancia - - -
-
- Buscar Instancia - -
+

Mensagem

+✉️ Este recurso concentra todas as funcionalidades relacionadas ao envio e gerenciamento de mensagens através da Evolution API. Com ele, você pode enviar diversos tipos de conteúdo como textos, imagens, vídeos, áudios, documentos, contatos, listas interativas, botões e até mesmo mensagens PIX. Cada tipo de mensagem possui opções avançadas como delay, mentions, replies e formatações especiais. O recurso foi desenvolvido para proporcionar uma experiência completa de comunicação, permitindo explorar ao máximo os recursos nativos do WhatsApp de forma simples e eficiente. +
- Definir Comportamento - + Lista de operações +
+    ✅ Enviar Texto +
+
+    ✅ Enviar Imagem +
+
+    ✅ Enviar Video +
+
+    ✅ Enviar Audio +
+
+    ✅ Enviar Documento +
+
+    ✅ Enviar Enquete +
+
+    ✅ Enviar Contato +
+
+    ✅ Enviar Lista +
+
+    ✅ Enviar Botão +
+
+    ✅ Enviar Pix +
+
+    ✅ Enviar Status +
+
+    ✅ Reagir a Mensagem +
+ +

Grupo

+👥 Com este recurso, você conta com um conjunto completo de funcionalidades para gerenciamento de grupos no WhatsApp por meio da Evolution API. Ele abrange desde a criação e administração de grupos até o gerenciamento de participantes, configuração de permissões, links de convite e mensagens temporárias. Tudo foi projetado para oferecer controle eficiente e simplificado na administração de grupos. +
- Definir Presença - + Lista de operações +
+    ✅ Criar Grupo +
+
+    ✅ Atualizar Imagem do Grupo +
+
+    ✅ Atualizar Nome do Grupo +
+
+    ✅ Atualizar Descrição do Grupo +
+
+    ✅ Atualizar Configurações do Grupo +
+
+    ✅ Atualizar Membros +
+
+    ✅ Buscar Link de convite do Grupo +
+
+    ✅ Revogar Link de convite do Grupo +
+
+    ✅ Enviar Link de Convite do Grupo +
+
+    ✅ Encontrar Participantes +
+
+    ✅ Mensagens Temporarias +
+
+    ✅ Sair do Grupo +
+
+    ✅ Entrar no Grupo +
+ +

Chat

+💬 Este recurso disponibiliza um conjunto abrangente de ferramentas para o gerenciamento de conversas e interações utilizando a Evolution API. Com ele, é possível verificar números, enviar e gerenciar mensagens, manipular arquivos de mídia, controlar status de leitura, administrar contatos e monitorar presença. Todas as operações são desenvolvidas para proporcionar um controle completo e eficiente das comunicações, facilitando a gestão tanto de conversas individuais quanto em grupo. +
- Reiniciar Instancia - + Lista de operações +
+    ✅ Verificar Numero +
+
+    ✅ Ler Mensagem +
+
+    ✅ Gerenciar Arquivoo +
+
+    ✅ Marcar como Não lido +
+
+    ✅ Deletar Mensagem +
+
+    ✅ Buscar Foto de Perfil +
+
+    ✅ Obter Midia em Base64 +
+
+    ✅ Editar Mensagem +
+
+    ✅ Enviar Presença +
+
+    ✅ Bloquear Contato +
+
+    ✅ Buscar Contatos +
+
+    ✅ Procurar Mensagens +
+
+    ✅ Procurar Status +
+
+    ✅ Procurar Chats +
+ +

Evento

+⚡ Este recurso oferece mecanismos avançados para integração e monitoramento em tempo real das atividades da Evolution API. Ele permite configurar e gerenciar Webhooks e RabbitMQ, possibilitando o acompanhamento de eventos como mensagens recebidas, alterações em grupos, status de conexão e muito mais. Essas funcionalidades foram projetadas para garantir uma comunicação ágil e automatizada entre sua aplicação e a API, promovendo respostas imediatas a diferentes eventos do WhatsApp. +
- Desconectar Instancia - + Lista de operações +
+    ✅ Webhook +
+
+    ✅ RabbitMQ +
+ +

Integração

+🔗 Este recurso disponibiliza uma ampla gama de conectores para integrar a Evolution API a diversas plataformas e serviços externos. Entre as possibilidades estão conexões com Chatwoot para atendimento ao cliente, Evolution Bot para automações, Typebot para fluxos conversacionais, além de integrações com Flowise e Dify para soluções de inteligência artificial. Essas integrações ampliam as capacidades da API, permitindo criar soluções robustas e automatizadas para diferentes cenários de negócios. +
- Deletar Instancia - + Lista de operações +
+    ✅ Chatwoot +
+
+    ✅ Evolution Bot +
+
+    ✅ Typebot +
+
+    ✅ Dify +
+
+    ✅ Floise +

-

📌 Recurso: Mensagem

-
- Enviar Texto - -
-
- Enviar Imagem - -
-
- Enviar Video - -
-
- Enviar Audio - -
-
- Enviar Documento - -
-
- Enviar Enquete - -
-
- Enviar Status - -
+ +

🤝 Contribuição

+ +Contribua para o crescimento deste projeto! Você pode ajudar de diversas formas: +- **Pull Requests**: Envie melhorias, correções ou novas funcionalidades. +- **Issues**: Relate problemas ou sugira novas ideias. +- **Sugestões**: Compartilhe suas opiniões e feedbacks. +- **Documentação**: Ajude a melhorar ou expandir a documentação existente.

-

📌 Recurso: Evento

-
- Webhook - -
-
- RabbitMQ - -
+ +

📌 Principais contribuidores

+ + + +

-

📌 Recurso: Integração

-
- Proxy - -
-
- Evolution Bot - -
-
- Chatwoot - -
+ + + + + Star History Chart + + -
- Typebot - -
-
- Flowise - -
-
- Dify - -
-
- OpenAI - -
-
- S3 - -
-
-🚨 Obs: Estas opções podem ser adicionadas ou removidas da versão final deste Node.🚨
+

+

+Desenvolvido com ❤️ por OrionDesign +

diff --git a/README_TEMPLATE.md b/README_TEMPLATE.md index 43e5a00..729fa1a 100644 --- a/README_TEMPLATE.md +++ b/README_TEMPLATE.md @@ -1,71 +1,268 @@ -Evolution API +![image](https://github.com/user-attachments/assets/813b7b34-377c-42e8-9f1a-12e27e682c7f)


-Este Community Nodes é uma solução 100% gratuita, criada com o intuito de simplificar e auxiliar toda a comunidade a integrar e utilizar ao máximo os principais recursos oferecidos pela Evolution API v2 em seus projetos. Desenvolvido por OrionDesign.

-🚨 Obs: Ainda em desenvolvimento🚨
+Este Community Nodes é uma solução 100% gratuita, criada com o intuito de simplificar e auxiliar toda a comunidade a integrar e utilizar ao máximo os principais recursos oferecidos pela Evolution API v2.2+ em seus projetos no N8N. Desenvolvido por OrionDesign.

+
+ +
+ Dynamic JSON Badge +
+
+

+

+ ”SetupOrion”      + ”SetupOrion”      + ”SetupOrion” +

+ + +

+ +

⚙️ Requisitos

+ +Para utilizar o nosso **Community Node**, é necessário atender aos seguintes requisitos: +- **N8N** na versão **1.54.4** ou superior +- **Evolution API** na versão **2.2.0** ou superior

-

💡 Features do Node

- -Instancias:
-✅ Criação de Instancia Básica;
-✅ Criação de Instancia com Proxy;
-✅ Busca por Instancia (com e sem filtro);
-✅ Configurações da Instancia;
-✅ Conexão de Instância;
-✅ Reiniciar Instancia;
-✅ Desconectar Instancia;
-✅ Deletar Instancia;
-✅ Set Presence;
+ +

📌 Recursos Disponíveis

+ +

Instância

+🖥️ Este recurso oferece acesso completo às principais funcionalidades relacionadas às instâncias da Evolution API. Ele permite realizar operações essenciais, como criar novas instâncias, conectar-se a elas, obter informações detalhadas, personalizar comportamentos, monitorar presença, reiniciar e até mesmo excluir instâncias de forma prática e eficiente.
-Mensagens:
-✅ Enviar Texto;
-✅ Enviar Imagem;
-✅ Enviar Video;
-✅ Enviar Audio;
-✅ Enviar Documentos;
-✅ Enviar Enquete;
-✅ Enviar Lista;
-✅ Marcação fantasma;
-✅ Enviar Status;
+
+ Lista de operações +
+    ✅ Criar Instancia +
+
+    ✅ Gerar Qr-Code +
+
+    ✅ Buscar Instancia +
+
+    ✅ Definir Comportamento +
+
+    ✅ Definir Presença +
+
+    ✅ Definir Proxy +
+
+    ✅ Buscar Proxy +
+
+    ✅ Desconectar WhatsApp +
+
+    ✅ Deletar Instancia +
+
+ +

Mensagem

+✉️ Este recurso concentra todas as funcionalidades relacionadas ao envio e gerenciamento de mensagens através da Evolution API. Com ele, você pode enviar diversos tipos de conteúdo como textos, imagens, vídeos, áudios, documentos, contatos, listas interativas, botões e até mesmo mensagens PIX. Cada tipo de mensagem possui opções avançadas como delay, mentions, replies e formatações especiais. O recurso foi desenvolvido para proporcionar uma experiência completa de comunicação, permitindo explorar ao máximo os recursos nativos do WhatsApp de forma simples e eficiente.
-Integrações:
-❌ Chatwoot:
-❌ Typebot
-❌ Webhook;
-❌ RabbitMQ;
-❌ OpenAI;
-❌ S3;
+
+ Lista de operações +
+    ✅ Enviar Texto +
+
+    ✅ Enviar Imagem +
+
+    ✅ Enviar Video +
+
+    ✅ Enviar Audio +
+
+    ✅ Enviar Documento +
+
+    ✅ Enviar Enquete +
+
+    ✅ Enviar Contato +
+
+    ✅ Enviar Lista +
+
+    ✅ Enviar Botão +
+
+    ✅ Enviar Pix +
+
+    ✅ Enviar Status +
+
+    ✅ Reagir a Mensagem +
+
+ +

Grupo

+👥 Com este recurso, você conta com um conjunto completo de funcionalidades para gerenciamento de grupos no WhatsApp por meio da Evolution API. Ele abrange desde a criação e administração de grupos até o gerenciamento de participantes, configuração de permissões, links de convite e mensagens temporárias. Tudo foi projetado para oferecer controle eficiente e simplificado na administração de grupos.
-Grupos:
-❌ Criar Grupo;
-❌ Deletar Grupo;
-❌ Atualizar foto do Grupo;
-❌ Alterar descrição do Grupo;
-❌ Altear configurações do Grupo;
-❌ Pegar link de convite do Grupo;
-❌ Adicionar Membro;
-❌ Remover Membro;
-❌ Ver todos os membros do grupo;
-❌ Ver todos os grupos;
-❌ Sair do Grupo;
+
+ Lista de operações +
+    ✅ Criar Grupo +
+
+    ✅ Atualizar Imagem do Grupo +
+
+    ✅ Atualizar Nome do Grupo +
+
+    ✅ Atualizar Descrição do Grupo +
+
+    ✅ Atualizar Configurações do Grupo +
+
+    ✅ Atualizar Membros +
+
+    ✅ Buscar Link de convite do Grupo +
+
+    ✅ Revogar Link de convite do Grupo +
+
+    ✅ Enviar Link de Convite do Grupo +
+
+    ✅ Encontrar Participantes +
+
+    ✅ Mensagens Temporarias +
+
+    ✅ Sair do Grupo +
+
+    ✅ Entrar no Grupo +
+
+

Chat

+💬 Este recurso disponibiliza um conjunto abrangente de ferramentas para o gerenciamento de conversas e interações utilizando a Evolution API. Com ele, é possível verificar números, enviar e gerenciar mensagens, manipular arquivos de mídia, controlar status de leitura, administrar contatos e monitorar presença. Todas as operações são desenvolvidas para proporcionar um controle completo e eficiente das comunicações, facilitando a gestão tanto de conversas individuais quanto em grupo.
-Chats:
-❌ Verificar Numero no Whatsapp;
-❌ Buscar base64/link da mensagem;
-❌ Buscar Contatos;
-❌ Buscar Mensagens;
-❌ Ver todas Tags;
-❌ Aplicar Tag em contato;
+
+ Lista de operações +
+    ✅ Verificar Numero +
+
+    ✅ Ler Mensagem +
+
+    ✅ Gerenciar Arquivoo +
+
+    ✅ Marcar como Não lido +
+
+    ✅ Deletar Mensagem +
+
+    ✅ Buscar Foto de Perfil +
+
+    ✅ Obter Midia em Base64 +
+
+    ✅ Editar Mensagem +
+
+    ✅ Enviar Presença +
+
+    ✅ Bloquear Contato +
+
+    ✅ Buscar Contatos +
+
+    ✅ Procurar Mensagens +
+
+    ✅ Procurar Status +
+
+    ✅ Procurar Chats +
+
+ +

Evento

+⚡ Este recurso oferece mecanismos avançados para integração e monitoramento em tempo real das atividades da Evolution API. Ele permite configurar e gerenciar Webhooks e RabbitMQ, possibilitando o acompanhamento de eventos como mensagens recebidas, alterações em grupos, status de conexão e muito mais. Essas funcionalidades foram projetadas para garantir uma comunicação ágil e automatizada entre sua aplicação e a API, promovendo respostas imediatas a diferentes eventos do WhatsApp.
-Perfil:
-❌ Alterar Nome do Perfil;
-❌ Alterar Status do Perfil;
-❌ Alterar Foto do Perfil;
-❌ Remover Foto do Perfil;
-❌ Ver Configurações de Privacidade;
-❌ Alterar Configurações de Privacidade;
+
+ Lista de operações +
+    ✅ Webhook +
+
+    ✅ RabbitMQ +
+
+ +

Integração

+🔗 Este recurso disponibiliza uma ampla gama de conectores para integrar a Evolution API a diversas plataformas e serviços externos. Entre as possibilidades estão conexões com Chatwoot para atendimento ao cliente, Evolution Bot para automações, Typebot para fluxos conversacionais, além de integrações com Flowise e Dify para soluções de inteligência artificial. Essas integrações ampliam as capacidades da API, permitindo criar soluções robustas e automatizadas para diferentes cenários de negócios.
-🚨 Obs: Estas opções podem ser adicionadas ou removidas da versão final deste Node.🚨
+
+ Lista de operações +
+    ✅ Chatwoot +
+
+    ✅ Evolution Bot +
+
+    ✅ Typebot +
+
+    ✅ Dify +
+
+    ✅ Floise +
+
+ +

+ +

🤝 Contribuição

+ +Contribua para o crescimento deste projeto! Você pode ajudar de diversas formas: +- **Pull Requests**: Envie melhorias, correções ou novas funcionalidades. +- **Issues**: Relate problemas ou sugira novas ideias. +- **Sugestões**: Compartilhe suas opiniões e feedbacks. +- **Documentação**: Ajude a melhorar ou expandir a documentação existente. + +

+ +

📌 Principais contribuidores

+ + + + +

+ + + + + Star History Chart + + + +

+

+Desenvolvido com ❤️ por OrionDesign +

diff --git a/credentials/HttpBinApi.credentials.ts b/credentials/EvolutionApi.credentials.ts similarity index 77% rename from credentials/HttpBinApi.credentials.ts rename to credentials/EvolutionApi.credentials.ts index fc5440b..210cb66 100644 --- a/credentials/HttpBinApi.credentials.ts +++ b/credentials/EvolutionApi.credentials.ts @@ -5,8 +5,8 @@ import { INodeProperties, } from 'n8n-workflow'; -export class HttpBinApi implements ICredentialType { - name = 'httpbinApi'; +export class EvolutionApi implements ICredentialType { + name = 'evolutionApi'; displayName = 'Evolution API'; documentationUrl = 'https://doc.evolution-api.com/pt'; properties: INodeProperties[] = [ @@ -23,7 +23,7 @@ export class HttpBinApi implements ICredentialType { default: '', typeOptions: { password: true, - } + }, }, ]; @@ -38,7 +38,8 @@ export class HttpBinApi implements ICredentialType { test: ICredentialTestRequest = { request: { - baseURL: '={{$credentials["server-url"].startsWith("http") ? $credentials["server-url"] : "https://" + $credentials["server-url"]}}', + baseURL: + '={{$credentials["server-url"].startsWith("http") ? $credentials["server-url"] : "https://" + $credentials["server-url"]}}', url: '/instance/fetchInstances', method: 'GET', headers: { diff --git a/nodes/HttpBin/HttpBin.node.json b/nodes/EvolutionApi/EvolutionApi.node.json similarity index 71% rename from nodes/HttpBin/HttpBin.node.json rename to nodes/EvolutionApi/EvolutionApi.node.json index 25085bd..17023a7 100644 --- a/nodes/HttpBin/HttpBin.node.json +++ b/nodes/EvolutionApi/EvolutionApi.node.json @@ -1,8 +1,11 @@ { "node": "n8n-nodes-base.httpbin", - "nodeVersion": "1.0", - "codexVersion": "1.0", - "categories": ["Development", "Developer Tools"], + "nodeVersion": "1.1", + "codexVersion": "1.1", + "categories": [ + "Development", + "Developer Tools" + ], "resources": { "credentialDocumentation": [ { diff --git a/nodes/EvolutionApi/EvolutionApi.node.ts b/nodes/EvolutionApi/EvolutionApi.node.ts new file mode 100644 index 0000000..8e8d155 --- /dev/null +++ b/nodes/EvolutionApi/EvolutionApi.node.ts @@ -0,0 +1,67 @@ +import { + IExecuteFunctions, + INodeExecutionData, + INodeType, + INodeTypeDescription, + NodeApiError, +} from 'n8n-workflow'; +import { evolutionNodeProperties } from './properties'; +import { resourceOperationsFunctions } from './execute'; + +export class EvolutionApi implements INodeType { + description: INodeTypeDescription = { + displayName: 'Evolution API', + name: 'evolutionApi', + icon: 'file:evolutionapi.svg', + group: ['transform'], + version: 1, + subtitle: '={{$parameter["operation"]}}', + description: 'Interact with Evolution API', + defaults: { + name: 'Evolution API', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'evolutionApi', + required: true, + }, + ], + requestDefaults: { + baseURL: 'https://doc.evolution-api.com/api-reference', + url: '', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + }, + // A estrutura de propriedades do nó: + // • Resources: Recursos disponíveis (Instancia, Mensagens, Eventos, Integrações) + // • Operations: Operações de cada recurso (Ex: Criar instancia, Enviar mensagem, Definir Webhook) + // • Fields: Campos de cada operação + properties: evolutionNodeProperties, + }; + + async execute(this: IExecuteFunctions): Promise { + const resource = this.getNodeParameter('resource', 0) as string; + const operation = this.getNodeParameter('operation', 0) as string; + + // Busca a função para o recurso e operação selecionados + const fn = resourceOperationsFunctions[resource][operation]; + + // Se não encontrar a função, retorna um erro + if (!fn) { + throw new NodeApiError(this.getNode(), { + message: 'Operação não suportada.', + description: `A função "${operation}" para o recurso "${resource}" não é suportada!`, + }); + } + + // Executa a função + const responseData = await fn(this); + + // Retornar apenas o JSON + return [this.helpers.returnJsonArray(responseData)]; + } +} diff --git a/nodes/HttpBin/evolutionapi.svg b/nodes/EvolutionApi/evolutionapi.svg similarity index 100% rename from nodes/HttpBin/evolutionapi.svg rename to nodes/EvolutionApi/evolutionapi.svg diff --git a/nodes/EvolutionApi/execute/chat/blockContact.ts b/nodes/EvolutionApi/execute/chat/blockContact.ts new file mode 100644 index 0000000..07126c7 --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/blockContact.ts @@ -0,0 +1,57 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function blockContact(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const status = ef.getNodeParameter('status', 0) as string; + + const body = { + number: remoteJid, + status, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/updateBlockStatus/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao gerenciar bloqueio do contato', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/checkNumber.ts b/nodes/EvolutionApi/execute/chat/checkNumber.ts new file mode 100644 index 0000000..97c1b7e --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/checkNumber.ts @@ -0,0 +1,57 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function checkNumber(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const numbersString = ef.getNodeParameter('numbers', 0) as string; + + const numbers = numbersString.split(',').map(number => number.trim()); + + const body = { + numbers, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/whatsappNumbers/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao verificar números no WhatsApp', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/deleteMessage.ts b/nodes/EvolutionApi/execute/chat/deleteMessage.ts new file mode 100644 index 0000000..5dc922c --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/deleteMessage.ts @@ -0,0 +1,59 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function deleteMessage(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const messageId = ef.getNodeParameter('messageId', 0) as string; + const fromMe = ef.getNodeParameter('fromMe', 0) as boolean; + + const body = { + id: messageId, + remoteJid, + fromMe, + }; + + const requestOptions: IRequestOptions = { + method: 'DELETE' as IHttpRequestMethods, + uri: `/chat/deleteMessageForEveryone/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao deletar mensagem', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/fetchProfilePicture.ts b/nodes/EvolutionApi/execute/chat/fetchProfilePicture.ts new file mode 100644 index 0000000..943c61f --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/fetchProfilePicture.ts @@ -0,0 +1,55 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function fetchProfilePicture(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const number = ef.getNodeParameter('number', 0) as string; + + const body = { + number, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/fetchProfilePictureUrl/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao buscar foto do perfil', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/findChats.ts b/nodes/EvolutionApi/execute/chat/findChats.ts new file mode 100644 index 0000000..d2c1af0 --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/findChats.ts @@ -0,0 +1,63 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function findChats(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const messageId = ef.getNodeParameter('messageId', 0) as string; + const page = ef.getNodeParameter('page', 0, 1) as number; + const offset = ef.getNodeParameter('offset', 0, 10) as number; + + const body = { + where: { + remoteJid: remoteJid.includes('@') ? remoteJid : `${remoteJid}@s.whatsapp.net`, + id: messageId, + }, + page, + offset, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/findChats/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao buscar chats', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/findContacts.ts b/nodes/EvolutionApi/execute/chat/findContacts.ts new file mode 100644 index 0000000..5c44a40 --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/findContacts.ts @@ -0,0 +1,62 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function findContacts(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const listAll = ef.getNodeParameter('listAll', 0) as boolean; + + let body = {}; + + if (!listAll) { + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + body = { + where: { + id: remoteJid.includes('@') ? remoteJid : `${remoteJid}@s.whatsapp.net`, + }, + }; + } + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/findContacts/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao buscar contatos', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/findMessages.ts b/nodes/EvolutionApi/execute/chat/findMessages.ts new file mode 100644 index 0000000..f01b2a6 --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/findMessages.ts @@ -0,0 +1,63 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function findMessages(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const page = ef.getNodeParameter('page', 0, 1) as number; + const offset = ef.getNodeParameter('offset', 0, 10) as number; + + const body = { + where: { + key: { + remoteJid: remoteJid.includes('@') ? remoteJid : `${remoteJid}@s.whatsapp.net`, + }, + }, + page, + offset, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/findMessages/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao buscar mensagens', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/findStatusMessages.ts b/nodes/EvolutionApi/execute/chat/findStatusMessages.ts new file mode 100644 index 0000000..d3d1e78 --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/findStatusMessages.ts @@ -0,0 +1,64 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function findStatusMessages(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const messageId = ef.getNodeParameter('messageId', 0) as string; + const page = ef.getNodeParameter('page', 0, 1) as number; + const offset = ef.getNodeParameter('offset', 0, 10) as number; + + const body = { + where: { + instanceId: instanceName, + remoteJid: remoteJid.includes('@') ? remoteJid : `${remoteJid}@s.whatsapp.net`, + keyId: messageId, + }, + page, + offset, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/findStatusMessage/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao buscar status das mensagens', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/getMediaBase64.ts b/nodes/EvolutionApi/execute/chat/getMediaBase64.ts new file mode 100644 index 0000000..c1faea9 --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/getMediaBase64.ts @@ -0,0 +1,61 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function getMediaBase64(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const messageId = ef.getNodeParameter('messageId', 0) as string; + const convertToMp4 = ef.getNodeParameter('convertToMp4', 0) as boolean; + + const body = { + message: { + key: { + id: messageId, + }, + }, + convertToMp4, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/getBase64FromMediaMessage/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao obter mídia em Base64', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/manageArchive.ts b/nodes/EvolutionApi/execute/chat/manageArchive.ts new file mode 100644 index 0000000..2db4672 --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/manageArchive.ts @@ -0,0 +1,66 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function manageArchive(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const chat = ef.getNodeParameter('chat', 0) as string; + const archive = ef.getNodeParameter('archive', 0) as boolean; + const fromMe = ef.getNodeParameter('fromMe', 0) as boolean; + const messageId = ef.getNodeParameter('messageId', 0) as string; + + const body = { + lastMessage: { + key: { + remoteJid: chat, + fromMe, + id: messageId + } + }, + chat, + archive, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/archiveChat/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao gerenciar arquivo da conversa', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/markChatUnread.ts b/nodes/EvolutionApi/execute/chat/markChatUnread.ts new file mode 100644 index 0000000..0279b7e --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/markChatUnread.ts @@ -0,0 +1,64 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function markChatUnread(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const chat = ef.getNodeParameter('chat', 0) as string; + const fromMe = ef.getNodeParameter('fromMe', 0) as boolean; + const messageId = ef.getNodeParameter('messageId', 0) as string; + + const body = { + lastMessage: { + key: { + remoteJid: chat, + fromMe, + id: messageId + } + }, + chat, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/markChatUnread/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao marcar conversa como não lida', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/readMessages.ts b/nodes/EvolutionApi/execute/chat/readMessages.ts new file mode 100644 index 0000000..2c98445 --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/readMessages.ts @@ -0,0 +1,63 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function readMessages(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const fromMe = ef.getNodeParameter('fromMe', 0) as boolean; + const messageId = ef.getNodeParameter('messageId', 0) as string; + + const body = { + readMessages: [ + { + remoteJid, + fromMe, + id: messageId, + }, + ], + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/markMessageAsRead/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao marcar mensagens como lidas', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/sendPresence.ts b/nodes/EvolutionApi/execute/chat/sendPresence.ts new file mode 100644 index 0000000..75346cf --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/sendPresence.ts @@ -0,0 +1,59 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendPresence(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const presence = ef.getNodeParameter('presence', 0) as string; + const delay = ef.getNodeParameter('delay', 0) as number; + + const body = { + number: remoteJid, + presence, + delay, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/sendPresence/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao enviar presença', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/chat/updateMessage.ts b/nodes/EvolutionApi/execute/chat/updateMessage.ts new file mode 100644 index 0000000..9eef092 --- /dev/null +++ b/nodes/EvolutionApi/execute/chat/updateMessage.ts @@ -0,0 +1,63 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function updateMessage(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const messageId = ef.getNodeParameter('messageId', 0) as string; + const text = ef.getNodeParameter('text', 0) as string; + + const body = { + number: remoteJid, + key: { + remoteJid, + fromMe: true, + id: messageId, + }, + text, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/updateMessage/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao editar mensagem', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/events/setProxy.ts b/nodes/EvolutionApi/execute/events/setProxy.ts new file mode 100644 index 0000000..9636bd9 --- /dev/null +++ b/nodes/EvolutionApi/execute/events/setProxy.ts @@ -0,0 +1,69 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function setProxy(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + const enabled = ef.getNodeParameter('enabled', 0) || ''; + const proxyHost = ef.getNodeParameter('proxyHost', 0) || '1234'; + const proxyPort = ef.getNodeParameter('proxyPort', 0) || ''; + const proxyProtocol = ef.getNodeParameter('proxyProtocol', 0) || ''; + const proxyUsername = ef.getNodeParameter('proxyUsername', 0) || ''; + const proxyPassword = ef.getNodeParameter('proxyPassword', 0) || ''; + + const body = { + enabled: enabled, + host: proxyHost, + port: proxyPort, + protocol: proxyProtocol, + username: proxyUsername, + password: proxyPassword, + }; + + const options: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/proxy/set/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao configurar proxy', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/events/setRabbitMQ.ts b/nodes/EvolutionApi/execute/events/setRabbitMQ.ts new file mode 100644 index 0000000..7f04105 --- /dev/null +++ b/nodes/EvolutionApi/execute/events/setRabbitMQ.ts @@ -0,0 +1,89 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function setRabbitMQ(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + const resourceForRabbitMQ = ef.getNodeParameter('resourceForRabbitMQ', 0); + + let options: IRequestOptions; + + if (resourceForRabbitMQ === 'setRabbitMQ') { + const enabled = ef.getNodeParameter('enabled', 0); + const rabbitMQEvents = ef.getNodeParameter('rabbitMQEvents', 0) || []; + + const body = { + rabbitmq: { + enabled: enabled, + events: rabbitMQEvents, + }, + }; + + options = { + method: 'POST' as IHttpRequestMethods, + uri: `/rabbitmq/set/${instanceName}`, + body, + json: true, + }; + } else if (resourceForRabbitMQ === 'findRabbitMQ') { + options = { + method: 'GET' as IHttpRequestMethods, + uri: `/rabbitmq/find/${instanceName}`, + json: true, + }; + } else { + const errorData = { + success: false, + error: { + message: 'Operação de RabbitMQ não reconhecida', + details: 'A operação solicitada não é válida para o recurso de RabbitMQ', + code: 'INVALID_OPERATION', + timestamp: new Date().toISOString(), + }, + }; + throw new NodeOperationError(ef.getNode(), errorData.error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao configurar RabbitMQ', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/events/setWebhook.ts b/nodes/EvolutionApi/execute/events/setWebhook.ts new file mode 100644 index 0000000..64f512b --- /dev/null +++ b/nodes/EvolutionApi/execute/events/setWebhook.ts @@ -0,0 +1,95 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function setWebhook(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + const resourceForWebhook = ef.getNodeParameter('resourceForWebhook', 0); + + let options: IRequestOptions; + + if (resourceForWebhook === 'setWebhook') { + const enabled = ef.getNodeParameter('enabled', 0); + const webhookUrl = ef.getNodeParameter('webhookUrl', 0) || 'vazio'; + const webhookByEvents = ef.getNodeParameter('webhookByEvents', 0); + const webhookBase64 = ef.getNodeParameter('webhookBase64', 0); + const webhookEvents = ef.getNodeParameter('webhookEvents', 0) || []; + + const body = { + webhook: { + enabled: enabled, + url: webhookUrl, + webhookByEvents, + webhookBase64, + events: webhookEvents, + }, + }; + + options = { + method: 'POST' as IHttpRequestMethods, + uri: `/webhook/set/${instanceName}`, + body, + json: true, + }; + } else if (resourceForWebhook === 'findWebhook') { + options = { + method: 'GET' as IHttpRequestMethods, + uri: `/webhook/find/${instanceName}`, + json: true, + }; + } else { + const errorData = { + success: false, + error: { + message: 'Operação de webhook não reconhecida', + details: 'A operação solicitada não é válida para o recurso de webhook', + code: 'INVALID_OPERATION', + timestamp: new Date().toISOString(), + }, + }; + throw new NodeOperationError(ef.getNode(), errorData.error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao configurar webhook', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/evolutionRequest.ts b/nodes/EvolutionApi/execute/evolutionRequest.ts new file mode 100644 index 0000000..0fd1d62 --- /dev/null +++ b/nodes/EvolutionApi/execute/evolutionRequest.ts @@ -0,0 +1,18 @@ +import { IExecuteFunctions, IRequestOptions } from 'n8n-workflow'; + +export async function evolutionRequest(ef: IExecuteFunctions, options: IRequestOptions) { + const credentials = await ef.getCredentials('evolutionApi'); + const serverUrl = credentials['server-url']; + const apiKey = credentials.apikey; + + const requestOptions: IRequestOptions = { + ...options, + headers: { + apikey: apiKey, + ...(options.headers || {}), + }, + uri: `${serverUrl}${options.uri}`, + }; + + return await ef.helpers.request(requestOptions); +} diff --git a/nodes/EvolutionApi/execute/groups/createGroup.ts b/nodes/EvolutionApi/execute/groups/createGroup.ts new file mode 100644 index 0000000..f951cdd --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/createGroup.ts @@ -0,0 +1,61 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function createGroup(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const subject = ef.getNodeParameter('subject', 0) as string; + const description = ef.getNodeParameter('description', 0) as string; + const participantsString = ef.getNodeParameter('participants', 0) as string; + + const participants = participantsString.split(',').map(number => number.trim()); + + const body = { + subject, + description, + participants, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/group/create/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao criar grupo', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/fetchGroups.ts b/nodes/EvolutionApi/execute/groups/fetchGroups.ts new file mode 100644 index 0000000..d0abc97 --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/fetchGroups.ts @@ -0,0 +1,77 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function fetchGroups(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const searchMethod = ef.getNodeParameter('searchMethod', 0) as string; + let requestOptions: IRequestOptions; + + switch (searchMethod) { + case 'inviteCode': + const inviteCode = ef.getNodeParameter('inviteCode', 0) as string; + requestOptions = { + method: 'GET' as IHttpRequestMethods, + uri: `/group/inviteInfo/${instanceName}?inviteCode=${inviteCode}`, + json: true, + }; + break; + + case 'groupJid': + const groupJid = ef.getNodeParameter('groupJid', 0) as string; + requestOptions = { + method: 'GET' as IHttpRequestMethods, + uri: `/group/findGroupInfos/${instanceName}?groupJid=${groupJid}`, + json: true, + }; + break; + + case 'fetchAll': + const getParticipants = ef.getNodeParameter('getParticipants', 0) as boolean; + requestOptions = { + method: 'GET' as IHttpRequestMethods, + uri: `/group/fetchAllGroups/${instanceName}?getParticipants=${getParticipants}`, + json: true, + }; + break; + + default: + throw new Error('Método de busca inválido'); + } + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao buscar informações do(s) grupo(s)', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/fetchInviteCode.ts b/nodes/EvolutionApi/execute/groups/fetchInviteCode.ts new file mode 100644 index 0000000..80534b2 --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/fetchInviteCode.ts @@ -0,0 +1,50 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function fetchInviteCode(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const groupJid = ef.getNodeParameter('groupJid', 0) as string; + + const requestOptions: IRequestOptions = { + method: 'GET' as IHttpRequestMethods, + uri: `/group/inviteCode/${instanceName}?groupJid=${groupJid}`, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao buscar código de convite do grupo', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/findParticipants.ts b/nodes/EvolutionApi/execute/groups/findParticipants.ts new file mode 100644 index 0000000..495420f --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/findParticipants.ts @@ -0,0 +1,50 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function findParticipants(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const groupJid = ef.getNodeParameter('groupJid', 0) as string; + + const requestOptions: IRequestOptions = { + method: 'GET' as IHttpRequestMethods, + uri: `/group/participants/${instanceName}?groupJid=${groupJid}`, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao buscar participantes do grupo', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/joinGroup.ts b/nodes/EvolutionApi/execute/groups/joinGroup.ts new file mode 100644 index 0000000..4b96fe9 --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/joinGroup.ts @@ -0,0 +1,50 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function joinGroup(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const inviteCode = ef.getNodeParameter('inviteCode', 0) as string; + + const requestOptions: IRequestOptions = { + method: 'GET' as IHttpRequestMethods, + uri: `/group/acceptInviteCode/${instanceName}?inviteCode=${inviteCode}`, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao entrar no grupo', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/leaveGroup.ts b/nodes/EvolutionApi/execute/groups/leaveGroup.ts new file mode 100644 index 0000000..e58fc2c --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/leaveGroup.ts @@ -0,0 +1,50 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function leaveGroup(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const groupJid = ef.getNodeParameter('groupJid', 0) as string; + + const requestOptions: IRequestOptions = { + method: 'DELETE' as IHttpRequestMethods, + uri: `/group/leaveGroup/${instanceName}?groupJid=${groupJid}`, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao sair do grupo', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/revokeInviteCode.ts b/nodes/EvolutionApi/execute/groups/revokeInviteCode.ts new file mode 100644 index 0000000..ebcad6d --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/revokeInviteCode.ts @@ -0,0 +1,50 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function revokeInviteCode(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const groupJid = ef.getNodeParameter('groupJid', 0) as string; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/group/revokeInviteCode/${instanceName}?groupJid=${groupJid}`, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao revogar código de convite do grupo', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/sendInviteLink.ts b/nodes/EvolutionApi/execute/groups/sendInviteLink.ts new file mode 100644 index 0000000..a614930 --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/sendInviteLink.ts @@ -0,0 +1,61 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendInviteLink(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const groupJid = ef.getNodeParameter('groupJid', 0) as string; + const description = ef.getNodeParameter('description', 0) as string; + const numbersString = ef.getNodeParameter('numbers', 0) as string; + + const numbers = numbersString.split(',').map(number => number.trim()); + + const body = { + groupJid, + description, + numbers, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/group/sendInvite/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao enviar link de convite do grupo', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/toggleEphemeral.ts b/nodes/EvolutionApi/execute/groups/toggleEphemeral.ts new file mode 100644 index 0000000..748a91d --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/toggleEphemeral.ts @@ -0,0 +1,56 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function toggleEphemeral(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const groupJid = ef.getNodeParameter('groupJid', 0) as string; + const expiration = ef.getNodeParameter('expiration', 0) as number; + + const body = { + expiration, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/group/toggleEphemeral/${instanceName}?groupJid=${groupJid}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao configurar mensagens temporárias', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/updateGroupDescription.ts b/nodes/EvolutionApi/execute/groups/updateGroupDescription.ts new file mode 100644 index 0000000..3e1f501 --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/updateGroupDescription.ts @@ -0,0 +1,56 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function updateGroupDescription(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const groupJid = ef.getNodeParameter('groupJid', 0) as string; + const description = ef.getNodeParameter('description', 0) as string; + + const body = { + description, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/group/updateGroupDescription/${instanceName}?groupJid=${groupJid}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao atualizar descrição do grupo', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/updateGroupName.ts b/nodes/EvolutionApi/execute/groups/updateGroupName.ts new file mode 100644 index 0000000..4ff3891 --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/updateGroupName.ts @@ -0,0 +1,56 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function updateGroupName(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const groupJid = ef.getNodeParameter('groupJid', 0) as string; + const subject = ef.getNodeParameter('subject', 0) as string; + + const body = { + subject, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/group/updateGroupSubject/${instanceName}?groupJid=${groupJid}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao atualizar nome do grupo', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/updateGroupPicture.ts b/nodes/EvolutionApi/execute/groups/updateGroupPicture.ts new file mode 100644 index 0000000..4dcfa0f --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/updateGroupPicture.ts @@ -0,0 +1,56 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function updateGroupPicture(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const groupJid = ef.getNodeParameter('groupJid', 0) as string; + const image = ef.getNodeParameter('image', 0) as string; + + const body = { + image, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/group/updateGroupPicture/${instanceName}?groupJid=${groupJid}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao atualizar imagem do grupo', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/updateParticipants.ts b/nodes/EvolutionApi/execute/groups/updateParticipants.ts new file mode 100644 index 0000000..68cd2dc --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/updateParticipants.ts @@ -0,0 +1,60 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function updateParticipants(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const groupJid = ef.getNodeParameter('groupJid', 0) as string; + const action = ef.getNodeParameter('action', 0) as string; + const participantsString = ef.getNodeParameter('participants', 0) as string; + + const participants = participantsString.split(',').map(number => number.trim()); + + const body = { + action, + participants, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/group/updateParticipant/${instanceName}?groupJid=${groupJid}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao atualizar membros do grupo', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/groups/updateSettings.ts b/nodes/EvolutionApi/execute/groups/updateSettings.ts new file mode 100644 index 0000000..24d5dbc --- /dev/null +++ b/nodes/EvolutionApi/execute/groups/updateSettings.ts @@ -0,0 +1,56 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function updateSettings(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const groupJid = ef.getNodeParameter('groupJid', 0) as string; + const action = ef.getNodeParameter('action', 0) as string; + + const body = { + action, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/group/updateSetting/${instanceName}?groupJid=${groupJid}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao atualizar configurações do grupo', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/index.ts b/nodes/EvolutionApi/execute/index.ts new file mode 100644 index 0000000..9d75269 --- /dev/null +++ b/nodes/EvolutionApi/execute/index.ts @@ -0,0 +1,152 @@ +import { IExecuteFunctions } from 'n8n-workflow'; +import { createInstanceBasic } from './instance/createInstanceBasic'; +import { deleteInstance } from './instance/deleteInstance'; +import { fetchInstances } from './instance/fetchInstances'; +import { instanceConnect } from './instance/instanceConnect'; +import { instanceSettings } from './instance/instanceSettings'; +import { logoutInstance } from './instance/logoutInstance'; +import { restartInstance } from './instance/restartInstance'; +import { setPresence } from './instance/setPresence'; +import { setProxy } from './instance/setProxy'; +import { setChatwoot } from './integrations/setChatwoot'; +import { setEvolutionBot } from './integrations/setEvolutionBot'; +import { setTypebot } from './integrations/setTypebot'; +import { sendAudio } from './messages/sendAudio'; +import { sendDocument } from './messages/sendDocument'; +import { sendImage } from './messages/sendImage'; +import { sendPoll } from './messages/sendPoll'; +import { sendContact } from './messages/sendContact'; +import { sendStories } from './messages/sendStories'; +import { sendText } from './messages/sendText'; +import { sendVideo } from './messages/sendVideo'; +import { setRabbitMQ } from './events/setRabbitMQ'; +import { setWebhook } from './events/setWebhook'; +import { setDifyBot } from './integrations/setDifyBot'; +import { setFlowiseBot } from './integrations/setFlowiseBot'; +import { sendList } from './messages/sendList'; +import { sendButtons } from './messages/sendButtons'; +import { sendPix } from './messages/sendPix'; +import { sendReaction } from './messages/sendReaction'; +import { createGroup } from './groups/createGroup'; +import { updateGroupPicture } from './groups/updateGroupPicture'; +import { updateGroupName } from './groups/updateGroupName'; +import { updateGroupDescription } from './groups/updateGroupDescription'; +import { fetchInviteCode } from './groups/fetchInviteCode'; +import { revokeInviteCode } from './groups/revokeInviteCode'; +import { sendInviteLink } from './groups/sendInviteLink'; +import { fetchGroups } from './groups/fetchGroups'; +import { findParticipants } from './groups/findParticipants'; +import { updateParticipants } from './groups/updateParticipants'; +import { updateSettings } from './groups/updateSettings'; +import { toggleEphemeral } from './groups/toggleEphemeral'; +import { leaveGroup } from './groups/leaveGroup'; +import { checkNumber } from './chat/checkNumber'; +import { readMessages } from './chat/readMessages'; +import { manageArchive } from './chat/manageArchive'; +import { markChatUnread } from './chat/markChatUnread'; +import { deleteMessage } from './chat/deleteMessage'; +import { fetchProfilePicture } from './chat/fetchProfilePicture'; +import { getMediaBase64 } from './chat/getMediaBase64'; +import { updateMessage } from './chat/updateMessage'; +import { sendPresence } from './chat/sendPresence'; +import { blockContact } from './chat/blockContact'; +import { findContacts } from './chat/findContacts'; +import { findMessages } from './chat/findMessages'; +import { findStatusMessages } from './chat/findStatusMessages'; +import { findChats } from './chat/findChats'; +import { fetchBusinessProfile } from './profile/fetchBusinessProfile'; +import { fetchProfile } from './profile/fetchProfile'; +import { updateProfileName } from './profile/updateProfileName'; +import { updateProfileStatus } from './profile/updateProfileStatus'; +import { updateProfilePicture } from './profile/updateProfilePicture'; +import { removeProfilePicture } from './profile/removeProfilePicture'; +import { fetchPrivacySettings } from './profile/fetchPrivacySettings'; +import { updatePrivacySettings } from './profile/updatePrivacySettings'; +import { joinGroup } from './groups/joinGroup'; +type ResourceOperationFunctions = { + [resource: string]: { + [operation: string]: (ef: IExecuteFunctions) => Promise; + }; +}; + +// este dicionario é utilizado para mapear as operações disponíveis para cada recurso e operação para cada função +export const resourceOperationsFunctions: ResourceOperationFunctions = { + 'instances-api': { + 'instance-basic': createInstanceBasic, + 'instance-connect': instanceConnect, + 'restart-instance': restartInstance, + 'logout-instance': logoutInstance, + 'set-presence': setPresence, + 'delete-instance': deleteInstance, + 'fetch-instances': fetchInstances, + 'instance-settings': instanceSettings, + 'set-proxy': setProxy, + }, + 'messages-api': { + 'send-text': sendText, + 'send-image': sendImage, + 'send-video': sendVideo, + 'send-audio': sendAudio, + 'send-document': sendDocument, + 'send-poll': sendPoll, + 'send-contact': sendContact, + 'send-list': sendList, + 'send-buttons': sendButtons, + 'send-stories': sendStories, + 'send-pix': sendPix, + 'send-reaction': sendReaction, + }, + 'events-api': { + 'webhook': setWebhook, + 'rabbitmq': setRabbitMQ, + }, + 'integrations-api': { + 'chatwoot': setChatwoot, + 'typebot': setTypebot, + 'evolution-bot': setEvolutionBot, + 'dify-bot': setDifyBot, + 'flowise-bot': setFlowiseBot, + }, + 'groups-api': { + 'create-group': createGroup, + 'update-group-picture': updateGroupPicture, + 'update-group-name': updateGroupName, + 'update-group-description': updateGroupDescription, + 'fetch-invite-code': fetchInviteCode, + 'revoke-invite-code': revokeInviteCode, + 'send-invite-link': sendInviteLink, + 'fetch-groups': fetchGroups, + 'find-participants': findParticipants, + 'update-participants': updateParticipants, + 'update-settings': updateSettings, + 'toggle-ephemeral': toggleEphemeral, + 'join-group': joinGroup, + 'leave-group': leaveGroup, + }, + 'chat-api': { + 'check-number': checkNumber, + 'read-messages': readMessages, + 'manage-archive': manageArchive, + 'mark-unread': markChatUnread, + 'delete-message': deleteMessage, + 'fetch-profile-picture': fetchProfilePicture, + 'get-media-base64': getMediaBase64, + 'update-message': updateMessage, + 'send-presence': sendPresence, + 'block-contact': blockContact, + 'find-contacts': findContacts, + 'find-messages': findMessages, + 'find-status-messages': findStatusMessages, + 'find-chats': findChats, + }, + 'profile-api': { + 'fetch-profile': fetchProfile, + 'fetch-business-profile': fetchBusinessProfile, + 'update-profile-name': updateProfileName, + 'update-profile-status': updateProfileStatus, + 'update-profile-picture': updateProfilePicture, + 'remove-profile-picture': removeProfilePicture, + 'fetch-privacy-settings': fetchPrivacySettings, + 'update-privacy-settings': updatePrivacySettings, + }, +}; diff --git a/nodes/EvolutionApi/execute/instance/createInstanceBasic.ts b/nodes/EvolutionApi/execute/instance/createInstanceBasic.ts new file mode 100644 index 0000000..8721cd8 --- /dev/null +++ b/nodes/EvolutionApi/execute/instance/createInstanceBasic.ts @@ -0,0 +1,180 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function createInstanceBasic(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + const token = ef.getNodeParameter('token', 0) || ''; + const number = ef.getNodeParameter('number', 0) || ''; + + const body: any = { + instanceName, + integration: 'WHATSAPP-BAILEYS', + }; + + if (token) { + body.token = token; + } + if (number) { + body.number = number; + } + + // Verifica e adiciona configurações da instância se existirem + const instanceSettings = ef.getNodeParameter( + 'options_Create_instance.instanceSettings.settings', + 0, + {}, + ) as { + rejectCall?: boolean; + msgCall?: string; + groupsIgnore?: boolean; + alwaysOnline?: boolean; + readMessages?: boolean; + readStatus?: boolean; + syncFullHistory?: boolean; + }; + if (instanceSettings && Object.keys(instanceSettings).length > 0) { + Object.assign(body, instanceSettings); + } + + // Verifica e adiciona configurações de proxy se existirem + const proxySettings = ef.getNodeParameter( + 'options_Create_instance.proxy.proxySettings', + 0, + {}, + ) as { + proxyHost?: string; + proxyPort?: number; + proxyProtocol?: string; + proxyUsername?: string; + proxyPassword?: string; + }; + if (proxySettings && Object.keys(proxySettings).length > 0) { + Object.assign(body, { + proxyHost: proxySettings.proxyHost || '', + proxyPort: proxySettings.proxyPort ? String(proxySettings.proxyPort) : '1234', + proxyProtocol: proxySettings.proxyProtocol || '', + proxyUsername: proxySettings.proxyUsername || '', + proxyPassword: proxySettings.proxyPassword || '', + }); + } + + // Verifica e adiciona configurações do Webhook se existirem + const webhookSettings = ef.getNodeParameter( + 'options_Create_instance.webhook.webhookSettings', + 0, + {}, + ) as { + webhookUrl?: string; + webhookByEvents?: boolean; + webhookBase64?: boolean; + webhookEvents?: string[]; + }; + + if (webhookSettings && Object.keys(webhookSettings).length > 0) { + Object.assign(body, { + webhook: { + url: webhookSettings.webhookUrl || '', + byEvents: webhookSettings.webhookByEvents || false, + base64: webhookSettings.webhookBase64 || false, + events: webhookSettings.webhookEvents || [], + }, + }); + } + + // Verifica e adiciona configurações do RabbitMQ se existirem + const rabbitmqSettings = ef.getNodeParameter( + 'options_Create_instance.rabbitmq.rabbitmqSettings', + 0, + {}, + ) as { + rabbitmqEnabled?: boolean; + rabbitmqEvents?: string[]; + }; + if (rabbitmqSettings && Object.keys(rabbitmqSettings).length > 0) { + Object.assign(body, { + rabbitmq: { + enabled: rabbitmqSettings.rabbitmqEnabled || false, + events: rabbitmqSettings.rabbitmqEvents || [], + }, + }); + } + + // Verifica e adiciona configurações do Chatwoot se existirem + const chatwootSettings = ef.getNodeParameter( + 'options_Create_instance.chatwoot.chatwootSettings', + 0, + {}, + ) as { + chatwootAccountId?: number; + chatwootToken?: string; + chatwootUrl?: string; + chatwootSignMsg?: boolean; + chatwootReopenConversation?: boolean; + chatwootConversationPending?: boolean; + chatwootImportContacts?: boolean; + chatwootNameInbox?: string; + chatwootMergeBrazilContacts?: boolean; + chatwootImportMessages?: boolean; + chatwootDaysLimitImportMessages?: number; + chatwootOrganization?: string; + chatwootLogo?: string; + }; + + // Adiciona todos os campos do Chatwoot + if (chatwootSettings && Object.keys(chatwootSettings).length > 0) { + Object.assign(body, { + chatwootAccountId: chatwootSettings.chatwootAccountId || '', + chatwootToken: chatwootSettings.chatwootToken || '', + chatwootUrl: chatwootSettings.chatwootUrl || '', + chatwootSignMsg: chatwootSettings.chatwootSignMsg !== undefined ? chatwootSettings.chatwootSignMsg : false, + }); + } + + const options: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/instance/create`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao criar instância', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/instance/deleteInstance.ts b/nodes/EvolutionApi/execute/instance/deleteInstance.ts new file mode 100644 index 0000000..78be3de --- /dev/null +++ b/nodes/EvolutionApi/execute/instance/deleteInstance.ts @@ -0,0 +1,53 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function deleteInstance(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + + const options: IRequestOptions = { + method: 'DELETE' as IHttpRequestMethods, + uri: `/instance/delete/${instanceName}`, + json: true, + }; + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao deletar instância', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/instance/fetchInstances.ts b/nodes/EvolutionApi/execute/instance/fetchInstances.ts new file mode 100644 index 0000000..544e84d --- /dev/null +++ b/nodes/EvolutionApi/execute/instance/fetchInstances.ts @@ -0,0 +1,53 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function fetchInstances(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + + const options: IRequestOptions = { + method: 'GET' as IHttpRequestMethods, + uri: `/instance/fetchInstances${instanceName ? `?instanceName=${instanceName}` : ''}`, + json: true, + }; + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao buscar instâncias', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/instance/instanceConnect.ts b/nodes/EvolutionApi/execute/instance/instanceConnect.ts new file mode 100644 index 0000000..957ec74 --- /dev/null +++ b/nodes/EvolutionApi/execute/instance/instanceConnect.ts @@ -0,0 +1,53 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function instanceConnect(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + + const options: IRequestOptions = { + method: 'GET' as IHttpRequestMethods, + uri: `/instance/connect/${instanceName}`, + json: true, + }; + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao conectar instância', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/instance/instanceSettings.ts b/nodes/EvolutionApi/execute/instance/instanceSettings.ts new file mode 100644 index 0000000..9d32178 --- /dev/null +++ b/nodes/EvolutionApi/execute/instance/instanceSettings.ts @@ -0,0 +1,78 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function instanceSettings(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + const rejectCall = ef.getNodeParameter('rejectCall', 0); + const msgCall = ef.getNodeParameter('msgCall', 0) || ''; + const groupsIgnore = ef.getNodeParameter('groupsIgnore', 0); + const alwaysOnline = ef.getNodeParameter('alwaysOnline', 0); + const readMessages = ef.getNodeParameter('readMessages', 0); + const syncFullHistory = ef.getNodeParameter('syncFullHistory', 0); + const readStatus = ef.getNodeParameter('readStatus', 0); + + const body: any = { + rejectCall, + msgCall: msgCall || '', + groupsIgnore, + alwaysOnline, + readMessages, + syncFullHistory, + readStatus, + }; + + if (rejectCall) { + body.msgCall = msgCall || ''; + } + + const options: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/settings/set/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao definir configurações da instância', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/instance/logoutInstance.ts b/nodes/EvolutionApi/execute/instance/logoutInstance.ts new file mode 100644 index 0000000..4c48d6e --- /dev/null +++ b/nodes/EvolutionApi/execute/instance/logoutInstance.ts @@ -0,0 +1,53 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function logoutInstance(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + + const options: IRequestOptions = { + method: 'DELETE' as IHttpRequestMethods, + uri: `/instance/logout/${instanceName}`, + json: true, + }; + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao desconectar instância', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/instance/restartInstance.ts b/nodes/EvolutionApi/execute/instance/restartInstance.ts new file mode 100644 index 0000000..972aba0 --- /dev/null +++ b/nodes/EvolutionApi/execute/instance/restartInstance.ts @@ -0,0 +1,53 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function restartInstance(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + + const options: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/instance/restart/${instanceName}`, + json: true, + }; + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao reiniciar instância', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/instance/setPresence.ts b/nodes/EvolutionApi/execute/instance/setPresence.ts new file mode 100644 index 0000000..e26974c --- /dev/null +++ b/nodes/EvolutionApi/execute/instance/setPresence.ts @@ -0,0 +1,60 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function setPresence(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + const presence = ef.getNodeParameter('presence', 0); + + const options: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/instance/setPresence/${instanceName}`, + body: { + 'presence': presence + }, + json: true, + }; + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao definir presença da instância', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/instance/setProxy.ts b/nodes/EvolutionApi/execute/instance/setProxy.ts new file mode 100644 index 0000000..36e282c --- /dev/null +++ b/nodes/EvolutionApi/execute/instance/setProxy.ts @@ -0,0 +1,95 @@ +import { evolutionRequest } from '../evolutionRequest'; +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; + +export async function setProxy(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + const resourceForProxy = ef.getNodeParameter('resourceForProxy', 0); + + let options: IRequestOptions; + + if (resourceForProxy === 'setProxy') { + const enabled = ef.getNodeParameter('enabled', 0) || ''; + const proxyHost = ef.getNodeParameter('proxyHost', 0) || '1234'; + const proxyPort = ef.getNodeParameter('proxyPort', 0) || ''; + const proxyProtocol = ef.getNodeParameter('proxyProtocol', 0) || ''; + const proxyUsername = ef.getNodeParameter('proxyUsername', 0) || ''; + const proxyPassword = ef.getNodeParameter('proxyPassword', 0) || ''; + + const body = { + enabled: enabled, + host: proxyHost, + port: proxyPort, + protocol: proxyProtocol, + username: proxyUsername, + password: proxyPassword, + }; + + options = { + method: 'POST' as IHttpRequestMethods, + uri: `/proxy/set/${instanceName}`, + body, + json: true, + }; + } else if (resourceForProxy === 'findProxy') { + options = { + method: 'GET' as IHttpRequestMethods, + uri: `/proxy/find/${instanceName}`, + json: true, + }; + } else { + const errorData = { + success: false, + error: { + message: 'Operação de Proxy não reconhecida', + details: 'A operação solicitada não é válida para o recurso de Proxy', + code: 'INVALID_OPERATION', + timestamp: new Date().toISOString(), + }, + }; + throw new NodeOperationError(ef.getNode(), errorData.error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao configurar proxy', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/integrations/setChatwoot.ts b/nodes/EvolutionApi/execute/integrations/setChatwoot.ts new file mode 100644 index 0000000..3315005 --- /dev/null +++ b/nodes/EvolutionApi/execute/integrations/setChatwoot.ts @@ -0,0 +1,114 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function setChatwoot(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + const resourceForChatwoot = ef.getNodeParameter('resourceForChatwoot', 0); + + let options: IRequestOptions; + + if (resourceForChatwoot === 'setChatwoot') { + const accountId = ef.getNodeParameter('chatwootAccountId', 0) as string; + const token = ef.getNodeParameter('chatwootToken', 0) as string; + const url = ef.getNodeParameter('chatwootUrl', 0) as string; + const signMsg = ef.getNodeParameter('chatwootSignMsg', 0) as boolean; + const reopenConversation = ef.getNodeParameter('chatwootReopenConversation', 0) as boolean; + const conversationPending = ef.getNodeParameter('chatwootConversationPending', 0) as boolean; + const nameInbox = ef.getNodeParameter('chatwootNameInbox', 0) as string; + const mergeBrazilContacts = ef.getNodeParameter('chatwootMergeBrazilContacts', 0) as boolean; + const importContacts = ef.getNodeParameter('chatwootImportContacts', 0) as boolean; + const importMessages = ef.getNodeParameter('chatwootImportMessages', 0) as boolean; + const daysLimitImportMessages = ef.getNodeParameter('chatwootDaysLimitImportMessages', 0) as number; + const autoCreate = ef.getNodeParameter('chatwootAutoCreate', 0) as boolean; + const organization = ef.getNodeParameter('chatwootOrganization', 0) as string; + const logo = ef.getNodeParameter('chatwootLogo', 0) as string; + + const body = { + enabled: true, + accountId, + token, + url, + signMsg, + reopenConversation, + conversationPending, + nameInbox, + mergeBrazilContacts, + importContacts, + importMessages, + daysLimitImportMessages, + signDelimiter: '\n', + autoCreate, + organization, + logo, + ignoreJids: [''] + }; + + options = { + method: 'POST' as IHttpRequestMethods, + uri: `/chatwoot/set/${instanceName}`, + body, + json: true, + }; + } else if (resourceForChatwoot === 'findChatwoot') { + options = { + method: 'GET' as IHttpRequestMethods, + uri: `/chatwoot/find/${instanceName}`, + json: true, + }; + } else { + const errorData = { + success: false, + error: { + message: 'Operação do Chatwoot não reconhecida', + details: 'A operação solicitada não é válida para o recurso do Chatwoot', + code: 'INVALID_OPERATION', + timestamp: new Date().toISOString(), + }, + }; + throw new NodeOperationError(ef.getNode(), errorData.error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao configurar Chatwoot', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/integrations/setDifyBot.ts b/nodes/EvolutionApi/execute/integrations/setDifyBot.ts new file mode 100644 index 0000000..32bf236 --- /dev/null +++ b/nodes/EvolutionApi/execute/integrations/setDifyBot.ts @@ -0,0 +1,177 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function setDifyBot(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + const resourceForDifyBot = ef.getNodeParameter('resourceForDifyBot', 0); + + let options: IRequestOptions; + + if (resourceForDifyBot === 'createDify') { + const apiUrl = ef.getNodeParameter('apiUrl', 0) as string; + const apiKey = ef.getNodeParameter('apiKey', 0) as string; + const botType = ef.getNodeParameter('botType', 0) as string; + const triggerType = ef.getNodeParameter('triggerType', 0) as string; + const triggerOperator = ef.getNodeParameter('triggerOperator', 0) as string; + const triggerValue = ef.getNodeParameter('triggerValue', 0) as string; + const expire = ef.getNodeParameter('expire', 0) as number; + const keywordFinish = ef.getNodeParameter('keywordFinish', 0) as string; + const delayMessage = ef.getNodeParameter('delayMessage', 0) as number; + const unknownMessage = ef.getNodeParameter('unknownMessage', 0) as string; + const listeningFromMe = ef.getNodeParameter('listeningFromMe', 0) as boolean; + const stopBotFromMe = ef.getNodeParameter('stopBotFromMe', 0) as boolean; + const keepOpen = ef.getNodeParameter('keepOpen', 0) as boolean; + const debounceTime = ef.getNodeParameter('debounceTime', 0) as number; + const ignoreJids = ef.getNodeParameter('ignoreJids', 0) as string[]; + + const body = { + enabled: true, + apiUrl, + apiKey, + botType, + triggerType, + triggerOperator, + triggerValue, + expire, + keywordFinish, + delayMessage, + unknownMessage, + listeningFromMe, + stopBotFromMe, + keepOpen, + debounceTime, + ignoreJids: ignoreJids || [] + }; + + options = { + method: 'POST' as IHttpRequestMethods, + uri: `/dify/create/${instanceName}`, + body, + json: true, + }; + } else if (resourceForDifyBot === 'findDify') { + const difyBotId = ef.getNodeParameter('difyBotId', 0) as string; + + options = { + method: 'GET' as IHttpRequestMethods, + uri: difyBotId + ? `/dify/fetch/${difyBotId}/${instanceName}` + : `/dify/find/${instanceName}`, + json: true, + }; + } else if (resourceForDifyBot === 'deleteDify') { + const difyBotId = ef.getNodeParameter('difyBotId', 0) as string; + + options = { + method: 'DELETE' as IHttpRequestMethods, + uri: `/dify/delete/${difyBotId}/${instanceName}`, + json: true, + }; + } else if (resourceForDifyBot === 'updateDify') { + const difyBotId = ef.getNodeParameter('difyBotId', 0) as string; + const apiUrl = ef.getNodeParameter('apiUrl', 0) as string; + const apiKey = ef.getNodeParameter('apiKeyBot', 0) as string; + const botType = ef.getNodeParameter('botType', 0) as string; + const triggerType = ef.getNodeParameter('triggerType', 0) as string; + const triggerOperator = ef.getNodeParameter('triggerOperator', 0) as string; + const triggerValue = ef.getNodeParameter('triggerValue', 0) as string; + const expire = ef.getNodeParameter('expire', 0) as number; + const keywordFinish = ef.getNodeParameter('keywordFinish', 0) as string; + const delayMessage = ef.getNodeParameter('delayMessage', 0) as number; + const unknownMessage = ef.getNodeParameter('unknownMessage', 0) as string; + const listeningFromMe = ef.getNodeParameter('listeningFromMe', 0) as boolean; + const stopBotFromMe = ef.getNodeParameter('stopBotFromMe', 0) as boolean; + const keepOpen = ef.getNodeParameter('keepOpen', 0) as boolean; + const debounceTime = ef.getNodeParameter('debounceTime', 0) as number; + const ignoreJids = ef.getNodeParameter('ignoreJids', 0) as string[]; + + const body = { + enabled: true, + botType, + apiUrl, + apiKey, + triggerType, + triggerOperator, + triggerValue, + expire, + keywordFinish, + delayMessage, + unknownMessage, + listeningFromMe, + stopBotFromMe, + keepOpen, + debounceTime, + ignoreJids: ignoreJids || [] + }; + + options = { + method: 'PUT' as IHttpRequestMethods, + uri: `/dify/update/${difyBotId}/${instanceName}`, + body, + json: true, + }; + } else if (resourceForDifyBot === 'fetchSessionsDify') { + const difyBotId = ef.getNodeParameter('difyBotId', 0) as string; + + options = { + method: 'GET' as IHttpRequestMethods, + uri: `/dify/fetchSessions/${difyBotId}/${instanceName}`, + json: true, + }; + } else { + const errorData = { + success: false, + error: { + message: 'Operação do Dify não reconhecida', + details: 'A operação solicitada não é válida para o recurso do Dify', + code: 'INVALID_OPERATION', + timestamp: new Date().toISOString(), + }, + }; + throw new NodeOperationError(ef.getNode(), errorData.error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao configurar Dify', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/integrations/setEvolutionBot.ts b/nodes/EvolutionApi/execute/integrations/setEvolutionBot.ts new file mode 100644 index 0000000..1dc9bea --- /dev/null +++ b/nodes/EvolutionApi/execute/integrations/setEvolutionBot.ts @@ -0,0 +1,186 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function setEvolutionBot(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + const resourceForEvolutionBot = ef.getNodeParameter('resourceForEvolutionBot', 0); + + let options: IRequestOptions; + + if (resourceForEvolutionBot === 'createEvolutionBot') { + const apiUrl = ef.getNodeParameter('apiUrl', 0) as string; + const apiKey = ef.getNodeParameter('apiKeyBot', 0) as string; + const triggerType = ef.getNodeParameter('triggerType', 0) as string; + const triggerOperator = ef.getNodeParameter('triggerOperator', 0) as string; + const triggerValue = ef.getNodeParameter('triggerValue', 0) as string; + const expire = ef.getNodeParameter('expire', 0) as number; + const keywordFinish = ef.getNodeParameter('keywordFinish', 0) as string; + const delayMessage = ef.getNodeParameter('delayMessage', 0) as number; + const unknownMessage = ef.getNodeParameter('unknownMessage', 0) as string; + const listeningFromMe = ef.getNodeParameter('listeningFromMe', 0) as boolean; + const stopBotFromMe = ef.getNodeParameter('stopBotFromMe', 0) as boolean; + const keepOpen = ef.getNodeParameter('keepOpen', 0) as boolean; + const debounceTime = ef.getNodeParameter('debounceTime', 0) as number; + const ignoreJids = ef.getNodeParameter('ignoreJids', 0) as string[]; + + const body = { + enabled: true, + apiUrl, + ...(apiKey && { apiKey }), + triggerType, + triggerOperator, + triggerValue, + expire, + keywordFinish, + delayMessage, + unknownMessage, + listeningFromMe, + stopBotFromMe, + keepOpen, + debounceTime, + ignoreJids: ignoreJids || [] + }; + + options = { + method: 'POST' as IHttpRequestMethods, + uri: `/evolutionBot/create/${instanceName}`, + body, + json: true, + }; + } else if (resourceForEvolutionBot === 'findEvolutionBot') { + const evolutionBotId = ef.getNodeParameter('evolutionBotId', 0) as string; + + options = { + method: 'GET' as IHttpRequestMethods, + uri: evolutionBotId + ? `/evolutionBot/fetch/${evolutionBotId}/${instanceName}` + : `/evolutionBot/find/${instanceName}`, + json: true, + }; + } else if (resourceForEvolutionBot === 'updateEvolutionBot') { + const evolutionBotId = ef.getNodeParameter('evolutionBotId', 0) as string; + const apiUrl = ef.getNodeParameter('apiUrl', 0) as string; + const apiKey = ef.getNodeParameter('apiKeyBot', 0) as string; + const triggerType = ef.getNodeParameter('triggerType', 0) as string; + const triggerOperator = ef.getNodeParameter('triggerOperator', 0) as string; + const triggerValue = ef.getNodeParameter('triggerValue', 0) as string; + const expire = ef.getNodeParameter('expire', 0) as number; + const keywordFinish = ef.getNodeParameter('keywordFinish', 0) as string; + const delayMessage = ef.getNodeParameter('delayMessage', 0) as number; + const unknownMessage = ef.getNodeParameter('unknownMessage', 0) as string; + const listeningFromMe = ef.getNodeParameter('listeningFromMe', 0) as boolean; + const stopBotFromMe = ef.getNodeParameter('stopBotFromMe', 0) as boolean; + const keepOpen = ef.getNodeParameter('keepOpen', 0) as boolean; + const debounceTime = ef.getNodeParameter('debounceTime', 0) as number; + const ignoreJids = ef.getNodeParameter('ignoreJids', 0) as string[]; + + const body = { + enabled: true, + apiUrl, + ...(apiKey && { apiKey }), + triggerType, + triggerOperator, + triggerValue, + expire, + keywordFinish, + delayMessage, + unknownMessage, + listeningFromMe, + stopBotFromMe, + keepOpen, + debounceTime, + ignoreJids: ignoreJids || [] + }; + + options = { + method: 'PUT' as IHttpRequestMethods, + uri: `/evolutionBot/update/${evolutionBotId}/${instanceName}`, + body, + json: true, + }; + } else if (resourceForEvolutionBot === 'deleteEvolutionBot') { + const evolutionBotId = ef.getNodeParameter('evolutionBotId', 0) as string; + + options = { + method: 'DELETE' as IHttpRequestMethods, + uri: `/evolutionBot/delete/${evolutionBotId}/${instanceName}`, + json: true, + }; + } else if (resourceForEvolutionBot === 'fetchSessionsEvolutionBot') { + const evolutionBotId = ef.getNodeParameter('evolutionBotId', 0) as string; + + options = { + method: 'GET' as IHttpRequestMethods, + uri: `/evolutionBot/fetchSessions/${evolutionBotId}/${instanceName}`, + json: true, + }; + } else if (resourceForEvolutionBot === 'changeStatusEvolutionBot') { + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const status = ef.getNodeParameter('status', 0) as string; + + options = { + method: 'POST' as IHttpRequestMethods, + uri: `/evolutionBot/changeStatus/${instanceName}`, + body: { + remoteJid, + status, + }, + json: true, + }; + } else { + const errorData = { + success: false, + error: { + message: 'Operação do Evolution Bot não reconhecida', + details: 'A operação solicitada não é válida para o recurso do Evolution Bot', + code: 'INVALID_OPERATION', + timestamp: new Date().toISOString(), + }, + }; + throw new NodeOperationError(ef.getNode(), errorData.error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao configurar Evolution Bot', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/integrations/setFlowiseBot.ts b/nodes/EvolutionApi/execute/integrations/setFlowiseBot.ts new file mode 100644 index 0000000..6cafcb1 --- /dev/null +++ b/nodes/EvolutionApi/execute/integrations/setFlowiseBot.ts @@ -0,0 +1,186 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function setFlowiseBot(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + const resourceForFlowiseBot = ef.getNodeParameter('resourceForFlowiseBot', 0); + + let options: IRequestOptions; + + if (resourceForFlowiseBot === 'createFlowise') { + const apiUrl = ef.getNodeParameter('apiUrl', 0) as string; + const apiKey = ef.getNodeParameter('apiKeyBot', 0) as string; + const triggerType = ef.getNodeParameter('triggerType', 0) as string; + const triggerOperator = ef.getNodeParameter('triggerOperator', 0) as string; + const triggerValue = ef.getNodeParameter('triggerValue', 0) as string; + const expire = ef.getNodeParameter('expire', 0) as number; + const keywordFinish = ef.getNodeParameter('keywordFinish', 0) as string; + const delayMessage = ef.getNodeParameter('delayMessage', 0) as number; + const unknownMessage = ef.getNodeParameter('unknownMessage', 0) as string; + const listeningFromMe = ef.getNodeParameter('listeningFromMe', 0) as boolean; + const stopBotFromMe = ef.getNodeParameter('stopBotFromMe', 0) as boolean; + const keepOpen = ef.getNodeParameter('keepOpen', 0) as boolean; + const debounceTime = ef.getNodeParameter('debounceTime', 0) as number; + const ignoreJids = ef.getNodeParameter('ignoreJids', 0) as string[]; + + const body = { + enabled: true, + apiUrl, + apiKey, + triggerType, + triggerOperator, + triggerValue, + expire, + keywordFinish, + delayMessage, + unknownMessage, + listeningFromMe, + stopBotFromMe, + keepOpen, + debounceTime, + ignoreJids: ignoreJids || [] + }; + + options = { + method: 'POST' as IHttpRequestMethods, + uri: `/flowise/create/${instanceName}`, + body, + json: true, + }; + } else if (resourceForFlowiseBot === 'findFlowise') { + const flowiseBotId = ef.getNodeParameter('flowiseBotId', 0) as string; + + options = { + method: 'GET' as IHttpRequestMethods, + uri: flowiseBotId + ? `/flowise/fetch/${flowiseBotId}/${instanceName}` + : `/flowise/find/${instanceName}`, + json: true, + }; + } else if (resourceForFlowiseBot === 'updateFlowise') { + const flowiseBotId = ef.getNodeParameter('flowiseBotId', 0) as string; + const apiUrl = ef.getNodeParameter('apiUrl', 0) as string; + const apiKey = ef.getNodeParameter('apiKeyBot', 0) as string; + const triggerType = ef.getNodeParameter('triggerType', 0) as string; + const triggerOperator = ef.getNodeParameter('triggerOperator', 0) as string; + const triggerValue = ef.getNodeParameter('triggerValue', 0) as string; + const expire = ef.getNodeParameter('expire', 0) as number; + const keywordFinish = ef.getNodeParameter('keywordFinish', 0) as string; + const delayMessage = ef.getNodeParameter('delayMessage', 0) as number; + const unknownMessage = ef.getNodeParameter('unknownMessage', 0) as string; + const listeningFromMe = ef.getNodeParameter('listeningFromMe', 0) as boolean; + const stopBotFromMe = ef.getNodeParameter('stopBotFromMe', 0) as boolean; + const keepOpen = ef.getNodeParameter('keepOpen', 0) as boolean; + const debounceTime = ef.getNodeParameter('debounceTime', 0) as number; + const ignoreJids = ef.getNodeParameter('ignoreJids', 0) as string[]; + + const body = { + enabled: true, + apiUrl, + apiKey, + triggerType, + triggerOperator, + triggerValue, + expire, + keywordFinish, + delayMessage, + unknownMessage, + listeningFromMe, + stopBotFromMe, + keepOpen, + debounceTime, + ignoreJids: ignoreJids || [] + }; + + options = { + method: 'PUT' as IHttpRequestMethods, + uri: `/flowise/update/${flowiseBotId}/${instanceName}`, + body, + json: true, + }; + } else if (resourceForFlowiseBot === 'deleteFlowise') { + const flowiseBotId = ef.getNodeParameter('flowiseBotId', 0) as string; + + options = { + method: 'DELETE' as IHttpRequestMethods, + uri: `/flowise/delete/${flowiseBotId}/${instanceName}`, + json: true, + }; + } else if (resourceForFlowiseBot === 'fetchSessionsFlowise') { + const flowiseBotId = ef.getNodeParameter('flowiseBotId', 0) as string; + + options = { + method: 'GET' as IHttpRequestMethods, + uri: `/flowise/fetchSessions/${flowiseBotId}/${instanceName}`, + json: true, + }; + } else if (resourceForFlowiseBot === 'changeStatusFlowise') { + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const status = ef.getNodeParameter('status', 0) as string; + + options = { + method: 'POST' as IHttpRequestMethods, + uri: `/flowise/changeStatus/${instanceName}`, + body: { + remoteJid, + status, + }, + json: true, + }; + } else { + const errorData = { + success: false, + error: { + message: 'Operação do Flowise não reconhecida', + details: 'A operação solicitada não é válida para o recurso do Flowise', + code: 'INVALID_OPERATION', + timestamp: new Date().toISOString(), + }, + }; + throw new NodeOperationError(ef.getNode(), errorData.error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao configurar Flowise', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/integrations/setTypebot.ts b/nodes/EvolutionApi/execute/integrations/setTypebot.ts new file mode 100644 index 0000000..8419aed --- /dev/null +++ b/nodes/EvolutionApi/execute/integrations/setTypebot.ts @@ -0,0 +1,203 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function setTypebot(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0); + const resourceForTypebot = ef.getNodeParameter('resourceForTypebot', 0); + + let options: IRequestOptions; + + if (resourceForTypebot === 'createTypebot') { + const url = ef.getNodeParameter('url', 0) as string; + const typebot = ef.getNodeParameter('typebot', 0) as string; + const triggerType = ef.getNodeParameter('triggerType', 0) as string; + const triggerOperator = ef.getNodeParameter('triggerOperator', 0) as string; + const triggerValue = ef.getNodeParameter('triggerValue', 0) as string; + const expire = ef.getNodeParameter('expire', 0) as number; + const keywordFinish = ef.getNodeParameter('keywordFinish', 0) as string; + const delayMessage = ef.getNodeParameter('delayMessage', 0) as number; + const unknownMessage = ef.getNodeParameter('unknownMessage', 0) as string; + const listeningFromMe = ef.getNodeParameter('listeningFromMe', 0) as boolean; + const stopBotFromMe = ef.getNodeParameter('stopBotFromMe', 0) as boolean; + const keepOpen = ef.getNodeParameter('keepOpen', 0) as boolean; + const debounceTime = ef.getNodeParameter('debounceTime', 0) as number; + + const body = { + enabled: true, + url, + typebot, + triggerType, + triggerOperator, + triggerValue, + expire, + keywordFinish, + delayMessage, + unknownMessage, + listeningFromMe, + stopBotFromMe, + keepOpen, + debounceTime + }; + + options = { + method: 'POST' as IHttpRequestMethods, + uri: `/typebot/create/${instanceName}`, + body, + json: true, + }; + } else if (resourceForTypebot === 'findTypebot') { + const typebotId = ef.getNodeParameter('typebotId', 0) as string; + + options = { + method: 'GET' as IHttpRequestMethods, + uri: typebotId + ? `/typebot/fetch/${typebotId}/${instanceName}` + : `/typebot/find/${instanceName}`, + json: true, + }; + } else if (resourceForTypebot === 'updateTypebot') { + const typebotId = ef.getNodeParameter('typebotId', 0) as string; + const url = ef.getNodeParameter('url', 0) as string; + const typebot = ef.getNodeParameter('typebot', 0) as string; + const expire = ef.getNodeParameter('expire', 0) as number; + const keywordFinish = ef.getNodeParameter('keywordFinish', 0) as string; + const delayMessage = ef.getNodeParameter('delayMessage', 0) as number; + const unknownMessage = ef.getNodeParameter('unknownMessage', 0) as string; + const listeningFromMe = ef.getNodeParameter('listeningFromMe', 0) as boolean; + const stopBotFromMe = ef.getNodeParameter('stopBotFromMe', 0) as boolean; + const keepOpen = ef.getNodeParameter('keepOpen', 0) as boolean; + const debounceTime = ef.getNodeParameter('debounceTime', 0) as number; + const triggerType = ef.getNodeParameter('triggerType', 0) as string; + const triggerOperator = ef.getNodeParameter('triggerOperator', 0) as string; + const triggerValue = ef.getNodeParameter('triggerValue', 0) as string; + + const body = { + enabled: true, + url, + typebot, + expire, + keywordFinish, + delayMessage, + unknownMessage, + listeningFromMe, + stopBotFromMe, + keepOpen, + debounceTime, + triggerType, + triggerOperator, + triggerValue + }; + + options = { + method: 'PUT' as IHttpRequestMethods, + uri: `/typebot/update/${typebotId}/${instanceName}`, + body, + json: true, + }; + } else if (resourceForTypebot === 'deleteTypebot') { + const typebotId = ef.getNodeParameter('typebotId', 0) as string; + + options = { + method: 'DELETE' as IHttpRequestMethods, + uri: `/typebot/delete/${typebotId}/${instanceName}`, + json: true, + }; + } else if (resourceForTypebot === 'fetchSessionsTypebot') { + const typebotId = ef.getNodeParameter('typebotId', 0) as string; + + options = { + method: 'GET' as IHttpRequestMethods, + uri: `/typebot/fetchSessions/${typebotId}/${instanceName}`, + json: true, + }; + } else if (resourceForTypebot === 'changeStatusTypebot') { + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const status = ef.getNodeParameter('status', 0) as string; + + options = { + method: 'POST' as IHttpRequestMethods, + uri: `/typebot/changeStatus/${instanceName}`, + body: { + remoteJid, + status, + }, + json: true, + }; + } else if (resourceForTypebot === 'startTypebot') { + const url = ef.getNodeParameter('url', 0) as string; + const typebot = ef.getNodeParameter('typebot', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const startSession = ef.getNodeParameter('startSession', 0) as boolean; + const variables = ef.getNodeParameter('variables', 0) as Array<{ name: string; value: string }>; + + const body = { + url, + typebot, + remoteJid, + startSession, + ...(variables?.length && { variables }), + }; + + options = { + method: 'POST' as IHttpRequestMethods, + uri: `/typebot/start/${instanceName}`, + body, + json: true, + }; + } else { + const errorData = { + success: false, + error: { + message: 'Operação do Typebot não reconhecida', + details: 'A operação solicitada não é válida para o recurso do Typebot', + code: 'INVALID_OPERATION', + timestamp: new Date().toISOString(), + }, + }; + throw new NodeOperationError(ef.getNode(), errorData.error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + const response = await evolutionRequest(ef, options); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao configurar Typebot', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/messages/sendAudio.ts b/nodes/EvolutionApi/execute/messages/sendAudio.ts new file mode 100644 index 0000000..0024c56 --- /dev/null +++ b/nodes/EvolutionApi/execute/messages/sendAudio.ts @@ -0,0 +1,113 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendAudio(ef: IExecuteFunctions) { + try { + // Parâmetros obrigatórios + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const media = ef.getNodeParameter('media', 0) as string; + + // Parâmetros opcionais com valores padrão + const mimetype = (ef.getNodeParameter('mimetype', 0, 'audio/mp3') as string) || 'audio/mp3'; + const fileName = (ef.getNodeParameter('fileName', 0, 'audio.mp3') as string) || 'audio.mp3'; + + // Opções adicionais + const options = ef.getNodeParameter('options_message', 0, {}) as { + delay?: number; + quoted?: { + messageQuoted: { + messageId: string; + }; + }; + mentions?: { + mentionsSettings: { + mentionsEveryOne: boolean; + mentioned?: string; + }; + }; + }; + + const body: any = { + number: remoteJid, + audio: media, + mimetype: mimetype, + fileName: fileName, + }; + + if (options.delay) { + body.delay = options.delay; + } + + if (options.quoted?.messageQuoted?.messageId) { + body.quoted = { + key: { + id: options.quoted.messageQuoted.messageId, + }, + }; + } + + if (options.mentions?.mentionsSettings) { + const { mentionsEveryOne, mentioned } = options.mentions.mentionsSettings; + + if (mentionsEveryOne) { + body.mentionsEveryOne = true; + } else if (mentioned) { + const mentionedNumbers = mentioned.split(',') + .map(num => num.trim()) + .map(num => num.includes('@s.whatsapp.net') ? num : `${num}@s.whatsapp.net`); + + body.mentioned = mentionedNumbers; + } + } + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/message/sendWhatsAppAudio/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao enviar áudio', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/messages/sendButtons.ts b/nodes/EvolutionApi/execute/messages/sendButtons.ts new file mode 100644 index 0000000..18e8588 --- /dev/null +++ b/nodes/EvolutionApi/execute/messages/sendButtons.ts @@ -0,0 +1,154 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendButtons(ef: IExecuteFunctions) { + try { + // Parâmetros obrigatórios + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const title = ef.getNodeParameter('title', 0) as string; + const description = ef.getNodeParameter('description', 0) as string; + const footer = ef.getNodeParameter('footer', 0, '') as string; + const buttons = ef.getNodeParameter('buttons.buttonValues', 0, []) as Array<{ + type: 'reply' | 'copy' | 'url' | 'call'; + displayText: string; + id?: string; + copyCode?: string; + url?: string; + phoneNumber?: string; + }>; + + // Validação dos botões + if (!Array.isArray(buttons) || buttons.length === 0 || buttons.length > 3) { + const errorData = { + success: false, + error: { + message: 'Lista de botões inválida', + details: 'É necessário fornecer entre 1 e 3 botões', + code: 'INVALID_BUTTONS', + timestamp: new Date().toISOString(), + }, + }; + return { + json: errorData, + error: errorData, + }; + } + + // Opções adicionais + const options = ef.getNodeParameter('options_message', 0, {}) as { + delay?: number; + quoted?: { + messageQuoted: { + messageId: string; + }; + }; + mentions?: { + mentionsSettings: { + mentionsEveryOne: boolean; + mentioned: string; + }; + }; + }; + + const body: any = { + number: remoteJid, + title, + description, + buttons: buttons.map(button => { + const baseButton = { + type: button.type, + displayText: button.displayText, + }; + + switch (button.type) { + case 'reply': + return { ...baseButton, id: button.id }; + case 'copy': + return { ...baseButton, copyCode: button.copyCode }; + case 'url': + return { ...baseButton, url: button.url }; + case 'call': + return { ...baseButton, phoneNumber: button.phoneNumber }; + default: + return baseButton; + } + }), + }; + + if (footer) body.footer = footer; + if (options.delay) body.delay = options.delay; + + if (options.quoted?.messageQuoted?.messageId) { + body.quoted = { + key: { + id: options.quoted.messageQuoted.messageId, + }, + }; + } + + if (options.mentions?.mentionsSettings) { + const { mentionsEveryOne, mentioned } = options.mentions.mentionsSettings; + + if (mentionsEveryOne) { + body.mentionsEveryOne = true; + } else if (mentioned) { + const mentionedNumbers = mentioned + .split(',') + .map(num => num.trim()) + .map(num => (num.includes('@s.whatsapp.net') ? num : `${num}@s.whatsapp.net`)); + + body.mentioned = mentionedNumbers; + } + } + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/message/sendButtons/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao enviar botões', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/messages/sendContact.ts b/nodes/EvolutionApi/execute/messages/sendContact.ts new file mode 100644 index 0000000..b789d7c --- /dev/null +++ b/nodes/EvolutionApi/execute/messages/sendContact.ts @@ -0,0 +1,96 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendContact(ef: IExecuteFunctions) { + try { + // Parâmetros obrigatórios + const instanceName = ef.getNodeParameter('instanceName', 0); + const remoteJid = ef.getNodeParameter('remoteJid', 0); + const contacts = ef.getNodeParameter('contacts.contactValues', 0) as { + fullName: string; + wuid: string; + phoneNumber: string; + organization?: string; + email?: string; + url?: string; + }[]; + + // Validação dos contatos + if (!Array.isArray(contacts) || contacts.length === 0) { + const errorData = { + success: false, + error: { + message: 'Lista de contatos inválida', + details: 'É necessário fornecer pelo menos um contato', + code: 'INVALID_CONTACTS', + timestamp: new Date().toISOString(), + }, + }; + return { + json: errorData, + error: errorData, + }; + } + + const body: any = { + number: remoteJid, + contact: contacts.map(contact => ({ + fullName: contact.fullName, + wuid: contact.wuid, + phoneNumber: contact.phoneNumber, + ...(contact.organization && { organization: contact.organization }), + ...(contact.email && { email: contact.email }), + ...(contact.url && { url: contact.url }), + })), + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/message/sendContact/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao enviar contato', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/messages/sendDocument.ts b/nodes/EvolutionApi/execute/messages/sendDocument.ts new file mode 100644 index 0000000..180a096 --- /dev/null +++ b/nodes/EvolutionApi/execute/messages/sendDocument.ts @@ -0,0 +1,119 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeApiError, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendDocument(ef: IExecuteFunctions) { + try { + // Parâmetros obrigatórios + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const media = ef.getNodeParameter('media', 0) as string; + + // Validação do campo media + if (!media.startsWith('http') && !media.startsWith('data:')) { + throw new NodeApiError(ef.getNode(), { + message: 'Formato de mídia inválido', + description: 'O documento deve ser uma URL válida ou um base64', + }); + } + + // Parâmetros opcionais com valores padrão + const mimetype = (ef.getNodeParameter('mimetype', 0, 'application/pdf') as string) || 'application/pdf'; + const caption = ef.getNodeParameter('caption', 0, '') as string; + const fileName = (ef.getNodeParameter('fileName', 0, 'document.pdf') as string) || 'document.pdf'; + + // Opções adicionais + const options = ef.getNodeParameter('options_message', 0, {}) as { + delay?: number; + quoted?: { + messageQuoted: { + messageId: string; + }; + }; + mentions?: { + mentionsSettings: { + mentionsEveryOne: boolean; + mentioned?: string; + }; + }; + }; + + const body: any = { + number: remoteJid, + media: media, + mediatype: 'document', + mimetype: mimetype, + caption: caption || '', + fileName: fileName, + }; + + if (options.delay) { + body.delay = options.delay; + } + + if (options.quoted?.messageQuoted?.messageId) { + body.quoted = { + key: { + id: options.quoted.messageQuoted.messageId, + }, + }; + } + + if (options.mentions?.mentionsSettings) { + const { mentionsEveryOne, mentioned } = options.mentions.mentionsSettings; + + if (mentionsEveryOne) { + body.mentionsEveryOne = true; + } else if (mentioned) { + const mentionedNumbers = mentioned.split(',') + .map(num => num.trim()) + .map(num => num.includes('@s.whatsapp.net') ? num : `${num}@s.whatsapp.net`); + + body.mentioned = mentionedNumbers; + } + } + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/message/sendMedia/${instanceName}`, + body, + json: true, + }; + + return await evolutionRequest(ef, requestOptions); + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao enviar documento', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/messages/sendImage.ts b/nodes/EvolutionApi/execute/messages/sendImage.ts new file mode 100644 index 0000000..54ed113 --- /dev/null +++ b/nodes/EvolutionApi/execute/messages/sendImage.ts @@ -0,0 +1,129 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + INodeExecutionData, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendImage(ef: IExecuteFunctions) { + const items = ef.getInputData(); + const returnData: INodeExecutionData[] = []; + + for (let i = 0; i < items.length; i++) { + try { + // Parâmetros obrigatórios + const instanceName = ef.getNodeParameter('instanceName', i) as string; + const remoteJid = ef.getNodeParameter('remoteJid', i) as string; + const media = ef.getNodeParameter('media', i) as string; + + // Parâmetros opcionais com valores padrão + const mimetype = (ef.getNodeParameter('mimetype', i, 'image/jpeg') as string) || 'image/jpeg'; + const caption = ef.getNodeParameter('caption', i, '') as string; + const fileName = (ef.getNodeParameter('fileName', i, 'image.jpg') as string) || 'image.jpg'; + + // Opções adicionais + const options = ef.getNodeParameter('options_message', i, {}) as { + delay?: number; + quoted?: { + messageQuoted: { + messageId: string; + }; + }; + mentions?: { + mentionsSettings: { + mentionsEveryOne: boolean; + mentioned?: string; + }; + }; + }; + + const body: any = { + number: remoteJid, + mediatype: 'image', + media: media, + mimetype: mimetype, + caption: caption || '', + fileName: fileName, + }; + + if (options.delay) { + body.delay = options.delay; + } + + if (options.quoted?.messageQuoted?.messageId) { + body.quoted = { + key: { + id: options.quoted.messageQuoted.messageId, + }, + }; + } + + if (options.mentions?.mentionsSettings) { + const { mentionsEveryOne, mentioned } = options.mentions.mentionsSettings; + + if (mentionsEveryOne) { + body.mentionsEveryOne = true; + } else if (mentioned) { + const mentionedNumbers = mentioned.split(',') + .map(num => num.trim()) + .map(num => num.includes('@s.whatsapp.net') ? num : `${num}@s.whatsapp.net`); + + body.mentioned = mentionedNumbers; + } + } + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/message/sendMedia/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + returnData.push({ + json: { + success: true, + data: response, + }, + }); + } catch (error) { + const errorMessage = error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao enviar imagem'; + + const errorDetails = error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), errorMessage, { + message: errorMessage, + description: errorDetails, + }); + } + + returnData.push({ + json: { + success: false, + error: { + message: errorMessage, + details: errorDetails, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }, + error: new NodeOperationError(ef.getNode(), errorMessage, { + message: errorMessage, + description: errorDetails, + }), + }); + } + } + + return returnData; +} diff --git a/nodes/EvolutionApi/execute/messages/sendList.ts b/nodes/EvolutionApi/execute/messages/sendList.ts new file mode 100644 index 0000000..f439ea4 --- /dev/null +++ b/nodes/EvolutionApi/execute/messages/sendList.ts @@ -0,0 +1,147 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendList(ef: IExecuteFunctions) { + try { + // Parâmetros obrigatórios + const instanceName = ef.getNodeParameter('instanceName', 0); + const remoteJid = ef.getNodeParameter('remoteJid', 0); + const title = ef.getNodeParameter('title', 0); + const description = ef.getNodeParameter('description', 0); + const buttonText = ef.getNodeParameter('buttonText', 0); + const sections = ef.getNodeParameter('sections.sectionValues', 0) as { + title: string; + rows: { + rowValues: { + title: string; + description?: string; + rowId?: string; + }[]; + }; + }[]; + + // Validação das seções + if (!Array.isArray(sections) || sections.length === 0) { + const errorData = { + success: false, + error: { + message: 'Lista de seções inválida', + details: 'É necessário fornecer pelo menos uma seção com opções', + code: 'INVALID_SECTIONS', + timestamp: new Date().toISOString(), + }, + }; + return { + json: errorData, + error: errorData, + }; + } + + // Opções adicionais + const options = ef.getNodeParameter('options_message', 0, {}) as { + footer?: string; + delay?: number; + quoted?: { + messageQuoted: { + messageId: string; + }; + }; + mentions?: { + mentionsSettings: { + mentionsEveryOne: boolean; + mentioned?: string; + }; + }; + }; + + const body: any = { + number: remoteJid, + title, + description, + buttonText, + footerText: options.footer || '', + sections: sections.map(section => ({ + title: section.title, + rows: section.rows.rowValues.map(row => ({ + title: row.title, + description: row.description || '', + rowId: row.rowId || `${section.title}_${row.title}` + })) + })) + }; + + if (options.delay) body.delay = options.delay; + + if (options.quoted?.messageQuoted?.messageId) { + body.quoted = { + key: { + id: options.quoted.messageQuoted.messageId, + }, + }; + } + + if (options.mentions?.mentionsSettings) { + const { mentionsEveryOne, mentioned } = options.mentions.mentionsSettings; + + if (mentionsEveryOne) { + body.mentionsEveryOne = true; + } else if (mentioned) { + const mentionedNumbers = mentioned + .split(',') + .map(num => num.trim()) + .map(num => num.includes('@s.whatsapp.net') ? num : `${num}@s.whatsapp.net`); + + body.mentioned = mentionedNumbers; + } + } + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/message/sendList/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao enviar lista', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/messages/sendPix.ts b/nodes/EvolutionApi/execute/messages/sendPix.ts new file mode 100644 index 0000000..f281e61 --- /dev/null +++ b/nodes/EvolutionApi/execute/messages/sendPix.ts @@ -0,0 +1,93 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendPix(ef: IExecuteFunctions) { + try { + // Parâmetros obrigatórios + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const name = ef.getNodeParameter('name', 0) as string; + const keyType = ef.getNodeParameter('keyType', 0) as string; + const key = ef.getNodeParameter('key', 0) as string; + + // Validação do tipo de chave PIX + const validKeyTypes = ['cpf', 'cnpj', 'email', 'phone', 'random']; + if (!validKeyTypes.includes(keyType)) { + const errorData = { + success: false, + error: { + message: 'Tipo de chave PIX inválida', + details: 'O tipo de chave PIX deve ser: cpf, cnpj, email, phone ou random', + code: 'INVALID_PIX_KEY_TYPE', + timestamp: new Date().toISOString(), + }, + }; + return { + json: errorData, + error: errorData, + }; + } + + const body: any = { + number: remoteJid, + buttons: [ + { + type: 'pix', + currency: 'BRL', + name, + keyType, + key, + }, + ], + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/message/sendButtons/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao enviar botão PIX', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/messages/sendPoll.ts b/nodes/EvolutionApi/execute/messages/sendPoll.ts new file mode 100644 index 0000000..b72dfc2 --- /dev/null +++ b/nodes/EvolutionApi/execute/messages/sendPoll.ts @@ -0,0 +1,113 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendPoll(ef: IExecuteFunctions) { + try { + // Parâmetros obrigatórios + const instanceName = ef.getNodeParameter('instanceName', 0); + const remoteJid = ef.getNodeParameter('remoteJid', 0); + const pollTitle = ef.getNodeParameter('caption', 0); + const options = ef.getNodeParameter('options_display.metadataValues', 0) as { + optionValue: string; + }[]; + + // Opções adicionais + const options_message = ef.getNodeParameter('options_message', 0, {}) as { + delay?: number; + quoted?: { + messageQuoted: { + messageId: string; + }; + }; + }; + + // Verifica se options é um array e não está vazio + const pollOptions = Array.isArray(options) ? options.map((option) => option.optionValue) : []; + + if (pollOptions.length === 0) { + const errorData = { + success: false, + error: { + message: 'Opções da enquete inválidas', + details: 'A enquete precisa ter pelo menos uma opção', + code: 'INVALID_POLL_OPTIONS', + timestamp: new Date().toISOString(), + }, + }; + return { + json: errorData, + error: errorData, + }; + } + + const body: any = { + number: remoteJid, + name: pollTitle, + selectableCount: 1, + values: pollOptions, + }; + + // Adiciona delay se especificado + if (options_message.delay) { + body.delay = options_message.delay; + } + + // Adiciona quoted se especificado + if (options_message.quoted?.messageQuoted?.messageId) { + body.quoted = { + key: { + id: options_message.quoted.messageQuoted.messageId, + }, + }; + } + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/message/sendPoll/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao enviar enquete', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/messages/sendReaction.ts b/nodes/EvolutionApi/execute/messages/sendReaction.ts new file mode 100644 index 0000000..1a8e60e --- /dev/null +++ b/nodes/EvolutionApi/execute/messages/sendReaction.ts @@ -0,0 +1,88 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendReaction(ef: IExecuteFunctions) { + try { + // Parâmetros obrigatórios + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const messageId = ef.getNodeParameter('messageId', 0) as string; + const fromMe = ef.getNodeParameter('fromMe', 0) as boolean; + const reaction = ef.getNodeParameter('reaction', 0) as string; + + // Validação da reação + if (!reaction) { + const errorData = { + success: false, + error: { + message: 'Reação inválida', + details: 'É necessário fornecer um emoji para a reação', + code: 'INVALID_REACTION', + timestamp: new Date().toISOString(), + }, + }; + return { + json: errorData, + error: errorData, + }; + } + + const body: any = { + key: { + remoteJid, + fromMe, + id: messageId, + }, + reaction, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/message/sendReaction/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao enviar reação', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/messages/sendStories.ts b/nodes/EvolutionApi/execute/messages/sendStories.ts new file mode 100644 index 0000000..d070a0b --- /dev/null +++ b/nodes/EvolutionApi/execute/messages/sendStories.ts @@ -0,0 +1,109 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendStories(ef: IExecuteFunctions) { + try { + // Parâmetros obrigatórios + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const content = ef.getNodeParameter('content', 0) as string; + const type = ef.getNodeParameter('type', 0) as 'text' | 'image' | 'video' | 'audio'; + const caption = ef.getNodeParameter('caption', 0, '') as string; + const allContacts = ef.getNodeParameter('allContacts', 0, false) as boolean; + const backgroundColor = ef.getNodeParameter('backgroundColor', 0, '#000000') as string; + const font = ef.getNodeParameter('font', 0, 1) as number; + + // Validação da URL do conteúdo para tipos não texto + if (type !== 'text' && !content.startsWith('http') && !content.startsWith('data:')) { + const errorData = { + success: false, + error: { + message: 'Formato de conteúdo inválido', + details: 'O conteúdo deve ser uma URL válida ou um base64', + code: 'INVALID_CONTENT_FORMAT', + timestamp: new Date().toISOString(), + }, + }; + return { + json: errorData, + error: errorData, + }; + } + + const body: any = { + type, + content, + backgroundColor, + font, + allContacts + }; + + // Adiciona caption apenas para imagem ou vídeo + if ((type === 'image' || type === 'video') && caption) { + body.caption = caption; + } + + // Se não for para todos os contatos, pega a lista específica + if (!allContacts) { + const statusJidList = ef.getNodeParameter('statusJidList', 0, '') as string; + if (statusJidList) { + body.statusJidList = statusJidList.split(',') + .map(num => num.trim()) + .map(num => num.includes('@s.whatsapp.net') ? num : `${num}@s.whatsapp.net`); + } + } + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/message/sendStatus/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + + if (!response) { + throw new Error('Resposta vazia do servidor'); + } + + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao enviar status', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/messages/sendText.ts b/nodes/EvolutionApi/execute/messages/sendText.ts new file mode 100644 index 0000000..d465091 --- /dev/null +++ b/nodes/EvolutionApi/execute/messages/sendText.ts @@ -0,0 +1,122 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + INodeExecutionData, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendText(ef: IExecuteFunctions) { + const items = ef.getInputData(); + const returnData: INodeExecutionData[] = []; + + for (let i = 0; i < items.length; i++) { + try { + const instanceName = ef.getNodeParameter('instanceName', i) as string; + const remoteJid = ef.getNodeParameter('remoteJid', i) as string; + const messageText = ef.getNodeParameter('messageText', i) as string; + const options = ef.getNodeParameter('options_message', i, {}) as { + delay?: number; + linkPreview?: boolean; + quoted?: { + messageQuoted: { + messageId: string; + }; + }; + mentions?: { + mentionsSettings: { + mentionsEveryOne: boolean; + mentioned?: string; + }; + }; + }; + + const body: any = { + number: remoteJid, + text: messageText, + }; + + if (options.delay) { + body.delay = options.delay; + } + + if (options.linkPreview !== undefined) { + body.linkPreview = options.linkPreview; + } + + if (options.quoted?.messageQuoted?.messageId) { + body.quoted = { + key: { + id: options.quoted.messageQuoted.messageId, + }, + }; + } + + if (options.mentions?.mentionsSettings) { + const { mentionsEveryOne, mentioned } = options.mentions.mentionsSettings; + + if (mentionsEveryOne) { + body.mentionsEveryOne = true; + } else if (mentioned) { + const mentionedNumbers = mentioned.split(',') + .map(num => num.trim()) + .map(num => num.includes('@s.whatsapp.net') ? num : `${num}@s.whatsapp.net`); + + body.mentioned = mentionedNumbers; + } + } + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/message/sendText/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + returnData.push({ + json: { + success: true, + data: response, + }, + }); + } catch (error) { + const errorMessage = error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao enviar mensagem de texto'; + + const errorDetails = error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), errorMessage, { + message: errorMessage, + description: errorDetails, + }); + } + + returnData.push({ + json: { + success: false, + error: { + message: errorMessage, + details: errorDetails, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }, + error: new NodeOperationError(ef.getNode(), errorMessage, { + message: errorMessage, + description: errorDetails, + }), + }); + } + } + + return returnData; +} diff --git a/nodes/EvolutionApi/execute/messages/sendVideo.ts b/nodes/EvolutionApi/execute/messages/sendVideo.ts new file mode 100644 index 0000000..6653e91 --- /dev/null +++ b/nodes/EvolutionApi/execute/messages/sendVideo.ts @@ -0,0 +1,116 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function sendVideo(ef: IExecuteFunctions) { + try { + // Parâmetros obrigatórios + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + const media = ef.getNodeParameter('media', 0) as string; + + // Parâmetros opcionais com valores padrão + const mimetype = (ef.getNodeParameter('mimetype', 0, 'video/mp4') as string) || 'video/mp4'; + const caption = ef.getNodeParameter('caption', 0, '') as string; + const fileName = (ef.getNodeParameter('fileName', 0, 'video.mp4') as string) || 'video.mp4'; + + // Opções adicionais + const options = ef.getNodeParameter('options_message', 0, {}) as { + delay?: number; + quoted?: { + messageQuoted: { + messageId: string; + }; + }; + mentions?: { + mentionsSettings: { + mentionsEveryOne: boolean; + mentioned?: string; + }; + }; + }; + + const body: any = { + number: remoteJid, + mediatype: 'video', + media: media, + mimetype: mimetype, + caption: caption || '', + fileName: fileName, + }; + + if (options.delay) { + body.delay = options.delay; + } + + if (options.quoted?.messageQuoted?.messageId) { + body.quoted = { + key: { + id: options.quoted.messageQuoted.messageId, + }, + }; + } + + if (options.mentions?.mentionsSettings) { + const { mentionsEveryOne, mentioned } = options.mentions.mentionsSettings; + + if (mentionsEveryOne) { + body.mentionsEveryOne = true; + } else if (mentioned) { + const mentionedNumbers = mentioned.split(',') + .map(num => num.trim()) + .map(num => num.includes('@s.whatsapp.net') ? num : `${num}@s.whatsapp.net`); + + body.mentioned = mentionedNumbers; + } + } + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + headers: { + 'Content-Type': 'application/json', + }, + uri: `/message/sendMedia/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message.includes('Could not get parameter') + ? 'Parâmetros inválidos ou ausentes' + : 'Erro ao enviar vídeo', + details: error.message.includes('Could not get parameter') + ? 'Verifique se todos os campos obrigatórios foram preenchidos corretamente' + : error.message, + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/profile/fetchBusinessProfile.ts b/nodes/EvolutionApi/execute/profile/fetchBusinessProfile.ts new file mode 100644 index 0000000..5f07ebb --- /dev/null +++ b/nodes/EvolutionApi/execute/profile/fetchBusinessProfile.ts @@ -0,0 +1,55 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function fetchBusinessProfile(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + + const body = { + number: remoteJid.includes('@') ? remoteJid : `${remoteJid}@s.whatsapp.net`, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/fetchBusinessProfile/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao buscar perfil de negócio', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/profile/fetchPrivacySettings.ts b/nodes/EvolutionApi/execute/profile/fetchPrivacySettings.ts new file mode 100644 index 0000000..bf60933 --- /dev/null +++ b/nodes/EvolutionApi/execute/profile/fetchPrivacySettings.ts @@ -0,0 +1,49 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function fetchPrivacySettings(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + + const requestOptions: IRequestOptions = { + method: 'GET' as IHttpRequestMethods, + uri: `/chat/fetchPrivacySettings/${instanceName}`, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao buscar configurações de privacidade', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/profile/fetchProfile.ts b/nodes/EvolutionApi/execute/profile/fetchProfile.ts new file mode 100644 index 0000000..a60c5e1 --- /dev/null +++ b/nodes/EvolutionApi/execute/profile/fetchProfile.ts @@ -0,0 +1,55 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function fetchProfile(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const remoteJid = ef.getNodeParameter('remoteJid', 0) as string; + + const body = { + number: remoteJid.includes('@') ? remoteJid : `${remoteJid}@s.whatsapp.net`, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/fetchProfile/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao buscar perfil', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/profile/removeProfilePicture.ts b/nodes/EvolutionApi/execute/profile/removeProfilePicture.ts new file mode 100644 index 0000000..1bcf040 --- /dev/null +++ b/nodes/EvolutionApi/execute/profile/removeProfilePicture.ts @@ -0,0 +1,49 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function removeProfilePicture(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + + const requestOptions: IRequestOptions = { + method: 'DELETE' as IHttpRequestMethods, + uri: `/chat/removeProfilePicture/${instanceName}`, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao remover foto do perfil', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/profile/updatePrivacySettings.ts b/nodes/EvolutionApi/execute/profile/updatePrivacySettings.ts new file mode 100644 index 0000000..5bee3ff --- /dev/null +++ b/nodes/EvolutionApi/execute/profile/updatePrivacySettings.ts @@ -0,0 +1,65 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function updatePrivacySettings(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const readreceipts = ef.getNodeParameter('readreceipts', 0) as string; + const profile = ef.getNodeParameter('profile', 0) as string; + const status = ef.getNodeParameter('status', 0) as string; + const online = ef.getNodeParameter('online', 0) as string; + const last = ef.getNodeParameter('last', 0) as string; + const groupadd = ef.getNodeParameter('groupadd', 0) as string; + + const body = { + readreceipts, + profile, + status, + online, + last, + groupadd, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/updatePrivacySettings/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao atualizar configurações de privacidade', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/profile/updateProfileName.ts b/nodes/EvolutionApi/execute/profile/updateProfileName.ts new file mode 100644 index 0000000..4fa1006 --- /dev/null +++ b/nodes/EvolutionApi/execute/profile/updateProfileName.ts @@ -0,0 +1,55 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function updateProfileName(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const name = ef.getNodeParameter('name', 0) as string; + + const body = { + name, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/updateProfileName/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao atualizar nome do perfil', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/profile/updateProfilePicture.ts b/nodes/EvolutionApi/execute/profile/updateProfilePicture.ts new file mode 100644 index 0000000..52abfa5 --- /dev/null +++ b/nodes/EvolutionApi/execute/profile/updateProfilePicture.ts @@ -0,0 +1,55 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function updateProfilePicture(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const picture = ef.getNodeParameter('picture', 0) as string; + + const body = { + picture, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/updateProfilePicture/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao atualizar foto do perfil', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/execute/profile/updateProfileStatus.ts b/nodes/EvolutionApi/execute/profile/updateProfileStatus.ts new file mode 100644 index 0000000..2fe533a --- /dev/null +++ b/nodes/EvolutionApi/execute/profile/updateProfileStatus.ts @@ -0,0 +1,55 @@ +import { + IExecuteFunctions, + IRequestOptions, + IHttpRequestMethods, + NodeOperationError, +} from 'n8n-workflow'; +import { evolutionRequest } from '../evolutionRequest'; + +export async function updateProfileStatus(ef: IExecuteFunctions) { + try { + const instanceName = ef.getNodeParameter('instanceName', 0) as string; + const status = ef.getNodeParameter('status', 0) as string; + + const body = { + status, + }; + + const requestOptions: IRequestOptions = { + method: 'POST' as IHttpRequestMethods, + uri: `/chat/updateProfileStatus/${instanceName}`, + body, + json: true, + }; + + const response = await evolutionRequest(ef, requestOptions); + return { + json: { + success: true, + data: response, + }, + }; + } catch (error) { + const errorData = { + success: false, + error: { + message: error.message, + details: 'Erro ao atualizar status do perfil', + code: error.code || 'UNKNOWN_ERROR', + timestamp: new Date().toISOString(), + }, + }; + + if (!ef.continueOnFail()) { + throw new NodeOperationError(ef.getNode(), error.message, { + message: errorData.error.message, + description: errorData.error.details, + }); + } + + return { + json: errorData, + error: errorData, + }; + } +} diff --git a/nodes/EvolutionApi/properties/chat.fields.ts b/nodes/EvolutionApi/properties/chat.fields.ts new file mode 100644 index 0000000..24a4214 --- /dev/null +++ b/nodes/EvolutionApi/properties/chat.fields.ts @@ -0,0 +1,609 @@ +import { INodeProperties, NodePropertyTypes } from 'n8n-workflow'; + +export const chatFields: INodeProperties[] = [ + // Campos comuns para todas as operações + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância', + displayOptions: { + show: { + resource: ['chat-api'], + }, + }, + }, + + // Campos para verificar número + { + displayName: 'Números', + name: 'numbers', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Lista de números para verificar (separados por vírgula)', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['check-number'], + }, + }, + }, + + // Campos para ler mensagens + { + displayName: 'Contato', + name: 'remoteJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['read-messages'], + }, + }, + }, + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID da mensagem', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['read-messages'], + }, + }, + }, + { + displayName: 'Mensagem é Minha', + name: 'fromMe', + type: 'boolean' as NodePropertyTypes, + default: false, + required: true, + description: 'Se a mensagem foi enviada pela instância', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['read-messages'], + }, + }, + }, + + // Campos para gerenciar arquivo + { + displayName: 'Contato', + name: 'chat', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['manage-archive'], + }, + }, + }, + { + displayName: 'Ação', + name: 'archive', + type: 'options' as NodePropertyTypes, + options: [ + { + name: 'Arquivar', + value: true, + }, + { + name: 'Desarquivar', + value: false, + }, + ], + default: true, + required: true, + description: 'Escolha se deseja arquivar ou desarquivar a conversa', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['manage-archive'], + }, + }, + }, + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID da última mensagem', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['manage-archive'], + }, + }, + }, + { + displayName: 'Mensagem é Minha', + name: 'fromMe', + type: 'boolean' as NodePropertyTypes, + default: false, + required: true, + description: 'Se a mensagem foi enviada pela instância', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['manage-archive'], + }, + }, + }, + + // Campos para marcar como não lido + { + displayName: 'Contato', + name: 'chat', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['mark-unread'], + }, + }, + }, + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID da última mensagem', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['mark-unread'], + }, + }, + }, + { + displayName: 'Mensagem é Minha', + name: 'fromMe', + type: 'boolean' as NodePropertyTypes, + default: false, + required: true, + description: 'Se a mensagem foi enviada pela instância', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['mark-unread'], + }, + }, + }, + + // Campos para deletar mensagem + { + displayName: 'Contato', + name: 'remoteJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['delete-message'], + }, + }, + }, + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID da mensagem que será deletada', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['delete-message'], + }, + }, + }, + { + displayName: 'Mensagem é Minha', + name: 'fromMe', + type: 'boolean' as NodePropertyTypes, + default: false, + required: true, + description: 'Se a mensagem foi enviada pela instância', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['delete-message'], + }, + }, + }, + + // Campos para buscar foto do perfil + { + displayName: 'Contato', + name: 'number', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato (ex: 5511999999999)', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['fetch-profile-picture'], + }, + }, + }, + + // Campos para obter mídia em Base64 + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID da mensagem que contém a mídia', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['get-media-base64'], + }, + }, + }, + { + displayName: 'Converter para MP4', + name: 'convertToMp4', + type: 'boolean' as NodePropertyTypes, + default: false, + required: true, + description: 'Se deve converter o vídeo para formato MP4', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['get-media-base64'], + }, + }, + }, + + // Campos para editar mensagem + { + displayName: 'Contato', + name: 'remoteJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['update-message'], + }, + }, + }, + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID da mensagem que será editada', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['update-message'], + }, + }, + }, + { + displayName: 'Nova Mensagem', + name: 'text', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Novo texto da mensagem', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['update-message'], + }, + }, + }, + + // Campos para enviar presença + { + displayName: 'Contato', + name: 'remoteJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['send-presence'], + }, + }, + }, + { + displayName: 'Presença', + name: 'presence', + type: 'options', + options: [ + { + name: 'Escrevendo...', + value: 'composing', + }, + { + name: 'Gravando...', + value: 'recording', + }, + ], + default: 'composing', + required: true, + description: 'Tipo de presença a ser enviada', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['send-presence'], + }, + }, + }, + { + displayName: 'Delay', + name: 'delay', + type: 'number' as NodePropertyTypes, + default: 1200, + required: true, + description: 'Tempo em milissegundos que a presença ficará ativa', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['send-presence'], + }, + }, + }, + + // Campos para bloquear contato + { + displayName: 'Contato', + name: 'remoteJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['block-contact'], + }, + }, + }, + { + displayName: 'Ação', + name: 'status', + type: 'options', + options: [ + { + name: 'Bloquear', + value: 'block', + }, + { + name: 'Desbloquear', + value: 'unblock', + }, + ], + default: 'block', + required: true, + description: 'Ação a ser executada', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['block-contact'], + }, + }, + }, + + // Campos para listar contatos + { + displayName: 'Listar Todos', + name: 'listAll', + type: 'boolean' as NodePropertyTypes, + default: true, + required: true, + description: 'Se deve listar todos os contatos', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-contacts'], + }, + }, + }, + { + displayName: 'Contato', + name: 'remoteJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato específico', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-contacts'], + listAll: [false], + }, + }, + }, + + // Campos para procurar mensagens + { + displayName: 'Contato', + name: 'remoteJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-messages'], + }, + }, + }, + { + displayName: 'Página', + name: 'page', + type: 'number' as NodePropertyTypes, + default: 1, + required: false, + description: 'Número da página', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-messages'], + }, + }, + }, + { + displayName: 'Quantidade por Página', + name: 'offset', + type: 'number' as NodePropertyTypes, + default: 10, + required: false, + description: 'Quantidade de mensagens por página', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-messages'], + }, + }, + }, + + // Campos para procurar status de mensagens + { + displayName: 'Contato', + name: 'remoteJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-status-messages'], + }, + }, + }, + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID da mensagem', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-status-messages'], + }, + }, + }, + { + displayName: 'Página', + name: 'page', + type: 'number' as NodePropertyTypes, + default: 1, + required: false, + description: 'Número da página', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-status-messages'], + }, + }, + }, + { + displayName: 'Quantidade por Página', + name: 'offset', + type: 'number' as NodePropertyTypes, + default: 10, + required: false, + description: 'Quantidade de mensagens por página', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-status-messages'], + }, + }, + }, + + // Campos para procurar chats + { + displayName: 'Contato', + name: 'remoteJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-chats'], + }, + }, + }, + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID da mensagem', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-chats'], + }, + }, + }, + { + displayName: 'Página', + name: 'page', + type: 'number' as NodePropertyTypes, + default: 1, + required: false, + description: 'Número da página', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-chats'], + }, + }, + }, + { + displayName: 'Quantidade por Página', + name: 'offset', + type: 'number' as NodePropertyTypes, + default: 10, + required: false, + description: 'Quantidade de chats por página', + displayOptions: { + show: { + resource: ['chat-api'], + operation: ['find-chats'], + }, + }, + }, +]; diff --git a/nodes/EvolutionApi/properties/chat.operations.ts b/nodes/EvolutionApi/properties/chat.operations.ts new file mode 100644 index 0000000..e5a4ec7 --- /dev/null +++ b/nodes/EvolutionApi/properties/chat.operations.ts @@ -0,0 +1,100 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const chatOperations: INodeProperties = { + displayName: 'Operação', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { + show: { + resource: ['chat-api'], + }, + }, + options: [ + { + name: 'Verificar Número', + action: 'Verificar número no WhatsApp', + description: 'Verifica se um número está registrado no WhatsApp', + value: 'check-number', + }, + { + name: 'Ler Mensagens', + action: 'Marcar mensagens como lidas', + description: 'Marca mensagens específicas como lidas', + value: 'read-messages', + }, + { + name: 'Gerenciar Arquivo', + action: 'Gerenciar arquivo de conversa', + description: 'Arquiva ou desarquiva uma conversa', + value: 'manage-archive', + }, + { + name: 'Marcar Como Não Lido', + action: 'Marcar conversa como não lida', + description: 'Marca uma conversa específica como não lida', + value: 'mark-unread', + }, + { + name: 'Deletar Mensagem', + action: 'Deletar mensagem', + description: 'Deleta uma mensagem específica para todos', + value: 'delete-message', + }, + { + name: 'Buscar Foto do Perfil', + action: 'Buscar foto do perfil', + description: 'Obtém a URL da foto do perfil de um contato', + value: 'fetch-profile-picture', + }, + { + name: 'Obter Mídia em Base64', + action: 'Obter mídia em Base64', + description: 'Obtém o conteúdo de uma mídia em formato Base64', + value: 'get-media-base64', + }, + { + name: 'Editar Mensagem', + action: 'Editar mensagem', + description: 'Edita uma mensagem enviada anteriormente', + value: 'update-message', + }, + { + name: 'Enviar Presença', + action: 'Enviar presença', + description: 'Envia o status de presença (digitando/gravando) para um contato', + value: 'send-presence', + }, + { + name: 'Bloquear Contato', + action: 'Bloquear Contato', + description: 'Bloqueia ou desbloqueia um contato', + value: 'block-contact', + }, + { + name: 'Listar Contatos', + action: 'Listar contatos', + description: 'Lista todos os contatos ou busca um contato específico', + value: 'find-contacts', + }, + { + name: 'Procurar Mensagens', + action: 'Procurar mensagens de um contato', + description: 'Busca mensagens de um contato específico', + value: 'find-messages', + }, + { + name: 'Procurar Status', + action: 'Procurar status de mensagens', + description: 'Busca status de mensagens de um contato específico', + value: 'find-status-messages', + }, + { + name: 'Procurar Chats', + action: 'Procurar chats', + description: 'Busca chats de um contato específico', + value: 'find-chats', + }, + ], + default: 'check-number', +}; diff --git a/nodes/EvolutionApi/properties/events.fields.ts b/nodes/EvolutionApi/properties/events.fields.ts new file mode 100644 index 0000000..99bd691 --- /dev/null +++ b/nodes/EvolutionApi/properties/events.fields.ts @@ -0,0 +1,367 @@ +import { INodeProperties } from 'n8n-workflow'; + +// Campo das Eventos +export const eventsFields: INodeProperties[] = [ + // Campos = Webhook + { + displayName: 'Nome da Instancia', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar a mensagem', + displayOptions: { + show: { + resource: ['events-api'], + operation: ['webhook'], + }, + }, + }, + { + displayName: 'O que deseja fazer', + name: 'resourceForWebhook', + type: 'options', + options: [ + { + name: 'Definir Webhook', + value: 'setWebhook', + }, + { + name: 'Verificar Webhook', + value: 'findWebhook', + }, + ], + default: 'setWebhook', + description: 'Escolha entre definir um novo webhook ou verificar o webhook', + displayOptions: { + show: { + resource: ['events-api'], + operation: ['webhook'], + }, + }, + }, + { + displayName: 'Ativar Webhook', + name: 'enabled', + type: 'boolean', + default: true, + description: 'Whether to enable or disable integration with Webhook', + displayOptions: { + show: { + resource: ['events-api'], + operation: ['webhook'], + resourceForWebhook: ['setWebhook'], + }, + }, + }, + { + displayName: 'Url do Webhook', + name: 'webhookUrl', + type: 'string', + default: '', + description: 'Digite a Url que vai receber os eventos do Webhook', + displayOptions: { + show: { + resource: ['events-api'], + operation: ['webhook'], + resourceForWebhook: ['setWebhook'], + }, + }, + }, + { + displayName: 'Webhook por Eventos', + name: 'webhookByEvents', + type: 'boolean', + default: false, + description: + 'Whether to create a route for each event by appending the event name to the end of the URL', + displayOptions: { + show: { + resource: ['events-api'], + operation: ['webhook'], + resourceForWebhook: ['setWebhook'], + }, + }, + }, + { + displayName: 'Base64 no Webhook', + name: 'webhookBase64', + type: 'boolean', + default: false, + description: 'Whether to send media data in base64 format in the webhook', + displayOptions: { + show: { + resource: ['events-api'], + operation: ['webhook'], + resourceForWebhook: ['setWebhook'], + }, + }, + }, + { + displayName: 'Eventos', + name: 'webhookEvents', + type: 'multiOptions', + displayOptions: { + show: { + resource: ['events-api'], + operation: ['webhook'], + resourceForWebhook: ['setWebhook'], + }, + }, + default: [], + options: [ + { + name: 'CALL', + value: 'CALL', + }, + { + name: 'CHATS_DELETE', + value: 'CHATS_DELETE', + }, + { + name: 'CHATS_SET', + value: 'CHATS_SET', + }, + { + name: 'CHATS_UPDATE', + value: 'CHATS_UPDATE', + }, + { + name: 'CHATS_UPSERT', + value: 'CHATS_UPSERT', + }, + { + name: 'CONNECTION_UPDATE', + value: 'CONNECTION_UPDATE', + }, + { + name: 'CONTACTS_SET', + value: 'CONTACTS_SET', + }, + { + name: 'CONTACTS_UPDATE', + value: 'CONTACTS_UPDATE', + }, + { + name: 'CONTACTS_UPSERT', + value: 'CONTACTS_UPSERT', + }, + { + name: 'GROUP_PARTICIPANTS_UPDATE', + value: 'GROUP_PARTICIPANTS_UPDATE', + }, + { + name: 'GROUP_UPDATE', + value: 'GROUP_UPDATE', + }, + { + name: 'GROUPS_UPSERT', + value: 'GROUPS_UPSERT', + }, + { + name: 'LABELS_ASSOCIATION', + value: 'LABELS_ASSOCIATION', + }, + { + name: 'LABELS_EDIT', + value: 'LABELS_EDIT', + }, + { + name: 'MESSAGES_DELETE', + value: 'MESSAGES_DELETE', + }, + { + name: 'MESSAGES_SET', + value: 'MESSAGES_SET', + }, + { + name: 'MESSAGES_UPDATE', + value: 'MESSAGES_UPDATE', + }, + { + name: 'MESSAGES_UPSERT', + value: 'MESSAGES_UPSERT', + }, + { + name: 'PRESENCE_UPDATE', + value: 'PRESENCE_UPDATE', + }, + { + name: 'QRCODE_UPDATED', + value: 'QRCODE_UPDATED', + }, + { + name: 'SEND_MESSAGE', + value: 'SEND_MESSAGE', + }, + { + name: 'TYPEBOT_CHANGE_STATUS', + value: 'TYPEBOT_CHANGE_STATUS', + }, + { + name: 'TYPEBOT_START', + value: 'TYPEBOT_START', + }, + ], + }, + + // Campos = RabbitMQ + { + displayName: 'Nome da Instancia', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar a mensagem', + displayOptions: { + show: { + resource: ['events-api'], + operation: ['rabbitmq'], + }, + }, + }, + { + displayName: 'O que deseja fazer', + name: 'resourceForRabbitMQ', + type: 'options', + options: [ + { + name: 'Definir RabbitMQ', + value: 'setRabbitMQ', + }, + { + name: 'Verificar RabbitMQ', + value: 'findRabbitMQ', + }, + ], + default: 'setRabbitMQ', + description: 'Escolha entre ativar/desativar RabbitMQ ou verificar o RabbitMQ', + displayOptions: { + show: { + resource: ['events-api'], + operation: ['rabbitmq'], + }, + }, + }, + { + displayName: 'Ativar RabbitMQ', + name: 'enabled', + type: 'boolean', + default: true, + description: 'Whether to enable or disable integration with RabbitMQ.', + displayOptions: { + show: { + resource: ['events-api'], + operation: ['rabbitmq'], + resourceForRabbitMQ: ['setRabbitMQ'], + }, + }, + }, + { + displayName: 'Eventos', + name: 'rabbitMQEvents', + type: 'multiOptions', + displayOptions: { + show: { + resource: ['events-api'], + operation: ['rabbitmq'], + resourceForRabbitMQ: ['setRabbitMQ'], + }, + }, + default: [], + options: [ + { + name: 'CALL', + value: 'CALL', + }, + { + name: 'CHATS_DELETE', + value: 'CHATS_DELETE', + }, + { + name: 'CHATS_SET', + value: 'CHATS_SET', + }, + { + name: 'CHATS_UPDATE', + value: 'CHATS_UPDATE', + }, + { + name: 'CHATS_UPSERT', + value: 'CHATS_UPSERT', + }, + { + name: 'CONNECTION_UPDATE', + value: 'CONNECTION_UPDATE', + }, + { + name: 'CONTACTS_SET', + value: 'CONTACTS_SET', + }, + { + name: 'CONTACTS_UPDATE', + value: 'CONTACTS_UPDATE', + }, + { + name: 'CONTACTS_UPSERT', + value: 'CONTACTS_UPSERT', + }, + { + name: 'GROUP_PARTICIPANTS_UPDATE', + value: 'GROUP_PARTICIPANTS_UPDATE', + }, + { + name: 'GROUP_UPDATE', + value: 'GROUP_UPDATE', + }, + { + name: 'GROUPS_UPSERT', + value: 'GROUPS_UPSERT', + }, + { + name: 'LABELS_ASSOCIATION', + value: 'LABELS_ASSOCIATION', + }, + { + name: 'LABELS_EDIT', + value: 'LABELS_EDIT', + }, + { + name: 'MESSAGES_DELETE', + value: 'MESSAGES_DELETE', + }, + { + name: 'MESSAGES_SET', + value: 'MESSAGES_SET', + }, + { + name: 'MESSAGES_UPDATE', + value: 'MESSAGES_UPDATE', + }, + { + name: 'MESSAGES_UPSERT', + value: 'MESSAGES_UPSERT', + }, + { + name: 'PRESENCE_UPDATE', + value: 'PRESENCE_UPDATE', + }, + { + name: 'QRCODE_UPDATED', + value: 'QRCODE_UPDATED', + }, + { + name: 'SEND_MESSAGE', + value: 'SEND_MESSAGE', + }, + { + name: 'TYPEBOT_CHANGE_STATUS', + value: 'TYPEBOT_CHANGE_STATUS', + }, + { + name: 'TYPEBOT_START', + value: 'TYPEBOT_START', + }, + ], + }, +]; diff --git a/nodes/EvolutionApi/properties/events.operations.ts b/nodes/EvolutionApi/properties/events.operations.ts new file mode 100644 index 0000000..9519e13 --- /dev/null +++ b/nodes/EvolutionApi/properties/events.operations.ts @@ -0,0 +1,33 @@ +import { INodeProperties } from 'n8n-workflow'; + +// Opções da events-api (Eventos) +export const eventsOperationsOptions: INodeProperties = { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { + show: { + resource: ['events-api'], // Value do Resource + }, + }, + options: [ + // Opção = Enviar mensagem de Texto + { + // Set/find Webhook + name: 'Webhook', + action: 'Webhook', + description: 'Define/Busca integração com Webhook', + value: 'webhook', + }, + { + // Set/find Rabbitmq + name: 'RabbitMQ', + action: 'Rabbitmq', + description: 'Define/Busca integração com RabbitMQ', + value: 'rabbitmq', + }, + ], + // Definindo como padrão a opção "Enviar Texto" + default: 'webhook', +}; diff --git a/nodes/EvolutionApi/properties/groups.fields.ts b/nodes/EvolutionApi/properties/groups.fields.ts new file mode 100644 index 0000000..5ababad --- /dev/null +++ b/nodes/EvolutionApi/properties/groups.fields.ts @@ -0,0 +1,691 @@ +import { INodeProperties, NodePropertyTypes } from 'n8n-workflow'; + +export const groupsFields: INodeProperties[] = [ + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância que vai criar o grupo', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['create-group'], + }, + }, + }, + { + displayName: 'Nome do Grupo', + name: 'subject', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome do grupo que será criado', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['create-group'], + }, + }, + }, + { + displayName: 'Descrição', + name: 'description', + type: 'string' as NodePropertyTypes, + default: '', + required: false, + description: 'Digite a descrição do grupo (opcional)', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['create-group'], + }, + }, + }, + { + displayName: 'Participantes', + name: 'participants', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite os números dos participantes separados por vírgula (ex: 5511999999999,5511888888888)', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['create-group'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância que vai atualizar a imagem', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-group-picture'], + }, + }, + }, + { + displayName: 'ID do Grupo', + name: 'groupJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID do grupo que terá a imagem atualizada', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-group-picture'], + }, + }, + }, + { + displayName: 'URL da Imagem', + name: 'image', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'URL da imagem que será definida como foto do grupo', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-group-picture'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância que vai atualizar o nome do grupo', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-group-name'], + }, + }, + }, + { + displayName: 'ID do Grupo', + name: 'groupJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID do grupo que terá o nome atualizado', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-group-name'], + }, + }, + }, + { + displayName: 'Novo Nome do Grupo', + name: 'subject', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Novo nome que será definido para o grupo', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-group-name'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância que vai atualizar a descrição', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-group-description'], + }, + }, + }, + { + displayName: 'ID do Grupo', + name: 'groupJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID do grupo que terá a descrição atualizada', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-group-description'], + }, + }, + }, + { + displayName: 'Nova Descrição', + name: 'description', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Nova descrição que será definida para o grupo', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-group-description'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância que vai buscar o código', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['fetch-invite-code'], + }, + }, + }, + { + displayName: 'ID do Grupo', + name: 'groupJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID do grupo para obter o código de convite', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['fetch-invite-code'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância que vai revogar o código', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['revoke-invite-code'], + }, + }, + }, + { + displayName: 'ID do Grupo', + name: 'groupJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID do grupo para revogar o código de convite', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['revoke-invite-code'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar o convite', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['send-invite-link'], + }, + }, + }, + { + displayName: 'ID do Grupo', + name: 'groupJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID do grupo para enviar o convite', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['send-invite-link'], + }, + }, + }, + { + displayName: 'Mensagem do Convite', + name: 'description', + type: 'string' as NodePropertyTypes, + default: 'Segue o link do grupo', + required: true, + description: 'Mensagem que será enviada junto com o link do convite', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['send-invite-link'], + }, + }, + }, + { + displayName: 'Destinatários', + name: 'numbers', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite os números dos destinatários separados por vírgula (ex: 5511999999999,5511888888888)', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['send-invite-link'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância que vai buscar o grupo', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['fetch-group-by-code'], + }, + }, + }, + { + displayName: 'Código do Convite', + name: 'inviteCode', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Código do convite do grupo (ex: JZNHJLvnNd04UvGefiEZAA)', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['fetch-group-by-code'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['fetch-groups'], + }, + }, + }, + { + displayName: 'Método de Busca', + name: 'searchMethod', + type: 'options' as NodePropertyTypes, + options: [ + { + name: 'Por Código de Convite', + value: 'inviteCode', + }, + { + name: 'Por ID do Grupo', + value: 'groupJid', + }, + { + name: 'Buscar Todos os Grupos', + value: 'fetchAll', + }, + ], + default: 'inviteCode', + required: true, + description: 'Escolha o método para buscar os grupos', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['fetch-groups'], + }, + }, + }, + { + displayName: 'Código do Convite', + name: 'inviteCode', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Código do convite do grupo (ex: JZNHJLvnNd04UvGefiEZAA)', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['fetch-groups'], + searchMethod: ['inviteCode'], + }, + }, + }, + { + displayName: 'ID do Grupo', + name: 'groupJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID do grupo para buscar informações', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['fetch-groups'], + searchMethod: ['groupJid'], + }, + }, + }, + { + displayName: 'Obter Participantes', + name: 'getParticipants', + type: 'boolean' as NodePropertyTypes, + default: false, + required: false, + description: 'Se deve obter a lista de participantes dos grupos', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['fetch-groups'], + searchMethod: ['fetchAll'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['find-participants'], + }, + }, + }, + { + displayName: 'ID do Grupo', + name: 'groupJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID do grupo para buscar os participantes', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['find-participants'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-participants'], + }, + }, + }, + { + displayName: 'ID do Grupo', + name: 'groupJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID do grupo para atualizar os membros', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-participants'], + }, + }, + }, + { + displayName: 'Ação', + name: 'action', + type: 'options' as NodePropertyTypes, + options: [ + { + name: 'Adicionar Membro', + value: 'add', + }, + { + name: 'Remover Membro', + value: 'remove', + }, + { + name: 'Promover a Administrador', + value: 'promote', + }, + { + name: 'Rebaixar para Membro', + value: 'demote', + }, + ], + default: 'add', + required: true, + description: 'Ação a ser executada com os membros', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-participants'], + }, + }, + }, + { + displayName: 'Membros', + name: 'participants', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Lista de números dos membros separados por vírgula (ex: 5511999999999,5511888888888)', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-participants'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-settings'], + }, + }, + }, + { + displayName: 'ID do Grupo', + name: 'groupJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID do grupo para atualizar as configurações', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-settings'], + }, + }, + }, + { + displayName: 'Ação', + name: 'action', + type: 'options' as NodePropertyTypes, + options: [ + { + name: 'Somente Admins Enviam Mensagens', + value: 'announcement', + }, + { + name: 'Todos Enviam Mensagens', + value: 'not_announcement', + }, + { + name: 'Somente Admins Editam Configurações', + value: 'locked', + }, + { + name: 'Todos Editam Configurações', + value: 'unlocked', + }, + ], + default: 'not_announcement', + required: true, + description: 'Configuração a ser aplicada no grupo', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['update-settings'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['toggle-ephemeral'], + }, + }, + }, + { + displayName: 'ID do Grupo', + name: 'groupJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID do grupo para configurar mensagens temporárias', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['toggle-ephemeral'], + }, + }, + }, + { + displayName: 'Expiração', + name: 'expiration', + type: 'options' as NodePropertyTypes, + options: [ + { + name: 'Desativado', + value: 0, + }, + { + name: '24 Horas', + value: 86400, + }, + { + name: '7 Dias', + value: 604800, + }, + { + name: '90 Dias', + value: 7776000, + }, + ], + default: 0, + required: true, + description: 'Tempo de expiração das mensagens', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['toggle-ephemeral'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['leave-group'], + }, + }, + }, + { + displayName: 'ID do Grupo', + name: 'groupJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'ID do grupo que deseja sair', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['leave-group'], + }, + }, + }, + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância que vai entrar no grupo', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['join-group'], + }, + }, + }, + { + displayName: 'Código do Convite', + name: 'inviteCode', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o código do convite do grupo (ex: JZNHJLvnNd04UvGefiEZAA)', + displayOptions: { + show: { + resource: ['groups-api'], + operation: ['join-group'], + }, + }, + }, +]; diff --git a/nodes/EvolutionApi/properties/groups.operations.ts b/nodes/EvolutionApi/properties/groups.operations.ts new file mode 100644 index 0000000..c4d5f12 --- /dev/null +++ b/nodes/EvolutionApi/properties/groups.operations.ts @@ -0,0 +1,100 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const groupsOperations: INodeProperties = { + displayName: 'Operação', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { + show: { + resource: ['groups-api'], + }, + }, + options: [ + { + name: 'Criar Grupo', + action: 'Criar um novo grupo', + description: 'Cria um novo grupo no WhatsApp', + value: 'create-group', + }, + { + name: 'Atualizar Imagem do Grupo', + action: 'Atualizar imagem do grupo', + description: 'Atualiza a imagem de perfil do grupo', + value: 'update-group-picture', + }, + { + name: 'Atualizar Nome do Grupo', + action: 'Atualizar nome do grupo', + description: 'Atualiza o nome/título do grupo', + value: 'update-group-name', + }, + { + name: 'Atualizar Descrição do Grupo', + action: 'Atualizar descrição do grupo', + description: 'Atualiza a descrição do grupo', + value: 'update-group-description', + }, + { + name: 'Atualizar Configurações', + action: 'Atualizar configurações do grupo', + description: 'Atualiza as configurações de permissões do grupo', + value: 'update-settings', + }, + { + name: 'Atualizar Membros', + action: 'Atualizar membros do grupo', + description: 'Adiciona, remove ou atualiza permissões de membros', + value: 'update-participants', + }, + { + name: 'Buscar Link de Convite', + action: 'Buscar Link de Convite', + description: 'Obtém o link de convite do grupo', + value: 'fetch-invite-code', + }, + { + name: 'Revogar Link de Convite', + action: 'Revogar Link de Convite', + description: 'Revoga o link de convite atual do grupo', + value: 'revoke-invite-code', + }, + { + name: 'Enviar Link de Convite', + action: 'Enviar link de convite', + description: 'Envia o link de convite do grupo para contatos', + value: 'send-invite-link', + }, + { + name: 'Buscar Grupos', + action: 'Buscar grupos', + description: 'Busca informações de grupos por diferentes métodos', + value: 'fetch-groups', + }, + { + name: 'Encontrar Participantes', + action: 'Encontrar participantes do grupo', + description: 'Obtém a lista de participantes de um grupo', + value: 'find-participants', + }, + { + name: 'Mensagens Temporárias', + action: 'Configurar mensagens temporárias', + description: 'Define o tempo de expiração das mensagens no grupo', + value: 'toggle-ephemeral', + }, + { + name: 'Entrar no Grupo', + action: 'Entrar no grupo', + description: 'Entra em um grupo usando o código de convite', + value: 'join-group', + }, + { + name: 'Sair do Grupo', + action: 'Sair do grupo', + description: 'Remove a instância do grupo', + value: 'leave-group', + }, + ], + default: 'create-group', +}; diff --git a/nodes/EvolutionApi/properties/index.ts b/nodes/EvolutionApi/properties/index.ts new file mode 100644 index 0000000..e99db8b --- /dev/null +++ b/nodes/EvolutionApi/properties/index.ts @@ -0,0 +1,78 @@ +import { INodeProperties } from 'n8n-workflow'; +import { eventsFields as eventsFields } from './events.fields'; +import { instancesFields } from './instances.fields'; +import { integrationsFields as integrationsFields } from './integrations.fields'; +import { messagesFields as messagesFields } from './messages.fields'; +import { eventsOperationsOptions } from './events.operations'; +import { instancesOperationsOptions } from './instances.operations'; +import { integrationsOperationsOptions } from './integrations.operations'; +import { messagesOperationsOptions } from './messages.operations'; +import { groupsFields } from './groups.fields'; +import { groupsOperations } from './groups.operations'; +import { chatFields } from './chat.fields'; +import { chatOperations } from './chat.operations'; +import { profileFields } from './profile.fields'; +import { profileOperationsOptions } from './profile.operations'; +const resourcesOptions: INodeProperties = { + displayName: 'Recurso', + name: 'resource', + type: 'options', + noDataExpression: true, + options: [ + { + name: 'Instancia', + value: 'instances-api', + }, + { + name: 'Mensagem', + value: 'messages-api', + }, + { + name: 'Grupo', + value: 'groups-api', + }, + { + name: 'Chat', + value: 'chat-api', + }, + { + name: 'Perfil', + value: 'profile-api', + }, + { + name: 'Evento', + value: 'events-api', + }, + { + name: 'Integração', + value: 'integrations-api', + }, + ], + default: 'instances-api', +}; + +export const evolutionNodeProperties = [ + resourcesOptions, + // Funções disponíveis quando selecionado o recurso "Instancias" + instancesOperationsOptions, + // Funções disponíveis quando selecionado o recurso "Mensagens" + messagesOperationsOptions, + // Funções disponíveis quando selecionado o recurso "Grupos" + groupsOperations, + // Funções disponíveis quando selecionado o recurso "Eventos" + eventsOperationsOptions, + // Funções disponíveis quando selecionado o recurso "Integrações" + integrationsOperationsOptions, + // Funções disponíveis quando selecionado o recurso "Perfil" + profileOperationsOptions, + // Funções disponíveis quando selecionado o recurso "Chat" + chatOperations, + // Campos disponíveis quando selecionado o recurso e alguma operação + ...instancesFields, + ...messagesFields, + ...groupsFields, + ...eventsFields, + ...integrationsFields, + ...chatFields, + ...profileFields, +]; diff --git a/nodes/EvolutionApi/properties/instances.fields.ts b/nodes/EvolutionApi/properties/instances.fields.ts new file mode 100644 index 0000000..f938648 --- /dev/null +++ b/nodes/EvolutionApi/properties/instances.fields.ts @@ -0,0 +1,952 @@ +import { INodeProperties } from 'n8n-workflow'; + +// Campos das instancias +export const instancesFields: INodeProperties[] = [ + // Campos = Criar Instancia + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome para a instância', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-basic'], + }, + }, + }, + { + displayName: 'Apikey para instancia', + name: 'token', + type: 'string', + typeOptions: { + password: true, + }, + default: '', + required: false, + description: 'Opicional: Digite um Token para a instancia', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-basic'], + }, + }, + }, + { + displayName: 'Número do WhatsApp', + name: 'number', + type: 'string', + default: '', + required: false, + description: + 'Opicional: Numero que vai ser conectado na instancia, para receber o Código de pareamento', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-basic'], + }, + }, + }, + { + displayName: 'Opções', + name: 'options_Create_instance', + type: 'collection', + placeholder: 'Adicionar Campo', + default: {}, + options: [ + { + displayName: 'Comportamento', + name: 'instanceSettings', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { settings: {} }, + options: [ + { + displayName: 'Comportamento Da Instancia', + name: 'settings', + values: [ + { + displayName: 'Rejeitar Ligações', + name: 'rejectCall', + type: 'boolean', + default: false, + description: 'Whether to automatically reject incoming calls', + }, + { + displayName: 'Mensagem Ao Rejeitar', + name: 'msgCall', + type: 'string', + default: '', + description: + 'Whether to send a message after rejecting a call, and if so, what message', + }, + { + displayName: 'Ignorar Grupos', + name: 'groupsIgnore', + type: 'boolean', + default: false, + description: 'Whether to ignore messages from groups', + }, + { + displayName: 'Sempre Online', + name: 'alwaysOnline', + type: 'boolean', + default: false, + description: 'Whether to keep the status always set to Online', + }, + { + displayName: 'Ler Mensagens', + name: 'readMessages', + type: 'boolean', + default: false, + description: 'Whether to automatically mark messages as read', + }, + { + displayName: 'Ler Status', + name: 'readStatus', + type: 'boolean', + default: false, + description: 'Whether to allow the API to view the Status of added contacts', + }, + { + displayName: 'Sincronizar Histórico', + name: 'syncFullHistory', + type: 'boolean', + default: false, + description: 'Whether to synchronize the full message history with the API', + }, + ], + }, + ], + description: 'Comportamento da instância', + }, + { + displayName: 'Proxy', + name: 'proxy', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { settings: {} }, + options: [ + { + displayName: 'Configurações Do Proxy', + name: 'proxySettings', + values: [ + { + displayName: 'Host Do Proxy', + name: 'proxyHost', + type: 'string', + default: '', + description: 'Digite o host do proxy', + }, + { + displayName: 'Porta Do Proxy', + name: 'proxyPort', + type: 'string', + default: '1234', + description: 'Digite a porta do proxy', + }, + { + displayName: 'Protocolo Do Proxy', + name: 'proxyProtocol', + type: 'options', + options: [ + { + name: 'HTTP', + value: 'http', + }, + { + name: 'HTTPS', + value: 'https', + }, + ], + default: 'http', + description: 'Selecione o protocolo do proxy', + }, + { + displayName: 'Usuário Do Proxy', + name: 'proxyUsername', + type: 'string', + default: '', + description: 'Digite o usuário do proxy', + }, + { + displayName: 'Senha Do Proxy', + name: 'proxyPassword', + type: 'string', + typeOptions: { + password: true, + }, + default: '', + description: 'Digite a senha do proxy', + }, + ], + }, + ], + description: 'Configurações do proxy', + }, + + { + displayName: 'Webhook', + name: 'webhook', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { settings: {} }, + options: [ + { + displayName: 'Configurações Do Webhook', + name: 'webhookSettings', + values: [ + { + displayName: 'Url do Webhook', + name: 'webhookUrl', + type: 'string', + default: '', + description: 'Digite a Url que vai receber os eventos do Webhook', + }, + { + displayName: 'Webhook por Eventos', + name: 'webhookByEvents', + type: 'boolean', + default: false, + description: + 'Whether to create a route for each event by appending the event name to the end of the URL', // Atualizado + }, + { + displayName: 'Base64 no Webhook', + name: 'webhookBase64', + type: 'boolean', + default: false, + description: 'Whether to send media data in base64 format in the webhook', // Atualizado + }, + { + displayName: 'Eventos', + name: 'webhookEvents', + type: 'multiOptions', + default: [], // Adicionado para resolver o erro + options: [ + { + name: 'CALL', + value: 'CALL', + }, + { + name: 'CHATS_DELETE', + value: 'CHATS_DELETE', + }, + { + name: 'CHATS_SET', + value: 'CHATS_SET', + }, + { + name: 'CHATS_UPDATE', + value: 'CHATS_UPDATE', + }, + { + name: 'CHATS_UPSERT', + value: 'CHATS_UPSERT', + }, + { + name: 'CONNECTION_UPDATE', + value: 'CONNECTION_UPDATE', + }, + { + name: 'CONTACTS_SET', + value: 'CONTACTS_SET', + }, + { + name: 'CONTACTS_UPDATE', + value: 'CONTACTS_UPDATE', + }, + { + name: 'CONTACTS_UPSERT', + value: 'CONTACTS_UPSERT', + }, + { + name: 'GROUP_PARTICIPANTS_UPDATE', + value: 'GROUP_PARTICIPANTS_UPDATE', + }, + { + name: 'GROUP_UPDATE', + value: 'GROUP_UPDATE', + }, + { + name: 'GROUPS_UPSERT', + value: 'GROUPS_UPSERT', + }, + { + name: 'LABELS_ASSOCIATION', + value: 'LABELS_ASSOCIATION', + }, + { + name: 'LABELS_EDIT', + value: 'LABELS_EDIT', + }, + { + name: 'MESSAGES_DELETE', + value: 'MESSAGES_DELETE', + }, + { + name: 'MESSAGES_SET', + value: 'MESSAGES_SET', + }, + { + name: 'MESSAGES_UPDATE', + value: 'MESSAGES_UPDATE', + }, + { + name: 'MESSAGES_UPSERT', + value: 'MESSAGES_UPSERT', + }, + { + name: 'PRESENCE_UPDATE', + value: 'PRESENCE_UPDATE', + }, + { + name: 'QRCODE_UPDATED', + value: 'QRCODE_UPDATED', + }, + { + name: 'SEND_MESSAGE', + value: 'SEND_MESSAGE', + }, + { + name: 'TYPEBOT_CHANGE_STATUS', + value: 'TYPEBOT_CHANGE_STATUS', + }, + { + name: 'TYPEBOT_START', + value: 'TYPEBOT_START', + }, + ], + }, + ], + }, + ], + description: 'Os eventos a serem monitorados', + }, + + { + displayName: 'RabbitMQ', + name: 'rabbitmq', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { settings: {} }, + options: [ + { + displayName: 'Configurações Do RabbitMQ', + name: 'rabbitmqSettings', + values: [ + { + displayName: 'Ativa ou desativa o RabbitMQ', + name: 'rabbitmqEnabled', + type: 'boolean', + default: false, + description: 'Whether to send media data in base64 format in the RabbitMQ', // Atualizado + }, + { + displayName: 'Eventos', + name: 'rabbitmqEvents', + type: 'multiOptions', + default: [], // Adicionado para resolver o erro + options: [ + { + name: 'CALL', + value: 'CALL', + }, + { + name: 'CHATS_DELETE', + value: 'CHATS_DELETE', + }, + { + name: 'CHATS_SET', + value: 'CHATS_SET', + }, + { + name: 'CHATS_UPDATE', + value: 'CHATS_UPDATE', + }, + { + name: 'CHATS_UPSERT', + value: 'CHATS_UPSERT', + }, + { + name: 'CONNECTION_UPDATE', + value: 'CONNECTION_UPDATE', + }, + { + name: 'CONTACTS_SET', + value: 'CONTACTS_SET', + }, + { + name: 'CONTACTS_UPDATE', + value: 'CONTACTS_UPDATE', + }, + { + name: 'CONTACTS_UPSERT', + value: 'CONTACTS_UPSERT', + }, + { + name: 'GROUP_PARTICIPANTS_UPDATE', + value: 'GROUP_PARTICIPANTS_UPDATE', + }, + { + name: 'GROUP_UPDATE', + value: 'GROUP_UPDATE', + }, + { + name: 'GROUPS_UPSERT', + value: 'GROUPS_UPSERT', + }, + { + name: 'LABELS_ASSOCIATION', + value: 'LABELS_ASSOCIATION', + }, + { + name: 'LABELS_EDIT', + value: 'LABELS_EDIT', + }, + { + name: 'MESSAGES_DELETE', + value: 'MESSAGES_DELETE', + }, + { + name: 'MESSAGES_SET', + value: 'MESSAGES_SET', + }, + { + name: 'MESSAGES_UPDATE', + value: 'MESSAGES_UPDATE', + }, + { + name: 'MESSAGES_UPSERT', + value: 'MESSAGES_UPSERT', + }, + { + name: 'PRESENCE_UPDATE', + value: 'PRESENCE_UPDATE', + }, + { + name: 'QRCODE_UPDATED', + value: 'QRCODE_UPDATED', + }, + { + name: 'SEND_MESSAGE', + value: 'SEND_MESSAGE', + }, + { + name: 'TYPEBOT_CHANGE_STATUS', + value: 'TYPEBOT_CHANGE_STATUS', + }, + { + name: 'TYPEBOT_START', + value: 'TYPEBOT_START', + }, + ], + }, + ], + }, + ], + description: 'Os eventos a serem monitorados', + }, + + { + displayName: 'Chatwoot', + name: 'chatwoot', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { settings: {} }, + options: [ + { + displayName: 'Configurações Do Chatwoot', + name: 'chatwootSettings', + values: [ + { + displayName: 'ID Da Conta Do Chatwoot', + name: 'chatwootAccountId', + type: 'string', + default: '', + description: 'Digite o ID da conta do Chatwoot', + }, + { + displayName: 'Token De Admin Do Chatwoot', + name: 'chatwootToken', + type: 'string', + typeOptions: { + password: true, + }, + default: '', + description: 'Digite o token de admin do Chatwoot', + }, + { + displayName: 'Link Do Chatwoot', + name: 'chatwootUrl', + type: 'string', + default: '', + description: 'Digite o link do Chatwoot', + }, + { + displayName: 'Assinatura Do Agente Do Chatwoot', + name: 'chatwootSignMsg', + type: 'boolean', + default: false, + description: 'Whether to enable or disable the Chatwoot agent signature', + }, + { + displayName: 'Reabrir Mensagens No Chatwoot', + name: 'chatwootReopenConversation', + type: 'boolean', + default: false, + description: 'Whether to enable or disable reopening messages in Chatwoot', + }, + { + displayName: 'Iniciar Conversas Como Pendentes No Chatwoot', + name: 'chatwootConversationPending', + type: 'boolean', + default: false, + description: 'Whether to start conversations as pending in Chatwoot', + }, + { + displayName: 'Importar Contatos Para O Chatwoot', + name: 'chatwootImportContacts', + type: 'boolean', + default: false, + description: 'Whether to import contacts to Chatwoot', + }, + { + displayName: 'Nome Da Inbox Do Chatwoot', + name: 'chatwootNameInbox', + type: 'string', + default: '', + description: 'Digite o nome da Inbox do Chatwoot', + }, + { + displayName: 'Mesclar Contatos Brasileiros No Chatwoot', + name: 'chatwootMergeBrazilContacts', + type: 'boolean', + default: false, + description: 'Whether to merge Brazilian contacts in Chatwoot', + }, + { + displayName: 'Importar Mensagens Para O Chatwoot', + name: 'chatwootImportMessages', + type: 'boolean', + default: false, + description: 'Whether to import messages to Chatwoot', + }, + { + displayName: 'Importar Mensagens De Quantos Dias Para O Chatwoot', + name: 'chatwootDaysLimitImportMessages', + type: 'number', + default: 0, + description: + 'Digite o número de dias para limitar a importação de mensagens para o Chatwoot', + }, + { + displayName: 'Nome Do Contato De QRCode No Chatwoot', + name: 'chatwootOrganization', + type: 'string', + default: '', + description: 'Digite o nome do contato de QRCode no Chatwoot', + }, + { + displayName: 'Url Do Logo Para O Contato No Chatwoot', + name: 'chatwootLogo', + type: 'string', + default: + 'https://github.com/user-attachments/assets/4d1e9cd6-377a-4383-820a-9a97e6cfbb63', + description: 'Digite a URL do logo para o contato no Chatwoot', + }, + ], + }, + ], + description: 'Configurações do Chatwoot', + }, + ], + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-basic'], + }, + }, + }, + + // Campos = Conectar Instância + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que deseja pesquisar', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-connect'], + }, + }, + }, + + // Campos = Buscar Instancia + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: false, + description: 'Digite o nome da instância que deseja pesquisar', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['fetch-instances'], + }, + }, + }, + + // Campos = Definir Comportamento + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome para a instância', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-settings'], + }, + }, + }, + { + displayName: 'Rejeitar Chamadas', + name: 'rejectCall', + type: 'boolean', + default: false, + description: 'Whether to reject calls or not.', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-settings'], + }, + }, + }, + { + displayName: 'Mensagem de Chamadas', + name: 'msgCall', + type: 'string', + default: 'Não aceitamos ligações telefônicas.', + required: false, + description: 'Mensagem a ser enviada se as chamadas forem rejeitadas.', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-settings'], + }, + }, + }, + { + displayName: 'Ignorar Grupos', + name: 'groupsIgnore', + type: 'boolean', + default: false, + description: 'Whether to mention them all', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-settings'], + }, + }, + }, + { + displayName: 'Sempre Online', + name: 'alwaysOnline', + type: 'boolean', + default: false, + description: 'Whether the instance should always be online or not.', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-settings'], + }, + }, + }, + { + displayName: 'Ler Mensagens', + name: 'readMessages', + type: 'boolean', + default: false, + description: 'Whether to mention them all', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-settings'], + }, + }, + }, + { + displayName: 'Sincronizar Histórico Completo', + name: 'syncFullHistory', + type: 'boolean', + default: false, + description: 'Whether to mention them all history or not.', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-settings'], + }, + }, + }, + { + displayName: 'Ler Status', + name: 'readStatus', + type: 'boolean', + default: false, + description: 'Whether to mention them all', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['instance-settings'], + }, + }, + }, + + // Campos = Definir presença + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['set-presence'], + }, + }, + }, + { + displayName: 'Presença', + name: 'presence', + type: 'options', + options: [ + { + name: 'Disponível', + value: 'available', + }, + { + name: 'Indisponível', + value: 'unavailable', + }, + ], + default: 'available', + required: true, + description: 'Status de presença da instância', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['set-presence'], + }, + }, + }, + + // Campos = Proxy + { + displayName: 'Nome da Instancia', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar a mensagem', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['set-proxy'], + }, + }, + }, + + { + displayName: 'O que deseja fazer', + name: 'resourceForProxy', + type: 'options', + options: [ + { + name: 'Definir Proxy', + value: 'setProxy', + }, + { + name: 'Verificar proxy', + value: 'findProxy', + }, + ], + default: 'setProxy', + description: 'Escolha entre ativar/desativar proxy ou verificar o proxy', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['set-proxy'], + }, + }, + }, + { + displayName: 'Ativar proxy', + name: 'enabled', + type: 'boolean', + default: true, + description: 'Whether to enable or disable integration with proxy.', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['set-proxy'], + resourceForProxy: ['setProxy'], + }, + }, + }, + { + displayName: 'Protocolo Do Proxy', + name: 'proxyProtocol', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['set-proxy'], + resourceForProxy: ['setProxy'], + }, + }, + type: 'options', + options: [ + { + name: 'HTTP', + value: 'http', + }, + { + name: 'HTTPS', + value: 'https', + }, + ], + default: 'http', + description: 'Selecione o protocolo do proxy', + }, + { + displayName: 'Host Do Proxy', + name: 'proxyHost', + type: 'string', + default: '', + required: true, + description: 'Digite o host do proxy', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['set-proxy'], + resourceForProxy: ['setProxy'], + }, + }, + }, + { + displayName: 'Porta Do Proxy', + name: 'proxyPort', + type: 'string', + default: '1234', + required: true, + description: 'Digite a porta do proxy', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['set-proxy'], + resourceForProxy: ['setProxy'], + }, + }, + }, + { + displayName: 'Usuário Do Proxy', + name: 'proxyUsername', + type: 'string', + default: '', + required: true, + description: 'Digite o usuário do proxy', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['set-proxy'], + resourceForProxy: ['setProxy'], + }, + }, + }, + { + displayName: 'Senha Do Proxy', + name: 'proxyPassword', + type: 'string', + required: true, + typeOptions: { + password: true, + }, + default: '', + description: 'Digite a senha do proxy', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['set-proxy'], + resourceForProxy: ['setProxy'], + }, + }, + }, + + // Campos = Reiniciar instancia + { + displayName: 'Nome da Insticância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que deseja pesquisar', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['restart-instance'], + }, + }, + }, + + // Campos = Desconectar instancia + { + displayName: 'Nome da Insticância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que deseja pesquisar', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['logout-instance'], + }, + }, + }, + + // Campos = Deletar instancia + { + displayName: 'Nome da Instancia', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai ser deletada', + displayOptions: { + show: { + resource: ['instances-api'], + operation: ['delete-instance'], + }, + }, + }, +]; diff --git a/nodes/EvolutionApi/properties/instances.operations.ts b/nodes/EvolutionApi/properties/instances.operations.ts new file mode 100644 index 0000000..cefd8db --- /dev/null +++ b/nodes/EvolutionApi/properties/instances.operations.ts @@ -0,0 +1,99 @@ +import { INodeProperties } from 'n8n-workflow'; + +// Opções da instances-api (Instancias) +export const instancesOperationsOptions: INodeProperties = { + displayName: 'Função', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { + show: { + resource: ['instances-api'], // Value do Resource + }, + }, + + // Opções que serão vinculadas a Operação "Instancia" + options: [ + // Opção = Criar instancia + { + // Create Instance Basic + name: 'Criar Instancia', + action: 'Criar Instancia', + description: 'Cria uma nova Instancia', + value: 'instance-basic', + }, + + // Opção = Conectar Instância + { + // Instance Connect + name: 'Conectar Instancia', + action: 'Conectar Instancia', + description: 'Gera a conexão de uma Instancia (QR ou Base64)', + value: 'instance-connect', + }, + + // Opção = Buscar Instancia + { + // Fetch Instances + name: 'Buscar Instancia', + action: 'Buscar Instancia', + description: 'Busca e lista as Instancias criadas', + value: 'fetch-instances', + }, + + // Opção = Definir Comportamento da instancia + { + name: 'Definir Comportamento', + action: 'Definir Comportamento', + description: 'Define o comportamento da instancia', + value: 'instance-settings', + }, + + // Opção = Definir presença + { + // Set Presence + name: 'Definir Presença', + action: 'Definir Presença', + description: 'Define a presença na instancia', + value: 'set-presence', + }, + + // Opção = Definit Proxy + { + // Set/find Proxy + name: 'Definir/Buscar Proxy', + action: 'Proxy', + description: 'Define um Proxy na instancia', + value: 'set-proxy', + }, + + // Opção = Reiniciar instancia + { + // Restart Instance + name: 'Reiniciar Instancia', + action: 'Reiniciar Instancia', + description: 'Reinicia o socket da Instancia', + value: 'restart-instance', + }, + + // Opção = Desconectar instancia + { + // Logout Instance + name: 'Desconectar Instancia', + action: 'Desconectar Instancia', + description: 'Desconecta o WhatsApp da Instancia', + value: 'logout-instance', + }, + + // Opção = Deletar instancia + { + // Delete Instance + name: 'Deletar Instancia', + action: 'Deletar Instancia', + description: 'Deleta uma Instancia', + value: 'delete-instance', + }, + ], + // Definindo como padrão a opção "Criar Instancia" + default: 'instance-basic', +}; diff --git a/nodes/EvolutionApi/properties/integrations.fields.ts b/nodes/EvolutionApi/properties/integrations.fields.ts new file mode 100644 index 0000000..802a027 --- /dev/null +++ b/nodes/EvolutionApi/properties/integrations.fields.ts @@ -0,0 +1,1813 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const integrationsFields: INodeProperties[] = [ + // Campos = Chatwoot + { + displayName: 'Nome da Instancia', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar a mensagem', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + }, + }, + }, + { + displayName: 'O que deseja fazer', + name: 'resourceForChatwoot', + type: 'options', + options: [ + { + name: 'Definir Chatwoot', + value: 'setChatwoot', + }, + { + name: 'Verificar Chatwoot', + value: 'findChatwoot', + }, + ], + default: 'setChatwoot', + description: 'Escolha entre ativar/desativar Chatwoot ou verificar o Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + }, + }, + }, + { + displayName: 'Ativar Chatwoot', + name: 'enabled', + type: 'boolean', + default: true, + description: 'Whether to enable or disable integration with Chatwoot.', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Link Do Chatwoot', + name: 'chatwootUrl', + type: 'string', + default: '', + required: true, + description: 'Digite o link do Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'ID Da Conta Do Chatwoot', + name: 'chatwootAccountId', + type: 'string', + default: '', + required: true, + description: 'Digite o ID da conta do Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Token De Admin Do Chatwoot', + name: 'chatwootToken', + type: 'string', + required: true, + typeOptions: { + password: true, + }, + default: '', + description: 'Digite o token de admin do Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Assinatura Do Agente Do Chatwoot', + name: 'chatwootSignMsg', + type: 'boolean', + default: false, + description: 'Whether to enable or disable the Chatwoot agent signature', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Reabrir Mensagens No Chatwoot', + name: 'chatwootReopenConversation', + type: 'boolean', + default: false, + description: 'Whether to enable or disable reopening messages in Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Iniciar Conversas Como Pendentes No Chatwoot', + name: 'chatwootConversationPending', + type: 'boolean', + default: false, + description: 'Whether to start conversations as pending in Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Importar Contatos Para O Chatwoot', + name: 'chatwootImportContacts', + type: 'boolean', + default: false, + description: 'Whether to import contacts to Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Nome Da Inbox Do Chatwoot', + name: 'chatwootNameInbox', + type: 'string', + default: '', + description: 'Opicional: Digite o nome da Inbox do Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Mesclar Contatos Brasileiros No Chatwoot', + name: 'chatwootMergeBrazilContacts', + type: 'boolean', + default: false, + description: 'Whether to merge Brazilian contacts in Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Importar Mensagens Para O Chatwoot', + name: 'chatwootImportMessages', + type: 'boolean', + default: false, + description: 'Whether to import messages to Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Importar Mensagens De Quantos Dias Para O Chatwoot', + name: 'chatwootDaysLimitImportMessages', + type: 'number', + default: 0, + description: + 'Opicional: Digite o número de dias para limitar a importação de mensagens para o Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Criar Caixa De Entrada', + name: 'chatwootAutoCreate', + type: 'boolean', + default: true, + description: 'Whether to create an inbox automatically', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Nome Do Contato De QRCode No Chatwoot', + name: 'chatwootOrganization', + type: 'string', + default: '', + description: 'Opicional: Digite o nome do contato de QRCode no Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + { + displayName: 'Url Do Logo Para O Contato No Chatwoot', + name: 'chatwootLogo', + type: 'string', + default: 'https://github.com/user-attachments/assets/4d1e9cd6-377a-4383-820a-9a97e6cfbb63', + description: 'Opicional: Digite a URL do logo para o contato no Chatwoot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['chatwoot'], + resourceForChatwoot: ['setChatwoot'], + }, + }, + }, + + // Campos = Typebot + { + displayName: 'Nome da Instancia', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar a mensagem', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + }, + }, + }, + + { + displayName: 'O Que Deseja Fazer', + name: 'resourceForTypebot', + type: 'options', + options: [ + { + name: 'Adicionar Typebot', + value: 'createTypebot', + }, + { + name: 'Verificar Typebot', + value: 'findTypebot', + }, + { + name: 'Atualizar Typebot', + value: 'updateTypebot', + }, + { + name: 'Deletar Typebot', + value: 'deleteTypebot', + }, + { + name: 'Iniciar Typebot', + value: 'startTypebot', + }, + { + name: 'Procurar Sessão No Typebot', + value: 'fetchSessionsTypebot', + }, + { + name: 'Alterar Status Da Sessão No Typebot', + value: 'changeStatusTypebot', + }, + ], + default: 'createTypebot', + description: 'Escolha uma opção para realizar com a integração do Typebot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + }, + }, + }, + + // updateTypebot + { + displayName: 'Id do Typebot', + name: 'typebotId', + type: 'string', + default: '', + required: false, + description: 'Digite o ID do Typebot que deseja buscar, deixe vazio para procurar todos', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: [ + 'updateTypebot', + 'findTypebot', + 'deleteTypebot', + 'fetchSessionsTypebot', + 'changeStatusTypebot', + ], + }, + }, + }, + + //Se createTypebot ou updateTypebot + { + displayName: 'URL Da API Do Typebot', + name: 'url', + type: 'string', + default: '', + required: true, + description: 'Digite a URL do seu typebot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot', 'startTypebot'], + }, + }, + }, + { + displayName: 'Nome Do Typebot', + name: 'typebot', + type: 'string', + default: '', + required: true, + description: 'Digite o nome do seu fluxo no typebot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot', 'startTypebot'], + }, + }, + }, + { + displayName: 'Tipo De Gatilho', + name: 'triggerType', + type: 'options', + options: [ + { + name: 'Palavra Chave', + value: 'keyword', + }, + { + name: 'Todos', + value: 'all', + }, + ], + default: 'keyword', + description: 'Escolha uma opção para realizar com a integração do Typebot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot'], + }, + }, + }, + { + displayName: 'Operador Do Gatilho', + name: 'triggerOperator', + type: 'options', + options: [ + { + name: 'Contem', + value: 'contains', + }, + { + name: 'Igual à', + value: 'equals', + }, + { + name: 'Começa com', + value: 'startsWith', + }, + { + name: 'Termina com', + value: 'endsWith', + }, + { + name: 'Regex', + value: 'regex', + }, + ], + default: 'contains', + description: 'Escolha uma opção para realizar com a integração do Typebot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot'], + triggerType: ['keyword'], + }, + }, + }, + { + displayName: 'Gatilho', + name: 'triggerValue', + type: 'string', + default: '', + required: true, + description: + 'Digite a palavra/frase ou regex para ser usado como gatilho para iniciar o Typebot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot'], + triggerType: ['keyword'], + }, + }, + }, + { + displayName: 'Expira Em (Minutos)', + name: 'expire', + type: 'number', + default: 0, + required: true, + description: 'Digite quantos minutos sem respostas o bot devera ser desativado', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot'], + }, + }, + }, + { + displayName: 'Palavra Chave de Finalização', + name: 'keywordFinish', + type: 'string', + default: '#sair', + required: true, + description: 'Digite a palavra/frase que sera usado para fechar o bot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot'], + }, + }, + }, + { + displayName: 'Delay Padrão Da Mensagem (Em Milésimos)', + name: 'delayMessage', + type: 'number', + default: 1000, + required: true, + description: 'Digite quantos milisegundos o bot terá de delay', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot'], + }, + }, + }, + { + displayName: 'Palavra Chave de Finalização', + name: 'unknownMessage', + type: 'string', + default: 'Mensagem não reconhecida', + required: true, + description: 'Digite a palavra/frase que sera usado para fechar o bot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot'], + }, + }, + }, + { + displayName: 'Escuta mensagens enviadas por mim', + name: 'listeningFromMe', + type: 'boolean', + default: false, + description: 'Whether...', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot'], + }, + }, + }, + { + displayName: 'Pausa o bot quando eu enviar uma mensagem', + name: 'stopBotFromMe', + type: 'boolean', + default: false, + description: 'Whether...', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot'], + }, + }, + }, + { + displayName: 'Mantem a sessão do bot aberta', + name: 'keepOpen', + type: 'boolean', + default: false, + description: 'Whether...', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot'], + }, + }, + }, + { + displayName: 'Tempo de Espera (Em Segundos)', + name: 'debounceTime', + type: 'number', + default: 0, + required: true, + description: + 'Este é o tempo que o bot ficará esperando as proximas mensagens após receber uma mensagem, depois ele juntará todas as mensagens em uma só', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['createTypebot', 'updateTypebot'], + }, + }, + }, + + // startTypebot + { + displayName: 'Numero Do Destinatario', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'RemoteJid do destinarario', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['startTypebot', 'changeStatusTypebot'], + }, + }, + }, + { + displayName: 'Iniciar Seção', + name: 'startSession', + type: 'boolean', + default: false, + description: 'Se deve iniciar uma nova sessão', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['startTypebot'], + }, + }, + }, + { + displayName: 'Variáveis', + name: 'variables', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + options: [ + { + name: 'variable', + displayName: 'Variável', + values: [ + { + displayName: 'Nome Da Variavel', + name: 'name', + type: 'string', + default: '', + description: 'Nome da variável', + }, + { + displayName: 'Valor Da Variavel', + name: 'value', + type: 'string', + default: '', + description: 'Valor da variável', + }, + ], + }, + ], + description: 'Variáveis para enviar ao typebot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['startTypebot'], + }, + }, + }, + + // Change Session Status + { + displayName: 'Status', + name: 'status', + type: 'options', + options: [ + { + name: 'Aberta', + value: 'opened', + }, + { + name: 'Pausada', + value: 'paused', + }, + { + name: 'Fechada', + value: 'closed', + }, + ], + default: 'opened', + description: 'Escolha qual será o status da seção', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['typebot'], + resourceForTypebot: ['changeStatusTypebot'], + }, + }, + }, + + // EVOLUTION BOT + { + displayName: 'Nome Da Instancia', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar a mensagem', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + }, + }, + }, + + { + displayName: 'O Que Deseja Fazer', + name: 'resourceForEvolutionBot', + type: 'options', + options: [ + { + name: 'Adicionar Evolution Bot', + value: 'createEvolutionBot', + }, + { + name: 'Verificar Evolution Bot', + value: 'findEvolutionBot', + }, + { + name: 'Atualizar Evolution Bot', + value: 'updateEvolutionBot', + }, + { + name: 'Deletar Evolution Bot', + value: 'deleteEvolutionBot', + }, + { + name: 'Procurar Sessão No Evolution Bot', + value: 'fetchSessionsEvolutionBot', + }, + { + name: 'Alterar Status Da Sessão No Evolution Bot', + value: 'changeStatusEvolutionBot', + }, + ], + default: 'createEvolutionBot', + description: 'Escolha uma opção para realizar com a integração do EvolutionBot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + }, + }, + }, + + // update EvolutionBot + { + displayName: 'Id do Evolution Bot', + name: 'evolutionBotId', + type: 'string', + default: '', + required: false, + description: 'Digite o ID do Evolution Bot que deseja buscar, deixe vazio para procurar todos', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: [ + 'findEvolutionBot', + 'updateEvolutionBot', + 'deleteEvolutionBot', + 'fetchSessionsEvolutionBot', + 'changeStatusEvolutionBot', + ], + }, + }, + }, + + //Se createEvolutionBot ou updateEvolutionBot + { + displayName: 'URL Da API Do Evolution Bot', + name: 'apiUrl', + type: 'string', + default: '', + required: true, + description: 'Digite a URL do seu Evolution Bot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + }, + { + displayName: 'ApiKey da Evolution Bot', + name: 'apiKeyBot', + type: 'string', + default: '', + required: false, + description: 'Digite a ApiKey do seu Evolution Bot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + }, + { + displayName: 'Tipo De Gatilho', + name: 'triggerType', + type: 'options', + options: [ + { + name: 'Palavra Chave', + value: 'keyword', + }, + { + name: 'Todos', + value: 'all', + }, + ], + default: 'keyword', + description: 'Escolha uma opção para realizar com a integração do EvolutionBot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + }, + { + displayName: 'Operador Do Gatilho', + name: 'triggerOperator', + type: 'options', + options: [ + { + name: 'Contem', + value: 'contains', + }, + { + name: 'Igual à', + value: 'equals', + }, + { + name: 'Começa com', + value: 'startsWith', + }, + { + name: 'Termina com', + value: 'endsWith', + }, + { + name: 'Regex', + value: 'regex', + }, + ], + default: 'contains', + description: 'Escolha uma opção para realizar com a integração do EvolutionBot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + triggerType: ['keyword'], + }, + }, + }, + { + displayName: 'Gatilho', + name: 'triggerValue', + type: 'string', + default: '', + required: true, + description: + 'Digite a palavra/frase ou regex para ser usado como gatilho para iniciar o EvolutionBot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + triggerType: ['keyword'], + }, + }, + }, + { + displayName: 'Expira Em (Minutos)', + name: 'expire', + type: 'number', + default: 0, + required: true, + description: 'Digite quantos minutos sem respostas o bot devera ser desativado', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + }, + { + displayName: 'Palavra Chave de Finalização', + name: 'keywordFinish', + type: 'string', + default: '#sair', + required: true, + description: 'Digite a palavra/frase que sera usado para fechar o bot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + }, + { + displayName: 'Delay Padrão Da Mensagem (Em Milésimos)', + name: 'delayMessage', + type: 'number', + default: 1000, + required: true, + description: 'Digite quantos milisegundos o bot terá de delay', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + }, + { + displayName: 'Palavra Chave de Finalização', + name: 'unknownMessage', + type: 'string', + default: 'Mensagem não reconhecida', + required: true, + description: 'Digite a palavra/frase que sera usado para fechar o bot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + }, + { + displayName: 'Escuta mensagens enviadas por mim', + name: 'listeningFromMe', + type: 'boolean', + default: false, + description: 'Whether...', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + }, + { + displayName: 'Pausa o bot quando eu enviar uma mensagem', + name: 'stopBotFromMe', + type: 'boolean', + default: false, + description: 'Whether...', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + }, + { + displayName: 'Mantem a sessão do bot aberta', + name: 'keepOpen', + type: 'boolean', + default: false, + description: 'Whether...', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + }, + { + displayName: 'Tempo de Espera (Em Segundos)', + name: 'debounceTime', + type: 'number', + default: 0, + required: true, + description: + 'Este é o tempo que o bot ficará esperando as proximas mensagens após receber uma mensagem, depois ele juntará todas as mensagens em uma só', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + }, + + // Change Session Status EvolutionBot + { + displayName: 'Numero Do Destinatario', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'RemoteJid do destinarario', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['changeStatusEvolutionBot'], + }, + }, + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + options: [ + { + name: 'Aberta', + value: 'opened', + }, + { + name: 'Pausada', + value: 'paused', + }, + { + name: 'Fechada', + value: 'closed', + }, + ], + default: 'opened', + description: 'Escolha qual será o status da seção', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['changeStatusEvolutionBot'], + }, + }, + }, + + // Dify + { + displayName: 'Nome da Instancia', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar a mensagem', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + }, + }, + }, + { + displayName: 'O Que Deseja Fazer', + name: 'resourceForDifyBot', + type: 'options', + options: [ + { + name: 'Adicionar Dify', + value: 'createDify', + }, + { + name: 'Verificar Dify', + value: 'findDify', + }, + { + name: 'Atualizar Dify', + value: 'updateDify', + }, + { + name: 'Deletar Dify', + value: 'deleteDify', + }, + { + name: 'Procurar Sessão No Dify', + value: 'fetchSessionsDify', + }, + { + name: 'Alterar Status Da Sessão No Dify', + value: 'changeStatusDify', + }, + ], + default: 'createDify', + description: 'Escolha uma opção para realizar com a integração do Dify', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + }, + }, + }, + { + displayName: 'Tipo do Bot', + name: 'botType', + type: 'options', + options: [ + { + name: 'Bot de Chat', + value: 'chatBot', + }, + { + name: 'Gerador de Texto', + value: 'textGenerator', + }, + { + name: 'Agente', + value: 'agent', + }, + { + name: 'Fluxo de Trabalho', + value: 'workflow', + }, + ], + default: 'chatBot', + required: true, + description: 'Escolha o tipo do bot Dify', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['dify'], + resourceForDifyBot: ['createDify'], + }, + }, + }, + + // update Dify + { + displayName: 'Id do Dify', + name: 'difyBotId', + type: 'string', + default: '', + required: false, + description: 'Digite o ID do Dify que deseja buscar, deixe vazio para procurar todos', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: [ + 'findDify', + 'updateDify', + 'deleteDify', + 'fetchSessionsDify', + 'changeStatusDify', + ], + }, + }, + }, + + //Se createDify ou updateDify + { + displayName: 'Url do Dify', + name: 'apiUrl', + type: 'string', + default: '', + required: true, + description: 'Digite a URL do seu Dify', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + }, + }, + }, + { + displayName: 'ApiKey do Dify', + name: 'apiKeyBot', + type: 'string', + default: '', + required: true, + description: 'Digite a ApiKey do seu bot do Dify', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + }, + }, + }, + { + displayName: 'Tipo De Gatilho', + name: 'triggerType', + type: 'options', + options: [ + { + name: 'Palavra Chave', + value: 'keyword', + }, + { + name: 'Todos', + value: 'all', + }, + ], + default: 'keyword', + description: 'Escolha uma opção para realizar com a integração do Dify', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + }, + }, + }, + { + displayName: 'Operador Do Gatilho', + name: 'triggerOperator', + type: 'options', + options: [ + { + name: 'Contem', + value: 'contains', + }, + { + name: 'Igual à', + value: 'equals', + }, + { + name: 'Começa com', + value: 'startsWith', + }, + { + name: 'Termina com', + value: 'endsWith', + }, + { + name: 'Regex', + value: 'regex', + }, + ], + default: 'contains', + description: 'Escolha uma opção para realizar com a integração do Dify', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + triggerType: ['keyword'], + }, + }, + }, + { + displayName: 'Gatilho', + name: 'triggerValue', + type: 'string', + default: '', + required: true, + description: 'Digite a palavra/frase ou regex para ser usado como gatilho para iniciar o Dify', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + triggerType: ['keyword'], + }, + }, + }, + { + displayName: 'Expira Em (Minutos)', + name: 'expire', + type: 'number', + default: 0, + required: true, + description: 'Digite quantos minutos sem respostas o bot devera ser desativado', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + }, + }, + }, + { + displayName: 'Palavra Chave de Finalização', + name: 'keywordFinish', + type: 'string', + default: '#sair', + required: true, + description: 'Digite a palavra/frase que sera usado para fechar o bot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + }, + }, + }, + { + displayName: 'Delay Padrão Da Mensagem (Em Milésimos)', + name: 'delayMessage', + type: 'number', + default: 1000, + required: true, + description: 'Digite quantos milisegundos o bot terá de delay', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + }, + }, + }, + { + displayName: 'Palavra Chave de Finalização', + name: 'unknownMessage', + type: 'string', + default: 'Mensagem não reconhecida', + required: true, + description: 'Digite a palavra/frase que sera usado para fechar o bot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + }, + }, + }, + { + displayName: 'Escuta mensagens enviadas por mim', + name: 'listeningFromMe', + type: 'boolean', + default: false, + description: 'Whether...', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + }, + }, + }, + { + displayName: 'Pausa o bot quando eu enviar uma mensagem', + name: 'stopBotFromMe', + type: 'boolean', + default: false, + description: 'Whether...', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + }, + }, + }, + { + displayName: 'Mantem a sessão do bot aberta', + name: 'keepOpen', + type: 'boolean', + default: false, + description: 'Whether...', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + }, + }, + }, + { + displayName: 'Tempo de Espera (Em Segundos)', + name: 'debounceTime', + type: 'number', + default: 0, + required: true, + description: + 'Este é o tempo que o bot ficará esperando as proximas mensagens após receber uma mensagem, depois ele juntará todas as mensagens em uma só', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['createDify', 'updateDify'], + }, + }, + }, + + // Change Session Status Dify + { + displayName: 'Numero Do Destinatario', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'RemoteJid do destinarario', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['changeStatusDify'], + }, + }, + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + options: [ + { + name: 'Aberta', + value: 'opened', + }, + { + name: 'Pausada', + value: 'paused', + }, + { + name: 'Fechada', + value: 'closed', + }, + ], + default: 'opened', + description: 'Escolha qual será o status da seção', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['difyBot'], + resourceForDifyBot: ['changeStatusDify'], + }, + }, + }, + + { + displayName: 'Nome da Instancia', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar a mensagem', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + }, + }, + }, + { + displayName: 'O Que Deseja Fazer', + name: 'resourceForFlowiseBot', + type: 'options', + options: [ + { + name: 'Adicionar Flowise', + value: 'createFlowise', + }, + { + name: 'Verificar Flowise', + value: 'findFlowise', + }, + { + name: 'Atualizar Flowise', + value: 'updateFlowise', + }, + { + name: 'Deletar Flowise', + value: 'deleteFlowise', + }, + { + name: 'Procurar Sessão No Flowise', + value: 'fetchSessionsFlowise', + }, + { + name: 'Alterar Status Da Sessão No Flowise', + value: 'changeStatusFlowise', + }, + ], + default: 'createFlowise', + description: 'Escolha uma opção para realizar com a integração do Flowise', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + }, + }, + }, + + // update Flowise + { + displayName: 'Id do Flowise', + name: 'flowiseBotId', + type: 'string', + default: '', + required: false, + description: 'Digite o ID do Flowise que deseja buscar, deixe vazio para procurar todos', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: [ + 'updateFlowise', + 'findFlowise', + 'deleteFlowise', + 'fetchSessionsFlowise', + 'changeStatusFlowise', + ], + }, + }, + }, + + //Se createFlowise ou updateFlowise + { + displayName: 'Url do Flowise', + name: 'apiUrl', + type: 'string', + default: '', + required: true, + description: 'Digite a URL do seu Flowise', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + }, + }, + }, + { + displayName: 'ApiKey do Flowise', + name: 'apiKeyBot', + type: 'string', + default: '', + required: false, + description: 'Digite a ApiKey do seu bot do Flowise', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + }, + }, + }, + { + displayName: 'Tipo De Gatilho', + name: 'triggerType', + type: 'options', + options: [ + { + name: 'Palavra Chave', + value: 'keyword', + }, + { + name: 'Todos', + value: 'all', + }, + ], + default: 'keyword', + description: 'Escolha uma opção para realizar com a integração do Flowise', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + }, + }, + }, + { + displayName: 'Operador Do Gatilho', + name: 'triggerOperator', + type: 'options', + options: [ + { + name: 'Contem', + value: 'contains', + }, + { + name: 'Igual à', + value: 'equals', + }, + { + name: 'Começa com', + value: 'startsWith', + }, + { + name: 'Termina com', + value: 'endsWith', + }, + { + name: 'Regex', + value: 'regex', + }, + ], + default: 'contains', + description: 'Escolha uma opção para realizar com a integração do Flowise', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + triggerType: ['keyword'], + }, + }, + }, + { + displayName: 'Gatilho', + name: 'triggerValue', + type: 'string', + default: '', + required: true, + description: + 'Digite a palavra/frase ou regex para ser usado como gatilho para iniciar o Flowise', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + triggerType: ['keyword'], + }, + }, + }, + { + displayName: 'Expira Em (Minutos)', + name: 'expire', + type: 'number', + default: 0, + required: true, + description: 'Digite quantos minutos sem respostas o bot devera ser desativado', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + }, + }, + }, + { + displayName: 'Palavra Chave de Finalização', + name: 'keywordFinish', + type: 'string', + default: '#sair', + required: true, + description: 'Digite a palavra/frase que sera usado para fechar o bot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + }, + }, + }, + { + displayName: 'Delay Padrão Da Mensagem (Em Milésimos)', + name: 'delayMessage', + type: 'number', + default: 1000, + required: true, + description: 'Digite quantos milisegundos o bot terá de delay', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + }, + }, + }, + { + displayName: 'Palavra Chave de Finalização', + name: 'unknownMessage', + type: 'string', + default: 'Mensagem não reconhecida', + required: true, + description: 'Digite a palavra/frase que sera usado para fechar o bot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + }, + }, + }, + { + displayName: 'Escuta mensagens enviadas por mim', + name: 'listeningFromMe', + type: 'boolean', + default: false, + description: 'Whether...', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + }, + }, + }, + { + displayName: 'Pausa o bot quando eu enviar uma mensagem', + name: 'stopBotFromMe', + type: 'boolean', + default: false, + description: 'Whether...', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + }, + }, + }, + { + displayName: 'Mantem a sessão do bot aberta', + name: 'keepOpen', + type: 'boolean', + default: false, + description: 'Whether...', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + }, + }, + }, + { + displayName: 'Tempo de Espera (Em Segundos)', + name: 'debounceTime', + type: 'number', + default: 0, + required: true, + description: + 'Este é o tempo que o bot ficará esperando as proximas mensagens após receber uma mensagem, depois ele juntará todas as mensagens em uma só', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], + }, + }, + }, + + // Change Session Status Flowise + { + displayName: 'Numero Do Destinatario', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'RemoteJid do destinarario', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['changeStatusFlowise'], + }, + }, + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + options: [ + { + name: 'Aberta', + value: 'opened', + }, + { + name: 'Pausada', + value: 'paused', + }, + { + name: 'Fechada', + value: 'closed', + }, + ], + default: 'opened', + description: 'Escolha qual será o status da seção', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['flowiseBot'], + resourceForFlowiseBot: ['changeStatusFlowise'], + }, + }, + }, + + { + displayName: 'JIDs Ignorados', + name: 'ignoreJids', + type: 'string', + typeOptions: { + multipleValues: true, + }, + default: [], + description: 'Lista de JIDs que serão ignorados pelo bot', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + }, + { + displayName: 'Tipo do Operador', + name: 'triggerOperator', + type: 'options', + options: [ + { + name: 'Contém', + value: 'contains', + }, + { + name: 'Igual', + value: 'equals', + }, + { + name: 'Começa Com', + value: 'startsWith', + }, + { + name: 'Termina Com', + value: 'endsWith', + }, + { + name: 'Regex', + value: 'regex', + }, + { + name: 'Nenhum', + value: 'none', + }, + ], + default: 'equals', + description: 'Escolha o tipo de operador para o gatilho', + displayOptions: { + show: { + resource: ['integrations-api'], + operation: ['evolution-bot'], + resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], + }, + }, + } +]; diff --git a/nodes/EvolutionApi/properties/integrations.operations.ts b/nodes/EvolutionApi/properties/integrations.operations.ts new file mode 100644 index 0000000..2a01da9 --- /dev/null +++ b/nodes/EvolutionApi/properties/integrations.operations.ts @@ -0,0 +1,53 @@ +import { INodeProperties } from 'n8n-workflow'; + +// Opções da integrations-api (Integração) +export const integrationsOperationsOptions: INodeProperties = { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { + show: { + resource: ['integrations-api'], // Value do Resource + }, + }, + options: [ + { + // Set/find Chatwoot + name: 'Chatwoot', + action: 'Chatwoot', + description: 'Define/Busca integração com Chatwoot', + value: 'chatwoot', + }, + { + // Create/find/fetch/Update/Delete/Start/Change Status/Fetch Sessions da Evolution Bot + name: 'Evolution Bot', + action: 'Evolution bot', + description: 'Controla a integração com Evolution Bot', + value: 'evolution-bot', + }, + { + // Create/find/fetch/Update/Delete/Start/Change Status/Fetch Sessions do Typebot + name: 'Typebot', + action: 'Typebot', + description: 'Controla a integração com Typebot', + value: 'typebot', + }, + { + // Create/find/fetch/Update/Delete/Start/Change Status/Fetch Sessions da Dify + name: 'Dify', + action: 'Dify', + description: 'Controla a integração com Dify', + value: 'difyBot', + }, + { + // Create/find/fetch/Update/Delete/Start/Change Status/Fetch Sessions da Dify + name: 'Flowise', + action: 'Flowise', + description: 'Controla a integração com Flowise', + value: 'flowiseBot', + }, + ], + // Definindo como padrão a opção "Enviar Texto" + default: 'chatwoot', +}; diff --git a/nodes/EvolutionApi/properties/messages.fields.ts b/nodes/EvolutionApi/properties/messages.fields.ts new file mode 100644 index 0000000..a0387ac --- /dev/null +++ b/nodes/EvolutionApi/properties/messages.fields.ts @@ -0,0 +1,1921 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const messagesFields: INodeProperties[] = [ + // Campos = Enviar mensagem de texto + { + displayName: 'Nome da Instancia', + name: 'instanceName', + type: 'string', + default: '', + required: false, + description: 'Digite o nome da instância que vai enviar a mensagem', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-text'], + }, + }, + }, + { + displayName: 'Numero do destinatario', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'remoteJid do destinarario', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-text'], + }, + }, + }, + { + displayName: 'Mensagem', + name: 'messageText', + type: 'string', + default: '', + required: true, + description: 'Digite a mensagem de texto que será enviado', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-text'], + }, + }, + }, + { + displayName: 'Opções', + name: 'options_message', + type: 'collection', + placeholder: 'Adicionar Campo', + default: {}, + options: [ + { + displayName: 'Delay', + name: 'delay', + type: 'number', + default: 1200, + description: 'Digite quantos milisegundos de delay a mensagem terá antes de ser enviada', + }, + { + displayName: 'Responder Mensagem', + name: 'quoted', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + messageQuoted: { + messageId: '', + }, + }, + options: [ + { + name: 'messageQuoted', + displayName: 'Mensagem', + values: [ + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string', + default: '', + description: 'ID da mensagem que será respondida', + }, + ], + }, + ], + }, + { + displayName: 'Menções', + name: 'mentions', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + mentionsSettings: { + mentionsEveryOne: false, + mentioned: '', + }, + }, + options: [ + { + name: 'mentionsSettings', + displayName: 'Configurações', + values: [ + { + displayName: 'Mencionar Todos', + name: 'mentionsEveryOne', + type: 'boolean', + default: false, + description: 'Menciona todos os participantes do grupo', + }, + { + displayName: 'Números para Mencionar', + name: 'mentioned', + type: 'string', + default: '', + displayOptions: { + show: { + mentionsEveryOne: [false], + }, + }, + description: 'Lista de números para mencionar (separados por vírgula)', + }, + ], + }, + ], + }, + { + displayName: 'Preview de Link', + name: 'linkPreview', + type: 'boolean', + default: true, + description: 'Habilita ou desabilita a prévia de links na mensagem', + }, + ], + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-text'], + }, + }, + }, + + // Campos = Enviar Imagem + { + displayName: 'Nome da Instancia', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar a mensagem', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-image'], + }, + }, + }, + { + displayName: 'Número do Destinatário', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'Número do destinatário', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-image'], + }, + }, + }, + { + displayName: 'Imagem', + name: 'media', + type: 'string', + default: '', + required: true, + description: 'URL ou base64 da imagem', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-image'], + }, + }, + }, + { + displayName: 'Caption', + name: 'caption', + type: 'string', + default: '', + required: false, + description: 'Texto a ser enviado junto a imagem', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-image'], + }, + }, + }, + { + displayName: 'Opções', + name: 'options_message', + type: 'collection', + placeholder: 'Adicionar Campo', + default: {}, + options: [ + { + displayName: 'Delay', + name: 'delay', + type: 'number', + default: 1200, + description: 'Digite quantos milisegundos de delay a mensagem terá antes de ser enviada', + }, + { + displayName: 'Responder Mensagem', + name: 'quoted', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + messageQuoted: { + messageId: '', + }, + }, + options: [ + { + name: 'messageQuoted', + displayName: 'Mensagem', + values: [ + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string', + default: '', + description: 'ID da mensagem que será respondida', + }, + ], + }, + ], + }, + { + displayName: 'Menções', + name: 'mentions', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + mentionsSettings: { + mentionsEveryOne: false, + mentioned: '', + }, + }, + options: [ + { + name: 'mentionsSettings', + displayName: 'Configurações', + values: [ + { + displayName: 'Mencionar Todos', + name: 'mentionsEveryOne', + type: 'boolean', + default: false, + description: 'Menciona todos os participantes do grupo', + }, + { + displayName: 'Números para Mencionar', + name: 'mentioned', + type: 'string', + default: '', + displayOptions: { + show: { + mentionsEveryOne: [false], + }, + }, + description: 'Lista de números para mencionar (separados por vírgula)', + }, + ], + }, + ], + }, + ], + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-image'], + }, + }, + }, + + // Campos = Enviar Video + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar o vídeo', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-video'], + }, + }, + }, + { + displayName: 'Número do Destinatário', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'Número do destinatário', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-video'], + }, + }, + }, + { + displayName: 'Video', + name: 'media', + type: 'string', + default: '', + required: true, + description: 'URL ou base64 do vídeo', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-video'], + }, + }, + }, + { + displayName: 'Caption', + name: 'caption', + type: 'string', + default: '', + required: false, + description: 'Texto a ser enviado junto ao vídeo', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-video'], + }, + }, + }, + { + displayName: 'Opções', + name: 'options_message', + type: 'collection', + placeholder: 'Adicionar Campo', + default: {}, + options: [ + { + displayName: 'Delay', + name: 'delay', + type: 'number', + default: 1200, + description: 'Digite quantos milisegundos de delay a mensagem terá antes de ser enviada', + }, + { + displayName: 'Responder Mensagem', + name: 'quoted', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + messageQuoted: { + messageId: '', + }, + }, + options: [ + { + name: 'messageQuoted', + displayName: 'Mensagem', + values: [ + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string', + default: '', + description: 'ID da mensagem que será respondida', + }, + ], + }, + ], + }, + { + displayName: 'Menções', + name: 'mentions', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + mentionsSettings: { + mentionsEveryOne: false, + mentioned: '', + }, + }, + options: [ + { + name: 'mentionsSettings', + displayName: 'Configurações', + values: [ + { + displayName: 'Mencionar Todos', + name: 'mentionsEveryOne', + type: 'boolean', + default: false, + description: 'Menciona todos os participantes do grupo', + }, + { + displayName: 'Números para Mencionar', + name: 'mentioned', + type: 'string', + default: '', + displayOptions: { + show: { + mentionsEveryOne: [false], + }, + }, + description: 'Digite os números que deseja mencionar separados por vírgula (ex: 5511999999999,5511888888888)', + }, + ], + }, + ], + }, + ], + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-video'], + }, + }, + }, + + // Campos = Enviar Audio + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar o áudio', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-audio'], + }, + }, + }, + { + displayName: 'Número do Destinatário', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'Número do destinatário', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-audio'], + }, + }, + }, + { + displayName: 'Audio', + name: 'media', + type: 'string', + default: '', + required: true, + description: 'URL ou base64 do áudio', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-audio'], + }, + }, + }, + { + displayName: 'Opções', + name: 'options_message', + type: 'collection', + placeholder: 'Adicionar Campo', + default: {}, + options: [ + { + displayName: 'Delay', + name: 'delay', + type: 'number', + default: 1200, + description: 'Digite quantos milisegundos de delay a mensagem terá antes de ser enviada', + }, + //{ + // displayName: 'Responder Mensagem', + // name: 'quoted', + // type: 'fixedCollection', + // typeOptions: { + // multipleValues: false, + // }, + // default: { + // messageQuoted: { + // messageId: '', + // }, + // }, + // options: [ + // { + // name: 'messageQuoted', + // displayName: 'Mensagem', + // values: [ + // { + // displayName: 'ID da Mensagem', + // name: 'messageId', + // type: 'string', + // default: '', + // description: 'ID da mensagem que será respondida', + // }, + // ], + // }, + // ], + //}, + + //{ + // displayName: 'Menções', + // name: 'mentions', + // type: 'fixedCollection', + // typeOptions: { + // multipleValues: false, + // }, + // default: { + // mentionsSettings: { + // mentionsEveryOne: false, + // mentioned: '', + // }, + // }, + // options: [ + // { + // name: 'mentionsSettings', + // displayName: 'Configurações', + // values: [ + // { + // displayName: 'Mencionar Todos', + // name: 'mentionsEveryOne', + // type: 'boolean', + // default: false, + // description: 'Menciona todos os participantes do grupo', + // }, + // { + // displayName: 'Números para Mencionar', + // name: 'mentioned', + // type: 'string', + // default: '', + // displayOptions: { + // show: { + // mentionsEveryOne: [false], + // }, + // }, + // description: 'Digite os números que deseja mencionar separados por vírgula (ex: 5511999999999,5511888888888)', + // }, + // ], + // }, + // ], + //}, + ], + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-audio'], + }, + }, + }, + + // Campos = Enviar Documento + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar o documento', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-document'], + }, + }, + }, + { + displayName: 'Número do Destinatário', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'Número do destinatário', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-document'], + }, + }, + }, + { + displayName: 'Documento', + name: 'media', + type: 'string', + default: '', + required: true, + description: 'URL ou base64 do documento', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-document'], + }, + }, + }, + { + displayName: 'Mensagem', + name: 'caption', + type: 'string', + default: '', + required: false, + description: 'Texto a ser enviado junto ao documento', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-document'], + }, + }, + }, + { + displayName: 'Nome do Arquivo', + name: 'fileName', + type: 'string', + default: 'document.pdf', + required: false, + description: 'Nome do arquivo do documento', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-document'], + }, + }, + }, + { + displayName: 'Opções', + name: 'options_message', + type: 'collection', + placeholder: 'Adicionar Campo', + default: {}, + options: [ + { + displayName: 'Delay', + name: 'delay', + type: 'number', + default: 1200, + description: 'Digite quantos milisegundos de delay a mensagem terá antes de ser enviada', + }, + { + displayName: 'Responder Mensagem', + name: 'quoted', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + messageQuoted: { + messageId: '', + }, + }, + options: [ + { + name: 'messageQuoted', + displayName: 'Mensagem', + values: [ + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string', + default: '', + description: 'ID da mensagem que será respondida', + }, + ], + }, + ], + }, + { + displayName: 'Menções', + name: 'mentions', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + mentionsSettings: { + mentionsEveryOne: false, + mentioned: '', + }, + }, + options: [ + { + name: 'mentionsSettings', + displayName: 'Configurações', + values: [ + { + displayName: 'Mencionar Todos', + name: 'mentionsEveryOne', + type: 'boolean', + default: false, + description: 'Menciona todos os participantes do grupo', + }, + { + displayName: 'Números para Mencionar', + name: 'mentioned', + type: 'string', + default: '', + displayOptions: { + show: { + mentionsEveryOne: [false], + }, + }, + description: 'Digite os números que deseja mencionar separados por vírgula (ex: 5511999999999,5511888888888)', + }, + ], + }, + ], + }, + ], + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-document'], + }, + }, + }, + + // Campos = Enviar Enquete + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar a enquete', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-poll'], + }, + }, + }, + { + displayName: 'Número do Destinatário', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'Número do destinatário', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-poll'], + }, + }, + }, + { + displayName: 'Titulo da Enquete', + name: 'caption', + type: 'string', + default: '', + required: true, + description: 'Digite o titulo da sua enquete', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-poll'], + }, + }, + }, + { + displayName: 'Mínimo 2 opções, Máximo 12. Cada opção deve ser única.', + name: 'notice', + type: 'notice', + default: '', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-poll'], + }, + }, + }, + { + displayName: 'Opções da Enquete', + name: 'options_display', + type: 'fixedCollection', + default: { metadataValues: [] }, + required: true, + typeOptions: { + multipleValues: true, + }, + description: 'Digite as opções da enquete (mínimo 2, máximo 12). Cada opção deve ser única.', + options: [ + { + name: 'metadataValues', + displayName: 'Metadata', + values: [ + { + displayName: 'Opção', + name: 'optionValue', + type: 'string', + default: '', + }, + ], + }, + ], + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-poll'], + }, + }, + }, + { + displayName: 'Opções', + name: 'options_message', + type: 'collection', + placeholder: 'Adicionar Campo', + default: {}, + options: [ + { + displayName: 'Delay', + name: 'delay', + type: 'number', + default: 1200, + description: 'Digite quantos milisegundos de delay a mensagem terá antes de ser enviada', + }, + { + displayName: 'Responder Mensagem', + name: 'quoted', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + messageQuoted: { + messageId: '', + }, + }, + options: [ + { + name: 'messageQuoted', + displayName: 'Mensagem', + values: [ + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string', + default: '', + description: 'ID da mensagem que será respondida', + }, + ], + }, + ], + }, + { + displayName: 'Menções', + name: 'mentions', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + mentionsSettings: { + mentionsEveryOne: false, + mentioned: '', + }, + }, + options: [ + { + name: 'mentionsSettings', + displayName: 'Configurações', + values: [ + { + displayName: 'Mencionar Todos', + name: 'mentionsEveryOne', + type: 'boolean', + default: false, + description: 'Menciona todos os participantes do grupo', + }, + { + displayName: 'Números para Mencionar', + name: 'mentioned', + type: 'string', + default: '', + displayOptions: { + show: { + mentionsEveryOne: [false], + }, + }, + description: 'Digite os números que deseja mencionar separados por vírgula (ex: 5511999999999,5511888888888)', + }, + ], + }, + ], + }, + ], + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-list'], + }, + }, + }, + + // Campos = Enviar Status + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar o status', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-stories'], + }, + }, + }, + { + displayName: 'Tipo do status', + name: 'type', + type: 'options', + description: 'Escolha o tipo de status você vai postar', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-stories'], + }, + }, + options: [ + { + name: 'Status de Texto', + value: 'text', + }, + { + name: 'Status de imagem', + value: 'image', + }, + { + name: 'Status de Video', + value: 'video', + }, + { + name: 'Status de Audio', + value: 'audio', + }, + ], + default: 'text', + }, + { + displayName: 'Conteudo ou URL', + name: 'content', + type: 'string', + default: '', + required: true, + description: 'Digite o conteudo ou Url da imagem/video/audio a ser postado', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-stories'], + }, + }, + }, + { + displayName: 'Texto para status de Imagem/Video', + name: 'caption', + type: 'string', + default: '', + required: false, + description: 'Digite o texto para status de Imagem/Video', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-stories'], + }, + }, + }, + { + displayName: 'Cor do Background', + name: 'backgroundColor', + type: 'color', + default: '#000000', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-stories'], + }, + }, + }, + { + displayName: 'Font do texto', + name: 'font', + type: 'options', + description: 'Escolha o tipo da font do seu texto', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-stories'], + }, + }, + options: [ + { + name: 'SERIF', + value: 1, + }, + { + name: 'NORICAN REGULAR', + value: 2, + }, + { + name: 'BRYNDAN WRITE', + value: 3, + }, + { + name: 'BEBASNEUE REGULAR', + value: 4, + }, + { + name: 'OSWALD HEAVY', + value: 5, + }, + ], + default: 1, + }, + + // Campos = Enviar Documento + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar o documento', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['sendDocument'], + }, + }, + }, + { + displayName: 'Número do Destinatário', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'Número do destinatário', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['sendDocument'], + }, + }, + }, + { + displayName: 'Documento', + name: 'media', + type: 'string', + default: '', + required: true, + description: 'URL ou base64 do documento', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['sendDocument'], + }, + }, + }, + { + displayName: 'Mensagem', + name: 'caption', + type: 'string', + default: '', + required: false, + description: 'Texto a ser enviado junto ao documento', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['sendDocument'], + }, + }, + }, + { + displayName: 'Nome do Arquivo', + name: 'fileName', + type: 'string', + default: 'document.pdf', + required: false, + description: 'Nome do arquivo do documento', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['sendDocument'], + }, + }, + }, + { + displayName: 'Opções', + name: 'options_message', + type: 'collection', + placeholder: 'Adicionar Campo', + default: {}, + options: [ + { + displayName: 'Delay', + name: 'delay', + type: 'number', + default: 1200, + description: 'Digite quantos milisegundos de delay a mensagem terá antes de ser enviada', + }, + { + displayName: 'Responder Mensagem', + name: 'quoted', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + messageQuoted: { + messageId: '', + }, + }, + options: [ + { + name: 'messageQuoted', + displayName: 'Mensagem', + values: [ + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string', + default: '', + description: 'ID da mensagem que será respondida', + }, + ], + }, + ], + }, + { + displayName: 'Menções', + name: 'mentions', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + mentionsSettings: { + mentionsEveryOne: false, + mentioned: '', + }, + }, + options: [ + { + name: 'mentionsSettings', + displayName: 'Configurações', + values: [ + { + displayName: 'Mencionar Todos', + name: 'mentionsEveryOne', + type: 'boolean', + default: false, + description: 'Menciona todos os participantes do grupo', + }, + { + displayName: 'Números para Mencionar', + name: 'mentioned', + type: 'string', + default: '', + displayOptions: { + show: { + mentionsEveryOne: [false], + }, + }, + description: 'Digite os números que deseja mencionar separados por vírgula (ex: 5511999999999,5511888888888)', + }, + ], + }, + ], + }, + ], + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['sendDocument'], + }, + }, + }, + + // Campos = Enviar Contato + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar o contato', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-contact'], + }, + }, + }, + { + displayName: 'Número do Destinatário', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'Número do destinatário', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-contact'], + }, + }, + }, + { + displayName: 'Contatos', + name: 'contacts', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: { contactValues: [] }, + options: [ + { + name: 'contactValues', + displayName: 'Contato', + values: [ + { + displayName: 'Nome Completo', + name: 'fullName', + type: 'string', + default: '', + required: true, + description: 'Nome completo do contato', + }, + { + displayName: 'Número do WhatsApp', + name: 'wuid', + type: 'string', + default: '', + required: true, + description: 'Número do WhatsApp (apenas números, ex: 559999999999)', + }, + { + displayName: 'Número Formatado', + name: 'phoneNumber', + type: 'string', + default: '', + required: true, + description: 'Número formatado (ex: +55 99 9 9999-9999)', + }, + { + displayName: 'Organização', + name: 'organization', + type: 'string', + default: '', + description: 'Nome da organização/empresa', + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + description: 'Endereço de email do contato', + }, + { + displayName: 'URL', + name: 'url', + type: 'string', + default: '', + description: 'URL da página do contato', + }, + ], + }, + ], + description: 'Lista de contatos para enviar', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-contact'], + }, + }, + }, + + // Campos = Enviar Lista + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar a lista', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-list'], + }, + }, + }, + { + displayName: 'Número do Destinatário', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'Número do destinatário', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-list'], + }, + }, + }, + { + displayName: 'Título da Lista', + name: 'title', + type: 'string', + default: '', + required: true, + description: 'Título principal da lista', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-list'], + }, + }, + }, + { + displayName: 'Descrição', + name: 'description', + type: 'string', + default: '', + required: true, + description: 'Descrição da lista', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-list'], + }, + }, + }, + { + displayName: 'Texto do Botão', + name: 'buttonText', + type: 'string', + default: 'Ver Opções', + required: true, + description: 'Texto que aparecerá no botão da lista', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-list'], + }, + }, + }, + { + displayName: 'Texto do Rodapé', + name: 'footerText', + type: 'string', + default: '', + required: true, + description: 'Texto que aparecerá no rodapé da lista', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-list'], + }, + }, + }, + { + displayName: 'Seções', + name: 'sections', + placeholder: 'Adicionar Seção', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + options: [ + { + name: 'sectionValues', + displayName: 'Seção', + values: [ + { + displayName: 'Título da Seção', + name: 'title', + type: 'string', + default: '', + description: 'Título da seção', + }, + { + displayName: 'Linhas', + name: 'rows', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + options: [ + { + name: 'rowValues', + displayName: 'Linha', + values: [ + { + displayName: 'Título', + name: 'title', + type: 'string', + default: '', + required: true, + description: 'Título da linha', + }, + { + displayName: 'Descrição', + name: 'description', + type: 'string', + default: '', + description: 'Descrição da linha (Opcional)', + }, + { + displayName: 'ID da Linha', + name: 'rowId', + type: 'string', + default: '', + description: 'ID único da opção', + } + ] + } + ] + } + ] + } + ], + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-list'], + }, + } + }, + { + displayName: 'Opções', + name: 'options_message', + type: 'collection', + placeholder: 'Adicionar Campo', + default: {}, + options: [ + { + displayName: 'Delay', + name: 'delay', + type: 'number', + default: 1200, + description: 'Digite quantos milisegundos de delay a mensagem terá antes de ser enviada', + }, + { + displayName: 'Responder Mensagem', + name: 'quoted', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + messageQuoted: { + messageId: '', + }, + }, + options: [ + { + name: 'messageQuoted', + displayName: 'Mensagem', + values: [ + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string', + default: '', + description: 'ID da mensagem que será respondida', + }, + ], + }, + ], + }, + { + displayName: 'Menções', + name: 'mentions', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: { + mentionsSettings: { + mentionsEveryOne: false, + mentioned: '', + }, + }, + options: [ + { + name: 'mentionsSettings', + displayName: 'Configurações', + values: [ + { + displayName: 'Mencionar Todos', + name: 'mentionsEveryOne', + type: 'boolean', + default: false, + description: 'Menciona todos os participantes do grupo', + }, + { + displayName: 'Números para Mencionar', + name: 'mentioned', + type: 'string', + default: '', + displayOptions: { + show: { + mentionsEveryOne: [false], + }, + }, + description: 'Digite os números que deseja mencionar separados por vírgula (ex: 5511999999999,5511888888888)', + }, + ], + }, + ], + }, + ], + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-list'], + }, + }, + }, + + // Campos = Enviar Botões + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar os botões', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-buttons'], + }, + }, + }, + { + displayName: 'Número do Destinatário', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'Número do destinatário', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-buttons'], + }, + }, + }, + { + displayName: 'Título', + name: 'title', + type: 'string', + default: '', + required: true, + description: 'Título da mensagem com botões', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-buttons'], + }, + }, + }, + { + displayName: 'Descrição', + name: 'description', + type: 'string', + default: '', + required: true, + description: 'Descrição da mensagem com botões', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-buttons'], + }, + }, + }, + { + displayName: 'Rodapé', + name: 'footer', + type: 'string', + default: '', + //required: false, + description: 'Texto do rodapé da mensagem', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-buttons'], + }, + }, + }, + { + displayName: 'Botões', + name: 'buttons', + placeholder: 'Adicionar Botão', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + maxValue: 3, + }, + default: {}, + options: [ + { + name: 'buttonValues', + displayName: 'Botão', + values: [ + { + displayName: 'Tipo', + name: 'type', + type: 'options', + options: [ + { + name: 'Resposta', + value: 'reply', + }, + { + name: 'Copiar', + value: 'copy', + }, + { + name: 'URL', + value: 'url', + }, + { + name: 'Ligar', + value: 'call', + }, + ], + default: 'reply', + }, + { + displayName: 'Texto do Botão', + name: 'displayText', + type: 'string', + default: '', + required: true, + }, + { + displayName: 'ID', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + type: ['reply'], + }, + }, + }, + { + displayName: 'Código para Copiar', + name: 'copyCode', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + type: ['copy'], + }, + }, + }, + { + displayName: 'URL', + name: 'url', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + type: ['url'], + }, + }, + }, + { + displayName: 'Número de Telefone', + name: 'phoneNumber', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + type: ['call'], + }, + }, + }, + ], + }, + ], + description: 'Botões da mensagem (máximo 3)', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-buttons'], + }, + }, + }, + + // Campos = Enviar PIX + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância que vai enviar o PIX', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-pix'], + }, + }, + }, + { + displayName: 'Número do Destinatário', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'Número do destinatário', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-pix'], + }, + }, + }, + { + displayName: 'Nome do Beneficiário', + name: 'name', + type: 'string', + default: '', + required: true, + description: 'Nome do beneficiário do PIX', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-pix'], + }, + }, + }, + { + displayName: 'Tipo da Chave', + name: 'keyType', + type: 'options', + options: [ + { + name: 'Telefone', + value: 'phone', + }, + { + name: 'E-mail', + value: 'email', + }, + { + name: 'CPF', + value: 'cpf', + }, + { + name: 'CNPJ', + value: 'cnpj', + }, + { + name: 'Aleatória', + value: 'random', + }, + ], + default: 'email', + required: true, + description: 'Tipo da chave PIX', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-pix'], + }, + }, + }, + { + displayName: 'Chave PIX', + name: 'key', + type: 'string', + default: '', + required: true, + description: 'Chave PIX do beneficiário', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-pix'], + }, + }, + }, + { + displayName: 'Enviar para Todos', + name: 'allContacts', + type: 'boolean', + default: false, + description: 'Envia o status para todos os contatos', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-stories'], + }, + }, + }, + { + displayName: 'Lista de Contatos', + name: 'statusJidList', + type: 'string', + default: '', + required: true, + description: 'Lista de contatos que receberão o status (separados por vírgula)', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-stories'], + allContacts: [false], + }, + }, + }, + + // Campos = Reagir Mensagem + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string', + default: '', + required: true, + description: 'Digite o nome da instância', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-reaction'], + }, + }, + }, + { + displayName: 'Número do Chat', + name: 'remoteJid', + type: 'string', + default: '', + required: true, + description: 'Número do chat onde está a mensagem', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-reaction'], + }, + }, + }, + { + displayName: 'ID da Mensagem', + name: 'messageId', + type: 'string', + default: '', + required: true, + description: 'ID da mensagem que receberá a reação', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-reaction'], + }, + }, + }, + { + displayName: 'Mensagem Própria', + name: 'fromMe', + type: 'boolean', + default: true, + description: 'A mensagem foi enviada por você?', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-reaction'], + }, + }, + }, + { + displayName: 'Emoji da Reação', + name: 'reaction', + type: 'string', + default: '👍', + required: true, + description: 'Emoji que será usado como reação', + displayOptions: { + show: { + resource: ['messages-api'], + operation: ['send-reaction'], + }, + }, + } +]; diff --git a/nodes/EvolutionApi/properties/messages.operations.ts b/nodes/EvolutionApi/properties/messages.operations.ts new file mode 100644 index 0000000..8f9e700 --- /dev/null +++ b/nodes/EvolutionApi/properties/messages.operations.ts @@ -0,0 +1,119 @@ +import { INodeProperties } from 'n8n-workflow'; + +// Opções da messages-api (Mensagens) +export const messagesOperationsOptions: INodeProperties = { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { + show: { + resource: ['messages-api'], // Value do Resource + }, + }, + options: [ + // Opção = Enviar mensagem de Texto + { + // Send Text + name: 'Enviar Texto', + action: 'Enviar Texto', + description: 'Envia mensagem de Texto', + value: 'send-text', + }, + + // Opção = Enviar Imagem + { + // Send Media + name: 'Enviar Imagem', + action: 'Enviar Imagem', + description: 'Envia mensagem de Imagem', + value: 'send-image', + }, + + // Opção = Enviar Video + { + // Send Media + name: 'Enviar Video', + action: 'Enviar Video', + description: 'Enviar mensagem de Video', + value: 'send-video', + }, + + // Opção = Enviar Audio + { + // Send Narrated Audio + name: 'Enviar Audio', + action: 'Enviar Audio', + description: 'Enviar mensagem de Audio', + value: 'send-audio', + }, + + // Opção = Enviar Documento + { + // Send Media + name: 'Enviar Documento', + action: 'Enviar Documento', + description: 'Enviar mensagem de Video', + value: 'send-document', + }, + + // Opção = Enviar Enquete + { + // Send Poll + name: 'Enviar Enquete', + action: 'Enviar Enquete', + description: 'Envia uma Enquete de até 12 opções', + value: 'send-poll', + }, + + // Opção = Enviar Contato + { + name: 'Enviar Contato', + action: 'Enviar Contato', + description: 'Envia um contato no whatsapp', + value: 'send-contact', + }, + + // Opção = Enviar Lista + { + name: 'Enviar Lista', + action: 'Enviar Lista', + description: 'Envia uma lista de opções interativa', + value: 'send-list', + }, + + // Opção = Enviar Botões + { + name: 'Enviar Botões', + action: 'Enviar Botões', + description: 'Envia mensagem com botões interativos', + value: 'send-buttons', + }, + + // Opção = Enviar PIX + { + name: 'Enviar PIX', + action: 'Enviar PIX', + description: 'Envia botão de pagamento PIX', + value: 'send-pix', + }, + + // Opção = Enviar Status + { + name: 'Enviar Status', + action: 'Enviar Status', + description: 'Publicar um Status/Stories', + value: 'send-stories', + }, + + // Opção = Reagir Mensagem + { + name: 'Reagir Mensagem', + action: 'Reagir Mensagem', + description: 'Adiciona uma reação em uma mensagem', + value: 'send-reaction', + }, + ], + // Definindo como padrão a opção "Enviar Texto" + default: 'send-text', +}; diff --git a/nodes/EvolutionApi/properties/profile.fields.ts b/nodes/EvolutionApi/properties/profile.fields.ts new file mode 100644 index 0000000..f8b95cd --- /dev/null +++ b/nodes/EvolutionApi/properties/profile.fields.ts @@ -0,0 +1,252 @@ +import { INodeProperties, NodePropertyTypes } from 'n8n-workflow'; + +export const profileFields: INodeProperties[] = [ + { + displayName: 'Nome da Instância', + name: 'instanceName', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Digite o nome da instância', + displayOptions: { + show: { + resource: ['profile-api'], + }, + }, + }, + { + displayName: 'Nome', + name: 'name', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Novo nome do perfil', + displayOptions: { + show: { + resource: ['profile-api'], + operation: ['update-profile-name'], + }, + }, + }, + { + displayName: 'Contato', + name: 'remoteJid', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Número do contato', + displayOptions: { + show: { + resource: ['profile-api'], + operation: [ + 'fetch-profile', + 'fetch-business-profile', + 'fetch-professional-profile' + ], + }, + }, + }, + { + displayName: 'Status', + name: 'status', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'Novo status do perfil (máximo 139 caracteres)', + typeOptions: { + maxLength: 139, + }, + displayOptions: { + show: { + resource: ['profile-api'], + operation: ['update-profile-status'], + }, + }, + }, + { + displayName: 'URL da Imagem', + name: 'picture', + type: 'string' as NodePropertyTypes, + default: '', + required: true, + description: 'URL da imagem que será definida como foto do perfil', + displayOptions: { + show: { + resource: ['profile-api'], + operation: ['update-profile-picture'], + }, + }, + }, + { + displayName: 'Confirmação de Leitura', + name: 'readreceipts', + type: 'options' as NodePropertyTypes, + options: [ + { + name: 'Todos', + value: 'all', + }, + { + name: 'Ninguém', + value: 'none', + }, + ], + default: 'all', + required: true, + description: 'Quem pode ver quando você leu as mensagens', + displayOptions: { + show: { + resource: ['profile-api'], + operation: ['update-privacy-settings'], + }, + }, + }, + { + displayName: 'Foto do Perfil', + name: 'profile', + type: 'options' as NodePropertyTypes, + options: [ + { + name: 'Todos', + value: 'all', + }, + { + name: 'Meus Contatos', + value: 'contacts', + }, + { + name: 'Exceto Contatos Específicos', + value: 'contact_blacklist', + }, + { + name: 'Ninguém', + value: 'none', + }, + ], + default: 'all', + required: true, + description: 'Quem pode ver sua foto de perfil', + displayOptions: { + show: { + resource: ['profile-api'], + operation: ['update-privacy-settings'], + }, + }, + }, + { + displayName: 'Status', + name: 'status', + type: 'options' as NodePropertyTypes, + options: [ + { + name: 'Todos', + value: 'all', + }, + { + name: 'Meus Contatos', + value: 'contacts', + }, + { + name: 'Exceto Contatos Específicos', + value: 'contact_blacklist', + }, + { + name: 'Ninguém', + value: 'none', + }, + ], + default: 'contacts', + required: true, + description: 'Quem pode ver seu status', + displayOptions: { + show: { + resource: ['profile-api'], + operation: ['update-privacy-settings'], + }, + }, + }, + { + displayName: 'Online', + name: 'online', + type: 'options' as NodePropertyTypes, + options: [ + { + name: 'Todos', + value: 'all', + }, + { + name: 'Igual ao Visto por Último', + value: 'match_last_seen', + }, + ], + default: 'all', + required: true, + description: 'Quem pode ver quando você está online', + displayOptions: { + show: { + resource: ['profile-api'], + operation: ['update-privacy-settings'], + }, + }, + }, + { + displayName: 'Visto por Último', + name: 'last', + type: 'options' as NodePropertyTypes, + options: [ + { + name: 'Todos', + value: 'all', + }, + { + name: 'Meus Contatos', + value: 'contacts', + }, + { + name: 'Exceto Contatos Específicos', + value: 'contact_blacklist', + }, + { + name: 'Ninguém', + value: 'none', + }, + ], + default: 'contacts', + required: true, + description: 'Quem pode ver seu último acesso', + displayOptions: { + show: { + resource: ['profile-api'], + operation: ['update-privacy-settings'], + }, + }, + }, + { + displayName: 'Grupos', + name: 'groupadd', + type: 'options' as NodePropertyTypes, + options: [ + { + name: 'Todos', + value: 'all', + }, + { + name: 'Meus Contatos', + value: 'contacts', + }, + { + name: 'Exceto Contatos Específicos', + value: 'contact_blacklist', + }, + ], + default: 'all', + required: true, + description: 'Quem pode te adicionar em grupos', + displayOptions: { + show: { + resource: ['profile-api'], + operation: ['update-privacy-settings'], + }, + }, + }, +]; diff --git a/nodes/EvolutionApi/properties/profile.operations.ts b/nodes/EvolutionApi/properties/profile.operations.ts new file mode 100644 index 0000000..692b7cd --- /dev/null +++ b/nodes/EvolutionApi/properties/profile.operations.ts @@ -0,0 +1,64 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const profileOperationsOptions: INodeProperties = { + displayName: 'Operação', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { + show: { + resource: ['profile-api'], + }, + }, + options: [ + { + name: 'Buscar Perfil', + value: 'fetch-profile', + description: 'Busca informações do perfil', + action: 'Buscar perfil', + }, + { + name: 'Buscar Perfil Profissional', + value: 'fetch-business-profile', + description: 'Busca informações do perfil profissional', + action: 'Buscar perfil profissional', + }, + { + name: 'Atualizar Nome do Perfil', + value: 'update-profile-name', + description: 'Atualiza o nome do perfil', + action: 'Atualizar nome do perfil', + }, + { + name: 'Atualizar Status', + value: 'update-profile-status', + description: 'Atualiza o status do perfil', + action: 'Atualizar status do perfil', + }, + { + name: 'Atualizar Foto do Perfil', + value: 'update-profile-picture', + description: 'Atualiza a foto do perfil', + action: 'Atualizar foto do perfil', + }, + { + name: 'Remover Foto do Perfil', + value: 'remove-profile-picture', + description: 'Remove a foto do perfil', + action: 'Remover foto do perfil', + }, + { + name: 'Buscar Configurações de Privacidade', + value: 'fetch-privacy-settings', + description: 'Busca as configurações de privacidade da instância', + action: 'Buscar configurações de privacidade', + }, + { + name: 'Atualizar Configurações de Privacidade', + value: 'update-privacy-settings', + description: 'Atualiza as configurações de privacidade da instância', + action: 'Atualizar configurações de privacidade', + }, + ], + default: 'fetch-profile', +}; diff --git a/nodes/EvolutionApi/properties/readme.txt b/nodes/EvolutionApi/properties/readme.txt new file mode 100644 index 0000000..db449fe --- /dev/null +++ b/nodes/EvolutionApi/properties/readme.txt @@ -0,0 +1,43 @@ +Observação deste documento: +Este documento serve para a Definição de Operações que devem aparecer +em cada Resource, incluindo a criação de novos campos para cada Operation + + ██████╗ ██████╗ ███████╗██████╗ █████╗ ████████╗██╗ ██████╗ ███╗ ██╗ +██╔═══██╗██╔══██╗██╔════╝██╔══██╗██╔══██╗╚══██╔══╝██║██╔═══██╗████╗ ██║ +██║ ██║██████╔╝█████╗ ██████╔╝███████║ ██║ ██║██║ ██║██╔██╗ ██║ +██║ ██║██╔═══╝ ██╔══╝ ██╔══██╗██╔══██║ ██║ ██║██║ ██║██║╚██╗██║ +╚██████╔╝██║ ███████╗██║ ██║██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║ + ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ + +Operation = Funções/Opções de cada Resource (Instancia, Mensagens, Integração, Conversa, Perfil e Grupo) + +"O que cada Resource vai apresentar ao ser selecionado" + +Exemplo: +Instancias: + • Criar instncia; + • Criar instancia com proxy; + • Conectar instancia; + +Cada Resource adicionada tera um desse para listar as opções/funções de cada Resource + + + + + ███████╗██╗ ███████╗███╗ ███╗███████╗███╗ ██╗████████╗███████╗ + ██╔════╝██║ ██╔════╝████╗ ████║██╔════╝████╗ ██║╚══██╔══╝██╔════╝ + █████╗ ██║ █████╗ ██╔████╔██║█████╗ ██╔██╗ ██║ ██║ ███████╗ + ██╔══╝ ██║ ██╔══╝ ██║╚██╔╝██║██╔══╝ ██║╚██╗██║ ██║ ╚════██║ + ███████╗███████╗███████╗██║ ╚═╝ ██║███████╗██║ ╚████║ ██║ ███████║ + ╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝ + +Elements = Os campos que aparecem em cada Operation + +"Cada Operation (ex: Enviar mensagem de Texto) tem campos que precisam ser preenchido para fazer uma requisição" + +Exemplo: +Enviar Mensagem de Texto: + • Instancia que vai enviar; + • RemoteJid do destinatario; + • Mensagem que vai ser enviada; + diff --git a/nodes/EvolutionApi/properties/resources.ts b/nodes/EvolutionApi/properties/resources.ts new file mode 100644 index 0000000..b4c8b0f --- /dev/null +++ b/nodes/EvolutionApi/properties/resources.ts @@ -0,0 +1,39 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const resources: INodeProperties = { + displayName: 'Recurso', + name: 'resource', + type: 'options', + noDataExpression: true, + options: [ + { + name: 'Instância', + value: 'instances-api', + }, + { + name: 'Mensagem', + value: 'messages-api', + }, + { + name: 'Chat', + value: 'chat-api', + }, + { + name: 'Grupo', + value: 'groups-api', + }, + { + name: 'Perfil', + value: 'profile-api', + }, + { + name: 'Evento', + value: 'events-api', + }, + { + name: 'Integração', + value: 'integrations-api', + }, + ], + default: 'instances-api', +}; diff --git a/nodes/HttpBin/HttpBin.node.ts b/nodes/HttpBin/HttpBin.node.ts deleted file mode 100644 index 985d144..0000000 --- a/nodes/HttpBin/HttpBin.node.ts +++ /dev/null @@ -1,1518 +0,0 @@ -import { INodeType, INodeTypeDescription, IExecuteFunctions, INodeExecutionData, IRequestOptions, IHttpRequestMethods, NodeApiError } from 'n8n-workflow'; -import { httpVerbFields, httpVerbOperations } from './HttpVerbDescription'; -// Observação deste documento: -// Este documento serve para a realizar as requisições do node -// Utilizando os campos definidos no HttpVerbDescription.ts - -export class HttpBin implements INodeType { - description: INodeTypeDescription = { - displayName: 'Evolution API', - name: 'httpBin', - icon: 'file:evolutionapi.svg', - group: ['transform'], - version: 1, - subtitle: '={{$parameter["operation"]}}', - description: 'Interact with Evolution API', - defaults: { - name: 'Evolution API', - }, - inputs: ['main'], - outputs: ['main'], - credentials: [ - { - name: 'httpbinApi', - required: true, - }, - ], - requestDefaults: { - baseURL: 'https://doc.evolution-api.com/api-reference', - url: '', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - }, - properties: [ - { - displayName: 'Recurso', - name: 'resource', - type: 'options', - noDataExpression: true, - options: [ - { - name: 'Instancia', - value: 'instances-api', - }, - { - name: 'Mensagem', - value: 'messages-api', - }, - { - name: 'Evento', - value: 'events-api', - }, - { - name: 'Integração', - value: 'integrations-api', - }, - ], - default: 'instances-api', - }, - ...httpVerbOperations, - ...httpVerbFields, - ], - }; - - async execute(this: IExecuteFunctions): Promise { - const resource = this.getNodeParameter('resource', 0); - const operation = this.getNodeParameter('operation', 0); - - let responseData; - - // Criar instancia basica - if (resource === 'instances-api' && operation === 'instance-basic') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - - const instanceName = this.getNodeParameter('instanceName', 0); - const token = this.getNodeParameter('token', 0) || ''; - const number = this.getNodeParameter('number', 0) || ''; - - // Inicializa o corpo básico da requisição - const body: any = { - instanceName, - integration: 'WHATSAPP-BAILEYS', - }; - - if (token) { - body.token = token; - } - if (number) { - body.number = number; - } - - // Verifica e adiciona configurações da instância se existirem - const instanceSettings = this.getNodeParameter('options_Create_instance.instanceSettings.settings', 0, {}) as { - rejectCall?: boolean; - msgCall?: string; - groupsIgnore?: boolean; - alwaysOnline?: boolean; - readMessages?: boolean; - readStatus?: boolean; - syncFullHistory?: boolean; - }; - if (instanceSettings && Object.keys(instanceSettings).length > 0) { - Object.assign(body, instanceSettings); - } - - // Verifica e adiciona configurações de proxy se existirem - const proxySettings = this.getNodeParameter('options_Create_instance.proxy.proxySettings', 0, {}) as { - proxyHost?: string; - proxyPort?: number; - proxyProtocol?: string; - proxyUsername?: string; - proxyPassword?: string; - }; - if (proxySettings && Object.keys(proxySettings).length > 0) { - Object.assign(body, { - proxyHost: proxySettings.proxyHost || "", - proxyPort: proxySettings.proxyPort ? String(proxySettings.proxyPort) : "1234", // Converte para string - proxyProtocol: proxySettings.proxyProtocol || "", - proxyUsername: proxySettings.proxyUsername || "", - proxyPassword: proxySettings.proxyPassword || "", - }); - } - - // Verifica e adiciona configurações do Webhook se existirem - const webhookSettings = this.getNodeParameter('options_Create_instance.webhook.webhookSettings', 0, {}) as { - webhookUrl?: string; - webhookByEvents?: boolean; - webhookBase64?: boolean; - webhookEvents?: string[]; - }; - - if (webhookSettings && Object.keys(webhookSettings).length > 0) { - Object.assign(body, { - 'webhook': { - url: webhookSettings.webhookUrl || "", - byEvents: webhookSettings.webhookByEvents || false, - base64: webhookSettings.webhookBase64 || false, - events: webhookSettings.webhookEvents || [], - } - }); - } - - // Verifica e adiciona configurações do RabbitMQ se existirem - const rabbitmqSettings = this.getNodeParameter('options_Create_instance.rabbitmq.rabbitmqSettings', 0, {}) as { - rabbitmqEnabled?: boolean; - rabbitmqEvents?: string[]; - }; - - if (rabbitmqSettings && Object.keys(rabbitmqSettings).length > 0) { - Object.assign(body, { - 'rabbitmq': { - enabled: rabbitmqSettings.rabbitmqEnabled || false, - events: rabbitmqSettings.rabbitmqEvents || [], - } - }); - } - - // Verifica e adiciona configurações do Chatwoot se existirem - const chatwootSettings = this.getNodeParameter('options_Create_instance.chatwoot.chatwootSettings', 0, {}) as { - chatwootAccountId?: number; - chatwootToken?: string; - chatwootUrl?: string; - chatwootSignMsg?: boolean; - chatwootReopenConversation?: boolean; - chatwootConversationPending?: boolean; - chatwootImportContacts?: boolean; - chatwootNameInbox?: string; - chatwootMergeBrazilContacts?: boolean; - chatwootImportMessages?: boolean; - chatwootDaysLimitImportMessages?: number; - chatwootOrganization?: string; - chatwootLogo?: string; - }; - - // Adiciona todos os campos do Chatwoot - body.chatwootAccountId = chatwootSettings.chatwootAccountId || ''; - body.chatwootToken = chatwootSettings.chatwootToken || ''; - body.chatwootUrl = chatwootSettings.chatwootUrl || ''; - body.chatwootSignMsg = chatwootSettings.chatwootSignMsg !== undefined ? chatwootSettings.chatwootSignMsg : false; - body.chatwootReopenConversation = chatwootSettings.chatwootReopenConversation || false; - body.chatwootConversationPending = chatwootSettings.chatwootConversationPending || false; - body.chatwootImportContacts = chatwootSettings.chatwootImportContacts || false; - body.chatwootNameInbox = chatwootSettings.chatwootNameInbox || ''; - body.chatwootMergeBrazilContacts = chatwootSettings.chatwootMergeBrazilContacts || false; - body.chatwootImportMessages = chatwootSettings.chatwootImportMessages || false; - body.chatwootDaysLimitImportMessages = chatwootSettings.chatwootDaysLimitImportMessages || 0; - body.chatwootOrganization = chatwootSettings.chatwootOrganization || ''; - body.chatwootLogo = chatwootSettings.chatwootLogo || ''; - - const options: IRequestOptions = { - method: 'POST' as IHttpRequestMethods, - headers: { - 'Content-Type': 'application/json', - apikey: apiKey, - }, - uri: `${serverUrl}/instance/create`, - body, - json: true, - }; - - responseData = await this.helpers.request(options); - } - - // Conectar Instância - if (resource === 'instances-api' && operation === 'instance-connect') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - - const options: IRequestOptions = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/instance/connect/${instanceName}`, - json: true, - }; - - responseData = await this.helpers.request(options); - } - - // Reiniciar Instancia - if (resource === 'instances-api' && operation === 'restart-instance') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - - const options: IRequestOptions = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/instance/restart/${instanceName}`, - json: true, - }; - - responseData = await this.helpers.request(options); - } - - // Desconectar instancia - if (resource === 'instances-api' && operation === 'logout-instance') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - - const options: IRequestOptions = { - method: 'DELETE' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/instance/logout/${instanceName}`, - json: true, - }; - - responseData = await this.helpers.request(options); - } - - // Definir presença - if (resource === 'instances-api' && operation === 'setPresence') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - const presence = this.getNodeParameter('presence', 0); - - const options: IRequestOptions = { - method: 'POST' as IHttpRequestMethods, - headers: { - 'Content-Type': 'application/json', - apikey: apiKey, - }, - uri: `${serverUrl}/instance/setPresence/${instanceName}`, - body: { - presence: presence, - }, - json: true, - }; - responseData = await this.helpers.request(options); - } - - // Deletar instancia - if (resource === 'instances-api' && operation === 'delete-instance') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - - const options: IRequestOptions = { - method: 'DELETE' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/instance/delete/${instanceName}`, - json: true, - }; - - responseData = await this.helpers.request(options); - } - - // Buscar Instancia - if (resource === 'instances-api' && operation === 'fetch-instances') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - - const options: IRequestOptions = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/instance/fetchInstances${instanceName ? `?instanceName=${instanceName}` : ''}`, - json: true, - }; - - responseData = await this.helpers.request(options); - } - - // Confiturações da instancia - if (resource === 'instances-api' && operation === 'instanceSettings') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - const rejectCall = this.getNodeParameter('rejectCall', 0); - const msgCall = this.getNodeParameter('msgCall', 0) || ''; // Define um valor padrão - const groupsIgnore = this.getNodeParameter('groupsIgnore', 0); - const alwaysOnline = this.getNodeParameter('alwaysOnline', 0); - const readMessages = this.getNodeParameter('readMessages', 0); - const syncFullHistory = this.getNodeParameter('syncFullHistory', 0); - const readStatus = this.getNodeParameter('readStatus', 0); - - const body: any = { - rejectCall, - msgCall: msgCall || '', - groupsIgnore, - alwaysOnline, - readMessages, - syncFullHistory, - readStatus, - }; - - const options: IRequestOptions = { - method: 'POST' as IHttpRequestMethods, - headers: { - 'Content-Type': 'application/json', - apikey: apiKey, - }, - uri: `${serverUrl}/settings/set/${instanceName}`, - body, - json: true, - }; - responseData = await this.helpers.request(options); - // Adiciona msgCall apenas se rejectCall for true - if (rejectCall) { - body.msgCall = msgCall || ''; - } - } - - // Enviar mensagem de texto - if (resource === 'messages-api' && operation === 'sendText') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - const remoteJid = this.getNodeParameter('remoteJid', 0); - const messageText = this.getNodeParameter('messageText', 0); - const mentionsEveryOne = this.getNodeParameter('mentionsEveryOne', 0); - - const options: IRequestOptions = { - method: 'POST' as IHttpRequestMethods, - headers: { - 'Content-Type': 'application/json', - apikey: apiKey, - }, - uri: `${serverUrl}/message/sendText/${instanceName}`, - body: { - number: remoteJid, - text: messageText, - mentionsEveryOne: mentionsEveryOne, - }, - json: true, - }; - responseData = await this.helpers.request(options); - } - - // Enviar mensagem de imagem - if (resource === 'messages-api' && operation === 'sendImage') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - const remoteJid = this.getNodeParameter('remoteJid', 0); - const media = this.getNodeParameter('media', 0); - // const mimetype = this.getNodeParameter('mimetype', 0); - const caption = this.getNodeParameter('caption', 0); - // const fileName = this.getNodeParameter('fileName', 0); - const mentionsEveryOne = this.getNodeParameter('mentionsEveryOne', 0); - - const options: IRequestOptions = { - method: 'POST' as IHttpRequestMethods, - headers: { - 'Content-Type': 'application/json', - apikey: apiKey, - }, - uri: `${serverUrl}/message/sendMedia/${instanceName}`, - body: { - number: remoteJid, - 'mediatype': 'image', - media: media, - 'mimetype': '', - caption: caption, - 'fileName': '', - mentionsEveryOne: mentionsEveryOne, - - }, - json: true, - }; - responseData = await this.helpers.request(options); - } - - // Enviar mensagem de video - if (resource === 'messages-api' && operation === 'sendVideo') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - const remoteJid = this.getNodeParameter('remoteJid', 0); - const media = this.getNodeParameter('media', 0); - // const mimetype = this.getNodeParameter('mimetype', 0); - const caption = this.getNodeParameter('caption', 0); - // const fileName = this.getNodeParameter('fileName', 0); - const mentionsEveryOne = this.getNodeParameter('mentionsEveryOne', 0); - - const options: IRequestOptions = { - method: 'POST' as IHttpRequestMethods, - headers: { - 'Content-Type': 'application/json', - apikey: apiKey, - }, - uri: `${serverUrl}/message/sendMedia/${instanceName}`, - body: { - number: remoteJid, - 'mediatype': 'video', - media: media, - 'mimetype': '', - caption: caption, - 'fileName': '', - mentionsEveryOne: mentionsEveryOne, - }, - json: true, - }; - responseData = await this.helpers.request(options); - } - - // Enviar mensagem de audio - if (resource === 'messages-api' && operation === 'sendAudio') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - const remoteJid = this.getNodeParameter('remoteJid', 0); - const media = this.getNodeParameter('media', 0); - const mentionsEveryOne = this.getNodeParameter('mentionsEveryOne', 0); - - const options: IRequestOptions = { - method: 'POST' as IHttpRequestMethods, - headers: { - 'Content-Type': 'application/json', - apikey: apiKey, - }, - uri: `${serverUrl}/message/sendWhatsAppAudio/${instanceName}`, - body: { - number: remoteJid, - audio: media, - mentionsEveryOne: mentionsEveryOne, - }, - json: true, - }; - responseData = await this.helpers.request(options); - } - - // Enviar mensagem de documento - if (resource === 'messages-api' && operation === 'sendDocumento') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - const remoteJid = this.getNodeParameter('remoteJid', 0); - const media = this.getNodeParameter('media', 0); - const caption = this.getNodeParameter('caption', 0); - // const fileName = this.getNodeParameter('fileName', 0); - const mentionsEveryOne = this.getNodeParameter('mentionsEveryOne', 0); - - const options: IRequestOptions = { - method: 'POST' as IHttpRequestMethods, - headers: { - 'Content-Type': 'application/json', - apikey: apiKey, - }, - uri: `${serverUrl}/message/sendMedia/${instanceName}`, - body: { - number: remoteJid, - 'mediatype': 'document', - media: media, - caption: caption, - 'fileName': '', - mentionsEveryOne: mentionsEveryOne, - }, - json: true, - }; - responseData = await this.helpers.request(options); - } - - // Enviar Enquete - if (resource === 'messages-api' && operation === 'sendPoll') { - try { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - - const instanceName = this.getNodeParameter('instanceName', 0); - const remoteJid = this.getNodeParameter('remoteJid', 0); - const pollTitle = this.getNodeParameter('caption', 0); - const options = this.getNodeParameter('options_display.metadataValues', 0) as { optionValue: string }[]; - const mentionsEveryOne = this.getNodeParameter('mentionsEveryOne', 0); - - // Verifica se options é um array e não está vazio - const pollOptions = Array.isArray(options) ? options.map(option => option.optionValue) : []; - - const requestOptions: IRequestOptions = { - method: 'POST' as IHttpRequestMethods, - headers: { - 'Content-Type': 'application/json', - apikey: apiKey, - }, - uri: `${serverUrl}/message/sendPoll/${instanceName}`, - body: { - number: remoteJid, - name: pollTitle, - selectableCount: 1, - mentionsEveryOne: mentionsEveryOne, - values: pollOptions, - }, - json: true, - }; - - responseData = await this.helpers.request(requestOptions); - } catch (error) { - // console.error('Erro ao enviar a enquete:', error); - throw new NodeApiError(this.getNode(), error); // Substitua aqui - } - } - - - // Enviar status - if (resource === 'messages-api' && operation === 'sendStories') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - const instanceName = this.getNodeParameter('instanceName', 0); - const type = this.getNodeParameter('type', 0); - const content = this.getNodeParameter('content', 0); - const caption = this.getNodeParameter('caption', 0); - const backgroundColor = this.getNodeParameter('backgroundColor', 0); - const font = this.getNodeParameter('font', 0); - - const options: IRequestOptions = { - method: 'POST' as IHttpRequestMethods, - headers: { - 'Content-Type': 'application/json', - apikey: apiKey, - }, - uri: `${serverUrl}/message/sendStatus/${instanceName}`, - body: { - type: type, - content: content, - caption: caption, - backgroundColor: backgroundColor, - font: font, - 'allContacts': true, - }, - json: true, - }; - responseData = await this.helpers.request(options); - } - - // Definir/Buscar Webhook - if (resource === 'events-api' && operation === 'webhook') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - - const instanceName = this.getNodeParameter('instanceName', 0); - const resourceForWebhook = this.getNodeParameter('resourceForWebhook', 0); - - let options: IRequestOptions; // Declare a variável antes de usá-la - - if (resourceForWebhook === 'setWebhook') { - // Configurações do Webhook - const enabled = this.getNodeParameter('enabled', 0); - const webhookUrl = this.getNodeParameter('webhookUrl', 0) || 'vazio'; - const webhookByEvents = this.getNodeParameter('webhookByEvents', 0); - const webhookBase64 = this.getNodeParameter('webhookBase64', 0); - const webhookEvents = this.getNodeParameter('webhookEvents', 0) || []; - - const body = { - 'webhook': { - enabled: enabled, - url: webhookUrl, - webhookByEvents, - webhookBase64, - events: webhookEvents, - } - }; - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/webhook/set/${instanceName}`, - body, - json: true, - }; - } else if (resourceForWebhook === 'findWebhook') { - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/webhook/find/${instanceName}`, - json: true, - }; - } else { - throw new NodeApiError(this.getNode(), { - message: 'Operação de webhook não reconhecida.', - description: 'A operação solicitada não é válida para o recurso de webhook.', - }); - } - responseData = await this.helpers.request(options); - } - - // Definir/Buscar RabbitMQ - if (resource === 'events-api' && operation === 'rabbitMQ') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - - const instanceName = this.getNodeParameter('instanceName', 0); - const resourceForRabbitMQ = this.getNodeParameter('resourceForRabbitMQ', 0); - - let options: IRequestOptions; // Declare a variável antes de usá-la - - if (resourceForRabbitMQ === 'setRabbitMQ') { - // Configurações do RabbitMQ - const enabled = this.getNodeParameter('enabled', 0); - const rabbitMQEvents = this.getNodeParameter('rabbitMQEvents', 0) || []; - - const body = { - 'rabbitmq': { - enabled: enabled, - events: rabbitMQEvents, - } - }; - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/rabbitmq/set/${instanceName}`, - body, - json: true, - }; - } else if (resourceForRabbitMQ === 'findRabbitMQ') { - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/rabbitmq/find/${instanceName}`, - json: true, - }; - } else { - throw new NodeApiError(this.getNode(), { - message: 'Operação de RabbitMQ não reconhecida.', - description: 'A operação solicitada não é válida para o recurso de RabbitMQ.', - }); - } - responseData = await this.helpers.request(options); - } - - // Definir/Buscar Chatwoot - if (resource === 'integrations-api' && operation === 'chatwoot') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - - const instanceName = this.getNodeParameter('instanceName', 0); - const resourceForChatwoot = this.getNodeParameter('resourceForChatwoot', 0); - - let options: IRequestOptions; - - if (resourceForChatwoot === 'setChatwoot') { - // Configurações do Chatwoot - const enabled = this.getNodeParameter('enabled', 0) as boolean; - const chatwootAccountId = this.getNodeParameter('chatwootAccountId', 0) as number; - const chatwootToken = this.getNodeParameter('chatwootToken', 0) as string; - const chatwootUrl = this.getNodeParameter('chatwootUrl', 0) as string; - const chatwootSignMsg = this.getNodeParameter('chatwootSignMsg', 0) as boolean; - const chatwootReopenConversation = this.getNodeParameter('chatwootReopenConversation', 0) as boolean; - const chatwootConversationPending = this.getNodeParameter('chatwootConversationPending', 0) as boolean; - const chatwootImportContacts = this.getNodeParameter('chatwootImportContacts', 0) as boolean; - const chatwootNameInbox = this.getNodeParameter('chatwootNameInbox', 0) as string; - const chatwootMergeBrazilContacts = this.getNodeParameter('chatwootMergeBrazilContacts', 0) as boolean; - const chatwootImportMessages = this.getNodeParameter('chatwootImportMessages', 0) as boolean; - const chatwootAutoCreate = this.getNodeParameter('chatwootAutoCreate', 0) as boolean; - const chatwootDaysLimitImportMessages = this.getNodeParameter('chatwootDaysLimitImportMessages', 0) as number; - const chatwootOrganization = this.getNodeParameter('chatwootOrganization', 0) as string; - const chatwootLogo = this.getNodeParameter('chatwootLogo', 0, 'https://github.com/user-attachments/assets/4d1e9cd6-377a-4383-820a-9a97e6cfbb63') as string; - - const body = { - enabled: enabled, - accountId: chatwootAccountId, - token: chatwootToken, - url: chatwootUrl, - signMsg: chatwootSignMsg, - reopenConversation: chatwootReopenConversation, - conversationPending: chatwootConversationPending, - nameInbox: chatwootNameInbox, - mergeBrazilContacts: chatwootMergeBrazilContacts, - importContacts: chatwootImportContacts, - importMessages: chatwootImportMessages, - daysLimitImportMessages: chatwootDaysLimitImportMessages, - 'signDelimiter': '\n', - autoCreate: chatwootAutoCreate, - organization: chatwootOrganization, - logo: chatwootLogo, - }; - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/chatwoot/set/${instanceName}`, - body, - json: true, - }; - } else if (resourceForChatwoot === 'findChatwoot') { - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/chatwoot/find/${instanceName}`, - json: true, - }; - } else { - throw new NodeApiError(this.getNode(), { - message: 'Operação de Chatwoot não reconhecida.', - description: 'A operação solicitada não é válida para o recurso de Chatwoot.', - }); - } - - responseData = await this.helpers.request(options); - } - - // Definir/Buscar Proxy - if (resource === 'instances-api' && operation === 'proxy') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - - const instanceName = this.getNodeParameter('instanceName', 0); - const resourceForProxy = this.getNodeParameter('resourceForProxy', 0); - - let options: IRequestOptions; // Declare a variável antes de usá-la - - if (resourceForProxy === 'setProxy') { - // Configurações do Proxy - const enabled = this.getNodeParameter('enabled', 0) || ''; - const proxyHost = this.getNodeParameter('proxyHost', 0) || "1234"; - const proxyPort = this.getNodeParameter('proxyPort', 0) || ''; - const proxyProtocol = this.getNodeParameter('proxyProtocol', 0) || ''; - const proxyUsername = this.getNodeParameter('proxyUsername', 0) || ''; - const proxyPassword = this.getNodeParameter('proxyPassword', 0) || ''; - - const body = { - enabled: enabled, - host: proxyHost, - port: proxyPort, - protocol: proxyProtocol, - username: proxyUsername, - password: proxyPassword, - }; - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/proxy/set/${instanceName}`, - body, - json: true, - }; - } else if (resourceForProxy === 'findProxy') { - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/proxy/find/${instanceName}`, - json: true, - }; - } else { - throw new NodeApiError(this.getNode(), { - message: 'Operação de Proxy não reconhecida.', - description: 'A operação solicitada não é válida para o recurso de Proxy.', - }); - } - - responseData = await this.helpers.request(options); - } - - // Definir/Buscar Typebot - if (resource === 'integrations-api' && operation === 'typebot') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - - const instanceName = this.getNodeParameter('instanceName', 0); - const resourceForTypebot = this.getNodeParameter('resourceForTypebot', 0); - - let options: IRequestOptions; - - if (resourceForTypebot === 'createTypebot') { - const url = this.getNodeParameter('url', 0) as string; - const typebot = this.getNodeParameter('typebot', 0) as string; - const triggerType = this.getNodeParameter('triggerType', 0) as string; - - const body: any = { - enabled: true, - url, - typebot, - triggerType, - }; - - if (triggerType === 'keyword') { - const triggerOperator = this.getNodeParameter('triggerOperator', 0) as string; - const triggerValue = this.getNodeParameter('triggerValue', 0) as string; - body.triggerOperator = triggerOperator; - body.triggerValue = triggerValue; - } - - // Campos adicionais - body.keywordFinish = this.getNodeParameter('keywordFinish', 0) || ''; - body.delayMessage = this.getNodeParameter('delayMessage', 0) || 1000; - body.unknownMessage = this.getNodeParameter('unknownMessage', 0) || 'Mensagem não reconhecida'; - body.listeningFromMe = this.getNodeParameter('listeningFromMe', 0) || false; - body.stopBotFromMe = this.getNodeParameter('stopBotFromMe', 0) || false; - body.keepOpen = this.getNodeParameter('keepOpen', 0) || false; - body.debounceTime = this.getNodeParameter('debounceTime', 0) || 0; - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/typebot/create/${instanceName}`, - body, - json: true, - }; - } else if (resourceForTypebot === 'findTypebot') { - const typebotId = this.getNodeParameter('typebotId', 0) as string; - - if (typebotId) { - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/typebot/fetch/${typebotId}/${instanceName}`, - json: true, - }; - } else { - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/typebot/find/${instanceName}`, - json: true, - }; - } - } else if (resourceForTypebot === 'updateTypebot') { - const typebotId = this.getNodeParameter('typebotId', 0) as string; - const url = this.getNodeParameter('url', 0) as string; - const typebot = this.getNodeParameter('typebot', 0) as string; - const triggerType = this.getNodeParameter('triggerType', 0) as string; - - const body: any = { - enabled: true, - url, - typebot, - triggerType, - }; - - if (triggerType === 'keyword') { - const triggerOperator = this.getNodeParameter('triggerOperator', 0) as string; - const triggerValue = this.getNodeParameter('triggerValue', 0) as string; - body.triggerOperator = triggerOperator; - body.triggerValue = triggerValue; - } - - // Campos adicionais - body.keywordFinish = this.getNodeParameter('keywordFinish', 0) || ''; - body.delayMessage = this.getNodeParameter('delayMessage', 0) || 1000; - body.unknownMessage = this.getNodeParameter('unknownMessage', 0) || 'Mensagem não reconhecida'; - body.listeningFromMe = this.getNodeParameter('listeningFromMe', 0) || false; - body.stopBotFromMe = this.getNodeParameter('stopBotFromMe', 0) || false; - body.keepOpen = this.getNodeParameter('keepOpen', 0) || false; - body.debounceTime = this.getNodeParameter('debounceTime', 0) || 0; - - options = { - method: 'PUT' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/typebot/update/${typebotId}/${instanceName}`, - body, - json: true, - }; - } else if (resourceForTypebot === 'deleteTypebot') { - const typebotId = this.getNodeParameter('typebotId', 0) as string; - - options = { - method: 'DELETE' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/typebot/delete/${typebotId}/${instanceName}`, - json: true, - }; - } else if (resourceForTypebot === 'startTypebot') { - const url = this.getNodeParameter('url', 0) as string; - const typebot = this.getNodeParameter('typebot', 0) as string; - const remoteJid = this.getNodeParameter('remoteJid', 0) as string; - const startSession = this.getNodeParameter('startSession', 0) as boolean; - - const body: any = { - url, - typebot, - remoteJid, - startSession, - }; - - const variablesDisplay = this.getNodeParameter('variables_display', 0) as { metadataValues: { name: string; value: string }[] }; - if (variablesDisplay.metadataValues.length > 0) { - body.variables = variablesDisplay.metadataValues.map(variable => ({ - name: variable.name, - value: variable.value, - })); - } - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/typebot/start/${instanceName}`, - body, - json: true, - }; - } else if (resourceForTypebot === 'fetchSessionsTypebot') { - const typebotId = this.getNodeParameter('typebotId', 0) as string; - - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/typebot/fetchSessions/${typebotId}/${instanceName}`, - json: true, - }; - } else if (resourceForTypebot === 'changeStatusTypebot') { - const remoteJid = this.getNodeParameter('remoteJid', 0) as string; - const status = this.getNodeParameter('status', 0) as string; - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/typebot/changeStatus/${instanceName}`, - body: { - remoteJid, - status, - }, - json: true, - }; - } else { - // console.error('Operação de Typebot não reconhecida:', resourceForTypebot); // Adiciona log no console - throw new NodeApiError(this.getNode(), { - message: 'Erro na requisição.', - description: `Verifique se você preencheu todos os campos... Segue o erro: ${resourceForTypebot}.`, - }); - } - - responseData = await this.helpers.request(options); - } - - //EvolutionBot - // Definir/Buscar Evolution Bot - if (resource === 'integrations-api' && operation === 'evolutionBot') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - - const instanceName = this.getNodeParameter('instanceName', 0); - const resourceForEvolutionBot = this.getNodeParameter('resourceForEvolutionBot', 0); - - let options: IRequestOptions | undefined; - - if (resourceForEvolutionBot === 'createEvolutionBot') { - const apiUrl = this.getNodeParameter('apiUrl', 0) as string; - const apiKeyBot = this.getNodeParameter('apiKeyBot', 0) as string; - const triggerType = this.getNodeParameter('triggerType', 0) as string; - - const body: any = { - enabled: true, - apiUrl, - 'apiKey': apiKeyBot, - triggerType, - }; - - if (triggerType === 'keyword') { - const triggerOperator = this.getNodeParameter('triggerOperator', 0) as string; - const triggerValue = this.getNodeParameter('triggerValue', 0) as string; - body.triggerOperator = triggerOperator; - body.triggerValue = triggerValue; - } - - // Campos adicionais - body.keywordFinish = this.getNodeParameter('keywordFinish', 0) || ''; - body.delayMessage = this.getNodeParameter('delayMessage', 0) || 1000; - body.unknownMessage = this.getNodeParameter('unknownMessage', 0) || 'Mensagem não reconhecida'; - body.listeningFromMe = this.getNodeParameter('listeningFromMe', 0) || false; - body.stopBotFromMe = this.getNodeParameter('stopBotFromMe', 0) || false; - body.keepOpen = this.getNodeParameter('keepOpen', 0) || false; - body.debounceTime = this.getNodeParameter('debounceTime', 0) || 0; - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/evolutionBot/create/${instanceName}`, - body, - json: true, - }; - } else if (resourceForEvolutionBot === 'findEvolutionBot') { - const evolutionBotId = this.getNodeParameter('evolutionBotId', 0) as string; - - if (evolutionBotId) { - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/evolutionBot/fetch/${evolutionBotId}/${instanceName}`, - json: true, - }; - } else { - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/evolutionBot/find/${instanceName}`, - json: true, - }; - } - } else if (resourceForEvolutionBot === 'updateEvolutionBot') { - const evolutionBotId = this.getNodeParameter('evolutionBotId', 0) as string; - const apiUrl = this.getNodeParameter('apiUrl', 0) as string; - const apiKeyBot = this.getNodeParameter('apiKeyBot', 0) as string; - const triggerType = this.getNodeParameter('triggerType', 0) as string; - - const body: any = { - enabled: true, - apiUrl, - 'apiKey': apiKeyBot, - triggerType, - }; - - if (triggerType === 'keyword') { - const triggerOperator = this.getNodeParameter('triggerOperator', 0) as string; - const triggerValue = this.getNodeParameter('triggerValue', 0) as string; - body.triggerOperator = triggerOperator; - body.triggerValue = triggerValue; - } - - // Campos adicionais - body.keywordFinish = this.getNodeParameter('keywordFinish', 0) || ''; - body.delayMessage = this.getNodeParameter('delayMessage', 0) || 1000; - body.unknownMessage = this.getNodeParameter('unknownMessage', 0) || 'Mensagem não reconhecida'; - body.listeningFromMe = this.getNodeParameter('listeningFromMe', 0) || false; - body.stopBotFromMe = this.getNodeParameter('stopBotFromMe', 0) || false; - body.keepOpen = this.getNodeParameter('keepOpen', 0) || false; - body.debounceTime = this.getNodeParameter('debounceTime', 0) || 0; - - options = { - method: 'PUT' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/evolutionBot/update/${evolutionBotId}/${instanceName}`, - body, - json: true, - }; - } else if (resourceForEvolutionBot === 'deleteEvolutionBot') { - const evolutionBotId = this.getNodeParameter('evolutionBotId', 0) as string; - - options = { - method: 'DELETE' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/evolutionBot/delete/${evolutionBotId}/${instanceName}`, - json: true, - }; - } else if (resourceForEvolutionBot === 'fetchSessionsEvolutionBot') { - const evolutionBotId = this.getNodeParameter('evolutionBotId', 0) as string; - - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/evolutionBot/fetchSessions/${evolutionBotId}/${instanceName}`, - json: true, - }; - } else if (resourceForEvolutionBot === 'changeStatusEvolutionBot') { - const remoteJid = this.getNodeParameter('remoteJid', 0) as string; - const status = this.getNodeParameter('status', 0) as string; - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/evolutionBot/changeStatus/${instanceName}`, - body: { - remoteJid, - status, - }, - json: true, - }; - } else { - throw new NodeApiError(this.getNode(), { - message: 'Operação de Evolution Bot não reconhecida.', - description: 'A operação solicitada não é válida para o recurso de Evolution Bot.', - }); - } - - if (options) { // Verifique se options foi inicializado - responseData = await this.helpers.request(options); - } else { - throw new NodeApiError(this.getNode(), { - message: 'Nenhuma opção de requisição foi definida.', - description: 'Verifique a operação solicitada.', - }); - } - } - - // Dify - if (resource === 'integrations-api' && operation === 'difyBot') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - - const instanceName = this.getNodeParameter('instanceName', 0); - const resourceForDifyBot = this.getNodeParameter('resourceForDifyBot', 0); - - let options: IRequestOptions | undefined; - - if (resourceForDifyBot === 'createDify') { - const botType = this.getNodeParameter('botType', 0) as string; - const apiUrl = this.getNodeParameter('apiUrl', 0) as string; - const apiKeyBot = this.getNodeParameter('apiKeyBot', 0) as string; - const triggerType = this.getNodeParameter('triggerType', 0) as string; - - const body: any = { - enabled: true, - botType, - apiUrl, - apiKey: apiKeyBot, - triggerType, - }; - - if (triggerType === 'keyword') { - const triggerOperator = this.getNodeParameter('triggerOperator', 0) as string; - const triggerValue = this.getNodeParameter('triggerValue', 0) as string; - body.triggerOperator = triggerOperator; - body.triggerValue = triggerValue; - } - - // Campos adicionais - body.keywordFinish = this.getNodeParameter('keywordFinish', 0) || ''; - body.delayMessage = this.getNodeParameter('delayMessage', 0) || 1000; - body.unknownMessage = this.getNodeParameter('unknownMessage', 0) || 'Mensagem não reconhecida'; - body.listeningFromMe = this.getNodeParameter('listeningFromMe', 0) || false; - body.stopBotFromMe = this.getNodeParameter('stopBotFromMe', 0) || false; - body.keepOpen = this.getNodeParameter('keepOpen', 0) || false; - body.debounceTime = this.getNodeParameter('debounceTime', 0) || 0; - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/dify/create/${instanceName}`, - body, - json: true, - }; - } else if (resourceForDifyBot === 'findDify') { - const difyBotId = this.getNodeParameter('difyBotId', 0) as string; - - if (difyBotId) { - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/dify/fetch/${difyBotId}/${instanceName}`, - json: true, - }; - } else { - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/dify/find/${instanceName}`, - json: true, - }; - } - } else if (resourceForDifyBot === 'updateDify') { - const difyBotId = this.getNodeParameter('difyBotId', 0) as string; - const botType = this.getNodeParameter('botType', 0) as string; - const apiUrl = this.getNodeParameter('apiUrl', 0) as string; - const apiKeyBot = this.getNodeParameter('apiKeyBot', 0) as string; - const triggerType = this.getNodeParameter('triggerType', 0) as string; - - const body: any = { - enabled: true, - botType, - apiUrl, - apiKey: apiKeyBot, - triggerType, - }; - - if (triggerType === 'keyword') { - const triggerOperator = this.getNodeParameter('triggerOperator', 0) as string; - const triggerValue = this.getNodeParameter('triggerValue', 0) as string; - body.triggerOperator = triggerOperator; - body.triggerValue = triggerValue; - } - - // Campos adicionais - body.keywordFinish = this.getNodeParameter('keywordFinish', 0) || ''; - body.delayMessage = this.getNodeParameter('delayMessage', 0) || 1000; - body.unknownMessage = this.getNodeParameter('unknownMessage', 0) || 'Mensagem não reconhecida'; - body.listeningFromMe = this.getNodeParameter('listeningFromMe', 0) || false; - body.stopBotFromMe = this.getNodeParameter('stopBotFromMe', 0) || false; - body.keepOpen = this.getNodeParameter('keepOpen', 0) || false; - body.debounceTime = this.getNodeParameter('debounceTime', 0) || 0; - - options = { - method: 'PUT' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/dify/update/${difyBotId}/${instanceName}`, - body, - json: true, - }; - } else if (resourceForDifyBot === 'deleteDify') { - const difyBotId = this.getNodeParameter('difyBotId', 0) as string; - - options = { - method: 'DELETE' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/dify/delete/${difyBotId}/${instanceName}`, - json: true, - }; - } else if (resourceForDifyBot === 'fetchSessionsDify') { - const difyBotId = this.getNodeParameter('difyBotId', 0) as string; - - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/dify/fetchSessions/${difyBotId}/${instanceName}`, - json: true, - }; - } else if (resourceForDifyBot === 'changeStatusDify') { - const remoteJid = this.getNodeParameter('remoteJid', 0) as string; - const status = this.getNodeParameter('status', 0) as string; - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/dify/changeStatus/${instanceName}`, - body: { - remoteJid, - status, - }, - json: true, - }; - } else { - throw new NodeApiError(this.getNode(), { - message: 'Operação de Dify não reconhecida.', - description: 'A operação solicitada não é válida para o recurso de Dify.', - }); - } - - if (options) { - responseData = await this.helpers.request(options); - } else { - throw new NodeApiError(this.getNode(), { - message: 'Nenhuma opção de requisição foi definida.', - description: 'Verifique a operação solicitada.', - }); - } - } - - // Flowise - if (resource === 'integrations-api' && operation === 'flowiseBot') { - const credentials = await this.getCredentials('httpbinApi'); - const serverUrl = credentials['server-url']; - const apiKey = credentials.apikey; - - const instanceName = this.getNodeParameter('instanceName', 0); - const resourceForFlowiseBot = this.getNodeParameter('resourceForFlowiseBot', 0); - - let options: IRequestOptions | undefined; - - if (resourceForFlowiseBot === 'createFlowise') { - const apiUrl = this.getNodeParameter('apiUrl', 0) as string; - const apiKeyBot = this.getNodeParameter('apiKeyBot', 0) as string; - const triggerType = this.getNodeParameter('triggerType', 0) as string; - - const body: any = { - enabled: true, - apiUrl, - apiKey: apiKeyBot, - triggerType, - }; - - if (triggerType === 'keyword') { - const triggerOperator = this.getNodeParameter('triggerOperator', 0) as string; - const triggerValue = this.getNodeParameter('triggerValue', 0) as string; - body.triggerOperator = triggerOperator; - body.triggerValue = triggerValue; - } - - // Campos adicionais - body.keywordFinish = this.getNodeParameter('keywordFinish', 0) || ''; - body.delayMessage = this.getNodeParameter('delayMessage', 0) || 1000; - body.unknownMessage = this.getNodeParameter('unknownMessage', 0) || 'Mensagem não reconhecida'; - body.listeningFromMe = this.getNodeParameter('listeningFromMe', 0) || false; - body.stopBotFromMe = this.getNodeParameter('stopBotFromMe', 0) || false; - body.keepOpen = this.getNodeParameter('keepOpen', 0) || false; - body.debounceTime = this.getNodeParameter('debounceTime', 0) || 0; - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/flowise/create/${instanceName}`, - body, - json: true, - }; - } else if (resourceForFlowiseBot === 'findFlowise') { - const flowiseBotId = this.getNodeParameter('flowiseBotId', 0) as string; - - if (flowiseBotId) { - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/flowise/fetch/${flowiseBotId}/${instanceName}`, - json: true, - }; - } else { - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/flowise/find/${instanceName}`, - json: true, - }; - } - } else if (resourceForFlowiseBot === 'updateFlowise') { - const flowiseBotId = this.getNodeParameter('flowiseBotId', 0) as string; - const apiUrl = this.getNodeParameter('apiUrl', 0) as string; - const apiKeyBot = this.getNodeParameter('apiKeyBot', 0) as string; - const triggerType = this.getNodeParameter('triggerType', 0) as string; - - const body: any = { - enabled: true, - apiUrl, - apiKey: apiKeyBot, - triggerType, - }; - - if (triggerType === 'keyword') { - const triggerOperator = this.getNodeParameter('triggerOperator', 0) as string; - const triggerValue = this.getNodeParameter('triggerValue', 0) as string; - body.triggerOperator = triggerOperator; - body.triggerValue = triggerValue; - } - - // Campos adicionais - body.keywordFinish = this.getNodeParameter('keywordFinish', 0) || ''; - body.delayMessage = this.getNodeParameter('delayMessage', 0) || 1000; - body.unknownMessage = this.getNodeParameter('unknownMessage', 0) || 'Mensagem não reconhecida'; - body.listeningFromMe = this.getNodeParameter('listeningFromMe', 0) || false; - body.stopBotFromMe = this.getNodeParameter('stopBotFromMe', 0) || false; - body.keepOpen = this.getNodeParameter('keepOpen', 0) || false; - body.debounceTime = this.getNodeParameter('debounceTime', 0) || 0; - - options = { - method: 'PUT' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/flowise/update/${flowiseBotId}/${instanceName}`, - body, - json: true, - }; - } else if (resourceForFlowiseBot === 'deleteFlowise') { - const flowiseBotId = this.getNodeParameter('flowiseBotId', 0) as string; - - options = { - method: 'DELETE' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/flowise/delete/${flowiseBotId}/${instanceName}`, - json: true, - }; - } else if (resourceForFlowiseBot === 'fetchSessionsFlowise') { - const flowiseBotId = this.getNodeParameter('flowiseBotId', 0) as string; - - options = { - method: 'GET' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/flowise/fetchSessions/${flowiseBotId}/${instanceName}`, - json: true, - }; - } else if (resourceForFlowiseBot === 'changeStatusFlowise') { - const remoteJid = this.getNodeParameter('remoteJid', 0) as string; - const status = this.getNodeParameter('status', 0) as string; - - options = { - method: 'POST' as IHttpRequestMethods, - headers: { - apikey: apiKey, - }, - uri: `${serverUrl}/flowise/changeStatus/${instanceName}`, - body: { - remoteJid, - status, - }, - json: true, - }; - } else { - throw new NodeApiError(this.getNode(), { - message: 'Operação de Flowise não reconhecida.', - description: 'A operação solicitada não é válida para o recurso de Flowise.', - }); - } - - if (options) { - responseData = await this.helpers.request(options); - } else { - throw new NodeApiError(this.getNode(), { - message: 'Nenhuma opção de requisição foi definida.', - description: 'Verifique a operação solicitada.', - }); - } - } - - - // Retornar apenas o JSON - return [this.helpers.returnJsonArray(responseData)]; - } -} diff --git a/nodes/HttpBin/HttpVerbDescription.ts b/nodes/HttpBin/HttpVerbDescription.ts deleted file mode 100644 index 0686770..0000000 --- a/nodes/HttpBin/HttpVerbDescription.ts +++ /dev/null @@ -1,4006 +0,0 @@ -import { INodeProperties } from 'n8n-workflow'; -// Observação deste documento: -// Este documento serve para a Definição de Operações que devem aparecer -// em cada Resource, incluindo a criação de novos campos para cada Operation - - -// ██████╗ ██████╗ ███████╗██████╗ █████╗ ████████╗██╗ ██████╗ ███╗ ██╗ -// ██╔═══██╗██╔══██╗██╔════╝██╔══██╗██╔══██╗╚══██╔══╝██║██╔═══██╗████╗ ██║ -// ██║ ██║██████╔╝█████╗ ██████╔╝███████║ ██║ ██║██║ ██║██╔██╗ ██║ -// ██║ ██║██╔═══╝ ██╔══╝ ██╔══██╗██╔══██║ ██║ ██║██║ ██║██║╚██╗██║ -// ╚██████╔╝██║ ███████╗██║ ██║██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║ -// ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ - -// Operation = Funções/Opções de cada Resource (Instancia, Mensagen, Integração, Conversa, Perfil e Grupo) - -// "O que cada Resource vai apresentar ao ser selecionado" - -// Exemplo: -// Instancias: -// • Criar instncia; -// • Criar instancia com proxy; -// • Conectar instancia; - -export const httpVerbOperations: INodeProperties[] = [ - -// Cada Resource adicionada tera um desse para listar as opções/funções de cada Resource -// Opções da instances-api (Instancias) - { - displayName: 'Função', - name: 'operation', - type: 'options', - noDataExpression: true, - displayOptions: { - show: { - resource: ['instances-api'], // Value do Resource - }, - }, - - // Opções que serão vinculadas a Operação "Instancia" - options: [ - - // Opção = Criar instancia - { - // Create Instance Basic - name: 'Criar Instancia', - action: 'Criar Instancia', - description: 'Cria uma nova Instancia', - value: 'instance-basic', - }, - - // Opção = Conectar Instância - { - // Instance Connect - name: 'Conectar Instancia', - action: 'Conectar Instancia', - description: 'Gera a conexão de uma Instancia (QR ou Base64)', - value: 'instance-connect', - }, - - // Opção = Buscar Instancia - { - // Fetch Instances - name: 'Buscar Instancia', - action: 'Buscar Instancia', - description: 'Busca e lista as Instancias criadas', - value: 'fetch-instances', - }, - - // Opção = Definir Comportamento da instancia - { - name: 'Definir Comportamento', - action: 'Definir Comportamento', - description: 'Define o comportamento da instancia', - value: 'instanceSettings', - }, - - // Opção = Definir presença - { - // Set Presence - name: 'Definir Presença', - action: 'Definir Presença', - description: 'Define a presença na instancia', - value: 'setPresence', - }, - - // Opção = Definit Proxy - { - // Set/find Proxy - name: 'Definir/Buscar Proxy', - action: 'Proxy', - description: 'Define um Proxy na instancia', - value: 'proxy', - }, - - // Opção = Reiniciar instancia - { - // Restart Instance - name: 'Reiniciar Instancia', - action: 'Reiniciar Instancia', - description: 'Reinicia o socket da Instancia', - value: 'restart-instance', - }, - - // Opção = Desconectar instancia - { - // Logout Instance - name: 'Desconectar Instancia', - action: 'Desconectar Instancia', - description: 'Desconecta o WhatsApp da Instancia', - value: 'logout-instance', - }, - - // Opção = Deletar instancia - { - // Delete Instance - name: 'Deletar Instancia', - action: 'Deletar Instancia', - description: 'Deleta uma Instancia', - value: 'delete-instance', - }, - - - ], - // Definindo como padrão a opção "Criar Instancia" - default: 'instance-basic', - }, - - -// ===== Espaço para dividir melhor uma coisa da outra ===== // -// ===== Espaço para dividir melhor uma coisa da outra ===== // -// ===== Espaço para dividir melhor uma coisa da outra ===== // - - - // Opções da messages-api (Mensagens) - { - displayName: 'Operation', - name: 'operation', - type: 'options', - noDataExpression: true, - displayOptions: { - show: { - resource: ['messages-api'], // Value do Resource - }, - }, - options: [ - - // Opção = Enviar mensagem de Texto - { - // Send Text - name: 'Enviar Texto', - action: 'Enviar Texto', - description: 'Envia mensagem de Texto', - value: 'sendText', - }, - - // Opção = Enviar Imagem - { - // Send Media - name: 'Enviar Imagem', - action: 'Enviar Imagem', - description: 'Envia mensagem de Imagem', - value: 'sendImage', - }, - - // Opção = Enviar Video - { - // Send Media - name: 'Enviar Video', - value: 'sendVideo', - description: 'Enviar mensagem de Video', - action: 'Enviar Video', - }, - - // Opção = Enviar Audio - { - // Send Narrated Audio - name: 'Enviar Audio', - action: 'Enviar Audio', - description: 'Enviar mensagem de Audio', - value: 'sendAudio', - }, - - // Opção = Enviar Documento - { - // Send Media - name: 'Enviar Documento', - action: 'Enviar Documento', - description: 'Enviar mensagem de Video', - value: 'sendDocumento', - }, - - // Opção = Enviar Enquete - { - // Send Poll - name: 'Enviar Enquete', - action: 'Enviar Enquete', - description: 'Envia uma Enquete de até 12 opções', - value: 'sendPoll', - }, - - // Opção = Enviar Status - { - // Send Status/Stories - name: 'Enviar Status', - action: 'Enviar Status', - description: 'Publicar um Status/Stories', - value: 'sendStories', - }, - - ], - // Definindo como padrão a opção "Enviar Texto" - default: 'sendText', - }, - -// ===== Espaço para dividir melhor uma coisa da outra ===== // -// ===== Espaço para dividir melhor uma coisa da outra ===== // -// ===== Espaço para dividir melhor uma coisa da outra ===== // - - - // Opções da events-api (Integração) - { - displayName: 'Operation', - name: 'operation', - type: 'options', - noDataExpression: true, - displayOptions: { - show: { - resource: ['events-api'], // Value do Resource - }, - }, - options: [ - - // Opção = Enviar mensagem de Texto - { - // Set/find Webhook - name: 'Webhook', - action: 'Webhook', - description: 'Define/Busca integração com Webhook', - value: 'webhook', - }, - { - // Set/find Rabbitmq - name: 'RabbitMQ', - action: 'Rabbitmq', - description: 'Define/Busca integração com RabbitMQ', - value: 'rabbitMQ', - }, - - ], - // Definindo como padrão a opção "Enviar Texto" - default: 'webhook', - }, - -// ===== Espaço para dividir melhor uma coisa da outra ===== // -// ===== Espaço para dividir melhor uma coisa da outra ===== // -// ===== Espaço para dividir melhor uma coisa da outra ===== // - - - // Opções da integrations-api (Integração) - { - displayName: 'Operation', - name: 'operation', - type: 'options', - noDataExpression: true, - displayOptions: { - show: { - resource: ['integrations-api'], // Value do Resource - }, - }, - options: [ - { - // Set/find Chatwoot - name: 'Chatwoot', - action: 'Chatwoot', - description: 'Define/Busca integração com Chatwoot', - value: 'chatwoot', - }, - { - // Create/find/fetch/Update/Delete/Start/Change Status/Fetch Sessions da Evolution Bot - name: 'Evolution Bot', - action: 'Evolution bot', - description: 'Controla a integração com Evolution Bot', - value: 'evolutionBot', - }, - { - // Create/find/fetch/Update/Delete/Start/Change Status/Fetch Sessions do Typebot - name: 'Typebot', - action: 'Typebot', - description: 'Controla a integração com Typebot', - value: 'typebot', - }, - { - // Create/find/fetch/Update/Delete/Start/Change Status/Fetch Sessions da Dify - name: 'Dify', - action: 'Dify', - description: 'Controla a integração com Dify', - value: 'difyBot', - }, - { - // Create/find/fetch/Update/Delete/Start/Change Status/Fetch Sessions da Dify - name: 'Flowise', - action: 'Flowise', - description: 'Controla a integração com Flowise', - value: 'flowiseBot', - }, - - ], - // Definindo como padrão a opção "Enviar Texto" - default: 'chatwoot', - }, - -]; - - -// ===== Espaço para dividir melhor uma coisa da outra ===== // -// ===== Espaço para dividir melhor uma coisa da outra ===== // -// ===== Espaço para dividir melhor uma coisa da outra ===== // - - -// ███████╗██╗ ███████╗███╗ ███╗███████╗███╗ ██╗████████╗███████╗ -// ██╔════╝██║ ██╔════╝████╗ ████║██╔════╝████╗ ██║╚══██╔══╝██╔════╝ -// █████╗ ██║ █████╗ ██╔████╔██║█████╗ ██╔██╗ ██║ ██║ ███████╗ -// ██╔══╝ ██║ ██╔══╝ ██║╚██╔╝██║██╔══╝ ██║╚██╗██║ ██║ ╚════██║ -// ███████╗███████╗███████╗██║ ╚═╝ ██║███████╗██║ ╚████║ ██║ ███████║ -// ╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝ - -// Elements = Os campos que aparecem em cada Operation - -// "Cada Operation (ex: Enviar mensagem de Texto) tem campos que precisam ser preenchido para fazer uma requisição" - -// Exemplo: -// Enviar Mensagem de Texto: -// • Instancia que vai enviar; -// • RemoteJid do destinatario; -// • Mensagem que vai ser enviada; - -// Campos das instancias -const instanceOperation: INodeProperties[] = [ - - // Campos = Criar Instancia - { - displayName: 'Nome da Instância', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome para a instância', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instance-basic'], - }, - }, - }, - { - displayName: 'Apikey para instancia', - name: 'token', - type: 'string', - typeOptions: { - password: true, - }, - default: '', - required: false, - description: 'Opicional: Digite um Token para a instancia', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instance-basic'], - }, - }, - }, - { - displayName: 'Número do WhatsApp', - name: 'number', - type: 'string', - default: '', - required: false, - description: 'Opicional: Numero que vai ser conectado na instancia, para receber o Código de pareamento', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instance-basic'], - }, - }, - }, - { - displayName: 'Opções', - name: 'options_Create_instance', - type: 'collection', - placeholder: 'Adicionar Campo', - default: {}, - options: [ - { - displayName: 'Comportamento', - name: 'instanceSettings', - type: 'fixedCollection', - typeOptions: { - multipleValues: false, - }, - default: { settings: {} }, - options: [ - { - displayName: 'Comportamento Da Instancia', - name: 'settings', - values: [ - { - displayName: 'Rejeitar Ligações', - name: 'rejectCall', - type: 'boolean', - default: false, - description: 'Whether to automatically reject incoming calls', - }, - { - displayName: 'Mensagem Ao Rejeitar', - name: 'msgCall', - type: 'string', - default: '', - description: 'Whether to send a message after rejecting a call, and if so, what message', - }, - { - displayName: 'Ignorar Grupos', - name: 'groupsIgnore', - type: 'boolean', - default: false, - description: 'Whether to ignore messages from groups', - }, - { - displayName: 'Sempre Online', - name: 'alwaysOnline', - type: 'boolean', - default: false, - description: 'Whether to keep the status always set to Online', - }, - { - displayName: 'Ler Mensagens', - name: 'readMessages', - type: 'boolean', - default: false, - description: 'Whether to automatically mark messages as read', - }, - { - displayName: 'Ler Status', - name: 'readStatus', - type: 'boolean', - default: false, - description: 'Whether to allow the API to view the Status of added contacts', - }, - { - displayName: 'Sincronizar Histórico', - name: 'syncFullHistory', - type: 'boolean', - default: false, - description: 'Whether to synchronize the full message history with the API', - }, - ], - }, - ], - description: 'Comportamento da instância', - }, - { - displayName: 'Proxy', - name: 'proxy', - type: 'fixedCollection', - typeOptions: { - multipleValues: false, - }, - default: { settings: {} }, - options: [ - { - displayName: 'Configurações Do Proxy', - name: 'proxySettings', - values: [ - { - displayName: 'Host Do Proxy', - name: 'proxyHost', - type: 'string', - default: '', - description: 'Digite o host do proxy', - }, - { - displayName: 'Porta Do Proxy', - name: 'proxyPort', - type: 'string', - default: '1234', - description: 'Digite a porta do proxy', - }, - { - displayName: 'Protocolo Do Proxy', - name: 'proxyProtocol', - type: 'options', - options: [ - { - name: 'HTTP', - value: 'http', - }, - { - name: 'HTTPS', - value: 'https', - }, - ], - default: 'http', - description: 'Selecione o protocolo do proxy', - }, - { - displayName: 'Usuário Do Proxy', - name: 'proxyUsername', - type: 'string', - default: '', - description: 'Digite o usuário do proxy', - }, - { - displayName: 'Senha Do Proxy', - name: 'proxyPassword', - type: 'string', - typeOptions: { - password: true, - }, - default: '', - description: 'Digite a senha do proxy', - }, - ], - }, - ], - description: 'Configurações do proxy', - }, - - { - displayName: 'Webhook', - name: 'webhook', - type: 'fixedCollection', - typeOptions: { - multipleValues: false, - }, - default: { settings: {} }, - options: [ - { - displayName: 'Configurações Do Webhook', - name: 'webhookSettings', - values: [ - { - displayName: 'Url do Webhook', - name: 'webhookUrl', - type: 'string', - default: '', - description: 'Digite a Url que vai receber os eventos do Webhook', - }, - { - displayName: 'Webhook por Eventos', - name: 'webhookByEvents', - type: 'boolean', - default: false, - description: 'Whether to create a route for each event by appending the event name to the end of the URL', // Atualizado - }, - { - displayName: 'Base64 no Webhook', - name: 'webhookBase64', - type: 'boolean', - default: false, - description: 'Whether to send media data in base64 format in the webhook', // Atualizado - }, - { - displayName: 'Eventos', - name: 'webhookEvents', - type: 'multiOptions', - default: [], // Adicionado para resolver o erro - options: [ - { - name: 'CALL', - value: 'CALL', - }, - { - name: 'CHATS_DELETE', - value: 'CHATS_DELETE', - }, - { - name: 'CHATS_SET', - value: 'CHATS_SET', - }, - { - name: 'CHATS_UPDATE', - value: 'CHATS_UPDATE', - }, - { - name: 'CHATS_UPSERT', - value: 'CHATS_UPSERT', - }, - { - name: 'CONNECTION_UPDATE', - value: 'CONNECTION_UPDATE', - }, - { - name: 'CONTACTS_SET', - value: 'CONTACTS_SET', - }, - { - name: 'CONTACTS_UPDATE', - value: 'CONTACTS_UPDATE', - }, - { - name: 'CONTACTS_UPSERT', - value: 'CONTACTS_UPSERT', - }, - { - name: 'GROUP_PARTICIPANTS_UPDATE', - value: 'GROUP_PARTICIPANTS_UPDATE', - }, - { - name: 'GROUP_UPDATE', - value: 'GROUP_UPDATE', - }, - { - name: 'GROUPS_UPSERT', - value: 'GROUPS_UPSERT', - }, - { - name: 'LABELS_ASSOCIATION', - value: 'LABELS_ASSOCIATION', - }, - { - name: 'LABELS_EDIT', - value: 'LABELS_EDIT', - }, - { - name: 'MESSAGES_DELETE', - value: 'MESSAGES_DELETE', - }, - { - name: 'MESSAGES_SET', - value: 'MESSAGES_SET', - }, - { - name: 'MESSAGES_UPDATE', - value: 'MESSAGES_UPDATE', - }, - { - name: 'MESSAGES_UPSERT', - value: 'MESSAGES_UPSERT', - }, - { - name: 'PRESENCE_UPDATE', - value: 'PRESENCE_UPDATE', - }, - { - name: 'QRCODE_UPDATED', - value: 'QRCODE_UPDATED', - }, - { - name: 'SEND_MESSAGE', - value: 'SEND_MESSAGE', - }, - { - name: 'TYPEBOT_CHANGE_STATUS', - value: 'TYPEBOT_CHANGE_STATUS', - }, - { - name: 'TYPEBOT_START', - value: 'TYPEBOT_START', - }, - ] - }, - ], - }, - ], - description: 'Os eventos a serem monitorados', - }, - - { - displayName: 'RabbitMQ', - name: 'rabbitmq', - type: 'fixedCollection', - typeOptions: { - multipleValues: false, - }, - default: { settings: {} }, - options: [ - { - displayName: 'Configurações Do RabbitMQ', - name: 'rabbitmqSettings', - values: [ - { - displayName: 'Ativa ou desativa o RabbitMQ', - name: 'rabbitmqEnabled', - type: 'boolean', - default: false, - description: 'Whether to send media data in base64 format in the RabbitMQ', // Atualizado - }, - { - displayName: 'Eventos', - name: 'rabbitmqEvents', - type: 'multiOptions', - default: [], // Adicionado para resolver o erro - options: [ - { - name: 'CALL', - value: 'CALL', - }, - { - name: 'CHATS_DELETE', - value: 'CHATS_DELETE', - }, - { - name: 'CHATS_SET', - value: 'CHATS_SET', - }, - { - name: 'CHATS_UPDATE', - value: 'CHATS_UPDATE', - }, - { - name: 'CHATS_UPSERT', - value: 'CHATS_UPSERT', - }, - { - name: 'CONNECTION_UPDATE', - value: 'CONNECTION_UPDATE', - }, - { - name: 'CONTACTS_SET', - value: 'CONTACTS_SET', - }, - { - name: 'CONTACTS_UPDATE', - value: 'CONTACTS_UPDATE', - }, - { - name: 'CONTACTS_UPSERT', - value: 'CONTACTS_UPSERT', - }, - { - name: 'GROUP_PARTICIPANTS_UPDATE', - value: 'GROUP_PARTICIPANTS_UPDATE', - }, - { - name: 'GROUP_UPDATE', - value: 'GROUP_UPDATE', - }, - { - name: 'GROUPS_UPSERT', - value: 'GROUPS_UPSERT', - }, - { - name: 'LABELS_ASSOCIATION', - value: 'LABELS_ASSOCIATION', - }, - { - name: 'LABELS_EDIT', - value: 'LABELS_EDIT', - }, - { - name: 'MESSAGES_DELETE', - value: 'MESSAGES_DELETE', - }, - { - name: 'MESSAGES_SET', - value: 'MESSAGES_SET', - }, - { - name: 'MESSAGES_UPDATE', - value: 'MESSAGES_UPDATE', - }, - { - name: 'MESSAGES_UPSERT', - value: 'MESSAGES_UPSERT', - }, - { - name: 'PRESENCE_UPDATE', - value: 'PRESENCE_UPDATE', - }, - { - name: 'QRCODE_UPDATED', - value: 'QRCODE_UPDATED', - }, - { - name: 'SEND_MESSAGE', - value: 'SEND_MESSAGE', - }, - { - name: 'TYPEBOT_CHANGE_STATUS', - value: 'TYPEBOT_CHANGE_STATUS', - }, - { - name: 'TYPEBOT_START', - value: 'TYPEBOT_START', - }, - ] - }, - ], - }, - ], - description: 'Os eventos a serem monitorados', - }, - - { - displayName: 'Chatwoot', - name: 'chatwoot', - type: 'fixedCollection', - typeOptions: { - multipleValues: false, - }, - default: { settings: {} }, - options: [ - { - displayName: 'Configurações Do Chatwoot', - name: 'chatwootSettings', - values: [ - { - displayName: 'ID Da Conta Do Chatwoot', - name: 'chatwootAccountId', - type: 'string', - default: '', - description: 'Digite o ID da conta do Chatwoot', - }, - { - displayName: 'Token De Admin Do Chatwoot', - name: 'chatwootToken', - type: 'string', - typeOptions: { - password: true, - }, - default: '', - description: 'Digite o token de admin do Chatwoot', - }, - { - displayName: 'Link Do Chatwoot', - name: 'chatwootUrl', - type: 'string', - default: '', - description: 'Digite o link do Chatwoot', - }, - { - displayName: 'Assinatura Do Agente Do Chatwoot', - name: 'chatwootSignMsg', - type: 'boolean', - default: false, - description: 'Whether to enable or disable the Chatwoot agent signature', - }, - { - displayName: 'Reabrir Mensagens No Chatwoot', - name: 'chatwootReopenConversation', - type: 'boolean', - default: false, - description: 'Whether to enable or disable reopening messages in Chatwoot', - }, - { - displayName: 'Iniciar Conversas Como Pendentes No Chatwoot', - name: 'chatwootConversationPending', - type: 'boolean', - default: false, - description: 'Whether to start conversations as pending in Chatwoot', - }, - { - displayName: 'Importar Contatos Para O Chatwoot', - name: 'chatwootImportContacts', - type: 'boolean', - default: false, - description: 'Whether to import contacts to Chatwoot', - }, - { - displayName: 'Nome Da Inbox Do Chatwoot', - name: 'chatwootNameInbox', - type: 'string', - default: '', - description: 'Digite o nome da Inbox do Chatwoot', - }, - { - displayName: 'Mesclar Contatos Brasileiros No Chatwoot', - name: 'chatwootMergeBrazilContacts', - type: 'boolean', - default: false, - description: 'Whether to merge Brazilian contacts in Chatwoot', - }, - { - displayName: 'Importar Mensagens Para O Chatwoot', - name: 'chatwootImportMessages', - type: 'boolean', - default: false, - description: 'Whether to import messages to Chatwoot', - }, - { - displayName: 'Importar Mensagens De Quantos Dias Para O Chatwoot', - name: 'chatwootDaysLimitImportMessages', - type: 'number', - default: 0, - description: 'Digite o número de dias para limitar a importação de mensagens para o Chatwoot', - }, - { - displayName: 'Nome Do Contato De QRCode No Chatwoot', - name: 'chatwootOrganization', - type: 'string', - default: '', - description: 'Digite o nome do contato de QRCode no Chatwoot', - }, - { - displayName: 'Url Do Logo Para O Contato No Chatwoot', - name: 'chatwootLogo', - type: 'string', - default: 'https://github.com/user-attachments/assets/4d1e9cd6-377a-4383-820a-9a97e6cfbb63', - description: 'Digite a URL do logo para o contato no Chatwoot', - }, - ], - }, - ], - description: 'Configurações do Chatwoot', - }, - ], - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instance-basic'], - }, - }, - }, - - // Campos = Conectar Instância - { - displayName: 'Nome da Instância', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que deseja pesquisar', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instance-connect'], - }, - }, - }, - - // Campos = Buscar Instancia - { - displayName: 'Nome da Instância', - name: 'instanceName', - type: 'string', - default: '', - required: false, - description: 'Digite o nome da instância que deseja pesquisar', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['fetch-instances'], - }, - }, - }, - - // Campos = Definir Comportamento - { - displayName: 'Nome da Instância', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome para a instância', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instanceSettings'], - }, - }, - }, - { - displayName: 'Rejeitar Chamadas', - name: 'rejectCall', - type: 'boolean', - default: false, - description: 'Whether to reject calls or not.', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instanceSettings'], - }, - }, - }, - { - displayName: 'Mensagem de Chamadas', - name: 'msgCall', - type: 'string', - default: 'Não aceitamos ligações telefônicas.', - required: false, - description: 'Mensagem a ser enviada se as chamadas forem rejeitadas.', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instanceSettings'], - }, - }, - }, - { - displayName: 'Ignorar Grupos', - name: 'groupsIgnore', - type: 'boolean', - default: false, - description: 'Whether to mention them all', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instanceSettings'], - }, - }, - }, - { - displayName: 'Sempre Online', - name: 'alwaysOnline', - type: 'boolean', - default: false, - description: 'Whether the instance should always be online or not.', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instanceSettings'], - }, - }, - }, - { - displayName: 'Ler Mensagens', - name: 'readMessages', - type: 'boolean', - default: false, - description: 'Whether to mention them all', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instanceSettings'], - }, - }, - }, - { - displayName: 'Sincronizar Histórico Completo', - name: 'syncFullHistory', - type: 'boolean', - default: false, - description: 'Whether to mention them all history or not.', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instanceSettings'], - }, - }, - }, - { - displayName: 'Ler Status', - name: 'readStatus', - type: 'boolean', - default: false, - description: 'Whether to mention them all', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['instanceSettings'], - }, - }, - }, - - // Campos = Definir presença - { - displayName: 'Nome da Instancia', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai ser deletada', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['setPresence'], - }, - }, - }, - { - displayName: 'Presença', - name: 'presence', - type: 'options', - description: 'Define o status da presença na instancia', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['setPresence'], - }, - }, - options: [ - { - name: 'Disponivel', - value: 'available', - }, - { - name: 'Indisponível', - value: 'unavailable', - }, - ], - default: 'available', - }, - - // Campos = Proxy - { - displayName: 'Nome da Instancia', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar a mensagem', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['proxy'], - }, - }, - }, - - { - displayName: 'O que deseja fazer', - name: 'resourceForProxy', - type: 'options', - options: [ - { - name: 'Definir Proxy', - value: 'setProxy', - }, - { - name: 'Verificar proxy', - value: 'findProxy', - }, - ], - default: 'setProxy', - description: 'Escolha entre ativar/desativar proxy ou verificar o proxy', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['proxy'], - }, - }, - }, - { - displayName: 'Ativar proxy', - name: 'enabled', - type: 'boolean', - default: true, - description: 'Whether to enable or disable integration with proxy.', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['proxy'], - resourceForProxy: ['setProxy'], - }, - }, - }, - { - displayName: 'Host Do Proxy', - name: 'proxyHost', - type: 'string', - default: '', - required: true, - description: 'Digite o host do proxy', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['proxy'], - resourceForProxy: ['setProxy'], - }, - }, - }, - { - displayName: 'Porta Do Proxy', - name: 'proxyPort', - type: 'string', - default: '1234', - required: true, - description: 'Digite a porta do proxy', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['proxy'], - resourceForProxy: ['setProxy'], - }, - }, - }, - { - displayName: 'Protocolo Do Proxy', - name: 'proxyProtocol', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['proxy'], - resourceForProxy: ['setProxy'], - }, - }, - type: 'options', - options: [ - { - name: 'HTTP', - value: 'http', - }, - { - name: 'HTTPS', - value: 'https', - }, - ], - default: 'http', - description: 'Selecione o protocolo do proxy', - }, - { - displayName: 'Usuário Do Proxy', - name: 'proxyUsername', - type: 'string', - default: '', - required: true, - description: 'Digite o usuário do proxy', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['proxy'], - resourceForProxy: ['setProxy'], - }, - }, - }, - { - displayName: 'Senha Do Proxy', - name: 'proxyPassword', - type: 'string', - required: true, - typeOptions: { - password: true, - }, - default: '', - description: 'Digite a senha do proxy', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['proxy'], - resourceForProxy: ['setProxy'], - }, - }, - }, - - // Campos = Reiniciar instancia - { - displayName: 'Nome da Insticância', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que deseja pesquisar', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['restart-instance'], - }, - }, - }, - - - // Campos = Desconectar instancia - { - displayName: 'Nome da Insticância', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que deseja pesquisar', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['logout-instance'], - }, - }, - }, - - // Campos = Deletar instancia - { - displayName: 'Nome da Instancia', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai ser deletada', - displayOptions: { - show: { - resource: ['instances-api'], - operation: ['delete-instance'], - }, - }, - }, - -]; - -// Campo das Mensagens -const messageOperation: INodeProperties[] = [ - // Campos = Enviar mensagem de texto - { - displayName: 'Nome da Instancia', - name: 'instanceName', - type: 'string', - default: '', - required: false, - description: 'Digite o nome da instância que vai enviar a mensagem', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendText'], - }, - }, - }, - { - displayName: 'Numero do destinatario', - name: 'remoteJid', - type: 'string', - default: '', - required: true, - description: 'remoteJid do destinarario', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendText'], - }, - }, - }, - { - displayName: 'Mensagem', - name: 'messageText', - type: 'string', - default: '', - required: true, - description: 'Digite a mensagem de texto que será enviado', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendText'], - }, - }, - }, - { - displayName: 'Enviar com Marcação Fantasma?', - name: 'mentionsEveryOne', - type: 'boolean', - default: false, - description: 'Whether to mention them all', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendText'], - }, - }, - }, - - - // Campos = Enviar Imagem - { - displayName: 'Nome da Instancia', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar a mensagem', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendImage'], - }, - }, - }, - { - displayName: 'Número do Destinatário', - name: 'remoteJid', - type: 'string', - default: '', - required: true, - description: 'Número do destinatário', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendImage'], - }, - }, - }, - { - displayName: 'Imagem', - name: 'media', - type: 'string', - default: '', - required: true, - description: 'URL ou base64 da imagem', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendImage'], - }, - }, - }, - { - displayName: 'Caption', - name: 'caption', - type: 'string', - default: '', - required: false, - description: 'Texto a ser enviado junto a imagem', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendImage'], - }, - }, - }, - //{ - // displayName: 'Mimetype', - // name: 'mimetype', - // type: 'string', - // default: 'image/png', - // required: false, - // description: 'Tipo MIME da imagem', - // displayOptions: { - // show: { - // resource: ['messages-api'], - // operation: ['sendImage'], - // }, - // }, - //}, - //{ - // displayName: 'Nome do Arquivo', - // name: 'fileName', - // type: 'string', - // default: 'Imagem.png', - // required: false, - // description: 'Nome do arquivo da imagem', - // displayOptions: { - // show: { - // resource: ['messages-api'], - // operation: ['sendImage'], - // }, - // }, - //}, - { - displayName: 'Enviar com Marcação Fantasma?', - name: 'mentionsEveryOne', - type: 'boolean', - default: false, - description: 'Whether to mention them all', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendImage'], - }, - }, - }, - - - // Campos = Enviar Video - { - displayName: 'Nome da Instância', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar o vídeo', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendVideo'], - }, - }, - }, - { - displayName: 'Número do Destinatário', - name: 'remoteJid', - type: 'string', - default: '', - required: true, - description: 'Número do destinatário', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendVideo'], - }, - }, - }, - { - displayName: 'Vídeo', - name: 'media', - type: 'string', - default: '', - required: true, - description: 'URL ou base64 do vídeo', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendVideo'], - }, - }, - }, - { - displayName: 'Caption', - name: 'caption', - type: 'string', - default: '', - required: false, - description: 'Texto a ser enviado junto ao vídeo', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendVideo'], - }, - }, - }, - // { - // displayName: 'Mimetype', - // name: 'mimetype', - // type: 'string', - // default: 'video/mp4', - // required: false, - // description: 'Tipo MIME do vídeo', - // displayOptions: { - // show: { - // resource: ['messages-api'], - // operation: ['sendVideo'], - // }, - // }, - // }, - // { - // displayName: 'Nome do Arquivo', - // name: 'fileName', - // type: 'string', - // default: 'Video.mp4', - // required: false, - // description: 'Nome do arquivo do vídeo', - // displayOptions: { - // show: { - // resource: ['messages-api'], - // operation: ['sendVideo'], - // }, - // }, - // }, - { - displayName: 'Enviar com Marcação Fantasma?', - name: 'mentionsEveryOne', - type: 'boolean', - default: false, - description: 'Whether to mention them all', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendVideo'], - }, - }, - }, - - - // Campos = Enviar Audio - { - displayName: 'Nome da Instância', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar o áudio', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendAudio'], - }, - }, - }, - { - displayName: 'Número do Destinatário', - name: 'remoteJid', - type: 'string', - default: '', - required: true, - description: 'Número do destinatário', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendAudio'], - }, - }, - }, - { - displayName: 'Audio', - name: 'media', - type: 'string', - default: '', - required: true, - description: 'URL ou base64 do áudio', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendAudio'], - }, - }, - }, - { - displayName: 'Enviar com Marcação Fantasma?', - name: 'mentionsEveryOne', - type: 'boolean', - default: false, - description: 'Whether to mention them all', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendAudio'], - }, - }, - }, - - - // Campos = Enviar Documento - { - displayName: 'Nome da Instância', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar o documento', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendDocumento'], - }, - }, - }, - { - displayName: 'Número do Destinatário', - name: 'remoteJid', - type: 'string', - default: '', - required: true, - description: 'Número do destinatário', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendDocumento'], - }, - }, - }, - { - displayName: 'Documento', - name: 'media', - type: 'string', - default: '', - required: true, - description: 'URL ou base64 do documento', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendDocumento'], - }, - }, - }, - { - displayName: 'Mensagem', - name: 'caption', - type: 'string', - default: '', - required: false, - description: 'Texto a ser enviado junto ao documento', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendDocumento'], - }, - }, - }, - //{ - // displayName: 'Nome do Arquivo', - // name: 'fileName', - // type: 'string', - // default: '', - // required: false, - // description: 'Nome do arquivo do vídeo', - // displayOptions: { - // show: { - // resource: ['messages-api'], - // operation: ['sendDocumento'], - // }, - // }, - //}, - { - displayName: 'Enviar com Marcação Fantasma?', - name: 'mentionsEveryOne', - type: 'boolean', - default: false, - description: 'Whether to mention them all', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendDocumento'], - }, - }, - }, - - - // Campos = Enviar Enquete - { - displayName: 'Nome da Instância', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar a enquete', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendPoll'], - }, - }, - }, - { - displayName: 'Número do Destinatário', - name: 'remoteJid', - type: 'string', - default: '', - required: true, - description: 'Número do destinatário', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendPoll'], - }, - }, - }, - { - displayName: 'Titulo da Enquete', - name: 'caption', - type: 'string', - default: '', - required: true, - description: 'Digite o titulo da sua enquete', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendPoll'], - }, - }, - }, - { - displayName: 'Mínimo 2 opções, Máximo 12. Cada opção deve ser única.', - name: 'notice', - type: 'notice', - default: '', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendPoll'], - }, - }, - }, - { - displayName: 'Opções', - name: 'options_display', - type: 'fixedCollection', - default: { metadataValues: [] }, - required: true, - typeOptions: { - multipleValues: true, - }, - description: 'Digite as opções da enquete (mínimo 2, máximo 12). Cada opção deve ser única.', - options: [ - { - name: 'metadataValues', - displayName: 'Metadata', - values: [ - { - displayName: 'Opção', - name: 'optionValue', - type: 'string', - default: '', - }, - ], - }, - ], - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendPoll'], - }, - }, - }, - { - displayName: 'Enviar com Marcação Fantasma?', - name: 'mentionsEveryOne', - type: 'boolean', - default: false, - description: 'Whether to mention them all', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendPoll'], - }, - }, - }, - - // Campos = Enviar Status - { - displayName: 'Nome da Instância', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar o status', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendStories'], - }, - }, - }, - { - displayName: 'Tipo do status', - name: 'type', - type: 'options', - description: 'Escolha o tipo de status você vai postar', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendStories'], - }, - }, - options: [ - { - name: 'Status de Texto', - value: 'text', - }, - { - name: 'Status de imagem', - value: 'image', - }, - { - name: 'Status de Video', - value: 'video', - }, - { - name: 'Status de Audio', - value: 'audio', - }, - ], - default: 'text', - }, - { - displayName: 'Conteudo ou URL', - name: 'content', - type: 'string', - default: '', - required: true, - description: 'Digite o conteudo ou Url da imagem/video/audio a ser postado', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendStories'], - }, - }, - }, - { - displayName: 'Texto para status de Imagem/Video', - name: 'caption', - type: 'string', - default: '', - required: false, - description: 'Digite o texto para status de Imagem/Video', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendStories'], - }, - }, - }, - { - displayName: 'Cor do Background', - name: 'backgroundColor', - type: 'color', - default: '#000000', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendStories'], - }, - }, - }, - { - displayName: 'Font do texto', - name: 'font', - type: 'options', - description: 'Escolha o tipo da font do seu texto', - displayOptions: { - show: { - resource: ['messages-api'], - operation: ['sendStories'], - }, - }, - options: [ - { - name: 'SERIF', - value: 1, - }, - { - name: 'NORICAN REGULAR', - value: 2, - }, - { - name: 'BRYNDAN WRITE', - value: 3, - }, - { - name: 'BEBASNEUE REGULAR', - value: 4, - }, - { - name: 'OSWALD HEAVY', - value: 5, - }, - ], - default: 1, - }, - -]; -// Campo das Eventos -const eventsOperation: INodeProperties[] = [ - // Campos = Webhook - { - displayName: 'Nome da Instancia', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar a mensagem', - displayOptions: { - show: { - resource: ['events-api'], - operation: ['webhook'], - }, - }, - }, - { - displayName: 'O que deseja fazer', - name: 'resourceForWebhook', - type: 'options', - options: [ - { - name: 'Definir Webhook', - value: 'setWebhook', - }, - { - name: 'Verificar Webhook', - value: 'findWebhook', - }, - ], - default: 'setWebhook', - description: 'Escolha entre definir um novo webhook ou verificar o webhook', - displayOptions: { - show: { - resource: ['events-api'], - operation: ['webhook'], - }, - }, - }, - { - displayName: 'Ativar Webhook', - name: 'enabled', - type: 'boolean', - default: true, - description: 'Whether to enable or disable integration with Webhook', - displayOptions: { - show: { - resource: ['events-api'], - operation: ['webhook'], - resourceForWebhook: ['setWebhook'], - }, - }, - }, - { - displayName: 'Url do Webhook', - name: 'webhookUrl', - type: 'string', - default: '', - description: 'Digite a Url que vai receber os eventos do Webhook', - displayOptions: { - show: { - resource: ['events-api'], - operation: ['webhook'], - resourceForWebhook: ['setWebhook'], - }, - }, - }, - { - displayName: 'Webhook por Eventos', - name: 'webhookByEvents', - type: 'boolean', - default: false, - description: 'Whether to create a route for each event by appending the event name to the end of the URL', - displayOptions: { - show: { - resource: ['events-api'], - operation: ['webhook'], - resourceForWebhook: ['setWebhook'], - }, - }, - }, - { - displayName: 'Base64 no Webhook', - name: 'webhookBase64', - type: 'boolean', - default: false, - description: 'Whether to send media data in base64 format in the webhook', - displayOptions: { - show: { - resource: ['events-api'], - operation: ['webhook'], - resourceForWebhook: ['setWebhook'], - }, - }, - }, - { - displayName: 'Eventos', - name: 'webhookEvents', - type: 'multiOptions', - displayOptions: { - show: { - resource: ['events-api'], - operation: ['webhook'], - resourceForWebhook: ['setWebhook'], - }, - }, - default: [], - options: [ - { - name: 'CALL', - value: 'CALL', - }, - { - name: 'CHATS_DELETE', - value: 'CHATS_DELETE', - }, - { - name: 'CHATS_SET', - value: 'CHATS_SET', - }, - { - name: 'CHATS_UPDATE', - value: 'CHATS_UPDATE', - }, - { - name: 'CHATS_UPSERT', - value: 'CHATS_UPSERT', - }, - { - name: 'CONNECTION_UPDATE', - value: 'CONNECTION_UPDATE', - }, - { - name: 'CONTACTS_SET', - value: 'CONTACTS_SET', - }, - { - name: 'CONTACTS_UPDATE', - value: 'CONTACTS_UPDATE', - }, - { - name: 'CONTACTS_UPSERT', - value: 'CONTACTS_UPSERT', - }, - { - name: 'GROUP_PARTICIPANTS_UPDATE', - value: 'GROUP_PARTICIPANTS_UPDATE', - }, - { - name: 'GROUP_UPDATE', - value: 'GROUP_UPDATE', - }, - { - name: 'GROUPS_UPSERT', - value: 'GROUPS_UPSERT', - }, - { - name: 'LABELS_ASSOCIATION', - value: 'LABELS_ASSOCIATION', - }, - { - name: 'LABELS_EDIT', - value: 'LABELS_EDIT', - }, - { - name: 'MESSAGES_DELETE', - value: 'MESSAGES_DELETE', - }, - { - name: 'MESSAGES_SET', - value: 'MESSAGES_SET', - }, - { - name: 'MESSAGES_UPDATE', - value: 'MESSAGES_UPDATE', - }, - { - name: 'MESSAGES_UPSERT', - value: 'MESSAGES_UPSERT', - }, - { - name: 'PRESENCE_UPDATE', - value: 'PRESENCE_UPDATE', - }, - { - name: 'QRCODE_UPDATED', - value: 'QRCODE_UPDATED', - }, - { - name: 'SEND_MESSAGE', - value: 'SEND_MESSAGE', - }, - { - name: 'TYPEBOT_CHANGE_STATUS', - value: 'TYPEBOT_CHANGE_STATUS', - }, - { - name: 'TYPEBOT_START', - value: 'TYPEBOT_START', - }, - ] - }, - - // Campos = RabbitMQ - { - displayName: 'Nome da Instancia', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar a mensagem', - displayOptions: { - show: { - resource: ['events-api'], - operation: ['rabbitMQ'], - }, - }, - }, - { - displayName: 'O que deseja fazer', - name: 'resourceForRabbitMQ', - type: 'options', - options: [ - { - name: 'Definir RabbitMQ', - value: 'setRabbitMQ', - }, - { - name: 'Verificar RabbitMQ', - value: 'findRabbitMQ', - }, - ], - default: 'setRabbitMQ', - description: 'Escolha entre ativar/desativar RabbitMQ ou verificar o RabbitMQ', - displayOptions: { - show: { - resource: ['events-api'], - operation: ['rabbitMQ'], - }, - }, - }, - { - displayName: 'Ativar RabbitMQ', - name: 'enabled', - type: 'boolean', - default: true, - description: 'Whether to enable or disable integration with RabbitMQ.', - displayOptions: { - show: { - resource: ['events-api'], - operation: ['rabbitMQ'], - resourceForRabbitMQ: ['setRabbitMQ'], - }, - }, - }, - { - displayName: 'Eventos', - name: 'rabbitMQEvents', - type: 'multiOptions', - displayOptions: { - show: { - resource: ['events-api'], - operation: ['rabbitMQ'], - resourceForRabbitMQ: ['setRabbitMQ'], - }, - }, - default: [], - options: [ - { - name: 'CALL', - value: 'CALL', - }, - { - name: 'CHATS_DELETE', - value: 'CHATS_DELETE', - }, - { - name: 'CHATS_SET', - value: 'CHATS_SET', - }, - { - name: 'CHATS_UPDATE', - value: 'CHATS_UPDATE', - }, - { - name: 'CHATS_UPSERT', - value: 'CHATS_UPSERT', - }, - { - name: 'CONNECTION_UPDATE', - value: 'CONNECTION_UPDATE', - }, - { - name: 'CONTACTS_SET', - value: 'CONTACTS_SET', - }, - { - name: 'CONTACTS_UPDATE', - value: 'CONTACTS_UPDATE', - }, - { - name: 'CONTACTS_UPSERT', - value: 'CONTACTS_UPSERT', - }, - { - name: 'GROUP_PARTICIPANTS_UPDATE', - value: 'GROUP_PARTICIPANTS_UPDATE', - }, - { - name: 'GROUP_UPDATE', - value: 'GROUP_UPDATE', - }, - { - name: 'GROUPS_UPSERT', - value: 'GROUPS_UPSERT', - }, - { - name: 'LABELS_ASSOCIATION', - value: 'LABELS_ASSOCIATION', - }, - { - name: 'LABELS_EDIT', - value: 'LABELS_EDIT', - }, - { - name: 'MESSAGES_DELETE', - value: 'MESSAGES_DELETE', - }, - { - name: 'MESSAGES_SET', - value: 'MESSAGES_SET', - }, - { - name: 'MESSAGES_UPDATE', - value: 'MESSAGES_UPDATE', - }, - { - name: 'MESSAGES_UPSERT', - value: 'MESSAGES_UPSERT', - }, - { - name: 'PRESENCE_UPDATE', - value: 'PRESENCE_UPDATE', - }, - { - name: 'QRCODE_UPDATED', - value: 'QRCODE_UPDATED', - }, - { - name: 'SEND_MESSAGE', - value: 'SEND_MESSAGE', - }, - { - name: 'TYPEBOT_CHANGE_STATUS', - value: 'TYPEBOT_CHANGE_STATUS', - }, - { - name: 'TYPEBOT_START', - value: 'TYPEBOT_START', - }, - ] - }, -] - -// Campo das Integrações -const integrationsOperation: INodeProperties[] = [ - - // Campos = Chatwoot - { - displayName: 'Nome da Instancia', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar a mensagem', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - }, - }, - }, - { - displayName: 'O que deseja fazer', - name: 'resourceForChatwoot', - type: 'options', - options: [ - { - name: 'Definir Chatwoot', - value: 'setChatwoot', - }, - { - name: 'Verificar Chatwoot', - value: 'findChatwoot', - }, - ], - default: 'setChatwoot', - description: 'Escolha entre ativar/desativar Chatwoot ou verificar o Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - }, - }, - }, - { - displayName: 'Ativar Chatwoot', - name: 'enabled', - type: 'boolean', - default: true, - description: 'Whether to enable or disable integration with Chatwoot.', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'ID Da Conta Do Chatwoot', - name: 'chatwootAccountId', - type: 'string', - default: '', - required: true, - description: 'Digite o ID da conta do Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Token De Admin Do Chatwoot', - name: 'chatwootToken', - type: 'string', - required: true, - typeOptions: { - password: true, - }, - default: '', - description: 'Digite o token de admin do Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Link Do Chatwoot', - name: 'chatwootUrl', - type: 'string', - default: '', - required: true, - description: 'Digite o link do Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Assinatura Do Agente Do Chatwoot', - name: 'chatwootSignMsg', - type: 'boolean', - default: false, - description: 'Whether to enable or disable the Chatwoot agent signature', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Reabrir Mensagens No Chatwoot', - name: 'chatwootReopenConversation', - type: 'boolean', - default: false, - description: 'Whether to enable or disable reopening messages in Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Iniciar Conversas Como Pendentes No Chatwoot', - name: 'chatwootConversationPending', - type: 'boolean', - default: false, - description: 'Whether to start conversations as pending in Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Importar Contatos Para O Chatwoot', - name: 'chatwootImportContacts', - type: 'boolean', - default: false, - description: 'Whether to import contacts to Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Nome Da Inbox Do Chatwoot', - name: 'chatwootNameInbox', - type: 'string', - default: '', - description: 'Opicional: Digite o nome da Inbox do Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Mesclar Contatos Brasileiros No Chatwoot', - name: 'chatwootMergeBrazilContacts', - type: 'boolean', - default: false, - description: 'Whether to merge Brazilian contacts in Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Importar Mensagens Para O Chatwoot', - name: 'chatwootImportMessages', - type: 'boolean', - default: false, - description: 'Whether to import messages to Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Importar Mensagens De Quantos Dias Para O Chatwoot', - name: 'chatwootDaysLimitImportMessages', - type: 'number', - default: 0, - description: 'Opicional: Digite o número de dias para limitar a importação de mensagens para o Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Criar Caixa De Entrada', - name: 'chatwootAutoCreate', - type: 'boolean', - default: true, - description: 'Whether to create an inbox automatically', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Nome Do Contato De QRCode No Chatwoot', - name: 'chatwootOrganization', - type: 'string', - default: '', - description: 'Opicional: Digite o nome do contato de QRCode no Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - { - displayName: 'Url Do Logo Para O Contato No Chatwoot', - name: 'chatwootLogo', - type: 'string', - default: 'https://github.com/user-attachments/assets/4d1e9cd6-377a-4383-820a-9a97e6cfbb63', - description: 'Opicional: Digite a URL do logo para o contato no Chatwoot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['chatwoot'], - resourceForChatwoot: ['setChatwoot'], - }, - }, - }, - - // Campos = Typebot - { - displayName: 'Nome da Instancia', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar a mensagem', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - }, - }, - }, - - { - displayName: 'O Que Deseja Fazer', - name: 'resourceForTypebot', - type: 'options', - options: [ - { - name: 'Adicionar Typebot', - value: 'createTypebot', - }, - { - name: 'Verificar Typebot', - value: 'findTypebot', - }, - { - name: 'Atualizar Typebot', - value: 'updateTypebot', - }, - { - name: 'Deletar Typebot', - value: 'deleteTypebot', - }, - { - name: 'Iniciar Typebot', - value: 'startTypebot', - }, - { - name: 'Procurar Sessão No Typebot', - value: 'fetchSessionsTypebot', - }, - { - name: 'Alterar Status Da Sessão No Typebot', - value: 'changeStatusTypebot', - }, - ], - default: 'createTypebot', - description: 'Escolha uma opção para realizar com a integração do Typebot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - }, - }, - }, - - // updateTypebot - { - displayName: 'Id do Typebot', - name: 'typebotId', - type: 'string', - default: '', - required: false, - description: 'Digite o ID do Typebot que deseja buscar, deixe vazio para procurar todos', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['updateTypebot', 'findTypebot', 'deleteTypebot', 'fetchSessionsTypebot', 'changeStatusTypebot'], - }, - }, - }, - - //Se createTypebot ou updateTypebot - { - displayName: 'URL Da API Do Typebot', - name: 'url', - type: 'string', - default: '', - required: true, - description: 'Digite a URL do seu typebot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot', 'startTypebot'], - }, - }, - }, - { - displayName: 'Nome Do Typebot', - name: 'typebot', - type: 'string', - default: '', - required: true, - description: 'Digite o nome do seu fluxo no typebot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot', 'startTypebot'], - }, - }, - }, - { - displayName: 'Tipo De Gatilho', - name: 'triggerType', - type: 'options', - options: [ - { - name: 'Palavra Chave', - value: 'keyword', - }, - { - name: 'Todos', - value: 'all', - }, - ], - default: 'keyword', - description: 'Escolha uma opção para realizar com a integração do Typebot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot'], - }, - }, - }, - { - displayName: 'Operador Do Gatilho', - name: 'triggerOperator', - type: 'options', - options: [ - { - name: 'Contem', - value: 'contains', - }, - { - name: 'Igual à', - value: 'equals', - }, - { - name: 'Começa com', - value: 'startsWith', - }, - { - name: 'Termina com', - value: 'endsWith', - }, - { - name: 'Regex', - value: 'regex', - }, - ], - default: 'contains', - description: 'Escolha uma opção para realizar com a integração do Typebot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot'], - triggerType: ['keyword'], - }, - }, - }, - { - displayName: 'Gatilho', - name: 'triggerValue', - type: 'string', - default: '', - required: true, - description: 'Digite a palavra/frase ou regex para ser usado como gatilho para iniciar o Typebot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot'], - triggerType: ['keyword'], - }, - }, - }, - { - displayName: 'Expira Em (Minutos)', - name: 'expire', - type: 'number', - default: 0, - required: true, - description: 'Digite quantos minutos sem respostas o bot devera ser desativado', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot'], - }, - }, - }, - { - displayName: 'Palavra Chave de Finalização', - name: 'keywordFinish', - type: 'string', - default: '#sair', - required: true, - description: 'Digite a palavra/frase que sera usado para fechar o bot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot'], - }, - }, - }, - { - displayName: 'Delay Padrão Da Mensagem (Em Milésimos)', - name: 'delayMessage', - type: 'number', - default: 1000, - required: true, - description: 'Digite quantos milisegundos o bot terá de delay', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot'], - }, - }, - }, - { - displayName: 'Palavra Chave de Finalização', - name: 'unknownMessage', - type: 'string', - default: 'Mensagem não reconhecida', - required: true, - description: 'Digite a palavra/frase que sera usado para fechar o bot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot'], - }, - }, - }, - { - displayName: 'Escuta mensagens enviadas por mim', - name: 'listeningFromMe', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot'], - }, - }, - }, - { - displayName: 'Pausa o bot quando eu enviar uma mensagem', - name: 'stopBotFromMe', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot'], - }, - }, - }, - { - displayName: 'Mantem a sessão do bot aberta', - name: 'keepOpen', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot'], - }, - }, - }, - { - displayName: 'Tempo de Espera (Em Segundos)', - name: 'debounceTime', - type: 'number', - default: 0, - required: true, - description: 'Este é o tempo que o bot ficará esperando as proximas mensagens após receber uma mensagem, depois ele juntará todas as mensagens em uma só', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['createTypebot', 'updateTypebot'], - }, - }, - }, - - // startTypebot - { - displayName: 'Numero Do Destinatario', - name: 'remoteJid', - type: 'string', - default: '', - required: true, - description: 'RemoteJid do destinarario', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['startTypebot', 'changeStatusTypebot'], - }, - }, - }, - { - displayName: 'Iniciar Seção', - name: 'startSession', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['startTypebot'], - }, - }, - }, - { - displayName: 'Variaveis', - name: 'variables_display', - type: 'fixedCollection', - default: { metadataValues: [] }, - required: false, - typeOptions: { - multipleValues: true, - }, - description: 'Digite as opções da enquete (mínimo 2, máximo 12). Cada opção deve ser única.', - options: [ - { - name: 'metadataValues', - displayName: 'Metadata', - values: [ - { - displayName: 'Nome Da Variavel', - name: 'name', - type: 'string', - default: '', - }, - { - displayName: 'Valor Da Variavel', - name: 'value', - type: 'string', - default: '', - }, - ], - }, - ], - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['startTypebot'], - }, - }, - }, - - // Change Session Status - { - displayName: 'Status', - name: 'status', - type: 'options', - options: [ - { - name: 'Aberta', - value: 'opened', - }, - { - name: 'Pausada', - value: 'paused', - }, - { - name: 'Fechada', - value: 'closed', - }, - ], - default: 'opened', - description: 'Escolha qual será o status da seção', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['typebot'], - resourceForTypebot: ['changeStatusTypebot'], - }, - }, - }, - - // EVOLUTION BOT - { - displayName: 'Nome Da Instancia', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar a mensagem', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - }, - }, - }, - - { - displayName: 'O Que Deseja Fazer', - name: 'resourceForEvolutionBot', - type: 'options', - options: [ - { - name: 'Adicionar Evolution Bot', - value: 'createEvolutionBot', - }, - { - name: 'Verificar Evolution Bot', - value: 'findEvolutionBot', - }, - { - name: 'Atualizar Evolution Bot', - value: 'updateEvolutionBot', - }, - { - name: 'Deletar Evolution Bot', - value: 'deleteEvolutionBot', - }, - { - name: 'Procurar Sessão No Evolution Bot', - value: 'fetchSessionsEvolutionBot', - }, - { - name: 'Alterar Status Da Sessão No Evolution Bot', - value: 'changeStatusEvolutionBot', - }, - ], - default: 'createEvolutionBot', - description: 'Escolha uma opção para realizar com a integração do EvolutionBot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - }, - }, - }, - - // update EvolutionBot - { - displayName: 'Id do Evolution Bot', - name: 'evolutionBotId', - type: 'string', - default: '', - required: false, - description: 'Digite o ID do EvolutionBot que deseja buscar, deixe vazio para procurar todos', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['updateEvolutionBot', 'findEvolutionBot', 'deleteEvolutionBot', 'fetchSessionsEvolutionBot', 'changeStatusEvolutionBot'], - }, - }, - }, - - //Se createEvolutionBot ou updateEvolutionBot - { - displayName: 'URL Da API Do Evolution Bot', - name: 'apiUrl', - type: 'string', - default: '', - required: true, - description: 'Digite a URL do seu Evolution Bot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - }, - }, - }, - { - displayName: 'ApiKey da Evolution Bot', - name: 'apiKeyBot', - type: 'string', - default: '', - required: false, - description: 'Digite a ApiKey do seu Evolution Bot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - }, - }, - }, - { - displayName: 'Tipo De Gatilho', - name: 'triggerType', - type: 'options', - options: [ - { - name: 'Palavra Chave', - value: 'keyword', - }, - { - name: 'Todos', - value: 'all', - }, - ], - default: 'keyword', - description: 'Escolha uma opção para realizar com a integração do EvolutionBot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - }, - }, - }, - { - displayName: 'Operador Do Gatilho', - name: 'triggerOperator', - type: 'options', - options: [ - { - name: 'Contem', - value: 'contains', - }, - { - name: 'Igual à', - value: 'equals', - }, - { - name: 'Começa com', - value: 'startsWith', - }, - { - name: 'Termina com', - value: 'endsWith', - }, - { - name: 'Regex', - value: 'regex', - }, - ], - default: 'contains', - description: 'Escolha uma opção para realizar com a integração do EvolutionBot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - triggerType: ['keyword'], - }, - }, - }, - { - displayName: 'Gatilho', - name: 'triggerValue', - type: 'string', - default: '', - required: true, - description: 'Digite a palavra/frase ou regex para ser usado como gatilho para iniciar o EvolutionBot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - triggerType: ['keyword'], - }, - }, - }, - { - displayName: 'Expira Em (Minutos)', - name: 'expire', - type: 'number', - default: 0, - required: true, - description: 'Digite quantos minutos sem respostas o bot devera ser desativado', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - }, - }, - }, - { - displayName: 'Palavra Chave de Finalização', - name: 'keywordFinish', - type: 'string', - default: '#sair', - required: true, - description: 'Digite a palavra/frase que sera usado para fechar o bot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - }, - }, - }, - { - displayName: 'Delay Padrão Da Mensagem (Em Milésimos)', - name: 'delayMessage', - type: 'number', - default: 1000, - required: true, - description: 'Digite quantos milisegundos o bot terá de delay', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - }, - }, - }, - { - displayName: 'Palavra Chave de Finalização', - name: 'unknownMessage', - type: 'string', - default: 'Mensagem não reconhecida', - required: true, - description: 'Digite a palavra/frase que sera usado para fechar o bot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - }, - }, - }, - { - displayName: 'Escuta mensagens enviadas por mim', - name: 'listeningFromMe', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - }, - }, - }, - { - displayName: 'Pausa o bot quando eu enviar uma mensagem', - name: 'stopBotFromMe', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - }, - }, - }, - { - displayName: 'Mantem a sessão do bot aberta', - name: 'keepOpen', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - }, - }, - }, - { - displayName: 'Tempo de Espera (Em Segundos)', - name: 'debounceTime', - type: 'number', - default: 0, - required: true, - description: 'Este é o tempo que o bot ficará esperando as proximas mensagens após receber uma mensagem, depois ele juntará todas as mensagens em uma só', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['createEvolutionBot', 'updateEvolutionBot'], - }, - }, - }, - - // Change Session Status EvolutionBot - { - displayName: 'Numero Do Destinatario', - name: 'remoteJid', - type: 'string', - default: '', - required: true, - description: 'RemoteJid do destinarario', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['changeStatusEvolutionBot'], - }, - }, - }, - { - displayName: 'Status', - name: 'status', - type: 'options', - options: [ - { - name: 'Aberta', - value: 'opened', - }, - { - name: 'Pausada', - value: 'paused', - }, - { - name: 'Fechada', - value: 'closed', - }, - ], - default: 'opened', - description: 'Escolha qual será o status da seção', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['evolutionBot'], - resourceForEvolutionBot: ['changeStatusEvolutionBot'], - }, - }, - }, - - // Dify - { - displayName: 'Nome da Instancia', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar a mensagem', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - }, - }, - }, - { - displayName: 'O Que Deseja Fazer', - name: 'resourceForDifyBot', - type: 'options', - options: [ - { - name: 'Adicionar Dify', - value: 'createDify', - }, - { - name: 'Verificar Dify', - value: 'findDify', - }, - { - name: 'Atualizar Dify', - value: 'updateDify', - }, - { - name: 'Deletar Dify', - value: 'deleteDify', - }, - { - name: 'Procurar Sessão No Dify', - value: 'fetchSessionsDify', - }, - { - name: 'Alterar Status Da Sessão No Dify', - value: 'changeStatusDify', - }, - ], - default: 'createDify', - description: 'Escolha uma opção para realizar com a integração do Dify', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - }, - }, - }, - { - displayName: 'Tipo do Bot', - name: 'botType', - type: 'options', - options: [ - { - name: 'Bot de Chat', - value: 'chatBot', - }, - { - name: 'Gerador de Texto', - value: 'textGenerator', - }, - { - name: 'Agente', - value: 'agent', - }, - { - name: 'Fluxo de Trabalho', - value: 'workflow', - }, - ], - default: 'chatBot', - description: 'Escolha qual o tipo de bot que você deseja vincular', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - }, - }, - }, - - // update Dify - { - displayName: 'Id do Dify', - name: 'difyBotId', - type: 'string', - default: '', - required: false, - description: 'Digite o ID do Dify que deseja buscar, deixe vazio para procurar todos', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['updateDify', 'findDify', 'deleteDify', 'fetchSessionsDify', 'changeStatusDify'], - }, - }, - }, - - //Se createDify ou updateDify - { - displayName: 'Url do Dify', - name: 'apiUrl', - type: 'string', - default: '', - required: true, - description: 'Digite a URL do seu Dify', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - }, - }, - }, - { - displayName: 'ApiKey do Dify', - name: 'apiKeyBot', - type: 'string', - default: '', - required: true, - description: 'Digite a ApiKey do seu bot do Dify', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - }, - }, - }, - { - displayName: 'Tipo De Gatilho', - name: 'triggerType', - type: 'options', - options: [ - { - name: 'Palavra Chave', - value: 'keyword', - }, - { - name: 'Todos', - value: 'all', - }, - ], - default: 'keyword', - description: 'Escolha uma opção para realizar com a integração do Dify', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - }, - }, - }, - { - displayName: 'Operador Do Gatilho', - name: 'triggerOperator', - type: 'options', - options: [ - { - name: 'Contem', - value: 'contains', - }, - { - name: 'Igual à', - value: 'equals', - }, - { - name: 'Começa com', - value: 'startsWith', - }, - { - name: 'Termina com', - value: 'endsWith', - }, - { - name: 'Regex', - value: 'regex', - }, - ], - default: 'contains', - description: 'Escolha uma opção para realizar com a integração do Dify', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - triggerType: ['keyword'], - }, - }, - }, - { - displayName: 'Gatilho', - name: 'triggerValue', - type: 'string', - default: '', - required: true, - description: 'Digite a palavra/frase ou regex para ser usado como gatilho para iniciar o Dify', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - triggerType: ['keyword'], - }, - }, - }, - { - displayName: 'Expira Em (Minutos)', - name: 'expire', - type: 'number', - default: 0, - required: true, - description: 'Digite quantos minutos sem respostas o bot devera ser desativado', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - }, - }, - }, - { - displayName: 'Palavra Chave de Finalização', - name: 'keywordFinish', - type: 'string', - default: '#sair', - required: true, - description: 'Digite a palavra/frase que sera usado para fechar o bot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - }, - }, - }, - { - displayName: 'Delay Padrão Da Mensagem (Em Milésimos)', - name: 'delayMessage', - type: 'number', - default: 1000, - required: true, - description: 'Digite quantos milisegundos o bot terá de delay', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - }, - }, - }, - { - displayName: 'Palavra Chave de Finalização', - name: 'unknownMessage', - type: 'string', - default: 'Mensagem não reconhecida', - required: true, - description: 'Digite a palavra/frase que sera usado para fechar o bot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - }, - }, - }, - { - displayName: 'Escuta mensagens enviadas por mim', - name: 'listeningFromMe', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - }, - }, - }, - { - displayName: 'Pausa o bot quando eu enviar uma mensagem', - name: 'stopBotFromMe', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - }, - }, - }, - { - displayName: 'Mantem a sessão do bot aberta', - name: 'keepOpen', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - }, - }, - }, - { - displayName: 'Tempo de Espera (Em Segundos)', - name: 'debounceTime', - type: 'number', - default: 0, - required: true, - description: 'Este é o tempo que o bot ficará esperando as proximas mensagens após receber uma mensagem, depois ele juntará todas as mensagens em uma só', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['createDify', 'updateDify'], - }, - }, - }, - - // Change Session Status Dify - { - displayName: 'Numero Do Destinatario', - name: 'remoteJid', - type: 'string', - default: '', - required: true, - description: 'RemoteJid do destinarario', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['changeStatusDify'], - }, - }, - }, - { - displayName: 'Status', - name: 'status', - type: 'options', - options: [ - { - name: 'Aberta', - value: 'opened', - }, - { - name: 'Pausada', - value: 'paused', - }, - { - name: 'Fechada', - value: 'closed', - }, - ], - default: 'opened', - description: 'Escolha qual será o status da seção', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['difyBot'], - resourceForDifyBot: ['changeStatusDify'], - }, - }, - }, - - { - displayName: 'Nome da Instancia', - name: 'instanceName', - type: 'string', - default: '', - required: true, - description: 'Digite o nome da instância que vai enviar a mensagem', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - }, - }, - }, - { - displayName: 'O Que Deseja Fazer', - name: 'resourceForFlowiseBot', - type: 'options', - options: [ - { - name: 'Adicionar Flowise', - value: 'createFlowise', - }, - { - name: 'Verificar Flowise', - value: 'findFlowise', - }, - { - name: 'Atualizar Flowise', - value: 'updateFlowise', - }, - { - name: 'Deletar Flowise', - value: 'deleteFlowise', - }, - { - name: 'Procurar Sessão No Flowise', - value: 'fetchSessionsFlowise', - }, - { - name: 'Alterar Status Da Sessão No Flowise', - value: 'changeStatusFlowise', - }, - ], - default: 'createFlowise', - description: 'Escolha uma opção para realizar com a integração do Flowise', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - }, - }, - }, - - // update Flowise - { - displayName: 'Id do Flowise', - name: 'flowiseBotId', - type: 'string', - default: '', - required: false, - description: 'Digite o ID do Flowise que deseja buscar, deixe vazio para procurar todos', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['updateFlowise', 'findFlowise', 'deleteFlowise', 'fetchSessionsFlowise', 'changeStatusFlowise'], - }, - }, - }, - - //Se createFlowise ou updateFlowise - { - displayName: 'Url do Flowise', - name: 'apiUrl', - type: 'string', - default: '', - required: true, - description: 'Digite a URL do seu Flowise', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - }, - }, - }, - { - displayName: 'ApiKey do Flowise', - name: 'apiKeyBot', - type: 'string', - default: '', - required: false, - description: 'Digite a ApiKey do seu bot do Flowise', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - }, - }, - }, - { - displayName: 'Tipo De Gatilho', - name: 'triggerType', - type: 'options', - options: [ - { - name: 'Palavra Chave', - value: 'keyword', - }, - { - name: 'Todos', - value: 'all', - }, - ], - default: 'keyword', - description: 'Escolha uma opção para realizar com a integração do Flowise', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - }, - }, - }, - { - displayName: 'Operador Do Gatilho', - name: 'triggerOperator', - type: 'options', - options: [ - { - name: 'Contem', - value: 'contains', - }, - { - name: 'Igual à', - value: 'equals', - }, - { - name: 'Começa com', - value: 'startsWith', - }, - { - name: 'Termina com', - value: 'endsWith', - }, - { - name: 'Regex', - value: 'regex', - }, - ], - default: 'contains', - description: 'Escolha uma opção para realizar com a integração do Flowise', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - triggerType: ['keyword'], - }, - }, - }, - { - displayName: 'Gatilho', - name: 'triggerValue', - type: 'string', - default: '', - required: true, - description: 'Digite a palavra/frase ou regex para ser usado como gatilho para iniciar o Flowise', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - triggerType: ['keyword'], - }, - }, - }, - { - displayName: 'Expira Em (Minutos)', - name: 'expire', - type: 'number', - default: 0, - required: true, - description: 'Digite quantos minutos sem respostas o bot devera ser desativado', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - }, - }, - }, - { - displayName: 'Palavra Chave de Finalização', - name: 'keywordFinish', - type: 'string', - default: '#sair', - required: true, - description: 'Digite a palavra/frase que sera usado para fechar o bot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - }, - }, - }, - { - displayName: 'Delay Padrão Da Mensagem (Em Milésimos)', - name: 'delayMessage', - type: 'number', - default: 1000, - required: true, - description: 'Digite quantos milisegundos o bot terá de delay', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - }, - }, - }, - { - displayName: 'Palavra Chave de Finalização', - name: 'unknownMessage', - type: 'string', - default: 'Mensagem não reconhecida', - required: true, - description: 'Digite a palavra/frase que sera usado para fechar o bot', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - }, - }, - }, - { - displayName: 'Escuta mensagens enviadas por mim', - name: 'listeningFromMe', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - }, - }, - }, - { - displayName: 'Pausa o bot quando eu enviar uma mensagem', - name: 'stopBotFromMe', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - }, - }, - }, - { - displayName: 'Mantem a sessão do bot aberta', - name: 'keepOpen', - type: 'boolean', - default: false, - description: 'Whether...', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - }, - }, - }, - { - displayName: 'Tempo de Espera (Em Segundos)', - name: 'debounceTime', - type: 'number', - default: 0, - required: true, - description: 'Este é o tempo que o bot ficará esperando as proximas mensagens após receber uma mensagem, depois ele juntará todas as mensagens em uma só', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['createFlowise', 'updateFlowise'], - }, - }, - }, - - // Change Session Status Flowise - { - displayName: 'Numero Do Destinatario', - name: 'remoteJid', - type: 'string', - default: '', - required: true, - description: 'RemoteJid do destinarario', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['changeStatusFlowise'], - }, - }, - }, - { - displayName: 'Status', - name: 'status', - type: 'options', - options: [ - { - name: 'Aberta', - value: 'opened', - }, - { - name: 'Pausada', - value: 'paused', - }, - { - name: 'Fechada', - value: 'closed', - }, - ], - default: 'opened', - description: 'Escolha qual será o status da seção', - displayOptions: { - show: { - resource: ['integrations-api'], - operation: ['flowiseBot'], - resourceForFlowiseBot: ['changeStatusFlowise'], - }, - }, - }, - - -] - -export const httpVerbFields: INodeProperties[] = [ - ...instanceOperation, - ...messageOperation, - ...eventsOperation, - ...integrationsOperation, -]; diff --git a/package.json b/package.json index a6b7e07..fea98df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "n8n-nodes-evolution-api", - "version": "0.2.72", + "version": "1.0.0", "description": "Api não oficial do WhatsApp", "keywords": [ "n8n-community-node-package" @@ -36,10 +36,10 @@ "n8n": { "n8nNodesApiVersion": 1, "credentials": [ - "dist/credentials/HttpBinApi.credentials.js" + "dist/credentials/EvolutionApi.credentials.js" ], "nodes": [ - "dist/nodes/HttpBin/HttpBin.node.js" + "dist/nodes/EvolutionApi/EvolutionApi.node.js" ] }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..f20d6b5 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2903 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@typescript-eslint/parser': + specifier: ^8.3.0 + version: 8.17.0(eslint@8.57.1)(typescript@5.7.2) + eslint: + specifier: ^8.3.0 + version: 8.57.1 + eslint-plugin-n8n-nodes-base: + specifier: ^1.16.1 + version: 1.16.3(eslint@8.57.1)(typescript@5.7.2) + gulp: + specifier: ^5.0.0 + version: 5.0.0 + n8n-workflow: + specifier: '*' + version: 1.48.0 + prettier: + specifier: ^3.3.2 + version: 3.4.2 + typescript: + specifier: ^5.5.3 + version: 5.7.2 + +packages: + + '@eslint-community/eslint-utils@4.4.1': + resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/eslintrc@2.1.4': + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@eslint/js@8.57.1': + resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@gulpjs/messages@1.1.0': + resolution: {integrity: sha512-Ys9sazDatyTgZVb4xPlDufLweJ/Os2uHWOv+Caxvy2O85JcnT4M3vc73bi8pdLWlv3fdWQz3pdI9tVwo8rQQSg==} + engines: {node: '>=10.13.0'} + + '@gulpjs/to-absolute-glob@4.0.0': + resolution: {integrity: sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA==} + engines: {node: '>=10.13.0'} + + '@humanwhocodes/config-array@0.13.0': + resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} + engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/object-schema@2.0.3': + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead + + '@n8n/tournament@1.0.2': + resolution: {integrity: sha512-fTpi7F8ra5flGSVfRzohPyG7czAAKCZPlLjdKdwbLJivLoI/Ekhgodov1jfVSCVFVbwQ06gRQRxLEDzl2jl8ig==} + engines: {node: '>=18.10', pnpm: '>=8.6'} + + '@n8n_io/riot-tmpl@4.0.0': + resolution: {integrity: sha512-/xw8HQgYQlBCrt3IKpNSSB1CgpP7XArw1QTRjP+KEw+OHT8XGvHxXrW9VGdUu9RwDnzm/LFu+dNLeDmwJMeOwQ==} + + '@n8n_io/riot-tmpl@4.0.1': + resolution: {integrity: sha512-/zdRbEfTFjsm1NqnpPQHgZTkTdbp5v3VUxGeMA9098sps8jRCTraQkc3AQstJgHUm7ylBXJcIVhnVeLUMWAfwQ==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/semver@7.5.8': + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + + '@typescript-eslint/parser@8.17.0': + resolution: {integrity: sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@6.21.0': + resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} + engines: {node: ^16.0.0 || >=18.0.0} + + '@typescript-eslint/scope-manager@8.17.0': + resolution: {integrity: sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/types@6.21.0': + resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} + engines: {node: ^16.0.0 || >=18.0.0} + + '@typescript-eslint/types@8.17.0': + resolution: {integrity: sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@6.21.0': + resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/typescript-estree@8.17.0': + resolution: {integrity: sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@6.21.0': + resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + + '@typescript-eslint/visitor-keys@6.21.0': + resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} + engines: {node: ^16.0.0 || >=18.0.0} + + '@typescript-eslint/visitor-keys@8.17.0': + resolution: {integrity: sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-each@1.0.1: + resolution: {integrity: sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==} + engines: {node: '>=0.10.0'} + + array-slice@1.1.0: + resolution: {integrity: sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==} + engines: {node: '>=0.10.0'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + assert@2.1.0: + resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} + + ast-types@0.15.2: + resolution: {integrity: sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==} + engines: {node: '>=4'} + + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + + async-done@2.0.0: + resolution: {integrity: sha512-j0s3bzYq9yKIVLKGE/tWlCpa3PfFLcrDZLTSVdnnCTGagXuXBJO4SsY9Xdk/fQBirCkH4evW5xOeJXqlAQFdsw==} + engines: {node: '>= 10.13.0'} + + async-settle@2.0.0: + resolution: {integrity: sha512-Obu/KE8FurfQRN6ODdHN9LuXqwC+JFIM9NRyZqJJ4ZfLJmIYN9Rg0/kb+wF70VV5+fJusTMQlJ1t5rF7J/ETdg==} + engines: {node: '>= 10.13.0'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axios@1.6.7: + resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==} + + bach@2.0.1: + resolution: {integrity: sha512-A7bvGMGiTOxGMpNupYl9HQTf0FFDNF4VCmks4PJpFyN1AX2pdKuxuwdvUz2Hu388wcgp+OvGFNsumBfFNkR7eg==} + engines: {node: '>=10.13.0'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + bare-events@2.5.0: + resolution: {integrity: sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + bl@5.1.0: + resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone-stats@1.0.0: + resolution: {integrity: sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==} + + clone@2.1.2: + resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} + engines: {node: '>=0.8'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + copy-props@4.0.0: + resolution: {integrity: sha512-bVWtw1wQLzzKiYROtvNlbJgxgBYt2bMJpkCbKmXM3xyijvcjjWXEk5nyrrT3bgJ7ODb19ZohE2T0Y3FgNPyoTw==} + engines: {node: '>= 10.13.0'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-equal@2.2.0: + resolution: {integrity: sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + detect-file@1.0.0: + resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} + engines: {node: '>=0.10.0'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + each-props@3.0.0: + resolution: {integrity: sha512-IYf1hpuWrdzse/s/YJOrFmU15lyhSzxelNVAHTEG3DtP4QsLTWZUzcUL3HMXmKQxXpa4EIrBPpwRgj0aehdvAw==} + engines: {node: '>= 10.13.0'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-riot@1.0.0: + resolution: {integrity: sha512-NB/L/1Y30qyJcG5xZxCJKW/+bqyj+llbcCwo9DEz8bESIP0SLTOQ8T1DWCCFc+wJ61AMEstj4511PSScqMMfCw==} + + eslint-plugin-local@1.0.0: + resolution: {integrity: sha512-bcwcQnKL/Iw5Vi/F2lG1he5oKD2OGjhsLmrcctkWrWq5TujgiaYb0cj3pZgr3XI54inNVnneOFdAx1daLoYLJQ==} + + eslint-plugin-n8n-nodes-base@1.16.3: + resolution: {integrity: sha512-edLX42Vg4B+y0kzkitTVDmHZQrG5/wUZO874N5Z9leBuxt5TG1pqMY4zdr35RlpM4p4REr/T9x+6DpsQSL63WA==} + engines: {node: '>=20.15', pnpm: '>=9.6'} + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@8.57.1: + resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. + hasBin: true + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esprima-next@5.8.4: + resolution: {integrity: sha512-8nYVZ4ioIH4Msjb/XmhnBdz5WRRBaYqevKa1cv9nGJdCehMbzZCPNEEnqfLCZVetUVrUPEcb5IYyu1GG4hFqgg==} + engines: {node: '>=12'} + hasBin: true + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + expand-tilde@2.0.2: + resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} + engines: {node: '>=0.10.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-levenshtein@3.0.0: + resolution: {integrity: sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==} + + fastest-levenshtein@1.0.16: + resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} + engines: {node: '>= 4.9.1'} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + findup-sync@5.0.0: + resolution: {integrity: sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==} + engines: {node: '>= 10.13.0'} + + fined@2.0.0: + resolution: {integrity: sha512-OFRzsL6ZMHz5s0JrsEr+TpdGNCtrVtnuG3x1yzGNiQHT0yaDnXAj8V/lWcpJVrnoDpcwXcASxAZYbuXda2Y82A==} + engines: {node: '>= 10.13.0'} + + flagged-respawn@2.0.0: + resolution: {integrity: sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA==} + engines: {node: '>= 10.13.0'} + + flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + + flatted@3.3.2: + resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + for-in@1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + + for-own@1.0.0: + resolution: {integrity: sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==} + engines: {node: '>=0.10.0'} + + form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + + fs-mkdirp-stream@2.0.1: + resolution: {integrity: sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==} + engines: {node: '>=10.13.0'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob-stream@8.0.2: + resolution: {integrity: sha512-R8z6eTB55t3QeZMmU1C+Gv+t5UnNRkA55c5yo67fAVfxODxieTwsjNG7utxS/73NdP1NbDgCrhVEg2h00y4fFw==} + engines: {node: '>=10.13.0'} + + glob-watcher@6.0.0: + resolution: {integrity: sha512-wGM28Ehmcnk2NqRORXFOTOR064L4imSw3EeOqU5bIwUf62eXGwg89WivH6VMahL8zlQHeodzvHpXplrqzrz3Nw==} + engines: {node: '>= 10.13.0'} + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + global-modules@1.0.0: + resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==} + engines: {node: '>=0.10.0'} + + global-prefix@1.0.2: + resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} + engines: {node: '>=0.10.0'} + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + glogg@2.2.0: + resolution: {integrity: sha512-eWv1ds/zAlz+M1ioHsyKJomfY7jbDDPpwSkv14KQj89bycx1nvK5/2Cj/T9g7kzJcX5Bc7Yv22FjfBZS/jl94A==} + engines: {node: '>= 10.13.0'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + gulp-cli@3.0.0: + resolution: {integrity: sha512-RtMIitkT8DEMZZygHK2vEuLPqLPAFB4sntSxg4NoDta7ciwGZ18l7JuhCTiS5deOJi2IoK0btE+hs6R4sfj7AA==} + engines: {node: '>=10.13.0'} + hasBin: true + + gulp@5.0.0: + resolution: {integrity: sha512-S8Z8066SSileaYw1S2N1I64IUc/myI2bqe2ihOBzO6+nKpvNSg7ZcWJt/AwF8LC/NVN+/QZ560Cb/5OPsyhkhg==} + engines: {node: '>=10.13.0'} + hasBin: true + + gulplog@2.2.0: + resolution: {integrity: sha512-V2FaKiOhpR3DRXZuYdRLn/qiY0yI5XmqbTKrYbdemJ+xOh2d2MOweI/XFgMzd/9+1twdvMwllnZbWZNJ+BOm4A==} + engines: {node: '>= 10.13.0'} + + has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.1.0: + resolution: {integrity: sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + homedir-polyfill@1.0.3: + resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indefinite@2.5.1: + resolution: {integrity: sha512-Ul0hCdnSjuFDEloYWeozTaEfljbz+0q+u4HsHns2dOk2DlhGlbRMGFtNcIL+Ve7sZYeIOTOAKA0usAXBGHpNDg==} + engines: {node: '>=6.0.0'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + + interpret@3.1.1: + resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} + engines: {node: '>=10.13.0'} + + is-absolute@1.0.0: + resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==} + engines: {node: '>=0.10.0'} + + is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-boolean-object@1.2.0: + resolution: {integrity: sha512-kR5g0+dXf/+kXnqI+lu0URKYPKgICtHGGNCDSB10AaUFj3o/HkB3u7WfpRBJGFopxxY0oH3ux7ZsDjLtK7xqvw==} + engines: {node: '>= 0.4'} + + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + + is-negated-glob@1.0.0: + resolution: {integrity: sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==} + engines: {node: '>=0.10.0'} + + is-number-object@1.1.0: + resolution: {integrity: sha512-KVSZV0Dunv9DTPkhXwcZ3Q+tUc9TsaE1ZwX5J2WMvsSGS6Md8TFPun5uwh0yRdrNerI6vf/tbJxqSx4c1ZI1Lw==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + + is-regex@1.2.0: + resolution: {integrity: sha512-B6ohK4ZmoftlUe+uvenXSbPJFo6U37BH7oO1B3nQH8f/7h27N56s85MhUtbFJAziz5dcmuR3i8ovUl35zp8pFA==} + engines: {node: '>= 0.4'} + + is-relative@1.0.0: + resolution: {integrity: sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==} + engines: {node: '>=0.10.0'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + + is-string@1.1.0: + resolution: {integrity: sha512-PlfzajuF9vSo5wErv3MJAKD/nqf9ngAs1NFQYm16nUYFO2IzxJ2hcm+IOCg+EEopdykNNUhVq5cz35cAUxU8+g==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.0: + resolution: {integrity: sha512-qS8KkNNXUZ/I+nX6QT8ZS1/Yx0A444yhzdTKxCzKkNjQ9sHErBxJnJAgh+f5YhusYECEcjo4XcyH87hn6+ks0A==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + + is-unc-path@1.0.0: + resolution: {integrity: sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==} + engines: {node: '>=0.10.0'} + + is-valid-glob@1.0.0: + resolution: {integrity: sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==} + engines: {node: '>=0.10.0'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.3: + resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} + engines: {node: '>= 0.4'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + + jmespath@0.16.0: + resolution: {integrity: sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==} + engines: {node: '>= 0.6.0'} + + js-base64@3.7.2: + resolution: {integrity: sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + jssha@3.3.1: + resolution: {integrity: sha512-VCMZj12FCFMQYcFLPRm/0lOBbLi8uM2BhXPTqw3U4YAfs4AZfiApOoBLoN8cQE60Z50m1MYMTQVCfgF/KaCVhQ==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + last-run@2.0.0: + resolution: {integrity: sha512-j+y6WhTLN4Itnf9j5ZQos1BGPCS8DAwmgMroR3OzfxAsBxam0hMw7J8M3KqZl0pLQJ1jNnwIexg5DYpC/ctwEQ==} + engines: {node: '>= 10.13.0'} + + lead@4.0.0: + resolution: {integrity: sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==} + engines: {node: '>=10.13.0'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + liftoff@5.0.0: + resolution: {integrity: sha512-a5BQjbCHnB+cy+gsro8lXJ4kZluzOijzJ1UVVfyJYZC+IP2pLv1h4+aysQeKuTmyO8NAqfyQAk4HWaP/HjcKTg==} + engines: {node: '>=10.13.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + + luxon@3.3.0: + resolution: {integrity: sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==} + engines: {node: '>=12'} + + map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + + md5@2.3.0: + resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mute-stdout@2.0.0: + resolution: {integrity: sha512-32GSKM3Wyc8dg/p39lWPKYu8zci9mJFzV1Np9Of0ZEpe6Fhssn/FbI7ywAMd40uX+p3ZKh3T5EeCFv81qS3HmQ==} + engines: {node: '>= 10.13.0'} + + n8n-workflow@1.48.0: + resolution: {integrity: sha512-zHeOHhlf7BB2+DeAcm81+sJfmss8u/TE3KLpc/vCRc1vPonvF0iN5X5/DskHTGKPyXrP6N7wR6bkGWEXN7w08A==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + now-and-later@3.0.0: + resolution: {integrity: sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==} + engines: {node: '>= 10.13.0'} + + object-inspect@1.13.3: + resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} + engines: {node: '>= 0.4'} + + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + + object.defaults@1.1.0: + resolution: {integrity: sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==} + engines: {node: '>=0.10.0'} + + object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-filepath@1.0.2: + resolution: {integrity: sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==} + engines: {node: '>=0.8'} + + parse-passwd@1.0.0: + resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} + engines: {node: '>=0.10.0'} + + pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-root-regex@0.1.2: + resolution: {integrity: sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==} + engines: {node: '>=0.10.0'} + + path-root@0.1.1: + resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==} + engines: {node: '>=0.10.0'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.4.2: + resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} + engines: {node: '>=14'} + hasBin: true + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + queue-tick@1.0.1: + resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + recast@0.21.5: + resolution: {integrity: sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==} + engines: {node: '>= 4'} + + recast@0.22.0: + resolution: {integrity: sha512-5AAx+mujtXijsEavc5lWXBPQqrM4+Dl5qNH96N2aNeuJFUzpiiToKPsxQD/zAIJHspz7zz0maX0PCtCTFVlixQ==} + engines: {node: '>= 4'} + + rechoir@0.8.0: + resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} + engines: {node: '>= 10.13.0'} + + regexp.prototype.flags@1.5.3: + resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==} + engines: {node: '>= 0.4'} + + remove-trailing-separator@1.1.0: + resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} + + replace-ext@2.0.0: + resolution: {integrity: sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==} + engines: {node: '>= 10'} + + replace-homedir@2.0.0: + resolution: {integrity: sha512-bgEuQQ/BHW0XkkJtawzrfzHFSN70f/3cNOiHa2QsYxqrjaC30X1k74FJ6xswVBP0sr0SpGIdVFuPwfrYziVeyw==} + engines: {node: '>= 10.13.0'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-dir@1.0.1: + resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-options@2.0.0: + resolution: {integrity: sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==} + engines: {node: '>= 10.13.0'} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sax@1.4.1: + resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} + + semver-greatest-satisfied-range@2.0.0: + resolution: {integrity: sha512-lH3f6kMbwyANB7HuOWRMlLCa2itaCrZJ+SAqqkSZrZKO/cAsk2EOyaKHUtNkVLFyFW9pct22SFesFp3Z7zpA0g==} + engines: {node: '>= 10.13.0'} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + + sentence-case@3.0.4: + resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sparkles@2.1.0: + resolution: {integrity: sha512-r7iW1bDw8R/cFifrD3JnQJX0K1jqT0kprL48BiBpLZLJPmAm34zsVBsK5lc7HirZYZqMW65dOXZgbAGt/I6frg==} + engines: {node: '>= 10.13.0'} + + stop-iteration-iterator@1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} + + stream-composer@1.0.2: + resolution: {integrity: sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==} + + stream-exhaust@1.0.2: + resolution: {integrity: sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==} + + streamx@2.21.0: + resolution: {integrity: sha512-Qz6MsDZXJ6ur9u+b+4xCG18TluU7PGlRfXVAAjNiGsFrBUt/ioyLkxbFaKJygoPs+/kW4VyBj0bSj89Qu0IGyg==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + sver@1.8.4: + resolution: {integrity: sha512-71o1zfzyawLfIWBOmw8brleKyvnbn73oVHNCsu51uPMz/HWiKkkXsI31JjHW5zqXEqnPYkIiHd8ZmL7FCimLEA==} + + teex@1.0.1: + resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==} + + text-decoder@1.2.1: + resolution: {integrity: sha512-x9v3H/lTKIJKQQe7RPQkLfKAnc9lUTkWDypIQgTzPJAq+5/GCDHonmshfvlsNSj58yyshbIJJDLmU15qNERrXQ==} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + title-case@3.0.3: + resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + to-through@3.0.0: + resolution: {integrity: sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==} + engines: {node: '>=10.13.0'} + + transliteration@2.3.5: + resolution: {integrity: sha512-HAGI4Lq4Q9dZ3Utu2phaWgtm3vB6PkLUFqWAScg/UW+1eZ/Tg6Exo4oC0/3VUol/w4BlefLhUUSVBr/9/ZGQOw==} + engines: {node: '>=6.0.0'} + hasBin: true + + ts-api-utils@1.4.3: + resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + typescript@5.7.2: + resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} + engines: {node: '>=14.17'} + hasBin: true + + unc-path-regex@0.1.2: + resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} + engines: {node: '>=0.10.0'} + + undertaker-registry@2.0.0: + resolution: {integrity: sha512-+hhVICbnp+rlzZMgxXenpvTxpuvA67Bfgtt+O9WOE5jo7w/dyiF1VmoZVIHvP2EkUjsyKyTwYKlLhA+j47m1Ew==} + engines: {node: '>= 10.13.0'} + + undertaker@2.0.0: + resolution: {integrity: sha512-tO/bf30wBbTsJ7go80j0RzA2rcwX6o7XPBpeFcb+jzoeb4pfMM2zUeSDIkY1AWqeZabWxaQZ/h8N9t35QKDLPQ==} + engines: {node: '>=10.13.0'} + + upper-case-first@2.0.2: + resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + + v8flags@4.0.1: + resolution: {integrity: sha512-fcRLaS4H/hrZk9hYwbdRM35D0U8IYMfEClhXxCivOojl+yTRAZH3Zy2sSy6qVCiGbV9YAtPssP6jaChqC9vPCg==} + engines: {node: '>= 10.13.0'} + + value-or-function@4.0.0: + resolution: {integrity: sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==} + engines: {node: '>= 10.13.0'} + + vinyl-contents@2.0.0: + resolution: {integrity: sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==} + engines: {node: '>=10.13.0'} + + vinyl-fs@4.0.0: + resolution: {integrity: sha512-7GbgBnYfaquMk3Qu9g22x000vbYkOex32930rBnc3qByw6HfMEAoELjCjoJv4HuEQxHAurT+nvMHm6MnJllFLw==} + engines: {node: '>=10.13.0'} + + vinyl-sourcemap@2.0.0: + resolution: {integrity: sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==} + engines: {node: '>=10.13.0'} + + vinyl@3.0.0: + resolution: {integrity: sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==} + engines: {node: '>=10.13.0'} + + which-boxed-primitive@1.1.0: + resolution: {integrity: sha512-Ei7Miu/AXe2JJ4iNF5j/UphAgRoma4trE6PtisM09bPygb3egMH3YLW/befsWb1A1AxvNSFidOFTB18XtnIIng==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.16: + resolution: {integrity: sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==} + engines: {node: '>= 0.4'} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + xml2js@0.6.2: + resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} + engines: {node: '>=4.0.0'} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@eslint-community/eslint-utils@4.4.1(eslint@8.57.1)': + dependencies: + eslint: 8.57.1 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/eslintrc@2.1.4': + dependencies: + ajv: 6.12.6 + debug: 4.3.7 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.2 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@8.57.1': {} + + '@gulpjs/messages@1.1.0': {} + + '@gulpjs/to-absolute-glob@4.0.0': + dependencies: + is-negated-glob: 1.0.0 + + '@humanwhocodes/config-array@0.13.0': + dependencies: + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.7 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/object-schema@2.0.3': {} + + '@n8n/tournament@1.0.2': + dependencies: + '@n8n_io/riot-tmpl': 4.0.1 + ast-types: 0.16.1 + esprima-next: 5.8.4 + recast: 0.22.0 + + '@n8n_io/riot-tmpl@4.0.0': + dependencies: + eslint-config-riot: 1.0.0 + + '@n8n_io/riot-tmpl@4.0.1': + dependencies: + eslint-config-riot: 1.0.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@types/json-schema@7.0.15': {} + + '@types/semver@7.5.8': {} + + '@typescript-eslint/parser@8.17.0(eslint@8.57.1)(typescript@5.7.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.17.0 + '@typescript-eslint/types': 8.17.0 + '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.17.0 + debug: 4.3.7 + eslint: 8.57.1 + optionalDependencies: + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@6.21.0': + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + + '@typescript-eslint/scope-manager@8.17.0': + dependencies: + '@typescript-eslint/types': 8.17.0 + '@typescript-eslint/visitor-keys': 8.17.0 + + '@typescript-eslint/types@6.21.0': {} + + '@typescript-eslint/types@8.17.0': {} + + '@typescript-eslint/typescript-estree@6.21.0(typescript@5.7.2)': + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.7 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.6.3 + ts-api-utils: 1.4.3(typescript@5.7.2) + optionalDependencies: + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/typescript-estree@8.17.0(typescript@5.7.2)': + dependencies: + '@typescript-eslint/types': 8.17.0 + '@typescript-eslint/visitor-keys': 8.17.0 + debug: 4.3.7 + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.4.3(typescript@5.7.2) + optionalDependencies: + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@5.7.2)': + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.7.2) + eslint: 8.57.1 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/visitor-keys@6.21.0': + dependencies: + '@typescript-eslint/types': 6.21.0 + eslint-visitor-keys: 3.4.3 + + '@typescript-eslint/visitor-keys@8.17.0': + dependencies: + '@typescript-eslint/types': 8.17.0 + eslint-visitor-keys: 4.2.0 + + '@ungap/structured-clone@1.2.0': {} + + acorn-jsx@5.3.2(acorn@8.14.0): + dependencies: + acorn: 8.14.0 + + acorn@8.14.0: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + argparse@2.0.1: {} + + array-each@1.0.1: {} + + array-slice@1.1.0: {} + + array-union@2.1.0: {} + + assert@2.1.0: + dependencies: + call-bind: 1.0.7 + is-nan: 1.3.2 + object-is: 1.1.6 + object.assign: 4.1.5 + util: 0.12.5 + + ast-types@0.15.2: + dependencies: + tslib: 2.8.1 + + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + + async-done@2.0.0: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + stream-exhaust: 1.0.2 + + async-settle@2.0.0: + dependencies: + async-done: 2.0.0 + + asynckit@0.4.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.0.0 + + axios@1.6.7: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + bach@2.0.1: + dependencies: + async-done: 2.0.0 + async-settle: 2.0.0 + now-and-later: 3.0.0 + + balanced-match@1.0.2: {} + + bare-events@2.5.0: + optional: true + + base64-js@1.5.1: {} + + binary-extensions@2.3.0: {} + + bl@5.1.0: + dependencies: + buffer: 6.0.3 + inherits: 2.0.4 + readable-stream: 3.6.2 + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + call-bind@1.0.7: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + + callsites@3.1.0: {} + + camel-case@4.1.2: + dependencies: + pascal-case: 3.1.2 + tslib: 2.8.1 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + charenc@0.0.2: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone-stats@1.0.0: {} + + clone@2.1.2: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + concat-map@0.0.1: {} + + convert-source-map@2.0.0: {} + + copy-props@4.0.0: + dependencies: + each-props: 3.0.0 + is-plain-object: 5.0.0 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypt@0.0.2: {} + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + deep-equal@2.2.0: + dependencies: + call-bind: 1.0.7 + es-get-iterator: 1.1.3 + get-intrinsic: 1.2.4 + is-arguments: 1.1.1 + is-array-buffer: 3.0.4 + is-date-object: 1.0.5 + is-regex: 1.2.0 + is-shared-array-buffer: 1.0.3 + isarray: 2.0.5 + object-is: 1.1.6 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.3 + side-channel: 1.0.6 + which-boxed-primitive: 1.1.0 + which-collection: 1.0.2 + which-typed-array: 1.1.16 + + deep-is@0.1.4: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + delayed-stream@1.0.0: {} + + detect-file@1.0.0: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + each-props@3.0.0: + dependencies: + is-plain-object: 5.0.0 + object.defaults: 1.1.0 + + emoji-regex@8.0.0: {} + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + es-define-property@1.0.0: + dependencies: + get-intrinsic: 1.2.4 + + es-errors@1.3.0: {} + + es-get-iterator@1.1.3: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.1.0 + is-arguments: 1.1.1 + is-map: 2.0.3 + is-set: 2.0.3 + is-string: 1.1.0 + isarray: 2.0.5 + stop-iteration-iterator: 1.0.0 + + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-riot@1.0.0: {} + + eslint-plugin-local@1.0.0: {} + + eslint-plugin-n8n-nodes-base@1.16.3(eslint@8.57.1)(typescript@5.7.2): + dependencies: + '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.7.2) + camel-case: 4.1.2 + eslint-plugin-local: 1.0.0 + indefinite: 2.5.1 + pascal-case: 3.1.2 + pluralize: 8.0.0 + sentence-case: 3.0.4 + title-case: 3.0.3 + transitivePeerDependencies: + - eslint + - supports-color + - typescript + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.0: {} + + eslint@8.57.1: + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@eslint-community/regexpp': 4.12.1 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.1 + '@humanwhocodes/config-array': 0.13.0 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.3.7 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + espree@9.6.1: + dependencies: + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 3.4.3 + + esprima-next@5.8.4: {} + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + expand-tilde@2.0.2: + dependencies: + homedir-polyfill: 1.0.3 + + extend@3.0.2: {} + + fast-deep-equal@3.1.3: {} + + fast-fifo@1.3.2: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-levenshtein@3.0.0: + dependencies: + fastest-levenshtein: 1.0.16 + + fastest-levenshtein@1.0.16: {} + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + file-entry-cache@6.0.1: + dependencies: + flat-cache: 3.2.0 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + findup-sync@5.0.0: + dependencies: + detect-file: 1.0.0 + is-glob: 4.0.3 + micromatch: 4.0.8 + resolve-dir: 1.0.1 + + fined@2.0.0: + dependencies: + expand-tilde: 2.0.2 + is-plain-object: 5.0.0 + object.defaults: 1.1.0 + object.pick: 1.3.0 + parse-filepath: 1.0.2 + + flagged-respawn@2.0.0: {} + + flat-cache@3.2.0: + dependencies: + flatted: 3.3.2 + keyv: 4.5.4 + rimraf: 3.0.2 + + flatted@3.3.2: {} + + follow-redirects@1.15.9: {} + + for-each@0.3.3: + dependencies: + is-callable: 1.2.7 + + for-in@1.0.2: {} + + for-own@1.0.0: + dependencies: + for-in: 1.0.2 + + form-data@4.0.0: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + fs-mkdirp-stream@2.0.1: + dependencies: + graceful-fs: 4.2.11 + streamx: 2.21.0 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + functions-have-names@1.2.3: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.2.4: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.1.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob-stream@8.0.2: + dependencies: + '@gulpjs/to-absolute-glob': 4.0.0 + anymatch: 3.1.3 + fastq: 1.17.1 + glob-parent: 6.0.2 + is-glob: 4.0.3 + is-negated-glob: 1.0.0 + normalize-path: 3.0.0 + streamx: 2.21.0 + + glob-watcher@6.0.0: + dependencies: + async-done: 2.0.0 + chokidar: 3.6.0 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + global-modules@1.0.0: + dependencies: + global-prefix: 1.0.2 + is-windows: 1.0.2 + resolve-dir: 1.0.1 + + global-prefix@1.0.2: + dependencies: + expand-tilde: 2.0.2 + homedir-polyfill: 1.0.3 + ini: 1.3.8 + is-windows: 1.0.2 + which: 1.3.1 + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + glogg@2.2.0: + dependencies: + sparkles: 2.1.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + gulp-cli@3.0.0: + dependencies: + '@gulpjs/messages': 1.1.0 + chalk: 4.1.2 + copy-props: 4.0.0 + gulplog: 2.2.0 + interpret: 3.1.1 + liftoff: 5.0.0 + mute-stdout: 2.0.0 + replace-homedir: 2.0.0 + semver-greatest-satisfied-range: 2.0.0 + string-width: 4.2.3 + v8flags: 4.0.1 + yargs: 16.2.0 + + gulp@5.0.0: + dependencies: + glob-watcher: 6.0.0 + gulp-cli: 3.0.0 + undertaker: 2.0.0 + vinyl-fs: 4.0.0 + + gulplog@2.2.0: + dependencies: + glogg: 2.2.0 + + has-bigints@1.0.2: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.0 + + has-proto@1.1.0: + dependencies: + call-bind: 1.0.7 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + homedir-polyfill@1.0.3: + dependencies: + parse-passwd: 1.0.0 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + indefinite@2.5.1: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ini@1.3.8: {} + + internal-slot@1.0.7: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.0.6 + + interpret@3.1.1: {} + + is-absolute@1.0.0: + dependencies: + is-relative: 1.0.0 + is-windows: 1.0.2 + + is-arguments@1.1.1: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-array-buffer@3.0.4: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.0.2 + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-boolean-object@1.2.0: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-buffer@1.1.6: {} + + is-callable@1.2.7: {} + + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + + is-date-object@1.0.5: + dependencies: + has-tostringtag: 1.0.2 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.0.10: + dependencies: + has-tostringtag: 1.0.2 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-nan@1.3.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + + is-negated-glob@1.0.0: {} + + is-number-object@1.1.0: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-path-inside@3.0.3: {} + + is-plain-object@5.0.0: {} + + is-regex@1.2.0: + dependencies: + call-bind: 1.0.7 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-relative@1.0.0: + dependencies: + is-unc-path: 1.0.0 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.3: + dependencies: + call-bind: 1.0.7 + + is-string@1.1.0: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-symbol@1.1.0: + dependencies: + call-bind: 1.0.7 + has-symbols: 1.1.0 + safe-regex-test: 1.0.3 + + is-typed-array@1.1.13: + dependencies: + which-typed-array: 1.1.16 + + is-unc-path@1.0.0: + dependencies: + unc-path-regex: 0.1.2 + + is-valid-glob@1.0.0: {} + + is-weakmap@2.0.2: {} + + is-weakset@2.0.3: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + + is-windows@1.0.2: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isobject@3.0.1: {} + + jmespath@0.16.0: {} + + js-base64@3.7.2: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + jssha@3.3.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + last-run@2.0.0: {} + + lead@4.0.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + liftoff@5.0.0: + dependencies: + extend: 3.0.2 + findup-sync: 5.0.0 + fined: 2.0.0 + flagged-respawn: 2.0.0 + is-plain-object: 5.0.0 + rechoir: 0.8.0 + resolve: 1.22.8 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + lodash@4.17.21: {} + + lower-case@2.0.2: + dependencies: + tslib: 2.8.1 + + luxon@3.3.0: {} + + map-cache@0.2.2: {} + + md5@2.3.0: + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + is-buffer: 1.1.6 + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.3: + dependencies: + brace-expansion: 2.0.1 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + ms@2.1.3: {} + + mute-stdout@2.0.0: {} + + n8n-workflow@1.48.0: + dependencies: + '@n8n/tournament': 1.0.2 + '@n8n_io/riot-tmpl': 4.0.0 + ast-types: 0.15.2 + axios: 1.6.7 + callsites: 3.1.0 + deep-equal: 2.2.0 + esprima-next: 5.8.4 + form-data: 4.0.0 + jmespath: 0.16.0 + js-base64: 3.7.2 + jssha: 3.3.1 + lodash: 4.17.21 + luxon: 3.3.0 + md5: 2.3.0 + recast: 0.21.5 + title-case: 3.0.3 + transliteration: 2.3.5 + xml2js: 0.6.2 + transitivePeerDependencies: + - debug + + natural-compare@1.4.0: {} + + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + + normalize-path@3.0.0: {} + + now-and-later@3.0.0: + dependencies: + once: 1.4.0 + + object-inspect@1.13.3: {} + + object-is@1.1.6: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + + object-keys@1.1.1: {} + + object.assign@4.1.5: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.defaults@1.1.0: + dependencies: + array-each: 1.0.1 + array-slice: 1.1.0 + for-own: 1.0.0 + isobject: 3.0.1 + + object.pick@1.3.0: + dependencies: + isobject: 3.0.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-filepath@1.0.2: + dependencies: + is-absolute: 1.0.0 + map-cache: 0.2.2 + path-root: 0.1.1 + + parse-passwd@1.0.0: {} + + pascal-case@3.1.2: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-root-regex@0.1.2: {} + + path-root@0.1.1: + dependencies: + path-root-regex: 0.1.2 + + path-type@4.0.0: {} + + picomatch@2.3.1: {} + + pluralize@8.0.0: {} + + possible-typed-array-names@1.0.0: {} + + prelude-ls@1.2.1: {} + + prettier@3.4.2: {} + + proxy-from-env@1.1.0: {} + + punycode@2.3.1: {} + + queue-microtask@1.2.3: {} + + queue-tick@1.0.1: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + recast@0.21.5: + dependencies: + ast-types: 0.15.2 + esprima: 4.0.1 + source-map: 0.6.1 + tslib: 2.8.1 + + recast@0.22.0: + dependencies: + assert: 2.1.0 + ast-types: 0.15.2 + esprima: 4.0.1 + source-map: 0.6.1 + tslib: 2.8.1 + + rechoir@0.8.0: + dependencies: + resolve: 1.22.8 + + regexp.prototype.flags@1.5.3: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + + remove-trailing-separator@1.1.0: {} + + replace-ext@2.0.0: {} + + replace-homedir@2.0.0: {} + + require-directory@2.1.1: {} + + resolve-dir@1.0.1: + dependencies: + expand-tilde: 2.0.2 + global-modules: 1.0.0 + + resolve-from@4.0.0: {} + + resolve-options@2.0.0: + dependencies: + value-or-function: 4.0.0 + + resolve@1.22.8: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.0.4: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-buffer@5.2.1: {} + + safe-regex-test@1.0.3: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-regex: 1.2.0 + + safer-buffer@2.1.2: {} + + sax@1.4.1: {} + + semver-greatest-satisfied-range@2.0.0: + dependencies: + sver: 1.8.4 + + semver@6.3.1: + optional: true + + semver@7.6.3: {} + + sentence-case@3.0.4: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + upper-case-first: 2.0.2 + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel@1.0.6: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.3 + + slash@3.0.0: {} + + source-map@0.6.1: {} + + sparkles@2.1.0: {} + + stop-iteration-iterator@1.0.0: + dependencies: + internal-slot: 1.0.7 + + stream-composer@1.0.2: + dependencies: + streamx: 2.21.0 + + stream-exhaust@1.0.2: {} + + streamx@2.21.0: + dependencies: + fast-fifo: 1.3.2 + queue-tick: 1.0.1 + text-decoder: 1.2.1 + optionalDependencies: + bare-events: 2.5.0 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + sver@1.8.4: + optionalDependencies: + semver: 6.3.1 + + teex@1.0.1: + dependencies: + streamx: 2.21.0 + + text-decoder@1.2.1: {} + + text-table@0.2.0: {} + + title-case@3.0.3: + dependencies: + tslib: 2.8.1 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + to-through@3.0.0: + dependencies: + streamx: 2.21.0 + + transliteration@2.3.5: + dependencies: + yargs: 17.7.2 + + ts-api-utils@1.4.3(typescript@5.7.2): + dependencies: + typescript: 5.7.2 + + tslib@2.8.1: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.20.2: {} + + typescript@5.7.2: {} + + unc-path-regex@0.1.2: {} + + undertaker-registry@2.0.0: {} + + undertaker@2.0.0: + dependencies: + bach: 2.0.1 + fast-levenshtein: 3.0.0 + last-run: 2.0.0 + undertaker-registry: 2.0.0 + + upper-case-first@2.0.2: + dependencies: + tslib: 2.8.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.1.1 + is-generator-function: 1.0.10 + is-typed-array: 1.1.13 + which-typed-array: 1.1.16 + + v8flags@4.0.1: {} + + value-or-function@4.0.0: {} + + vinyl-contents@2.0.0: + dependencies: + bl: 5.1.0 + vinyl: 3.0.0 + + vinyl-fs@4.0.0: + dependencies: + fs-mkdirp-stream: 2.0.1 + glob-stream: 8.0.2 + graceful-fs: 4.2.11 + iconv-lite: 0.6.3 + is-valid-glob: 1.0.0 + lead: 4.0.0 + normalize-path: 3.0.0 + resolve-options: 2.0.0 + stream-composer: 1.0.2 + streamx: 2.21.0 + to-through: 3.0.0 + value-or-function: 4.0.0 + vinyl: 3.0.0 + vinyl-sourcemap: 2.0.0 + + vinyl-sourcemap@2.0.0: + dependencies: + convert-source-map: 2.0.0 + graceful-fs: 4.2.11 + now-and-later: 3.0.0 + streamx: 2.21.0 + vinyl: 3.0.0 + vinyl-contents: 2.0.0 + + vinyl@3.0.0: + dependencies: + clone: 2.1.2 + clone-stats: 1.0.0 + remove-trailing-separator: 1.1.0 + replace-ext: 2.0.0 + teex: 1.0.1 + + which-boxed-primitive@1.1.0: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.0 + is-number-object: 1.1.0 + is-string: 1.1.0 + is-symbol: 1.1.0 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.3 + + which-typed-array@1.1.16: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrappy@1.0.2: {} + + xml2js@0.6.2: + dependencies: + sax: 1.4.1 + xmlbuilder: 11.0.1 + + xmlbuilder@11.0.1: {} + + y18n@5.0.8: {} + + yargs-parser@20.2.9: {} + + yargs-parser@21.1.1: {} + + yargs@16.2.0: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {}