From ae4c4e00aa627acb0fd882d0f784090f6efb42a7 Mon Sep 17 00:00:00 2001 From: Travis Fischer Date: Sun, 26 May 2024 15:41:18 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- legacy/readme.md | 3 +- legacy/src/services/index.ts | 1 + legacy/src/services/searxng-client.ts | 77 +++++++++++++++++++++++++++ legacy/src/utils.ts | 6 +-- legacy/tsconfig.json | 1 + 5 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 legacy/src/services/searxng-client.ts diff --git a/legacy/readme.md b/legacy/readme.md index 12d7f8bc..94b45d08 100644 --- a/legacy/readme.md +++ b/legacy/readme.md @@ -27,6 +27,7 @@ - perigon - predict leads - proxycurl +- searxng - serpapi - serper - twitter @@ -43,7 +44,7 @@ - walter - services - exa - need to update to correct format - - searxng + - wolfram alpha - wikipedia - midjourney - firecrawl diff --git a/legacy/src/services/index.ts b/legacy/src/services/index.ts index 38eb6612..32b1c9fb 100644 --- a/legacy/src/services/index.ts +++ b/legacy/src/services/index.ts @@ -7,6 +7,7 @@ export * from './perigon-client.js' export * from './predict-leads-client.js' export * from './proxycurl-client.js' export * from './scraper-client.js' +export * from './searxng-client.js' export * from './serpapi-client.js' export * from './serper-client.js' export * from './twitter-client.js' diff --git a/legacy/src/services/searxng-client.ts b/legacy/src/services/searxng-client.ts new file mode 100644 index 00000000..315fff67 --- /dev/null +++ b/legacy/src/services/searxng-client.ts @@ -0,0 +1,77 @@ +import defaultKy, { type KyInstance } from 'ky' + +import { assert, getEnv, omit, pick, pruneUndefined } from '../utils.js' + +export namespace searxng { + export interface SearchOptions { + query: string + categories?: string[] + engines?: string[] + language?: string + pageno?: number + } + + export interface SearchResult { + title: string + url: string + img_src?: string + thumbnail_src?: string + thumbnail?: string + content?: string + author?: string + iframe_src?: string + } + + export interface SearchResponse { + results: SearchResult[] + suggestions: string[] + } +} + +/** + * @see https://docs.searxng.org + */ +export class SearxngClient { + readonly ky: KyInstance + readonly apiKey: string + readonly apiBaseUrl: string + + constructor({ + apiKey = getEnv('SEARXNG_API_KEY'), + apiBaseUrl = getEnv('SEARXNG_API_BASE_URL'), + ky = defaultKy + }: { + apiKey?: string + apiBaseUrl?: string + ky?: KyInstance + } = {}) { + assert( + apiKey, + 'SearxngClient missing required "apiKey" (defaults to "SEARXNG_API_KEY")' + ) + assert( + apiBaseUrl, + 'SearxngClient missing required "apiBaseUrl" (defaults to "SEARXNG_API_BASE_URL")' + ) + + this.apiKey = apiKey + this.apiBaseUrl = apiBaseUrl + + this.ky = ky.extend({ prefixUrl: apiBaseUrl }) + } + + async search(opts: searxng.SearchOptions): Promise { + const res = await this.ky + .get('search', { + searchParams: pruneUndefined({ + ...omit(opts, 'categories', 'engines'), + categories: opts.categories?.join(','), + engines: opts.categories?.join(','), + format: 'json' + }) + }) + .json() + + return pick(res, 'results', 'suggestions') + } +} diff --git a/legacy/src/utils.ts b/legacy/src/utils.ts index b0575d9e..b080d1d9 100644 --- a/legacy/src/utils.ts +++ b/legacy/src/utils.ts @@ -12,7 +12,7 @@ export { default as assert } from 'tiny-invariant' * ``` */ export const omit = < - T extends Record, + T extends Record | object, K extends keyof T = keyof T >( inputObj: T, @@ -33,7 +33,7 @@ export const omit = < * ``` */ export const pick = < - T extends Record, + T extends Record | object, K extends keyof T = keyof T >( inputObj: T, @@ -47,7 +47,7 @@ export const pick = < export function pruneUndefined>( obj: T -): NonNullable { +): NonNullable<{ [K in keyof T]: Exclude }> { return Object.fromEntries( Object.entries(obj).filter(([, value]) => value !== undefined) ) as NonNullable diff --git a/legacy/tsconfig.json b/legacy/tsconfig.json index 4066d276..07b69730 100644 --- a/legacy/tsconfig.json +++ b/legacy/tsconfig.json @@ -16,6 +16,7 @@ // "emitDecoratorMetadata": true, "strict": true, + "strictNullChecks": true, "noUncheckedIndexedAccess": true, "forceConsistentCasingInFileNames": true,