Add support for SerpStack API (#669)
Browse files* Add support for SerpStack API
* update const to SERPSTACK_API_KEY
* update readme
* lint
---------
Co-authored-by: Nathan Sarrazin <[email protected]>
- .env +1 -0
- README.md +1 -1
- src/lib/server/websearch/searchWeb.ts +43 -1
- src/routes/+layout.server.ts +8 -1
.env
CHANGED
@@ -16,6 +16,7 @@ HF_ACCESS_TOKEN=#LEGACY! Use HF_TOKEN instead
|
|
16 |
YDC_API_KEY=#your docs.you.com api key here
|
17 |
SERPER_API_KEY=#your serper.dev api key here
|
18 |
SERPAPI_KEY=#your serpapi key here
|
|
|
19 |
USE_LOCAL_WEBSEARCH=#set to true to parse google results yourself, overrides other API keys
|
20 |
|
21 |
WEBSEARCH_ALLOWLIST=`[]` # if it's defined, allow websites from only this list.
|
|
|
16 |
YDC_API_KEY=#your docs.you.com api key here
|
17 |
SERPER_API_KEY=#your serper.dev api key here
|
18 |
SERPAPI_KEY=#your serpapi key here
|
19 |
+
SERPSTACK_API_KEY=#your serpstack api key here
|
20 |
USE_LOCAL_WEBSEARCH=#set to true to parse google results yourself, overrides other API keys
|
21 |
|
22 |
WEBSEARCH_ALLOWLIST=`[]` # if it's defined, allow websites from only this list.
|
README.md
CHANGED
@@ -122,7 +122,7 @@ PUBLIC_APP_DISCLAIMER=
|
|
122 |
|
123 |
### Web Search config
|
124 |
|
125 |
-
You can enable the web search through an API by adding `YDC_API_KEY` ([docs.you.com](https://docs.you.com)) or `SERPER_API_KEY` ([serper.dev](https://serper.dev/)) or `SERPAPI_KEY` ([serpapi.com](https://serpapi.com/)) to your `.env.local`.
|
126 |
|
127 |
You can also simply enable the local websearch by setting `USE_LOCAL_WEBSEARCH=true` in your `.env.local`.
|
128 |
|
|
|
122 |
|
123 |
### Web Search config
|
124 |
|
125 |
+
You can enable the web search through an API by adding `YDC_API_KEY` ([docs.you.com](https://docs.you.com)) or `SERPER_API_KEY` ([serper.dev](https://serper.dev/)) or `SERPAPI_KEY` ([serpapi.com](https://serpapi.com/)) or `SERPSTACK_API_KEY` ([serpstack.com](https://serpstack.com/)) to your `.env.local`.
|
126 |
|
127 |
You can also simply enable the local websearch by setting `USE_LOCAL_WEBSEARCH=true` in your `.env.local`.
|
128 |
|
src/lib/server/websearch/searchWeb.ts
CHANGED
@@ -1,6 +1,12 @@
|
|
1 |
import type { YouWebSearch } from "../../types/WebSearch";
|
2 |
import { WebSearchProvider } from "../../types/WebSearch";
|
3 |
-
import {
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
import { getJson } from "serpapi";
|
5 |
import type { GoogleParameters } from "serpapi";
|
6 |
import { searchWebLocal } from "./searchWebLocal";
|
@@ -24,6 +30,9 @@ export async function searchWeb(query: string) {
|
|
24 |
if (SERPAPI_KEY) {
|
25 |
return await searchWebSerpApi(query);
|
26 |
}
|
|
|
|
|
|
|
27 |
throw new Error("No You.com or Serper.dev or SerpAPI key found");
|
28 |
}
|
29 |
|
@@ -100,3 +109,36 @@ export async function searchWebYouApi(query: string) {
|
|
100 |
organic_results: formattedResultsWithSnippets,
|
101 |
};
|
102 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import type { YouWebSearch } from "../../types/WebSearch";
|
2 |
import { WebSearchProvider } from "../../types/WebSearch";
|
3 |
+
import {
|
4 |
+
SERPAPI_KEY,
|
5 |
+
SERPER_API_KEY,
|
6 |
+
SERPSTACK_API_KEY,
|
7 |
+
USE_LOCAL_WEBSEARCH,
|
8 |
+
YDC_API_KEY,
|
9 |
+
} from "$env/static/private";
|
10 |
import { getJson } from "serpapi";
|
11 |
import type { GoogleParameters } from "serpapi";
|
12 |
import { searchWebLocal } from "./searchWebLocal";
|
|
|
30 |
if (SERPAPI_KEY) {
|
31 |
return await searchWebSerpApi(query);
|
32 |
}
|
33 |
+
if (SERPSTACK_API_KEY) {
|
34 |
+
return await searchSerpStack(query);
|
35 |
+
}
|
36 |
throw new Error("No You.com or Serper.dev or SerpAPI key found");
|
37 |
}
|
38 |
|
|
|
109 |
organic_results: formattedResultsWithSnippets,
|
110 |
};
|
111 |
}
|
112 |
+
|
113 |
+
export async function searchSerpStack(query: string) {
|
114 |
+
const response = await fetch(
|
115 |
+
`http://api.serpstack.com/search?access_key=${SERPSTACK_API_KEY}&query=${query}&hl=en&gl=us`,
|
116 |
+
{
|
117 |
+
method: "GET",
|
118 |
+
headers: {
|
119 |
+
"Content-type": "application/json; charset=UTF-8",
|
120 |
+
},
|
121 |
+
}
|
122 |
+
);
|
123 |
+
|
124 |
+
const data = (await response.json()) as Record<string, any>;
|
125 |
+
|
126 |
+
if (!response.ok) {
|
127 |
+
throw new Error(
|
128 |
+
data["error"] ??
|
129 |
+
`SerpStack API returned error code ${response.status} - ${response.statusText}`
|
130 |
+
);
|
131 |
+
}
|
132 |
+
|
133 |
+
const resultsWithSnippets = data["organic_results"].map(
|
134 |
+
({ title, url, snippet }: { title: string; url: string; snippet: string | undefined }) => ({
|
135 |
+
title,
|
136 |
+
link: url,
|
137 |
+
text: snippet || "",
|
138 |
+
})
|
139 |
+
);
|
140 |
+
|
141 |
+
return {
|
142 |
+
organic_results: resultsWithSnippets ?? [],
|
143 |
+
};
|
144 |
+
}
|
src/routes/+layout.server.ts
CHANGED
@@ -8,6 +8,7 @@ import { DEFAULT_SETTINGS } from "$lib/types/Settings";
|
|
8 |
import {
|
9 |
SERPAPI_KEY,
|
10 |
SERPER_API_KEY,
|
|
|
11 |
MESSAGES_BEFORE_LOGIN,
|
12 |
YDC_API_KEY,
|
13 |
USE_LOCAL_WEBSEARCH,
|
@@ -77,7 +78,13 @@ export const load: LayoutServerLoad = async ({ locals, depends }) => {
|
|
77 |
}))
|
78 |
.toArray(),
|
79 |
settings: {
|
80 |
-
searchEnabled: !!(
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
ethicsModalAccepted: !!settings?.ethicsModalAcceptedAt,
|
82 |
ethicsModalAcceptedAt: settings?.ethicsModalAcceptedAt ?? null,
|
83 |
activeModel: settings?.activeModel ?? DEFAULT_SETTINGS.activeModel,
|
|
|
8 |
import {
|
9 |
SERPAPI_KEY,
|
10 |
SERPER_API_KEY,
|
11 |
+
SERPSTACK_API_KEY,
|
12 |
MESSAGES_BEFORE_LOGIN,
|
13 |
YDC_API_KEY,
|
14 |
USE_LOCAL_WEBSEARCH,
|
|
|
78 |
}))
|
79 |
.toArray(),
|
80 |
settings: {
|
81 |
+
searchEnabled: !!(
|
82 |
+
SERPAPI_KEY ||
|
83 |
+
SERPER_API_KEY ||
|
84 |
+
SERPSTACK_API_KEY ||
|
85 |
+
YDC_API_KEY ||
|
86 |
+
USE_LOCAL_WEBSEARCH
|
87 |
+
),
|
88 |
ethicsModalAccepted: !!settings?.ethicsModalAcceptedAt,
|
89 |
ethicsModalAcceptedAt: settings?.ethicsModalAcceptedAt ?? null,
|
90 |
activeModel: settings?.activeModel ?? DEFAULT_SETTINGS.activeModel,
|