windscout 0.5.7 → 0.5.8
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 +2 -0
- package/dist/cli.js +7 -0
- package/dist/config.js +1 -0
- package/dist/tui/picker.js +14 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,6 +52,7 @@ Run `windscout` with no arguments to open the interactive picker:
|
|
|
52
52
|
| `1`–`6` | toggle a protocol (`1`–`5` on Linux, which has no IKEv2) |
|
|
53
53
|
| `s` | toggle the speed test (off = connect-only mode) |
|
|
54
54
|
| `f` | toggle "block internet while scanning" (firewall) |
|
|
55
|
+
| `r` | toggle random order: scan the selected countries shuffled, a new order each run |
|
|
55
56
|
| `u` | update to the newer version and restart (only when the picker shows one is out) |
|
|
56
57
|
| `enter` | start scanning |
|
|
57
58
|
| `q` | quit (during a scan: stop and show partial results; press again to force quit) |
|
|
@@ -80,6 +81,7 @@ windscout -t 40 -a # longer connect timeout, also list
|
|
|
80
81
|
| `-a, --all` | include failed attempts in the final table | off |
|
|
81
82
|
| `-n, --no-speed` | connect-only mode: skip the download test, rank by latency | picker: saved, or connect-only on first run; with `-c`: speed test on |
|
|
82
83
|
| `-f, --firewall` | block internet while scanning, except through the VPN | picker: saved, or off; with `-c`: off |
|
|
84
|
+
| `-r, --random` | scan the countries in a random order | picker: saved, or off; with `-c`: off |
|
|
83
85
|
| `-v, --version` | print the installed version; if a newer one is on npm, show the update command (with `sudo` when needed) and ask (y/n) to run it | |
|
|
84
86
|
|
|
85
87
|
## Connect-only mode
|
package/dist/cli.js
CHANGED
|
@@ -27,6 +27,7 @@ Options:
|
|
|
27
27
|
-a, --all also show failed attempts in the final table
|
|
28
28
|
-n, --no-speed connect-only: skip the download test, rank by latency (faster scan)
|
|
29
29
|
-f, --firewall block internet while scanning, except through the VPN (turned back off afterwards)
|
|
30
|
+
-r, --random scan the countries in a random order
|
|
30
31
|
-v, --version show the installed version (and offer to update if a newer one is out)
|
|
31
32
|
-h, --help show this help
|
|
32
33
|
|
|
@@ -83,6 +84,7 @@ async function main() {
|
|
|
83
84
|
version: { type: "boolean", short: "v", default: false },
|
|
84
85
|
"no-speed": { type: "boolean", short: "n", default: false },
|
|
85
86
|
firewall: { type: "boolean", short: "f", default: false },
|
|
87
|
+
random: { type: "boolean", short: "r", default: false },
|
|
86
88
|
},
|
|
87
89
|
});
|
|
88
90
|
if (a.help)
|
|
@@ -104,6 +106,7 @@ async function main() {
|
|
|
104
106
|
let protocols = a.protocols ? list(a.protocols) : undefined;
|
|
105
107
|
let speedTest = !a["no-speed"];
|
|
106
108
|
let firewall = a.firewall;
|
|
109
|
+
let random = a.random;
|
|
107
110
|
if (!countries) {
|
|
108
111
|
if (!tty)
|
|
109
112
|
throw new Error("no terminal for the picker: pass countries with -c");
|
|
@@ -115,6 +118,7 @@ async function main() {
|
|
|
115
118
|
speedTest: speedTest && (saved?.speed ?? false), // first run: connect-only
|
|
116
119
|
// already on in the app: show it on, since the scan won't turn it off
|
|
117
120
|
firewall: firewall || isFirewallOn(status) || (saved?.firewall ?? false),
|
|
121
|
+
random: random || (saved?.random ?? false),
|
|
118
122
|
});
|
|
119
123
|
if (!choice)
|
|
120
124
|
return;
|
|
@@ -124,10 +128,13 @@ async function main() {
|
|
|
124
128
|
protocols ??= choice.protocols;
|
|
125
129
|
speedTest = choice.speed;
|
|
126
130
|
firewall = choice.firewall;
|
|
131
|
+
random = choice.random;
|
|
127
132
|
timeout = choice.timeout;
|
|
128
133
|
}
|
|
129
134
|
protocols ??= PROTOCOLS;
|
|
130
135
|
timeout ??= DEFAULT_TIMEOUT;
|
|
136
|
+
if (random)
|
|
137
|
+
countries = countries.map((c) => [Math.random(), c]).sort(([x], [y]) => x - y).map(([, c]) => c);
|
|
131
138
|
const scan = new Scan(countries, protocols, { timeout, speedTest });
|
|
132
139
|
const blocking = firewall && (await blockInternet());
|
|
133
140
|
const view = tty ? showProgress(scan, blocking) : logProgress(scan);
|
package/dist/config.js
CHANGED
|
@@ -15,6 +15,7 @@ export function loadConfig() {
|
|
|
15
15
|
protocols: (c.protocols ?? []).filter((x) => PROTOCOLS.includes(x)),
|
|
16
16
|
speed: c.speed !== false,
|
|
17
17
|
firewall: c.firewall === true,
|
|
18
|
+
random: c.random === true,
|
|
18
19
|
timeout: c.timeout >= MIN_TIMEOUT ? c.timeout : DEFAULT_TIMEOUT,
|
|
19
20
|
};
|
|
20
21
|
}
|
package/dist/tui/picker.js
CHANGED
|
@@ -9,7 +9,7 @@ import { bold, cyan, dim, green, under, vw, yellow } from "./text.js";
|
|
|
9
9
|
import { box, centerIn, grid } from "./widgets.js";
|
|
10
10
|
const flip = (set, value) => (set.has(value) ? set.delete(value) : set.add(value));
|
|
11
11
|
/** Resolves to the choice (also saved for next time), null when the user quits, or "update" for u */
|
|
12
|
-
export function pick(saved, { timeout, speedTest, firewall }) {
|
|
12
|
+
export function pick(saved, { timeout, speedTest, firewall, random }) {
|
|
13
13
|
const selected = new Set(saved?.countries ?? []);
|
|
14
14
|
const protos = new Set(saved?.protocols.length ? saved.protocols : PROTOCOLS);
|
|
15
15
|
let cursor = 0, top = 0, message = "", query = "", searching = false;
|
|
@@ -25,7 +25,7 @@ export function pick(saved, { timeout, speedTest, firewall }) {
|
|
|
25
25
|
const rows = out.rows || 24;
|
|
26
26
|
const version = versionLines(true);
|
|
27
27
|
const matches = visible();
|
|
28
|
-
const height = Math.max(3, rows -
|
|
28
|
+
const height = Math.max(3, rows - 22 - version.length);
|
|
29
29
|
cursor = Math.max(0, Math.min(cursor, matches.length - 1));
|
|
30
30
|
if (cursor < top)
|
|
31
31
|
top = cursor;
|
|
@@ -40,6 +40,9 @@ export function pick(saved, { timeout, speedTest, firewall }) {
|
|
|
40
40
|
const fwLine = `${dim(under("f"))} ${firewall ? green("● " + fwLabel) : dim("○ " + fwLabel)} ${dim(firewall
|
|
41
41
|
? "only VPN traffic gets through"
|
|
42
42
|
: "off: apps may leak in between")}`;
|
|
43
|
+
const randomLine = `${dim(under("r"))} ${random ? green("● random order") : dim("○ random order")} ${dim(random
|
|
44
|
+
? "scans the countries shuffled, a new order each run"
|
|
45
|
+
: "off: scans in list order")}`;
|
|
43
46
|
timeout = Number(seconds);
|
|
44
47
|
const short = timeout < MIN_TIMEOUT;
|
|
45
48
|
const timeoutLine = `${dim(under("t"))} timeout ${editing ? bold(seconds) + cyan("▏") : (short ? yellow : bold)(seconds || "?")} s ${dim(`per connection · at least ${MIN_TIMEOUT}`)}`;
|
|
@@ -63,9 +66,9 @@ export function pick(saved, { timeout, speedTest, firewall }) {
|
|
|
63
66
|
["quit", under("Q") + "uit"],
|
|
64
67
|
];
|
|
65
68
|
const buttonLine = buttons.map(([id, label]) => (id === "start" ? bold(cyan(`[ ${label} ]`)) : dim(`[ ${label} ]`))).join(" ");
|
|
66
|
-
const table = grid([{ title: "" }, { title: "Code" }, { title: "Country" }], body, { caption: search, captionRight: dim(range), minWidth: Math.max(vw(protoLine), vw(speedLine), vw(fwLine), vw(timeoutLine)) + 4 });
|
|
69
|
+
const table = grid([{ title: "" }, { title: "Code" }, { title: "Country" }], body, { caption: search, captionRight: dim(range), minWidth: Math.max(vw(protoLine), vw(speedLine), vw(fwLine), vw(randomLine), vw(timeoutLine)) + 4 });
|
|
67
70
|
const width = vw(table[0]);
|
|
68
|
-
const head = box([protoLine, speedLine, fwLine, timeoutLine], {
|
|
71
|
+
const head = box([protoLine, speedLine, fwLine, randomLine, timeoutLine], {
|
|
69
72
|
title: bold(cyan("WindScout")),
|
|
70
73
|
right: `${bold(String(selected.size))}${dim(`/${COUNTRIES.length} selected`)}`,
|
|
71
74
|
width: width - 4,
|
|
@@ -85,7 +88,7 @@ export function pick(saved, { timeout, speedTest, firewall }) {
|
|
|
85
88
|
: searching
|
|
86
89
|
? "type to filter · ↑↓ move · enter/esc done"
|
|
87
90
|
: `↑↓ move · space select · a/n ${query ? "all/none shown" : "all/none"} · / search`), width),
|
|
88
|
-
centerIn(dim(searching || editing ? "" : `1-${PROTOCOLS.length} protocols · s speed test · f firewall · t timeout · enter start · ${query ? "esc clear · " : ""}q quit`), width),
|
|
91
|
+
centerIn(dim(searching || editing ? "" : `1-${PROTOCOLS.length} protocols · s speed test · f firewall · r random · t timeout · enter start · ${query ? "esc clear · " : ""}q quit`), width),
|
|
89
92
|
];
|
|
90
93
|
if (message)
|
|
91
94
|
lines.push(centerIn(yellow(message), width));
|
|
@@ -107,7 +110,7 @@ export function pick(saved, { timeout, speedTest, firewall }) {
|
|
|
107
110
|
return range;
|
|
108
111
|
});
|
|
109
112
|
hit = {
|
|
110
|
-
protoRow: at.top + 1, protoHits, speedRow: at.top + 2, firewallRow: at.top + 3,
|
|
113
|
+
protoRow: at.top + 1, protoHits, speedRow: at.top + 2, firewallRow: at.top + 3, randomRow: at.top + 4, timeoutRow: at.top + 5,
|
|
111
114
|
searchRow: at.top + head.length + 1,
|
|
112
115
|
firstRow: at.top + head.length + 5, shown: shown.length,
|
|
113
116
|
buttonRow: at.top + head.length + table.length + 1, buttonHits,
|
|
@@ -139,6 +142,7 @@ export function pick(saved, { timeout, speedTest, firewall }) {
|
|
|
139
142
|
protocols: PROTOCOLS.filter((p) => protos.has(p)),
|
|
140
143
|
speed: speedTest,
|
|
141
144
|
firewall,
|
|
145
|
+
random,
|
|
142
146
|
timeout,
|
|
143
147
|
};
|
|
144
148
|
saveConfig(choice);
|
|
@@ -178,6 +182,8 @@ export function pick(saved, { timeout, speedTest, firewall }) {
|
|
|
178
182
|
speedTest = !speedTest;
|
|
179
183
|
else if (y === hit.firewallRow)
|
|
180
184
|
firewall = !firewall;
|
|
185
|
+
else if (y === hit.randomRow)
|
|
186
|
+
random = !random;
|
|
181
187
|
else if (y === hit.buttonRow) {
|
|
182
188
|
const id = hit.buttonHits.find(([, a, b]) => x >= a && x < b)?.[0];
|
|
183
189
|
if (id === "start" && start())
|
|
@@ -253,6 +259,8 @@ export function pick(saved, { timeout, speedTest, firewall }) {
|
|
|
253
259
|
speedTest = !speedTest;
|
|
254
260
|
else if (k === "f")
|
|
255
261
|
firewall = !firewall;
|
|
262
|
+
else if (k === "r")
|
|
263
|
+
random = !random;
|
|
256
264
|
else if (k === "t")
|
|
257
265
|
editing = true, seconds = "";
|
|
258
266
|
else if (k === "u" && canUpdate())
|