n8n-nodes-underchat 0.1.12 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -2
- package/dist/nodes/UnderChat/GenericFunctions.d.ts +2 -0
- package/dist/nodes/UnderChat/GenericFunctions.js +30 -0
- package/dist/nodes/UnderChat/GenericFunctions.js.map +1 -1
- package/dist/nodes/UnderChat/SendMessage.d.ts +10 -0
- package/dist/nodes/UnderChat/SendMessage.js +90 -0
- package/dist/nodes/UnderChat/SendMessage.js.map +1 -0
- package/dist/nodes/UnderChat/StartChatByPhone.d.ts +4 -0
- package/dist/nodes/UnderChat/StartChatByPhone.js +445 -0
- package/dist/nodes/UnderChat/StartChatByPhone.js.map +1 -0
- package/dist/nodes/UnderChat/UnderChat.node.d.ts +5 -0
- package/dist/nodes/UnderChat/UnderChat.node.js +265 -27
- package/dist/nodes/UnderChat/UnderChat.node.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,8 +8,9 @@ Community Node do n8n para integrar workflows à API pública da UnderChat.
|
|
|
8
8
|
- Entrar em um atendimento aguardando com o executor selecionado
|
|
9
9
|
- Buscar ID do contato pelo telefone
|
|
10
10
|
- Criar contato
|
|
11
|
-
-
|
|
12
|
-
- Enviar
|
|
11
|
+
- Buscar/criar o contato e iniciar um atendimento em uma única operação
|
|
12
|
+
- Enviar texto, documento ou imagem por `chat_id`
|
|
13
|
+
- Enviar texto, documento ou imagem por telefone, criando o contato quando necessário
|
|
13
14
|
- Enviar template oficial em uma conversa
|
|
14
15
|
- Listar executores, usuários e setores
|
|
15
16
|
- Transferir um chat para outro usuário, setor ou worker
|
|
@@ -28,6 +29,85 @@ A operação **Enviar mensagem por telefone** executa automaticamente:
|
|
|
28
29
|
buscar contato → criar se necessário → iniciar conversa → enviar mensagem
|
|
29
30
|
```
|
|
30
31
|
|
|
32
|
+
## Envio de texto, documento ou imagem
|
|
33
|
+
|
|
34
|
+
As operações **Enviar Mensagem Por Chat ID** e **Enviar Mensagem Por Telefone**
|
|
35
|
+
oferecem o campo **O que deseja enviar?**:
|
|
36
|
+
|
|
37
|
+
- **Texto:** envia `type=text` e a mensagem em JSON, mantendo o comportamento das
|
|
38
|
+
versões anteriores do node.
|
|
39
|
+
- **Documento:** envia o arquivo como documento e aceita uma legenda opcional.
|
|
40
|
+
- **Imagem:** envia a imagem para ser exibida diretamente na conversa e também
|
|
41
|
+
aceita uma legenda opcional.
|
|
42
|
+
|
|
43
|
+
Quando o node anterior fornecer apenas um arquivo, ele será selecionado
|
|
44
|
+
automaticamente. Se houver mais de um, use **Opções Avançadas > Arquivo A Enviar**
|
|
45
|
+
para escolher. O nome original e o tipo do arquivo são preservados no upload, e
|
|
46
|
+
cada item de entrada envia um arquivo.
|
|
47
|
+
|
|
48
|
+
Internamente, documentos usam `type=document` e o campo `documents`; imagens usam
|
|
49
|
+
`type=image` e o campo `images`. O cliente HTTP do n8n prepara automaticamente o
|
|
50
|
+
`multipart/form-data`, inclusive o boundary correto; o usuário não precisa
|
|
51
|
+
configurar headers ou parâmetros técnicos.
|
|
52
|
+
|
|
53
|
+
## Buscar/criar contato e iniciar atendimento
|
|
54
|
+
|
|
55
|
+
A operação **Buscar/Criar Contato E Iniciar Atendimento** (`startChatByPhone`)
|
|
56
|
+
substitui a sequência manual de nodes usada para localizar ou cadastrar o contato,
|
|
57
|
+
obter seu ID e abrir a conversa. Ela recebe o telefone diretamente e executa:
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
buscar pelo telefone → criar se não existir → buscar o ID novamente
|
|
61
|
+
→ validar canal e setor → reutilizar um chat ativo ou iniciar o atendimento
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Configure os seguintes campos:
|
|
65
|
+
|
|
66
|
+
- **Executor:** usuário ativo que realiza as chamadas à API.
|
|
67
|
+
- **DDI** e **Telefone:** usados na busca exata; informe o telefone sem o DDI.
|
|
68
|
+
- **Nome para novo contato:** usado somente quando o contato não existe.
|
|
69
|
+
- **Criar se não existir:** ativado por padrão. Quando desativado, a operação falha
|
|
70
|
+
sem criar dados caso o telefone não seja encontrado.
|
|
71
|
+
- **Canal:** obrigatório em toda nova abertura, oficial ou não.
|
|
72
|
+
- **Setor:** obrigatório em toda nova abertura, oficial ou não.
|
|
73
|
+
- **Template oficial** e **Variáveis:** usados quando as regras do canal oficial
|
|
74
|
+
exigirem um template aprovado.
|
|
75
|
+
|
|
76
|
+
O usuário não precisa consultar nem transportar o `contact_id`. A API de criação
|
|
77
|
+
de contato não devolve esse ID; por isso o node consulta novamente o telefone após
|
|
78
|
+
uma criação bem-sucedida e só então inicia o atendimento. Se já existir um chat
|
|
79
|
+
ativo no mesmo canal e setor, ele é reutilizado em vez de criar outro. Um chat no
|
|
80
|
+
mesmo canal, mas em outro setor, não é movido silenciosamente: use a operação de
|
|
81
|
+
transferência ou selecione o setor atual.
|
|
82
|
+
|
|
83
|
+
O cadastro do contato e a abertura do atendimento são chamadas separadas da API.
|
|
84
|
+
Se a criação funcionar e uma validação posterior ou a abertura falhar, o contato
|
|
85
|
+
permanece cadastrado. Uma nova execução o localizará e reutilizará, sem duplicá-lo.
|
|
86
|
+
|
|
87
|
+
### Canal oficial e templates
|
|
88
|
+
|
|
89
|
+
Depois de resolver o contato, o node consulta o contexto oficial usando o canal e
|
|
90
|
+
o `contact_id`. Ele respeita a janela retornada pela UnderChat:
|
|
91
|
+
|
|
92
|
+
- texto livre só pode ser enviado quando `can_send_freeform` permitir;
|
|
93
|
+
- um template só pode ser usado quando estiver aprovado e disponível no contexto;
|
|
94
|
+
- quando `requires_template` estiver ativo, a abertura não continua sem um template
|
|
95
|
+
aprovado e todos os valores obrigatórios;
|
|
96
|
+
- `key`, componente, posição, nome do parâmetro e índice de botão vêm da API; o
|
|
97
|
+
usuário informa apenas os valores das variáveis, pelos campos ou em JSON;
|
|
98
|
+
- o template é enviado junto da abertura do chat, evitando depender de um
|
|
99
|
+
`chat_id` criado em um node anterior.
|
|
100
|
+
|
|
101
|
+
O campo **Template oficial** usa o seletor do n8n e também permite informar o nome
|
|
102
|
+
manualmente. A API pública lista os templates no contexto oficial, que exige um
|
|
103
|
+
`contact_id`. Quando o telefone é dinâmico ou o contato ainda não existe, o node
|
|
104
|
+
usa um contato já vinculado ao canal somente para carregar o catálogo no editor,
|
|
105
|
+
sem criar nem alterar dados. Na execução, ele consulta novamente o contexto com o
|
|
106
|
+
contato real e recusa qualquer template que não esteja aprovado ou cujas variáveis
|
|
107
|
+
não correspondam ao contrato retornado. Se o canal ainda não tiver nenhum contato,
|
|
108
|
+
o catálogo não poderá ser carregado antecipadamente; nesse caso ainda é possível
|
|
109
|
+
usar o modo manual/JSON, com a mesma validação rigorosa durante a execução.
|
|
110
|
+
|
|
31
111
|
Na operação **Transferir para setor ou usuário**, ative **Entrar no atendimento
|
|
32
112
|
antes de transferir** quando o chat ainda estiver aguardando atendimento. O node
|
|
33
113
|
muda o status para `in_chat` e, após a confirmação da API, realiza a transferência.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { IDataObject, IExecuteFunctions, IHttpRequestMethods, ILoadOptionsFunctions } from 'n8n-workflow';
|
|
2
2
|
export declare function underChatApiRequest(this: IExecuteFunctions | ILoadOptionsFunctions, method: IHttpRequestMethods, endpoint: string, body?: IDataObject, qs?: IDataObject, executorId?: string): Promise<IDataObject>;
|
|
3
3
|
export declare function responseData(response: IDataObject): unknown;
|
|
4
|
+
export declare function underChatApiMultipartRequest(this: IExecuteFunctions, endpoint: string, formData: IDataObject, executorId: string): Promise<IDataObject>;
|
|
5
|
+
export declare function underChatApiMediaRequest(this: IExecuteFunctions, endpoint: string, formData: FormData, executorId: string): Promise<IDataObject>;
|
|
4
6
|
export declare function collectionRecords(value: unknown): IDataObject[];
|
|
5
7
|
export declare function firstRecord(response: IDataObject): IDataObject | undefined;
|
|
6
8
|
export declare function getOpaqueId(record: IDataObject | undefined, names: string[]): string | undefined;
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.underChatApiRequest = underChatApiRequest;
|
|
4
4
|
exports.responseData = responseData;
|
|
5
|
+
exports.underChatApiMultipartRequest = underChatApiMultipartRequest;
|
|
6
|
+
exports.underChatApiMediaRequest = underChatApiMediaRequest;
|
|
5
7
|
exports.collectionRecords = collectionRecords;
|
|
6
8
|
exports.firstRecord = firstRecord;
|
|
7
9
|
exports.getOpaqueId = getOpaqueId;
|
|
@@ -32,6 +34,34 @@ function responseData(response) {
|
|
|
32
34
|
var _a;
|
|
33
35
|
return (_a = response.data) !== null && _a !== void 0 ? _a : response;
|
|
34
36
|
}
|
|
37
|
+
async function underChatApiMultipartRequest(endpoint, formData, executorId) {
|
|
38
|
+
const credentials = await this.getCredentials('underChatApi');
|
|
39
|
+
const baseUrl = String(credentials.baseUrl).replace(/\/$/, '');
|
|
40
|
+
const options = {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
url: `${baseUrl}${endpoint}`,
|
|
43
|
+
body: formData,
|
|
44
|
+
json: true,
|
|
45
|
+
headers: {
|
|
46
|
+
'content-type': 'multipart/form-data',
|
|
47
|
+
'x-underchat-user-id': executorId,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
return (await this.helpers.httpRequestWithAuthentication.call(this, 'underChatApi', options));
|
|
51
|
+
}
|
|
52
|
+
async function underChatApiMediaRequest(endpoint, formData, executorId) {
|
|
53
|
+
const credentials = await this.getCredentials('underChatApi');
|
|
54
|
+
const baseUrl = String(credentials.baseUrl).replace(/\/$/, '');
|
|
55
|
+
const options = {
|
|
56
|
+
method: 'POST',
|
|
57
|
+
url: `${baseUrl}${endpoint}`,
|
|
58
|
+
body: formData,
|
|
59
|
+
json: true,
|
|
60
|
+
timeout: 120000,
|
|
61
|
+
headers: { 'x-underchat-user-id': executorId },
|
|
62
|
+
};
|
|
63
|
+
return (await this.helpers.httpRequestWithAuthentication.call(this, 'underChatApi', options));
|
|
64
|
+
}
|
|
35
65
|
function collectionRecords(value) {
|
|
36
66
|
if (Array.isArray(value)) {
|
|
37
67
|
return value.filter((item) => Boolean(item) && typeof item === 'object' && !Array.isArray(item));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GenericFunctions.js","sourceRoot":"","sources":["../../../nodes/UnderChat/GenericFunctions.ts"],"names":[],"mappings":";;AAQA,kDA6BC;AAED,oCAEC;AAED,8CAiBC;AAED,kCASC;AAED,kCAOC;AAED,0CAKC;AAED,0CAiBC;AAED,wCAKC;AAED,gDAIC;
|
|
1
|
+
{"version":3,"file":"GenericFunctions.js","sourceRoot":"","sources":["../../../nodes/UnderChat/GenericFunctions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IDataObject, IExecuteFunctions } from 'n8n-workflow';
|
|
2
|
+
export type PreparedChatMessage = {
|
|
3
|
+
kind: 'text';
|
|
4
|
+
body: IDataObject;
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'formData';
|
|
7
|
+
body: FormData;
|
|
8
|
+
};
|
|
9
|
+
export declare function prepareChatMessage(this: IExecuteFunctions, itemIndex: number): Promise<PreparedChatMessage>;
|
|
10
|
+
export declare function sendChatMessage(this: IExecuteFunctions, preparedMessage: PreparedChatMessage, chatId: string, executorId: string): Promise<IDataObject>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.prepareChatMessage = prepareChatMessage;
|
|
4
|
+
exports.sendChatMessage = sendChatMessage;
|
|
5
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
6
|
+
const GenericFunctions_1 = require("./GenericFunctions");
|
|
7
|
+
function binaryInputForItem(itemIndex) {
|
|
8
|
+
var _a;
|
|
9
|
+
const combined = this.getWorkflowSettings().binaryMode === n8n_workflow_1.BINARY_MODE_COMBINED;
|
|
10
|
+
const item = this.getInputData()[itemIndex];
|
|
11
|
+
const source = combined ? (_a = item === null || item === void 0 ? void 0 : item.json) === null || _a === void 0 ? void 0 : _a[n8n_workflow_1.BINARY_IN_JSON_PROPERTY] : item === null || item === void 0 ? void 0 : item.binary;
|
|
12
|
+
const values = source && typeof source === 'object' && !Array.isArray(source) ? source : {};
|
|
13
|
+
return { combined, values: values };
|
|
14
|
+
}
|
|
15
|
+
async function prepareChatMessage(itemIndex) {
|
|
16
|
+
var _a, _b, _c, _d;
|
|
17
|
+
const sendType = String(this.getNodeParameter('sendType', itemIndex, 'text'));
|
|
18
|
+
if (sendType === 'text') {
|
|
19
|
+
const message = this.getNodeParameter('message', itemIndex);
|
|
20
|
+
return { kind: 'text', body: { type: 'text', message } };
|
|
21
|
+
}
|
|
22
|
+
if (sendType !== 'document' && sendType !== 'image') {
|
|
23
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Tipo de envio não suportado: ${sendType}`, {
|
|
24
|
+
itemIndex,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const attachmentOptions = this.getNodeParameter('attachmentOptions', itemIndex, {});
|
|
28
|
+
const selectedBinaryProperty = typeof attachmentOptions.binaryPropertyName === 'string'
|
|
29
|
+
? attachmentOptions.binaryPropertyName.trim()
|
|
30
|
+
: '';
|
|
31
|
+
const binaryInput = binaryInputForItem.call(this, itemIndex);
|
|
32
|
+
const binaryProperties = Object.keys(binaryInput.values);
|
|
33
|
+
let binaryPropertyName = selectedBinaryProperty;
|
|
34
|
+
let binaryParameter;
|
|
35
|
+
if (binaryPropertyName) {
|
|
36
|
+
const selectedValue = binaryInput.values[binaryPropertyName];
|
|
37
|
+
binaryParameter =
|
|
38
|
+
selectedValue && typeof selectedValue === 'object'
|
|
39
|
+
? selectedValue
|
|
40
|
+
: binaryInput.combined
|
|
41
|
+
? `${n8n_workflow_1.BINARY_IN_JSON_PROPERTY}.${binaryPropertyName}`
|
|
42
|
+
: binaryPropertyName;
|
|
43
|
+
}
|
|
44
|
+
else if (binaryProperties.length === 1) {
|
|
45
|
+
[binaryPropertyName] = binaryProperties;
|
|
46
|
+
binaryParameter = binaryInput.values[binaryPropertyName];
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
if (binaryProperties.length > 1) {
|
|
50
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Mais de um arquivo foi recebido (${binaryProperties.join(', ')}). Em Opções Avançadas, escolha qual arquivo enviar.`, { itemIndex });
|
|
51
|
+
}
|
|
52
|
+
binaryPropertyName = 'data';
|
|
53
|
+
binaryParameter = binaryInput.combined
|
|
54
|
+
? `${n8n_workflow_1.BINARY_IN_JSON_PROPERTY}.${binaryPropertyName}`
|
|
55
|
+
: binaryPropertyName;
|
|
56
|
+
}
|
|
57
|
+
let binaryData;
|
|
58
|
+
try {
|
|
59
|
+
binaryData = this.helpers.assertBinaryData(itemIndex, binaryParameter);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
const errorMessage = selectedBinaryProperty
|
|
63
|
+
? `O arquivo escolhido ('${binaryPropertyName}') não foi encontrado nos dados de entrada.`
|
|
64
|
+
: 'Nenhum arquivo foi recebido. Conecte antes uma etapa que forneça o documento ou a imagem.';
|
|
65
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage, { itemIndex });
|
|
66
|
+
}
|
|
67
|
+
const normalizedMimeType = (_b = (_a = binaryData.mimeType) === null || _a === void 0 ? void 0 : _a.trim().toLowerCase()) !== null && _b !== void 0 ? _b : '';
|
|
68
|
+
if (sendType === 'image' && !normalizedMimeType.startsWith('image/')) {
|
|
69
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'O arquivo escolhido não é uma imagem. Selecione Documento ou forneça uma imagem válida.', { itemIndex });
|
|
70
|
+
}
|
|
71
|
+
const binaryBuffer = await this.helpers.getBinaryDataBuffer(itemIndex, binaryData);
|
|
72
|
+
const caption = this.getNodeParameter('caption', itemIndex, '').trim();
|
|
73
|
+
const mimeType = binaryData.mimeType || 'application/octet-stream';
|
|
74
|
+
const fileExtension = (_c = binaryData.fileExtension) === null || _c === void 0 ? void 0 : _c.trim().replace(/^\./, '');
|
|
75
|
+
const fileName = ((_d = binaryData.fileName) === null || _d === void 0 ? void 0 : _d.trim()) || `arquivo.${fileExtension || 'bin'}`;
|
|
76
|
+
const fileField = sendType === 'image' ? 'images' : 'documents';
|
|
77
|
+
const formData = new FormData();
|
|
78
|
+
formData.append('type', sendType);
|
|
79
|
+
if (caption)
|
|
80
|
+
formData.append('message', caption);
|
|
81
|
+
formData.append(fileField, new Blob([new Uint8Array(binaryBuffer)], { type: mimeType }), fileName);
|
|
82
|
+
return { kind: 'formData', body: formData };
|
|
83
|
+
}
|
|
84
|
+
async function sendChatMessage(preparedMessage, chatId, executorId) {
|
|
85
|
+
if (preparedMessage.kind === 'formData') {
|
|
86
|
+
return await GenericFunctions_1.underChatApiMediaRequest.call(this, `/chat/${chatId}`, preparedMessage.body, executorId);
|
|
87
|
+
}
|
|
88
|
+
return await GenericFunctions_1.underChatApiRequest.call(this, 'POST', `/chat/${chatId}`, preparedMessage.body, {}, executorId);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=SendMessage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SendMessage.js","sourceRoot":"","sources":["../../../nodes/UnderChat/SendMessage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IDataObject, IExecuteFunctions, ILoadOptionsFunctions, INodeListSearchResult, ResourceMapperFields } from 'n8n-workflow';
|
|
2
|
+
export declare function searchOfficialTemplates(this: ILoadOptionsFunctions, filter?: string): Promise<INodeListSearchResult>;
|
|
3
|
+
export declare function getOfficialTemplateVariables(this: ILoadOptionsFunctions): Promise<ResourceMapperFields>;
|
|
4
|
+
export declare function executeStartChatByPhone(this: IExecuteFunctions, itemIndex: number, executorId: string): Promise<IDataObject>;
|