n8n-nodes-chatflow 0.4.1 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -27
- package/dist/credentials/ChatflowApi.credentials.js +44 -27
- package/dist/index.js +7 -4
- package/dist/nodes/ChatflowMessage.node.js +244 -107
- package/dist/nodes/ChatflowTrigger.node.js +270 -0
- package/dist/nodes/black.svg +10 -0
- package/dist/nodes/chatflow.png +0 -0
- package/dist/nodes/chatflow.svg +18 -0
- package/dist/nodes/white.svg +10 -0
- package/package.json +16 -15
- package/credentials/ChatflowApi.credentials.js +0 -29
- package/index.js +0 -4
- package/nodes/ChatflowMessage.node.js +0 -122
- package/nodes/chatflow.png +0 -0
package/README.md
CHANGED
|
@@ -1,43 +1,61 @@
|
|
|
1
1
|
# n8n-nodes-chatflow
|
|
2
2
|
|
|
3
|
-
n8n
|
|
3
|
+
Community n8n nodes for [Chatflow](https://app.chatflow.kz) — send and receive WhatsApp & Telegram messages.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Nodes
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
### Chatflow Message
|
|
8
|
+
Send messages via WhatsApp or Telegram through Chatflow API.
|
|
9
|
+
|
|
10
|
+
**Operations:**
|
|
11
|
+
- Send Text
|
|
12
|
+
- Send Image (with optional caption)
|
|
13
|
+
- Send Video (with optional caption)
|
|
14
|
+
- Send Audio
|
|
15
|
+
- Send Document (with optional caption)
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
### Chatflow Trigger
|
|
18
|
+
Webhook-based trigger that starts your workflow when a new message arrives.
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
20
|
+
**Supported events:**
|
|
21
|
+
- Incoming message
|
|
22
|
+
- Delivery status updates
|
|
23
|
+
- Authorization status changes
|
|
24
|
+
- Incoming calls
|
|
25
|
+
- Outgoing messages (API / Phone)
|
|
18
26
|
|
|
19
27
|
## Credentials
|
|
20
28
|
|
|
21
|
-
|
|
29
|
+
Each credential is bound to one instance:
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
| Field | Description |
|
|
32
|
+
|---|---|
|
|
33
|
+
| **Server URL** | Your Chatflow server (default: `https://app.chatflow.kz`) |
|
|
34
|
+
| **Token** | API token from Chatflow → Settings → API Access |
|
|
35
|
+
| **Instance ID** | Instance ID from Chatflow → Instances |
|
|
36
|
+
| **Platform** | `WhatsApp` or `Telegram` |
|
|
26
37
|
|
|
27
|
-
|
|
38
|
+
> **Tip:** Create separate credentials for each instance you want to use.
|
|
28
39
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
### In n8n (Community Nodes)
|
|
43
|
+
1. Go to **Settings → Community Nodes**
|
|
44
|
+
2. Enter `n8n-nodes-chatflow`
|
|
45
|
+
3. Click **Install**
|
|
46
|
+
|
|
47
|
+
### Manual
|
|
48
|
+
```bash
|
|
49
|
+
cd ~/.n8n
|
|
50
|
+
npm install n8n-nodes-chatflow
|
|
51
|
+
```
|
|
32
52
|
|
|
33
|
-
## Usage
|
|
53
|
+
## Usage
|
|
34
54
|
|
|
35
|
-
1. Add
|
|
36
|
-
2.
|
|
37
|
-
3.
|
|
38
|
-
4. Provide the required parameters
|
|
39
|
-
5. Connect to other nodes as needed
|
|
55
|
+
1. Add your Chatflow credentials (token + instance ID + platform)
|
|
56
|
+
2. **To send messages:** Add a "Chatflow Message" node, choose operation, set recipient
|
|
57
|
+
3. **To receive messages:** Add a "Chatflow Trigger" node, select event types, activate workflow
|
|
40
58
|
|
|
41
|
-
##
|
|
59
|
+
## License
|
|
42
60
|
|
|
43
|
-
|
|
61
|
+
MIT
|
|
@@ -1,29 +1,46 @@
|
|
|
1
1
|
class ChatflowApi {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
2
|
+
constructor() {
|
|
3
|
+
this.name = 'chatflowApi';
|
|
4
|
+
this.displayName = 'Chatflow API';
|
|
5
|
+
this.documentationUrl = 'https://app.chatflow.kz';
|
|
6
|
+
this.properties = [
|
|
7
|
+
{
|
|
8
|
+
displayName: 'Server URL',
|
|
9
|
+
name: 'serverUrl',
|
|
10
|
+
type: 'string',
|
|
11
|
+
default: 'https://app.chatflow.kz',
|
|
12
|
+
required: true,
|
|
13
|
+
description: 'Your Chatflow server URL (e.g. https://app.chatflow.kz)',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
displayName: 'Token',
|
|
17
|
+
name: 'token',
|
|
18
|
+
type: 'string',
|
|
19
|
+
typeOptions: { password: true },
|
|
20
|
+
default: '',
|
|
21
|
+
required: true,
|
|
22
|
+
description: 'API token from Chatflow → Settings → API Access',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
displayName: 'Flow ID',
|
|
26
|
+
name: 'flowId',
|
|
27
|
+
type: 'string',
|
|
28
|
+
default: '',
|
|
29
|
+
required: true,
|
|
30
|
+
description: 'Flow ID copied from your Chatflow Flow Builder',
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
this.test = {
|
|
34
|
+
request: {
|
|
35
|
+
baseURL: '={{$credentials.serverUrl}}',
|
|
36
|
+
url: '/api/v1/n8n/ping',
|
|
37
|
+
method: 'GET',
|
|
38
|
+
qs: {
|
|
39
|
+
token: '={{$credentials.token}}',
|
|
40
|
+
flow_id: '={{$credentials.flowId}}',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
27
45
|
}
|
|
28
|
-
|
|
29
|
-
module.exports = ChatflowApi;
|
|
46
|
+
module.exports = { ChatflowApi };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
1
|
+
// Точка входа: экспортируем классы, а не пути. Относительные пути
|
|
2
|
+
// будут корректно работать как из исходников, так и после сборки в dist.
|
|
3
|
+
const { ChatflowMessage } = require('./nodes/ChatflowMessage.node.js');
|
|
4
|
+
const { ChatflowApi } = require('./credentials/ChatflowApi.credentials.js');
|
|
5
|
+
exports.nodes = [ChatflowMessage];
|
|
6
|
+
exports.credentials = [ChatflowApi];
|
|
7
|
+
module.exports = { nodes: exports.nodes, credentials: exports.credentials };
|
|
@@ -1,122 +1,259 @@
|
|
|
1
1
|
class ChatflowMessage {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
name: 'chatflowMessage',
|
|
6
|
-
icon: 'file:chatflow.png',
|
|
7
|
-
group: ['output'],
|
|
8
|
-
version: 1,
|
|
9
|
-
subtitle: '={{$parameter["operation"]}}',
|
|
10
|
-
description: 'Send WhatsApp messages via Chatflow API',
|
|
11
|
-
defaults: { name: 'Chatflow Message' },
|
|
12
|
-
inputs: [{ type: 'main' }],
|
|
13
|
-
outputs: [{ type: 'main' }],
|
|
14
|
-
credentials: [
|
|
15
|
-
{ name: 'chatflowApi', required: true },
|
|
16
|
-
],
|
|
17
|
-
properties: [
|
|
18
|
-
{
|
|
19
|
-
displayName: 'Operation',
|
|
20
|
-
name: 'operation',
|
|
21
|
-
type: 'options',
|
|
22
|
-
options: [
|
|
23
|
-
{ name: 'Text', value: 'text' },
|
|
24
|
-
{ name: 'Audio', value: 'audio' },
|
|
25
|
-
{ name: 'Video', value: 'video' },
|
|
26
|
-
{ name: 'Document', value: 'document' },
|
|
27
|
-
{ name: 'Image', value: 'image' },
|
|
28
|
-
],
|
|
29
|
-
default: 'text',
|
|
30
|
-
},
|
|
31
|
-
{ displayName: 'Instance ID', name: 'instance_id', type: 'string', default: '', required: true },
|
|
32
|
-
{ displayName: 'JID', name: 'jid', type: 'string', default: '', required: true },
|
|
33
|
-
|
|
34
|
-
// Text
|
|
35
|
-
{ displayName: 'Message', name: 'msg', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['text'] } } },
|
|
36
|
-
|
|
37
|
-
// Audio
|
|
38
|
-
{ displayName: 'Audio URL', name: 'audiourl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['audio'] } } },
|
|
39
|
-
|
|
40
|
-
// Video
|
|
41
|
-
{ displayName: 'Video URL', name: 'videourl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['video'] } } },
|
|
42
|
-
{ displayName: 'Caption', name: 'caption', type: 'string', default: '', displayOptions: { show: { operation: ['video'] } } },
|
|
43
|
-
|
|
44
|
-
// Document
|
|
45
|
-
{ displayName: 'Document URL', name: 'docurl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['document'] } } },
|
|
46
|
-
{ displayName: 'Caption', name: 'captionDoc', type: 'string', default: '', displayOptions: { show: { operation: ['document'] } } },
|
|
47
|
-
|
|
48
|
-
// Image
|
|
49
|
-
{ displayName: 'Image URL', name: 'imageurl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['image'] } } },
|
|
50
|
-
{ displayName: 'Caption', name: 'captionImg', type: 'string', default: '', displayOptions: { show: { operation: ['image'] } } },
|
|
2
|
+
constructor() {
|
|
3
|
+
this.description = ChatflowMessage.description;
|
|
4
|
+
}
|
|
51
5
|
|
|
52
|
-
|
|
53
|
-
|
|
6
|
+
methods = {
|
|
7
|
+
loadOptions: {
|
|
8
|
+
async getPlatform() {
|
|
9
|
+
try {
|
|
10
|
+
const credentials = await this.getCredentials('chatflowApi');
|
|
11
|
+
const serverUrl = (credentials.serverUrl || 'https://app.chatflow.kz').replace(/\/+$/, '');
|
|
12
|
+
if (!credentials.flowId) return [];
|
|
13
|
+
|
|
14
|
+
const response = await this.helpers.httpRequest({
|
|
15
|
+
method: 'GET',
|
|
16
|
+
url: `${serverUrl}/api/v1/n8n/flow-info/${credentials.flowId}`,
|
|
17
|
+
qs: { token: credentials.token },
|
|
18
|
+
json: true,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
if (response && response.platform) {
|
|
22
|
+
const platName = response.platform === 'telegram' ? 'Telegram' : 'WhatsApp';
|
|
23
|
+
return [{ name: platName, value: response.platform }];
|
|
24
|
+
}
|
|
25
|
+
} catch(e) {
|
|
26
|
+
console.error('Failed to load platform:', e);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return [
|
|
30
|
+
{ name: 'WhatsApp', value: 'whatsapp' },
|
|
31
|
+
{ name: 'Telegram', value: 'telegram' }
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
54
35
|
};
|
|
55
|
-
}
|
|
56
36
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
37
|
+
async execute() {
|
|
38
|
+
const items = this.getInputData();
|
|
39
|
+
const out = [];
|
|
40
|
+
const credentials = await this.getCredentials('chatflowApi');
|
|
41
|
+
const token = credentials.token;
|
|
42
|
+
const flowId = credentials.flowId;
|
|
43
|
+
const serverUrl = (credentials.serverUrl || 'https://app.chatflow.kz').replace(/\/+$/, '');
|
|
44
|
+
const platform = this.getNodeParameter('platform', 0, 'whatsapp');
|
|
60
45
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const operation = this.getNodeParameter('operation', 0);
|
|
64
|
-
const continueOnFail = this.getNodeParameter('continueOnFail', 0);
|
|
46
|
+
const operation = this.getNodeParameter('operation', 0);
|
|
47
|
+
const continueOnFail = this.getNodeParameter('continueOnFail', 0);
|
|
65
48
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
video: 'api/v1/send-video',
|
|
70
|
-
document: 'api/v1/send-doc',
|
|
71
|
-
image: 'api/v1/send-image',
|
|
72
|
-
};
|
|
49
|
+
for (let i = 0; i < items.length; i++) {
|
|
50
|
+
try {
|
|
51
|
+
const recipient = this.getNodeParameter('recipient', i);
|
|
73
52
|
|
|
74
|
-
|
|
75
|
-
|
|
53
|
+
// Build query string params
|
|
54
|
+
const qs = { token, flow_id: flowId };
|
|
76
55
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
56
|
+
// Set recipient field based on platform
|
|
57
|
+
if (platform === 'telegram') {
|
|
58
|
+
qs.chat_id = recipient;
|
|
59
|
+
} else {
|
|
60
|
+
qs.jid = recipient;
|
|
61
|
+
}
|
|
81
62
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
63
|
+
// Operation-specific params
|
|
64
|
+
if (operation === 'text') {
|
|
65
|
+
qs.msg = this.getNodeParameter('msg', i);
|
|
66
|
+
}
|
|
67
|
+
if (operation === 'audio') {
|
|
68
|
+
qs.audiourl = this.getNodeParameter('audiourl', i);
|
|
69
|
+
}
|
|
70
|
+
if (operation === 'video') {
|
|
71
|
+
qs.videourl = this.getNodeParameter('videourl', i);
|
|
72
|
+
const cap = this.getNodeParameter('captionVideo', i, '');
|
|
73
|
+
if (cap) qs.caption = cap;
|
|
74
|
+
}
|
|
75
|
+
if (operation === 'document') {
|
|
76
|
+
qs.docurl = this.getNodeParameter('docurl', i);
|
|
77
|
+
const cap = this.getNodeParameter('captionDoc', i, '');
|
|
78
|
+
if (cap) qs.caption = cap;
|
|
79
|
+
}
|
|
80
|
+
if (operation === 'image') {
|
|
81
|
+
qs.imageurl = this.getNodeParameter('imageurl', i);
|
|
82
|
+
const cap = this.getNodeParameter('captionImg', i, '');
|
|
83
|
+
if (cap) qs.caption = cap;
|
|
84
|
+
}
|
|
97
85
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
};
|
|
86
|
+
const options = {
|
|
87
|
+
method: 'GET',
|
|
88
|
+
url: `${serverUrl}/api/v1/n8n/action/${operation}`,
|
|
89
|
+
qs,
|
|
90
|
+
headers: { Accept: 'application/json' },
|
|
91
|
+
timeout: 15000,
|
|
92
|
+
};
|
|
106
93
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
94
|
+
const responseData = await this.helpers.httpRequest(options);
|
|
95
|
+
out.push({ json: responseData });
|
|
96
|
+
} catch (error) {
|
|
97
|
+
if (continueOnFail) {
|
|
98
|
+
out.push({
|
|
99
|
+
json: {
|
|
100
|
+
success: false,
|
|
101
|
+
message: (error && error.message) || 'Request failed',
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
113
108
|
}
|
|
114
|
-
|
|
115
|
-
}
|
|
109
|
+
return [out];
|
|
116
110
|
}
|
|
117
|
-
|
|
118
|
-
return [out];
|
|
119
|
-
}
|
|
120
111
|
}
|
|
121
112
|
|
|
122
|
-
|
|
113
|
+
ChatflowMessage.description = {
|
|
114
|
+
displayName: 'Chatflow Message',
|
|
115
|
+
name: 'chatflowMessage',
|
|
116
|
+
icon: {
|
|
117
|
+
light: 'file:black.svg',
|
|
118
|
+
dark: 'file:white.svg'
|
|
119
|
+
},
|
|
120
|
+
group: ['output'],
|
|
121
|
+
version: 2,
|
|
122
|
+
subtitle: '={{$parameter["operation"]}} ({{$parameter["platform"]}})',
|
|
123
|
+
description: 'Send WhatsApp & Telegram messages via Chatflow API',
|
|
124
|
+
defaults: { name: 'Chatflow Message' },
|
|
125
|
+
inputs: [{ type: 'main' }],
|
|
126
|
+
outputs: [{ type: 'main' }],
|
|
127
|
+
credentials: [
|
|
128
|
+
{ name: 'chatflowApi', required: true },
|
|
129
|
+
],
|
|
130
|
+
properties: [
|
|
131
|
+
{
|
|
132
|
+
displayName: 'Messaging Platform',
|
|
133
|
+
name: 'platform',
|
|
134
|
+
type: 'options',
|
|
135
|
+
typeOptions: { loadOptionsMethod: 'getPlatform' },
|
|
136
|
+
default: '',
|
|
137
|
+
required: true,
|
|
138
|
+
description: 'Automatically determined from your Chatflow credentials (Flow ID)',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
displayName: 'Operation',
|
|
142
|
+
name: 'operation',
|
|
143
|
+
type: 'options',
|
|
144
|
+
noDataExpression: true,
|
|
145
|
+
options: [
|
|
146
|
+
{ name: 'Send Text', value: 'text', description: 'Send a text message' },
|
|
147
|
+
{ name: 'Send Image', value: 'image', description: 'Send an image with optional caption' },
|
|
148
|
+
{ name: 'Send Video', value: 'video', description: 'Send a video with optional caption' },
|
|
149
|
+
{ name: 'Send Audio', value: 'audio', description: 'Send an audio file' },
|
|
150
|
+
{ name: 'Send Document', value: 'document', description: 'Send a document with optional caption' },
|
|
151
|
+
],
|
|
152
|
+
default: 'text',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
displayName: 'Recipient Number (WhatsApp)',
|
|
156
|
+
name: 'recipient',
|
|
157
|
+
type: 'string',
|
|
158
|
+
default: '',
|
|
159
|
+
required: true,
|
|
160
|
+
displayOptions: { show: { platform: ['whatsapp'] } },
|
|
161
|
+
description: 'WhatsApp phone number (e.g. 77001234567)',
|
|
162
|
+
placeholder: '77001234567',
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
displayName: 'Chat ID (Telegram)',
|
|
166
|
+
name: 'recipient',
|
|
167
|
+
type: 'string',
|
|
168
|
+
default: '',
|
|
169
|
+
required: true,
|
|
170
|
+
displayOptions: { show: { platform: ['telegram'] } },
|
|
171
|
+
description: 'Telegram numeric Chat ID',
|
|
172
|
+
},
|
|
173
|
+
// --- Text ---
|
|
174
|
+
{
|
|
175
|
+
displayName: 'Message',
|
|
176
|
+
name: 'msg',
|
|
177
|
+
type: 'string',
|
|
178
|
+
typeOptions: { rows: 4 },
|
|
179
|
+
default: '',
|
|
180
|
+
required: true,
|
|
181
|
+
displayOptions: { show: { operation: ['text'] } },
|
|
182
|
+
description: 'Text of the message to send',
|
|
183
|
+
},
|
|
184
|
+
// --- Image ---
|
|
185
|
+
{
|
|
186
|
+
displayName: 'Image URL',
|
|
187
|
+
name: 'imageurl',
|
|
188
|
+
type: 'string',
|
|
189
|
+
default: '',
|
|
190
|
+
required: true,
|
|
191
|
+
displayOptions: { show: { operation: ['image'] } },
|
|
192
|
+
description: 'Public URL of the image file',
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
displayName: 'Caption',
|
|
196
|
+
name: 'captionImg',
|
|
197
|
+
type: 'string',
|
|
198
|
+
default: '',
|
|
199
|
+
displayOptions: { show: { operation: ['image'] } },
|
|
200
|
+
description: 'Optional caption for the image',
|
|
201
|
+
},
|
|
202
|
+
// --- Video ---
|
|
203
|
+
{
|
|
204
|
+
displayName: 'Video URL',
|
|
205
|
+
name: 'videourl',
|
|
206
|
+
type: 'string',
|
|
207
|
+
default: '',
|
|
208
|
+
required: true,
|
|
209
|
+
displayOptions: { show: { operation: ['video'] } },
|
|
210
|
+
description: 'Public URL of the video file',
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
displayName: 'Caption',
|
|
214
|
+
name: 'captionVideo',
|
|
215
|
+
type: 'string',
|
|
216
|
+
default: '',
|
|
217
|
+
displayOptions: { show: { operation: ['video'] } },
|
|
218
|
+
description: 'Optional caption for the video',
|
|
219
|
+
},
|
|
220
|
+
// --- Audio ---
|
|
221
|
+
{
|
|
222
|
+
displayName: 'Audio URL',
|
|
223
|
+
name: 'audiourl',
|
|
224
|
+
type: 'string',
|
|
225
|
+
default: '',
|
|
226
|
+
required: true,
|
|
227
|
+
displayOptions: { show: { operation: ['audio'] } },
|
|
228
|
+
description: 'Public URL of the audio file',
|
|
229
|
+
},
|
|
230
|
+
// --- Document ---
|
|
231
|
+
{
|
|
232
|
+
displayName: 'Document URL',
|
|
233
|
+
name: 'docurl',
|
|
234
|
+
type: 'string',
|
|
235
|
+
default: '',
|
|
236
|
+
required: true,
|
|
237
|
+
displayOptions: { show: { operation: ['document'] } },
|
|
238
|
+
description: 'Public URL of the document file',
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
displayName: 'Caption',
|
|
242
|
+
name: 'captionDoc',
|
|
243
|
+
type: 'string',
|
|
244
|
+
default: '',
|
|
245
|
+
displayOptions: { show: { operation: ['document'] } },
|
|
246
|
+
description: 'Optional caption for the document',
|
|
247
|
+
},
|
|
248
|
+
// --- Options ---
|
|
249
|
+
{
|
|
250
|
+
displayName: 'Continue On Fail',
|
|
251
|
+
name: 'continueOnFail',
|
|
252
|
+
type: 'boolean',
|
|
253
|
+
default: true,
|
|
254
|
+
description: 'Whether to continue workflow execution on send failure',
|
|
255
|
+
},
|
|
256
|
+
],
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
module.exports = { ChatflowMessage };
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
class ChatflowTrigger {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.description = ChatflowTrigger.description;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
methods = {
|
|
7
|
+
loadOptions: {
|
|
8
|
+
async getPlatform() {
|
|
9
|
+
try {
|
|
10
|
+
const credentials = await this.getCredentials('chatflowApi');
|
|
11
|
+
const serverUrl = (credentials.serverUrl || 'https://app.chatflow.kz').replace(/\/+$/, '');
|
|
12
|
+
if (!credentials.flowId) return [];
|
|
13
|
+
|
|
14
|
+
const response = await this.helpers.httpRequest({
|
|
15
|
+
method: 'GET',
|
|
16
|
+
url: `${serverUrl}/api/v1/n8n/flow-info/${credentials.flowId}`,
|
|
17
|
+
qs: { token: credentials.token },
|
|
18
|
+
json: true,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
if (response && response.platform) {
|
|
22
|
+
const platName = response.platform === 'telegram' ? 'Telegram' : 'WhatsApp';
|
|
23
|
+
return [{ name: platName, value: response.platform }];
|
|
24
|
+
}
|
|
25
|
+
} catch(e) {
|
|
26
|
+
console.error('Failed to load platform:', e);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return [
|
|
30
|
+
{ name: 'WhatsApp', value: 'whatsapp' },
|
|
31
|
+
{ name: 'Telegram', value: 'telegram' }
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
webhookMethods = {
|
|
38
|
+
default: {
|
|
39
|
+
async checkExists() {
|
|
40
|
+
const webhookData = this.getWorkflowStaticData('node');
|
|
41
|
+
const webhookUrl = this.getNodeWebhookUrl('default');
|
|
42
|
+
|
|
43
|
+
if (webhookData.webhookId) {
|
|
44
|
+
// Check if webhook is still registered on the server
|
|
45
|
+
try {
|
|
46
|
+
const credentials = await this.getCredentials('chatflowApi');
|
|
47
|
+
const serverUrl = (credentials.serverUrl || 'https://app.chatflow.kz').replace(/\/+$/, '');
|
|
48
|
+
|
|
49
|
+
const response = await this.helpers.httpRequest({
|
|
50
|
+
method: 'GET',
|
|
51
|
+
url: `${serverUrl}/api/v1/n8n/webhook/${webhookData.webhookId}`,
|
|
52
|
+
qs: { token: credentials.token },
|
|
53
|
+
headers: { Accept: 'application/json' },
|
|
54
|
+
timeout: 10000,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
if (response && response.success && response.webhook) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
} catch (e) {
|
|
61
|
+
// Webhook not found, needs to be re-created
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
async create() {
|
|
68
|
+
const webhookUrl = this.getNodeWebhookUrl('default');
|
|
69
|
+
const credentials = await this.getCredentials('chatflowApi');
|
|
70
|
+
const serverUrl = (credentials.serverUrl || 'https://app.chatflow.kz').replace(/\/+$/, '');
|
|
71
|
+
const flowId = credentials.flowId;
|
|
72
|
+
const token = credentials.token;
|
|
73
|
+
|
|
74
|
+
// Get event filters from node parameters
|
|
75
|
+
const events = this.getNodeParameter('events', {});
|
|
76
|
+
|
|
77
|
+
const body = {
|
|
78
|
+
token,
|
|
79
|
+
flow_id: flowId,
|
|
80
|
+
webhook_url: webhookUrl,
|
|
81
|
+
events: events || { incoming_message: true },
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const response = await this.helpers.httpRequest({
|
|
85
|
+
method: 'POST',
|
|
86
|
+
url: `${serverUrl}/api/v1/n8n/register-webhook`,
|
|
87
|
+
body,
|
|
88
|
+
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
89
|
+
timeout: 10000,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (!response || !response.success || !response.webhookId) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`Failed to register webhook: ${(response && response.message) || 'Unknown error'}`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const webhookData = this.getWorkflowStaticData('node');
|
|
99
|
+
webhookData.webhookId = response.webhookId;
|
|
100
|
+
|
|
101
|
+
return true;
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
async delete() {
|
|
105
|
+
const webhookData = this.getWorkflowStaticData('node');
|
|
106
|
+
const credentials = await this.getCredentials('chatflowApi');
|
|
107
|
+
const serverUrl = (credentials.serverUrl || 'https://app.chatflow.kz').replace(/\/+$/, '');
|
|
108
|
+
|
|
109
|
+
if (webhookData.webhookId) {
|
|
110
|
+
try {
|
|
111
|
+
await this.helpers.httpRequest({
|
|
112
|
+
method: 'DELETE',
|
|
113
|
+
url: `${serverUrl}/api/v1/n8n/register-webhook`,
|
|
114
|
+
body: {
|
|
115
|
+
token: credentials.token,
|
|
116
|
+
webhookId: webhookData.webhookId,
|
|
117
|
+
},
|
|
118
|
+
headers: { 'Content-Type': 'application/json' },
|
|
119
|
+
timeout: 10000,
|
|
120
|
+
});
|
|
121
|
+
} catch (e) {
|
|
122
|
+
// Best-effort cleanup
|
|
123
|
+
}
|
|
124
|
+
delete webhookData.webhookId;
|
|
125
|
+
}
|
|
126
|
+
return true;
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
async webhook() {
|
|
132
|
+
const bodyData = this.getBodyData();
|
|
133
|
+
const headerData = this.getHeaderData();
|
|
134
|
+
|
|
135
|
+
// Verify the source (optional: check token header)
|
|
136
|
+
// const credentials = await this.getCredentials('chatflowApi');
|
|
137
|
+
|
|
138
|
+
// Normalize: Chatflow sends { messages: [...] }
|
|
139
|
+
const messages = bodyData.messages || [bodyData];
|
|
140
|
+
const returnData = [];
|
|
141
|
+
|
|
142
|
+
for (const message of messages) {
|
|
143
|
+
returnData.push({
|
|
144
|
+
json: {
|
|
145
|
+
// Core message fields
|
|
146
|
+
platform: message.platform || 'whatsapp',
|
|
147
|
+
event_type: message.wh_type || 'incoming_message',
|
|
148
|
+
// Sender info
|
|
149
|
+
from: message.chat_id || message.from || '',
|
|
150
|
+
sender_name: message.contact?.FullName || message.contact?.FirstName || message.pushName || '',
|
|
151
|
+
// Message content
|
|
152
|
+
message_id: message.id || message.task_id || '',
|
|
153
|
+
text: message.body || message.text || '',
|
|
154
|
+
type: message.type || 'text',
|
|
155
|
+
// Media (if any)
|
|
156
|
+
media_url: message.media_url || message.body_file || '',
|
|
157
|
+
caption: message.caption || '',
|
|
158
|
+
// Metadata
|
|
159
|
+
timestamp: message.time || Date.now(),
|
|
160
|
+
profile_id: message.profile_id || '',
|
|
161
|
+
instance_id: message.instance_id || '',
|
|
162
|
+
// Full raw payload for advanced use
|
|
163
|
+
_raw: message,
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
workflowData: [returnData],
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
ChatflowTrigger.description = {
|
|
175
|
+
displayName: 'Chatflow Trigger',
|
|
176
|
+
name: 'chatflowTrigger',
|
|
177
|
+
icon: {
|
|
178
|
+
light: 'file:black.svg',
|
|
179
|
+
dark: 'file:white.svg'
|
|
180
|
+
},
|
|
181
|
+
group: ['trigger'],
|
|
182
|
+
version: 1,
|
|
183
|
+
subtitle: '={{$parameter["platform"]}}',
|
|
184
|
+
description: 'Triggers workflow on incoming messages via Chatflow',
|
|
185
|
+
defaults: { name: 'Chatflow Trigger' },
|
|
186
|
+
inputs: [],
|
|
187
|
+
outputs: [{ type: 'main' }],
|
|
188
|
+
credentials: [
|
|
189
|
+
{ name: 'chatflowApi', required: true },
|
|
190
|
+
],
|
|
191
|
+
webhooks: [
|
|
192
|
+
{
|
|
193
|
+
name: 'default',
|
|
194
|
+
httpMethod: 'POST',
|
|
195
|
+
responseMode: 'onReceived',
|
|
196
|
+
path: 'webhook',
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
properties: [
|
|
200
|
+
{
|
|
201
|
+
displayName: 'Messaging Platform',
|
|
202
|
+
name: 'platform',
|
|
203
|
+
type: 'options',
|
|
204
|
+
typeOptions: { loadOptionsMethod: 'getPlatform' },
|
|
205
|
+
default: '',
|
|
206
|
+
required: true,
|
|
207
|
+
description: 'Automatically determined from your Chatflow credentials (Flow ID)',
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
displayName: 'Events',
|
|
211
|
+
name: 'events',
|
|
212
|
+
type: 'fixedCollection',
|
|
213
|
+
typeOptions: { multipleValues: false },
|
|
214
|
+
default: {},
|
|
215
|
+
description: 'Filter which events trigger this workflow',
|
|
216
|
+
options: [
|
|
217
|
+
{
|
|
218
|
+
displayName: 'Event Filters',
|
|
219
|
+
name: 'filters',
|
|
220
|
+
values: [
|
|
221
|
+
{
|
|
222
|
+
displayName: 'Incoming Message',
|
|
223
|
+
name: 'incoming_message',
|
|
224
|
+
type: 'boolean',
|
|
225
|
+
default: true,
|
|
226
|
+
description: 'Trigger on new incoming messages',
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
displayName: 'Delivery Status',
|
|
230
|
+
name: 'delivery_status',
|
|
231
|
+
type: 'boolean',
|
|
232
|
+
default: false,
|
|
233
|
+
description: 'Trigger on message delivery status updates',
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
displayName: 'Authorization Status',
|
|
237
|
+
name: 'authorization_status',
|
|
238
|
+
type: 'boolean',
|
|
239
|
+
default: false,
|
|
240
|
+
description: 'Trigger on instance authorization changes',
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
displayName: 'Incoming Call',
|
|
244
|
+
name: 'incoming_call',
|
|
245
|
+
type: 'boolean',
|
|
246
|
+
default: false,
|
|
247
|
+
description: 'Trigger on incoming voice/video calls',
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
displayName: 'Outgoing Message (API)',
|
|
251
|
+
name: 'outgoing_message_api',
|
|
252
|
+
type: 'boolean',
|
|
253
|
+
default: false,
|
|
254
|
+
description: 'Trigger on messages sent via API',
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
displayName: 'Outgoing Message (Phone)',
|
|
258
|
+
name: 'outgoing_message_phone',
|
|
259
|
+
type: 'boolean',
|
|
260
|
+
default: false,
|
|
261
|
+
description: 'Trigger on messages sent from phone',
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
module.exports = { ChatflowTrigger };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg width="144" height="130" viewBox="0 0 144 130" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g transform="translate(72 65) scale(1.15) translate(-72 -65)">
|
|
3
|
+
<rect x="39.7617" y="19.8789" width="64.1613" height="15.3626" fill="black"/>
|
|
4
|
+
<rect x="64.1621" y="93.0762" width="39.762" height="15.3626" fill="black"/>
|
|
5
|
+
<rect x="64.1621" y="100.309" width="67.7761" height="15.3626" transform="rotate(-90 64.1621 100.309)" fill="black"/>
|
|
6
|
+
<rect x="93.9844" width="49.7025" height="56.0282" rx="4.29273" fill="black"/>
|
|
7
|
+
<rect width="49.7025" height="56.0282" rx="4.29273" fill="black"/>
|
|
8
|
+
<rect x="93.9844" y="73.1992" width="49.7025" height="56.0282" rx="4.29273" fill="black"/>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
package/dist/nodes/chatflow.png
CHANGED
|
Binary file
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 868 780" width="60" height="60" preserveAspectRatio="xMidYMid meet">
|
|
2
|
+
<g fill="currentColor">
|
|
3
|
+
<!-- Top-left bracket -->
|
|
4
|
+
<path d="M 100 118 L 100 0 L 300 0 C 320 0 338 18 338 38 L 338 300 C 338 320 320 338 300 338 L 180 338 L 180 213 L 258 213 L 258 120 L 100 118 Z" />
|
|
5
|
+
|
|
6
|
+
<!-- Top-right bracket -->
|
|
7
|
+
<path d="M 568 0 L 828 0 L 828 118 L 610 120 L 610 213 L 748 213 L 748 338 L 568 338 C 548 338 530 320 530 300 L 530 38 C 530 18 548 0 568 0 Z" />
|
|
8
|
+
|
|
9
|
+
<!-- Bottom-right bracket (L-shape connection) -->
|
|
10
|
+
<path d="M 530 442 L 748 442 L 748 502 L 610 502 L 610 667 L 828 667 L 828 780 L 568 780 C 548 780 530 762 530 742 L 530 462 C 530 448 544 442 560 442 L 530 442 Z" />
|
|
11
|
+
|
|
12
|
+
<!-- Vertical connecting bar (stem) -->
|
|
13
|
+
<rect x="300" y="213" width="88" height="354" rx="0"/>
|
|
14
|
+
|
|
15
|
+
<!-- Horizontal connecting bar (bottom horizontal) -->
|
|
16
|
+
<rect x="388" y="654" width="180" height="88" rx="0"/>
|
|
17
|
+
</g>
|
|
18
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg width="144" height="130" viewBox="0 0 144 130" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g transform="translate(72 65) scale(1.15) translate(-72 -65)">
|
|
3
|
+
<rect x="39.7617" y="19.8789" width="64.1613" height="15.3626" fill="white"/>
|
|
4
|
+
<rect x="64.1621" y="93.0762" width="39.762" height="15.3626" fill="white"/>
|
|
5
|
+
<rect x="64.1621" y="100.309" width="67.7761" height="15.3626" transform="rotate(-90 64.1621 100.309)" fill="white"/>
|
|
6
|
+
<rect x="93.9844" width="49.7025" height="56.0282" rx="4.29273" fill="white"/>
|
|
7
|
+
<rect width="49.7025" height="56.0282" rx="4.29273" fill="white"/>
|
|
8
|
+
<rect x="93.9844" y="73.1992" width="49.7025" height="56.0282" rx="4.29273" fill="white"/>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
package/package.json
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-chatflow",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "n8n community
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "n8n community nodes for Chatflow — send WhatsApp & Telegram messages and receive triggers",
|
|
5
5
|
"author": "Chatflow",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"n8n-community-node-package",
|
|
9
|
+
"n8n",
|
|
10
|
+
"community-node",
|
|
9
11
|
"chatflow",
|
|
10
12
|
"whatsapp",
|
|
11
|
-
"
|
|
13
|
+
"telegram",
|
|
14
|
+
"messaging",
|
|
15
|
+
"trigger"
|
|
12
16
|
],
|
|
13
17
|
"repository": {
|
|
14
18
|
"type": "git",
|
|
@@ -16,7 +20,8 @@
|
|
|
16
20
|
},
|
|
17
21
|
"n8n": {
|
|
18
22
|
"nodes": [
|
|
19
|
-
"dist/nodes/ChatflowMessage.node.js"
|
|
23
|
+
"dist/nodes/ChatflowMessage.node.js",
|
|
24
|
+
"dist/nodes/ChatflowTrigger.node.js"
|
|
20
25
|
],
|
|
21
26
|
"credentials": [
|
|
22
27
|
"dist/credentials/ChatflowApi.credentials.js"
|
|
@@ -25,24 +30,20 @@
|
|
|
25
30
|
"main": "dist/index.js",
|
|
26
31
|
"files": [
|
|
27
32
|
"dist",
|
|
28
|
-
"nodes",
|
|
29
|
-
"credentials",
|
|
30
|
-
"index.js",
|
|
31
33
|
"README.md",
|
|
32
34
|
"LICENSE"
|
|
33
35
|
],
|
|
34
36
|
"scripts": {
|
|
35
|
-
"
|
|
36
|
-
"clean": "rimraf dist",
|
|
37
|
-
"test": "node test-package.js",
|
|
38
|
-
"prepublishOnly": "npm run build"
|
|
37
|
+
"test": "node test-package.js"
|
|
39
38
|
},
|
|
40
|
-
"
|
|
41
|
-
"n8n-core": "
|
|
42
|
-
"n8n-workflow": "
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"n8n-core": "*",
|
|
41
|
+
"n8n-workflow": "*"
|
|
43
42
|
},
|
|
44
43
|
"devDependencies": {
|
|
45
44
|
"cpx": "^1.5.0",
|
|
46
|
-
"
|
|
45
|
+
"eslint-plugin-n8n-nodes-base": "^1.16.3",
|
|
46
|
+
"rimraf": "^5.0.5",
|
|
47
|
+
"typescript": "^5.0.0"
|
|
47
48
|
}
|
|
48
49
|
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
class ChatflowApi {
|
|
2
|
-
constructor() {
|
|
3
|
-
this.name = 'chatflowApi';
|
|
4
|
-
this.displayName = 'Chatflow API';
|
|
5
|
-
this.documentationUrl = 'https://app.chatflow.kz';
|
|
6
|
-
this.properties = [
|
|
7
|
-
{
|
|
8
|
-
displayName: 'Token',
|
|
9
|
-
name: 'token',
|
|
10
|
-
type: 'string',
|
|
11
|
-
typeOptions: { password: true },
|
|
12
|
-
default: '',
|
|
13
|
-
required: true,
|
|
14
|
-
description: 'API token from Chatflow → Settings → API Access',
|
|
15
|
-
},
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
// Basic test to ensure base URL is reachable
|
|
19
|
-
this.test = {
|
|
20
|
-
request: {
|
|
21
|
-
baseURL: 'https://app.chatflow.kz/',
|
|
22
|
-
url: 'ping',
|
|
23
|
-
method: 'GET',
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
module.exports = ChatflowApi;
|
package/index.js
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
class ChatflowMessage {
|
|
2
|
-
constructor() {
|
|
3
|
-
this.description = {
|
|
4
|
-
displayName: 'Chatflow',
|
|
5
|
-
name: 'chatflowMessage',
|
|
6
|
-
icon: 'file:chatflow.png',
|
|
7
|
-
group: ['output'],
|
|
8
|
-
version: 1,
|
|
9
|
-
subtitle: '={{$parameter["operation"]}}',
|
|
10
|
-
description: 'Send WhatsApp messages via Chatflow API',
|
|
11
|
-
defaults: { name: 'Chatflow Message' },
|
|
12
|
-
inputs: [{ type: 'main' }],
|
|
13
|
-
outputs: [{ type: 'main' }],
|
|
14
|
-
credentials: [
|
|
15
|
-
{ name: 'chatflowApi', required: true },
|
|
16
|
-
],
|
|
17
|
-
properties: [
|
|
18
|
-
{
|
|
19
|
-
displayName: 'Operation',
|
|
20
|
-
name: 'operation',
|
|
21
|
-
type: 'options',
|
|
22
|
-
options: [
|
|
23
|
-
{ name: 'Text', value: 'text' },
|
|
24
|
-
{ name: 'Audio', value: 'audio' },
|
|
25
|
-
{ name: 'Video', value: 'video' },
|
|
26
|
-
{ name: 'Document', value: 'document' },
|
|
27
|
-
{ name: 'Image', value: 'image' },
|
|
28
|
-
],
|
|
29
|
-
default: 'text',
|
|
30
|
-
},
|
|
31
|
-
{ displayName: 'Instance ID', name: 'instance_id', type: 'string', default: '', required: true },
|
|
32
|
-
{ displayName: 'JID', name: 'jid', type: 'string', default: '', required: true },
|
|
33
|
-
|
|
34
|
-
// Text
|
|
35
|
-
{ displayName: 'Message', name: 'msg', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['text'] } } },
|
|
36
|
-
|
|
37
|
-
// Audio
|
|
38
|
-
{ displayName: 'Audio URL', name: 'audiourl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['audio'] } } },
|
|
39
|
-
|
|
40
|
-
// Video
|
|
41
|
-
{ displayName: 'Video URL', name: 'videourl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['video'] } } },
|
|
42
|
-
{ displayName: 'Caption', name: 'caption', type: 'string', default: '', displayOptions: { show: { operation: ['video'] } } },
|
|
43
|
-
|
|
44
|
-
// Document
|
|
45
|
-
{ displayName: 'Document URL', name: 'docurl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['document'] } } },
|
|
46
|
-
{ displayName: 'Caption', name: 'captionDoc', type: 'string', default: '', displayOptions: { show: { operation: ['document'] } } },
|
|
47
|
-
|
|
48
|
-
// Image
|
|
49
|
-
{ displayName: 'Image URL', name: 'imageurl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['image'] } } },
|
|
50
|
-
{ displayName: 'Caption', name: 'captionImg', type: 'string', default: '', displayOptions: { show: { operation: ['image'] } } },
|
|
51
|
-
|
|
52
|
-
{ displayName: 'Continue On Fail', name: 'continueOnFail', type: 'boolean', default: true },
|
|
53
|
-
]
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async execute() {
|
|
58
|
-
const items = this.getInputData();
|
|
59
|
-
const out = [];
|
|
60
|
-
|
|
61
|
-
const credentials = await this.getCredentials('chatflowApi');
|
|
62
|
-
const token = credentials.token;
|
|
63
|
-
const operation = this.getNodeParameter('operation', 0);
|
|
64
|
-
const continueOnFail = this.getNodeParameter('continueOnFail', 0);
|
|
65
|
-
|
|
66
|
-
const endpointMap = {
|
|
67
|
-
text: 'api/v1/send-text',
|
|
68
|
-
audio: 'api/v1/send-audio',
|
|
69
|
-
video: 'api/v1/send-video',
|
|
70
|
-
document: 'api/v1/send-doc',
|
|
71
|
-
image: 'api/v1/send-image',
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const urlJoin = (a, b) => a.replace(/\/+$/, '') + '/' + b.replace(/^\/+/, '');
|
|
75
|
-
const baseUrl = 'https://app.chatflow.kz/';
|
|
76
|
-
|
|
77
|
-
for (let i = 0; i < items.length; i++) {
|
|
78
|
-
try {
|
|
79
|
-
const instance_id = this.getNodeParameter('instance_id', i);
|
|
80
|
-
const jid = this.getNodeParameter('jid', i);
|
|
81
|
-
|
|
82
|
-
const qs = { token, instance_id, jid };
|
|
83
|
-
if (operation === 'text') qs.msg = this.getNodeParameter('msg', i);
|
|
84
|
-
if (operation === 'audio') qs.audiourl = this.getNodeParameter('audiourl', i);
|
|
85
|
-
if (operation === 'video') {
|
|
86
|
-
qs.videourl = this.getNodeParameter('videourl', i);
|
|
87
|
-
const capV = this.getNodeParameter('caption', i, ''); if (capV) qs.caption = capV;
|
|
88
|
-
}
|
|
89
|
-
if (operation === 'document') {
|
|
90
|
-
qs.docurl = this.getNodeParameter('docurl', i);
|
|
91
|
-
const capD = this.getNodeParameter('captionDoc', i, ''); if (capD) qs.caption = capD;
|
|
92
|
-
}
|
|
93
|
-
if (operation === 'image') {
|
|
94
|
-
qs.imageurl = this.getNodeParameter('imageurl', i);
|
|
95
|
-
const capI = this.getNodeParameter('captionImg', i, ''); if (capI) qs.caption = capI;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const options = {
|
|
99
|
-
method: 'GET',
|
|
100
|
-
url: urlJoin(baseUrl, endpointMap[operation]),
|
|
101
|
-
qs,
|
|
102
|
-
headers: { Accept: 'application/json' },
|
|
103
|
-
timeout: 10000,
|
|
104
|
-
retry: { times: 1, interval: 500 },
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const responseData = await this.helpers.httpRequest(options);
|
|
108
|
-
out.push({ json: responseData });
|
|
109
|
-
} catch (error) {
|
|
110
|
-
if (continueOnFail) {
|
|
111
|
-
out.push({ json: { success: false, message: (error && error.message) || 'Request failed' } });
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
throw error;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return [out];
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
module.exports = ChatflowMessage;
|
package/nodes/chatflow.png
DELETED
|
Binary file
|