@connectorx/n8n-nodes-cortex 0.1.12 → 0.1.15
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 +35 -0
- package/dist/credentials/CortexApi.credentials.js +3 -3
- package/dist/nodes/Cortex/Cortex.node.js +212 -150
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# n8n-nodes-cortex
|
|
2
|
+
|
|
3
|
+
This is an n8n Community Node for interacting with the **Cortex API**. It allows you to send messages, manage conversations, and interact with Kanban resources within your Cortex environment.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Authentication**: Supports standard Cortex User Tokens and API Tokens.
|
|
8
|
+
- **Dynamic Tenant Selection**: Automatically fetches accessible tenants.
|
|
9
|
+
- **User Tokens**: Lists all tenants the user has access to.
|
|
10
|
+
- **API Tokens**: Automatically detects the single tenant associated with the token.
|
|
11
|
+
- **Resources**:
|
|
12
|
+
- **Message**: Send text, media, notes, and reactions.
|
|
13
|
+
- **Conversation**: Update conversation status, owner, and column.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
You can install this node directly in n8n via **Settings > Community Nodes**.
|
|
18
|
+
|
|
19
|
+
**Package Name**: `@connectorx/n8n-nodes-cortex`
|
|
20
|
+
|
|
21
|
+
## Credentials
|
|
22
|
+
|
|
23
|
+
1. **Base URL**: The URL to your Cortex API functions (e.g., `https://your-project.supabase.co/functions/v1/api`).
|
|
24
|
+
2. **Access Token**: Your Cortex JWT or API Token (`cortex_...`).
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
### Tenant Selection
|
|
29
|
+
The node requires you to select a **Tenant** to interact with.
|
|
30
|
+
- If you use a **User Token**, the dropdown will populate with all your tenants.
|
|
31
|
+
- If you use an **API Token** (`cortex_...`), the dropdown will automatically show the specific tenant bound to that token.
|
|
32
|
+
|
|
33
|
+
### Operations
|
|
34
|
+
- **Send Message**: Supports various types (Text, Image, Video, Audio, Document, Voice, Note, Reaction).
|
|
35
|
+
- **Update Conversation**: Move cards between columns, change owners, or update status (Open/Closed/Snoozed).
|
|
@@ -11,11 +11,11 @@ class CortexApi {
|
|
|
11
11
|
name: 'apiBaseUrl',
|
|
12
12
|
type: 'string',
|
|
13
13
|
default: 'https://api.your-cortex-instance.com',
|
|
14
|
-
description: 'The base URL of the Cortex API (e.g. https://your-project.supabase.co/functions/v1/api)
|
|
14
|
+
description: 'The base URL of the Cortex Integration API (e.g. https://your-project.supabase.co/functions/v1/api/integrations)',
|
|
15
15
|
required: true,
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
|
-
displayName: '
|
|
18
|
+
displayName: 'API Token',
|
|
19
19
|
name: 'accessToken',
|
|
20
20
|
type: 'string',
|
|
21
21
|
typeOptions: {
|
|
@@ -29,7 +29,7 @@ class CortexApi {
|
|
|
29
29
|
this.test = {
|
|
30
30
|
request: {
|
|
31
31
|
baseURL: '={{$credentials.apiBaseUrl.replace(/\\/$/, "")}}',
|
|
32
|
-
url: '/
|
|
32
|
+
url: '/validate',
|
|
33
33
|
method: 'GET',
|
|
34
34
|
headers: {
|
|
35
35
|
Authorization: '={{ "Bearer " + $credentials.accessToken }}',
|
|
@@ -4,7 +4,7 @@ exports.Cortex = void 0;
|
|
|
4
4
|
class Cortex {
|
|
5
5
|
constructor() {
|
|
6
6
|
this.description = {
|
|
7
|
-
displayName: 'Cortex
|
|
7
|
+
displayName: 'Cortex',
|
|
8
8
|
name: 'cortex',
|
|
9
9
|
icon: 'file:cortex.png',
|
|
10
10
|
group: ['input'],
|
|
@@ -37,20 +37,13 @@ class Cortex {
|
|
|
37
37
|
name: 'Conversation',
|
|
38
38
|
value: 'conversation',
|
|
39
39
|
},
|
|
40
|
+
{
|
|
41
|
+
name: 'Contact',
|
|
42
|
+
value: 'contact',
|
|
43
|
+
},
|
|
40
44
|
],
|
|
41
45
|
default: 'message',
|
|
42
46
|
},
|
|
43
|
-
{
|
|
44
|
-
displayName: 'Tenant Name',
|
|
45
|
-
name: 'tenantId',
|
|
46
|
-
type: 'options',
|
|
47
|
-
typeOptions: {
|
|
48
|
-
loadOptionsMethod: 'getTenants',
|
|
49
|
-
},
|
|
50
|
-
default: '',
|
|
51
|
-
required: true,
|
|
52
|
-
description: 'The Tenant to interact with',
|
|
53
|
-
},
|
|
54
47
|
{
|
|
55
48
|
displayName: 'Operation',
|
|
56
49
|
name: 'operation',
|
|
@@ -58,21 +51,19 @@ class Cortex {
|
|
|
58
51
|
noDataExpression: true,
|
|
59
52
|
displayOptions: {
|
|
60
53
|
show: {
|
|
61
|
-
resource: [
|
|
62
|
-
'message',
|
|
63
|
-
],
|
|
54
|
+
resource: ['message'],
|
|
64
55
|
},
|
|
65
56
|
},
|
|
66
57
|
options: [
|
|
67
58
|
{
|
|
68
59
|
name: 'Send',
|
|
69
60
|
value: 'send',
|
|
70
|
-
description: 'Send a message (Text, Media,
|
|
61
|
+
description: 'Send a message (Text, Media, Template, etc.)',
|
|
71
62
|
},
|
|
72
63
|
{
|
|
73
64
|
name: 'Send Typing',
|
|
74
65
|
value: 'sendTyping',
|
|
75
|
-
description: 'Send a typing indicator',
|
|
66
|
+
description: 'Send a typing/recording indicator',
|
|
76
67
|
},
|
|
77
68
|
],
|
|
78
69
|
default: 'send',
|
|
@@ -84,98 +75,90 @@ class Cortex {
|
|
|
84
75
|
noDataExpression: true,
|
|
85
76
|
displayOptions: {
|
|
86
77
|
show: {
|
|
87
|
-
resource: [
|
|
88
|
-
'conversation',
|
|
89
|
-
],
|
|
78
|
+
resource: ['conversation'],
|
|
90
79
|
},
|
|
91
80
|
},
|
|
92
81
|
options: [
|
|
93
82
|
{
|
|
94
83
|
name: 'Update',
|
|
95
84
|
value: 'update',
|
|
96
|
-
description: '
|
|
85
|
+
description: 'Move column or assign owner',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: 'Get History',
|
|
89
|
+
value: 'getHistory',
|
|
90
|
+
description: 'Get conversation message history',
|
|
97
91
|
},
|
|
98
92
|
],
|
|
99
93
|
default: 'update',
|
|
100
94
|
},
|
|
101
95
|
{
|
|
102
|
-
displayName: '
|
|
103
|
-
name: '
|
|
104
|
-
type: 'string',
|
|
105
|
-
default: '',
|
|
106
|
-
required: true,
|
|
107
|
-
description: 'The Conversation ID',
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
displayName: 'Message Type',
|
|
111
|
-
name: 'msg_type',
|
|
96
|
+
displayName: 'Operation',
|
|
97
|
+
name: 'operation',
|
|
112
98
|
type: 'options',
|
|
99
|
+
noDataExpression: true,
|
|
113
100
|
displayOptions: {
|
|
114
101
|
show: {
|
|
115
|
-
resource: ['
|
|
116
|
-
operation: ['send'],
|
|
102
|
+
resource: ['contact'],
|
|
117
103
|
},
|
|
118
104
|
},
|
|
119
105
|
options: [
|
|
120
|
-
{
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
{
|
|
126
|
-
|
|
127
|
-
|
|
106
|
+
{
|
|
107
|
+
name: 'Get',
|
|
108
|
+
value: 'get',
|
|
109
|
+
description: 'Get contact details',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: 'Update',
|
|
113
|
+
value: 'update',
|
|
114
|
+
description: 'Update contact fields (name, email, tags, custom_data)',
|
|
115
|
+
},
|
|
128
116
|
],
|
|
129
|
-
default: '
|
|
117
|
+
default: 'get',
|
|
130
118
|
},
|
|
131
119
|
{
|
|
132
|
-
displayName: '
|
|
133
|
-
name: '
|
|
120
|
+
displayName: 'Conversation ID',
|
|
121
|
+
name: 'conversationId',
|
|
134
122
|
type: 'string',
|
|
123
|
+
required: true,
|
|
135
124
|
displayOptions: {
|
|
136
125
|
show: {
|
|
137
|
-
resource: ['message'],
|
|
138
|
-
operation: ['send'],
|
|
139
|
-
},
|
|
140
|
-
hide: {
|
|
141
|
-
msg_type: ['reaction'],
|
|
126
|
+
resource: ['message', 'conversation'],
|
|
142
127
|
},
|
|
143
128
|
},
|
|
144
129
|
default: '',
|
|
145
|
-
description: '
|
|
130
|
+
description: 'The UUID of the conversation',
|
|
146
131
|
},
|
|
147
132
|
{
|
|
148
|
-
displayName: '
|
|
149
|
-
name: '
|
|
133
|
+
displayName: 'Contact ID',
|
|
134
|
+
name: 'contactId',
|
|
150
135
|
type: 'string',
|
|
136
|
+
required: true,
|
|
151
137
|
displayOptions: {
|
|
152
138
|
show: {
|
|
153
|
-
resource: ['
|
|
154
|
-
operation: ['send'],
|
|
155
|
-
msg_type: ['reaction'],
|
|
139
|
+
resource: ['contact'],
|
|
156
140
|
},
|
|
157
141
|
},
|
|
158
142
|
default: '',
|
|
159
|
-
|
|
160
|
-
description: 'ID of the message to react to',
|
|
143
|
+
description: 'The UUID of the contact',
|
|
161
144
|
},
|
|
162
145
|
{
|
|
163
|
-
displayName: '
|
|
146
|
+
displayName: 'Content (Text, URL, or Template JSON)',
|
|
164
147
|
name: 'content',
|
|
165
148
|
type: 'string',
|
|
149
|
+
required: true,
|
|
166
150
|
displayOptions: {
|
|
167
151
|
show: {
|
|
168
152
|
resource: ['message'],
|
|
169
153
|
operation: ['send'],
|
|
170
|
-
msg_type: ['reaction'],
|
|
171
154
|
},
|
|
172
155
|
},
|
|
173
156
|
default: '',
|
|
174
|
-
description: '
|
|
157
|
+
description: 'Message text, media URL, or JSON string for templates',
|
|
175
158
|
},
|
|
176
159
|
{
|
|
177
|
-
displayName: '
|
|
178
|
-
name: '
|
|
160
|
+
displayName: 'Message Type',
|
|
161
|
+
name: 'msg_type',
|
|
179
162
|
type: 'options',
|
|
180
163
|
displayOptions: {
|
|
181
164
|
show: {
|
|
@@ -184,10 +167,17 @@ class Cortex {
|
|
|
184
167
|
},
|
|
185
168
|
},
|
|
186
169
|
options: [
|
|
187
|
-
{ name: '
|
|
188
|
-
{ name: '
|
|
170
|
+
{ name: 'Text', value: 'text' },
|
|
171
|
+
{ name: 'Image', value: 'image' },
|
|
172
|
+
{ name: 'Video', value: 'video' },
|
|
173
|
+
{ name: 'Audio', value: 'audio' },
|
|
174
|
+
{ name: 'Document', value: 'document' },
|
|
175
|
+
{ name: 'Voice', value: 'voice' },
|
|
176
|
+
{ name: 'Internal Note', value: 'internal_note' },
|
|
177
|
+
{ name: 'Template', value: 'template' },
|
|
178
|
+
{ name: 'Reaction', value: 'reaction' },
|
|
189
179
|
],
|
|
190
|
-
default: '
|
|
180
|
+
default: 'text',
|
|
191
181
|
},
|
|
192
182
|
{
|
|
193
183
|
displayName: 'Sender ID',
|
|
@@ -200,7 +190,21 @@ class Cortex {
|
|
|
200
190
|
},
|
|
201
191
|
},
|
|
202
192
|
default: '',
|
|
203
|
-
description: '
|
|
193
|
+
description: 'Optional sender identifier (defaults to "agent")',
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
displayName: 'React to Message ID',
|
|
197
|
+
name: 'react_to_message_id',
|
|
198
|
+
type: 'string',
|
|
199
|
+
displayOptions: {
|
|
200
|
+
show: {
|
|
201
|
+
resource: ['message'],
|
|
202
|
+
operation: ['send'],
|
|
203
|
+
msg_type: ['reaction'],
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
default: '',
|
|
207
|
+
description: 'UUID of the message to react to',
|
|
204
208
|
},
|
|
205
209
|
{
|
|
206
210
|
displayName: 'Reply To Message ID',
|
|
@@ -213,10 +217,10 @@ class Cortex {
|
|
|
213
217
|
},
|
|
214
218
|
hide: {
|
|
215
219
|
msg_type: ['reaction'],
|
|
216
|
-
}
|
|
220
|
+
},
|
|
217
221
|
},
|
|
218
222
|
default: '',
|
|
219
|
-
description: '
|
|
223
|
+
description: 'UUID of the message to reply to',
|
|
220
224
|
},
|
|
221
225
|
{
|
|
222
226
|
displayName: 'Status',
|
|
@@ -230,7 +234,8 @@ class Cortex {
|
|
|
230
234
|
},
|
|
231
235
|
options: [
|
|
232
236
|
{ name: 'Typing', value: 'typing' },
|
|
233
|
-
{ name: '
|
|
237
|
+
{ name: 'Recording', value: 'recording' },
|
|
238
|
+
{ name: 'Stopped', value: 'stopped' },
|
|
234
239
|
],
|
|
235
240
|
default: 'typing',
|
|
236
241
|
},
|
|
@@ -240,7 +245,6 @@ class Cortex {
|
|
|
240
245
|
type: 'options',
|
|
241
246
|
typeOptions: {
|
|
242
247
|
loadOptionsMethod: 'getColumns',
|
|
243
|
-
loadOptionsDependsOn: ['tenantId'],
|
|
244
248
|
},
|
|
245
249
|
displayOptions: {
|
|
246
250
|
show: {
|
|
@@ -257,7 +261,6 @@ class Cortex {
|
|
|
257
261
|
type: 'options',
|
|
258
262
|
typeOptions: {
|
|
259
263
|
loadOptionsMethod: 'getUsers',
|
|
260
|
-
loadOptionsDependsOn: ['tenantId'],
|
|
261
264
|
},
|
|
262
265
|
displayOptions: {
|
|
263
266
|
show: {
|
|
@@ -269,83 +272,109 @@ class Cortex {
|
|
|
269
272
|
description: 'New Owner ID. Leave empty to keep current.',
|
|
270
273
|
},
|
|
271
274
|
{
|
|
272
|
-
displayName: '
|
|
273
|
-
name: '
|
|
274
|
-
type: '
|
|
275
|
+
displayName: 'Limit',
|
|
276
|
+
name: 'limit',
|
|
277
|
+
type: 'number',
|
|
278
|
+
displayOptions: {
|
|
279
|
+
show: {
|
|
280
|
+
resource: ['conversation'],
|
|
281
|
+
operation: ['getHistory'],
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
typeOptions: {
|
|
285
|
+
minValue: 1,
|
|
286
|
+
maxValue: 100,
|
|
287
|
+
},
|
|
288
|
+
default: 20,
|
|
289
|
+
description: 'How many messages to retrieve',
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
displayName: 'Before (ISO Timestamp)',
|
|
293
|
+
name: 'before',
|
|
294
|
+
type: 'dateTime',
|
|
275
295
|
displayOptions: {
|
|
276
296
|
show: {
|
|
277
297
|
resource: ['conversation'],
|
|
298
|
+
operation: ['getHistory'],
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
default: '',
|
|
302
|
+
description: 'Timestamp for pagination',
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
displayName: 'Name',
|
|
306
|
+
name: 'contactName',
|
|
307
|
+
type: 'string',
|
|
308
|
+
displayOptions: {
|
|
309
|
+
show: {
|
|
310
|
+
resource: ['contact'],
|
|
311
|
+
operation: ['update'],
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
default: '',
|
|
315
|
+
description: 'Updated contact name',
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
displayName: 'Email',
|
|
319
|
+
name: 'contactEmail',
|
|
320
|
+
type: 'string',
|
|
321
|
+
displayOptions: {
|
|
322
|
+
show: {
|
|
323
|
+
resource: ['contact'],
|
|
324
|
+
operation: ['update'],
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
default: '',
|
|
328
|
+
description: 'Updated contact email',
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
displayName: 'Tags (Comma Separated)',
|
|
332
|
+
name: 'contactTags',
|
|
333
|
+
type: 'string',
|
|
334
|
+
displayOptions: {
|
|
335
|
+
show: {
|
|
336
|
+
resource: ['contact'],
|
|
278
337
|
operation: ['update'],
|
|
279
338
|
},
|
|
280
339
|
},
|
|
281
|
-
options: [
|
|
282
|
-
{ name: 'No Change', value: '' },
|
|
283
|
-
{ name: 'Open', value: 'open' },
|
|
284
|
-
{ name: 'Closed', value: 'closed' },
|
|
285
|
-
{ name: 'Snoozed', value: 'snoozed' },
|
|
286
|
-
],
|
|
287
340
|
default: '',
|
|
288
|
-
description: '
|
|
341
|
+
description: 'List of tags separated by commas',
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
displayName: 'Custom Data (JSON)',
|
|
345
|
+
name: 'contactCustomData',
|
|
346
|
+
type: 'string',
|
|
347
|
+
displayOptions: {
|
|
348
|
+
show: {
|
|
349
|
+
resource: ['contact'],
|
|
350
|
+
operation: ['update'],
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
default: '',
|
|
354
|
+
description: 'Custom properties in JSON format',
|
|
289
355
|
},
|
|
290
356
|
],
|
|
291
357
|
};
|
|
292
358
|
this.methods = {
|
|
293
359
|
loadOptions: {
|
|
294
|
-
async getTenants() {
|
|
295
|
-
const credentials = await this.getCredentials('cortexApi');
|
|
296
|
-
const baseUrl = credentials.apiBaseUrl.replace(/\/$/, '');
|
|
297
|
-
const options = {
|
|
298
|
-
headers: {
|
|
299
|
-
'Content-Type': 'application/json',
|
|
300
|
-
'Authorization': `Bearer ${credentials.accessToken}`,
|
|
301
|
-
},
|
|
302
|
-
method: 'GET',
|
|
303
|
-
uri: `${baseUrl}/user-tenants`,
|
|
304
|
-
json: true,
|
|
305
|
-
};
|
|
306
|
-
try {
|
|
307
|
-
const response = await this.helpers.request(options);
|
|
308
|
-
return response.map((t) => ({
|
|
309
|
-
name: t.name || t.tenant_id,
|
|
310
|
-
value: t.tenant_id
|
|
311
|
-
}));
|
|
312
|
-
}
|
|
313
|
-
catch (error) {
|
|
314
|
-
try {
|
|
315
|
-
options.uri = `${baseUrl}/integrations/validate`;
|
|
316
|
-
const validateResponse = await this.helpers.request(options);
|
|
317
|
-
if (validateResponse.valid && validateResponse.tenant_id) {
|
|
318
|
-
return [{
|
|
319
|
-
name: `Current Tenant (${validateResponse.tenant_id.slice(0, 8)}...)`,
|
|
320
|
-
value: validateResponse.tenant_id
|
|
321
|
-
}];
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
catch (e) {
|
|
325
|
-
}
|
|
326
|
-
console.error('getTenants error: Failed to fetch tenants via list or validate', error);
|
|
327
|
-
return [];
|
|
328
|
-
}
|
|
329
|
-
},
|
|
330
360
|
async getColumns() {
|
|
331
361
|
const credentials = await this.getCredentials('cortexApi');
|
|
332
362
|
const baseUrl = credentials.apiBaseUrl.replace(/\/$/, '');
|
|
333
|
-
const tenantId = this.getNodeParameter('tenantId');
|
|
334
|
-
if (!tenantId) {
|
|
335
|
-
return [];
|
|
336
|
-
}
|
|
337
363
|
const options = {
|
|
338
364
|
headers: {
|
|
339
365
|
'Content-Type': 'application/json',
|
|
340
366
|
'Authorization': `Bearer ${credentials.accessToken}`,
|
|
341
367
|
},
|
|
342
368
|
method: 'GET',
|
|
343
|
-
uri: `${baseUrl}/
|
|
369
|
+
uri: `${baseUrl}/columns`,
|
|
344
370
|
json: true,
|
|
345
371
|
};
|
|
346
372
|
try {
|
|
347
373
|
const response = await this.helpers.request(options);
|
|
348
|
-
return response
|
|
374
|
+
return response.map((c) => ({
|
|
375
|
+
name: c.name || c.id,
|
|
376
|
+
value: c.id
|
|
377
|
+
}));
|
|
349
378
|
}
|
|
350
379
|
catch (error) {
|
|
351
380
|
return [];
|
|
@@ -354,24 +383,20 @@ class Cortex {
|
|
|
354
383
|
async getUsers() {
|
|
355
384
|
const credentials = await this.getCredentials('cortexApi');
|
|
356
385
|
const baseUrl = credentials.apiBaseUrl.replace(/\/$/, '');
|
|
357
|
-
const tenantId = this.getNodeParameter('tenantId');
|
|
358
|
-
if (!tenantId) {
|
|
359
|
-
return [];
|
|
360
|
-
}
|
|
361
386
|
const options = {
|
|
362
387
|
headers: {
|
|
363
388
|
'Content-Type': 'application/json',
|
|
364
389
|
'Authorization': `Bearer ${credentials.accessToken}`,
|
|
365
390
|
},
|
|
366
391
|
method: 'GET',
|
|
367
|
-
uri: `${baseUrl}/
|
|
392
|
+
uri: `${baseUrl}/users`,
|
|
368
393
|
json: true,
|
|
369
394
|
};
|
|
370
395
|
try {
|
|
371
396
|
const response = await this.helpers.request(options);
|
|
372
397
|
return response.map((u) => ({
|
|
373
|
-
name: u.name || u.
|
|
374
|
-
value: u.
|
|
398
|
+
name: u.name || u.email || u.id,
|
|
399
|
+
value: u.id
|
|
375
400
|
}));
|
|
376
401
|
}
|
|
377
402
|
catch (error) {
|
|
@@ -390,9 +415,6 @@ class Cortex {
|
|
|
390
415
|
const baseUrl = credentials.apiBaseUrl.replace(/\/$/, '');
|
|
391
416
|
for (let i = 0; i < items.length; i++) {
|
|
392
417
|
try {
|
|
393
|
-
const tenantId = this.getNodeParameter('tenantId', i);
|
|
394
|
-
const conversationId = this.getNodeParameter('conversation_id', i);
|
|
395
|
-
let responseData;
|
|
396
418
|
const options = {
|
|
397
419
|
headers: {
|
|
398
420
|
'Content-Type': 'application/json',
|
|
@@ -400,60 +422,100 @@ class Cortex {
|
|
|
400
422
|
},
|
|
401
423
|
method: 'POST',
|
|
402
424
|
uri: '',
|
|
403
|
-
body: {},
|
|
404
425
|
json: true,
|
|
405
426
|
};
|
|
406
427
|
if (resource === 'message') {
|
|
428
|
+
const conversationId = this.getNodeParameter('conversationId', i);
|
|
407
429
|
if (operation === 'send') {
|
|
408
|
-
options.method = 'POST';
|
|
409
430
|
options.uri = `${baseUrl}/messages/send`;
|
|
410
|
-
const msgType = this.getNodeParameter('msg_type', i);
|
|
411
431
|
const content = this.getNodeParameter('content', i);
|
|
412
|
-
const
|
|
432
|
+
const msgType = this.getNodeParameter('msg_type', i);
|
|
413
433
|
const senderId = this.getNodeParameter('sender_id', i);
|
|
414
434
|
const replyTo = this.getNodeParameter('reply_to_message_id', i);
|
|
415
435
|
const reactTo = this.getNodeParameter('react_to_message_id', i);
|
|
416
436
|
const body = {
|
|
417
437
|
conversation_id: conversationId,
|
|
418
|
-
|
|
438
|
+
content: content,
|
|
419
439
|
type: msgType,
|
|
420
|
-
sender_type: senderType,
|
|
421
440
|
};
|
|
422
|
-
if (content)
|
|
423
|
-
body.content = content;
|
|
424
441
|
if (senderId)
|
|
425
442
|
body.sender_id = senderId;
|
|
426
|
-
if (replyTo
|
|
443
|
+
if (replyTo)
|
|
427
444
|
body.reply_to_message_id = replyTo;
|
|
428
445
|
if (msgType === 'reaction' && reactTo)
|
|
429
446
|
body.react_to_message_id = reactTo;
|
|
430
447
|
options.body = body;
|
|
431
448
|
}
|
|
432
449
|
else if (operation === 'sendTyping') {
|
|
433
|
-
options.method = 'POST';
|
|
434
450
|
options.uri = `${baseUrl}/messages/typing`;
|
|
435
451
|
const status = this.getNodeParameter('typing_status', i);
|
|
436
452
|
options.body = {
|
|
437
453
|
conversation_id: conversationId,
|
|
438
|
-
tenant_id: tenantId,
|
|
439
454
|
status: status,
|
|
440
455
|
};
|
|
441
456
|
}
|
|
442
457
|
}
|
|
443
458
|
else if (resource === 'conversation') {
|
|
459
|
+
const conversationId = this.getNodeParameter('conversationId', i);
|
|
444
460
|
if (operation === 'update') {
|
|
445
461
|
options.method = 'PATCH';
|
|
446
|
-
options.uri = `${baseUrl}/
|
|
462
|
+
options.uri = `${baseUrl}/conversations/${conversationId}`;
|
|
447
463
|
const columnId = this.getNodeParameter('column_id', i);
|
|
448
464
|
const ownerId = this.getNodeParameter('owner_id', i);
|
|
449
|
-
const status = this.getNodeParameter('status', i);
|
|
450
465
|
const body = {};
|
|
451
466
|
if (columnId)
|
|
452
467
|
body.column_id = columnId;
|
|
453
468
|
if (ownerId)
|
|
454
469
|
body.owner_id = ownerId;
|
|
455
|
-
if (
|
|
456
|
-
body
|
|
470
|
+
if (Object.keys(body).length > 0) {
|
|
471
|
+
options.body = body;
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
returnData.push({ json: { status: 'no_changes' } });
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
else if (operation === 'getHistory') {
|
|
479
|
+
options.method = 'GET';
|
|
480
|
+
const limit = this.getNodeParameter('limit', i);
|
|
481
|
+
const before = this.getNodeParameter('before', i);
|
|
482
|
+
options.uri = `${baseUrl}/conversations/${conversationId}/messages`;
|
|
483
|
+
options.qs = {
|
|
484
|
+
limit: limit,
|
|
485
|
+
};
|
|
486
|
+
if (before)
|
|
487
|
+
options.qs.before = before;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
else if (resource === 'contact') {
|
|
491
|
+
const contactId = this.getNodeParameter('contactId', i);
|
|
492
|
+
if (operation === 'get') {
|
|
493
|
+
options.method = 'GET';
|
|
494
|
+
options.uri = `${baseUrl}/contacts/${contactId}`;
|
|
495
|
+
}
|
|
496
|
+
else if (operation === 'update') {
|
|
497
|
+
options.method = 'PATCH';
|
|
498
|
+
options.uri = `${baseUrl}/contacts/${contactId}`;
|
|
499
|
+
const name = this.getNodeParameter('contactName', i);
|
|
500
|
+
const email = this.getNodeParameter('contactEmail', i);
|
|
501
|
+
const tagsStr = this.getNodeParameter('contactTags', i);
|
|
502
|
+
const customDataStr = this.getNodeParameter('contactCustomData', i);
|
|
503
|
+
const body = {};
|
|
504
|
+
if (name)
|
|
505
|
+
body.name = name;
|
|
506
|
+
if (email)
|
|
507
|
+
body.email = email;
|
|
508
|
+
if (tagsStr) {
|
|
509
|
+
body.tags = tagsStr.split(',').map(t => t.trim()).filter(t => t);
|
|
510
|
+
}
|
|
511
|
+
if (customDataStr) {
|
|
512
|
+
try {
|
|
513
|
+
body.custom_data = JSON.parse(customDataStr);
|
|
514
|
+
}
|
|
515
|
+
catch (e) {
|
|
516
|
+
throw new Error('Custom Data must be a valid JSON string');
|
|
517
|
+
}
|
|
518
|
+
}
|
|
457
519
|
if (Object.keys(body).length > 0) {
|
|
458
520
|
options.body = body;
|
|
459
521
|
}
|
|
@@ -463,8 +525,8 @@ class Cortex {
|
|
|
463
525
|
}
|
|
464
526
|
}
|
|
465
527
|
}
|
|
466
|
-
responseData = await this.helpers.request(options);
|
|
467
|
-
returnData.push(responseData);
|
|
528
|
+
const responseData = await this.helpers.request(options);
|
|
529
|
+
returnData.push(Array.isArray(responseData) ? { json: responseData } : responseData);
|
|
468
530
|
}
|
|
469
531
|
catch (error) {
|
|
470
532
|
if (this.continueOnFail()) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@connectorx/n8n-nodes-cortex",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "n8n nodes for Cortex API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package"
|
|
@@ -44,4 +44,4 @@
|
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"n8n-workflow": "*"
|
|
46
46
|
}
|
|
47
|
-
}
|
|
47
|
+
}
|