@kichat/n8n-nodes-kirimchat 1.2.8 → 1.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.
|
@@ -41,6 +41,34 @@ function validateInteractiveMessage(interactive) {
|
|
|
41
41
|
}
|
|
42
42
|
return true;
|
|
43
43
|
}
|
|
44
|
+
const MAX_TEMPLATE_VARS = 20;
|
|
45
|
+
const templateVariableCountOptions = [
|
|
46
|
+
{ name: 'No variables', value: 0 },
|
|
47
|
+
...Array.from({ length: MAX_TEMPLATE_VARS }, (_, i) => ({
|
|
48
|
+
name: `${i + 1}`,
|
|
49
|
+
value: i + 1,
|
|
50
|
+
})),
|
|
51
|
+
];
|
|
52
|
+
// Generate individual template variable fields with displayOptions
|
|
53
|
+
// Each field shows only when templateVariableCount >= its number
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
+
const templateVariableFields = Array.from({ length: MAX_TEMPLATE_VARS }, (_, idx) => {
|
|
56
|
+
const varNum = idx + 1;
|
|
57
|
+
return {
|
|
58
|
+
displayName: `Variable {{${varNum}}}`,
|
|
59
|
+
name: `templateVar${varNum}`,
|
|
60
|
+
type: 'string',
|
|
61
|
+
displayOptions: {
|
|
62
|
+
show: {
|
|
63
|
+
operation: ['sendMessage'],
|
|
64
|
+
messageType: ['template'],
|
|
65
|
+
templateVariableCount: Array.from({ length: MAX_TEMPLATE_VARS - idx }, (_, j) => varNum + j),
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
default: '',
|
|
69
|
+
description: `Value for template placeholder {{${varNum}}}`,
|
|
70
|
+
};
|
|
71
|
+
});
|
|
44
72
|
class KirimChat {
|
|
45
73
|
constructor() {
|
|
46
74
|
this.description = {
|
|
@@ -99,6 +127,12 @@ class KirimChat {
|
|
|
99
127
|
description: 'Send typing indicator to show you are typing',
|
|
100
128
|
action: 'Send typing indicator',
|
|
101
129
|
},
|
|
130
|
+
{
|
|
131
|
+
name: 'Get Message Status',
|
|
132
|
+
value: 'getMessageStatus',
|
|
133
|
+
description: 'Check the delivery status of a sent message (sent, delivered, read, failed)',
|
|
134
|
+
action: 'Get message status',
|
|
135
|
+
},
|
|
102
136
|
],
|
|
103
137
|
default: 'sendMessage',
|
|
104
138
|
},
|
|
@@ -483,19 +517,21 @@ class KirimChat {
|
|
|
483
517
|
placeholder: 'en',
|
|
484
518
|
},
|
|
485
519
|
{
|
|
486
|
-
displayName: '
|
|
487
|
-
name: '
|
|
488
|
-
type: '
|
|
520
|
+
displayName: 'Number of Variables',
|
|
521
|
+
name: 'templateVariableCount',
|
|
522
|
+
type: 'options',
|
|
489
523
|
displayOptions: {
|
|
490
524
|
show: {
|
|
491
525
|
operation: ['sendMessage'],
|
|
492
526
|
messageType: ['template'],
|
|
493
527
|
},
|
|
494
528
|
},
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
529
|
+
options: templateVariableCountOptions,
|
|
530
|
+
default: 0,
|
|
531
|
+
noDataExpression: true,
|
|
532
|
+
description: 'Match the variable count shown in template name (e.g., [12 var] = select 12)',
|
|
498
533
|
},
|
|
534
|
+
...templateVariableFields,
|
|
499
535
|
{
|
|
500
536
|
displayName: 'Advanced: Template Components (JSON)',
|
|
501
537
|
name: 'templateComponents',
|
|
@@ -621,6 +657,65 @@ class KirimChat {
|
|
|
621
657
|
placeholder: 'https://example.com',
|
|
622
658
|
},
|
|
623
659
|
// Reply buttons specific fields
|
|
660
|
+
{
|
|
661
|
+
displayName: 'Use Advanced Mode (JSON)',
|
|
662
|
+
name: 'replyButtonsAdvancedMode',
|
|
663
|
+
type: 'boolean',
|
|
664
|
+
displayOptions: {
|
|
665
|
+
show: {
|
|
666
|
+
operation: ['sendMessage'],
|
|
667
|
+
messageType: ['interactive'],
|
|
668
|
+
interactiveType: ['button'],
|
|
669
|
+
},
|
|
670
|
+
},
|
|
671
|
+
default: false,
|
|
672
|
+
description: 'Enable to enter buttons as JSON. Disable for simple form input.',
|
|
673
|
+
},
|
|
674
|
+
// Simple mode - form fields
|
|
675
|
+
{
|
|
676
|
+
displayName: 'Reply Buttons',
|
|
677
|
+
name: 'replyButtonItems',
|
|
678
|
+
type: 'fixedCollection',
|
|
679
|
+
typeOptions: {
|
|
680
|
+
multipleValues: true,
|
|
681
|
+
maxValue: 3,
|
|
682
|
+
},
|
|
683
|
+
displayOptions: {
|
|
684
|
+
show: {
|
|
685
|
+
operation: ['sendMessage'],
|
|
686
|
+
messageType: ['interactive'],
|
|
687
|
+
interactiveType: ['button'],
|
|
688
|
+
replyButtonsAdvancedMode: [false],
|
|
689
|
+
},
|
|
690
|
+
},
|
|
691
|
+
default: { buttons: [] },
|
|
692
|
+
description: 'Add up to 3 reply buttons',
|
|
693
|
+
options: [
|
|
694
|
+
{
|
|
695
|
+
name: 'buttons',
|
|
696
|
+
displayName: 'Buttons',
|
|
697
|
+
values: [
|
|
698
|
+
{
|
|
699
|
+
displayName: 'ID',
|
|
700
|
+
name: 'id',
|
|
701
|
+
type: 'string',
|
|
702
|
+
default: '',
|
|
703
|
+
description: 'Unique identifier for this button (max 256 chars)',
|
|
704
|
+
placeholder: 'btn-yes',
|
|
705
|
+
},
|
|
706
|
+
{
|
|
707
|
+
displayName: 'Title',
|
|
708
|
+
name: 'title',
|
|
709
|
+
type: 'string',
|
|
710
|
+
default: '',
|
|
711
|
+
description: 'Button text displayed to user (max 20 chars)',
|
|
712
|
+
placeholder: 'Yes',
|
|
713
|
+
},
|
|
714
|
+
],
|
|
715
|
+
},
|
|
716
|
+
],
|
|
717
|
+
},
|
|
718
|
+
// Advanced mode (JSON)
|
|
624
719
|
{
|
|
625
720
|
displayName: 'Buttons (JSON)',
|
|
626
721
|
name: 'replyButtons',
|
|
@@ -631,6 +726,7 @@ class KirimChat {
|
|
|
631
726
|
operation: ['sendMessage'],
|
|
632
727
|
messageType: ['interactive'],
|
|
633
728
|
interactiveType: ['button'],
|
|
729
|
+
replyButtonsAdvancedMode: [true],
|
|
634
730
|
},
|
|
635
731
|
},
|
|
636
732
|
default: '[{"id": "btn1", "title": "Yes"}, {"id": "btn2", "title": "No"}]',
|
|
@@ -874,6 +970,23 @@ class KirimChat {
|
|
|
874
970
|
placeholder: 'tpl_abc123',
|
|
875
971
|
},
|
|
876
972
|
// ============================================
|
|
973
|
+
// GET MESSAGE STATUS FIELDS
|
|
974
|
+
// ============================================
|
|
975
|
+
{
|
|
976
|
+
displayName: 'Message ID',
|
|
977
|
+
name: 'statusMessageId',
|
|
978
|
+
type: 'string',
|
|
979
|
+
required: true,
|
|
980
|
+
displayOptions: {
|
|
981
|
+
show: {
|
|
982
|
+
operation: ['getMessageStatus'],
|
|
983
|
+
},
|
|
984
|
+
},
|
|
985
|
+
default: '',
|
|
986
|
+
description: 'The message ID returned from Send Message operation',
|
|
987
|
+
placeholder: 'cmlacq91h000pltieyh3w20rh',
|
|
988
|
+
},
|
|
989
|
+
// ============================================
|
|
877
990
|
// SEND TYPING FIELDS
|
|
878
991
|
// ============================================
|
|
879
992
|
{
|
|
@@ -1146,11 +1259,8 @@ class KirimChat {
|
|
|
1146
1259
|
value: JSON.stringify({
|
|
1147
1260
|
name: t.template_name,
|
|
1148
1261
|
language: t.language,
|
|
1149
|
-
has_variables: varCount > 0,
|
|
1150
|
-
variable_count: varCount,
|
|
1151
|
-
content: t.content,
|
|
1152
1262
|
}),
|
|
1153
|
-
description: ((_a = t.content) === null || _a === void 0 ? void 0 : _a.substring(0,
|
|
1263
|
+
description: ((_a = t.content) === null || _a === void 0 ? void 0 : _a.substring(0, 100)) || '',
|
|
1154
1264
|
};
|
|
1155
1265
|
});
|
|
1156
1266
|
}
|
|
@@ -1250,11 +1360,13 @@ class KirimChat {
|
|
|
1250
1360
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid template selection. Please re-select the template.', { itemIndex: i });
|
|
1251
1361
|
}
|
|
1252
1362
|
}
|
|
1253
|
-
// Handle
|
|
1254
|
-
const
|
|
1255
|
-
const templateVariables =
|
|
1256
|
-
|
|
1257
|
-
|
|
1363
|
+
// Handle template variables from individual fields
|
|
1364
|
+
const templateVarCount = this.getNodeParameter('templateVariableCount', i, 0);
|
|
1365
|
+
const templateVariables = [];
|
|
1366
|
+
for (let v = 1; v <= templateVarCount; v++) {
|
|
1367
|
+
const val = this.getNodeParameter(`templateVar${v}`, i, '');
|
|
1368
|
+
templateVariables.push(val);
|
|
1369
|
+
}
|
|
1258
1370
|
if (templateVariables.length > 0) {
|
|
1259
1371
|
// Build body component with parameters
|
|
1260
1372
|
const bodyParameters = templateVariables.map((v) => ({
|
|
@@ -1318,25 +1430,64 @@ class KirimChat {
|
|
|
1318
1430
|
};
|
|
1319
1431
|
}
|
|
1320
1432
|
else if (interactiveType === 'button') {
|
|
1321
|
-
const
|
|
1322
|
-
let
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1433
|
+
const advancedMode = this.getNodeParameter('replyButtonsAdvancedMode', i, false);
|
|
1434
|
+
let formattedButtons;
|
|
1435
|
+
if (advancedMode) {
|
|
1436
|
+
// Advanced mode: parse JSON
|
|
1437
|
+
const replyButtonsJson = this.getNodeParameter('replyButtons', i);
|
|
1438
|
+
let replyButtons;
|
|
1439
|
+
try {
|
|
1440
|
+
replyButtons = JSON.parse(replyButtonsJson);
|
|
1441
|
+
}
|
|
1442
|
+
catch (error) {
|
|
1443
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid JSON in Reply Buttons: ${error instanceof Error ? error.message : 'Parse failed'}`, { itemIndex: i });
|
|
1444
|
+
}
|
|
1445
|
+
if (!Array.isArray(replyButtons) || replyButtons.length === 0 || replyButtons.length > 3) {
|
|
1446
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Reply Buttons must be a JSON array with 1-3 buttons. Example: [{"id": "btn1", "title": "Yes"}]', { itemIndex: i });
|
|
1447
|
+
}
|
|
1448
|
+
// Transform to WhatsApp format
|
|
1449
|
+
formattedButtons = replyButtons.map((btn) => ({
|
|
1450
|
+
type: 'reply',
|
|
1451
|
+
reply: {
|
|
1452
|
+
id: (btn.id || '').trim(),
|
|
1453
|
+
title: (btn.title || '').trim(),
|
|
1454
|
+
},
|
|
1455
|
+
}));
|
|
1328
1456
|
}
|
|
1329
|
-
|
|
1330
|
-
|
|
1457
|
+
else {
|
|
1458
|
+
// Simple mode: build from form fields
|
|
1459
|
+
const buttonItemsData = this.getNodeParameter('replyButtonItems', i, { buttons: [] });
|
|
1460
|
+
if (!buttonItemsData.buttons || buttonItemsData.buttons.length === 0) {
|
|
1461
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'At least one reply button is required', { itemIndex: i });
|
|
1462
|
+
}
|
|
1463
|
+
if (buttonItemsData.buttons.length > 3) {
|
|
1464
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Maximum 3 reply buttons allowed', { itemIndex: i });
|
|
1465
|
+
}
|
|
1466
|
+
// Track IDs to ensure uniqueness
|
|
1467
|
+
const usedIds = new Set();
|
|
1468
|
+
formattedButtons = buttonItemsData.buttons.map((btn, index) => {
|
|
1469
|
+
const id = (btn.id || '').trim();
|
|
1470
|
+
const title = (btn.title || '').trim();
|
|
1471
|
+
if (!id || !title) {
|
|
1472
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Button ${index + 1}: ID and Title are required (cannot be empty)`, { itemIndex: i });
|
|
1473
|
+
}
|
|
1474
|
+
// Check for duplicate IDs
|
|
1475
|
+
if (usedIds.has(id)) {
|
|
1476
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Button ${index + 1}: Duplicate ID "${id}". Each button must have a unique ID.`, { itemIndex: i });
|
|
1477
|
+
}
|
|
1478
|
+
usedIds.add(id);
|
|
1479
|
+
if (id.length > 256) {
|
|
1480
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Button ${index + 1}: ID exceeds maximum length of 256 characters`, { itemIndex: i });
|
|
1481
|
+
}
|
|
1482
|
+
if (title.length > 20) {
|
|
1483
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Button ${index + 1}: Title exceeds maximum length of 20 characters`, { itemIndex: i });
|
|
1484
|
+
}
|
|
1485
|
+
return {
|
|
1486
|
+
type: 'reply',
|
|
1487
|
+
reply: { id, title },
|
|
1488
|
+
};
|
|
1489
|
+
});
|
|
1331
1490
|
}
|
|
1332
|
-
// Transform to n8n format
|
|
1333
|
-
const formattedButtons = replyButtons.map((btn) => ({
|
|
1334
|
-
type: 'reply',
|
|
1335
|
-
reply: {
|
|
1336
|
-
id: btn.id || '',
|
|
1337
|
-
title: btn.title || '',
|
|
1338
|
-
},
|
|
1339
|
-
}));
|
|
1340
1491
|
interactive.action = {
|
|
1341
1492
|
buttons: formattedButtons,
|
|
1342
1493
|
};
|
|
@@ -1554,6 +1705,17 @@ class KirimChat {
|
|
|
1554
1705
|
json: true,
|
|
1555
1706
|
});
|
|
1556
1707
|
}
|
|
1708
|
+
else if (operation === 'getMessageStatus') {
|
|
1709
|
+
// ============================================
|
|
1710
|
+
// GET MESSAGE STATUS OPERATION
|
|
1711
|
+
// ============================================
|
|
1712
|
+
const statusMsgId = this.getNodeParameter('statusMessageId', i);
|
|
1713
|
+
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'kirimChatApi', {
|
|
1714
|
+
method: 'GET',
|
|
1715
|
+
url: `${baseUrl}/messages/${statusMsgId}/status`,
|
|
1716
|
+
json: true,
|
|
1717
|
+
});
|
|
1718
|
+
}
|
|
1557
1719
|
else {
|
|
1558
1720
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The operation "${operation}" is not supported!`);
|
|
1559
1721
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kichat/n8n-nodes-kirimchat",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "n8n community node for KirimChat - Send WhatsApp, Instagram & Messenger messages with interactive buttons, flexible customer lookup, and typing indicators",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|