66 red ,
77} from "https://deno.land/[email protected] /fmt/colors.ts" ; 88
9+ const CLI_NAME = "mullvad-ping" ;
10+ const VERSION = "v0.8.0" ;
11+
912type ServerData = {
1013 hostname : string ;
1114 country_code : string ;
@@ -36,24 +39,17 @@ function error(...message: unknown[]) {
3639 Deno . exit ( 1 ) ;
3740}
3841
39- function checkRunMode ( stboot : boolean , runMode : string ) {
40- if ( runMode === "all" ) {
41- return true ;
42- } else if ( runMode === "ram" && stboot === true ) {
43- return true ;
44- } else if ( runMode === "disk" && stboot === false ) {
45- return true ;
46- }
47- return false ;
48- }
49-
5042const serverTypes = [ "openvpn" , "bridge" , "wireguard" , "all" ] ;
51- const runTypes = [ "all" , "ram" , "disk" ] ;
43+ const ownerTypes = [ "mullvad" , "rented" , "all" ] ;
44+ const runTypes = [ "ram" , "disk" , "all" ] ;
5245
5346const INTERVAL_DEFAULT = 0.2 ;
5447const COUNT_DEFAULT = 5 ;
5548const TOP_DEFAULT = 5 ;
5649const PORT_SPEED_DEFAULT = 0 ;
50+ const RUN_MODE_DEFAULT = "all" ;
51+ const OWNER_DEFAULT = "all" ;
52+ const TYPE_DEFAULT = "all" ;
5753
5854const args = parseArgs ( Deno . args , {
5955 "--" : false ,
@@ -63,7 +59,7 @@ const args = parseArgs(Deno.args, {
6359 "interval" ,
6460 "count" ,
6561 "top" ,
66- "owned " ,
62+ "owner " ,
6763 "port-speed" ,
6864 "provider" ,
6965 "run-mode" ,
@@ -75,43 +71,70 @@ const args = parseArgs(Deno.args, {
7571 "list-providers" ,
7672 "include-inactive" ,
7773 "json" ,
74+ "version" ,
7875 ] ,
7976 alias : {
77+ c : "country" ,
78+ l : "list" ,
79+ t : "type" ,
80+ C : "count" ,
81+ n : "top" ,
82+ s : "port-speed" ,
83+ p : "provider" ,
84+ j : "json" ,
8085 h : "help" ,
86+ V : "version" ,
8187 } ,
8288 default : {
8389 interval : `${ INTERVAL_DEFAULT } ` ,
8490 count : `${ COUNT_DEFAULT } ` ,
8591 top : `${ TOP_DEFAULT } ` ,
8692 "port-speed" : `${ PORT_SPEED_DEFAULT } ` ,
87- "run-mode" : "all" ,
88- "type" : "all" ,
93+ "run-mode" : RUN_MODE_DEFAULT ,
94+ owner : OWNER_DEFAULT ,
95+ "type" : TYPE_DEFAULT ,
8996 } ,
9097 unknown : ( arg ) => {
9198 error ( `Unknown argument ${ arg } ` ) ;
9299 } ,
93100} ) ;
94101
95102if ( args . help ) {
96- console . log ( `Usage: script [OPTION]
97- --country <code> the country you want to query (eg. us, gb, de)
98- --list lists the available servers
99- --list-countries lists the available countries
100- --list-providers lists the available providers
101- --type <type> the type of server to query (${
102- serverTypes . join ( ", " )
103- } )
104- --count <n> the number of pings to the server (default ${ COUNT_DEFAULT } )
105- --top <n> the number of top servers to show, (0=all, default ${ TOP_DEFAULT } )
106- --port-speed <n> only show servers with at least n Gigabit port speed
107- --provider <name> only show servers from the given provider
108- --owned <true|false> only show servers owned by Mullvad
109- --run-mode <type> only show servers running from (${
110- runTypes . join ( ", " )
111- } )
112- --include-inactive include inactive servers
113- --json output the results in JSON format
114- --help, -h display this help and exit` ) ;
103+ const serverTypesStr = serverTypes . join ( ", " ) ;
104+ const ownerTypesStr = ownerTypes . join ( ", " ) ;
105+ const runTypesStr = runTypes . join ( ", " ) ;
106+
107+ // This help is formatted like cargo's help
108+ console . log (
109+ `Gets the list of Mullvad servers with the best latency according to ping
110+
111+ ${ green ( bold ( "Usage:" ) ) } ${ cyan ( bold ( CLI_NAME ) ) } ${ cyan ( "[OPTIONS]" ) }
112+
113+ ${ green ( bold ( "Options:" ) ) }
114+ -c, --country <CODE> the country you want to query (eg. us, gb, de)
115+ -l, --list lists the available servers
116+ --list-countries lists the available countries
117+ --list-providers lists the available providers
118+ -t, --type <TYPE> the type of server to query (${ serverTypesStr } )
119+ -C, --count <COUNT> the number of pings to the server (default ${ COUNT_DEFAULT } )
120+ -n, --top <TOPN> the number of top servers to show, (0=all, default ${ TOP_DEFAULT } )
121+ -s, --port-speed <SPEED> only show servers with at least n Gbps port speed
122+ -p, --provider <NAME> only show servers from the given provider
123+ --owner <OWNER> only show servers by owner (${ ownerTypesStr } )
124+ --run-mode <TYPE> only show servers running from (${ runTypesStr } )
125+ --include-inactive include inactive servers
126+ -j, --json output the results in JSON format
127+ -h, --help display this help and exit
128+ -V, --version display version information and exit`
129+ . replace ( / ( - - ? [ a - z A - Z - ] + ) / g, cyan ( bold ( "$1" ) ) )
130+ . replace ( / ( < [ ^ > ] + > ) / g, cyan ( "$1" ) ) ,
131+ ) ;
132+
133+ Deno . exit ( 0 ) ;
134+ }
135+
136+ if ( args . version ) {
137+ console . log ( CLI_NAME , VERSION ) ;
115138 Deno . exit ( 0 ) ;
116139}
117140
@@ -133,25 +156,23 @@ const count = parseInt(args.count) || COUNT_DEFAULT;
133156const topN = parseInt ( args . top ) || TOP_DEFAULT ;
134157const portSpeed = parseInt ( args [ "port-speed" ] ) || PORT_SPEED_DEFAULT ;
135158
159+ const owned = args . owner . toLowerCase ( ) ;
160+ if ( ! ownerTypes . includes ( owned ) ) {
161+ error ( `Invalid owner, allowed types are: ${ ownerTypes . join ( ", " ) } ` ) ;
162+ }
163+
136164const runMode = args [ "run-mode" ] . toLowerCase ( ) ;
137165if ( ! runTypes . includes ( runMode ) ) {
138166 error (
139167 `Invalid run-mode, allowed types are: ${ runTypes . join ( ", " ) } ` ,
140168 ) ;
141169}
142170
143- let owned : boolean | undefined ;
144- if ( typeof args . owned === "string" ) {
145- const argOwner = args . owned . toLowerCase ( ) ;
146- if ( argOwner === "true" ) {
147- owned = true ;
148- } else if ( argOwner === "false" ) {
149- owned = false ;
150- } else {
151- error (
152- "Invalid value for owned, must be true or false. Example: --owned true" ,
153- ) ;
154- }
171+ // ensure that no more than 1 of list, list-countries, list-providers is set
172+ const listCount = [ args . list , args [ "list-countries" ] , args [ "list-providers" ] ]
173+ . filter ( ( e ) => e ) . length ;
174+ if ( listCount > 1 ) {
175+ error ( "Only one of list, list-countries, list-providers can be set" ) ;
155176}
156177
157178const provider = args . provider ;
@@ -176,14 +197,36 @@ if (fetchingSpinner) {
176197 console . log ( ) ;
177198}
178199
200+ function checkRunMode ( stboot : boolean , runMode : string ) {
201+ if ( runMode === "all" ) {
202+ return true ;
203+ } else if ( runMode === "ram" && stboot === true ) {
204+ return true ;
205+ } else if ( runMode === "disk" && stboot === false ) {
206+ return true ;
207+ }
208+ return false ;
209+ }
210+
211+ function checkOwnership ( owned : string , server : ServerData ) {
212+ if ( owned === "all" ) {
213+ return true ;
214+ } else if ( owned === "mullvad" && server . owned ) {
215+ return true ;
216+ } else if ( owned === "rented" && ! server . owned ) {
217+ return true ;
218+ }
219+ return false ;
220+ }
221+
179222const json : Array < ServerData > = await response . json ( ) ;
180223
181224const servers = json . filter ( ( server ) =>
182225 ( country === undefined || country === server . country_code ) &&
183226 ( server . network_port_speed >= portSpeed ) &&
184227 checkRunMode ( server . stboot , runMode ) &&
185228 ( provider === undefined || provider === server . provider ) &&
186- ( owned === undefined || owned === server . owned ) &&
229+ checkOwnership ( owned , server ) &&
187230 ( args [ "include-inactive" ] || server . active )
188231) ;
189232
0 commit comments