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 = {
40 BFL: 'api_key_bfl',40 BFL: 'api_key_bfl',
41 GENERIC: 'api_key_generic',41 GENERIC: 'api_key_generic',
42 DEEPSEEK: 'api_key_deepseek',42 DEEPSEEK: 'api_key_deepseek',
43 SERPER: 'api_key_serper',
43};44};
4445
45const INPUT_MAP = {46const INPUT_MAP = {
src/endpoints/search.js+41 -0
@@ -297,6 +297,47 @@ router.post('/koboldcpp', jsonParser, async (request, response) => {
297 }297 }
298});298});
299299
300router.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
300router.post('/visit', jsonParser, async (request, response) => {341router.post('/visit', jsonParser, async (request, response) => {
301 try {342 try {
302 const url = request.body.url;343 const url = request.body.url;
src/endpoints/secrets.js+1 -0
@@ -52,6 +52,7 @@ export const SECRET_KEYS = {
52 BFL: 'api_key_bfl',52 BFL: 'api_key_bfl',
53 GENERIC: 'api_key_generic',53 GENERIC: 'api_key_generic',
54 DEEPSEEK: 'api_key_deepseek',54 DEEPSEEK: 'api_key_deepseek',
55 SERPER: 'api_key_serper',
55};56};
5657
57// These are the keys that are safe to expose, even if allowKeysExposure is false58// These are the keys that are safe to expose, even if allowKeysExposure is false