UNPKG

n8n-nodes-duckduckgo-search

Version:

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.

194 lines (193 loc) 8.12 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.fallbackVideoSearch = exports.fallbackNewsSearch = exports.fallbackImageSearch = exports.fallbackWebSearch = exports.searchVideosWithFallback = exports.searchNewsWithFallback = exports.searchWithFallback = void 0; const duck_duck_scrape_1 = require("duck-duck-scrape"); const apiClient_1 = require("./apiClient"); const axios_1 = __importDefault(require("axios")); async function searchWithFallback(query, options = {}) { try { const result = await (0, duck_duck_scrape_1.search)(query, options); if (result && result.results && result.results.length > 0) { return result; } console.warn('Duck-duck-scrape returned no results, falling back to SearchAPI'); return await (0, apiClient_1.searchWithAPI)(query, options); } catch (error) { console.warn(`Duck-duck-scrape failed: ${error.message}, falling back to SearchAPI`); try { return await (0, apiClient_1.searchWithAPI)(query, options); } catch (fallbackError) { throw new Error(`Both search methods failed. SearchAPI error: ${fallbackError.message}`); } } } exports.searchWithFallback = searchWithFallback; async function searchNewsWithFallback(query, options = {}) { try { const result = await (0, duck_duck_scrape_1.searchNews)(query, options); if (result && result.results && result.results.length > 0) { return result; } console.warn('Duck-duck-scrape news returned no results, falling back to SearchAPI'); return await (0, apiClient_1.searchNewsWithAPI)(query, options); } catch (error) { console.warn(`Duck-duck-scrape news failed: ${error.message}, falling back to SearchAPI`); try { return await (0, apiClient_1.searchNewsWithAPI)(query, options); } catch (fallbackError) { throw new Error(`Both news search methods failed. SearchAPI error: ${fallbackError.message}`); } } } exports.searchNewsWithFallback = searchNewsWithFallback; async function searchVideosWithFallback(query, options = {}) { try { const result = await (0, duck_duck_scrape_1.searchVideos)(query, options); if (result && result.results && result.results.length > 0) { return result; } console.warn('Duck-duck-scrape videos returned no results, falling back to SearchAPI'); return await (0, apiClient_1.searchVideosWithAPI)(query, options); } catch (error) { console.warn(`Duck-duck-scrape videos failed: ${error.message}, falling back to SearchAPI`); try { return await (0, apiClient_1.searchVideosWithAPI)(query, options); } catch (fallbackError) { throw new Error(`Both video search methods failed. SearchAPI error: ${fallbackError.message}`); } } } exports.searchVideosWithFallback = searchVideosWithFallback; function parseSearchResultsFromHTML(html) { const results = []; const resultRegex = /<div[^>]*class="[^"]*result[^"]*"[^>]*>([\s\S]*?)<\/div>/gi; const titleRegex = /<a[^>]*class="[^"]*result__a[^"]*"[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/i; const snippetRegex = /<[^>]*class="[^"]*result__snippet[^"]*"[^>]*>(.*?)<\/[^>]*>/i; let match; while ((match = resultRegex.exec(html)) !== null) { const resultHTML = match[1]; const titleMatch = titleRegex.exec(resultHTML); const snippetMatch = snippetRegex.exec(resultHTML); if (titleMatch) { const href = titleMatch[1]; const title = titleMatch[2].replace(/<[^>]*>/g, '').trim(); const body = snippetMatch ? snippetMatch[1].replace(/<[^>]*>/g, '').trim() : ''; if (title && href) { results.push({ title: cleanText(title), href: href.startsWith('http') ? href : `https://${href}`, body: cleanText(body), }); } } } return results; } function cleanText(text) { return text .replace(/&nbsp;/g, ' ') .replace(/&amp;/g, '&') .replace(/&lt;/g, '<') .replace(/&gt;/g, '>') .replace(/&quot;/g, '"') .replace(/&#39;/g, "'") .replace(/\s+/g, ' ') .trim(); } async function fallbackWebSearch(query, options = {}) { try { const searchUrl = 'https://html.duckduckgo.com/html/'; const params = new URLSearchParams({ q: query, kl: options.locale || 'us-en', s: String(options.safeSearch || 'moderate'), df: options.time || '', }); const response = await axios_1.default.get(`${searchUrl}?${params.toString()}`, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip, deflate, br', 'DNT': '1', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1', }, timeout: 10000, }); const results = parseSearchResultsFromHTML(response.data); const noResultsIndicator = response.data.includes('no-results') || results.length === 0; return { success: true, noResults: noResultsIndicator, results, }; } catch (error) { console.error('Fallback search error:', error); return { success: false, noResults: true, results: [], error: `Fallback search failed: ${error instanceof Error ? error.message : 'Unknown error'}`, }; } } exports.fallbackWebSearch = fallbackWebSearch; async function fallbackImageSearch(query, options = {}) { try { const imageQuery = `${query} images photos pictures`; return await fallbackWebSearch(imageQuery, options); } catch (error) { console.error('Fallback image search error:', error); return { success: false, noResults: true, results: [], error: `Fallback image search failed: ${error instanceof Error ? error.message : 'Unknown error'}`, }; } } exports.fallbackImageSearch = fallbackImageSearch; async function fallbackNewsSearch(query, options = {}) { try { const newsQuery = `${query} site:news.com OR site:bbc.com OR site:cnn.com OR site:reuters.com`; return await fallbackWebSearch(newsQuery, options); } catch (error) { console.error('Fallback news search error:', error); return { success: false, noResults: true, results: [], error: `Fallback news search failed: ${error instanceof Error ? error.message : 'Unknown error'}`, }; } } exports.fallbackNewsSearch = fallbackNewsSearch; async function fallbackVideoSearch(query, options = {}) { try { const videoQuery = `${query} site:youtube.com OR site:vimeo.com OR site:dailymotion.com`; return await fallbackWebSearch(videoQuery, options); } catch (error) { console.error('Fallback video search error:', error); return { success: false, noResults: true, results: [], error: `Fallback video search failed: ${error instanceof Error ? error.message : 'Unknown error'}`, }; } } exports.fallbackVideoSearch = fallbackVideoSearch;