n8n-nodes-digitalsac 0.2.8 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -110,30 +110,22 @@ Onde:
110
110
 
111
111
  ### Enviar Mensagem de Texto
112
112
  1. Selecione a operação **Enviar Mensagem**
113
- 2. No campo **Parâmetro**, insira o UUID da conexão
114
- 3. No campo **Dados (JSON)**, insira os dados no formato:
115
- ```json
116
- {
117
- "body": "Sua mensagem aqui",
118
- "number": "5511999999999",
119
- "externalKey": "chave_opcional"
120
- }
121
- ```
113
+ 2. No campo **Parâmetro**, insira o UUID da conexão (ex: 999ab3a2-9f1f-4ffb-969a-bfb72234ece1)
114
+ 3. No campo **Corpo da Mensagem**, insira o texto da mensagem
115
+ 4. No campo **Número de Telefone**, insira o número no formato DDI+DDD+Número (ex: 5511999999999)
116
+ 5. No campo **Chave Externa**, insira um identificador único opcional
122
117
 
123
118
  ### Enviar Arquivo
124
- 1. Conecte um nó que forneça dados binários (ex: HTTP Request, Read Binary File)
125
- 2. Selecione a operação **Enviar Mensagem**
126
- 3. No campo **Parâmetro**, insira o UUID da conexão
127
- 4. No campo **Dados (JSON)**, insira os dados no formato:
128
- ```json
129
- {
130
- "body": "Mensagem que acompanha o arquivo",
131
- "number": "5511999999999",
132
- "externalKey": "chave_opcional",
133
- "binaryPropertyName": "data"
134
- }
135
- ```
136
- Onde `data` é o nome da propriedade binária que contém o arquivo.
119
+ 1. Conecte um nó que forneça dados binários (ex: **HTTP Request**, **Read Binary File**, **Google Drive**)
120
+ 2. Conecte ao **Digitalsac**
121
+ 3. Selecione a operação **Enviar Mensagem**
122
+ 4. No campo **Parâmetro**, insira o UUID da conexão
123
+ 5. Preencha os demais campos normalmente
124
+ 6. O nó detectará automaticamente o arquivo binário e enviará via FormData
125
+
126
+ **Nota**: O nó detecta automaticamente se há dados binários conectados e escolhe o método correto:
127
+ - **Sem arquivo**: Envia como JSON (texto)
128
+ - **Com arquivo**: Envia como FormData (arquivo + texto)
137
129
 
138
130
  ### Listar Tags
139
131
  1. Selecione a operação **Listar Tags**
@@ -263,15 +255,10 @@ Onde:
263
255
  - Configure para ler um arquivo PDF
264
256
  2. Conecte ao nó **Digitalsac**
265
257
  - Operação: **Enviar Mensagem**
266
- - Parâmetro: `seu-uuid-de-conexão`
267
- - Dados (JSON):
268
- ```json
269
- {
270
- "body": "Segue o PDF solicitado",
271
- "number": "5511999999999",
272
- "binaryPropertyName": "data"
273
- }
274
- ```
258
+ - Parâmetro: `999ab3a2-9f1f-4ffb-969a-bfb72234ece1` (seu UUID de conexão)
259
+ - Corpo da Mensagem: `Segue o PDF solicitado`
260
+ - Número de Telefone: `5511999999999`
261
+ - Chave Externa: `pdf_documento_123`
275
262
 
276
263
  ### Transferir ticket para uma fila específica
277
264
  1. Adicione um nó **Digitalsac**
@@ -130,6 +130,18 @@ class Digitalsac {
130
130
  },
131
131
  description: 'Cor da tag em formato hexadecimal (ex: #FF5733, #2196F3, #4CAF50)',
132
132
  },
133
+ {
134
+ displayName: 'Dados (JSON)',
135
+ name: 'bodyData',
136
+ type: 'json',
137
+ default: '{"data": "2024-01-15"}',
138
+ displayOptions: {
139
+ show: {
140
+ operation: ['validateDate'],
141
+ },
142
+ },
143
+ description: 'Data a ser validada no formato JSON',
144
+ },
133
145
  {
134
146
  displayName: 'Dados (JSON)',
135
147
  name: 'bodyData',
@@ -137,10 +149,70 @@ class Digitalsac {
137
149
  default: '{"ticketId": 123, "queueId": 1}',
138
150
  displayOptions: {
139
151
  show: {
140
- operation: ['validateDate', 'transferQueue', 'transferAgent', 'closeTicket', 'linkTag', 'linkKanban', 'linkCarteira'],
152
+ operation: ['transferQueue'],
153
+ },
154
+ },
155
+ description: 'ID do ticket e ID da fila de destino',
156
+ },
157
+ {
158
+ displayName: 'Dados (JSON)',
159
+ name: 'bodyData',
160
+ type: 'json',
161
+ default: '{"ticketId": 123, "userId": 1}',
162
+ displayOptions: {
163
+ show: {
164
+ operation: ['transferAgent'],
165
+ },
166
+ },
167
+ description: 'ID do ticket e ID do atendente de destino',
168
+ },
169
+ {
170
+ displayName: 'Dados (JSON)',
171
+ name: 'bodyData',
172
+ type: 'json',
173
+ default: '{"ticketId": 123}',
174
+ displayOptions: {
175
+ show: {
176
+ operation: ['closeTicket'],
177
+ },
178
+ },
179
+ description: 'ID do ticket a ser fechado',
180
+ },
181
+ {
182
+ displayName: 'Dados (JSON)',
183
+ name: 'bodyData',
184
+ type: 'json',
185
+ default: '{"ticketId": 123, "tagId": 456}',
186
+ displayOptions: {
187
+ show: {
188
+ operation: ['linkTag'],
189
+ },
190
+ },
191
+ description: 'ID do ticket e ID da tag a ser vinculada',
192
+ },
193
+ {
194
+ displayName: 'Dados (JSON)',
195
+ name: 'bodyData',
196
+ type: 'json',
197
+ default: '{"ticketId": 123, "kanbanId": 456, "userId": 789}',
198
+ displayOptions: {
199
+ show: {
200
+ operation: ['linkKanban'],
201
+ },
202
+ },
203
+ description: 'ID do ticket, ID do kanban e ID do usuário',
204
+ },
205
+ {
206
+ displayName: 'Dados (JSON)',
207
+ name: 'bodyData',
208
+ type: 'json',
209
+ default: '{"ticketId": 123, "userId": 456}',
210
+ displayOptions: {
211
+ show: {
212
+ operation: ['linkCarteira'],
141
213
  },
142
214
  },
143
- description: 'Dados no formato JSON conforme a operação selecionada',
215
+ description: 'ID do ticket e ID do usuário da carteira',
144
216
  },
145
217
  ],
146
218
  };
@@ -249,26 +321,75 @@ class Digitalsac {
249
321
  };
250
322
  break;
251
323
  case 'sendMessage':
324
+ // Validar se o UUID foi fornecido
325
+ if (!param || param.trim() === '') {
326
+ throw new Error('UUID da conexão é obrigatório para enviar mensagem. Preencha o campo "Parâmetro" com o UUID da conexão.');
327
+ }
252
328
  url = `/v1/api/external/${param}`;
253
329
  method = 'POST';
254
330
  // Usar campos separados em vez de JSON
255
331
  const messageBody = this.getNodeParameter('messageBody', i);
256
332
  const phoneNumber = this.getNodeParameter('phoneNumber', i);
257
333
  const externalKey = this.getNodeParameter('externalKey', i);
258
- // Criar o objeto diretamente
259
- body = {
260
- body: messageBody,
261
- number: phoneNumber,
262
- externalKey: externalKey
263
- };
264
- headers['Content-Type'] = 'application/json';
265
- options = {
266
- method,
267
- headers,
268
- body,
269
- uri: `${baseUrl}${url}`,
270
- json: true,
271
- };
334
+ // Verificar se dados binários (para envio de arquivo)
335
+ let hasBinaryData = false;
336
+ let binaryData;
337
+ let binaryFileName;
338
+ let binaryContentType;
339
+ if (items[i].binary) {
340
+ const binary = items[i].binary;
341
+ // Procurar por qualquer propriedade binária disponível
342
+ const binaryKeys = Object.keys(binary);
343
+ if (binaryKeys.length > 0) {
344
+ const binaryPropertyName = binaryKeys[0]; // Usar a primeira propriedade binária encontrada
345
+ hasBinaryData = true;
346
+ const binaryProperty = binary[binaryPropertyName];
347
+ binaryData = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
348
+ binaryFileName = binaryProperty.fileName || 'file';
349
+ binaryContentType = binaryProperty.mimeType;
350
+ }
351
+ }
352
+ if (hasBinaryData && binaryData) {
353
+ // Enviar como FormData (para arquivos)
354
+ const formData = {
355
+ body: messageBody,
356
+ number: phoneNumber,
357
+ externalKey: externalKey,
358
+ media: {
359
+ value: binaryData,
360
+ options: {
361
+ filename: binaryFileName,
362
+ contentType: binaryContentType,
363
+ },
364
+ },
365
+ };
366
+ options = {
367
+ method,
368
+ headers: {
369
+ Authorization: `Bearer ${token}`,
370
+ Accept: 'application/json',
371
+ },
372
+ formData: formData,
373
+ uri: `${baseUrl}${url}`,
374
+ json: true,
375
+ };
376
+ }
377
+ else {
378
+ // Enviar como JSON (para texto)
379
+ body = {
380
+ body: messageBody,
381
+ number: phoneNumber,
382
+ externalKey: externalKey
383
+ };
384
+ headers['Content-Type'] = 'application/json';
385
+ options = {
386
+ method,
387
+ headers,
388
+ body,
389
+ uri: `${baseUrl}${url}`,
390
+ json: true,
391
+ };
392
+ }
272
393
  break;
273
394
  case 'listTags':
274
395
  url = '/typebot/listar_tags';
@@ -4,6 +4,8 @@ import {
4
4
  INodeType,
5
5
  INodeTypeDescription,
6
6
  NodeConnectionType,
7
+ IDataObject,
8
+ IBinaryKeyData,
7
9
  } from 'n8n-workflow';
8
10
 
9
11
  export class Digitalsac implements INodeType {
@@ -135,6 +137,18 @@ export class Digitalsac implements INodeType {
135
137
  },
136
138
  description: 'Cor da tag em formato hexadecimal (ex: #FF5733, #2196F3, #4CAF50)',
137
139
  },
140
+ {
141
+ displayName: 'Dados (JSON)',
142
+ name: 'bodyData',
143
+ type: 'json',
144
+ default: '{"data": "2024-01-15"}',
145
+ displayOptions: {
146
+ show: {
147
+ operation: ['validateDate'],
148
+ },
149
+ },
150
+ description: 'Data a ser validada no formato JSON',
151
+ },
138
152
  {
139
153
  displayName: 'Dados (JSON)',
140
154
  name: 'bodyData',
@@ -142,10 +156,70 @@ export class Digitalsac implements INodeType {
142
156
  default: '{"ticketId": 123, "queueId": 1}',
143
157
  displayOptions: {
144
158
  show: {
145
- operation: ['validateDate', 'transferQueue', 'transferAgent', 'closeTicket', 'linkTag', 'linkKanban', 'linkCarteira'],
159
+ operation: ['transferQueue'],
160
+ },
161
+ },
162
+ description: 'ID do ticket e ID da fila de destino',
163
+ },
164
+ {
165
+ displayName: 'Dados (JSON)',
166
+ name: 'bodyData',
167
+ type: 'json',
168
+ default: '{"ticketId": 123, "userId": 1}',
169
+ displayOptions: {
170
+ show: {
171
+ operation: ['transferAgent'],
146
172
  },
147
173
  },
148
- description: 'Dados no formato JSON conforme a operação selecionada',
174
+ description: 'ID do ticket e ID do atendente de destino',
175
+ },
176
+ {
177
+ displayName: 'Dados (JSON)',
178
+ name: 'bodyData',
179
+ type: 'json',
180
+ default: '{"ticketId": 123}',
181
+ displayOptions: {
182
+ show: {
183
+ operation: ['closeTicket'],
184
+ },
185
+ },
186
+ description: 'ID do ticket a ser fechado',
187
+ },
188
+ {
189
+ displayName: 'Dados (JSON)',
190
+ name: 'bodyData',
191
+ type: 'json',
192
+ default: '{"ticketId": 123, "tagId": 456}',
193
+ displayOptions: {
194
+ show: {
195
+ operation: ['linkTag'],
196
+ },
197
+ },
198
+ description: 'ID do ticket e ID da tag a ser vinculada',
199
+ },
200
+ {
201
+ displayName: 'Dados (JSON)',
202
+ name: 'bodyData',
203
+ type: 'json',
204
+ default: '{"ticketId": 123, "kanbanId": 456, "userId": 789}',
205
+ displayOptions: {
206
+ show: {
207
+ operation: ['linkKanban'],
208
+ },
209
+ },
210
+ description: 'ID do ticket, ID do kanban e ID do usuário',
211
+ },
212
+ {
213
+ displayName: 'Dados (JSON)',
214
+ name: 'bodyData',
215
+ type: 'json',
216
+ default: '{"ticketId": 123, "userId": 456}',
217
+ displayOptions: {
218
+ show: {
219
+ operation: ['linkCarteira'],
220
+ },
221
+ },
222
+ description: 'ID do ticket e ID do usuário da carteira',
149
223
  },
150
224
  ],
151
225
  };
@@ -255,6 +329,11 @@ export class Digitalsac implements INodeType {
255
329
  };
256
330
  break;
257
331
  case 'sendMessage':
332
+ // Validar se o UUID foi fornecido
333
+ if (!param || param.trim() === '') {
334
+ throw new Error('UUID da conexão é obrigatório para enviar mensagem. Preencha o campo "Parâmetro" com o UUID da conexão.');
335
+ }
336
+
258
337
  url = `/v1/api/external/${param}`;
259
338
  method = 'POST';
260
339
 
@@ -263,21 +342,69 @@ export class Digitalsac implements INodeType {
263
342
  const phoneNumber = this.getNodeParameter('phoneNumber', i) as string;
264
343
  const externalKey = this.getNodeParameter('externalKey', i) as string;
265
344
 
266
- // Criar o objeto diretamente
267
- body = {
268
- body: messageBody,
269
- number: phoneNumber,
270
- externalKey: externalKey
271
- };
345
+ // Verificar se dados binários (para envio de arquivo)
346
+ let hasBinaryData = false;
347
+ let binaryData: Buffer | undefined;
348
+ let binaryFileName: string | undefined;
349
+ let binaryContentType: string | undefined;
272
350
 
273
- headers['Content-Type'] = 'application/json';
274
- options = {
275
- method,
276
- headers,
277
- body,
278
- uri: `${baseUrl}${url}`,
279
- json: true,
280
- };
351
+ if (items[i].binary) {
352
+ const binary = items[i].binary as IBinaryKeyData;
353
+ // Procurar por qualquer propriedade binária disponível
354
+ const binaryKeys = Object.keys(binary);
355
+ if (binaryKeys.length > 0) {
356
+ const binaryPropertyName = binaryKeys[0]; // Usar a primeira propriedade binária encontrada
357
+ hasBinaryData = true;
358
+
359
+ const binaryProperty = binary[binaryPropertyName];
360
+ binaryData = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
361
+ binaryFileName = binaryProperty.fileName || 'file';
362
+ binaryContentType = binaryProperty.mimeType;
363
+ }
364
+ }
365
+
366
+ if (hasBinaryData && binaryData) {
367
+ // Enviar como FormData (para arquivos)
368
+ const formData: IDataObject = {
369
+ body: messageBody,
370
+ number: phoneNumber,
371
+ externalKey: externalKey,
372
+ media: {
373
+ value: binaryData,
374
+ options: {
375
+ filename: binaryFileName,
376
+ contentType: binaryContentType,
377
+ },
378
+ },
379
+ };
380
+
381
+ options = {
382
+ method,
383
+ headers: {
384
+ Authorization: `Bearer ${token}`,
385
+ Accept: 'application/json',
386
+ },
387
+ formData: formData,
388
+ uri: `${baseUrl}${url}`,
389
+ json: true,
390
+ };
391
+ } else {
392
+ // Enviar como JSON (para texto)
393
+ body = {
394
+ body: messageBody,
395
+ number: phoneNumber,
396
+ externalKey: externalKey
397
+ };
398
+
399
+ headers['Content-Type'] = 'application/json';
400
+ options = {
401
+ method,
402
+ headers,
403
+ body,
404
+ uri: `${baseUrl}${url}`,
405
+ json: true,
406
+ };
407
+ }
281
408
  break;
282
409
  case 'listTags':
283
410
  url = '/typebot/listar_tags';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-digitalsac",
3
- "version": "0.2.8",
3
+ "version": "0.3.1",
4
4
  "description": "Izing Pro Digitalsac",
5
5
  "keywords": [
6
6
  "n8n",