n8n-nodes-evolution-message-search 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 +108 -0
- package/dist/credentials/EvolutionApi.credentials.js +33 -0
- package/dist/nodes/SearchMessages/SearchMessages.node.js +234 -0
- package/dist/nodes/SearchMessages/SearchMessages.node.json +20 -0
- package/dist/nodes/SearchMessages/icon.svg +5 -0
- package/index.js +8 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# n8n-nodes-evolution-message-search
|
|
2
|
+
|
|
3
|
+
Evolution API - Search Messages node for n8n. Search WhatsApp message history by keywords, dates, and conversation.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Search WhatsApp message history via Evolution API
|
|
8
|
+
- Filter by keywords in message content
|
|
9
|
+
- Filter by date range (from/to)
|
|
10
|
+
- Filter by conversation ID (WhatsApp JID)
|
|
11
|
+
- Paginated results with configurable page size
|
|
12
|
+
- AI agent tool support (usable as tool in AI workflows)
|
|
13
|
+
|
|
14
|
+
## Requirements
|
|
15
|
+
|
|
16
|
+
- n8n instance (v1.0+)
|
|
17
|
+
- Evolution API instance with API access
|
|
18
|
+
- Existing `evolutionApi` credentials configured in n8n
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
### Option 1: Install from npm (coming soon)
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install n8n-nodes-evolution-message-search
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Option 2: Install as community node
|
|
29
|
+
|
|
30
|
+
1. In n8n, go to **Settings > Community Nodes**
|
|
31
|
+
2. Click **Install**
|
|
32
|
+
3. Enter: `n8n-nodes-evolution-message-search`
|
|
33
|
+
4. Accept terms and install
|
|
34
|
+
|
|
35
|
+
### Option 3: Install from source
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
cd n8n-nodes-evolution-message-search
|
|
39
|
+
npm install
|
|
40
|
+
npm run build
|
|
41
|
+
npm link
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Then in your n8n installation directory:
|
|
45
|
+
```bash
|
|
46
|
+
cd ~/.n8n/custom
|
|
47
|
+
npm link n8n-nodes-evolution-message-search
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Configuration
|
|
51
|
+
|
|
52
|
+
### Credentials
|
|
53
|
+
|
|
54
|
+
This node uses the existing `evolutionApi` credential type. Before using the node:
|
|
55
|
+
|
|
56
|
+
1. Go to **Credentials** in n8n
|
|
57
|
+
2. Create a new `Evolution API` credential
|
|
58
|
+
3. Enter your Evolution API URL and API key
|
|
59
|
+
|
|
60
|
+
### Node Parameters
|
|
61
|
+
|
|
62
|
+
| Parameter | Who Sets | Model Can Change | Description |
|
|
63
|
+
|-----------|----------|------------------|-------------|
|
|
64
|
+
| Instance Name | User | No | Evolution API instance name |
|
|
65
|
+
| Conversation ID | User | Only if allowed | WhatsApp conversation JID |
|
|
66
|
+
| Allow Model to Set Conversation | User | No | Permission for AI model to set conversation |
|
|
67
|
+
| Keywords | Model | Yes | Search text in messages |
|
|
68
|
+
| Date From | Model | Yes | Start date for search |
|
|
69
|
+
| Date To | Model | Yes | End date for search |
|
|
70
|
+
| Items per Page | User | No | Results per page (1-100) |
|
|
71
|
+
| Page Number | Model | Yes | Page to retrieve |
|
|
72
|
+
|
|
73
|
+
## Output Format
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"total": 100,
|
|
78
|
+
"pages": 10,
|
|
79
|
+
"currentPage": 1,
|
|
80
|
+
"pageSize": 10,
|
|
81
|
+
"records": [
|
|
82
|
+
{
|
|
83
|
+
"id": "msg_abc123",
|
|
84
|
+
"key": {
|
|
85
|
+
"remote": "5511999999999@s.whatsapp.net",
|
|
86
|
+
"id": "some_id"
|
|
87
|
+
},
|
|
88
|
+
"message": {
|
|
89
|
+
"conversationMessage": {
|
|
90
|
+
"text": "Hello world"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"messageType": "conversation",
|
|
94
|
+
"fromMe": true,
|
|
95
|
+
"timestamp": 1703001234
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Evolution API Reference
|
|
102
|
+
|
|
103
|
+
- [Evolution API Documentation](https://docs.evolutionfoundation.com.br/evolution-api)
|
|
104
|
+
- [Find Messages Endpoint](https://docs.evolutionfoundation.com.br/evolution-api/find-messages.md)
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
MIT
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
const n8n_workflow_1 = require('n8n-workflow');
|
|
4
|
+
class EvolutionApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'evolutionApi';
|
|
7
|
+
this.displayName = 'Evolution API';
|
|
8
|
+
this.documentationUrl = 'https://docs.evolutionfoundation.com.br/evolution-api';
|
|
9
|
+
this.properties = [
|
|
10
|
+
{
|
|
11
|
+
displayName: 'API Key',
|
|
12
|
+
name: 'apiKey',
|
|
13
|
+
type: 'string',
|
|
14
|
+
default: '',
|
|
15
|
+
},
|
|
16
|
+
];
|
|
17
|
+
this.authenticate = {
|
|
18
|
+
type: 'generic',
|
|
19
|
+
properties: {
|
|
20
|
+
headers: {
|
|
21
|
+
apikey: '={{$credentials.apiKey}}',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
this.test = {
|
|
26
|
+
request: {
|
|
27
|
+
url: '/instance/connectionStatus',
|
|
28
|
+
method: 'GET',
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.EvolutionApi = EvolutionApi;
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.SearchMessages = void 0;
|
|
4
|
+
const n8n_workflow_1 = require('n8n-workflow');
|
|
5
|
+
class SearchMessages {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.description = {
|
|
8
|
+
displayName: 'Evolution API - Search Messages',
|
|
9
|
+
name: 'searchMessages',
|
|
10
|
+
icon: 'file:icon.svg',
|
|
11
|
+
group: ['transform'],
|
|
12
|
+
version: 1,
|
|
13
|
+
subtitle: 'Search WhatsApp message history',
|
|
14
|
+
description: 'Search WhatsApp message history by keywords, dates, and conversation',
|
|
15
|
+
defaults: {
|
|
16
|
+
name: 'Evolution API - Search Messages',
|
|
17
|
+
},
|
|
18
|
+
usableAsTool: true,
|
|
19
|
+
inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
20
|
+
outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
21
|
+
credentials: [
|
|
22
|
+
{
|
|
23
|
+
name: 'evolutionApi',
|
|
24
|
+
required: true,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
requestDefaults: {
|
|
28
|
+
baseURL: '={{$credentials.baseUrl || "http://localhost:8080"}}',
|
|
29
|
+
headers: {
|
|
30
|
+
'Accept': 'application/json',
|
|
31
|
+
'Content-Type': 'application/json',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
properties: [
|
|
35
|
+
{
|
|
36
|
+
displayName: 'Resource',
|
|
37
|
+
name: 'resource',
|
|
38
|
+
type: 'hidden',
|
|
39
|
+
default: 'messages',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
displayName: 'Instance Name',
|
|
43
|
+
name: 'instanceName',
|
|
44
|
+
type: 'string',
|
|
45
|
+
required: true,
|
|
46
|
+
displayOptions: {
|
|
47
|
+
show: {
|
|
48
|
+
resource: ['messages'],
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
description: 'Name of the Evolution API instance (set by user, model cannot change)',
|
|
52
|
+
hint: 'The instance name is defined by the user and cannot be modified by the AI model',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
displayName: 'Conversation ID',
|
|
56
|
+
name: 'conversationId',
|
|
57
|
+
type: 'string',
|
|
58
|
+
required: false,
|
|
59
|
+
displayOptions: {
|
|
60
|
+
show: {
|
|
61
|
+
resource: ['messages'],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
description: 'WhatsApp conversation ID (JID). If empty, searches all conversations. Model can use if provided by user.',
|
|
65
|
+
placeholder: '5511999999999@s.whatsapp.net',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
displayName: 'Allow Model to Set Conversation',
|
|
69
|
+
name: 'allowModelSetConversation',
|
|
70
|
+
type: 'boolean',
|
|
71
|
+
default: false,
|
|
72
|
+
displayOptions: {
|
|
73
|
+
show: {
|
|
74
|
+
resource: ['messages'],
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
description: 'If enabled, the AI model can set the conversation ID. If disabled, model must use the value provided above.',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
displayName: 'Search Parameters',
|
|
81
|
+
name: 'searchParams',
|
|
82
|
+
type: 'fixedCollection',
|
|
83
|
+
displayOptions: {
|
|
84
|
+
show: {
|
|
85
|
+
resource: ['messages'],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
default: {},
|
|
89
|
+
options: [
|
|
90
|
+
{
|
|
91
|
+
displayName: 'Search Fields',
|
|
92
|
+
name: 'fields',
|
|
93
|
+
values: [
|
|
94
|
+
{
|
|
95
|
+
displayName: 'Keywords',
|
|
96
|
+
name: 'keywords',
|
|
97
|
+
type: 'string',
|
|
98
|
+
default: '',
|
|
99
|
+
description: 'Search text in message content (model can set)',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
displayName: 'Date From',
|
|
103
|
+
name: 'dateFrom',
|
|
104
|
+
type: 'dateTime',
|
|
105
|
+
default: '',
|
|
106
|
+
description: 'Start date for message search (model can set)',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
displayName: 'Date To',
|
|
110
|
+
name: 'dateTo',
|
|
111
|
+
type: 'dateTime',
|
|
112
|
+
default: '',
|
|
113
|
+
description: 'End date for message search (model can set)',
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
displayName: 'Pagination',
|
|
121
|
+
name: 'pagination',
|
|
122
|
+
type: 'fixedCollection',
|
|
123
|
+
displayOptions: {
|
|
124
|
+
show: {
|
|
125
|
+
resource: ['messages'],
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
default: {
|
|
129
|
+
fields: {
|
|
130
|
+
pageSize: 10,
|
|
131
|
+
page: 1,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
options: [
|
|
135
|
+
{
|
|
136
|
+
displayName: 'Pagination Fields',
|
|
137
|
+
name: 'fields',
|
|
138
|
+
values: [
|
|
139
|
+
{
|
|
140
|
+
displayName: 'Items per Page',
|
|
141
|
+
name: 'pageSize',
|
|
142
|
+
type: 'number',
|
|
143
|
+
default: 10,
|
|
144
|
+
typeOptions: {
|
|
145
|
+
minValue: 1,
|
|
146
|
+
maxValue: 100,
|
|
147
|
+
},
|
|
148
|
+
description: 'Number of results per page (set by user, model cannot change)',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
displayName: 'Page Number',
|
|
152
|
+
name: 'page',
|
|
153
|
+
type: 'number',
|
|
154
|
+
default: 1,
|
|
155
|
+
typeOptions: {
|
|
156
|
+
minValue: 1,
|
|
157
|
+
},
|
|
158
|
+
description: 'Page number to retrieve (model can navigate)',
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
async execute(executeFunctions) {
|
|
168
|
+
const items = executeFunctions.getInputData();
|
|
169
|
+
const returnData = [];
|
|
170
|
+
for (let i = 0; i < items.length; i++) {
|
|
171
|
+
const instanceName = executeFunctions.getNodeParameter('instanceName', i);
|
|
172
|
+
const userConversationId = executeFunctions.getNodeParameter('conversationId', i);
|
|
173
|
+
const allowModelSetConversation = executeFunctions.getNodeParameter('allowModelSetConversation', i);
|
|
174
|
+
const searchParams = executeFunctions.getNodeParameter('searchParams.fields', i);
|
|
175
|
+
const pagination = executeFunctions.getNodeParameter('pagination.fields', i);
|
|
176
|
+
let conversationId = userConversationId;
|
|
177
|
+
if (!conversationId && allowModelSetConversation) {
|
|
178
|
+
conversationId = executeFunctions.getNodeParameter('modelConversationId', i, '');
|
|
179
|
+
}
|
|
180
|
+
const pageSize = pagination.pageSize;
|
|
181
|
+
const page = pagination.page;
|
|
182
|
+
const skip = (page - 1) * pageSize;
|
|
183
|
+
const whereClause = {};
|
|
184
|
+
if (conversationId) {
|
|
185
|
+
whereClause['key.remote'] = conversationId;
|
|
186
|
+
}
|
|
187
|
+
if (searchParams.keywords) {
|
|
188
|
+
whereClause['message.conversationMessage.text'] = {
|
|
189
|
+
contains: searchParams.keywords,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
if (searchParams.dateFrom || searchParams.dateTo) {
|
|
193
|
+
whereClause['timestamp'] = {};
|
|
194
|
+
if (searchParams.dateFrom) {
|
|
195
|
+
const fromTimestamp = new Date(searchParams.dateFrom).getTime() / 1000;
|
|
196
|
+
whereClause['timestamp']['gte'] = fromTimestamp;
|
|
197
|
+
}
|
|
198
|
+
if (searchParams.dateTo) {
|
|
199
|
+
const toTimestamp = new Date(searchParams.dateTo).getTime() / 1000;
|
|
200
|
+
whereClause['timestamp']['lte'] = toTimestamp;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const body = {
|
|
204
|
+
where: whereClause,
|
|
205
|
+
take: pageSize,
|
|
206
|
+
skip: skip,
|
|
207
|
+
orderBy: {
|
|
208
|
+
timestamp: 'desc',
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
const responseData = await executeFunctions.helpers.httpRequest({
|
|
212
|
+
method: 'POST',
|
|
213
|
+
url: `/chat/findMessages/${instanceName}`,
|
|
214
|
+
body,
|
|
215
|
+
});
|
|
216
|
+
const messages = responseData.messages || responseData;
|
|
217
|
+
const total = messages.total || messages.length || 0;
|
|
218
|
+
const totalPages = Math.ceil(total / pageSize);
|
|
219
|
+
const result = {
|
|
220
|
+
total,
|
|
221
|
+
pages: totalPages,
|
|
222
|
+
currentPage: page,
|
|
223
|
+
pageSize,
|
|
224
|
+
records: Array.isArray(messages.records) ? messages.records : messages,
|
|
225
|
+
};
|
|
226
|
+
returnData.push({
|
|
227
|
+
json: result,
|
|
228
|
+
pairedItem: { item: i },
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
return [returnData];
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
exports.SearchMessages = SearchMessages;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"node": "n8n-nodes-evolution-message-search",
|
|
3
|
+
"nodeVersion": "1.0",
|
|
4
|
+
"codexVersion": "1.0",
|
|
5
|
+
"categories": [
|
|
6
|
+
"Communication"
|
|
7
|
+
],
|
|
8
|
+
"resources": {
|
|
9
|
+
"credentialDocumentation": [
|
|
10
|
+
{
|
|
11
|
+
"url": "https://docs.evolutionfoundation.com.br/evolution-api"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"primaryDocumentation": [
|
|
15
|
+
{
|
|
16
|
+
"url": "https://docs.evolutionfoundation.com.br/evolution-api"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
|
|
2
|
+
<rect width="64" height="64" rx="8" fill="#25D366"/>
|
|
3
|
+
<path d="M32 16c-8.837 0-16 7.163-16 16 0 6.626 4.134 12.318 10 14.706V44l6.19-3.416c2.206.611 4.54.92 6.81.92 8.837 0 16-7.163 16-16S40.837 16 32 16zm0 30c-2.21 0-4.383-.44-6.4-1.23l-.46-.17-4.89 2.7 2.75-4.77-.27-.46C20.52 40.36 18 36.29 18 32c0-7.732 6.268-14 14-14s14 6.268 14 14-6.268 14-14 14z" fill="white"/>
|
|
4
|
+
<path d="M26 28h4v4h-4v-4zm6 0h4v4h-4v-4zm6 0h4v4h-4v-4z" fill="white"/>
|
|
5
|
+
</svg>
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "n8n-nodes-evolution-message-search",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Evolution API - Search Messages node for n8n. Search WhatsApp message history by keywords, dates, and conversation.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"n8n-community-node-package",
|
|
7
|
+
"evolution-api",
|
|
8
|
+
"whatsapp",
|
|
9
|
+
"message-search"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"homepage": "https://github.com/joaoramos/n8n-nodes-evolution-message-search",
|
|
13
|
+
"author": {
|
|
14
|
+
"name": "Joao Ramos"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/joaoramos/n8n-nodes-evolution-message-search.git"
|
|
19
|
+
},
|
|
20
|
+
"main": "index.js",
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"lint": "tsc --noEmit"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"n8n": {
|
|
29
|
+
"n8nNodesApiVersion": 1,
|
|
30
|
+
"credentials": [
|
|
31
|
+
"dist/credentials/EvolutionApi.credentials.js"
|
|
32
|
+
],
|
|
33
|
+
"nodes": [
|
|
34
|
+
"dist/nodes/SearchMessages/SearchMessages.node.js"
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^18.17.0",
|
|
39
|
+
"typescript": "^5.3.0"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"n8n": ">=1.0.0"
|
|
43
|
+
}
|
|
44
|
+
}
|