n8n-nodes-duckduckgo-search 30.0.3 → 30.0.5
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 +1 -1
- package/dist/nodes/DuckDuckGo/DuckDuckGo.node.js +1 -11
- package/dist/nodes/DuckDuckGo/apiClient.js +3 -1
- package/dist/nodes/DuckDuckGo/constants.js +2 -1
- package/dist/nodes/DuckDuckGo/directSearch.js +53 -20
- package/dist/nodes/DuckDuckGo/fallbackSearch.js +2 -1
- package/dist/nodes/DuckDuckGo/multiBackendSearch.js +3 -2
- package/dist/package.json +1 -2
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# DuckDuckGo Search Node for n8n
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/n8n-nodes-duckduckgo-search)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
|
|
6
6
|
A powerful and comprehensive n8n community node that seamlessly integrates DuckDuckGo search capabilities into your workflows. Search the web, find images, discover news, and explore videos - all with privacy-focused, reliable results.
|
|
@@ -59,16 +59,6 @@ const LOCALE_OPTIONS = [
|
|
|
59
59
|
function sleep(ms) {
|
|
60
60
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
61
61
|
}
|
|
62
|
-
function getRandomUserAgent() {
|
|
63
|
-
const userAgents = [
|
|
64
|
-
'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1',
|
|
65
|
-
'Mozilla/5.0 (Linux; Android 11; SM-G998U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.98 Mobile Safari/537.36',
|
|
66
|
-
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36',
|
|
67
|
-
'Mozilla/5.0 (Macintosh; Intel Mac OS X 12_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15',
|
|
68
|
-
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/117.0',
|
|
69
|
-
];
|
|
70
|
-
return userAgents[Math.floor(Math.random() * userAgents.length)];
|
|
71
|
-
}
|
|
72
62
|
function getSafeSearchType(value) {
|
|
73
63
|
switch (value) {
|
|
74
64
|
case 0:
|
|
@@ -1211,7 +1201,7 @@ class DuckDuckGo {
|
|
|
1211
1201
|
url: htmlUrl,
|
|
1212
1202
|
method: 'GET',
|
|
1213
1203
|
headers: {
|
|
1214
|
-
'User-Agent':
|
|
1204
|
+
'User-Agent': constants_1.BROWSER_USER_AGENT,
|
|
1215
1205
|
},
|
|
1216
1206
|
});
|
|
1217
1207
|
const page = parseHtmlResults(html);
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.searchVideosWithAPI = exports.searchNewsWithAPI = exports.searchImagesWithAPI = exports.searchWithAPI = exports.SearchAPIClient = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const constants_1 = require("./constants");
|
|
8
9
|
class SearchAPIClient {
|
|
9
10
|
constructor(apiKey) {
|
|
10
11
|
this.baseUrl = 'https://www.searchapi.io/api/v1/search';
|
|
@@ -30,7 +31,8 @@ class SearchAPIClient {
|
|
|
30
31
|
const headers = {
|
|
31
32
|
'Authorization': `Bearer ${this.apiKey}`,
|
|
32
33
|
'Content-Type': 'application/json',
|
|
33
|
-
'User-Agent':
|
|
34
|
+
'User-Agent': constants_1.BROWSER_USER_AGENT,
|
|
35
|
+
'Accept': 'application/json',
|
|
34
36
|
};
|
|
35
37
|
try {
|
|
36
38
|
const response = await axios_1.default.get(url.toString(), {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NODE_INFO = exports.DEFAULT_PARAMETERS = exports.REGIONS = void 0;
|
|
3
|
+
exports.BROWSER_USER_AGENT = exports.NODE_INFO = exports.DEFAULT_PARAMETERS = exports.REGIONS = void 0;
|
|
4
4
|
exports.REGIONS = [
|
|
5
5
|
{ name: 'Argentina', value: 'ar-es' },
|
|
6
6
|
{ name: 'Australia', value: 'au-en' },
|
|
@@ -63,3 +63,4 @@ exports.NODE_INFO = {
|
|
|
63
63
|
VERSION: 1,
|
|
64
64
|
DESCRIPTION: 'Search using DuckDuckGo',
|
|
65
65
|
};
|
|
66
|
+
exports.BROWSER_USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36';
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getSafeSearchString = exports.directImageSearch = exports.directWebSearch = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const constants_1 = require("./constants");
|
|
8
9
|
function cleanText(text) {
|
|
9
10
|
return text
|
|
10
11
|
.replace(/ /g, ' ')
|
|
@@ -28,7 +29,7 @@ async function directWebSearch(query, options = {}) {
|
|
|
28
29
|
kp: options.safeSearch === 'strict' ? '1' : options.safeSearch === 'moderate' ? '-1' : '-2',
|
|
29
30
|
}), {
|
|
30
31
|
headers: {
|
|
31
|
-
'User-Agent':
|
|
32
|
+
'User-Agent': constants_1.BROWSER_USER_AGENT,
|
|
32
33
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
33
34
|
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
|
34
35
|
'Accept-Language': 'en-US,en;q=0.9',
|
|
@@ -36,7 +37,7 @@ async function directWebSearch(query, options = {}) {
|
|
|
36
37
|
'Cache-Control': 'no-cache',
|
|
37
38
|
'Pragma': 'no-cache',
|
|
38
39
|
},
|
|
39
|
-
timeout:
|
|
40
|
+
timeout: 15000,
|
|
40
41
|
});
|
|
41
42
|
const results = [];
|
|
42
43
|
const html = response.data;
|
|
@@ -64,8 +65,22 @@ async function directWebSearch(query, options = {}) {
|
|
|
64
65
|
return { results };
|
|
65
66
|
}
|
|
66
67
|
catch (error) {
|
|
67
|
-
console.error('Direct web search error:', error);
|
|
68
|
-
|
|
68
|
+
console.error('Direct web search error:', error.message);
|
|
69
|
+
if (error.code === 'ECONNABORTED') {
|
|
70
|
+
throw new Error('Web search request timed out. Please try again.');
|
|
71
|
+
}
|
|
72
|
+
else if (error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED') {
|
|
73
|
+
throw new Error('Unable to connect to DuckDuckGo. Please check your internet connection.');
|
|
74
|
+
}
|
|
75
|
+
else if (error.response && error.response.status === 429) {
|
|
76
|
+
throw new Error('Too many requests. Please wait a moment before trying again.');
|
|
77
|
+
}
|
|
78
|
+
else if (error.response && error.response.status >= 500) {
|
|
79
|
+
throw new Error('DuckDuckGo server error. Please try again later.');
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
throw new Error(`Web search failed: ${error.message}`);
|
|
83
|
+
}
|
|
69
84
|
}
|
|
70
85
|
}
|
|
71
86
|
exports.directWebSearch = directWebSearch;
|
|
@@ -79,12 +94,12 @@ async function directImageSearch(query, options = {}) {
|
|
|
79
94
|
const searchUrl = `https://duckduckgo.com/?${searchParams.toString()}`;
|
|
80
95
|
const response = await axios_1.default.get(searchUrl, {
|
|
81
96
|
headers: {
|
|
82
|
-
'User-Agent':
|
|
97
|
+
'User-Agent': constants_1.BROWSER_USER_AGENT,
|
|
83
98
|
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
|
84
99
|
'Accept-Language': 'en-US,en;q=0.9',
|
|
85
100
|
'Accept-Encoding': 'gzip, deflate, br',
|
|
86
101
|
},
|
|
87
|
-
timeout:
|
|
102
|
+
timeout: 15000,
|
|
88
103
|
});
|
|
89
104
|
const vqdMatch = response.data.match(/vqd=([\d-]+)/);
|
|
90
105
|
const vqd = vqdMatch ? vqdMatch[1] : null;
|
|
@@ -109,14 +124,14 @@ async function directImageSearch(query, options = {}) {
|
|
|
109
124
|
});
|
|
110
125
|
const imageResponse = await axios_1.default.get(`https://duckduckgo.com/i.js?${imageParams.toString()}`, {
|
|
111
126
|
headers: {
|
|
112
|
-
'User-Agent':
|
|
127
|
+
'User-Agent': constants_1.BROWSER_USER_AGENT,
|
|
113
128
|
'Accept': 'application/json, text/javascript, */*; q=0.01',
|
|
114
129
|
'Accept-Language': 'en-US,en;q=0.9',
|
|
115
130
|
'Accept-Encoding': 'gzip, deflate, br',
|
|
116
131
|
'Referer': searchUrl,
|
|
117
132
|
'X-Requested-With': 'XMLHttpRequest',
|
|
118
133
|
},
|
|
119
|
-
timeout:
|
|
134
|
+
timeout: 15000,
|
|
120
135
|
});
|
|
121
136
|
const imageData = imageResponse.data;
|
|
122
137
|
const results = [];
|
|
@@ -138,25 +153,43 @@ async function directImageSearch(query, options = {}) {
|
|
|
138
153
|
return { results };
|
|
139
154
|
}
|
|
140
155
|
catch (error) {
|
|
141
|
-
console.error('Direct image search error:', error);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
156
|
+
console.error('Direct image search error:', error.message);
|
|
157
|
+
try {
|
|
158
|
+
console.log('Falling back to web search for image content...');
|
|
159
|
+
const webResults = await directWebSearch(`${query} images photos pictures`, options);
|
|
160
|
+
return {
|
|
161
|
+
results: webResults.results.map(result => ({
|
|
162
|
+
title: result.title,
|
|
163
|
+
url: result.url,
|
|
164
|
+
thumbnail: '',
|
|
165
|
+
source: result.url,
|
|
166
|
+
})),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
catch (fallbackError) {
|
|
170
|
+
if (error.code === 'ECONNABORTED') {
|
|
171
|
+
throw new Error('Image search request timed out. Please try again.');
|
|
172
|
+
}
|
|
173
|
+
else if (error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED') {
|
|
174
|
+
throw new Error('Unable to connect to DuckDuckGo for image search. Please check your internet connection.');
|
|
175
|
+
}
|
|
176
|
+
else if (error.response && error.response.status === 429) {
|
|
177
|
+
throw new Error('Too many image search requests. Please wait a moment before trying again.');
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
throw new Error(`Image search failed: ${error.message}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
151
183
|
}
|
|
152
184
|
}
|
|
153
185
|
exports.directImageSearch = directImageSearch;
|
|
154
186
|
function getSafeSearchString(value) {
|
|
155
187
|
switch (value) {
|
|
156
|
-
case
|
|
188
|
+
case 0:
|
|
157
189
|
return 'strict';
|
|
158
|
-
case 1:
|
|
190
|
+
case -1:
|
|
159
191
|
return 'moderate';
|
|
192
|
+
case -2:
|
|
160
193
|
default:
|
|
161
194
|
return 'off';
|
|
162
195
|
}
|
|
@@ -7,6 +7,7 @@ exports.fallbackVideoSearch = exports.fallbackNewsSearch = exports.fallbackImage
|
|
|
7
7
|
const duck_duck_scrape_1 = require("duck-duck-scrape");
|
|
8
8
|
const apiClient_1 = require("./apiClient");
|
|
9
9
|
const axios_1 = __importDefault(require("axios"));
|
|
10
|
+
const constants_1 = require("./constants");
|
|
10
11
|
async function searchWithFallback(query, options = {}) {
|
|
11
12
|
try {
|
|
12
13
|
const result = await (0, duck_duck_scrape_1.search)(query, options);
|
|
@@ -114,7 +115,7 @@ async function fallbackWebSearch(query, options = {}) {
|
|
|
114
115
|
});
|
|
115
116
|
const response = await axios_1.default.get(`${searchUrl}?${params.toString()}`, {
|
|
116
117
|
headers: {
|
|
117
|
-
'User-Agent':
|
|
118
|
+
'User-Agent': constants_1.BROWSER_USER_AGENT,
|
|
118
119
|
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
|
119
120
|
'Accept-Language': 'en-US,en;q=0.5',
|
|
120
121
|
'Accept-Encoding': 'gzip, deflate, br',
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.multiBackendSearch = exports.MultiBackendDuckDuckGoSearch = exports.Backend = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const constants_1 = require("./constants");
|
|
8
9
|
const duck_duck_scrape_1 = require("duck-duck-scrape");
|
|
9
10
|
const apiClient_1 = require("./apiClient");
|
|
10
11
|
var Backend;
|
|
@@ -191,7 +192,7 @@ class MultiBackendDuckDuckGoSearch {
|
|
|
191
192
|
}), {
|
|
192
193
|
headers: {
|
|
193
194
|
'Referer': 'https://html.duckduckgo.com/',
|
|
194
|
-
'User-Agent':
|
|
195
|
+
'User-Agent': constants_1.BROWSER_USER_AGENT,
|
|
195
196
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
196
197
|
},
|
|
197
198
|
timeout: 15000
|
|
@@ -218,7 +219,7 @@ class MultiBackendDuckDuckGoSearch {
|
|
|
218
219
|
}), {
|
|
219
220
|
headers: {
|
|
220
221
|
'Referer': 'https://lite.duckduckgo.com/',
|
|
221
|
-
'User-Agent':
|
|
222
|
+
'User-Agent': constants_1.BROWSER_USER_AGENT,
|
|
222
223
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
223
224
|
},
|
|
224
225
|
timeout: 15000
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-duckduckgo-search",
|
|
3
|
-
"version": "30.0.
|
|
3
|
+
"version": "30.0.5",
|
|
4
4
|
"description": "A powerful and comprehensive n8n community node that seamlessly integrates DuckDuckGo search capabilities into your workflows. Search the web, find images, discover news, and explore videos - all with privacy-focused, reliable results.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|
|
@@ -68,7 +68,6 @@
|
|
|
68
68
|
"@types/request-promise-native": "~1.0.15",
|
|
69
69
|
"@types/uuid": "^9.0.8",
|
|
70
70
|
"@typescript-eslint/parser": "~5.45",
|
|
71
|
-
"axios": "^1.9.0",
|
|
72
71
|
"babel-jest": "^29.7.0",
|
|
73
72
|
"copyfiles": "^2.4.1",
|
|
74
73
|
"eslint-plugin-n8n-nodes-base": "^1.11.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-duckduckgo-search",
|
|
3
|
-
"version": "30.0.
|
|
3
|
+
"version": "30.0.5",
|
|
4
4
|
"description": "A powerful and comprehensive n8n community node that seamlessly integrates DuckDuckGo search capabilities into your workflows. Search the web, find images, discover news, and explore videos - all with privacy-focused, reliable results.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|
|
@@ -68,7 +68,6 @@
|
|
|
68
68
|
"@types/request-promise-native": "~1.0.15",
|
|
69
69
|
"@types/uuid": "^9.0.8",
|
|
70
70
|
"@typescript-eslint/parser": "~5.45",
|
|
71
|
-
"axios": "^1.9.0",
|
|
72
71
|
"babel-jest": "^29.7.0",
|
|
73
72
|
"copyfiles": "^2.4.1",
|
|
74
73
|
"eslint-plugin-n8n-nodes-base": "^1.11.0",
|