windscout 0.4.0 → 0.4.2

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.
Files changed (3) hide show
  1. package/README.md +19 -14
  2. package/package.json +14 -3
  3. package/windscout.js +20 -15
package/README.md CHANGED
@@ -4,6 +4,8 @@ Find which Windscribe locations and protocols actually work from your network, r
4
4
 
5
5
  WindScout drives the official `windscribe-cli`: it connects to each country × protocol pair, measures latency and download speed through the tunnel, disconnects, and prints a ranked table.
6
6
 
7
+ ![WindScout picking countries, scanning, and printing the availability grid and ranked results](demo.gif)
8
+
7
9
  > Unofficial tool, not affiliated with Windscribe.
8
10
 
9
11
  ## Requirements
@@ -27,6 +29,7 @@ Run `windscout` with no arguments to open the interactive picker:
27
29
  ```
28
30
  ╭─ WindScout ──────────────────────────────────── 2/68 selected ─╮
29
31
  │ 1 ● wireguard 2 ● stealth 3 ○ wstunnel 4 ● udp 5 ● tcp │
32
+ │ s ○ speed test off: connect-only, ranks by latency │
30
33
  ╰────────────────────────────────────────────────────────────────╯
31
34
  ╭────────────────────────────────────────────────────────────────╮
32
35
  │ 🔍 an▏ 1–16 of 18 │
@@ -51,7 +54,7 @@ Run `windscout` with no arguments to open the interactive picker:
51
54
  | `enter` | start scanning |
52
55
  | `q` | quit (during a scan: stop and show partial results; press again to force quit) |
53
56
 
54
- **Mouse:** click a country to select or unselect it, click a protocol or the speed-test line to toggle it, click the search box to start typing (click anywhere else to leave it), and scroll the list with the wheel. The `[ ▶ Start ] [ All ] [ None ] [ Quit ]` buttons under the table do the same as their keys. This needs a terminal with mouse support, which most have. On Windows, use Windows Terminal; if clicks do nothing there, the keyboard does everything.
57
+ **Mouse:** click a country to select or unselect it, click a protocol or the speed-test line to toggle it, click the search box to start typing (click anywhere else to leave it), and scroll the list with the wheel. The `[ ▶ Start ] [ All ] [ None ] [ Quit ]` buttons under the table do the same as their keys; the shortcut key is underlined on screen (on the buttons, the protocol numbers and `s`). This needs a terminal with mouse support, which most have. On Windows, use Windows Terminal; if clicks do nothing there, the keyboard does everything.
55
58
 
56
59
  Your selection is saved to `~/.config/windscout/config.json` (`%USERPROFILE%\.config\windscout\config.json` on Windows) and preselected next time.
57
60
 
@@ -73,25 +76,26 @@ windscout -t 40 -a # longer connect timeout, also list
73
76
  | `-p, --protocols` | comma-separated: `wireguard`, `ikev2` (macOS and Windows), `stealth`, `wstunnel`, `udp`, `tcp`, optionally `:port` | saved, or all |
74
77
  | `-t, --timeout` | seconds to wait for each connection | 20 |
75
78
  | `-a, --all` | include failed attempts in the final table | off |
76
- | `-n, --no-speed` | connect-only mode: skip the download test, rank by latency | saved, or off |
79
+ | `-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 |
77
80
  | `-v, --version` | print the installed version, and the update command if a newer one is on npm | |
78
81
 
79
82
  ## Connect-only mode
80
83
 
81
- Often you only need to know **what connects**, not how fast it is. Turn the speed test off with `s` in the picker or with `--no-speed`. Each working connection is then checked with a quick latency test only. That saves about 15 s per working connection, and results are ranked by latency. The choice is remembered.
84
+ Often you only need to know **what connects**, not how fast it is. Turn the speed test off with `s` in the picker or with `--no-speed`. Each working connection is then checked with a quick latency test only. That saves about 15 s per working connection, and results are ranked by latency. Connect-only is the default on the first run, and the choice is remembered.
82
85
 
83
- Both modes show an **availability grid**: one row per country, and ✓ / ✗ for each protocol (`·` = not tried yet):
86
+ Both modes show an **availability grid**: one row per country, and ✓ / ✗ for each protocol (`·` = not tried yet). Location(s) lists each datacenter that connected, one per line, since protocols can land on different ones:
84
87
 
85
88
  ```
86
- ╭────────────────────────────────────────────────────────────────────────╮
87
- │ Availability 2/3 countries reachable │
88
- ├─────────────────────────┬──────────────────┬─────────┬───────────┬─────┤
89
- │ Country │ City │ stealth │ wireguard │ tcp │
90
- ├─────────────────────────┼──────────────────┼─────────┼───────────┼─────┤
91
- │ 🇩🇪 Germany │ Frankfurt │ ✓ │ ✓ │ ✓ │
92
- │ 🇳🇱 Netherlands │ Amsterdam │ ✓ │ ✓ │ · │
93
- │ 🇦🇪 United Arab Emirates │ Dubai │ ✗ │ ✗ │ ✗ │
94
- ╰─────────────────────────┴──────────────────┴─────────┴───────────┴─────╯
89
+ ╭──────────────────────────────────────────────────────────────────────────────╮
90
+ │ Availability 2/3 countries reachable │
91
+ ├─────────────────────────┬────────────────────────┬─────────┬───────────┬─────┤
92
+ │ Country │ Location(s) │ stealth │ wireguard │ tcp │
93
+ ├─────────────────────────┼────────────────────────┼─────────┼───────────┼─────┤
94
+ │ 🇩🇪 Germany │ Frankfurt - Castle │ ✓ │ ✓ │ ✓ │
95
+ │ │ Frankfurt - Wurst │ │ │ │
96
+ │ 🇳🇱 Netherlands │ Amsterdam - Tulip │ ✓ │ ✓ │ · │
97
+ │ 🇦🇪 United Arab Emirates │ Dubai │ ✗ │ ✗ │ ✗ │
98
+ ╰─────────────────────────┴────────────────────────┴─────────┴───────────┴─────╯
95
99
  ```
96
100
 
97
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.
@@ -127,9 +131,10 @@ At the end, the results, a per-protocol summary and the best pick are printed to
127
131
 
128
132
  ## Notes
129
133
 
130
- - **Connecting by country picks a random datacenter.** A single run tests one per country. Pass city names or nicknames with `-c` to test specific datacenters.
134
+ - **Connecting by country picks a random datacenter.** A single run tests one per country and protocol, so different protocols may land on different datacenters. Pass city names or nicknames with `-c` to test specific datacenters.
131
135
  - **The country list is built in.** On v2.24, `windscribe-cli locations` returns nothing, so WindScout uses a fixed list of country codes. Codes Windscribe doesn't serve are skipped quickly.
132
136
  - **A full scan takes a while.** The worst case is countries × protocols × timeout. Narrow it with `-c` and `-p`.
137
+ - **No flags in macOS Terminal.** Terminal.app draws flag emoji wider than their space, which pushes table borders out of line, so WindScout leaves them out there (as on Windows). iTerm2 and other terminals show them.
133
138
  - **Your connection changes during the scan.** WindScout connects and disconnects the VPN repeatedly, so don't run it while you need a stable connection.
134
139
 
135
140
  ## License
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "windscout",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Find which Windscribe locations and protocols work from your network, ranked by speed (unofficial)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -23,8 +23,19 @@
23
23
  "speedtest",
24
24
  "wireguard",
25
25
  "stealth",
26
- "cli"
26
+ "cli",
27
+ "censorship",
28
+ "firewall",
29
+ "unblock",
30
+ "vpn-speed-test",
31
+ "server-finder"
27
32
  ],
28
33
  "author": "Dier Cohen <i.am.dier.cohen@gmail.com>",
29
- "license": "MIT"
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/Diercohen/windscout.git"
38
+ },
39
+ "homepage": "https://github.com/Diercohen/windscout#readme",
40
+ "bugs": "https://github.com/Diercohen/windscout/issues"
30
41
  }
package/windscout.js CHANGED
@@ -41,8 +41,10 @@ const countryName = (code) => {
41
41
  try { return regionName.of(code); } catch { return code; } // city names / nicknames aren't region codes
42
42
  };
43
43
  // two regional-indicator letters render as the country's flag emoji (Windows has no flag glyphs: it would show
44
- // two boxed letters of unpredictable width and break the table borders, so leave the slot blank there)
45
- const flag = (code) => process.platform !== "win32" && /^[A-Z]{2}$/.test(code) ? String.fromCodePoint(...[...code].map((c) => 0x1f1a5 + c.charCodeAt(0))) : " ";
44
+ // two boxed letters of unpredictable width and break the table borders, so leave the slot blank there).
45
+ // macOS Terminal draws flags ~half a column wider than the 2 it advances, nudging table borders right: blank there too
46
+ const noFlags = process.platform === "win32" || process.env.TERM_PROGRAM === "Apple_Terminal";
47
+ const flag = (code) => !noFlags && /^[A-Z]{2}$/.test(code) ? String.fromCodePoint(...[...code].map((c) => 0x1f1a5 + c.charCodeAt(0))) : " ";
46
48
  let stop = 0;
47
49
  let speedTest = true; // false = connect-only mode: skip the download test, rank by latency
48
50
 
@@ -271,28 +273,31 @@ function matrix(results, protocols, { minWidth = 0, limit = Infinity } = {}) {
271
273
  const ranked = [...byCountry].map(([q, rs]) => ({ q, rs, good: rs.filter((r) => r.status === "ok").length }))
272
274
  .sort((a, b) => b.good - a.good); // stable: ties keep scan order
273
275
  const reachable = ranked.filter((c) => c.good).length;
274
- const rows = ranked.slice(0, limit).map(({ q, rs }) => {
276
+ const rows = ranked.slice(0, limit).flatMap(({ q, rs }) => {
275
277
  const seen = rs.find((r) => r.status === "ok") ?? rs.find((r) => r.location);
276
- // nickname = exact datacenter; protocols can land on different ones, so list each that connected
277
- const nicks = [...new Set(rs.filter((r) => r.status === "ok").map((r) => r.location.split(" - ")[1]).filter(Boolean))];
278
+ // protocols can land on different datacenters (even cities), so list each one that connected, one per line
279
+ const places = [...new Set(rs.filter((r) => r.status === "ok").map((r) => r.location).filter(Boolean))];
280
+ const [first = seen?.location?.split(" - ")[0] || dim("-"), ...more] = places;
278
281
  return [
279
- `${flag(q)} ${countryName(q)}`,
280
- seen?.location?.split(" - ")[0] || dim("-"),
281
- nicks.join(", ") || dim("-"),
282
- ...protocols.map((p) => {
283
- const r = rs.find((x) => x.protocol === p);
284
- return !r ? dim("·") : r.status === "ok" ? green("✓") : red("✗");
285
- }),
282
+ [
283
+ `${flag(q)} ${countryName(q)}`,
284
+ first,
285
+ ...protocols.map((p) => {
286
+ const r = rs.find((x) => x.protocol === p);
287
+ return !r ? dim("·") : r.status === "ok" ? green("✓") : red("✗");
288
+ }),
289
+ ],
290
+ ...more.map((place) => ["", place, ...protocols.map(() => "")]),
286
291
  ];
287
- });
292
+ }).slice(0, limit);
288
293
  return grid(
289
- [{ title: "Country" }, { title: "City" }, { title: "Location" }, ...protocols.map((p) => ({ title: p, align: "center" }))],
294
+ [{ title: "Country" }, { title: "Location(s)" }, ...protocols.map((p) => ({ title: p, align: "center" }))],
290
295
  rows,
291
296
  {
292
297
  caption: bold("Availability"),
293
298
  captionRight: dim(`${reachable}/${ranked.length} countries reachable${ranked.length > limit ? ` · top ${limit}` : ""}`),
294
299
  minWidth,
295
- stretch: 2,
300
+ stretch: 1,
296
301
  },
297
302
  );
298
303
  }