windscout 0.4.3 → 0.4.4
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 +1 -1
- package/package.json +1 -1
- package/windscout.js +17 -4
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ Both modes show an **availability grid**: one row per country, and ✓ / ✗ for
|
|
|
98
98
|
╰─────────────────────────┴────────────────────────┴─────────┴───────────┴─────╯
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
While scanning, press `tab` to switch between the availability grid and the speed or latency ranking. In connect-only mode the scan starts on the availability grid.
|
|
101
|
+
While scanning, press `tab` to switch between the availability grid and the speed or latency ranking. Press `p` (or `space`) to pause: the current attempt finishes, the VPN disconnects, and the scan waits until you press `p` again. Paused time doesn't count toward elapsed or remaining. In connect-only mode the scan starts on the availability grid.
|
|
102
102
|
|
|
103
103
|
## Output
|
|
104
104
|
|
package/package.json
CHANGED
package/windscout.js
CHANGED
|
@@ -599,12 +599,14 @@ async function scan(countries, protocols, timeout, tty) {
|
|
|
599
599
|
const started = now();
|
|
600
600
|
let done = 0, attemptStart = now(), current = "", step = "", frame = 0, finishedCountries = [];
|
|
601
601
|
let view = speedTest ? "ranking" : "availability"; // tab switches
|
|
602
|
+
// pause lands between attempts, so the VPN is disconnected while waiting; idle = seconds spent paused
|
|
603
|
+
let paused = false, waiting = false, waitStart = 0, idle = 0, resume = () => {};
|
|
602
604
|
|
|
603
605
|
const render = () => {
|
|
604
606
|
const rows = out.rows || 24;
|
|
605
|
-
const elapsed = now() - started;
|
|
607
|
+
const elapsed = now() - started - idle - (waiting ? now() - waitStart : 0);
|
|
606
608
|
// smooth bar: count the running attempt as partially done
|
|
607
|
-
const partial = Math.min(0.95, (now() - attemptStart) / attemptSeconds(timeout));
|
|
609
|
+
const partial = waiting ? 0 : Math.min(0.95, (now() - attemptStart) / attemptSeconds(timeout));
|
|
608
610
|
const fraction = (done + (done < total ? partial : 0)) / total;
|
|
609
611
|
const eta = (total - done) * (done ? elapsed / done : attemptSeconds(timeout));
|
|
610
612
|
const spinner = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"[frame++ % 10];
|
|
@@ -640,8 +642,9 @@ async function scan(countries, protocols, timeout, tty) {
|
|
|
640
642
|
"",
|
|
641
643
|
stop
|
|
642
644
|
? yellow(" stopping after the current attempt…")
|
|
645
|
+
: waiting ? yellow(" paused · VPN disconnected · press p to resume")
|
|
643
646
|
: ` ${cyan(spinner)} ${bold(current)}`,
|
|
644
|
-
stop ? "" : ` ${dim(step)} ${dim("·")} ${duration(now() - attemptStart)}`,
|
|
647
|
+
stop || waiting ? "" : ` ${dim(step)} ${dim("·")} ${duration(now() - attemptStart)}${paused ? yellow(" · pausing after this attempt") : ""}`,
|
|
645
648
|
null,
|
|
646
649
|
centerIn(stats, inner),
|
|
647
650
|
], {
|
|
@@ -658,7 +661,7 @@ async function scan(countries, protocols, timeout, tty) {
|
|
|
658
661
|
while (vw(txt) > width && failed.length) txt = txt.slice(0, -8) + "…"; // ponytail: crude trim, fine for a status line
|
|
659
662
|
lines.push("", centerIn(txt, width));
|
|
660
663
|
}
|
|
661
|
-
lines.push("", centerIn(dim(`tab ${view === "ranking" ? "availability" : "ranking"} view · q stop · q twice force quit`), width), "", centerIn(dim(repoLink), width));
|
|
664
|
+
lines.push("", centerIn(dim(`tab ${view === "ranking" ? "availability" : "ranking"} view · p ${paused ? "resume" : "pause"} · q stop · q twice force quit`), width), "", centerIn(dim(repoLink), width));
|
|
662
665
|
draw(lines);
|
|
663
666
|
};
|
|
664
667
|
|
|
@@ -669,12 +672,17 @@ async function scan(countries, protocols, timeout, tty) {
|
|
|
669
672
|
if (key.name === "tab") {
|
|
670
673
|
view = view === "ranking" ? "availability" : "ranking";
|
|
671
674
|
render();
|
|
675
|
+
} else if (key.name === "p" || key.name === "space") {
|
|
676
|
+
paused = !paused;
|
|
677
|
+
if (!paused) resume();
|
|
678
|
+
render();
|
|
672
679
|
} else if (key.name === "q" || key.name === "escape" || (key.ctrl && key.name === "c")) {
|
|
673
680
|
if (stop++) { // second press: bail out now
|
|
674
681
|
leaveScreen();
|
|
675
682
|
console.error(`stopped. the VPN may still be connecting: run '${CLI} disconnect'`);
|
|
676
683
|
process.exit(130);
|
|
677
684
|
}
|
|
685
|
+
resume(); // a paused scan stops right away
|
|
678
686
|
render();
|
|
679
687
|
}
|
|
680
688
|
});
|
|
@@ -686,6 +694,11 @@ async function scan(countries, protocols, timeout, tty) {
|
|
|
686
694
|
|
|
687
695
|
outer: for (const loc of countries) {
|
|
688
696
|
for (const proto of protocols) {
|
|
697
|
+
if (paused && !stop) {
|
|
698
|
+
waiting = true, waitStart = now();
|
|
699
|
+
await new Promise((r) => (resume = r));
|
|
700
|
+
waiting = false, idle += now() - waitStart;
|
|
701
|
+
}
|
|
689
702
|
if (stop) break outer;
|
|
690
703
|
current = `${flag(loc)} ${countryName(loc)} ${dim("·")} ${proto}`;
|
|
691
704
|
attemptStart = now();
|