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.

421 lines (420 loc) 15.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateSearchOperators = exports.parseSearchOperators = exports.buildSearchQuery = exports.OPERATOR_INFO = exports.SearchOperator = void 0; var SearchOperator; (function (SearchOperator) { SearchOperator["Site"] = "site:"; SearchOperator["Filetype"] = "filetype:"; SearchOperator["Intitle"] = "intitle:"; SearchOperator["Inurl"] = "inurl:"; SearchOperator["InBody"] = "inbody:"; SearchOperator["Cache"] = "cache:"; SearchOperator["Define"] = "define:"; SearchOperator["Related"] = "related:"; SearchOperator["Link"] = "link:"; SearchOperator["Ext"] = "ext:"; SearchOperator["Location"] = "location:"; SearchOperator["Region"] = "region:"; SearchOperator["Language"] = "language:"; SearchOperator["Feed"] = "feed:"; SearchOperator["HasFeed"] = "hasfeed:"; SearchOperator["IPAddress"] = "ip:"; SearchOperator["Prefer"] = "prefer:"; SearchOperator["AllInTitle"] = "allintitle:"; SearchOperator["AllInUrl"] = "allinurl:"; SearchOperator["AllInText"] = "allintext:"; SearchOperator["AllInAnchor"] = "allinanchor:"; })(SearchOperator = exports.SearchOperator || (exports.SearchOperator = {})); exports.OPERATOR_INFO = { site: { description: 'Search within a specific website or domain', example: 'site:example.com', placeholder: 'example.com', }, filetype: { description: 'Search for specific file types', example: 'filetype:pdf', placeholder: 'pdf, doc, xls, ppt, etc.', }, intitle: { description: 'Search for pages with specific words in the title', example: 'intitle:important', placeholder: 'words to find in title', }, inurl: { description: 'Search for pages with specific words in the URL', example: 'inurl:api', placeholder: 'words to find in URL', }, inbody: { description: 'Search for pages with specific words in the body text', example: 'inbody:content', placeholder: 'words to find in body', }, cache: { description: 'View the cached version of a webpage', example: 'cache:example.com', placeholder: 'example.com', }, define: { description: 'Get definitions for a word or phrase', example: 'define:quantum', placeholder: 'word to define', }, related: { description: 'Find websites related to a specific URL', example: 'related:example.com', placeholder: 'example.com', }, link: { description: 'Find pages that link to a specific URL', example: 'link:example.com', placeholder: 'example.com', }, ext: { description: 'Search for specific file extensions (alias for filetype)', example: 'ext:pdf', placeholder: 'pdf, doc, etc.', }, location: { description: 'Search for results from a specific location', example: 'location:"New York"', placeholder: 'city or country', }, region: { description: 'Search for results from a specific region', example: 'region:us', placeholder: 'country code', }, language: { description: 'Search for results in a specific language', example: 'language:en', placeholder: 'language code', }, feed: { description: 'Find RSS or Atom feeds', example: 'feed:blog', placeholder: 'feed keyword', }, hasfeed: { description: 'Find pages that have RSS or Atom feeds', example: 'hasfeed:news', placeholder: 'keyword', }, ip: { description: 'Search for information about an IP address', example: 'ip:192.168.1.1', placeholder: 'IP address', }, prefer: { description: 'Prefer newer or older results', example: 'prefer:newer', placeholder: 'newer or older', }, allintitle: { description: 'All words must appear in the title', example: 'allintitle:important news', placeholder: 'all words for title', }, allinurl: { description: 'All words must appear in the URL', example: 'allinurl:api docs', placeholder: 'all words for URL', }, allintext: { description: 'All words must appear in the text', example: 'allintext:complete guide', placeholder: 'all words for text', }, allinanchor: { description: 'All words must appear in anchor text', example: 'allinanchor:click here', placeholder: 'all words for anchors', }, exclude: { description: 'Exclude results containing specific words (use - prefix)', example: '-unwanted', placeholder: 'words to exclude', }, exact: { description: 'Search for exact phrase (use quotes)', example: '"exact phrase"', placeholder: 'exact phrase to match', }, or: { description: 'Search for any of the specified terms (use OR)', example: 'term1 OR term2', placeholder: 'alternative terms', }, }; function buildSearchQuery(baseQuery, operators) { if (!operators || Object.keys(operators).length === 0) { return baseQuery; } const queryParts = []; if (baseQuery.trim()) { queryParts.push(baseQuery); } if (operators.site) { queryParts.push(`site:${operators.site}`); } if (operators.filetype) { queryParts.push(`filetype:${operators.filetype}`); } if (operators.intitle) { queryParts.push(`intitle:${operators.intitle}`); } if (operators.inurl) { queryParts.push(`inurl:${operators.inurl}`); } if (operators.inbody) { queryParts.push(`inbody:${operators.inbody}`); } if (operators.cache) { queryParts.push(`cache:${operators.cache}`); } if (operators.define) { queryParts.push(`define:${operators.define}`); } if (operators.related) { queryParts.push(`related:${operators.related}`); } if (operators.link) { queryParts.push(`link:${operators.link}`); } if (operators.ext) { queryParts.push(`ext:${operators.ext}`); } if (operators.location) { const location = operators.location.includes(' ') ? `"${operators.location}"` : operators.location; queryParts.push(`location:${location}`); } if (operators.region) { queryParts.push(`region:${operators.region}`); } if (operators.language) { queryParts.push(`language:${operators.language}`); } if (operators.feed) { queryParts.push(`feed:${operators.feed}`); } if (operators.hasfeed) { queryParts.push(`hasfeed:${operators.hasfeed}`); } if (operators.ip) { queryParts.push(`ip:${operators.ip}`); } if (operators.prefer) { queryParts.push(`prefer:${operators.prefer}`); } if (operators.allintitle) { queryParts.push(`allintitle:${operators.allintitle}`); } if (operators.allinurl) { queryParts.push(`allinurl:${operators.allinurl}`); } if (operators.allintext) { queryParts.push(`allintext:${operators.allintext}`); } if (operators.allinanchor) { queryParts.push(`allinanchor:${operators.allinanchor}`); } if (operators.exclude) { const exclusions = operators.exclude.split(',').map(e => e.trim()); exclusions.forEach(exclusion => { if (exclusion && !exclusion.startsWith('-')) { queryParts.push(`-${exclusion}`); } else if (exclusion) { queryParts.push(exclusion); } }); } if (operators.exact) { const exactPhrase = operators.exact.trim(); if (exactPhrase && !exactPhrase.startsWith('"')) { queryParts.push(`"${exactPhrase}"`); } else if (exactPhrase) { queryParts.push(exactPhrase); } } if (operators.or && operators.or.length > 0) { const orQuery = operators.or.filter(term => term.trim()).join(' OR '); if (orQuery) { queryParts.push(`(${orQuery})`); } } return queryParts.join(' '); } exports.buildSearchQuery = buildSearchQuery; function parseSearchOperators(query) { const operators = {}; const removals = []; const markForRemoval = (startIndex, length) => { removals.push({ start: startIndex, end: startIndex + length }); }; const operatorRegex = /(\w+):("(?:[^"\\]|\\.)*"|\S+)/g; let match; while ((match = operatorRegex.exec(query)) !== null) { if (!match || !match[1] || !match[2]) continue; const [fullMatch, operator, value] = match; const cleanValue = value.replace(/^"|"$/g, ''); switch (operator.toLowerCase()) { case 'site': operators.site = cleanValue; break; case 'filetype': operators.filetype = cleanValue; break; case 'intitle': operators.intitle = cleanValue; break; case 'inurl': operators.inurl = cleanValue; break; case 'inbody': operators.inbody = cleanValue; break; case 'cache': operators.cache = cleanValue; break; case 'define': operators.define = cleanValue; break; case 'related': operators.related = cleanValue; break; case 'link': operators.link = cleanValue; break; case 'ext': operators.ext = cleanValue; break; case 'location': operators.location = cleanValue; break; case 'region': operators.region = cleanValue; break; case 'language': operators.language = cleanValue; break; case 'feed': operators.feed = cleanValue; break; case 'hasfeed': operators.hasfeed = cleanValue; break; case 'ip': operators.ip = cleanValue; break; case 'prefer': operators.prefer = cleanValue; break; case 'allintitle': operators.allintitle = cleanValue; break; case 'allinurl': operators.allinurl = cleanValue; break; case 'allintext': operators.allintext = cleanValue; break; case 'allinanchor': operators.allinanchor = cleanValue; break; } if (match.index !== undefined) { markForRemoval(match.index, fullMatch.length); } } const exclusions = []; const exclusionRegex = /(?:^|\s)-(\w+)(?=\s|$)/g; while ((match = exclusionRegex.exec(query)) !== null) { if (match && match[1] && match.index !== undefined) { exclusions.push(match[1]); markForRemoval(match.index, match[0].length); } } if (exclusions.length > 0) { operators.exclude = exclusions.join(', '); } const exactPhrases = []; const exactRegex = /"([^"]+)"/g; while ((match = exactRegex.exec(query)) !== null) { if (match && match[1] && match.index !== undefined) { const beforeIndex = match.index - 1; if (beforeIndex < 0 || query[beforeIndex] !== ':') { exactPhrases.push(match[1]); markForRemoval(match.index, match[0].length); } } } if (exactPhrases.length > 0) { operators.exact = exactPhrases.join(' '); } const orTerms = []; const orRegex = /(\w+)\s+OR\s+(\w+)/g; while ((match = orRegex.exec(query)) !== null) { if (match && match[1] && match[2] && match.index !== undefined) { orTerms.push(match[1], match[2]); markForRemoval(match.index, match[0].length); } } if (orTerms.length > 0) { operators.or = [...new Set(orTerms)]; } removals.sort((a, b) => b.start - a.start); const queryChars = query.split(''); removals.forEach(removal => { queryChars.splice(removal.start, removal.end - removal.start); }); let baseQuery = queryChars.join(''); baseQuery = baseQuery.replace(/\s+/g, ' ').trim(); return { baseQuery, operators }; } exports.parseSearchOperators = parseSearchOperators; function validateSearchOperators(operators) { const errors = []; if (operators.filetype) { const validFileTypes = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'rtf', 'odt', 'html', 'htm', 'xml', 'json', 'csv', 'zip', 'rar', '7z', 'tar', 'gz']; if (!validFileTypes.includes(operators.filetype.toLowerCase())) { errors.push(`Invalid filetype: ${operators.filetype}. Valid types: ${validFileTypes.join(', ')}`); } } if (operators.region) { const validRegions = ['us', 'uk', 'ca', 'au', 'de', 'fr', 'es', 'it', 'nl', 'br', 'mx', 'ar', 'in', 'jp', 'cn', 'kr', 'ru']; if (!validRegions.includes(operators.region.toLowerCase())) { errors.push(`Invalid region: ${operators.region}. Valid regions: ${validRegions.join(', ')}`); } } if (operators.language) { const validLanguages = ['en', 'es', 'fr', 'de', 'it', 'pt', 'nl', 'ru', 'ja', 'zh', 'ko', 'ar', 'hi', 'tr', 'pl', 'sv', 'da', 'no', 'fi']; if (!validLanguages.includes(operators.language.toLowerCase())) { errors.push(`Invalid language: ${operators.language}. Valid languages: ${validLanguages.join(', ')}`); } } if (operators.prefer && !['newer', 'older'].includes(operators.prefer.toLowerCase())) { errors.push(`Invalid prefer value: ${operators.prefer}. Use 'newer' or 'older'`); } if (operators.ip) { const ipRegex = /^(\d{1,3}\.){3}\d{1,3}$/; if (!ipRegex.test(operators.ip)) { errors.push(`Invalid IP address format: ${operators.ip}`); } else { const octets = operators.ip.split('.'); const invalidOctets = octets.filter(octet => { const num = parseInt(octet, 10); return num > 255; }); if (invalidOctets.length > 0) { errors.push(`Invalid IP address format: ${operators.ip}`); } } } return errors; } exports.validateSearchOperators = validateSearchOperators;