searchxng 1.0.0
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 +54 -0
- package/bin/searchxng.js +78 -0
- package/package.json +33 -0
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# SearchXNG CLI
|
|
2
|
+
|
|
3
|
+
A command-line interface for querying a [SearchXNG](https://docs.searxng.org/) instance.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g searchxng
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
searchxng "your search query here" [options]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Options:
|
|
18
|
+
- `-e, --endpoint <url>`: The SearchXNG instance URL (defaults to `http://localhost:8080/` or `SEARCHXNG_URL` env var)
|
|
19
|
+
- `-l, --language <lang>`: Language to search in (defaults to `en`)
|
|
20
|
+
- `-c, --categories <categories>`: Comma-separated list of categories (e.g. `news,science`)
|
|
21
|
+
- `-m, --max-results <number>`: Maximum number of results to return (defaults to `5`)
|
|
22
|
+
- `-j, --json`: Output raw JSON instead of formatted text
|
|
23
|
+
|
|
24
|
+
### Examples:
|
|
25
|
+
```bash
|
|
26
|
+
# Basic search with a specific endpoint
|
|
27
|
+
searchxng "cool new restaurants in orange county" --endpoint "http://192.168.4.4:8081/"
|
|
28
|
+
|
|
29
|
+
# Search in specific language
|
|
30
|
+
searchxng "best restaurants" -e "http://192.168.4.4:8081/" -l "es"
|
|
31
|
+
|
|
32
|
+
# Search with specific categories
|
|
33
|
+
searchxng "latest AI news" -e "http://192.168.4.4:8081/" -c "news,science"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Configuration
|
|
37
|
+
|
|
38
|
+
You can also omit the `--endpoint` parameter if you export the `SEARCHXNG_URL` environment variable in your session:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
export SEARCHXNG_URL="http://192.168.4.4:8081/"
|
|
42
|
+
searchxng "cool new restaurants in orange county"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Troubleshooting: 403 Forbidden Error
|
|
46
|
+
If you encounter a `403 Forbidden` error when running a search, it is likely because SearchXNG disables JSON API requests by default for security/privacy. To fix this, enable the `json` format in your SearchXNG's `settings.yml` file:
|
|
47
|
+
|
|
48
|
+
```yaml
|
|
49
|
+
search:
|
|
50
|
+
formats:
|
|
51
|
+
- html
|
|
52
|
+
- json
|
|
53
|
+
```
|
|
54
|
+
Restart your SearchXNG container or service after updating the settings.
|
package/bin/searchxng.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { Command } = require("commander");
|
|
4
|
+
|
|
5
|
+
const program = new Command();
|
|
6
|
+
|
|
7
|
+
program
|
|
8
|
+
.name("searchxng")
|
|
9
|
+
.description("CLI to query a local or remote SearchXNG instance")
|
|
10
|
+
.version("1.0.0");
|
|
11
|
+
|
|
12
|
+
program
|
|
13
|
+
.argument("<query>", "The search query")
|
|
14
|
+
.option("-e, --endpoint <url>", "The SearchXNG instance URL", process.env.SEARCHXNG_URL || "http://localhost:8080/")
|
|
15
|
+
.option("-l, --language <lang>", "Language to search in", "en")
|
|
16
|
+
.option("-c, --categories <categories>", "Comma-separated list of categories (e.g. news,science)")
|
|
17
|
+
.option("-m, --max-results <number>", "Maximum number of results to return", "5")
|
|
18
|
+
.option("-j, --json", "Output raw JSON instead of formatted text")
|
|
19
|
+
.action(async (query, options) => {
|
|
20
|
+
try {
|
|
21
|
+
let endpoint = options.endpoint;
|
|
22
|
+
if (!endpoint.startsWith("http://") && !endpoint.startsWith("https://")) {
|
|
23
|
+
endpoint = "http://" + endpoint;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const baseUrl = endpoint.endsWith("/") ? endpoint : `${endpoint}/`;
|
|
27
|
+
const url = new URL("search", baseUrl);
|
|
28
|
+
|
|
29
|
+
url.searchParams.set("q", query);
|
|
30
|
+
url.searchParams.set("format", "json");
|
|
31
|
+
url.searchParams.set("language", options.language);
|
|
32
|
+
|
|
33
|
+
if (options.categories) {
|
|
34
|
+
url.searchParams.set("categories", options.categories);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const controller = new AbortController();
|
|
38
|
+
const timeoutId = setTimeout(() => controller.abort(), 15000); // 15 second timeout
|
|
39
|
+
|
|
40
|
+
const response = await fetch(url.toString(), { signal: controller.signal });
|
|
41
|
+
clearTimeout(timeoutId);
|
|
42
|
+
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
console.error(`SearchXNG API returned status ${response.status}`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const data = await response.json();
|
|
49
|
+
|
|
50
|
+
const results = data.results || [];
|
|
51
|
+
|
|
52
|
+
let limit = parseInt(options.maxResults, 10);
|
|
53
|
+
if (isNaN(limit) || limit <= 0) limit = 5;
|
|
54
|
+
|
|
55
|
+
const topResults = results.slice(0, limit);
|
|
56
|
+
|
|
57
|
+
if (options.json) {
|
|
58
|
+
console.log(JSON.stringify(topResults, null, 2));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (topResults.length === 0) {
|
|
63
|
+
console.log("No results found.");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const formatted = topResults.map((r, i) => {
|
|
68
|
+
return `${i + 1}. ${r.title}\n URL: ${r.url}\n Snippet: ${r.content || r.snippet || ""}`;
|
|
69
|
+
}).join("\n\n");
|
|
70
|
+
|
|
71
|
+
console.log(formatted);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error(`Failed to search: ${error.message}`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "searchxng",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A command-line interface for querying a SearchXNG instance.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"searchxng": "./bin/searchxng.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"searchxng",
|
|
17
|
+
"search",
|
|
18
|
+
"cli"
|
|
19
|
+
],
|
|
20
|
+
"author": "chrisb",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/chrisb/searchxng-cli.git",
|
|
24
|
+
"directory": "packages/cli"
|
|
25
|
+
},
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=20.0.0"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"commander": "^14.0.3"
|
|
32
|
+
}
|
|
33
|
+
}
|