@kichat/n8n-nodes-kirimchat 1.0.5 → 1.2.0
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 +319 -139
- package/dist/nodes/KirimChat/KirimChat.node.js +606 -29
- package/package.json +16 -13
package/README.md
CHANGED
|
@@ -1,139 +1,319 @@
|
|
|
1
|
-
# n8n-nodes-kirimchat
|
|
2
|
-
|
|
3
|
-
This is an n8n community node for [KirimChat](https://kirim.chat) - a messaging platform that integrates WhatsApp Business API and
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Send Message** - Send text, image, document, audio, video, or
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
|
41
|
-
|
|
42
|
-
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
|
62
|
-
|
|
63
|
-
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
1
|
+
# n8n-nodes-kirimchat
|
|
2
|
+
|
|
3
|
+
This is an n8n community node for [KirimChat](https://kirim.chat) - a messaging platform that integrates WhatsApp Business API, Instagram DM, and Facebook Messenger.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Send Message** - Send text, image, document, audio, video, template, or interactive messages via WhatsApp, Instagram, or Messenger
|
|
8
|
+
- **List Templates** - List all WhatsApp message templates with filtering
|
|
9
|
+
- **Get Template** - Get a specific template by ID
|
|
10
|
+
- **Mark as Read** - Mark messages as read and send read receipts
|
|
11
|
+
- **Send Typing Indicator** - Show typing indicator to customers
|
|
12
|
+
- **Flexible Customer Lookup** - Find customers by ID, phone number, or Instagram username
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
### Community Nodes (Recommended)
|
|
17
|
+
|
|
18
|
+
1. Go to **Settings > Community Nodes**
|
|
19
|
+
2. Select **Install**
|
|
20
|
+
3. Enter `@kichat/n8n-nodes-kirimchat` and confirm
|
|
21
|
+
|
|
22
|
+
## Credentials
|
|
23
|
+
|
|
24
|
+
You need a KirimChat API key to use this node:
|
|
25
|
+
|
|
26
|
+
1. Log in to your KirimChat dashboard
|
|
27
|
+
2. Go to **Settings > Developers > API Keys**
|
|
28
|
+
3. Click **Create API Key** and copy the key (shown only once)
|
|
29
|
+
4. In n8n, create new credentials for **KirimChat API**
|
|
30
|
+
5. Paste your API key (starts with `kc_live_`)
|
|
31
|
+
|
|
32
|
+
## Operations
|
|
33
|
+
|
|
34
|
+
### Send Message
|
|
35
|
+
|
|
36
|
+
Send a message to a customer via WhatsApp, Instagram, or Messenger.
|
|
37
|
+
|
|
38
|
+
#### Customer Lookup Options
|
|
39
|
+
|
|
40
|
+
| Method | Description | Example |
|
|
41
|
+
|--------|-------------|---------|
|
|
42
|
+
| Customer ID | KirimChat customer ID | `cust_abc123` |
|
|
43
|
+
| Phone Number | Phone with country code | `+6281234567890` |
|
|
44
|
+
| Instagram Username | Instagram username | `johndoe` |
|
|
45
|
+
|
|
46
|
+
#### Channels & Message Types
|
|
47
|
+
|
|
48
|
+
| Channel | Message Types |
|
|
49
|
+
|---------|---------------|
|
|
50
|
+
| **WhatsApp** | `text`, `image`, `document`, `audio`, `video`, `template`, `interactive` |
|
|
51
|
+
| **Instagram** | `text`, `image`, `media_share` |
|
|
52
|
+
| **Messenger** | `text`, `image`, `video`, `audio`, `file` |
|
|
53
|
+
|
|
54
|
+
#### Parameters
|
|
55
|
+
|
|
56
|
+
| Parameter | Description |
|
|
57
|
+
|-----------|-------------|
|
|
58
|
+
| Customer Lookup | How to identify the customer |
|
|
59
|
+
| Channel | `whatsapp`, `instagram`, or `messenger` |
|
|
60
|
+
| Message Type | Type of message (varies by channel) |
|
|
61
|
+
| Content | Text content for text messages |
|
|
62
|
+
| Media URL | URL of media file for media messages |
|
|
63
|
+
| Caption | Optional caption for media messages |
|
|
64
|
+
| Filename | Filename for document/file messages |
|
|
65
|
+
|
|
66
|
+
#### WhatsApp Template Messages
|
|
67
|
+
|
|
68
|
+
| Parameter | Description |
|
|
69
|
+
|-----------|-------------|
|
|
70
|
+
| Template Name | Name of the approved template |
|
|
71
|
+
| Template Language | Language code (e.g., `en`, `id`) |
|
|
72
|
+
| Template Components | JSON array for variables and buttons |
|
|
73
|
+
|
|
74
|
+
**Example Template Components:**
|
|
75
|
+
```json
|
|
76
|
+
[
|
|
77
|
+
{
|
|
78
|
+
"type": "body",
|
|
79
|
+
"parameters": [
|
|
80
|
+
{ "type": "text", "text": "John" },
|
|
81
|
+
{ "type": "text", "text": "12345" }
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### WhatsApp Interactive Messages
|
|
88
|
+
|
|
89
|
+
Send buttons with your messages:
|
|
90
|
+
|
|
91
|
+
**CTA URL Button:**
|
|
92
|
+
| Parameter | Description |
|
|
93
|
+
|-----------|-------------|
|
|
94
|
+
| Interactive Type | `cta_url` |
|
|
95
|
+
| Body Text | Main message text (max 1024 chars) |
|
|
96
|
+
| Header Text | Optional header (max 60 chars) |
|
|
97
|
+
| Footer Text | Optional footer (max 60 chars) |
|
|
98
|
+
| Button Text | Text on button (max 20 chars) |
|
|
99
|
+
| Button URL | URL to open |
|
|
100
|
+
|
|
101
|
+
**Reply Buttons:**
|
|
102
|
+
| Parameter | Description |
|
|
103
|
+
|-----------|-------------|
|
|
104
|
+
| Interactive Type | `button` |
|
|
105
|
+
| Body Text | Main message text |
|
|
106
|
+
| Buttons (JSON) | Array of 1-3 buttons |
|
|
107
|
+
|
|
108
|
+
**Example Reply Buttons:**
|
|
109
|
+
```json
|
|
110
|
+
[
|
|
111
|
+
{ "id": "yes", "title": "Yes" },
|
|
112
|
+
{ "id": "no", "title": "No" },
|
|
113
|
+
{ "id": "maybe", "title": "Maybe" }
|
|
114
|
+
]
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Example Response:**
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"success": true,
|
|
121
|
+
"data": {
|
|
122
|
+
"message_id": "msg_xyz789",
|
|
123
|
+
"status": "sent",
|
|
124
|
+
"channel": "whatsapp",
|
|
125
|
+
"timestamp": "2025-11-26T10:31:00.000Z"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Mark as Read
|
|
131
|
+
|
|
132
|
+
Mark a message as read and send read receipt to the customer.
|
|
133
|
+
|
|
134
|
+
| Parameter | Description |
|
|
135
|
+
|-----------|-------------|
|
|
136
|
+
| Message ID | The ID of the message to mark as read (e.g., `msg_xyz789`) |
|
|
137
|
+
|
|
138
|
+
### List Templates
|
|
139
|
+
|
|
140
|
+
List all WhatsApp message templates with optional filtering.
|
|
141
|
+
|
|
142
|
+
| Parameter | Description |
|
|
143
|
+
|-----------|-------------|
|
|
144
|
+
| Filter by Status | `All`, `APPROVED`, `PENDING`, or `REJECTED` |
|
|
145
|
+
| Filter by Category | `All`, `MARKETING`, `UTILITY`, or `AUTHENTICATION` |
|
|
146
|
+
| Limit | Maximum templates to return (1-500, default 100) |
|
|
147
|
+
|
|
148
|
+
**Example Response:**
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"success": true,
|
|
152
|
+
"data": {
|
|
153
|
+
"templates": [
|
|
154
|
+
{
|
|
155
|
+
"id": "tpl_abc123",
|
|
156
|
+
"templateName": "order_confirmation",
|
|
157
|
+
"language": "en",
|
|
158
|
+
"status": "APPROVED",
|
|
159
|
+
"category": "UTILITY",
|
|
160
|
+
"content": "Your order {{1}} has been confirmed.",
|
|
161
|
+
"headerType": "TEXT",
|
|
162
|
+
"headerContent": "Order Update",
|
|
163
|
+
"footerContent": "Thank you for shopping!",
|
|
164
|
+
"variables": ["order_number"],
|
|
165
|
+
"createdAt": "2025-01-15T10:00:00.000Z"
|
|
166
|
+
}
|
|
167
|
+
],
|
|
168
|
+
"total": 1
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Get Template
|
|
174
|
+
|
|
175
|
+
Get a specific WhatsApp message template by ID.
|
|
176
|
+
|
|
177
|
+
| Parameter | Description |
|
|
178
|
+
|-----------|-------------|
|
|
179
|
+
| Template ID | The ID of the template (e.g., `tpl_abc123`) |
|
|
180
|
+
|
|
181
|
+
**Example Response:**
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"success": true,
|
|
185
|
+
"data": {
|
|
186
|
+
"id": "tpl_abc123",
|
|
187
|
+
"templateName": "order_confirmation",
|
|
188
|
+
"language": "en",
|
|
189
|
+
"status": "APPROVED",
|
|
190
|
+
"category": "UTILITY",
|
|
191
|
+
"content": "Your order {{1}} has been confirmed.",
|
|
192
|
+
"headerType": "TEXT",
|
|
193
|
+
"headerContent": "Order Update",
|
|
194
|
+
"footerContent": "Thank you for shopping!",
|
|
195
|
+
"buttons": [
|
|
196
|
+
{ "type": "URL", "text": "Track Order", "url": "https://..." }
|
|
197
|
+
],
|
|
198
|
+
"variables": ["order_number"],
|
|
199
|
+
"createdAt": "2025-01-15T10:00:00.000Z",
|
|
200
|
+
"updatedAt": "2025-01-15T10:00:00.000Z"
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Send Typing Indicator
|
|
206
|
+
|
|
207
|
+
Show typing indicator to a customer before sending a message.
|
|
208
|
+
|
|
209
|
+
| Parameter | Description |
|
|
210
|
+
|-----------|-------------|
|
|
211
|
+
| Customer Lookup | How to identify the customer |
|
|
212
|
+
| Customer ID/Phone/Username | Customer identifier |
|
|
213
|
+
| Channel | `whatsapp`, `instagram`, or auto-detect |
|
|
214
|
+
|
|
215
|
+
> **Note:** Rate limited to 1 request per customer per 3 seconds.
|
|
216
|
+
|
|
217
|
+
## Webhook Trigger
|
|
218
|
+
|
|
219
|
+
KirimChat supports outbound webhooks for real-time event notifications. Configure webhooks in your KirimChat dashboard under **Settings > Developers > Webhooks**.
|
|
220
|
+
|
|
221
|
+
### Supported Events
|
|
222
|
+
|
|
223
|
+
- `message.received` - New message from customer
|
|
224
|
+
- `message.sent` - Message sent to customer
|
|
225
|
+
- `message.delivered` - Message delivered
|
|
226
|
+
- `message.read` - Message read by customer
|
|
227
|
+
- `message.failed` - Message delivery failed
|
|
228
|
+
|
|
229
|
+
### Webhook Payload Example
|
|
230
|
+
|
|
231
|
+
```json
|
|
232
|
+
{
|
|
233
|
+
"event_type": "message.received",
|
|
234
|
+
"event_id": "evt_abc123",
|
|
235
|
+
"timestamp": "2025-11-26T10:30:00.000Z",
|
|
236
|
+
"data": {
|
|
237
|
+
"message_id": "msg_xyz789",
|
|
238
|
+
"customer_id": "cust_123",
|
|
239
|
+
"customer_phone": "+6281234567890",
|
|
240
|
+
"direction": "inbound",
|
|
241
|
+
"message_type": "text",
|
|
242
|
+
"content": "Hello!",
|
|
243
|
+
"channel": "whatsapp"
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Using with n8n Webhook Node
|
|
249
|
+
|
|
250
|
+
1. Create a new workflow with **Webhook** trigger node
|
|
251
|
+
2. Copy the webhook URL
|
|
252
|
+
3. In KirimChat, create a webhook endpoint with this URL
|
|
253
|
+
4. Select the events you want to receive
|
|
254
|
+
5. Connect the webhook to your KirimChat node for automated responses
|
|
255
|
+
|
|
256
|
+
## Rate Limits
|
|
257
|
+
|
|
258
|
+
| Limit Type | Rate |
|
|
259
|
+
|------------|------|
|
|
260
|
+
| Global | 100 requests per minute per API key |
|
|
261
|
+
| WhatsApp | 60 messages per minute |
|
|
262
|
+
| Instagram | 180 messages per hour |
|
|
263
|
+
| Messenger | 180 messages per hour |
|
|
264
|
+
| Typing Indicator | 1 request per customer per 3 seconds |
|
|
265
|
+
|
|
266
|
+
## Error Handling
|
|
267
|
+
|
|
268
|
+
The node returns standard error responses:
|
|
269
|
+
|
|
270
|
+
| Code | Description |
|
|
271
|
+
|------|-------------|
|
|
272
|
+
| 401 | Invalid or expired API key |
|
|
273
|
+
| 403 | Account disconnected or forbidden |
|
|
274
|
+
| 404 | Resource not found |
|
|
275
|
+
| 400 | Invalid request or messaging window closed |
|
|
276
|
+
| 429 | Rate limit exceeded |
|
|
277
|
+
|
|
278
|
+
### Common Error Codes
|
|
279
|
+
|
|
280
|
+
| Error Code | Description |
|
|
281
|
+
|------------|-------------|
|
|
282
|
+
| `ValidationError` | Invalid input parameters |
|
|
283
|
+
| `WindowClosed` | 24-hour messaging window expired |
|
|
284
|
+
| `ConfigurationError` | Channel not configured |
|
|
285
|
+
| `ConnectionError` | Account disconnected |
|
|
286
|
+
| `RateLimitExceeded` | Too many requests |
|
|
287
|
+
|
|
288
|
+
## Changelog
|
|
289
|
+
|
|
290
|
+
### v1.2.0 (Latest)
|
|
291
|
+
- ✅ Added **List Templates** operation - List all WhatsApp templates with filtering
|
|
292
|
+
- ✅ Added **Get Template** operation - Get template details by ID
|
|
293
|
+
- ✅ Filter templates by status (Approved, Pending, Rejected)
|
|
294
|
+
- ✅ Filter templates by category (Marketing, Utility, Authentication)
|
|
295
|
+
|
|
296
|
+
### v1.1.0
|
|
297
|
+
- ✅ Added Messenger channel support
|
|
298
|
+
- ✅ Added customer lookup by phone number and Instagram username
|
|
299
|
+
- ✅ Added WhatsApp Interactive messages (CTA URL buttons, Reply buttons)
|
|
300
|
+
- ✅ Improved typing indicator with flexible customer lookup
|
|
301
|
+
- ✅ Enhanced error messages
|
|
302
|
+
|
|
303
|
+
### v1.0.5
|
|
304
|
+
- Enhanced validation for media URLs
|
|
305
|
+
- Template components structure validation
|
|
306
|
+
|
|
307
|
+
### v1.0.1
|
|
308
|
+
- Initial security improvements
|
|
309
|
+
- JSON validation for templates
|
|
310
|
+
- Base URL security warning
|
|
311
|
+
|
|
312
|
+
## Resources
|
|
313
|
+
|
|
314
|
+
- [KirimChat Documentation](https://kirim.chat/developers)
|
|
315
|
+
- [n8n Community Nodes](https://docs.n8n.io/integrations/community-nodes/)
|
|
316
|
+
|
|
317
|
+
## License
|
|
318
|
+
|
|
319
|
+
MIT
|
|
@@ -23,6 +23,24 @@ function validateTemplateComponents(components) {
|
|
|
23
23
|
}
|
|
24
24
|
return components.every((component) => typeof component === 'object' && component !== null);
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Validates interactive message structure
|
|
28
|
+
*/
|
|
29
|
+
function validateInteractiveMessage(interactive) {
|
|
30
|
+
if (typeof interactive !== 'object' || interactive === null) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const obj = interactive;
|
|
34
|
+
// Must have type and body
|
|
35
|
+
if (!obj.type || !obj.body) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
// type must be 'cta_url' or 'button'
|
|
39
|
+
if (obj.type !== 'cta_url' && obj.type !== 'button') {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
26
44
|
class KirimChat {
|
|
27
45
|
constructor() {
|
|
28
46
|
this.description = {
|
|
@@ -32,7 +50,7 @@ class KirimChat {
|
|
|
32
50
|
group: ['transform'],
|
|
33
51
|
version: 1,
|
|
34
52
|
subtitle: '={{$parameter["operation"]}}',
|
|
35
|
-
description: 'Send WhatsApp &
|
|
53
|
+
description: 'Send WhatsApp, Instagram & Messenger messages, mark as read, and send typing indicators',
|
|
36
54
|
defaults: {
|
|
37
55
|
name: 'KirimChat',
|
|
38
56
|
},
|
|
@@ -54,9 +72,21 @@ class KirimChat {
|
|
|
54
72
|
{
|
|
55
73
|
name: 'Send Message',
|
|
56
74
|
value: 'sendMessage',
|
|
57
|
-
description: 'Send a message to a customer via WhatsApp or
|
|
75
|
+
description: 'Send a message to a customer via WhatsApp, Instagram, or Messenger',
|
|
58
76
|
action: 'Send a message',
|
|
59
77
|
},
|
|
78
|
+
{
|
|
79
|
+
name: 'List Templates',
|
|
80
|
+
value: 'listTemplates',
|
|
81
|
+
description: 'List WhatsApp message templates',
|
|
82
|
+
action: 'List templates',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: 'Get Template',
|
|
86
|
+
value: 'getTemplate',
|
|
87
|
+
description: 'Get a specific WhatsApp message template by ID',
|
|
88
|
+
action: 'Get template',
|
|
89
|
+
},
|
|
60
90
|
{
|
|
61
91
|
name: 'Mark as Read',
|
|
62
92
|
value: 'markAsRead',
|
|
@@ -72,7 +102,40 @@ class KirimChat {
|
|
|
72
102
|
],
|
|
73
103
|
default: 'sendMessage',
|
|
74
104
|
},
|
|
75
|
-
//
|
|
105
|
+
// ============================================
|
|
106
|
+
// SEND MESSAGE FIELDS
|
|
107
|
+
// ============================================
|
|
108
|
+
// Customer Lookup Method
|
|
109
|
+
{
|
|
110
|
+
displayName: 'Customer Lookup',
|
|
111
|
+
name: 'customerLookup',
|
|
112
|
+
type: 'options',
|
|
113
|
+
required: true,
|
|
114
|
+
displayOptions: {
|
|
115
|
+
show: {
|
|
116
|
+
operation: ['sendMessage'],
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
options: [
|
|
120
|
+
{
|
|
121
|
+
name: 'Customer ID',
|
|
122
|
+
value: 'customer_id',
|
|
123
|
+
description: 'Lookup by KirimChat customer ID (e.g., cust_abc123)',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: 'Phone Number',
|
|
127
|
+
value: 'phone_number',
|
|
128
|
+
description: 'Lookup by phone number (e.g., +6281234567890)',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'Instagram Username',
|
|
132
|
+
value: 'instagram_username',
|
|
133
|
+
description: 'Lookup by Instagram username',
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
default: 'customer_id',
|
|
137
|
+
description: 'How to identify the customer',
|
|
138
|
+
},
|
|
76
139
|
{
|
|
77
140
|
displayName: 'Customer ID',
|
|
78
141
|
name: 'customerId',
|
|
@@ -81,12 +144,44 @@ class KirimChat {
|
|
|
81
144
|
displayOptions: {
|
|
82
145
|
show: {
|
|
83
146
|
operation: ['sendMessage'],
|
|
147
|
+
customerLookup: ['customer_id'],
|
|
84
148
|
},
|
|
85
149
|
},
|
|
86
150
|
default: '',
|
|
87
151
|
description: 'The ID of the customer to send the message to',
|
|
88
152
|
placeholder: 'cust_abc123',
|
|
89
153
|
},
|
|
154
|
+
{
|
|
155
|
+
displayName: 'Phone Number',
|
|
156
|
+
name: 'phoneNumber',
|
|
157
|
+
type: 'string',
|
|
158
|
+
required: true,
|
|
159
|
+
displayOptions: {
|
|
160
|
+
show: {
|
|
161
|
+
operation: ['sendMessage'],
|
|
162
|
+
customerLookup: ['phone_number'],
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
default: '',
|
|
166
|
+
description: 'The phone number of the customer (with country code)',
|
|
167
|
+
placeholder: '+6281234567890',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
displayName: 'Instagram Username',
|
|
171
|
+
name: 'instagramUsername',
|
|
172
|
+
type: 'string',
|
|
173
|
+
required: true,
|
|
174
|
+
displayOptions: {
|
|
175
|
+
show: {
|
|
176
|
+
operation: ['sendMessage'],
|
|
177
|
+
customerLookup: ['instagram_username'],
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
default: '',
|
|
181
|
+
description: 'The Instagram username of the customer',
|
|
182
|
+
placeholder: 'username',
|
|
183
|
+
},
|
|
184
|
+
// Channel Selection
|
|
90
185
|
{
|
|
91
186
|
displayName: 'Channel',
|
|
92
187
|
name: 'channel',
|
|
@@ -106,10 +201,15 @@ class KirimChat {
|
|
|
106
201
|
name: 'Instagram',
|
|
107
202
|
value: 'instagram',
|
|
108
203
|
},
|
|
204
|
+
{
|
|
205
|
+
name: 'Messenger',
|
|
206
|
+
value: 'messenger',
|
|
207
|
+
},
|
|
109
208
|
],
|
|
110
209
|
default: 'whatsapp',
|
|
111
210
|
description: 'The messaging channel to use',
|
|
112
211
|
},
|
|
212
|
+
// Message Type - WhatsApp
|
|
113
213
|
{
|
|
114
214
|
displayName: 'Message Type',
|
|
115
215
|
name: 'messageType',
|
|
@@ -146,10 +246,15 @@ class KirimChat {
|
|
|
146
246
|
name: 'Template',
|
|
147
247
|
value: 'template',
|
|
148
248
|
},
|
|
249
|
+
{
|
|
250
|
+
name: 'Interactive (Buttons)',
|
|
251
|
+
value: 'interactive',
|
|
252
|
+
},
|
|
149
253
|
],
|
|
150
254
|
default: 'text',
|
|
151
255
|
description: 'The type of message to send (WhatsApp)',
|
|
152
256
|
},
|
|
257
|
+
// Message Type - Instagram
|
|
153
258
|
{
|
|
154
259
|
displayName: 'Message Type',
|
|
155
260
|
name: 'messageType',
|
|
@@ -178,6 +283,44 @@ class KirimChat {
|
|
|
178
283
|
default: 'text',
|
|
179
284
|
description: 'The type of message to send (Instagram)',
|
|
180
285
|
},
|
|
286
|
+
// Message Type - Messenger
|
|
287
|
+
{
|
|
288
|
+
displayName: 'Message Type',
|
|
289
|
+
name: 'messageType',
|
|
290
|
+
type: 'options',
|
|
291
|
+
required: true,
|
|
292
|
+
displayOptions: {
|
|
293
|
+
show: {
|
|
294
|
+
operation: ['sendMessage'],
|
|
295
|
+
channel: ['messenger'],
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
options: [
|
|
299
|
+
{
|
|
300
|
+
name: 'Text',
|
|
301
|
+
value: 'text',
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
name: 'Image',
|
|
305
|
+
value: 'image',
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
name: 'Video',
|
|
309
|
+
value: 'video',
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
name: 'Audio',
|
|
313
|
+
value: 'audio',
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
name: 'File',
|
|
317
|
+
value: 'file',
|
|
318
|
+
},
|
|
319
|
+
],
|
|
320
|
+
default: 'text',
|
|
321
|
+
description: 'The type of message to send (Messenger)',
|
|
322
|
+
},
|
|
323
|
+
// Text Content
|
|
181
324
|
{
|
|
182
325
|
displayName: 'Message Content',
|
|
183
326
|
name: 'content',
|
|
@@ -195,19 +338,23 @@ class KirimChat {
|
|
|
195
338
|
rows: 4,
|
|
196
339
|
},
|
|
197
340
|
},
|
|
341
|
+
// Media URL (for all media types)
|
|
198
342
|
{
|
|
199
343
|
displayName: 'Media URL',
|
|
200
344
|
name: 'mediaUrl',
|
|
201
345
|
type: 'string',
|
|
346
|
+
required: true,
|
|
202
347
|
displayOptions: {
|
|
203
348
|
show: {
|
|
204
349
|
operation: ['sendMessage'],
|
|
205
|
-
messageType: ['image', 'document', 'audio', 'video', 'media_share'],
|
|
350
|
+
messageType: ['image', 'document', 'audio', 'video', 'media_share', 'file'],
|
|
206
351
|
},
|
|
207
352
|
},
|
|
208
353
|
default: '',
|
|
209
|
-
description: 'URL of the media file to send',
|
|
354
|
+
description: 'URL of the media file to send (must be publicly accessible)',
|
|
355
|
+
placeholder: 'https://example.com/image.jpg',
|
|
210
356
|
},
|
|
357
|
+
// Caption (for media messages)
|
|
211
358
|
{
|
|
212
359
|
displayName: 'Caption',
|
|
213
360
|
name: 'caption',
|
|
@@ -221,6 +368,7 @@ class KirimChat {
|
|
|
221
368
|
default: '',
|
|
222
369
|
description: 'Optional caption for media messages',
|
|
223
370
|
},
|
|
371
|
+
// Filename (for documents)
|
|
224
372
|
{
|
|
225
373
|
displayName: 'Filename',
|
|
226
374
|
name: 'filename',
|
|
@@ -228,14 +376,16 @@ class KirimChat {
|
|
|
228
376
|
displayOptions: {
|
|
229
377
|
show: {
|
|
230
378
|
operation: ['sendMessage'],
|
|
231
|
-
messageType: ['document'],
|
|
379
|
+
messageType: ['document', 'file'],
|
|
232
380
|
},
|
|
233
381
|
},
|
|
234
382
|
default: '',
|
|
235
|
-
description: 'Filename for document messages',
|
|
383
|
+
description: 'Filename for document/file messages',
|
|
236
384
|
placeholder: 'invoice.pdf',
|
|
237
385
|
},
|
|
238
|
-
//
|
|
386
|
+
// ============================================
|
|
387
|
+
// TEMPLATE FIELDS (WhatsApp only)
|
|
388
|
+
// ============================================
|
|
239
389
|
{
|
|
240
390
|
displayName: 'Template Name',
|
|
241
391
|
name: 'templateName',
|
|
@@ -279,7 +429,130 @@ class KirimChat {
|
|
|
279
429
|
default: '[]',
|
|
280
430
|
description: 'Template components as JSON array (for variables, buttons, etc.)',
|
|
281
431
|
},
|
|
282
|
-
//
|
|
432
|
+
// ============================================
|
|
433
|
+
// INTERACTIVE MESSAGE FIELDS (WhatsApp only)
|
|
434
|
+
// ============================================
|
|
435
|
+
{
|
|
436
|
+
displayName: 'Interactive Type',
|
|
437
|
+
name: 'interactiveType',
|
|
438
|
+
type: 'options',
|
|
439
|
+
required: true,
|
|
440
|
+
displayOptions: {
|
|
441
|
+
show: {
|
|
442
|
+
operation: ['sendMessage'],
|
|
443
|
+
messageType: ['interactive'],
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
options: [
|
|
447
|
+
{
|
|
448
|
+
name: 'CTA URL Button',
|
|
449
|
+
value: 'cta_url',
|
|
450
|
+
description: 'Call-to-action button that opens a URL',
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
name: 'Reply Buttons',
|
|
454
|
+
value: 'button',
|
|
455
|
+
description: 'Up to 3 reply buttons',
|
|
456
|
+
},
|
|
457
|
+
],
|
|
458
|
+
default: 'cta_url',
|
|
459
|
+
description: 'Type of interactive message',
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
displayName: 'Body Text',
|
|
463
|
+
name: 'interactiveBody',
|
|
464
|
+
type: 'string',
|
|
465
|
+
required: true,
|
|
466
|
+
displayOptions: {
|
|
467
|
+
show: {
|
|
468
|
+
operation: ['sendMessage'],
|
|
469
|
+
messageType: ['interactive'],
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
default: '',
|
|
473
|
+
description: 'Main body text of the interactive message (max 1024 characters)',
|
|
474
|
+
typeOptions: {
|
|
475
|
+
rows: 3,
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
displayName: 'Header Text',
|
|
480
|
+
name: 'interactiveHeader',
|
|
481
|
+
type: 'string',
|
|
482
|
+
displayOptions: {
|
|
483
|
+
show: {
|
|
484
|
+
operation: ['sendMessage'],
|
|
485
|
+
messageType: ['interactive'],
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
default: '',
|
|
489
|
+
description: 'Optional header text (max 60 characters)',
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
displayName: 'Footer Text',
|
|
493
|
+
name: 'interactiveFooter',
|
|
494
|
+
type: 'string',
|
|
495
|
+
displayOptions: {
|
|
496
|
+
show: {
|
|
497
|
+
operation: ['sendMessage'],
|
|
498
|
+
messageType: ['interactive'],
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
default: '',
|
|
502
|
+
description: 'Optional footer text (max 60 characters)',
|
|
503
|
+
},
|
|
504
|
+
// CTA URL specific fields
|
|
505
|
+
{
|
|
506
|
+
displayName: 'Button Text',
|
|
507
|
+
name: 'ctaButtonText',
|
|
508
|
+
type: 'string',
|
|
509
|
+
required: true,
|
|
510
|
+
displayOptions: {
|
|
511
|
+
show: {
|
|
512
|
+
operation: ['sendMessage'],
|
|
513
|
+
messageType: ['interactive'],
|
|
514
|
+
interactiveType: ['cta_url'],
|
|
515
|
+
},
|
|
516
|
+
},
|
|
517
|
+
default: '',
|
|
518
|
+
description: 'Text displayed on the button (max 20 characters)',
|
|
519
|
+
placeholder: 'Visit Website',
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
displayName: 'Button URL',
|
|
523
|
+
name: 'ctaButtonUrl',
|
|
524
|
+
type: 'string',
|
|
525
|
+
required: true,
|
|
526
|
+
displayOptions: {
|
|
527
|
+
show: {
|
|
528
|
+
operation: ['sendMessage'],
|
|
529
|
+
messageType: ['interactive'],
|
|
530
|
+
interactiveType: ['cta_url'],
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
default: '',
|
|
534
|
+
description: 'URL to open when button is clicked',
|
|
535
|
+
placeholder: 'https://example.com',
|
|
536
|
+
},
|
|
537
|
+
// Reply buttons specific fields
|
|
538
|
+
{
|
|
539
|
+
displayName: 'Buttons (JSON)',
|
|
540
|
+
name: 'replyButtons',
|
|
541
|
+
type: 'json',
|
|
542
|
+
required: true,
|
|
543
|
+
displayOptions: {
|
|
544
|
+
show: {
|
|
545
|
+
operation: ['sendMessage'],
|
|
546
|
+
messageType: ['interactive'],
|
|
547
|
+
interactiveType: ['button'],
|
|
548
|
+
},
|
|
549
|
+
},
|
|
550
|
+
default: '[{"id": "btn1", "title": "Yes"}, {"id": "btn2", "title": "No"}]',
|
|
551
|
+
description: 'Array of buttons (1-3). Each button needs "id" (max 256 chars) and "title" (max 20 chars)',
|
|
552
|
+
},
|
|
553
|
+
// ============================================
|
|
554
|
+
// MARK AS READ FIELDS
|
|
555
|
+
// ============================================
|
|
283
556
|
{
|
|
284
557
|
displayName: 'Message ID',
|
|
285
558
|
name: 'messageId',
|
|
@@ -294,32 +567,203 @@ class KirimChat {
|
|
|
294
567
|
description: 'The ID of the message to mark as read',
|
|
295
568
|
placeholder: 'msg_xyz789',
|
|
296
569
|
},
|
|
297
|
-
//
|
|
570
|
+
// ============================================
|
|
571
|
+
// LIST TEMPLATES FIELDS
|
|
572
|
+
// ============================================
|
|
573
|
+
{
|
|
574
|
+
displayName: 'Filter by Status',
|
|
575
|
+
name: 'templateStatus',
|
|
576
|
+
type: 'options',
|
|
577
|
+
displayOptions: {
|
|
578
|
+
show: {
|
|
579
|
+
operation: ['listTemplates'],
|
|
580
|
+
},
|
|
581
|
+
},
|
|
582
|
+
options: [
|
|
583
|
+
{
|
|
584
|
+
name: 'All',
|
|
585
|
+
value: '',
|
|
586
|
+
description: 'Return all templates',
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
name: 'Approved',
|
|
590
|
+
value: 'APPROVED',
|
|
591
|
+
description: 'Only approved templates (ready to use)',
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
name: 'Pending',
|
|
595
|
+
value: 'PENDING',
|
|
596
|
+
description: 'Templates pending approval',
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
name: 'Rejected',
|
|
600
|
+
value: 'REJECTED',
|
|
601
|
+
description: 'Rejected templates',
|
|
602
|
+
},
|
|
603
|
+
],
|
|
604
|
+
default: '',
|
|
605
|
+
description: 'Filter templates by approval status',
|
|
606
|
+
},
|
|
607
|
+
{
|
|
608
|
+
displayName: 'Filter by Category',
|
|
609
|
+
name: 'templateCategory',
|
|
610
|
+
type: 'options',
|
|
611
|
+
displayOptions: {
|
|
612
|
+
show: {
|
|
613
|
+
operation: ['listTemplates'],
|
|
614
|
+
},
|
|
615
|
+
},
|
|
616
|
+
options: [
|
|
617
|
+
{
|
|
618
|
+
name: 'All',
|
|
619
|
+
value: '',
|
|
620
|
+
description: 'Return all categories',
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
name: 'Marketing',
|
|
624
|
+
value: 'MARKETING',
|
|
625
|
+
description: 'Marketing templates',
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
name: 'Utility',
|
|
629
|
+
value: 'UTILITY',
|
|
630
|
+
description: 'Utility templates (order updates, etc.)',
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
name: 'Authentication',
|
|
634
|
+
value: 'AUTHENTICATION',
|
|
635
|
+
description: 'Authentication templates (OTP, etc.)',
|
|
636
|
+
},
|
|
637
|
+
],
|
|
638
|
+
default: '',
|
|
639
|
+
description: 'Filter templates by category',
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
displayName: 'Limit',
|
|
643
|
+
name: 'templateLimit',
|
|
644
|
+
type: 'number',
|
|
645
|
+
displayOptions: {
|
|
646
|
+
show: {
|
|
647
|
+
operation: ['listTemplates'],
|
|
648
|
+
},
|
|
649
|
+
},
|
|
650
|
+
default: 100,
|
|
651
|
+
description: 'Maximum number of templates to return (max 500)',
|
|
652
|
+
typeOptions: {
|
|
653
|
+
minValue: 1,
|
|
654
|
+
maxValue: 500,
|
|
655
|
+
},
|
|
656
|
+
},
|
|
657
|
+
// ============================================
|
|
658
|
+
// GET TEMPLATE FIELDS
|
|
659
|
+
// ============================================
|
|
660
|
+
{
|
|
661
|
+
displayName: 'Template ID',
|
|
662
|
+
name: 'templateId',
|
|
663
|
+
type: 'string',
|
|
664
|
+
required: true,
|
|
665
|
+
displayOptions: {
|
|
666
|
+
show: {
|
|
667
|
+
operation: ['getTemplate'],
|
|
668
|
+
},
|
|
669
|
+
},
|
|
670
|
+
default: '',
|
|
671
|
+
description: 'The ID of the template to retrieve',
|
|
672
|
+
placeholder: 'tpl_abc123',
|
|
673
|
+
},
|
|
674
|
+
// ============================================
|
|
675
|
+
// SEND TYPING FIELDS
|
|
676
|
+
// ============================================
|
|
677
|
+
{
|
|
678
|
+
displayName: 'Customer Lookup',
|
|
679
|
+
name: 'typingCustomerLookup',
|
|
680
|
+
type: 'options',
|
|
681
|
+
required: true,
|
|
682
|
+
displayOptions: {
|
|
683
|
+
show: {
|
|
684
|
+
operation: ['sendTyping'],
|
|
685
|
+
},
|
|
686
|
+
},
|
|
687
|
+
options: [
|
|
688
|
+
{
|
|
689
|
+
name: 'Customer ID',
|
|
690
|
+
value: 'customer_id',
|
|
691
|
+
description: 'Lookup by KirimChat customer ID',
|
|
692
|
+
},
|
|
693
|
+
{
|
|
694
|
+
name: 'Phone Number',
|
|
695
|
+
value: 'phone_number',
|
|
696
|
+
description: 'Lookup by phone number',
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
name: 'Instagram Username',
|
|
700
|
+
value: 'instagram_username',
|
|
701
|
+
description: 'Lookup by Instagram username',
|
|
702
|
+
},
|
|
703
|
+
],
|
|
704
|
+
default: 'customer_id',
|
|
705
|
+
description: 'How to identify the customer',
|
|
706
|
+
},
|
|
298
707
|
{
|
|
299
708
|
displayName: 'Customer ID',
|
|
300
|
-
name: '
|
|
709
|
+
name: 'typingCustomerId',
|
|
301
710
|
type: 'string',
|
|
302
711
|
required: true,
|
|
303
712
|
displayOptions: {
|
|
304
713
|
show: {
|
|
305
714
|
operation: ['sendTyping'],
|
|
715
|
+
typingCustomerLookup: ['customer_id'],
|
|
306
716
|
},
|
|
307
717
|
},
|
|
308
718
|
default: '',
|
|
309
719
|
description: 'The ID of the customer to send typing indicator to',
|
|
310
720
|
placeholder: 'cust_abc123',
|
|
311
721
|
},
|
|
722
|
+
{
|
|
723
|
+
displayName: 'Phone Number',
|
|
724
|
+
name: 'typingPhoneNumber',
|
|
725
|
+
type: 'string',
|
|
726
|
+
required: true,
|
|
727
|
+
displayOptions: {
|
|
728
|
+
show: {
|
|
729
|
+
operation: ['sendTyping'],
|
|
730
|
+
typingCustomerLookup: ['phone_number'],
|
|
731
|
+
},
|
|
732
|
+
},
|
|
733
|
+
default: '',
|
|
734
|
+
description: 'The phone number of the customer',
|
|
735
|
+
placeholder: '+6281234567890',
|
|
736
|
+
},
|
|
737
|
+
{
|
|
738
|
+
displayName: 'Instagram Username',
|
|
739
|
+
name: 'typingInstagramUsername',
|
|
740
|
+
type: 'string',
|
|
741
|
+
required: true,
|
|
742
|
+
displayOptions: {
|
|
743
|
+
show: {
|
|
744
|
+
operation: ['sendTyping'],
|
|
745
|
+
typingCustomerLookup: ['instagram_username'],
|
|
746
|
+
},
|
|
747
|
+
},
|
|
748
|
+
default: '',
|
|
749
|
+
description: 'The Instagram username of the customer',
|
|
750
|
+
placeholder: 'username',
|
|
751
|
+
},
|
|
312
752
|
{
|
|
313
753
|
displayName: 'Channel',
|
|
314
|
-
name: '
|
|
754
|
+
name: 'typingChannel',
|
|
315
755
|
type: 'options',
|
|
316
|
-
required: true,
|
|
317
756
|
displayOptions: {
|
|
318
757
|
show: {
|
|
319
758
|
operation: ['sendTyping'],
|
|
320
759
|
},
|
|
321
760
|
},
|
|
322
761
|
options: [
|
|
762
|
+
{
|
|
763
|
+
name: 'Auto-detect',
|
|
764
|
+
value: '',
|
|
765
|
+
description: 'Automatically detect based on customer data',
|
|
766
|
+
},
|
|
323
767
|
{
|
|
324
768
|
name: 'WhatsApp',
|
|
325
769
|
value: 'whatsapp',
|
|
@@ -329,8 +773,8 @@ class KirimChat {
|
|
|
329
773
|
value: 'instagram',
|
|
330
774
|
},
|
|
331
775
|
],
|
|
332
|
-
default: '
|
|
333
|
-
description: 'The messaging channel to use',
|
|
776
|
+
default: '',
|
|
777
|
+
description: 'The messaging channel to use (leave empty for auto-detect)',
|
|
334
778
|
},
|
|
335
779
|
],
|
|
336
780
|
};
|
|
@@ -345,15 +789,27 @@ class KirimChat {
|
|
|
345
789
|
const operation = this.getNodeParameter('operation', i);
|
|
346
790
|
let responseData;
|
|
347
791
|
if (operation === 'sendMessage') {
|
|
348
|
-
//
|
|
349
|
-
|
|
792
|
+
// ============================================
|
|
793
|
+
// SEND MESSAGE OPERATION
|
|
794
|
+
// ============================================
|
|
795
|
+
const customerLookup = this.getNodeParameter('customerLookup', i);
|
|
350
796
|
const channel = this.getNodeParameter('channel', i);
|
|
351
797
|
const messageType = this.getNodeParameter('messageType', i);
|
|
352
798
|
const body = {
|
|
353
|
-
customer_id: customerId,
|
|
354
799
|
channel,
|
|
355
800
|
message_type: messageType,
|
|
356
801
|
};
|
|
802
|
+
// Set customer identifier based on lookup method
|
|
803
|
+
if (customerLookup === 'customer_id') {
|
|
804
|
+
body.customer_id = this.getNodeParameter('customerId', i);
|
|
805
|
+
}
|
|
806
|
+
else if (customerLookup === 'phone_number') {
|
|
807
|
+
body.phone_number = this.getNodeParameter('phoneNumber', i);
|
|
808
|
+
}
|
|
809
|
+
else if (customerLookup === 'instagram_username') {
|
|
810
|
+
body.instagram_username = this.getNodeParameter('instagramUsername', i);
|
|
811
|
+
}
|
|
812
|
+
// Handle different message types
|
|
357
813
|
if (messageType === 'text') {
|
|
358
814
|
body.content = this.getNodeParameter('content', i);
|
|
359
815
|
}
|
|
@@ -379,24 +835,90 @@ class KirimChat {
|
|
|
379
835
|
components: templateComponents,
|
|
380
836
|
};
|
|
381
837
|
}
|
|
838
|
+
else if (messageType === 'interactive') {
|
|
839
|
+
// WhatsApp interactive message
|
|
840
|
+
const interactiveType = this.getNodeParameter('interactiveType', i);
|
|
841
|
+
const interactiveBody = this.getNodeParameter('interactiveBody', i);
|
|
842
|
+
const interactiveHeader = this.getNodeParameter('interactiveHeader', i, '');
|
|
843
|
+
const interactiveFooter = this.getNodeParameter('interactiveFooter', i, '');
|
|
844
|
+
const interactive = {
|
|
845
|
+
type: interactiveType,
|
|
846
|
+
body: { text: interactiveBody },
|
|
847
|
+
};
|
|
848
|
+
// Add optional header
|
|
849
|
+
if (interactiveHeader) {
|
|
850
|
+
interactive.header = {
|
|
851
|
+
type: 'text',
|
|
852
|
+
text: interactiveHeader,
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
// Add optional footer
|
|
856
|
+
if (interactiveFooter) {
|
|
857
|
+
interactive.footer = { text: interactiveFooter };
|
|
858
|
+
}
|
|
859
|
+
// Add action based on type
|
|
860
|
+
if (interactiveType === 'cta_url') {
|
|
861
|
+
const ctaButtonText = this.getNodeParameter('ctaButtonText', i);
|
|
862
|
+
const ctaButtonUrl = this.getNodeParameter('ctaButtonUrl', i);
|
|
863
|
+
if (!isValidUrl(ctaButtonUrl)) {
|
|
864
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid Button URL format: "${ctaButtonUrl}". URL must start with http:// or https://`, { itemIndex: i });
|
|
865
|
+
}
|
|
866
|
+
interactive.action = {
|
|
867
|
+
name: 'cta_url',
|
|
868
|
+
parameters: {
|
|
869
|
+
display_text: ctaButtonText,
|
|
870
|
+
url: ctaButtonUrl,
|
|
871
|
+
},
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
else if (interactiveType === 'button') {
|
|
875
|
+
const replyButtonsJson = this.getNodeParameter('replyButtons', i);
|
|
876
|
+
let replyButtons;
|
|
877
|
+
try {
|
|
878
|
+
replyButtons = JSON.parse(replyButtonsJson);
|
|
879
|
+
}
|
|
880
|
+
catch (error) {
|
|
881
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid JSON in Reply Buttons: ${error instanceof Error ? error.message : 'Parse failed'}`, { itemIndex: i });
|
|
882
|
+
}
|
|
883
|
+
if (!Array.isArray(replyButtons) || replyButtons.length === 0 || replyButtons.length > 3) {
|
|
884
|
+
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 });
|
|
885
|
+
}
|
|
886
|
+
// Transform to n8n format
|
|
887
|
+
const formattedButtons = replyButtons.map((btn) => ({
|
|
888
|
+
type: 'reply',
|
|
889
|
+
reply: {
|
|
890
|
+
id: btn.id || '',
|
|
891
|
+
title: btn.title || '',
|
|
892
|
+
},
|
|
893
|
+
}));
|
|
894
|
+
interactive.action = {
|
|
895
|
+
buttons: formattedButtons,
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
if (!validateInteractiveMessage(interactive)) {
|
|
899
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid interactive message structure', { itemIndex: i });
|
|
900
|
+
}
|
|
901
|
+
body.interactive = interactive;
|
|
902
|
+
}
|
|
382
903
|
else {
|
|
383
|
-
// Media messages
|
|
384
|
-
const mediaUrl = this.getNodeParameter('mediaUrl', i
|
|
904
|
+
// Media messages (image, document, audio, video, media_share, file)
|
|
905
|
+
const mediaUrl = this.getNodeParameter('mediaUrl', i);
|
|
385
906
|
// Validate media URL is provided
|
|
386
907
|
if (!mediaUrl) {
|
|
387
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(),
|
|
908
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Media URL is required for ${messageType} messages`, { itemIndex: i });
|
|
388
909
|
}
|
|
389
910
|
// Validate media URL format
|
|
390
911
|
if (!isValidUrl(mediaUrl)) {
|
|
391
912
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid Media URL format: "${mediaUrl}". URL must start with http:// or https://`, { itemIndex: i });
|
|
392
913
|
}
|
|
393
914
|
body.media_url = mediaUrl;
|
|
915
|
+
// Add caption if provided
|
|
394
916
|
const caption = this.getNodeParameter('caption', i, '');
|
|
395
917
|
if (caption) {
|
|
396
918
|
body.caption = caption;
|
|
397
919
|
}
|
|
398
|
-
//
|
|
399
|
-
if (messageType === 'document') {
|
|
920
|
+
// Add filename for document/file types
|
|
921
|
+
if (messageType === 'document' || messageType === 'file') {
|
|
400
922
|
const filename = this.getNodeParameter('filename', i, '');
|
|
401
923
|
if (filename) {
|
|
402
924
|
body.filename = filename;
|
|
@@ -411,7 +933,9 @@ class KirimChat {
|
|
|
411
933
|
});
|
|
412
934
|
}
|
|
413
935
|
else if (operation === 'markAsRead') {
|
|
414
|
-
//
|
|
936
|
+
// ============================================
|
|
937
|
+
// MARK AS READ OPERATION
|
|
938
|
+
// ============================================
|
|
415
939
|
const messageId = this.getNodeParameter('messageId', i);
|
|
416
940
|
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'kirimChatApi', {
|
|
417
941
|
method: 'POST',
|
|
@@ -419,14 +943,67 @@ class KirimChat {
|
|
|
419
943
|
json: true,
|
|
420
944
|
});
|
|
421
945
|
}
|
|
946
|
+
else if (operation === 'listTemplates') {
|
|
947
|
+
// ============================================
|
|
948
|
+
// LIST TEMPLATES OPERATION
|
|
949
|
+
// ============================================
|
|
950
|
+
const templateStatus = this.getNodeParameter('templateStatus', i, '');
|
|
951
|
+
const templateCategory = this.getNodeParameter('templateCategory', i, '');
|
|
952
|
+
const templateLimit = this.getNodeParameter('templateLimit', i, 100);
|
|
953
|
+
// Build query string
|
|
954
|
+
const queryParams = [];
|
|
955
|
+
if (templateStatus) {
|
|
956
|
+
queryParams.push(`status=${templateStatus}`);
|
|
957
|
+
}
|
|
958
|
+
if (templateCategory) {
|
|
959
|
+
queryParams.push(`category=${templateCategory}`);
|
|
960
|
+
}
|
|
961
|
+
if (templateLimit) {
|
|
962
|
+
queryParams.push(`limit=${templateLimit}`);
|
|
963
|
+
}
|
|
964
|
+
const queryString = queryParams.length > 0 ? `?${queryParams.join('&')}` : '';
|
|
965
|
+
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'kirimChatApi', {
|
|
966
|
+
method: 'GET',
|
|
967
|
+
url: `${baseUrl}/templates${queryString}`,
|
|
968
|
+
json: true,
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
else if (operation === 'getTemplate') {
|
|
972
|
+
// ============================================
|
|
973
|
+
// GET TEMPLATE OPERATION
|
|
974
|
+
// ============================================
|
|
975
|
+
const templateId = this.getNodeParameter('templateId', i);
|
|
976
|
+
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'kirimChatApi', {
|
|
977
|
+
method: 'GET',
|
|
978
|
+
url: `${baseUrl}/templates/${templateId}`,
|
|
979
|
+
json: true,
|
|
980
|
+
});
|
|
981
|
+
}
|
|
422
982
|
else if (operation === 'sendTyping') {
|
|
423
|
-
//
|
|
424
|
-
|
|
425
|
-
|
|
983
|
+
// ============================================
|
|
984
|
+
// SEND TYPING INDICATOR OPERATION
|
|
985
|
+
// ============================================
|
|
986
|
+
const typingLookup = this.getNodeParameter('typingCustomerLookup', i);
|
|
987
|
+
const typingChannel = this.getNodeParameter('typingChannel', i, '');
|
|
988
|
+
// Get customer identifier based on lookup method
|
|
989
|
+
let customerIdentifier;
|
|
990
|
+
if (typingLookup === 'customer_id') {
|
|
991
|
+
customerIdentifier = this.getNodeParameter('typingCustomerId', i);
|
|
992
|
+
}
|
|
993
|
+
else if (typingLookup === 'phone_number') {
|
|
994
|
+
customerIdentifier = this.getNodeParameter('typingPhoneNumber', i);
|
|
995
|
+
}
|
|
996
|
+
else {
|
|
997
|
+
customerIdentifier = this.getNodeParameter('typingInstagramUsername', i);
|
|
998
|
+
}
|
|
999
|
+
const typingBody = {};
|
|
1000
|
+
if (typingChannel) {
|
|
1001
|
+
typingBody.channel = typingChannel;
|
|
1002
|
+
}
|
|
426
1003
|
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'kirimChatApi', {
|
|
427
1004
|
method: 'POST',
|
|
428
|
-
url: `${baseUrl}/conversations/${
|
|
429
|
-
body:
|
|
1005
|
+
url: `${baseUrl}/conversations/${customerIdentifier}/typing`,
|
|
1006
|
+
body: typingBody,
|
|
430
1007
|
json: true,
|
|
431
1008
|
});
|
|
432
1009
|
}
|
package/package.json
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@kichat/n8n-nodes-kirimchat",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "n8n community node for KirimChat - Send WhatsApp &
|
|
5
|
-
"keywords": [
|
|
6
|
-
"n8n-community-node-package",
|
|
7
|
-
"n8n",
|
|
8
|
-
"kirimchat",
|
|
9
|
-
"whatsapp",
|
|
10
|
-
"instagram",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@kichat/n8n-nodes-kirimchat",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "n8n community node for KirimChat - Send WhatsApp, Instagram & Messenger messages with interactive buttons, flexible customer lookup, and typing indicators",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"n8n-community-node-package",
|
|
7
|
+
"n8n",
|
|
8
|
+
"kirimchat",
|
|
9
|
+
"whatsapp",
|
|
10
|
+
"instagram",
|
|
11
|
+
"messenger",
|
|
12
|
+
"facebook",
|
|
13
|
+
"messaging",
|
|
14
|
+
"chat",
|
|
15
|
+
"automation"
|
|
16
|
+
],
|
|
14
17
|
"license": "MIT",
|
|
15
18
|
"homepage": "https://kirim.chat",
|
|
16
19
|
"author": {
|