@kichat/n8n-nodes-kirimchat 1.0.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 +145 -0
- package/dist/credentials/KirimChatApi.credentials.d.ts +9 -0
- package/dist/credentials/KirimChatApi.credentials.js +46 -0
- package/dist/nodes/KirimChat/KirimChat.node.d.ts +5 -0
- package/dist/nodes/KirimChat/KirimChat.node.js +424 -0
- package/dist/nodes/KirimChat/kirimchat.svg +6 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
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 Instagram DM.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Send Message** - Send text, image, document, audio, video, or template messages via WhatsApp or Instagram
|
|
8
|
+
- **Mark as Read** - Mark messages as read and send read receipts
|
|
9
|
+
- **Send Typing Indicator** - Show typing indicator to customers
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
### Community Nodes (Recommended)
|
|
14
|
+
|
|
15
|
+
1. Go to **Settings > Community Nodes**
|
|
16
|
+
2. Select **Install**
|
|
17
|
+
3. Enter `n8n-nodes-kirimchat` and confirm
|
|
18
|
+
|
|
19
|
+
### Manual Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install n8n-nodes-kirimchat
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Credentials
|
|
26
|
+
|
|
27
|
+
You need a KirimChat API key to use this node:
|
|
28
|
+
|
|
29
|
+
1. Log in to your KirimChat dashboard
|
|
30
|
+
2. Go to **Settings > Developers > API Keys**
|
|
31
|
+
3. Click **Create API Key** and copy the key (shown only once)
|
|
32
|
+
4. In n8n, create new credentials for **KirimChat API**
|
|
33
|
+
5. Paste your API key (starts with `kc_live_`)
|
|
34
|
+
|
|
35
|
+
## Operations
|
|
36
|
+
|
|
37
|
+
### Send Message
|
|
38
|
+
|
|
39
|
+
Send a message to a customer via WhatsApp or Instagram.
|
|
40
|
+
|
|
41
|
+
| Parameter | Description |
|
|
42
|
+
|-----------|-------------|
|
|
43
|
+
| Customer ID | The ID of the customer (e.g., `cust_abc123`) |
|
|
44
|
+
| Channel | `whatsapp` or `instagram` |
|
|
45
|
+
| Message Type | `text`, `image`, `document`, `audio`, `video`, `template` (WhatsApp) or `text`, `image`, `media_share` (Instagram) |
|
|
46
|
+
| Content | Text content for text messages |
|
|
47
|
+
| Media URL | URL of media file for media messages |
|
|
48
|
+
| Caption | Optional caption for media messages |
|
|
49
|
+
|
|
50
|
+
**Example Response:**
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"success": true,
|
|
54
|
+
"data": {
|
|
55
|
+
"message_id": "msg_xyz789",
|
|
56
|
+
"status": "sent",
|
|
57
|
+
"channel": "whatsapp",
|
|
58
|
+
"timestamp": "2025-11-26T10:31:00.000Z"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Mark as Read
|
|
64
|
+
|
|
65
|
+
Mark a message as read and send read receipt to the customer.
|
|
66
|
+
|
|
67
|
+
| Parameter | Description |
|
|
68
|
+
|-----------|-------------|
|
|
69
|
+
| Message ID | The ID of the message to mark as read (e.g., `msg_xyz789`) |
|
|
70
|
+
|
|
71
|
+
### Send Typing Indicator
|
|
72
|
+
|
|
73
|
+
Show typing indicator to a customer before sending a message.
|
|
74
|
+
|
|
75
|
+
| Parameter | Description |
|
|
76
|
+
|-----------|-------------|
|
|
77
|
+
| Customer ID | The ID of the customer |
|
|
78
|
+
| Channel | `whatsapp` or `instagram` |
|
|
79
|
+
|
|
80
|
+
> **Note:** Rate limited to 1 request per customer per 3 seconds.
|
|
81
|
+
|
|
82
|
+
## Webhook Trigger
|
|
83
|
+
|
|
84
|
+
KirimChat supports outbound webhooks for real-time event notifications. Configure webhooks in your KirimChat dashboard under **Settings > Developers > Webhooks**.
|
|
85
|
+
|
|
86
|
+
### Supported Events
|
|
87
|
+
|
|
88
|
+
- `message.received` - New message from customer
|
|
89
|
+
- `message.sent` - Message sent to customer
|
|
90
|
+
- `message.delivered` - Message delivered
|
|
91
|
+
- `message.read` - Message read by customer
|
|
92
|
+
- `message.failed` - Message delivery failed
|
|
93
|
+
|
|
94
|
+
### Webhook Payload Example
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"event_type": "message.received",
|
|
99
|
+
"event_id": "evt_abc123",
|
|
100
|
+
"timestamp": "2025-11-26T10:30:00.000Z",
|
|
101
|
+
"data": {
|
|
102
|
+
"message_id": "msg_xyz789",
|
|
103
|
+
"customer_id": "cust_123",
|
|
104
|
+
"customer_phone": "+6281234567890",
|
|
105
|
+
"direction": "inbound",
|
|
106
|
+
"message_type": "text",
|
|
107
|
+
"content": "Hello!",
|
|
108
|
+
"channel": "whatsapp"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Using with n8n Webhook Node
|
|
114
|
+
|
|
115
|
+
1. Create a new workflow with **Webhook** trigger node
|
|
116
|
+
2. Copy the webhook URL
|
|
117
|
+
3. In KirimChat, create a webhook endpoint with this URL
|
|
118
|
+
4. Select the events you want to receive
|
|
119
|
+
5. Connect the webhook to your KirimChat node for automated responses
|
|
120
|
+
|
|
121
|
+
## Rate Limits
|
|
122
|
+
|
|
123
|
+
- **Global:** 100 requests per minute per API key
|
|
124
|
+
- **Send Message:** 60 messages per minute per API key
|
|
125
|
+
- **Typing Indicator:** 1 request per customer per 3 seconds
|
|
126
|
+
|
|
127
|
+
## Error Handling
|
|
128
|
+
|
|
129
|
+
The node returns standard error responses:
|
|
130
|
+
|
|
131
|
+
| Code | Description |
|
|
132
|
+
|------|-------------|
|
|
133
|
+
| 401 | Invalid or expired API key |
|
|
134
|
+
| 404 | Resource not found |
|
|
135
|
+
| 400 | Invalid request or messaging window closed |
|
|
136
|
+
| 429 | Rate limit exceeded |
|
|
137
|
+
|
|
138
|
+
## Resources
|
|
139
|
+
|
|
140
|
+
- [KirimChat Documentation](https://kirim.chat/developers)
|
|
141
|
+
- [n8n Community Nodes](https://docs.n8n.io/integrations/community-nodes/)
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
export declare class KirimChatApi implements ICredentialType {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
documentationUrl: string;
|
|
6
|
+
properties: INodeProperties[];
|
|
7
|
+
authenticate: IAuthenticateGeneric;
|
|
8
|
+
test: ICredentialTestRequest;
|
|
9
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KirimChatApi = void 0;
|
|
4
|
+
class KirimChatApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'kirimChatApi';
|
|
7
|
+
this.displayName = 'KirimChat API';
|
|
8
|
+
this.documentationUrl = 'https://kirim.chat/developers';
|
|
9
|
+
this.properties = [
|
|
10
|
+
{
|
|
11
|
+
displayName: 'API Key',
|
|
12
|
+
name: 'apiKey',
|
|
13
|
+
type: 'string',
|
|
14
|
+
typeOptions: { password: true },
|
|
15
|
+
default: '',
|
|
16
|
+
required: true,
|
|
17
|
+
description: 'Your KirimChat API key (starts with kc_live_)',
|
|
18
|
+
placeholder: 'kc_live_your_api_key_here',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
displayName: 'API Base URL',
|
|
22
|
+
name: 'baseUrl',
|
|
23
|
+
type: 'string',
|
|
24
|
+
default: 'https://api.paijoe.com/api/v1/public',
|
|
25
|
+
required: true,
|
|
26
|
+
description: 'The base URL for the KirimChat API',
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
this.authenticate = {
|
|
30
|
+
type: 'generic',
|
|
31
|
+
properties: {
|
|
32
|
+
headers: {
|
|
33
|
+
Authorization: '=Bearer {{$credentials.apiKey}}',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
this.test = {
|
|
38
|
+
request: {
|
|
39
|
+
baseURL: '={{$credentials.baseUrl}}',
|
|
40
|
+
url: '/health',
|
|
41
|
+
method: 'GET',
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.KirimChatApi = KirimChatApi;
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KirimChat = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
class KirimChat {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.description = {
|
|
8
|
+
displayName: 'KirimChat',
|
|
9
|
+
name: 'kirimChat',
|
|
10
|
+
icon: 'file:kirimchat.svg',
|
|
11
|
+
group: ['transform'],
|
|
12
|
+
version: 1,
|
|
13
|
+
subtitle: '={{$parameter["operation"]}}',
|
|
14
|
+
description: 'Send WhatsApp & Instagram messages, mark as read, and send typing indicators',
|
|
15
|
+
defaults: {
|
|
16
|
+
name: 'KirimChat',
|
|
17
|
+
},
|
|
18
|
+
inputs: ['main'],
|
|
19
|
+
outputs: ['main'],
|
|
20
|
+
credentials: [
|
|
21
|
+
{
|
|
22
|
+
name: 'kirimChatApi',
|
|
23
|
+
required: true,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
properties: [
|
|
27
|
+
{
|
|
28
|
+
displayName: 'Operation',
|
|
29
|
+
name: 'operation',
|
|
30
|
+
type: 'options',
|
|
31
|
+
noDataExpression: true,
|
|
32
|
+
options: [
|
|
33
|
+
{
|
|
34
|
+
name: 'Send Message',
|
|
35
|
+
value: 'sendMessage',
|
|
36
|
+
description: 'Send a message to a customer via WhatsApp or Instagram',
|
|
37
|
+
action: 'Send a message',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'Mark as Read',
|
|
41
|
+
value: 'markAsRead',
|
|
42
|
+
description: 'Mark a message as read',
|
|
43
|
+
action: 'Mark a message as read',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'Send Typing Indicator',
|
|
47
|
+
value: 'sendTyping',
|
|
48
|
+
description: 'Send typing indicator to show you are typing',
|
|
49
|
+
action: 'Send typing indicator',
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
default: 'sendMessage',
|
|
53
|
+
},
|
|
54
|
+
// Send Message Fields
|
|
55
|
+
{
|
|
56
|
+
displayName: 'Customer ID',
|
|
57
|
+
name: 'customerId',
|
|
58
|
+
type: 'string',
|
|
59
|
+
required: true,
|
|
60
|
+
displayOptions: {
|
|
61
|
+
show: {
|
|
62
|
+
operation: ['sendMessage'],
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
default: '',
|
|
66
|
+
description: 'The ID of the customer to send the message to',
|
|
67
|
+
placeholder: 'cust_abc123',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
displayName: 'Channel',
|
|
71
|
+
name: 'channel',
|
|
72
|
+
type: 'options',
|
|
73
|
+
required: true,
|
|
74
|
+
displayOptions: {
|
|
75
|
+
show: {
|
|
76
|
+
operation: ['sendMessage'],
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
options: [
|
|
80
|
+
{
|
|
81
|
+
name: 'WhatsApp',
|
|
82
|
+
value: 'whatsapp',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: 'Instagram',
|
|
86
|
+
value: 'instagram',
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
default: 'whatsapp',
|
|
90
|
+
description: 'The messaging channel to use',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
displayName: 'Message Type',
|
|
94
|
+
name: 'messageType',
|
|
95
|
+
type: 'options',
|
|
96
|
+
required: true,
|
|
97
|
+
displayOptions: {
|
|
98
|
+
show: {
|
|
99
|
+
operation: ['sendMessage'],
|
|
100
|
+
channel: ['whatsapp'],
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
options: [
|
|
104
|
+
{
|
|
105
|
+
name: 'Text',
|
|
106
|
+
value: 'text',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'Image',
|
|
110
|
+
value: 'image',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'Document',
|
|
114
|
+
value: 'document',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'Audio',
|
|
118
|
+
value: 'audio',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'Video',
|
|
122
|
+
value: 'video',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'Template',
|
|
126
|
+
value: 'template',
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
default: 'text',
|
|
130
|
+
description: 'The type of message to send (WhatsApp)',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
displayName: 'Message Type',
|
|
134
|
+
name: 'messageType',
|
|
135
|
+
type: 'options',
|
|
136
|
+
required: true,
|
|
137
|
+
displayOptions: {
|
|
138
|
+
show: {
|
|
139
|
+
operation: ['sendMessage'],
|
|
140
|
+
channel: ['instagram'],
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
options: [
|
|
144
|
+
{
|
|
145
|
+
name: 'Text',
|
|
146
|
+
value: 'text',
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'Image',
|
|
150
|
+
value: 'image',
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: 'Media Share',
|
|
154
|
+
value: 'media_share',
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
default: 'text',
|
|
158
|
+
description: 'The type of message to send (Instagram)',
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
displayName: 'Message Content',
|
|
162
|
+
name: 'content',
|
|
163
|
+
type: 'string',
|
|
164
|
+
required: true,
|
|
165
|
+
displayOptions: {
|
|
166
|
+
show: {
|
|
167
|
+
operation: ['sendMessage'],
|
|
168
|
+
messageType: ['text'],
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
default: '',
|
|
172
|
+
description: 'The text content of the message',
|
|
173
|
+
typeOptions: {
|
|
174
|
+
rows: 4,
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
displayName: 'Media URL',
|
|
179
|
+
name: 'mediaUrl',
|
|
180
|
+
type: 'string',
|
|
181
|
+
displayOptions: {
|
|
182
|
+
show: {
|
|
183
|
+
operation: ['sendMessage'],
|
|
184
|
+
messageType: ['image', 'document', 'audio', 'video', 'media_share'],
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
default: '',
|
|
188
|
+
description: 'URL of the media file to send',
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
displayName: 'Caption',
|
|
192
|
+
name: 'caption',
|
|
193
|
+
type: 'string',
|
|
194
|
+
displayOptions: {
|
|
195
|
+
show: {
|
|
196
|
+
operation: ['sendMessage'],
|
|
197
|
+
messageType: ['image', 'document', 'video'],
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
default: '',
|
|
201
|
+
description: 'Optional caption for media messages',
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
displayName: 'Filename',
|
|
205
|
+
name: 'filename',
|
|
206
|
+
type: 'string',
|
|
207
|
+
displayOptions: {
|
|
208
|
+
show: {
|
|
209
|
+
operation: ['sendMessage'],
|
|
210
|
+
messageType: ['document'],
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
default: '',
|
|
214
|
+
description: 'Filename for document messages',
|
|
215
|
+
placeholder: 'invoice.pdf',
|
|
216
|
+
},
|
|
217
|
+
// Template fields (WhatsApp only)
|
|
218
|
+
{
|
|
219
|
+
displayName: 'Template Name',
|
|
220
|
+
name: 'templateName',
|
|
221
|
+
type: 'string',
|
|
222
|
+
required: true,
|
|
223
|
+
displayOptions: {
|
|
224
|
+
show: {
|
|
225
|
+
operation: ['sendMessage'],
|
|
226
|
+
messageType: ['template'],
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
default: '',
|
|
230
|
+
description: 'Name of the WhatsApp template to send',
|
|
231
|
+
placeholder: 'hello_world',
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
displayName: 'Template Language',
|
|
235
|
+
name: 'templateLanguage',
|
|
236
|
+
type: 'string',
|
|
237
|
+
required: true,
|
|
238
|
+
displayOptions: {
|
|
239
|
+
show: {
|
|
240
|
+
operation: ['sendMessage'],
|
|
241
|
+
messageType: ['template'],
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
default: 'en',
|
|
245
|
+
description: 'Language code for the template',
|
|
246
|
+
placeholder: 'en',
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
displayName: 'Template Components (JSON)',
|
|
250
|
+
name: 'templateComponents',
|
|
251
|
+
type: 'json',
|
|
252
|
+
displayOptions: {
|
|
253
|
+
show: {
|
|
254
|
+
operation: ['sendMessage'],
|
|
255
|
+
messageType: ['template'],
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
default: '[]',
|
|
259
|
+
description: 'Template components as JSON array (for variables, buttons, etc.)',
|
|
260
|
+
},
|
|
261
|
+
// Mark as Read Fields
|
|
262
|
+
{
|
|
263
|
+
displayName: 'Message ID',
|
|
264
|
+
name: 'messageId',
|
|
265
|
+
type: 'string',
|
|
266
|
+
required: true,
|
|
267
|
+
displayOptions: {
|
|
268
|
+
show: {
|
|
269
|
+
operation: ['markAsRead'],
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
default: '',
|
|
273
|
+
description: 'The ID of the message to mark as read',
|
|
274
|
+
placeholder: 'msg_xyz789',
|
|
275
|
+
},
|
|
276
|
+
// Send Typing Fields
|
|
277
|
+
{
|
|
278
|
+
displayName: 'Customer ID',
|
|
279
|
+
name: 'customerId',
|
|
280
|
+
type: 'string',
|
|
281
|
+
required: true,
|
|
282
|
+
displayOptions: {
|
|
283
|
+
show: {
|
|
284
|
+
operation: ['sendTyping'],
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
default: '',
|
|
288
|
+
description: 'The ID of the customer to send typing indicator to',
|
|
289
|
+
placeholder: 'cust_abc123',
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
displayName: 'Channel',
|
|
293
|
+
name: 'channel',
|
|
294
|
+
type: 'options',
|
|
295
|
+
required: true,
|
|
296
|
+
displayOptions: {
|
|
297
|
+
show: {
|
|
298
|
+
operation: ['sendTyping'],
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
options: [
|
|
302
|
+
{
|
|
303
|
+
name: 'WhatsApp',
|
|
304
|
+
value: 'whatsapp',
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
name: 'Instagram',
|
|
308
|
+
value: 'instagram',
|
|
309
|
+
},
|
|
310
|
+
],
|
|
311
|
+
default: 'whatsapp',
|
|
312
|
+
description: 'The messaging channel to use',
|
|
313
|
+
},
|
|
314
|
+
],
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
async execute() {
|
|
318
|
+
const items = this.getInputData();
|
|
319
|
+
const returnData = [];
|
|
320
|
+
const credentials = await this.getCredentials('kirimChatApi');
|
|
321
|
+
const baseUrl = credentials.baseUrl;
|
|
322
|
+
for (let i = 0; i < items.length; i++) {
|
|
323
|
+
try {
|
|
324
|
+
const operation = this.getNodeParameter('operation', i);
|
|
325
|
+
let responseData;
|
|
326
|
+
if (operation === 'sendMessage') {
|
|
327
|
+
// Send Message Operation
|
|
328
|
+
const customerId = this.getNodeParameter('customerId', i);
|
|
329
|
+
const channel = this.getNodeParameter('channel', i);
|
|
330
|
+
const messageType = this.getNodeParameter('messageType', i);
|
|
331
|
+
const body = {
|
|
332
|
+
customer_id: customerId,
|
|
333
|
+
channel,
|
|
334
|
+
message_type: messageType,
|
|
335
|
+
};
|
|
336
|
+
if (messageType === 'text') {
|
|
337
|
+
body.content = this.getNodeParameter('content', i);
|
|
338
|
+
}
|
|
339
|
+
else if (messageType === 'template') {
|
|
340
|
+
// WhatsApp template message
|
|
341
|
+
const templateName = this.getNodeParameter('templateName', i);
|
|
342
|
+
const templateLanguage = this.getNodeParameter('templateLanguage', i);
|
|
343
|
+
const templateComponentsJson = this.getNodeParameter('templateComponents', i, '[]');
|
|
344
|
+
let templateComponents = [];
|
|
345
|
+
try {
|
|
346
|
+
templateComponents = JSON.parse(templateComponentsJson);
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
// Keep empty array if invalid JSON
|
|
350
|
+
}
|
|
351
|
+
body.template = {
|
|
352
|
+
name: templateName,
|
|
353
|
+
language: { code: templateLanguage },
|
|
354
|
+
components: templateComponents,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
// Media messages
|
|
359
|
+
body.media_url = this.getNodeParameter('mediaUrl', i, '');
|
|
360
|
+
const caption = this.getNodeParameter('caption', i, '');
|
|
361
|
+
if (caption) {
|
|
362
|
+
body.caption = caption;
|
|
363
|
+
}
|
|
364
|
+
// Document filename
|
|
365
|
+
if (messageType === 'document') {
|
|
366
|
+
const filename = this.getNodeParameter('filename', i, '');
|
|
367
|
+
if (filename) {
|
|
368
|
+
body.filename = filename;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'kirimChatApi', {
|
|
373
|
+
method: 'POST',
|
|
374
|
+
url: `${baseUrl}/messages/send`,
|
|
375
|
+
body,
|
|
376
|
+
json: true,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
else if (operation === 'markAsRead') {
|
|
380
|
+
// Mark as Read Operation
|
|
381
|
+
const messageId = this.getNodeParameter('messageId', i);
|
|
382
|
+
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'kirimChatApi', {
|
|
383
|
+
method: 'POST',
|
|
384
|
+
url: `${baseUrl}/messages/${messageId}/read`,
|
|
385
|
+
json: true,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
else if (operation === 'sendTyping') {
|
|
389
|
+
// Send Typing Indicator Operation
|
|
390
|
+
const customerId = this.getNodeParameter('customerId', i);
|
|
391
|
+
const channel = this.getNodeParameter('channel', i);
|
|
392
|
+
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'kirimChatApi', {
|
|
393
|
+
method: 'POST',
|
|
394
|
+
url: `${baseUrl}/conversations/${customerId}/typing`,
|
|
395
|
+
body: { channel },
|
|
396
|
+
json: true,
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The operation "${operation}" is not supported!`);
|
|
401
|
+
}
|
|
402
|
+
const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
|
|
403
|
+
returnData.push(...executionData);
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
if (this.continueOnFail()) {
|
|
407
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
408
|
+
returnData.push({
|
|
409
|
+
json: {
|
|
410
|
+
error: errorMessage,
|
|
411
|
+
},
|
|
412
|
+
pairedItem: {
|
|
413
|
+
item: i,
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
throw error;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return [returnData];
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
exports.KirimChat = KirimChat;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg width="60" height="60" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<!-- Chat Bubble - White background with Black border -->
|
|
3
|
+
<path d="M3,9 Q3,3 9,3 H51 Q57,3 57,9 V42 Q57,48 51,48 H18 L3,57 V9 Z" fill="white" stroke="black" stroke-width="3"/>
|
|
4
|
+
<!-- Text - Black color -->
|
|
5
|
+
<text x="30" y="30" font-family="Arial, sans-serif" font-size="24" font-weight="900" fill="black" text-anchor="middle" dominant-baseline="middle">KC</text>
|
|
6
|
+
</svg>
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kichat/n8n-nodes-kirimchat",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "n8n community node for KirimChat - Send WhatsApp & Instagram messages, mark as read, and send typing indicators",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"n8n-community-node-package",
|
|
7
|
+
"n8n",
|
|
8
|
+
"kirimchat",
|
|
9
|
+
"whatsapp",
|
|
10
|
+
"instagram",
|
|
11
|
+
"messaging",
|
|
12
|
+
"chat"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"homepage": "https://kirim.chat",
|
|
16
|
+
"author": {
|
|
17
|
+
"name": "KirimChat",
|
|
18
|
+
"email": "support@kirim.chat"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/kirimchat/n8n-nodes-kirimchat.git"
|
|
23
|
+
},
|
|
24
|
+
"main": "dist/nodes/KirimChat/KirimChat.node.js",
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc && npm run copy-icons",
|
|
27
|
+
"copy-icons": "node -e \"require('fs').cpSync('nodes/KirimChat/kirimchat.svg', 'dist/nodes/KirimChat/kirimchat.svg')\"",
|
|
28
|
+
"dev": "tsc --watch",
|
|
29
|
+
"format": "prettier nodes credentials --write",
|
|
30
|
+
"lint": "eslint nodes credentials package.json",
|
|
31
|
+
"prepublishOnly": "npm run build"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist"
|
|
35
|
+
],
|
|
36
|
+
"n8n": {
|
|
37
|
+
"n8nNodesApiVersion": 1,
|
|
38
|
+
"credentials": [
|
|
39
|
+
"dist/credentials/KirimChatApi.credentials.js"
|
|
40
|
+
],
|
|
41
|
+
"nodes": [
|
|
42
|
+
"dist/nodes/KirimChat/KirimChat.node.js"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@typescript-eslint/parser": "^7.0.0",
|
|
47
|
+
"copyfiles": "^2.4.1",
|
|
48
|
+
"eslint": "^8.0.0",
|
|
49
|
+
"n8n-workflow": "^1.0.0",
|
|
50
|
+
"prettier": "^3.0.0",
|
|
51
|
+
"typescript": "^5.0.0"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"n8n-workflow": "*"
|
|
55
|
+
}
|
|
56
|
+
}
|