n8n-nodes-evolution-message-search 2.0.1 → 2.0.3

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.
@@ -4,7 +4,71 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
  exports.SearchMessages = void 0;
5
5
 
6
6
  const n8n_workflow_1 = require('n8n-workflow');
7
- const core_tools_1 = require('@langchain/core/tools');
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
+ }
8
72
 
9
73
  class SearchMessages {
10
74
  constructor() {
@@ -19,9 +83,9 @@ class SearchMessages {
19
83
  defaults: {
20
84
  name: 'Evolution API - Search Messages',
21
85
  },
22
- inputs: [],
23
- outputs: [n8n_workflow_1.NodeConnectionTypes.AiTool],
24
- outputNames: ['Tool'],
86
+ usableAsTool: true,
87
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
88
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
25
89
  credentials: [
26
90
  {
27
91
  name: 'evolutionApi',
@@ -43,7 +107,7 @@ class SearchMessages {
43
107
  type: 'string',
44
108
  required: false,
45
109
  default: '',
46
- description: 'WhatsApp conversation ID (JID). If empty, searches all conversations. Model can set if allowed.',
110
+ description: 'WhatsApp conversation ID (JID). If empty, searches all conversations.',
47
111
  placeholder: '5511999999999@s.whatsapp.net',
48
112
  },
49
113
  {
@@ -51,7 +115,33 @@ class SearchMessages {
51
115
  name: 'allowModelSetConversation',
52
116
  type: 'boolean',
53
117
  default: false,
54
- description: 'If enabled, the AI model can set the conversation ID',
118
+ description: 'If enabled, the AI model can set the conversation ID via $fromAI()',
119
+ },
120
+ {
121
+ displayName: 'Keywords',
122
+ name: 'keywords',
123
+ type: 'string',
124
+ required: false,
125
+ default: '',
126
+ description: 'Search text in message content (model can set)',
127
+ },
128
+ {
129
+ displayName: 'Date From',
130
+ name: 'dateFrom',
131
+ type: 'string',
132
+ required: false,
133
+ default: '',
134
+ description: 'Start date for message search (model can set)',
135
+ placeholder: '2024-01-01T00:00:00Z',
136
+ },
137
+ {
138
+ displayName: 'Date To',
139
+ name: 'dateTo',
140
+ type: 'string',
141
+ required: false,
142
+ default: '',
143
+ description: 'End date for message search (model can set)',
144
+ placeholder: '2024-12-31T23:59:59Z',
55
145
  },
56
146
  {
57
147
  displayName: 'Items per Page',
@@ -64,88 +154,41 @@ class SearchMessages {
64
154
  },
65
155
  description: 'Number of results per page (defined by user, model cannot change)',
66
156
  },
157
+ {
158
+ displayName: 'Page Number',
159
+ name: 'page',
160
+ type: 'number',
161
+ default: 1,
162
+ typeOptions: {
163
+ minValue: 1,
164
+ },
165
+ description: 'Page number to retrieve (model can navigate)',
166
+ },
67
167
  ],
68
168
  };
69
169
  }
70
170
 
71
- async supplyData(itemIndex) {
72
- const credentials = await this.getCredentials('evolutionApi');
73
- const serverUrl = credentials['server-url'];
74
- const apiKey = credentials.apikey;
75
- const instanceName = this.getNodeParameter('instanceName', itemIndex);
76
- const userConversationId = this.getNodeParameter('conversationId', itemIndex) || '';
77
- const allowModelSetConversation = this.getNodeParameter('allowModelSetConversation', itemIndex);
78
- const pageSizeDefault = this.getNodeParameter('pageSize', itemIndex) || 10;
79
- const ctx = this;
80
-
81
- const tool = new core_tools_1.DynamicTool({
82
- name: n8n_workflow_1.nodeNameToToolName(this.getNode()),
83
- description: 'Search WhatsApp message history. Input must be a JSON object with: keywords (string, optional), dateFrom (ISO date string, optional), dateTo (ISO date string, optional), page (number, default 1), pageSize (number, default 10), conversationId (string, optional). Returns paginated message search results.',
84
- func: async (input) => {
85
- const params = typeof input === 'string' ? JSON.parse(input) : (input || {});
86
- let conversationId = userConversationId;
87
- if (!conversationId && allowModelSetConversation && params.conversationId) {
88
- conversationId = params.conversationId;
89
- }
90
- const keywords = params.keywords || '';
91
- const dateFrom = params.dateFrom || '';
92
- const dateTo = params.dateTo || '';
93
- const pageSize = params.pageSize || pageSizeDefault;
94
- const page = params.page || 1;
95
- const skip = (page - 1) * pageSize;
96
-
97
- const whereClause = {};
98
- if (conversationId) {
99
- whereClause['key.remote'] = conversationId;
100
- }
101
- if (keywords) {
102
- whereClause['message.conversationMessage.text'] = { contains: keywords };
103
- }
104
- if (dateFrom || dateTo) {
105
- whereClause['timestamp'] = {};
106
- if (dateFrom) {
107
- whereClause['timestamp']['gte'] = new Date(dateFrom).getTime() / 1000;
108
- }
109
- if (dateTo) {
110
- whereClause['timestamp']['lte'] = new Date(dateTo).getTime() / 1000;
111
- }
112
- }
171
+ async execute() {
172
+ const items = typeof this.getInputData === 'function' ? this.getInputData() : [];
173
+ const returnData = [];
174
+ const max = items.length > 0 ? items.length : 1;
113
175
 
114
- const body = {
115
- where: whereClause,
116
- take: pageSize,
117
- skip: skip,
118
- orderBy: { timestamp: 'desc' },
119
- };
120
-
121
- const cleanUrl = serverUrl.replace(/\/$/, '');
122
- const response = await ctx.helpers.request({
123
- method: 'POST',
124
- uri: `${cleanUrl}/chat/findMessages/${instanceName}`,
125
- body,
126
- headers: {
127
- 'Content-Type': 'application/json',
128
- Accept: 'application/json',
129
- apikey: apiKey,
130
- },
131
- json: true,
176
+ for (let itemIndex = 0; itemIndex < max; itemIndex++) {
177
+ try {
178
+ const result = await performSearch(this, itemIndex);
179
+ returnData.push({
180
+ json: result,
181
+ pairedItem: { item: itemIndex },
132
182
  });
133
-
134
- const messages = response.messages || response;
135
- const total = messages.total || messages.length || 0;
136
- const totalPages = Math.ceil(total / pageSize);
137
-
138
- return JSON.stringify({
139
- total,
140
- pages: totalPages,
141
- currentPage: page,
142
- pageSize,
143
- records: Array.isArray(messages.records) ? messages.records : messages,
183
+ } catch (err) {
184
+ returnData.push({
185
+ json: { error: err.message },
186
+ pairedItem: { item: itemIndex },
144
187
  });
145
- },
146
- });
188
+ }
189
+ }
147
190
 
148
- return { response: tool };
191
+ return [returnData];
149
192
  }
150
193
  }
151
194
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-evolution-message-search",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
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",
@@ -24,7 +24,6 @@
24
24
  ]
25
25
  },
26
26
  "peerDependencies": {
27
- "n8n-workflow": "*",
28
- "@langchain/core": "*"
27
+ "n8n-workflow": "*"
29
28
  }
30
29
  }