bep40 commited on
Commit
eba4f63
·
1 Parent(s): 4aa6466

Web search: fallback chain DDG → Bing RSS → Google HTML (HF egress hay bị block bởi DDG/Google HTML)

Browse files
Files changed (1) hide show
  1. index.ts +27 -2
index.ts CHANGED
@@ -1458,7 +1458,29 @@ const server = Bun.serve({
1458
  }
1459
  return res;
1460
  };
1461
- // 2) Google HTML fallback (used when DDG returns nothing / is unreachable)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1462
  const ggl = async (): Promise<Array<any>> => {
1463
  const r = await fetch("https://www.google.com/search?q=" + encodeURIComponent(q) + "&num=10&hl=vi", { headers: { "User-Agent": UA, "Accept-Language": "vi-VN,vi;q=0.9" }, signal: AbortSignal.timeout(12000) });
1464
  const h = await r.text();
@@ -1507,11 +1529,14 @@ const server = Bun.serve({
1507
  try {
1508
  let results: Array<any> = [];
1509
  try { results = await ddg(); } catch (_e) { results = []; }
 
 
 
1510
  if (!results.length) {
1511
  try { results = await ggl(); } catch (_e) { results = []; }
1512
  }
1513
  if (!results.length) return Response.json({ error: "Web search unreachable." }, { status: 502 });
1514
- return Response.json({ results: dedupeFn(results), engine: "ddg+google" });
1515
  } catch { return Response.json({ error: "Web search unreachable." }, { status: 502 }); }
1516
  }},
1517
  "/api/web/content": { GET: async (req: Request) => {
 
1458
  }
1459
  return res;
1460
  };
1461
+ // 2) Bing RSS fallback (used when DDG returns nothing / is unreachable).
1462
+ // RSS endpoints are far more permissive than HTML scraping from HF egress.
1463
+ const bingRss = async (): Promise<Array<any>> => {
1464
+ const r = await fetch("https://www.bing.com/search?format=rss&q=" + encodeURIComponent(q), { headers: { "User-Agent": UA, "Accept-Language": "vi-VN,vi;q=0.9" }, signal: AbortSignal.timeout(12000) });
1465
+ const h = await r.text();
1466
+ const res: Array<any> = [];
1467
+ const items = [...h.matchAll(/<item>([\s\S]*?)<\/item>/gi)];
1468
+ for (const it of items) {
1469
+ const body = it[1];
1470
+ const tm = body.match(/<title>(?:<!\[CDATA\[)?([\s\S]*?)(?:\]\]>)?<\/title>/i);
1471
+ const lm2 = body.match(/<link>(?:<!\[CDATA\[)?([\s\S]*?)(?:\]\]>)?<\/link>/i);
1472
+ const dm = body.match(/<description>(?:<!\[CDATA\[)?([\s\S]*?)(?:\]\]>)?<\/description>/i);
1473
+ const title = tm ? dec(tm[1]).trim() : '';
1474
+ let href = lm2 ? lm2[1].trim() : '';
1475
+ const snippet = dm ? dec(dm[1]).replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim().slice(0, 160) : '';
1476
+ if (!title || !href || !/^https?:\/\//i.test(href)) continue;
1477
+ let source = '';
1478
+ try { source = new URL(href).hostname.replace(/^www\./, ''); } catch (_) {}
1479
+ res.push({ title, snippet, url: href, source });
1480
+ }
1481
+ return res;
1482
+ };
1483
+ // 3) Google HTML fallback (last resort — often blocked from HF egress)
1484
  const ggl = async (): Promise<Array<any>> => {
1485
  const r = await fetch("https://www.google.com/search?q=" + encodeURIComponent(q) + "&num=10&hl=vi", { headers: { "User-Agent": UA, "Accept-Language": "vi-VN,vi;q=0.9" }, signal: AbortSignal.timeout(12000) });
1486
  const h = await r.text();
 
1529
  try {
1530
  let results: Array<any> = [];
1531
  try { results = await ddg(); } catch (_e) { results = []; }
1532
+ if (!results.length) {
1533
+ try { results = await bingRss(); } catch (_e) { results = []; }
1534
+ }
1535
  if (!results.length) {
1536
  try { results = await ggl(); } catch (_e) { results = []; }
1537
  }
1538
  if (!results.length) return Response.json({ error: "Web search unreachable." }, { status: 502 });
1539
+ return Response.json({ results: dedupeFn(results), engine: "ddg+google+bing" });
1540
  } catch { return Response.json({ error: "Web search unreachable." }, { status: 502 }); }
1541
  }},
1542
  "/api/web/content": { GET: async (req: Request) => {