n8n-nodes-chat2crm 0.1.6 → 0.1.8
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/dist/nodes/Chat2CrmSend/Chat2CrmSend.node.d.ts +0 -1
- package/dist/nodes/Chat2CrmSend/Chat2CrmSend.node.js +28 -82
- package/dist/nodes/Chat2CrmTrigger/Chat2CrmTrigger.node.js +25 -84
- package/dist/nodes/Chat2CrmTrigger/Infra/StreamConfig.d.ts +35 -0
- package/dist/nodes/Chat2CrmTrigger/Infra/StreamConfig.js +128 -0
- package/package.json +1 -1
|
@@ -3,6 +3,5 @@ export declare class Chat2CrmSend implements INodeType {
|
|
|
3
3
|
description: INodeTypeDescription;
|
|
4
4
|
getStreams(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
5
5
|
private static createRedisConnectionForLoadOptions;
|
|
6
|
-
private static getStreamDb;
|
|
7
6
|
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
8
7
|
}
|
|
@@ -7,6 +7,7 @@ exports.Chat2CrmSend = void 0;
|
|
|
7
7
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
8
8
|
const ioredis_1 = __importDefault(require("ioredis"));
|
|
9
9
|
const RedisConnection_1 = require("../Chat2CrmTrigger/Infra/RedisConnection");
|
|
10
|
+
const StreamConfig_1 = require("../Chat2CrmTrigger/Infra/StreamConfig");
|
|
10
11
|
class Chat2CrmSend {
|
|
11
12
|
constructor() {
|
|
12
13
|
this.description = {
|
|
@@ -35,63 +36,7 @@ class Chat2CrmSend {
|
|
|
35
36
|
type: 'multiOptions',
|
|
36
37
|
required: true,
|
|
37
38
|
description: 'Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
|
38
|
-
options:
|
|
39
|
-
{
|
|
40
|
-
name: 'Chat Incoming Message',
|
|
41
|
-
value: 'chat_incoming_message',
|
|
42
|
-
description: 'Messages to chat (DB 0)',
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
name: 'Chat Outgoing Message',
|
|
46
|
-
value: 'chat_outgoing_message',
|
|
47
|
-
description: 'Messages from chat to CRM (DB 0)',
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: 'Chat Outgoing Status',
|
|
51
|
-
value: 'chat_outgoing_status',
|
|
52
|
-
description: 'Status messages from chat (DB 0)',
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
name: 'CRM Contacts',
|
|
56
|
-
value: 'crm_contacts',
|
|
57
|
-
description: 'CRM contacts stream (DB 1)',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
name: 'CRM Incoming Message',
|
|
61
|
-
value: 'crm_incoming_message',
|
|
62
|
-
description: 'Messages to CRM (DB 1)',
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
name: 'CRM Incoming Status',
|
|
66
|
-
value: 'crm_incoming_status',
|
|
67
|
-
description: 'Status messages to CRM (DB 0)',
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
name: 'CRM Lazy Incoming Message',
|
|
71
|
-
value: 'crm_lazy_incoming_message',
|
|
72
|
-
description: 'Lazy incoming messages to CRM (DB 1)',
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
name: 'CRM Outgoing Message',
|
|
76
|
-
value: 'crm_outgoing_message',
|
|
77
|
-
description: 'Messages from CRM to chat (DB 1)',
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
name: 'CRM Outgoing Status',
|
|
81
|
-
value: 'crm_outgoing_status',
|
|
82
|
-
description: 'Status messages from CRM (DB 0)',
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
name: 'N8N Incoming Message',
|
|
86
|
-
value: 'n8n_incoming_message',
|
|
87
|
-
description: 'Incoming messages to N8N (DB 0)',
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
name: 'N8N Outgoing Message',
|
|
91
|
-
value: 'n8n_outgoing_message',
|
|
92
|
-
description: 'Outgoing messages from N8N (DB 0)',
|
|
93
|
-
},
|
|
94
|
-
],
|
|
39
|
+
options: (0, StreamConfig_1.getStreamOptions)(),
|
|
95
40
|
default: [],
|
|
96
41
|
},
|
|
97
42
|
{
|
|
@@ -292,37 +237,21 @@ class Chat2CrmSend {
|
|
|
292
237
|
});
|
|
293
238
|
return redis;
|
|
294
239
|
}
|
|
295
|
-
// Определяем базу данных для стрима
|
|
296
|
-
static getStreamDb(stream) {
|
|
297
|
-
// Streams в DB 1 (CrmWorker)
|
|
298
|
-
if (stream === 'crm_outgoing_message' ||
|
|
299
|
-
stream === 'crm_incoming_message' ||
|
|
300
|
-
stream === 'crm_lazy_incoming_message' ||
|
|
301
|
-
stream === 'crm_contacts') {
|
|
302
|
-
return 1;
|
|
303
|
-
}
|
|
304
|
-
// Все остальные streams находятся в DB 0
|
|
305
|
-
return 0;
|
|
306
|
-
}
|
|
307
240
|
async execute() {
|
|
308
241
|
const items = this.getInputData();
|
|
309
242
|
const returnData = [];
|
|
310
243
|
const credentials = await this.getCredentials('chat2CrmRedisApi');
|
|
311
244
|
const selectedStreams = this.getNodeParameter('streams', 0);
|
|
312
245
|
const messageId = this.getNodeParameter('messageId', 0);
|
|
313
|
-
//
|
|
246
|
+
// Валидация входных данных
|
|
314
247
|
if (!selectedStreams || selectedStreams.length === 0) {
|
|
315
248
|
throw new n8n_workflow_1.ApplicationError('Please select at least one stream to send message to', { level: 'warning' });
|
|
316
249
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
streamsByDb.set(db, []);
|
|
323
|
-
}
|
|
324
|
-
streamsByDb.get(db).push(stream);
|
|
325
|
-
});
|
|
250
|
+
if (messageId && typeof messageId !== 'string') {
|
|
251
|
+
throw new n8n_workflow_1.ApplicationError('Message ID must be a string', { level: 'error' });
|
|
252
|
+
}
|
|
253
|
+
// Группируем выбранные streams по базам данных используя общую функцию
|
|
254
|
+
const streamsByDb = (0, StreamConfig_1.groupStreamsByDb)(selectedStreams);
|
|
326
255
|
// Создаем подключения к Redis только для нужных баз данных
|
|
327
256
|
const redisConnections = new Map();
|
|
328
257
|
try {
|
|
@@ -337,14 +266,28 @@ class Chat2CrmSend {
|
|
|
337
266
|
let messageData = {};
|
|
338
267
|
try {
|
|
339
268
|
if (typeof messageDataParam === 'string') {
|
|
340
|
-
|
|
269
|
+
// Если это строка, пытаемся распарсить JSON
|
|
270
|
+
if (messageDataParam.trim() === '') {
|
|
271
|
+
messageData = {};
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
messageData = JSON.parse(messageDataParam);
|
|
275
|
+
}
|
|
341
276
|
}
|
|
342
|
-
else if (typeof messageDataParam === 'object') {
|
|
277
|
+
else if (typeof messageDataParam === 'object' && messageDataParam !== null) {
|
|
278
|
+
// Если это уже объект, используем его напрямую
|
|
343
279
|
messageData = messageDataParam;
|
|
344
280
|
}
|
|
281
|
+
else {
|
|
282
|
+
throw new n8n_workflow_1.ApplicationError('messageData must be a JSON object or string', { level: 'error' });
|
|
283
|
+
}
|
|
345
284
|
}
|
|
346
285
|
catch (error) {
|
|
347
|
-
throw new n8n_workflow_1.ApplicationError(`Invalid JSON in messageData: ${error}`, { level: 'error' });
|
|
286
|
+
throw new n8n_workflow_1.ApplicationError(`Invalid JSON in messageData: ${error.message}`, { level: 'error' });
|
|
287
|
+
}
|
|
288
|
+
// Проверяем, что messageData не пустой
|
|
289
|
+
if (Object.keys(messageData).length === 0) {
|
|
290
|
+
throw new n8n_workflow_1.ApplicationError('messageData cannot be empty', { level: 'error' });
|
|
348
291
|
}
|
|
349
292
|
// Отправляем сообщение в каждый выбранный stream
|
|
350
293
|
const sent = [];
|
|
@@ -361,6 +304,9 @@ class Chat2CrmSend {
|
|
|
361
304
|
if (typeof value === 'object' && value !== null) {
|
|
362
305
|
fields.push(JSON.stringify(value));
|
|
363
306
|
}
|
|
307
|
+
else if (value === null || value === undefined) {
|
|
308
|
+
fields.push('');
|
|
309
|
+
}
|
|
364
310
|
else {
|
|
365
311
|
fields.push(String(value));
|
|
366
312
|
}
|
|
@@ -3,6 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Chat2CrmTrigger = void 0;
|
|
4
4
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
5
|
const RedisConnection_1 = require("./Infra/RedisConnection");
|
|
6
|
+
const StreamConfig_1 = require("./Infra/StreamConfig");
|
|
7
|
+
// Константы для валидации
|
|
8
|
+
const MIN_POLL_INTERVAL_SECONDS = 0.01;
|
|
9
|
+
const MAX_POLL_INTERVAL_SECONDS = 60;
|
|
10
|
+
const MIN_BLOCK_TIME_MS = 0;
|
|
11
|
+
const MAX_BLOCK_TIME_MS = 60000; // 60 секунд
|
|
12
|
+
const MIN_COUNT = 1;
|
|
13
|
+
const MAX_COUNT = 1000;
|
|
14
|
+
const MAX_BLOCK_TIME_FOR_RESPONSIVENESS_MS = 500;
|
|
6
15
|
class Chat2CrmTrigger {
|
|
7
16
|
constructor() {
|
|
8
17
|
this.description = {
|
|
@@ -29,70 +38,9 @@ class Chat2CrmTrigger {
|
|
|
29
38
|
displayName: 'Streams',
|
|
30
39
|
name: 'streams',
|
|
31
40
|
type: 'multiOptions',
|
|
32
|
-
required: true,
|
|
41
|
+
required: true,
|
|
33
42
|
description: 'Select Redis streams to listen to',
|
|
34
|
-
options:
|
|
35
|
-
{
|
|
36
|
-
name: 'Chat Incoming Message',
|
|
37
|
-
value: 'chat_incoming_message',
|
|
38
|
-
description: 'Messages to chat (DB 0)',
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
name: 'Chat Outgoing Message',
|
|
42
|
-
value: 'chat_outgoing_message',
|
|
43
|
-
description: 'Messages from chat to CRM (DB 0)',
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
name: 'Chat Outgoing Status',
|
|
47
|
-
value: 'chat_outgoing_status',
|
|
48
|
-
description: 'Status messages from chat (DB 0)',
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
name: 'Chat Outgoing Status (CRM)',
|
|
52
|
-
value: 'chat_outgoing_status',
|
|
53
|
-
description: 'Chat outgoing status in CRM DB (DB 1)',
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: 'CRM Contacts',
|
|
57
|
-
value: 'crm_contacts',
|
|
58
|
-
description: 'CRM contacts stream (DB 1)',
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: 'CRM Incoming Message',
|
|
62
|
-
value: 'crm_incoming_message',
|
|
63
|
-
description: 'Messages to CRM (DB 1)',
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
name: 'CRM Incoming Status',
|
|
67
|
-
value: 'crm_incoming_status',
|
|
68
|
-
description: 'Status messages to CRM (DB 0)',
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: 'CRM Lazy Incoming Message',
|
|
72
|
-
value: 'crm_lazy_incoming_message',
|
|
73
|
-
description: 'Lazy incoming messages to CRM (DB 1)',
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
name: 'CRM Outgoing Message',
|
|
77
|
-
value: 'crm_outgoing_message',
|
|
78
|
-
description: 'Messages from CRM to chat (DB 1)',
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
name: 'CRM Outgoing Status',
|
|
82
|
-
value: 'crm_outgoing_status',
|
|
83
|
-
description: 'Status messages from CRM (DB 1)',
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
name: 'N8N Incoming Message',
|
|
87
|
-
value: 'n8n_incoming_message',
|
|
88
|
-
description: 'Incoming messages to N8N (DB 0)',
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
name: 'N8N Outgoing Message',
|
|
92
|
-
value: 'n8n_outgoing_message',
|
|
93
|
-
description: 'Outgoing messages from N8N (DB 0)',
|
|
94
|
-
},
|
|
95
|
-
],
|
|
43
|
+
options: (0, StreamConfig_1.getStreamOptions)(),
|
|
96
44
|
default: ['chat_outgoing_message'],
|
|
97
45
|
},
|
|
98
46
|
{
|
|
@@ -125,29 +73,22 @@ class Chat2CrmTrigger {
|
|
|
125
73
|
const block = this.getNodeParameter('block', 1000);
|
|
126
74
|
const count = this.getNodeParameter('count', 10);
|
|
127
75
|
const pollIntervalSeconds = this.getNodeParameter('pollInterval', 0.5);
|
|
128
|
-
|
|
129
|
-
// Проверяем, что выбраны streams
|
|
76
|
+
// Валидация входных данных
|
|
130
77
|
if (!selectedStreams || selectedStreams.length === 0) {
|
|
131
78
|
throw new n8n_workflow_1.ApplicationError('Please select at least one stream to monitor', { level: 'warning' });
|
|
132
79
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
// crm_incoming_status, crm_outgoing_status) находятся в DB 0
|
|
146
|
-
if (!streamsByDb.has(db)) {
|
|
147
|
-
streamsByDb.set(db, []);
|
|
148
|
-
}
|
|
149
|
-
streamsByDb.get(db).push(stream);
|
|
150
|
-
});
|
|
80
|
+
if (pollIntervalSeconds < MIN_POLL_INTERVAL_SECONDS || pollIntervalSeconds > MAX_POLL_INTERVAL_SECONDS) {
|
|
81
|
+
throw new n8n_workflow_1.ApplicationError(`Poll interval must be between ${MIN_POLL_INTERVAL_SECONDS} and ${MAX_POLL_INTERVAL_SECONDS} seconds`, { level: 'error' });
|
|
82
|
+
}
|
|
83
|
+
if (block < MIN_BLOCK_TIME_MS || block > MAX_BLOCK_TIME_MS) {
|
|
84
|
+
throw new n8n_workflow_1.ApplicationError(`Block time must be between ${MIN_BLOCK_TIME_MS} and ${MAX_BLOCK_TIME_MS} milliseconds`, { level: 'error' });
|
|
85
|
+
}
|
|
86
|
+
if (count < MIN_COUNT || count > MAX_COUNT) {
|
|
87
|
+
throw new n8n_workflow_1.ApplicationError(`Count must be between ${MIN_COUNT} and ${MAX_COUNT}`, { level: 'error' });
|
|
88
|
+
}
|
|
89
|
+
const pollInterval = Math.min(pollIntervalSeconds * 1000, MAX_BLOCK_TIME_FOR_RESPONSIVENESS_MS);
|
|
90
|
+
// Группируем выбранные streams по базам данных используя общую функцию
|
|
91
|
+
const streamsByDb = (0, StreamConfig_1.groupStreamsByDb)(selectedStreams);
|
|
151
92
|
// Создаем подключения к Redis только для нужных баз данных
|
|
152
93
|
const redisConnections = new Map();
|
|
153
94
|
for (const db of streamsByDb.keys()) {
|
|
@@ -241,7 +182,7 @@ class Chat2CrmTrigger {
|
|
|
241
182
|
try {
|
|
242
183
|
const lastId = lastReadIds.get(stream) || '$';
|
|
243
184
|
// Используем более короткий block time для возможности быстрого закрытия
|
|
244
|
-
const blockTime = isClosing ? 0 : Math.min(block,
|
|
185
|
+
const blockTime = isClosing ? 0 : Math.min(block, MAX_BLOCK_TIME_FOR_RESPONSIVENESS_MS);
|
|
245
186
|
// Используем XREAD чтобы читать все сообщения напрямую из stream
|
|
246
187
|
// Это позволяет читать сообщения даже если они уже обработаны другими consumer'ами
|
|
247
188
|
const messages = await redis.xread('COUNT', count, 'BLOCK', blockTime, 'STREAMS', stream, lastId);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { INodePropertyOptions } from 'n8n-workflow';
|
|
2
|
+
/**
|
|
3
|
+
* Интерфейс для определения stream
|
|
4
|
+
*/
|
|
5
|
+
export interface StreamDefinition {
|
|
6
|
+
name: string;
|
|
7
|
+
value: string;
|
|
8
|
+
description: string;
|
|
9
|
+
db: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Полный список всех доступных streams с их конфигурацией
|
|
13
|
+
*/
|
|
14
|
+
export declare const STREAM_DEFINITIONS: StreamDefinition[];
|
|
15
|
+
/**
|
|
16
|
+
* Маппинг stream names к номерам баз данных
|
|
17
|
+
*/
|
|
18
|
+
export declare const STREAM_DB_MAP: Record<string, number>;
|
|
19
|
+
/**
|
|
20
|
+
* Определяет номер базы данных для указанного stream
|
|
21
|
+
* @param stream - Имя stream
|
|
22
|
+
* @returns Номер базы данных (0 или 1)
|
|
23
|
+
*/
|
|
24
|
+
export declare function getStreamDb(stream: string): number;
|
|
25
|
+
/**
|
|
26
|
+
* Группирует streams по базам данных
|
|
27
|
+
* @param streams - Массив имен streams
|
|
28
|
+
* @returns Map с ключом - номер DB, значением - массив streams
|
|
29
|
+
*/
|
|
30
|
+
export declare function groupStreamsByDb(streams: string[]): Map<number, string[]>;
|
|
31
|
+
/**
|
|
32
|
+
* Возвращает опции streams для n8n properties
|
|
33
|
+
* @returns Массив опций для multiOptions
|
|
34
|
+
*/
|
|
35
|
+
export declare function getStreamOptions(): INodePropertyOptions[];
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.STREAM_DB_MAP = exports.STREAM_DEFINITIONS = void 0;
|
|
4
|
+
exports.getStreamDb = getStreamDb;
|
|
5
|
+
exports.groupStreamsByDb = groupStreamsByDb;
|
|
6
|
+
exports.getStreamOptions = getStreamOptions;
|
|
7
|
+
/**
|
|
8
|
+
* Полный список всех доступных streams с их конфигурацией
|
|
9
|
+
*/
|
|
10
|
+
exports.STREAM_DEFINITIONS = [
|
|
11
|
+
{
|
|
12
|
+
name: 'Chat Incoming Message',
|
|
13
|
+
value: 'chat_incoming_message',
|
|
14
|
+
description: 'Messages to chat (DB 0)',
|
|
15
|
+
db: 0,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: 'Chat Outgoing Message',
|
|
19
|
+
value: 'chat_outgoing_message',
|
|
20
|
+
description: 'Messages from chat to CRM (DB 0)',
|
|
21
|
+
db: 0,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'Chat Outgoing Status',
|
|
25
|
+
value: 'chat_outgoing_status',
|
|
26
|
+
description: 'Status messages from chat (DB 0)',
|
|
27
|
+
db: 0,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'Chat Outgoing Status (CRM)',
|
|
31
|
+
value: 'chat_outgoing_status',
|
|
32
|
+
description: 'Chat outgoing status in CRM DB (DB 1)',
|
|
33
|
+
db: 1,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'CRM Contacts',
|
|
37
|
+
value: 'crm_contacts',
|
|
38
|
+
description: 'CRM contacts stream (DB 1)',
|
|
39
|
+
db: 1,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'CRM Incoming Message',
|
|
43
|
+
value: 'crm_incoming_message',
|
|
44
|
+
description: 'Messages to CRM (DB 1)',
|
|
45
|
+
db: 1,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'CRM Incoming Status',
|
|
49
|
+
value: 'crm_incoming_status',
|
|
50
|
+
description: 'Status messages to CRM (DB 0)',
|
|
51
|
+
db: 0,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'CRM Lazy Incoming Message',
|
|
55
|
+
value: 'crm_lazy_incoming_message',
|
|
56
|
+
description: 'Lazy incoming messages to CRM (DB 1)',
|
|
57
|
+
db: 1,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'CRM Outgoing Message',
|
|
61
|
+
value: 'crm_outgoing_message',
|
|
62
|
+
description: 'Messages from CRM to chat (DB 1)',
|
|
63
|
+
db: 1,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'CRM Outgoing Status',
|
|
67
|
+
value: 'crm_outgoing_status',
|
|
68
|
+
description: 'Status messages from CRM (DB 1)',
|
|
69
|
+
db: 1,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: 'N8N Incoming Message',
|
|
73
|
+
value: 'n8n_incoming_message',
|
|
74
|
+
description: 'Incoming messages to N8N (DB 0)',
|
|
75
|
+
db: 0,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'N8N Outgoing Message',
|
|
79
|
+
value: 'n8n_outgoing_message',
|
|
80
|
+
description: 'Outgoing messages from N8N (DB 0)',
|
|
81
|
+
db: 0,
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
/**
|
|
85
|
+
* Маппинг stream names к номерам баз данных
|
|
86
|
+
*/
|
|
87
|
+
exports.STREAM_DB_MAP = {
|
|
88
|
+
crm_outgoing_message: 1,
|
|
89
|
+
crm_incoming_message: 1,
|
|
90
|
+
crm_lazy_incoming_message: 1,
|
|
91
|
+
crm_contacts: 1,
|
|
92
|
+
crm_outgoing_status: 1,
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Определяет номер базы данных для указанного stream
|
|
96
|
+
* @param stream - Имя stream
|
|
97
|
+
* @returns Номер базы данных (0 или 1)
|
|
98
|
+
*/
|
|
99
|
+
function getStreamDb(stream) {
|
|
100
|
+
return exports.STREAM_DB_MAP[stream] ?? 0;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Группирует streams по базам данных
|
|
104
|
+
* @param streams - Массив имен streams
|
|
105
|
+
* @returns Map с ключом - номер DB, значением - массив streams
|
|
106
|
+
*/
|
|
107
|
+
function groupStreamsByDb(streams) {
|
|
108
|
+
const streamsByDb = new Map();
|
|
109
|
+
streams.forEach(stream => {
|
|
110
|
+
const db = getStreamDb(stream);
|
|
111
|
+
if (!streamsByDb.has(db)) {
|
|
112
|
+
streamsByDb.set(db, []);
|
|
113
|
+
}
|
|
114
|
+
streamsByDb.get(db).push(stream);
|
|
115
|
+
});
|
|
116
|
+
return streamsByDb;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Возвращает опции streams для n8n properties
|
|
120
|
+
* @returns Массив опций для multiOptions
|
|
121
|
+
*/
|
|
122
|
+
function getStreamOptions() {
|
|
123
|
+
return exports.STREAM_DEFINITIONS.map(def => ({
|
|
124
|
+
name: def.name,
|
|
125
|
+
value: def.value,
|
|
126
|
+
description: def.description,
|
|
127
|
+
}));
|
|
128
|
+
}
|