kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
pull/643/head^2
rodzic
b57e798531
commit
2ea18abab2
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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<searxng.SearchResponse> {
|
||||
const res = await this.ky
|
||||
.get('search', {
|
||||
searchParams: pruneUndefined({
|
||||
...omit(opts, 'categories', 'engines'),
|
||||
categories: opts.categories?.join(','),
|
||||
engines: opts.categories?.join(','),
|
||||
format: 'json'
|
||||
})
|
||||
})
|
||||
.json<searxng.SearchResponse>()
|
||||
|
||||
return pick(res, 'results', 'suggestions')
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ export { default as assert } from 'tiny-invariant'
|
|||
* ```
|
||||
*/
|
||||
export const omit = <
|
||||
T extends Record<any, unknown>,
|
||||
T extends Record<any, unknown> | object,
|
||||
K extends keyof T = keyof T
|
||||
>(
|
||||
inputObj: T,
|
||||
|
@ -33,7 +33,7 @@ export const omit = <
|
|||
* ```
|
||||
*/
|
||||
export const pick = <
|
||||
T extends Record<any, unknown>,
|
||||
T extends Record<any, unknown> | object,
|
||||
K extends keyof T = keyof T
|
||||
>(
|
||||
inputObj: T,
|
||||
|
@ -47,7 +47,7 @@ export const pick = <
|
|||
|
||||
export function pruneUndefined<T extends Record<string, any>>(
|
||||
obj: T
|
||||
): NonNullable<T> {
|
||||
): NonNullable<{ [K in keyof T]: Exclude<T[K], undefined> }> {
|
||||
return Object.fromEntries(
|
||||
Object.entries(obj).filter(([, value]) => value !== undefined)
|
||||
) as NonNullable<T>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
// "emitDecoratorMetadata": true,
|
||||
|
||||
"strict": true,
|
||||
"strictNullChecks": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue