Websearch: add Serper API endpoint

5e540f4f978550a3e373be73422a08ff399362c4

Cohee <18619528+Cohee1207@users.noreply.github.com>

3 files changed, +43 -0Showing whitespace changes
public/scripts/secrets.js+1 -0
@@ -40,6 +40,7 @@ export const SECRET_KEYS = {
4040 BFL: 'api_key_bfl',
4141 GENERIC: 'api_key_generic',
4242 DEEPSEEK: 'api_key_deepseek',
43+ SERPER: 'api_key_serper',
4344};
4445
4546const INPUT_MAP = {
src/endpoints/search.js+41 -0
@@ -297,6 +297,47 @@ router.post('/koboldcpp', jsonParser, async (request, response) => {
297297 }
298298});
299299
300+router.post('/serper', jsonParser, async (request, response) => {
301+ try {
302+ const key = readSecret(request.user.directories, SECRET_KEYS.SERPER);
303+
304+ if (!key) {
305+ console.error('No Serper key found');
306+ return response.sendStatus(400);
307+ }
308+
309+ const { query, images } = request.body;
310+
311+ const url = images
312+ ? 'https://google.serper.dev/images'
313+ : 'https://google.serper.dev/search';
314+
315+ const result = await fetch(url, {
316+ method: 'POST',
317+ headers: {
318+ 'X-API-KEY': key,
319+ 'Content-Type': 'application/json',
320+ },
321+ redirect: 'follow',
322+ body: JSON.stringify({ q: query }),
323+ });
324+
325+ console.debug('Serper query', query);
326+
327+ if (!result.ok) {
328+ const text = await result.text();
329+ console.warn('Serper request failed', result.statusText, text);
330+ return response.status(500).send(text);
331+ }
332+
333+ const data = await result.json();
334+ return response.json(data);
335+ } catch (error) {
336+ console.error(error);
337+ return response.sendStatus(500);
338+ }
339+});
340+
300341router.post('/visit', jsonParser, async (request, response) => {
301342 try {
302343 const url = request.body.url;
src/endpoints/secrets.js+1 -0
@@ -52,6 +52,7 @@ export const SECRET_KEYS = {
5252 BFL: 'api_key_bfl',
5353 GENERIC: 'api_key_generic',
5454 DEEPSEEK: 'api_key_deepseek',
55+ SERPER: 'api_key_serper',
5556};
5657
5758// These are the keys that are safe to expose, even if allowKeysExposure is false