kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
pull/643/head^2
rodzic
b57e798531
commit
2ea18abab2
|
@ -27,6 +27,7 @@
|
||||||
- perigon
|
- perigon
|
||||||
- predict leads
|
- predict leads
|
||||||
- proxycurl
|
- proxycurl
|
||||||
|
- searxng
|
||||||
- serpapi
|
- serpapi
|
||||||
- serper
|
- serper
|
||||||
- twitter
|
- twitter
|
||||||
|
@ -43,7 +44,7 @@
|
||||||
- walter
|
- walter
|
||||||
- services
|
- services
|
||||||
- exa - need to update to correct format
|
- exa - need to update to correct format
|
||||||
- searxng
|
- wolfram alpha
|
||||||
- wikipedia
|
- wikipedia
|
||||||
- midjourney
|
- midjourney
|
||||||
- firecrawl
|
- firecrawl
|
||||||
|
|
|
@ -7,6 +7,7 @@ export * from './perigon-client.js'
|
||||||
export * from './predict-leads-client.js'
|
export * from './predict-leads-client.js'
|
||||||
export * from './proxycurl-client.js'
|
export * from './proxycurl-client.js'
|
||||||
export * from './scraper-client.js'
|
export * from './scraper-client.js'
|
||||||
|
export * from './searxng-client.js'
|
||||||
export * from './serpapi-client.js'
|
export * from './serpapi-client.js'
|
||||||
export * from './serper-client.js'
|
export * from './serper-client.js'
|
||||||
export * from './twitter-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 = <
|
export const omit = <
|
||||||
T extends Record<any, unknown>,
|
T extends Record<any, unknown> | object,
|
||||||
K extends keyof T = keyof T
|
K extends keyof T = keyof T
|
||||||
>(
|
>(
|
||||||
inputObj: T,
|
inputObj: T,
|
||||||
|
@ -33,7 +33,7 @@ export const omit = <
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export const pick = <
|
export const pick = <
|
||||||
T extends Record<any, unknown>,
|
T extends Record<any, unknown> | object,
|
||||||
K extends keyof T = keyof T
|
K extends keyof T = keyof T
|
||||||
>(
|
>(
|
||||||
inputObj: T,
|
inputObj: T,
|
||||||
|
@ -47,7 +47,7 @@ export const pick = <
|
||||||
|
|
||||||
export function pruneUndefined<T extends Record<string, any>>(
|
export function pruneUndefined<T extends Record<string, any>>(
|
||||||
obj: T
|
obj: T
|
||||||
): NonNullable<T> {
|
): NonNullable<{ [K in keyof T]: Exclude<T[K], undefined> }> {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(obj).filter(([, value]) => value !== undefined)
|
Object.entries(obj).filter(([, value]) => value !== undefined)
|
||||||
) as NonNullable<T>
|
) as NonNullable<T>
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
// "emitDecoratorMetadata": true,
|
// "emitDecoratorMetadata": true,
|
||||||
|
|
||||||
"strict": true,
|
"strict": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
"noUncheckedIndexedAccess": true,
|
"noUncheckedIndexedAccess": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue