@kichat/n8n-nodes-kirimchat 1.0.4 → 1.1.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 +244 -139
- package/dist/nodes/KirimChat/KirimChat.node.js +489 -30
- package/package.json +17 -14
package/README.md
CHANGED
|
@@ -1,139 +1,244 @@
|
|
|
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
|
-
- **Mark as Read** - Mark messages as read and send read receipts
|
|
9
|
-
- **Send Typing Indicator** - Show typing indicator to customers
|
|
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
|
+
- **Mark as Read** - Mark messages as read and send read receipts
|
|
9
|
+
- **Send Typing Indicator** - Show typing indicator to customers
|
|
10
|
+
- **Flexible Customer Lookup** - Find customers by ID, phone number, or Instagram username
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
### Community Nodes (Recommended)
|
|
15
|
+
|
|
16
|
+
1. Go to **Settings > Community Nodes**
|
|
17
|
+
2. Select **Install**
|
|
18
|
+
3. Enter `@kichat/n8n-nodes-kirimchat` and confirm
|
|
19
|
+
|
|
20
|
+
## Credentials
|
|
21
|
+
|
|
22
|
+
You need a KirimChat API key to use this node:
|
|
23
|
+
|
|
24
|
+
1. Log in to your KirimChat dashboard
|
|
25
|
+
2. Go to **Settings > Developers > API Keys**
|
|
26
|
+
3. Click **Create API Key** and copy the key (shown only once)
|
|
27
|
+
4. In n8n, create new credentials for **KirimChat API**
|
|
28
|
+
5. Paste your API key (starts with `kc_live_`)
|
|
29
|
+
|
|
30
|
+
## Operations
|
|
31
|
+
|
|
32
|
+
### Send Message
|
|
33
|
+
|
|
34
|
+
Send a message to a customer via WhatsApp, Instagram, or Messenger.
|
|
35
|
+
|
|
36
|
+
#### Customer Lookup Options
|
|
37
|
+
|
|
38
|
+
| Method | Description | Example |
|
|
39
|
+
|--------|-------------|---------|
|
|
40
|
+
| Customer ID | KirimChat customer ID | `cust_abc123` |
|
|
41
|
+
| Phone Number | Phone with country code | `+6281234567890` |
|
|
42
|
+
| Instagram Username | Instagram username | `johndoe` |
|
|
43
|
+
|
|
44
|
+
#### Channels & Message Types
|
|
45
|
+
|
|
46
|
+
| Channel | Message Types |
|
|
47
|
+
|---------|---------------|
|
|
48
|
+
| **WhatsApp** | `text`, `image`, `document`, `audio`, `video`, `template`, `interactive` |
|
|
49
|
+
| **Instagram** | `text`, `image`, `media_share` |
|
|
50
|
+
| **Messenger** | `text`, `image`, `video`, `audio`, `file` |
|
|
51
|
+
|
|
52
|
+
#### Parameters
|
|
53
|
+
|
|
54
|
+
| Parameter | Description |
|
|
55
|
+
|-----------|-------------|
|
|
56
|
+
| Customer Lookup | How to identify the customer |
|
|
57
|
+
| Channel | `whatsapp`, `instagram`, or `messenger` |
|
|
58
|
+
| Message Type | Type of message (varies by channel) |
|
|
59
|
+
| Content | Text content for text messages |
|
|
60
|
+
| Media URL | URL of media file for media messages |
|
|
61
|
+
| Caption | Optional caption for media messages |
|
|
62
|
+
| Filename | Filename for document/file messages |
|
|
63
|
+
|
|
64
|
+
#### WhatsApp Template Messages
|
|
65
|
+
|
|
66
|
+
| Parameter | Description |
|
|
67
|
+
|-----------|-------------|
|
|
68
|
+
| Template Name | Name of the approved template |
|
|
69
|
+
| Template Language | Language code (e.g., `en`, `id`) |
|
|
70
|
+
| Template Components | JSON array for variables and buttons |
|
|
71
|
+
|
|
72
|
+
**Example Template Components:**
|
|
73
|
+
```json
|
|
74
|
+
[
|
|
75
|
+
{
|
|
76
|
+
"type": "body",
|
|
77
|
+
"parameters": [
|
|
78
|
+
{ "type": "text", "text": "John" },
|
|
79
|
+
{ "type": "text", "text": "12345" }
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
#### WhatsApp Interactive Messages
|
|
86
|
+
|
|
87
|
+
Send buttons with your messages:
|
|
88
|
+
|
|
89
|
+
**CTA URL Button:**
|
|
90
|
+
| Parameter | Description |
|
|
91
|
+
|-----------|-------------|
|
|
92
|
+
| Interactive Type | `cta_url` |
|
|
93
|
+
| Body Text | Main message text (max 1024 chars) |
|
|
94
|
+
| Header Text | Optional header (max 60 chars) |
|
|
95
|
+
| Footer Text | Optional footer (max 60 chars) |
|
|
96
|
+
| Button Text | Text on button (max 20 chars) |
|
|
97
|
+
| Button URL | URL to open |
|
|
98
|
+
|
|
99
|
+
**Reply Buttons:**
|
|
100
|
+
| Parameter | Description |
|
|
101
|
+
|-----------|-------------|
|
|
102
|
+
| Interactive Type | `button` |
|
|
103
|
+
| Body Text | Main message text |
|
|
104
|
+
| Buttons (JSON) | Array of 1-3 buttons |
|
|
105
|
+
|
|
106
|
+
**Example Reply Buttons:**
|
|
107
|
+
```json
|
|
108
|
+
[
|
|
109
|
+
{ "id": "yes", "title": "Yes" },
|
|
110
|
+
{ "id": "no", "title": "No" },
|
|
111
|
+
{ "id": "maybe", "title": "Maybe" }
|
|
112
|
+
]
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Example Response:**
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"success": true,
|
|
119
|
+
"data": {
|
|
120
|
+
"message_id": "msg_xyz789",
|
|
121
|
+
"status": "sent",
|
|
122
|
+
"channel": "whatsapp",
|
|
123
|
+
"timestamp": "2025-11-26T10:31:00.000Z"
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Mark as Read
|
|
129
|
+
|
|
130
|
+
Mark a message as read and send read receipt to the customer.
|
|
131
|
+
|
|
132
|
+
| Parameter | Description |
|
|
133
|
+
|-----------|-------------|
|
|
134
|
+
| Message ID | The ID of the message to mark as read (e.g., `msg_xyz789`) |
|
|
135
|
+
|
|
136
|
+
### Send Typing Indicator
|
|
137
|
+
|
|
138
|
+
Show typing indicator to a customer before sending a message.
|
|
139
|
+
|
|
140
|
+
| Parameter | Description |
|
|
141
|
+
|-----------|-------------|
|
|
142
|
+
| Customer Lookup | How to identify the customer |
|
|
143
|
+
| Customer ID/Phone/Username | Customer identifier |
|
|
144
|
+
| Channel | `whatsapp`, `instagram`, or auto-detect |
|
|
145
|
+
|
|
146
|
+
> **Note:** Rate limited to 1 request per customer per 3 seconds.
|
|
147
|
+
|
|
148
|
+
## Webhook Trigger
|
|
149
|
+
|
|
150
|
+
KirimChat supports outbound webhooks for real-time event notifications. Configure webhooks in your KirimChat dashboard under **Settings > Developers > Webhooks**.
|
|
151
|
+
|
|
152
|
+
### Supported Events
|
|
153
|
+
|
|
154
|
+
- `message.received` - New message from customer
|
|
155
|
+
- `message.sent` - Message sent to customer
|
|
156
|
+
- `message.delivered` - Message delivered
|
|
157
|
+
- `message.read` - Message read by customer
|
|
158
|
+
- `message.failed` - Message delivery failed
|
|
159
|
+
|
|
160
|
+
### Webhook Payload Example
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"event_type": "message.received",
|
|
165
|
+
"event_id": "evt_abc123",
|
|
166
|
+
"timestamp": "2025-11-26T10:30:00.000Z",
|
|
167
|
+
"data": {
|
|
168
|
+
"message_id": "msg_xyz789",
|
|
169
|
+
"customer_id": "cust_123",
|
|
170
|
+
"customer_phone": "+6281234567890",
|
|
171
|
+
"direction": "inbound",
|
|
172
|
+
"message_type": "text",
|
|
173
|
+
"content": "Hello!",
|
|
174
|
+
"channel": "whatsapp"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Using with n8n Webhook Node
|
|
180
|
+
|
|
181
|
+
1. Create a new workflow with **Webhook** trigger node
|
|
182
|
+
2. Copy the webhook URL
|
|
183
|
+
3. In KirimChat, create a webhook endpoint with this URL
|
|
184
|
+
4. Select the events you want to receive
|
|
185
|
+
5. Connect the webhook to your KirimChat node for automated responses
|
|
186
|
+
|
|
187
|
+
## Rate Limits
|
|
188
|
+
|
|
189
|
+
| Limit Type | Rate |
|
|
190
|
+
|------------|------|
|
|
191
|
+
| Global | 100 requests per minute per API key |
|
|
192
|
+
| WhatsApp | 60 messages per minute |
|
|
193
|
+
| Instagram | 180 messages per hour |
|
|
194
|
+
| Messenger | 180 messages per hour |
|
|
195
|
+
| Typing Indicator | 1 request per customer per 3 seconds |
|
|
196
|
+
|
|
197
|
+
## Error Handling
|
|
198
|
+
|
|
199
|
+
The node returns standard error responses:
|
|
200
|
+
|
|
201
|
+
| Code | Description |
|
|
202
|
+
|------|-------------|
|
|
203
|
+
| 401 | Invalid or expired API key |
|
|
204
|
+
| 403 | Account disconnected or forbidden |
|
|
205
|
+
| 404 | Resource not found |
|
|
206
|
+
| 400 | Invalid request or messaging window closed |
|
|
207
|
+
| 429 | Rate limit exceeded |
|
|
208
|
+
|
|
209
|
+
### Common Error Codes
|
|
210
|
+
|
|
211
|
+
| Error Code | Description |
|
|
212
|
+
|------------|-------------|
|
|
213
|
+
| `ValidationError` | Invalid input parameters |
|
|
214
|
+
| `WindowClosed` | 24-hour messaging window expired |
|
|
215
|
+
| `ConfigurationError` | Channel not configured |
|
|
216
|
+
| `ConnectionError` | Account disconnected |
|
|
217
|
+
| `RateLimitExceeded` | Too many requests |
|
|
218
|
+
|
|
219
|
+
## Changelog
|
|
220
|
+
|
|
221
|
+
### v1.1.0 (Latest)
|
|
222
|
+
- ✅ Added Messenger channel support
|
|
223
|
+
- ✅ Added customer lookup by phone number and Instagram username
|
|
224
|
+
- ✅ Added WhatsApp Interactive messages (CTA URL buttons, Reply buttons)
|
|
225
|
+
- ✅ Improved typing indicator with flexible customer lookup
|
|
226
|
+
- ✅ Enhanced error messages
|
|
227
|
+
|
|
228
|
+
### v1.0.5
|
|
229
|
+
- Enhanced validation for media URLs
|
|
230
|
+
- Template components structure validation
|
|
231
|
+
|
|
232
|
+
### v1.0.1
|
|
233
|
+
- Initial security improvements
|
|
234
|
+
- JSON validation for templates
|
|
235
|
+
- Base URL security warning
|
|
236
|
+
|
|
237
|
+
## Resources
|
|
238
|
+
|
|
239
|
+
- [KirimChat Documentation](https://kirim.chat/developers)
|
|
240
|
+
- [n8n Community Nodes](https://docs.n8n.io/integrations/community-nodes/)
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
MIT
|
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.KirimChat = void 0;
|
|
4
4
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
/**
|
|
6
|
+
* Validates if a string is a valid URL
|
|
7
|
+
*/
|
|
8
|
+
function isValidUrl(urlString) {
|
|
9
|
+
try {
|
|
10
|
+
const url = new URL(urlString);
|
|
11
|
+
return url.protocol === 'http:' || url.protocol === 'https:';
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Validates template components structure
|
|
19
|
+
*/
|
|
20
|
+
function validateTemplateComponents(components) {
|
|
21
|
+
if (!Array.isArray(components)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return components.every((component) => typeof component === 'object' && component !== null);
|
|
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
|
+
}
|
|
5
44
|
class KirimChat {
|
|
6
45
|
constructor() {
|
|
7
46
|
this.description = {
|
|
@@ -11,7 +50,7 @@ class KirimChat {
|
|
|
11
50
|
group: ['transform'],
|
|
12
51
|
version: 1,
|
|
13
52
|
subtitle: '={{$parameter["operation"]}}',
|
|
14
|
-
description: 'Send WhatsApp &
|
|
53
|
+
description: 'Send WhatsApp, Instagram & Messenger messages, mark as read, and send typing indicators',
|
|
15
54
|
defaults: {
|
|
16
55
|
name: 'KirimChat',
|
|
17
56
|
},
|
|
@@ -33,7 +72,7 @@ class KirimChat {
|
|
|
33
72
|
{
|
|
34
73
|
name: 'Send Message',
|
|
35
74
|
value: 'sendMessage',
|
|
36
|
-
description: 'Send a message to a customer via WhatsApp or
|
|
75
|
+
description: 'Send a message to a customer via WhatsApp, Instagram, or Messenger',
|
|
37
76
|
action: 'Send a message',
|
|
38
77
|
},
|
|
39
78
|
{
|
|
@@ -51,7 +90,40 @@ class KirimChat {
|
|
|
51
90
|
],
|
|
52
91
|
default: 'sendMessage',
|
|
53
92
|
},
|
|
54
|
-
//
|
|
93
|
+
// ============================================
|
|
94
|
+
// SEND MESSAGE FIELDS
|
|
95
|
+
// ============================================
|
|
96
|
+
// Customer Lookup Method
|
|
97
|
+
{
|
|
98
|
+
displayName: 'Customer Lookup',
|
|
99
|
+
name: 'customerLookup',
|
|
100
|
+
type: 'options',
|
|
101
|
+
required: true,
|
|
102
|
+
displayOptions: {
|
|
103
|
+
show: {
|
|
104
|
+
operation: ['sendMessage'],
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
options: [
|
|
108
|
+
{
|
|
109
|
+
name: 'Customer ID',
|
|
110
|
+
value: 'customer_id',
|
|
111
|
+
description: 'Lookup by KirimChat customer ID (e.g., cust_abc123)',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: 'Phone Number',
|
|
115
|
+
value: 'phone_number',
|
|
116
|
+
description: 'Lookup by phone number (e.g., +6281234567890)',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: 'Instagram Username',
|
|
120
|
+
value: 'instagram_username',
|
|
121
|
+
description: 'Lookup by Instagram username',
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
default: 'customer_id',
|
|
125
|
+
description: 'How to identify the customer',
|
|
126
|
+
},
|
|
55
127
|
{
|
|
56
128
|
displayName: 'Customer ID',
|
|
57
129
|
name: 'customerId',
|
|
@@ -60,12 +132,44 @@ class KirimChat {
|
|
|
60
132
|
displayOptions: {
|
|
61
133
|
show: {
|
|
62
134
|
operation: ['sendMessage'],
|
|
135
|
+
customerLookup: ['customer_id'],
|
|
63
136
|
},
|
|
64
137
|
},
|
|
65
138
|
default: '',
|
|
66
139
|
description: 'The ID of the customer to send the message to',
|
|
67
140
|
placeholder: 'cust_abc123',
|
|
68
141
|
},
|
|
142
|
+
{
|
|
143
|
+
displayName: 'Phone Number',
|
|
144
|
+
name: 'phoneNumber',
|
|
145
|
+
type: 'string',
|
|
146
|
+
required: true,
|
|
147
|
+
displayOptions: {
|
|
148
|
+
show: {
|
|
149
|
+
operation: ['sendMessage'],
|
|
150
|
+
customerLookup: ['phone_number'],
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
default: '',
|
|
154
|
+
description: 'The phone number of the customer (with country code)',
|
|
155
|
+
placeholder: '+6281234567890',
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
displayName: 'Instagram Username',
|
|
159
|
+
name: 'instagramUsername',
|
|
160
|
+
type: 'string',
|
|
161
|
+
required: true,
|
|
162
|
+
displayOptions: {
|
|
163
|
+
show: {
|
|
164
|
+
operation: ['sendMessage'],
|
|
165
|
+
customerLookup: ['instagram_username'],
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
default: '',
|
|
169
|
+
description: 'The Instagram username of the customer',
|
|
170
|
+
placeholder: 'username',
|
|
171
|
+
},
|
|
172
|
+
// Channel Selection
|
|
69
173
|
{
|
|
70
174
|
displayName: 'Channel',
|
|
71
175
|
name: 'channel',
|
|
@@ -85,10 +189,15 @@ class KirimChat {
|
|
|
85
189
|
name: 'Instagram',
|
|
86
190
|
value: 'instagram',
|
|
87
191
|
},
|
|
192
|
+
{
|
|
193
|
+
name: 'Messenger',
|
|
194
|
+
value: 'messenger',
|
|
195
|
+
},
|
|
88
196
|
],
|
|
89
197
|
default: 'whatsapp',
|
|
90
198
|
description: 'The messaging channel to use',
|
|
91
199
|
},
|
|
200
|
+
// Message Type - WhatsApp
|
|
92
201
|
{
|
|
93
202
|
displayName: 'Message Type',
|
|
94
203
|
name: 'messageType',
|
|
@@ -125,10 +234,15 @@ class KirimChat {
|
|
|
125
234
|
name: 'Template',
|
|
126
235
|
value: 'template',
|
|
127
236
|
},
|
|
237
|
+
{
|
|
238
|
+
name: 'Interactive (Buttons)',
|
|
239
|
+
value: 'interactive',
|
|
240
|
+
},
|
|
128
241
|
],
|
|
129
242
|
default: 'text',
|
|
130
243
|
description: 'The type of message to send (WhatsApp)',
|
|
131
244
|
},
|
|
245
|
+
// Message Type - Instagram
|
|
132
246
|
{
|
|
133
247
|
displayName: 'Message Type',
|
|
134
248
|
name: 'messageType',
|
|
@@ -157,6 +271,44 @@ class KirimChat {
|
|
|
157
271
|
default: 'text',
|
|
158
272
|
description: 'The type of message to send (Instagram)',
|
|
159
273
|
},
|
|
274
|
+
// Message Type - Messenger
|
|
275
|
+
{
|
|
276
|
+
displayName: 'Message Type',
|
|
277
|
+
name: 'messageType',
|
|
278
|
+
type: 'options',
|
|
279
|
+
required: true,
|
|
280
|
+
displayOptions: {
|
|
281
|
+
show: {
|
|
282
|
+
operation: ['sendMessage'],
|
|
283
|
+
channel: ['messenger'],
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
options: [
|
|
287
|
+
{
|
|
288
|
+
name: 'Text',
|
|
289
|
+
value: 'text',
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
name: 'Image',
|
|
293
|
+
value: 'image',
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: 'Video',
|
|
297
|
+
value: 'video',
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: 'Audio',
|
|
301
|
+
value: 'audio',
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
name: 'File',
|
|
305
|
+
value: 'file',
|
|
306
|
+
},
|
|
307
|
+
],
|
|
308
|
+
default: 'text',
|
|
309
|
+
description: 'The type of message to send (Messenger)',
|
|
310
|
+
},
|
|
311
|
+
// Text Content
|
|
160
312
|
{
|
|
161
313
|
displayName: 'Message Content',
|
|
162
314
|
name: 'content',
|
|
@@ -174,19 +326,23 @@ class KirimChat {
|
|
|
174
326
|
rows: 4,
|
|
175
327
|
},
|
|
176
328
|
},
|
|
329
|
+
// Media URL (for all media types)
|
|
177
330
|
{
|
|
178
331
|
displayName: 'Media URL',
|
|
179
332
|
name: 'mediaUrl',
|
|
180
333
|
type: 'string',
|
|
334
|
+
required: true,
|
|
181
335
|
displayOptions: {
|
|
182
336
|
show: {
|
|
183
337
|
operation: ['sendMessage'],
|
|
184
|
-
messageType: ['image', 'document', 'audio', 'video', 'media_share'],
|
|
338
|
+
messageType: ['image', 'document', 'audio', 'video', 'media_share', 'file'],
|
|
185
339
|
},
|
|
186
340
|
},
|
|
187
341
|
default: '',
|
|
188
|
-
description: 'URL of the media file to send',
|
|
342
|
+
description: 'URL of the media file to send (must be publicly accessible)',
|
|
343
|
+
placeholder: 'https://example.com/image.jpg',
|
|
189
344
|
},
|
|
345
|
+
// Caption (for media messages)
|
|
190
346
|
{
|
|
191
347
|
displayName: 'Caption',
|
|
192
348
|
name: 'caption',
|
|
@@ -200,6 +356,7 @@ class KirimChat {
|
|
|
200
356
|
default: '',
|
|
201
357
|
description: 'Optional caption for media messages',
|
|
202
358
|
},
|
|
359
|
+
// Filename (for documents)
|
|
203
360
|
{
|
|
204
361
|
displayName: 'Filename',
|
|
205
362
|
name: 'filename',
|
|
@@ -207,14 +364,16 @@ class KirimChat {
|
|
|
207
364
|
displayOptions: {
|
|
208
365
|
show: {
|
|
209
366
|
operation: ['sendMessage'],
|
|
210
|
-
messageType: ['document'],
|
|
367
|
+
messageType: ['document', 'file'],
|
|
211
368
|
},
|
|
212
369
|
},
|
|
213
370
|
default: '',
|
|
214
|
-
description: 'Filename for document messages',
|
|
371
|
+
description: 'Filename for document/file messages',
|
|
215
372
|
placeholder: 'invoice.pdf',
|
|
216
373
|
},
|
|
217
|
-
//
|
|
374
|
+
// ============================================
|
|
375
|
+
// TEMPLATE FIELDS (WhatsApp only)
|
|
376
|
+
// ============================================
|
|
218
377
|
{
|
|
219
378
|
displayName: 'Template Name',
|
|
220
379
|
name: 'templateName',
|
|
@@ -258,7 +417,130 @@ class KirimChat {
|
|
|
258
417
|
default: '[]',
|
|
259
418
|
description: 'Template components as JSON array (for variables, buttons, etc.)',
|
|
260
419
|
},
|
|
261
|
-
//
|
|
420
|
+
// ============================================
|
|
421
|
+
// INTERACTIVE MESSAGE FIELDS (WhatsApp only)
|
|
422
|
+
// ============================================
|
|
423
|
+
{
|
|
424
|
+
displayName: 'Interactive Type',
|
|
425
|
+
name: 'interactiveType',
|
|
426
|
+
type: 'options',
|
|
427
|
+
required: true,
|
|
428
|
+
displayOptions: {
|
|
429
|
+
show: {
|
|
430
|
+
operation: ['sendMessage'],
|
|
431
|
+
messageType: ['interactive'],
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
options: [
|
|
435
|
+
{
|
|
436
|
+
name: 'CTA URL Button',
|
|
437
|
+
value: 'cta_url',
|
|
438
|
+
description: 'Call-to-action button that opens a URL',
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
name: 'Reply Buttons',
|
|
442
|
+
value: 'button',
|
|
443
|
+
description: 'Up to 3 reply buttons',
|
|
444
|
+
},
|
|
445
|
+
],
|
|
446
|
+
default: 'cta_url',
|
|
447
|
+
description: 'Type of interactive message',
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
displayName: 'Body Text',
|
|
451
|
+
name: 'interactiveBody',
|
|
452
|
+
type: 'string',
|
|
453
|
+
required: true,
|
|
454
|
+
displayOptions: {
|
|
455
|
+
show: {
|
|
456
|
+
operation: ['sendMessage'],
|
|
457
|
+
messageType: ['interactive'],
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
default: '',
|
|
461
|
+
description: 'Main body text of the interactive message (max 1024 characters)',
|
|
462
|
+
typeOptions: {
|
|
463
|
+
rows: 3,
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
displayName: 'Header Text',
|
|
468
|
+
name: 'interactiveHeader',
|
|
469
|
+
type: 'string',
|
|
470
|
+
displayOptions: {
|
|
471
|
+
show: {
|
|
472
|
+
operation: ['sendMessage'],
|
|
473
|
+
messageType: ['interactive'],
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
default: '',
|
|
477
|
+
description: 'Optional header text (max 60 characters)',
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
displayName: 'Footer Text',
|
|
481
|
+
name: 'interactiveFooter',
|
|
482
|
+
type: 'string',
|
|
483
|
+
displayOptions: {
|
|
484
|
+
show: {
|
|
485
|
+
operation: ['sendMessage'],
|
|
486
|
+
messageType: ['interactive'],
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
default: '',
|
|
490
|
+
description: 'Optional footer text (max 60 characters)',
|
|
491
|
+
},
|
|
492
|
+
// CTA URL specific fields
|
|
493
|
+
{
|
|
494
|
+
displayName: 'Button Text',
|
|
495
|
+
name: 'ctaButtonText',
|
|
496
|
+
type: 'string',
|
|
497
|
+
required: true,
|
|
498
|
+
displayOptions: {
|
|
499
|
+
show: {
|
|
500
|
+
operation: ['sendMessage'],
|
|
501
|
+
messageType: ['interactive'],
|
|
502
|
+
interactiveType: ['cta_url'],
|
|
503
|
+
},
|
|
504
|
+
},
|
|
505
|
+
default: '',
|
|
506
|
+
description: 'Text displayed on the button (max 20 characters)',
|
|
507
|
+
placeholder: 'Visit Website',
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
displayName: 'Button URL',
|
|
511
|
+
name: 'ctaButtonUrl',
|
|
512
|
+
type: 'string',
|
|
513
|
+
required: true,
|
|
514
|
+
displayOptions: {
|
|
515
|
+
show: {
|
|
516
|
+
operation: ['sendMessage'],
|
|
517
|
+
messageType: ['interactive'],
|
|
518
|
+
interactiveType: ['cta_url'],
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
default: '',
|
|
522
|
+
description: 'URL to open when button is clicked',
|
|
523
|
+
placeholder: 'https://example.com',
|
|
524
|
+
},
|
|
525
|
+
// Reply buttons specific fields
|
|
526
|
+
{
|
|
527
|
+
displayName: 'Buttons (JSON)',
|
|
528
|
+
name: 'replyButtons',
|
|
529
|
+
type: 'json',
|
|
530
|
+
required: true,
|
|
531
|
+
displayOptions: {
|
|
532
|
+
show: {
|
|
533
|
+
operation: ['sendMessage'],
|
|
534
|
+
messageType: ['interactive'],
|
|
535
|
+
interactiveType: ['button'],
|
|
536
|
+
},
|
|
537
|
+
},
|
|
538
|
+
default: '[{"id": "btn1", "title": "Yes"}, {"id": "btn2", "title": "No"}]',
|
|
539
|
+
description: 'Array of buttons (1-3). Each button needs "id" (max 256 chars) and "title" (max 20 chars)',
|
|
540
|
+
},
|
|
541
|
+
// ============================================
|
|
542
|
+
// MARK AS READ FIELDS
|
|
543
|
+
// ============================================
|
|
262
544
|
{
|
|
263
545
|
displayName: 'Message ID',
|
|
264
546
|
name: 'messageId',
|
|
@@ -273,32 +555,99 @@ class KirimChat {
|
|
|
273
555
|
description: 'The ID of the message to mark as read',
|
|
274
556
|
placeholder: 'msg_xyz789',
|
|
275
557
|
},
|
|
276
|
-
//
|
|
558
|
+
// ============================================
|
|
559
|
+
// SEND TYPING FIELDS
|
|
560
|
+
// ============================================
|
|
561
|
+
{
|
|
562
|
+
displayName: 'Customer Lookup',
|
|
563
|
+
name: 'typingCustomerLookup',
|
|
564
|
+
type: 'options',
|
|
565
|
+
required: true,
|
|
566
|
+
displayOptions: {
|
|
567
|
+
show: {
|
|
568
|
+
operation: ['sendTyping'],
|
|
569
|
+
},
|
|
570
|
+
},
|
|
571
|
+
options: [
|
|
572
|
+
{
|
|
573
|
+
name: 'Customer ID',
|
|
574
|
+
value: 'customer_id',
|
|
575
|
+
description: 'Lookup by KirimChat customer ID',
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
name: 'Phone Number',
|
|
579
|
+
value: 'phone_number',
|
|
580
|
+
description: 'Lookup by phone number',
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
name: 'Instagram Username',
|
|
584
|
+
value: 'instagram_username',
|
|
585
|
+
description: 'Lookup by Instagram username',
|
|
586
|
+
},
|
|
587
|
+
],
|
|
588
|
+
default: 'customer_id',
|
|
589
|
+
description: 'How to identify the customer',
|
|
590
|
+
},
|
|
277
591
|
{
|
|
278
592
|
displayName: 'Customer ID',
|
|
279
|
-
name: '
|
|
593
|
+
name: 'typingCustomerId',
|
|
280
594
|
type: 'string',
|
|
281
595
|
required: true,
|
|
282
596
|
displayOptions: {
|
|
283
597
|
show: {
|
|
284
598
|
operation: ['sendTyping'],
|
|
599
|
+
typingCustomerLookup: ['customer_id'],
|
|
285
600
|
},
|
|
286
601
|
},
|
|
287
602
|
default: '',
|
|
288
603
|
description: 'The ID of the customer to send typing indicator to',
|
|
289
604
|
placeholder: 'cust_abc123',
|
|
290
605
|
},
|
|
606
|
+
{
|
|
607
|
+
displayName: 'Phone Number',
|
|
608
|
+
name: 'typingPhoneNumber',
|
|
609
|
+
type: 'string',
|
|
610
|
+
required: true,
|
|
611
|
+
displayOptions: {
|
|
612
|
+
show: {
|
|
613
|
+
operation: ['sendTyping'],
|
|
614
|
+
typingCustomerLookup: ['phone_number'],
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
default: '',
|
|
618
|
+
description: 'The phone number of the customer',
|
|
619
|
+
placeholder: '+6281234567890',
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
displayName: 'Instagram Username',
|
|
623
|
+
name: 'typingInstagramUsername',
|
|
624
|
+
type: 'string',
|
|
625
|
+
required: true,
|
|
626
|
+
displayOptions: {
|
|
627
|
+
show: {
|
|
628
|
+
operation: ['sendTyping'],
|
|
629
|
+
typingCustomerLookup: ['instagram_username'],
|
|
630
|
+
},
|
|
631
|
+
},
|
|
632
|
+
default: '',
|
|
633
|
+
description: 'The Instagram username of the customer',
|
|
634
|
+
placeholder: 'username',
|
|
635
|
+
},
|
|
291
636
|
{
|
|
292
637
|
displayName: 'Channel',
|
|
293
|
-
name: '
|
|
638
|
+
name: 'typingChannel',
|
|
294
639
|
type: 'options',
|
|
295
|
-
required: true,
|
|
296
640
|
displayOptions: {
|
|
297
641
|
show: {
|
|
298
642
|
operation: ['sendTyping'],
|
|
299
643
|
},
|
|
300
644
|
},
|
|
301
645
|
options: [
|
|
646
|
+
{
|
|
647
|
+
name: 'Auto-detect',
|
|
648
|
+
value: '',
|
|
649
|
+
description: 'Automatically detect based on customer data',
|
|
650
|
+
},
|
|
302
651
|
{
|
|
303
652
|
name: 'WhatsApp',
|
|
304
653
|
value: 'whatsapp',
|
|
@@ -308,8 +657,8 @@ class KirimChat {
|
|
|
308
657
|
value: 'instagram',
|
|
309
658
|
},
|
|
310
659
|
],
|
|
311
|
-
default: '
|
|
312
|
-
description: 'The messaging channel to use',
|
|
660
|
+
default: '',
|
|
661
|
+
description: 'The messaging channel to use (leave empty for auto-detect)',
|
|
313
662
|
},
|
|
314
663
|
],
|
|
315
664
|
};
|
|
@@ -324,15 +673,27 @@ class KirimChat {
|
|
|
324
673
|
const operation = this.getNodeParameter('operation', i);
|
|
325
674
|
let responseData;
|
|
326
675
|
if (operation === 'sendMessage') {
|
|
327
|
-
//
|
|
328
|
-
|
|
676
|
+
// ============================================
|
|
677
|
+
// SEND MESSAGE OPERATION
|
|
678
|
+
// ============================================
|
|
679
|
+
const customerLookup = this.getNodeParameter('customerLookup', i);
|
|
329
680
|
const channel = this.getNodeParameter('channel', i);
|
|
330
681
|
const messageType = this.getNodeParameter('messageType', i);
|
|
331
682
|
const body = {
|
|
332
|
-
customer_id: customerId,
|
|
333
683
|
channel,
|
|
334
684
|
message_type: messageType,
|
|
335
685
|
};
|
|
686
|
+
// Set customer identifier based on lookup method
|
|
687
|
+
if (customerLookup === 'customer_id') {
|
|
688
|
+
body.customer_id = this.getNodeParameter('customerId', i);
|
|
689
|
+
}
|
|
690
|
+
else if (customerLookup === 'phone_number') {
|
|
691
|
+
body.phone_number = this.getNodeParameter('phoneNumber', i);
|
|
692
|
+
}
|
|
693
|
+
else if (customerLookup === 'instagram_username') {
|
|
694
|
+
body.instagram_username = this.getNodeParameter('instagramUsername', i);
|
|
695
|
+
}
|
|
696
|
+
// Handle different message types
|
|
336
697
|
if (messageType === 'text') {
|
|
337
698
|
body.content = this.getNodeParameter('content', i);
|
|
338
699
|
}
|
|
@@ -341,12 +702,16 @@ class KirimChat {
|
|
|
341
702
|
const templateName = this.getNodeParameter('templateName', i);
|
|
342
703
|
const templateLanguage = this.getNodeParameter('templateLanguage', i);
|
|
343
704
|
const templateComponentsJson = this.getNodeParameter('templateComponents', i, '[]');
|
|
344
|
-
let templateComponents
|
|
705
|
+
let templateComponents;
|
|
345
706
|
try {
|
|
346
707
|
templateComponents = JSON.parse(templateComponentsJson);
|
|
347
708
|
}
|
|
348
709
|
catch (error) {
|
|
349
|
-
throw new
|
|
710
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid JSON in Template Components: ${error instanceof Error ? error.message : 'Parse failed'}`, { itemIndex: i });
|
|
711
|
+
}
|
|
712
|
+
// Validate template components structure
|
|
713
|
+
if (!validateTemplateComponents(templateComponents)) {
|
|
714
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Template Components must be a JSON array of objects. Example: [{"type": "body", "parameters": [...]}]', { itemIndex: i });
|
|
350
715
|
}
|
|
351
716
|
body.template = {
|
|
352
717
|
name: templateName,
|
|
@@ -354,15 +719,90 @@ class KirimChat {
|
|
|
354
719
|
components: templateComponents,
|
|
355
720
|
};
|
|
356
721
|
}
|
|
722
|
+
else if (messageType === 'interactive') {
|
|
723
|
+
// WhatsApp interactive message
|
|
724
|
+
const interactiveType = this.getNodeParameter('interactiveType', i);
|
|
725
|
+
const interactiveBody = this.getNodeParameter('interactiveBody', i);
|
|
726
|
+
const interactiveHeader = this.getNodeParameter('interactiveHeader', i, '');
|
|
727
|
+
const interactiveFooter = this.getNodeParameter('interactiveFooter', i, '');
|
|
728
|
+
const interactive = {
|
|
729
|
+
type: interactiveType,
|
|
730
|
+
body: { text: interactiveBody },
|
|
731
|
+
};
|
|
732
|
+
// Add optional header
|
|
733
|
+
if (interactiveHeader) {
|
|
734
|
+
interactive.header = {
|
|
735
|
+
type: 'text',
|
|
736
|
+
text: interactiveHeader,
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
// Add optional footer
|
|
740
|
+
if (interactiveFooter) {
|
|
741
|
+
interactive.footer = { text: interactiveFooter };
|
|
742
|
+
}
|
|
743
|
+
// Add action based on type
|
|
744
|
+
if (interactiveType === 'cta_url') {
|
|
745
|
+
const ctaButtonText = this.getNodeParameter('ctaButtonText', i);
|
|
746
|
+
const ctaButtonUrl = this.getNodeParameter('ctaButtonUrl', i);
|
|
747
|
+
if (!isValidUrl(ctaButtonUrl)) {
|
|
748
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid Button URL format: "${ctaButtonUrl}". URL must start with http:// or https://`, { itemIndex: i });
|
|
749
|
+
}
|
|
750
|
+
interactive.action = {
|
|
751
|
+
name: 'cta_url',
|
|
752
|
+
parameters: {
|
|
753
|
+
display_text: ctaButtonText,
|
|
754
|
+
url: ctaButtonUrl,
|
|
755
|
+
},
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
else if (interactiveType === 'button') {
|
|
759
|
+
const replyButtonsJson = this.getNodeParameter('replyButtons', i);
|
|
760
|
+
let replyButtons;
|
|
761
|
+
try {
|
|
762
|
+
replyButtons = JSON.parse(replyButtonsJson);
|
|
763
|
+
}
|
|
764
|
+
catch (error) {
|
|
765
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid JSON in Reply Buttons: ${error instanceof Error ? error.message : 'Parse failed'}`, { itemIndex: i });
|
|
766
|
+
}
|
|
767
|
+
if (!Array.isArray(replyButtons) || replyButtons.length === 0 || replyButtons.length > 3) {
|
|
768
|
+
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 });
|
|
769
|
+
}
|
|
770
|
+
// Transform to n8n format
|
|
771
|
+
const formattedButtons = replyButtons.map((btn) => ({
|
|
772
|
+
type: 'reply',
|
|
773
|
+
reply: {
|
|
774
|
+
id: btn.id || '',
|
|
775
|
+
title: btn.title || '',
|
|
776
|
+
},
|
|
777
|
+
}));
|
|
778
|
+
interactive.action = {
|
|
779
|
+
buttons: formattedButtons,
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
if (!validateInteractiveMessage(interactive)) {
|
|
783
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid interactive message structure', { itemIndex: i });
|
|
784
|
+
}
|
|
785
|
+
body.interactive = interactive;
|
|
786
|
+
}
|
|
357
787
|
else {
|
|
358
|
-
// Media messages
|
|
359
|
-
|
|
788
|
+
// Media messages (image, document, audio, video, media_share, file)
|
|
789
|
+
const mediaUrl = this.getNodeParameter('mediaUrl', i);
|
|
790
|
+
// Validate media URL is provided
|
|
791
|
+
if (!mediaUrl) {
|
|
792
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Media URL is required for ${messageType} messages`, { itemIndex: i });
|
|
793
|
+
}
|
|
794
|
+
// Validate media URL format
|
|
795
|
+
if (!isValidUrl(mediaUrl)) {
|
|
796
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid Media URL format: "${mediaUrl}". URL must start with http:// or https://`, { itemIndex: i });
|
|
797
|
+
}
|
|
798
|
+
body.media_url = mediaUrl;
|
|
799
|
+
// Add caption if provided
|
|
360
800
|
const caption = this.getNodeParameter('caption', i, '');
|
|
361
801
|
if (caption) {
|
|
362
802
|
body.caption = caption;
|
|
363
803
|
}
|
|
364
|
-
//
|
|
365
|
-
if (messageType === 'document') {
|
|
804
|
+
// Add filename for document/file types
|
|
805
|
+
if (messageType === 'document' || messageType === 'file') {
|
|
366
806
|
const filename = this.getNodeParameter('filename', i, '');
|
|
367
807
|
if (filename) {
|
|
368
808
|
body.filename = filename;
|
|
@@ -377,7 +817,9 @@ class KirimChat {
|
|
|
377
817
|
});
|
|
378
818
|
}
|
|
379
819
|
else if (operation === 'markAsRead') {
|
|
380
|
-
//
|
|
820
|
+
// ============================================
|
|
821
|
+
// MARK AS READ OPERATION
|
|
822
|
+
// ============================================
|
|
381
823
|
const messageId = this.getNodeParameter('messageId', i);
|
|
382
824
|
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'kirimChatApi', {
|
|
383
825
|
method: 'POST',
|
|
@@ -386,13 +828,30 @@ class KirimChat {
|
|
|
386
828
|
});
|
|
387
829
|
}
|
|
388
830
|
else if (operation === 'sendTyping') {
|
|
389
|
-
//
|
|
390
|
-
|
|
391
|
-
|
|
831
|
+
// ============================================
|
|
832
|
+
// SEND TYPING INDICATOR OPERATION
|
|
833
|
+
// ============================================
|
|
834
|
+
const typingLookup = this.getNodeParameter('typingCustomerLookup', i);
|
|
835
|
+
const typingChannel = this.getNodeParameter('typingChannel', i, '');
|
|
836
|
+
// Get customer identifier based on lookup method
|
|
837
|
+
let customerIdentifier;
|
|
838
|
+
if (typingLookup === 'customer_id') {
|
|
839
|
+
customerIdentifier = this.getNodeParameter('typingCustomerId', i);
|
|
840
|
+
}
|
|
841
|
+
else if (typingLookup === 'phone_number') {
|
|
842
|
+
customerIdentifier = this.getNodeParameter('typingPhoneNumber', i);
|
|
843
|
+
}
|
|
844
|
+
else {
|
|
845
|
+
customerIdentifier = this.getNodeParameter('typingInstagramUsername', i);
|
|
846
|
+
}
|
|
847
|
+
const typingBody = {};
|
|
848
|
+
if (typingChannel) {
|
|
849
|
+
typingBody.channel = typingChannel;
|
|
850
|
+
}
|
|
392
851
|
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'kirimChatApi', {
|
|
393
852
|
method: 'POST',
|
|
394
|
-
url: `${baseUrl}/conversations/${
|
|
395
|
-
body:
|
|
853
|
+
url: `${baseUrl}/conversations/${customerIdentifier}/typing`,
|
|
854
|
+
body: typingBody,
|
|
396
855
|
json: true,
|
|
397
856
|
});
|
|
398
857
|
}
|
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.1.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": {
|
|
@@ -53,4 +56,4 @@
|
|
|
53
56
|
"peerDependencies": {
|
|
54
57
|
"n8n-workflow": "*"
|
|
55
58
|
}
|
|
56
|
-
}
|
|
59
|
+
}
|