dsh-free-search 0.4.17 → 0.4.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/lib/client.js +28 -0
- package/lib/index.js +11 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -488,4 +488,10 @@ Windows users: The desktop shortcut already includes this configuration (`set NO
|
|
|
488
488
|
|
|
489
489
|
### License
|
|
490
490
|
|
|
491
|
-
MIT
|
|
491
|
+
MIT
|
|
492
|
+
|
|
493
|
+
## safeSearch 安全搜索过滤
|
|
494
|
+
|
|
495
|
+
- 全新配置项 `safeSearch`:`off`(引擎默认,不加参数)/ `moderate` / `strict`
|
|
496
|
+
- 作用于 Bing(adlt)、DuckDuckGo HTML(adlt)、DuckDuckGo Lite(adlt)
|
|
497
|
+
- 默认 `off`:不额外过滤,保持引擎自身默认行为;需要时在「设置 > 插件 > Free Search」切换
|
package/lib/client.js
CHANGED
|
@@ -273,6 +273,7 @@ window.__ModuleLoader__.load({
|
|
|
273
273
|
const [open, setOpen] = react.useState(false);
|
|
274
274
|
const [state, setState] = react.useState({ status: "loading" });
|
|
275
275
|
const [provider, setProvider] = react.useState("bing");
|
|
276
|
+
const [safeSearch, setSafeSearch] = react.useState("off");
|
|
276
277
|
const [exaKey, setExaKey] = react.useState("");
|
|
277
278
|
const [tavilyKey, setTavilyKey] = react.useState("");
|
|
278
279
|
const [keenableKey, setKeenableKey] = react.useState("");
|
|
@@ -303,6 +304,7 @@ window.__ModuleLoader__.load({
|
|
|
303
304
|
if (view) {
|
|
304
305
|
const v = view.value ?? {};
|
|
305
306
|
setProvider(v.provider ?? "ddg");
|
|
307
|
+
setSafeSearch(v.safeSearch === "strict" || v.safeSearch === "moderate" ? v.safeSearch : "off");
|
|
306
308
|
setLang(v.lang === "en" ? "en" : "zh");
|
|
307
309
|
setExaKey(v.exaApiKey ?? "");
|
|
308
310
|
setTavilyKey(v.tavilyApiKey ?? "");
|
|
@@ -383,6 +385,7 @@ window.__ModuleLoader__.load({
|
|
|
383
385
|
const ops = [{ op: "set", path: ["provider"], value: provider }];
|
|
384
386
|
ops.push({ op: "set", path: ["lang"], value: lang });
|
|
385
387
|
ops.push({ op: "set", path: ["keyStorage"], value: keyStorage });
|
|
388
|
+
ops.push({ op: "set", path: ["safeSearch"], value: safeSearch });
|
|
386
389
|
if (keyStorage !== "credentials") {
|
|
387
390
|
// settings 模式:key 仍写 settings.yaml(旧行为)
|
|
388
391
|
for (const [field, value] of keyFields) {
|
|
@@ -570,6 +573,31 @@ react_jsx_runtime.jsx("div", {
|
|
|
570
573
|
}),
|
|
571
574
|
],
|
|
572
575
|
}),
|
|
576
|
+
react_jsx_runtime.jsx("div", {
|
|
577
|
+
className: "dshfs-field",
|
|
578
|
+
children: [
|
|
579
|
+
react_jsx_runtime.jsx("div", {
|
|
580
|
+
className: "dshfs-label",
|
|
581
|
+
children: "Safe search filter (adlt)",
|
|
582
|
+
}),
|
|
583
|
+
react_jsx_runtime.jsx("select", {
|
|
584
|
+
className: "dshfs-select",
|
|
585
|
+
value: safeSearch,
|
|
586
|
+
style: { colorScheme: selectColorScheme },
|
|
587
|
+
disabled: !ready || saving,
|
|
588
|
+
onChange: (e) => setSafeSearch(e.target.value),
|
|
589
|
+
children: [
|
|
590
|
+
react_jsx_runtime.jsx("option", { value: "off", children: "Off - engine default (no filtering)" }, "off"),
|
|
591
|
+
react_jsx_runtime.jsx("option", { value: "moderate", children: "Moderate - Bing default" }, "moderate"),
|
|
592
|
+
react_jsx_runtime.jsx("option", { value: "strict", children: "Strict" }, "strict"),
|
|
593
|
+
],
|
|
594
|
+
}),
|
|
595
|
+
react_jsx_runtime.jsx("p", {
|
|
596
|
+
className: "dshfs-hint",
|
|
597
|
+
children: "Applies to bing (adlt), ddg, ddg-lite (adlt degree). If you see the engine's own filtering, adjust here.",
|
|
598
|
+
}),
|
|
599
|
+
],
|
|
600
|
+
}),
|
|
573
601
|
react_jsx_runtime.jsx("div", {
|
|
574
602
|
className: "dshfs-field",
|
|
575
603
|
children: [
|
package/lib/index.js
CHANGED
|
@@ -241,6 +241,9 @@ async function fetchHtmlWithRetry(url, signal) {
|
|
|
241
241
|
async function searchDdgHtml(query, maxResults, options, signal) {
|
|
242
242
|
const params = new URLSearchParams({ q: query });
|
|
243
243
|
if (options?.region) params.set("kl", options.region);
|
|
244
|
+
// DDG 安全搜索:off(adlt=-1) / moderate(adlt=0) / strict(adlt=1)
|
|
245
|
+
const adlt = options?.safeSearch ?? "off";
|
|
246
|
+
params.set("adlt", adlt === "strict" ? "1" : adlt === "moderate" ? "0" : "-1");
|
|
244
247
|
// DDG 时间过滤:df=d/w/m/y(只支持固定档,自定义取近似档)
|
|
245
248
|
if (options?.timeRange) {
|
|
246
249
|
const df = { day: "d", week: "w", month: "m", year: "y" }[approximateTimeRange(options.timeRange.days ?? 7)];
|
|
@@ -268,6 +271,8 @@ async function searchDdgHtml(query, maxResults, options, signal) {
|
|
|
268
271
|
|
|
269
272
|
async function searchDdgLite(query, maxResults, options, signal) {
|
|
270
273
|
const params = new URLSearchParams({ q: query });
|
|
274
|
+
const adlt = options?.safeSearch ?? "off";
|
|
275
|
+
params.set("adlt", adlt === "strict" ? "1" : adlt === "moderate" ? "0" : "-1");
|
|
271
276
|
// DDG Lite 同样支持 df 时间过滤
|
|
272
277
|
if (options?.timeRange) {
|
|
273
278
|
const df = { day: "d", week: "w", month: "m", year: "y" }[approximateTimeRange(options.timeRange.days ?? 7)];
|
|
@@ -296,6 +301,10 @@ async function searchDdgLite(query, maxResults, options, signal) {
|
|
|
296
301
|
|
|
297
302
|
async function searchBing(query, maxResults, options, signal) {
|
|
298
303
|
const params = new URLSearchParams({ q: query, mkt: options?.bingMarket ?? "zh-CN" });
|
|
304
|
+
const adlt = options?.safeSearch ?? "off";
|
|
305
|
+
if (adlt === "off") params.set("adlt", "off");
|
|
306
|
+
else if (adlt === "moderate") params.set("adlt", "moderate");
|
|
307
|
+
else if (adlt === "strict") params.set("adlt", "strict");
|
|
299
308
|
const html = await fetchHtmlWithRetry(`${BING_URL}?${params}`, signal);
|
|
300
309
|
const blocks = html.match(/<li class="b_algo"[\s\S]*?<\/li>/g) ?? [];
|
|
301
310
|
const sources = [];
|
|
@@ -1417,6 +1426,7 @@ const Config = z.object({
|
|
|
1417
1426
|
lang: z.string().default("zh"),
|
|
1418
1427
|
region: z.string(),
|
|
1419
1428
|
bingMarket: z.string().default("zh-CN"),
|
|
1429
|
+
safeSearch: z.string().default("off"),
|
|
1420
1430
|
searxngInstances: z.array(z.string()),
|
|
1421
1431
|
platforms: z.array(z.string()).default(["github", "v2ex", "bilibili", "reddit", "hn", "stackoverflow", "wikipedia", "npm"]),
|
|
1422
1432
|
exaApiKey: z.string().role("secret"),
|
|
@@ -2011,6 +2021,7 @@ function apply(ctx, config) {
|
|
|
2011
2021
|
"",
|
|
2012
2022
|
"You have the web_search tool. Its backend engine is chosen in Settings > Plugins > Free Search.",
|
|
2013
2023
|
"Current engine: " + (current().provider ?? "bing"),
|
|
2024
|
+
"Safe search filter (Settings > Plugins > Free Search): " + (current().safeSearch ?? "off") + " (off|moderate|strict). Engine default off; applies to bing/ddg/ddg-lite.",
|
|
2014
2025
|
"",
|
|
2015
2026
|
"Available engines and their requirements:",
|
|
2016
2027
|
"- ddg (DuckDuckGo HTML) - FREE, no key (may be rate-limited)",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-free-search",
|
|
3
|
-
"version":
|
|
3
|
+
"version": "0.4.18",
|
|
4
4
|
"description": "Free web search for DeepSeek Harness: 10 engines (Bing/DuckDuckGo/AnySearch/SearXNG/Exa/Tavily/Keenable keyless) + time filtering + platform search + web_fetch, with web settings UI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|