n8n-nodes-chatflow 0.1.2 → 0.1.4
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/LICENSE +22 -0
- package/README.md +29 -0
- package/credentials/ChatflowApi.credentials.js +6 -3
- package/credentials/ChatflowApi.credentials.ts +30 -0
- package/dist/credentials/ChatflowApi.credentials.js +6 -3
- package/dist/credentials/ChatflowApi.credentials.ts +30 -0
- package/dist/index.js +2 -1
- package/dist/nodes/ChatflowMessage.node.js +6 -3
- package/dist/nodes/ChatflowMessage.node.ts +135 -0
- package/index.js +2 -1
- package/nodes/ChatflowMessage.node.js +6 -3
- package/nodes/ChatflowMessage.node.ts +135 -0
- package/package.json +15 -4
- package/n8n-nodes-chatflow-0.1.1.tgz +0 -0
- package/n8n-nodes-chatflow-0.1.2.tgz +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Chatflow
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# n8n-nodes-chatflow
|
|
2
|
+
|
|
3
|
+
Chatflow node for n8n — send WhatsApp messages via Chatflow API (text, audio, video, document, image).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm i n8n-nodes-chatflow --save
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
If you use custom extensions for n8n, make sure `N8N_CUSTOM_EXTENSIONS` points to the package folder (e.g. `node_modules/n8n-nodes-chatflow`) or copy this package to your custom dir.
|
|
12
|
+
|
|
13
|
+
Restart n8n after installation.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
1. Create credentials "Chatflow API" and paste your token (from Chatflow → Api access).
|
|
17
|
+
2. Add node "Chatflow" and select the credential.
|
|
18
|
+
3. Choose Operation and fill required parameters:
|
|
19
|
+
- Text: `msg`, `instance_id`, `jid`
|
|
20
|
+
- Audio: `audiourl`, `instance_id`, `jid`
|
|
21
|
+
- Video: `videourl`, `caption?`, `instance_id`, `jid`
|
|
22
|
+
- Document: `docurl`, `caption?`, `instance_id`, `jid`
|
|
23
|
+
- Image: `imageurl`, `caption?`, `instance_id`, `jid`
|
|
24
|
+
|
|
25
|
+
The node performs GET requests to `https://app.chatflow.kz/` using endpoints:
|
|
26
|
+
- `api/v1/send-text`, `api/v1/send-audio`, `api/v1/send-video`, `api/v1/send-doc`, `api/v1/send-image`.
|
|
27
|
+
|
|
28
|
+
## License
|
|
29
|
+
MIT
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
class ChatflowApi {
|
|
2
2
|
constructor() {
|
|
3
3
|
this.name = 'chatflowApi';
|
|
4
4
|
this.displayName = 'Chatflow API';
|
|
@@ -18,10 +18,13 @@ module.exports = class ChatflowApi {
|
|
|
18
18
|
// simple test (no token needed)
|
|
19
19
|
this.test = {
|
|
20
20
|
request: {
|
|
21
|
-
baseURL: 'https://app.chatflow.kz',
|
|
21
|
+
baseURL: 'https://app.chatflow.kz/',
|
|
22
22
|
url: 'ping',
|
|
23
23
|
method: 'GET',
|
|
24
24
|
},
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
-
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
exports.ChatflowApi = ChatflowApi;
|
|
30
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
|
|
3
|
+
export class ChatflowApi implements ICredentialType {
|
|
4
|
+
name = 'chatflowApi';
|
|
5
|
+
displayName = 'Chatflow API';
|
|
6
|
+
documentationUrl = '';
|
|
7
|
+
|
|
8
|
+
properties: INodeProperties[] = [
|
|
9
|
+
{
|
|
10
|
+
displayName: 'Token',
|
|
11
|
+
name: 'token',
|
|
12
|
+
type: 'string',
|
|
13
|
+
typeOptions: { password: true },
|
|
14
|
+
default: '',
|
|
15
|
+
required: true,
|
|
16
|
+
description: 'API token from Chatflow → Api access',
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
// Optional basic test just to ensure base URL is reachable
|
|
21
|
+
// Token не проверяем, так как для ping он не нужен
|
|
22
|
+
test = {
|
|
23
|
+
request: {
|
|
24
|
+
baseURL: 'https://app.chatflow.kz/',
|
|
25
|
+
url: 'ping',
|
|
26
|
+
method: 'GET',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
class ChatflowApi {
|
|
2
2
|
constructor() {
|
|
3
3
|
this.name = 'chatflowApi';
|
|
4
4
|
this.displayName = 'Chatflow API';
|
|
@@ -18,10 +18,13 @@ module.exports = class ChatflowApi {
|
|
|
18
18
|
// simple test (no token needed)
|
|
19
19
|
this.test = {
|
|
20
20
|
request: {
|
|
21
|
-
baseURL: 'https://app.chatflow.kz',
|
|
21
|
+
baseURL: 'https://app.chatflow.kz/',
|
|
22
22
|
url: 'ping',
|
|
23
23
|
method: 'GET',
|
|
24
24
|
},
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
-
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
exports.ChatflowApi = ChatflowApi;
|
|
30
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
|
|
3
|
+
export class ChatflowApi implements ICredentialType {
|
|
4
|
+
name = 'chatflowApi';
|
|
5
|
+
displayName = 'Chatflow API';
|
|
6
|
+
documentationUrl = '';
|
|
7
|
+
|
|
8
|
+
properties: INodeProperties[] = [
|
|
9
|
+
{
|
|
10
|
+
displayName: 'Token',
|
|
11
|
+
name: 'token',
|
|
12
|
+
type: 'string',
|
|
13
|
+
typeOptions: { password: true },
|
|
14
|
+
default: '',
|
|
15
|
+
required: true,
|
|
16
|
+
description: 'API token from Chatflow → Api access',
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
// Optional basic test just to ensure base URL is reachable
|
|
21
|
+
// Token не проверяем, так как для ping он не нужен
|
|
22
|
+
test = {
|
|
23
|
+
request: {
|
|
24
|
+
baseURL: 'https://app.chatflow.kz/',
|
|
25
|
+
url: 'ping',
|
|
26
|
+
method: 'GET',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
class Chatflow {
|
|
2
2
|
constructor() {
|
|
3
3
|
this.description = {
|
|
4
4
|
displayName: 'Chatflow',
|
|
@@ -72,7 +72,7 @@ module.exports = class ChatflowMessage {
|
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
const urlJoin = (a, b) => a.replace(/\/+$/, '') + '/' + b.replace(/^\/+/, '');
|
|
75
|
-
const baseUrl = 'https://app.chatflow.kz';
|
|
75
|
+
const baseUrl = 'https://app.chatflow.kz/';
|
|
76
76
|
|
|
77
77
|
for (let i = 0; i < items.length; i++) {
|
|
78
78
|
try {
|
|
@@ -117,4 +117,7 @@ module.exports = class ChatflowMessage {
|
|
|
117
117
|
|
|
118
118
|
return [out];
|
|
119
119
|
}
|
|
120
|
-
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
exports.Chatflow = Chatflow;
|
|
123
|
+
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
2
|
+
import { NodeOperationError } from 'n8n-workflow';
|
|
3
|
+
|
|
4
|
+
type MessageType = 'text' | 'audio' | 'video' | 'document' | 'image';
|
|
5
|
+
|
|
6
|
+
export class ChatflowMessage implements INodeType {
|
|
7
|
+
description: INodeTypeDescription = {
|
|
8
|
+
displayName: 'Chatflow',
|
|
9
|
+
name: 'chatflow',
|
|
10
|
+
icon: 'file:chatflow.png',
|
|
11
|
+
group: ['output'],
|
|
12
|
+
version: 1,
|
|
13
|
+
subtitle: '={{$parameter["operation"]}}',
|
|
14
|
+
description: 'Send WhatsApp messages via Chatflow API',
|
|
15
|
+
defaults: { name: 'Chatflow Message' },
|
|
16
|
+
inputs: [
|
|
17
|
+
{ type: 'main' as any },
|
|
18
|
+
],
|
|
19
|
+
outputs: [
|
|
20
|
+
{ type: 'main' as any },
|
|
21
|
+
],
|
|
22
|
+
credentials: [
|
|
23
|
+
{
|
|
24
|
+
name: 'chatflowApi',
|
|
25
|
+
required: true,
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
properties: [
|
|
29
|
+
{
|
|
30
|
+
displayName: 'Operation',
|
|
31
|
+
name: 'operation',
|
|
32
|
+
type: 'options',
|
|
33
|
+
options: [
|
|
34
|
+
{ name: 'Text', value: 'text' },
|
|
35
|
+
{ name: 'Audio', value: 'audio' },
|
|
36
|
+
{ name: 'Video', value: 'video' },
|
|
37
|
+
{ name: 'Document', value: 'document' },
|
|
38
|
+
{ name: 'Image', value: 'image' },
|
|
39
|
+
],
|
|
40
|
+
default: 'text',
|
|
41
|
+
},
|
|
42
|
+
{ displayName: 'Instance ID', name: 'instance_id', type: 'string', default: '', required: true },
|
|
43
|
+
{ displayName: 'JID', name: 'jid', type: 'string', default: '', required: true },
|
|
44
|
+
|
|
45
|
+
// Text
|
|
46
|
+
{ displayName: 'Message', name: 'msg', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['text'] } } },
|
|
47
|
+
|
|
48
|
+
// Audio
|
|
49
|
+
{ displayName: 'Audio URL', name: 'audiourl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['audio'] } } },
|
|
50
|
+
|
|
51
|
+
// Video
|
|
52
|
+
{ displayName: 'Video URL', name: 'videourl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['video'] } } },
|
|
53
|
+
{ displayName: 'Caption', name: 'caption', type: 'string', default: '', displayOptions: { show: { operation: ['video'] } } },
|
|
54
|
+
|
|
55
|
+
// Document
|
|
56
|
+
{ displayName: 'Document URL', name: 'docurl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['document'] } } },
|
|
57
|
+
{ displayName: 'Caption', name: 'captionDoc', type: 'string', default: '', displayOptions: { show: { operation: ['document'] } } },
|
|
58
|
+
|
|
59
|
+
// Image
|
|
60
|
+
{ displayName: 'Image URL', name: 'imageurl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['image'] } } },
|
|
61
|
+
{ displayName: 'Caption', name: 'captionImg', type: 'string', default: '', displayOptions: { show: { operation: ['image'] } } },
|
|
62
|
+
|
|
63
|
+
{
|
|
64
|
+
displayName: 'Continue On Fail',
|
|
65
|
+
name: 'continueOnFail',
|
|
66
|
+
type: 'boolean',
|
|
67
|
+
default: true,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
|
73
|
+
const items = this.getInputData();
|
|
74
|
+
const out: INodeExecutionData[] = [];
|
|
75
|
+
|
|
76
|
+
const baseUrl = 'https://app.chatflow.kz/';
|
|
77
|
+
const credentials = await this.getCredentials('chatflowApi');
|
|
78
|
+
const token = (credentials as any).token as string;
|
|
79
|
+
const operation = this.getNodeParameter('operation', 0) as MessageType;
|
|
80
|
+
const continueOnFail = this.getNodeParameter('continueOnFail', 0) as boolean;
|
|
81
|
+
|
|
82
|
+
const endpointMap: Record<MessageType, string> = {
|
|
83
|
+
text: 'api/v1/send-text',
|
|
84
|
+
audio: 'api/v1/send-audio',
|
|
85
|
+
video: 'api/v1/send-video',
|
|
86
|
+
document: 'api/v1/send-doc',
|
|
87
|
+
image: 'api/v1/send-image',
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const urlJoin = (a: string, b: string) => a.replace(/\/+$/, '') + '/' + b.replace(/^\/+/, '');
|
|
91
|
+
|
|
92
|
+
for (let i = 0; i < items.length; i++) {
|
|
93
|
+
try {
|
|
94
|
+
const instance_id = this.getNodeParameter('instance_id', i) as string;
|
|
95
|
+
const jid = this.getNodeParameter('jid', i) as string;
|
|
96
|
+
|
|
97
|
+
const qs: Record<string, string> = { token, instance_id, jid };
|
|
98
|
+
switch (operation) {
|
|
99
|
+
case 'text': qs.msg = this.getNodeParameter('msg', i) as string; break;
|
|
100
|
+
case 'audio': qs.audiourl = this.getNodeParameter('audiourl', i) as string; break;
|
|
101
|
+
case 'video':
|
|
102
|
+
qs.videourl = this.getNodeParameter('videourl', i) as string;
|
|
103
|
+
const capV = this.getNodeParameter('caption', i, '') as string; if (capV) qs.caption = capV; break;
|
|
104
|
+
case 'document':
|
|
105
|
+
qs.docurl = this.getNodeParameter('docurl', i) as string;
|
|
106
|
+
const capD = this.getNodeParameter('captionDoc', i, '') as string; if (capD) qs.caption = capD; break;
|
|
107
|
+
case 'image':
|
|
108
|
+
qs.imageurl = this.getNodeParameter('imageurl', i) as string;
|
|
109
|
+
const capI = this.getNodeParameter('captionImg', i, '') as string; if (capI) qs.caption = capI; break;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const options = {
|
|
113
|
+
method: 'GET',
|
|
114
|
+
url: urlJoin(baseUrl, endpointMap[operation]),
|
|
115
|
+
qs,
|
|
116
|
+
headers: { Accept: 'application/json' },
|
|
117
|
+
timeout: 10000,
|
|
118
|
+
retry: { times: 1, interval: 500 },
|
|
119
|
+
} as unknown as any;
|
|
120
|
+
|
|
121
|
+
const responseData = await this.helpers.httpRequest(options);
|
|
122
|
+
out.push({ json: responseData });
|
|
123
|
+
} catch (error) {
|
|
124
|
+
if (continueOnFail) {
|
|
125
|
+
out.push({ json: { success: false, message: (error as Error).message || 'Request failed' } });
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
throw new NodeOperationError(this.getNode(), error as Error, { itemIndex: i });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return [out];
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
class Chatflow {
|
|
2
2
|
constructor() {
|
|
3
3
|
this.description = {
|
|
4
4
|
displayName: 'Chatflow',
|
|
@@ -72,7 +72,7 @@ module.exports = class ChatflowMessage {
|
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
const urlJoin = (a, b) => a.replace(/\/+$/, '') + '/' + b.replace(/^\/+/, '');
|
|
75
|
-
const baseUrl = 'https://app.chatflow.kz';
|
|
75
|
+
const baseUrl = 'https://app.chatflow.kz/';
|
|
76
76
|
|
|
77
77
|
for (let i = 0; i < items.length; i++) {
|
|
78
78
|
try {
|
|
@@ -117,4 +117,7 @@ module.exports = class ChatflowMessage {
|
|
|
117
117
|
|
|
118
118
|
return [out];
|
|
119
119
|
}
|
|
120
|
-
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
exports.Chatflow = Chatflow;
|
|
123
|
+
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
2
|
+
import { NodeOperationError } from 'n8n-workflow';
|
|
3
|
+
|
|
4
|
+
type MessageType = 'text' | 'audio' | 'video' | 'document' | 'image';
|
|
5
|
+
|
|
6
|
+
export class ChatflowMessage implements INodeType {
|
|
7
|
+
description: INodeTypeDescription = {
|
|
8
|
+
displayName: 'Chatflow',
|
|
9
|
+
name: 'chatflow',
|
|
10
|
+
icon: 'file:chatflow.png',
|
|
11
|
+
group: ['output'],
|
|
12
|
+
version: 1,
|
|
13
|
+
subtitle: '={{$parameter["operation"]}}',
|
|
14
|
+
description: 'Send WhatsApp messages via Chatflow API',
|
|
15
|
+
defaults: { name: 'Chatflow Message' },
|
|
16
|
+
inputs: [
|
|
17
|
+
{ type: 'main' as any },
|
|
18
|
+
],
|
|
19
|
+
outputs: [
|
|
20
|
+
{ type: 'main' as any },
|
|
21
|
+
],
|
|
22
|
+
credentials: [
|
|
23
|
+
{
|
|
24
|
+
name: 'chatflowApi',
|
|
25
|
+
required: true,
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
properties: [
|
|
29
|
+
{
|
|
30
|
+
displayName: 'Operation',
|
|
31
|
+
name: 'operation',
|
|
32
|
+
type: 'options',
|
|
33
|
+
options: [
|
|
34
|
+
{ name: 'Text', value: 'text' },
|
|
35
|
+
{ name: 'Audio', value: 'audio' },
|
|
36
|
+
{ name: 'Video', value: 'video' },
|
|
37
|
+
{ name: 'Document', value: 'document' },
|
|
38
|
+
{ name: 'Image', value: 'image' },
|
|
39
|
+
],
|
|
40
|
+
default: 'text',
|
|
41
|
+
},
|
|
42
|
+
{ displayName: 'Instance ID', name: 'instance_id', type: 'string', default: '', required: true },
|
|
43
|
+
{ displayName: 'JID', name: 'jid', type: 'string', default: '', required: true },
|
|
44
|
+
|
|
45
|
+
// Text
|
|
46
|
+
{ displayName: 'Message', name: 'msg', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['text'] } } },
|
|
47
|
+
|
|
48
|
+
// Audio
|
|
49
|
+
{ displayName: 'Audio URL', name: 'audiourl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['audio'] } } },
|
|
50
|
+
|
|
51
|
+
// Video
|
|
52
|
+
{ displayName: 'Video URL', name: 'videourl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['video'] } } },
|
|
53
|
+
{ displayName: 'Caption', name: 'caption', type: 'string', default: '', displayOptions: { show: { operation: ['video'] } } },
|
|
54
|
+
|
|
55
|
+
// Document
|
|
56
|
+
{ displayName: 'Document URL', name: 'docurl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['document'] } } },
|
|
57
|
+
{ displayName: 'Caption', name: 'captionDoc', type: 'string', default: '', displayOptions: { show: { operation: ['document'] } } },
|
|
58
|
+
|
|
59
|
+
// Image
|
|
60
|
+
{ displayName: 'Image URL', name: 'imageurl', type: 'string', default: '', required: true, displayOptions: { show: { operation: ['image'] } } },
|
|
61
|
+
{ displayName: 'Caption', name: 'captionImg', type: 'string', default: '', displayOptions: { show: { operation: ['image'] } } },
|
|
62
|
+
|
|
63
|
+
{
|
|
64
|
+
displayName: 'Continue On Fail',
|
|
65
|
+
name: 'continueOnFail',
|
|
66
|
+
type: 'boolean',
|
|
67
|
+
default: true,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
|
73
|
+
const items = this.getInputData();
|
|
74
|
+
const out: INodeExecutionData[] = [];
|
|
75
|
+
|
|
76
|
+
const baseUrl = 'https://app.chatflow.kz/';
|
|
77
|
+
const credentials = await this.getCredentials('chatflowApi');
|
|
78
|
+
const token = (credentials as any).token as string;
|
|
79
|
+
const operation = this.getNodeParameter('operation', 0) as MessageType;
|
|
80
|
+
const continueOnFail = this.getNodeParameter('continueOnFail', 0) as boolean;
|
|
81
|
+
|
|
82
|
+
const endpointMap: Record<MessageType, string> = {
|
|
83
|
+
text: 'api/v1/send-text',
|
|
84
|
+
audio: 'api/v1/send-audio',
|
|
85
|
+
video: 'api/v1/send-video',
|
|
86
|
+
document: 'api/v1/send-doc',
|
|
87
|
+
image: 'api/v1/send-image',
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const urlJoin = (a: string, b: string) => a.replace(/\/+$/, '') + '/' + b.replace(/^\/+/, '');
|
|
91
|
+
|
|
92
|
+
for (let i = 0; i < items.length; i++) {
|
|
93
|
+
try {
|
|
94
|
+
const instance_id = this.getNodeParameter('instance_id', i) as string;
|
|
95
|
+
const jid = this.getNodeParameter('jid', i) as string;
|
|
96
|
+
|
|
97
|
+
const qs: Record<string, string> = { token, instance_id, jid };
|
|
98
|
+
switch (operation) {
|
|
99
|
+
case 'text': qs.msg = this.getNodeParameter('msg', i) as string; break;
|
|
100
|
+
case 'audio': qs.audiourl = this.getNodeParameter('audiourl', i) as string; break;
|
|
101
|
+
case 'video':
|
|
102
|
+
qs.videourl = this.getNodeParameter('videourl', i) as string;
|
|
103
|
+
const capV = this.getNodeParameter('caption', i, '') as string; if (capV) qs.caption = capV; break;
|
|
104
|
+
case 'document':
|
|
105
|
+
qs.docurl = this.getNodeParameter('docurl', i) as string;
|
|
106
|
+
const capD = this.getNodeParameter('captionDoc', i, '') as string; if (capD) qs.caption = capD; break;
|
|
107
|
+
case 'image':
|
|
108
|
+
qs.imageurl = this.getNodeParameter('imageurl', i) as string;
|
|
109
|
+
const capI = this.getNodeParameter('captionImg', i, '') as string; if (capI) qs.caption = capI; break;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const options = {
|
|
113
|
+
method: 'GET',
|
|
114
|
+
url: urlJoin(baseUrl, endpointMap[operation]),
|
|
115
|
+
qs,
|
|
116
|
+
headers: { Accept: 'application/json' },
|
|
117
|
+
timeout: 10000,
|
|
118
|
+
retry: { times: 1, interval: 500 },
|
|
119
|
+
} as unknown as any;
|
|
120
|
+
|
|
121
|
+
const responseData = await this.helpers.httpRequest(options);
|
|
122
|
+
out.push({ json: responseData });
|
|
123
|
+
} catch (error) {
|
|
124
|
+
if (continueOnFail) {
|
|
125
|
+
out.push({ json: { success: false, message: (error as Error).message || 'Request failed' } });
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
throw new NodeOperationError(this.getNode(), error as Error, { itemIndex: i });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return [out];
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
package/package.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-chatflow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "n8n community node to send WhatsApp messages via Chatflow (text, audio, video, document, image)",
|
|
5
5
|
"author": "Chatflow",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"n8n-community-node-package",
|
|
9
|
-
"n8n-nodes",
|
|
10
9
|
"chatflow",
|
|
11
10
|
"whatsapp",
|
|
12
11
|
"messaging"
|
|
@@ -24,8 +23,20 @@
|
|
|
24
23
|
]
|
|
25
24
|
},
|
|
26
25
|
"main": "dist/index.js",
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"nodes",
|
|
29
|
+
"credentials",
|
|
30
|
+
"index.js",
|
|
31
|
+
"README.md",
|
|
32
|
+
"LICENSE"
|
|
33
|
+
],
|
|
27
34
|
"scripts": {
|
|
28
|
-
"build": "
|
|
29
|
-
"clean": "
|
|
35
|
+
"build": "rimraf dist && cpx \"nodes/**/*\" dist/nodes && cpx \"credentials/**/*\" dist/credentials && cpx \"index.js\" dist/",
|
|
36
|
+
"clean": "rimraf dist"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"cpx": "^1.5.0",
|
|
40
|
+
"rimraf": "^5.0.5"
|
|
30
41
|
}
|
|
31
42
|
}
|
|
Binary file
|
|
Binary file
|