n8n-nodes-evolution-message-search 2.0.2 → 2.0.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.
|
@@ -5,6 +5,71 @@ exports.SearchMessages = void 0;
|
|
|
5
5
|
|
|
6
6
|
const n8n_workflow_1 = require('n8n-workflow');
|
|
7
7
|
|
|
8
|
+
async function performSearch(ctx, itemIndex) {
|
|
9
|
+
const credentials = await ctx.getCredentials('evolutionApi');
|
|
10
|
+
const serverUrl = credentials['server-url'];
|
|
11
|
+
const apiKey = credentials.apikey;
|
|
12
|
+
|
|
13
|
+
const instanceName = ctx.getNodeParameter('instanceName', itemIndex);
|
|
14
|
+
const userConversationId = ctx.getNodeParameter('conversationId', itemIndex) || '';
|
|
15
|
+
const keywords = ctx.getNodeParameter('keywords', itemIndex) || '';
|
|
16
|
+
const dateFrom = ctx.getNodeParameter('dateFrom', itemIndex) || '';
|
|
17
|
+
const dateTo = ctx.getNodeParameter('dateTo', itemIndex) || '';
|
|
18
|
+
const pageSize = ctx.getNodeParameter('pageSize', itemIndex) || 10;
|
|
19
|
+
const page = ctx.getNodeParameter('page', itemIndex) || 1;
|
|
20
|
+
|
|
21
|
+
const skip = (page - 1) * pageSize;
|
|
22
|
+
|
|
23
|
+
const whereClause = {};
|
|
24
|
+
if (userConversationId) {
|
|
25
|
+
whereClause['key.remote'] = userConversationId;
|
|
26
|
+
}
|
|
27
|
+
if (keywords) {
|
|
28
|
+
whereClause['message.conversationMessage.text'] = { contains: keywords };
|
|
29
|
+
}
|
|
30
|
+
if (dateFrom || dateTo) {
|
|
31
|
+
whereClause['timestamp'] = {};
|
|
32
|
+
if (dateFrom) {
|
|
33
|
+
whereClause['timestamp']['gte'] = new Date(dateFrom).getTime() / 1000;
|
|
34
|
+
}
|
|
35
|
+
if (dateTo) {
|
|
36
|
+
whereClause['timestamp']['lte'] = new Date(dateTo).getTime() / 1000;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const body = {
|
|
41
|
+
where: whereClause,
|
|
42
|
+
take: pageSize,
|
|
43
|
+
skip: skip,
|
|
44
|
+
orderBy: { timestamp: 'desc' },
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const cleanUrl = serverUrl.replace(/\/$/, '');
|
|
48
|
+
const response = await ctx.helpers.request({
|
|
49
|
+
method: 'POST',
|
|
50
|
+
uri: `${cleanUrl}/chat/findMessages/${instanceName}`,
|
|
51
|
+
body,
|
|
52
|
+
headers: {
|
|
53
|
+
'Content-Type': 'application/json',
|
|
54
|
+
Accept: 'application/json',
|
|
55
|
+
apikey: apiKey,
|
|
56
|
+
},
|
|
57
|
+
json: true,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const messages = response.messages || response;
|
|
61
|
+
const total = messages.total || messages.length || 0;
|
|
62
|
+
const totalPages = Math.ceil(total / pageSize);
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
total,
|
|
66
|
+
pages: totalPages,
|
|
67
|
+
currentPage: page,
|
|
68
|
+
pageSize,
|
|
69
|
+
records: Array.isArray(messages.records) ? messages.records : messages,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
8
73
|
class SearchMessages {
|
|
9
74
|
constructor() {
|
|
10
75
|
this.description = {
|
|
@@ -28,6 +93,16 @@ class SearchMessages {
|
|
|
28
93
|
},
|
|
29
94
|
],
|
|
30
95
|
properties: [
|
|
96
|
+
{
|
|
97
|
+
displayName: 'Tool Description',
|
|
98
|
+
name: 'toolDescription',
|
|
99
|
+
type: 'string',
|
|
100
|
+
typeOptions: {
|
|
101
|
+
rows: 4,
|
|
102
|
+
},
|
|
103
|
+
default: 'Search the WhatsApp message history of a conversation. ALL parameters are OPTIONAL except when explicitly needed:\n\n- Use ONLY keywords when user wants to find specific words/topics\n- Use ONLY dateFrom/dateTo when user asks about a time period (e.g. "last month", "yesterday")\n- Use BOTH keywords AND dates to combine topic search with time period\n- Use NONE when user wants recent messages (uses page 1)\n\nExamples:\n- "Did we talk about payment?" → use keywords="payment"\n- "What did we discuss last month?" → use dateFrom and dateTo only\n- "Anything about refund in January?" → use keywords="refund" + dateFrom/dateTo\n\nNavigation:\n- page: increase to see older messages (model can change)\n- pageSize: number of results per page (user-defined, do not change)',
|
|
104
|
+
description: 'Custom description shown to AI agent to help it understand how to use this tool',
|
|
105
|
+
},
|
|
31
106
|
{
|
|
32
107
|
displayName: 'Instance Name',
|
|
33
108
|
name: 'instanceName',
|
|
@@ -42,7 +117,7 @@ class SearchMessages {
|
|
|
42
117
|
type: 'string',
|
|
43
118
|
required: false,
|
|
44
119
|
default: '',
|
|
45
|
-
description: 'WhatsApp conversation ID (JID).
|
|
120
|
+
description: 'WhatsApp conversation ID (JID). Leave empty to search all conversations.',
|
|
46
121
|
placeholder: '5511999999999@s.whatsapp.net',
|
|
47
122
|
},
|
|
48
123
|
{
|
|
@@ -58,7 +133,8 @@ class SearchMessages {
|
|
|
58
133
|
type: 'string',
|
|
59
134
|
required: false,
|
|
60
135
|
default: '',
|
|
61
|
-
description: 'Search text in message content
|
|
136
|
+
description: 'OPTIONAL: Search text in message content. Leave empty to search by date only.',
|
|
137
|
+
placeholder: '={{ $fromAI("Keywords", "", "string") }}',
|
|
62
138
|
},
|
|
63
139
|
{
|
|
64
140
|
displayName: 'Date From',
|
|
@@ -66,8 +142,8 @@ class SearchMessages {
|
|
|
66
142
|
type: 'string',
|
|
67
143
|
required: false,
|
|
68
144
|
default: '',
|
|
69
|
-
description: 'Start date
|
|
70
|
-
placeholder: '
|
|
145
|
+
description: 'OPTIONAL: Start date (ISO format). Use when user mentions a time period. Leave empty to search all time.',
|
|
146
|
+
placeholder: '={{ $fromAI("Date_From", "", "string") }}',
|
|
71
147
|
},
|
|
72
148
|
{
|
|
73
149
|
displayName: 'Date To',
|
|
@@ -75,8 +151,8 @@ class SearchMessages {
|
|
|
75
151
|
type: 'string',
|
|
76
152
|
required: false,
|
|
77
153
|
default: '',
|
|
78
|
-
description: 'End date
|
|
79
|
-
placeholder: '
|
|
154
|
+
description: 'OPTIONAL: End date (ISO format). Use when user mentions a time period. Leave empty to search all time.',
|
|
155
|
+
placeholder: '={{ $fromAI("Date_To", "", "string") }}',
|
|
80
156
|
},
|
|
81
157
|
{
|
|
82
158
|
displayName: 'Items per Page',
|
|
@@ -97,102 +173,35 @@ class SearchMessages {
|
|
|
97
173
|
typeOptions: {
|
|
98
174
|
minValue: 1,
|
|
99
175
|
},
|
|
100
|
-
description: 'Page
|
|
176
|
+
description: 'Page to retrieve (model can navigate: increase to see older messages)',
|
|
177
|
+
placeholder: '={{ $fromAI("Page_Number", "1", "number") }}',
|
|
101
178
|
},
|
|
102
179
|
],
|
|
103
180
|
};
|
|
104
181
|
}
|
|
105
182
|
|
|
106
183
|
async execute() {
|
|
107
|
-
const items = this.getInputData ? this.getInputData() : [];
|
|
184
|
+
const items = typeof this.getInputData === 'function' ? this.getInputData() : [];
|
|
108
185
|
const returnData = [];
|
|
186
|
+
const max = items.length > 0 ? items.length : 1;
|
|
109
187
|
|
|
110
|
-
for (let itemIndex = 0; itemIndex <
|
|
188
|
+
for (let itemIndex = 0; itemIndex < max; itemIndex++) {
|
|
111
189
|
try {
|
|
112
|
-
const result = await
|
|
190
|
+
const result = await performSearch(this, itemIndex);
|
|
113
191
|
returnData.push({
|
|
114
192
|
json: result,
|
|
115
193
|
pairedItem: { item: itemIndex },
|
|
116
194
|
});
|
|
117
195
|
} catch (err) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
});
|
|
123
|
-
} else {
|
|
124
|
-
throw err;
|
|
125
|
-
}
|
|
196
|
+
returnData.push({
|
|
197
|
+
json: { error: err.message },
|
|
198
|
+
pairedItem: { item: itemIndex },
|
|
199
|
+
});
|
|
126
200
|
}
|
|
127
201
|
}
|
|
128
202
|
|
|
129
203
|
return [returnData];
|
|
130
204
|
}
|
|
131
|
-
|
|
132
|
-
async executeSingle(itemIndex) {
|
|
133
|
-
const credentials = await this.getCredentials('evolutionApi');
|
|
134
|
-
const serverUrl = credentials['server-url'];
|
|
135
|
-
const apiKey = credentials.apikey;
|
|
136
|
-
|
|
137
|
-
const instanceName = this.getNodeParameter('instanceName', itemIndex);
|
|
138
|
-
const userConversationId = this.getNodeParameter('conversationId', itemIndex) || '';
|
|
139
|
-
const keywords = this.getNodeParameter('keywords', itemIndex) || '';
|
|
140
|
-
const dateFrom = this.getNodeParameter('dateFrom', itemIndex) || '';
|
|
141
|
-
const dateTo = this.getNodeParameter('dateTo', itemIndex) || '';
|
|
142
|
-
const pageSize = this.getNodeParameter('pageSize', itemIndex) || 10;
|
|
143
|
-
const page = this.getNodeParameter('page', itemIndex) || 1;
|
|
144
|
-
|
|
145
|
-
const skip = (page - 1) * pageSize;
|
|
146
|
-
|
|
147
|
-
const whereClause = {};
|
|
148
|
-
if (userConversationId) {
|
|
149
|
-
whereClause['key.remote'] = userConversationId;
|
|
150
|
-
}
|
|
151
|
-
if (keywords) {
|
|
152
|
-
whereClause['message.conversationMessage.text'] = { contains: keywords };
|
|
153
|
-
}
|
|
154
|
-
if (dateFrom || dateTo) {
|
|
155
|
-
whereClause['timestamp'] = {};
|
|
156
|
-
if (dateFrom) {
|
|
157
|
-
whereClause['timestamp']['gte'] = new Date(dateFrom).getTime() / 1000;
|
|
158
|
-
}
|
|
159
|
-
if (dateTo) {
|
|
160
|
-
whereClause['timestamp']['lte'] = new Date(dateTo).getTime() / 1000;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const body = {
|
|
165
|
-
where: whereClause,
|
|
166
|
-
take: pageSize,
|
|
167
|
-
skip: skip,
|
|
168
|
-
orderBy: { timestamp: 'desc' },
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
const cleanUrl = serverUrl.replace(/\/$/, '');
|
|
172
|
-
const response = await this.helpers.request({
|
|
173
|
-
method: 'POST',
|
|
174
|
-
uri: `${cleanUrl}/chat/findMessages/${instanceName}`,
|
|
175
|
-
body,
|
|
176
|
-
headers: {
|
|
177
|
-
'Content-Type': 'application/json',
|
|
178
|
-
Accept: 'application/json',
|
|
179
|
-
apikey: apiKey,
|
|
180
|
-
},
|
|
181
|
-
json: true,
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
const messages = response.messages || response;
|
|
185
|
-
const total = messages.total || messages.length || 0;
|
|
186
|
-
const totalPages = Math.ceil(total / pageSize);
|
|
187
|
-
|
|
188
|
-
return {
|
|
189
|
-
total,
|
|
190
|
-
pages: totalPages,
|
|
191
|
-
currentPage: page,
|
|
192
|
-
pageSize,
|
|
193
|
-
records: Array.isArray(messages.records) ? messages.records : messages,
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
205
|
}
|
|
197
206
|
|
|
198
207
|
exports.SearchMessages = SearchMessages;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-evolution-message-search",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "Evolution API - Search Messages node for n8n. Search WhatsApp message history by keywords, dates, and conversation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|