1- """
2- A CLI for ProtonVPN.
3-
4- Usage:
5- protonvpn init
6- protonvpn (c | connect) [<servername>] [-p <protocol>]
7- protonvpn (c | connect) [-f | --fastest] [-p <protocol>]
8- protonvpn (c | connect) [--cc <code>] [-p <protocol>]
9- protonvpn (c | connect) [--sc] [-p <protocol>]
10- protonvpn (c | connect) [--p2p] [-p <protocol>]
11- protonvpn (c | connect) [--tor] [-p <protocol>]
12- protonvpn (c | connect) [-r | --random] [-p <protocol>]
13- protonvpn (r | reconnect)
14- protonvpn (d | disconnect)
15- protonvpn (s | status)
16- protonvpn configure
17- protonvpn refresh
18- protonvpn examples
19- protonvpn (-h | --help)
20- protonvpn (-v | --version)
21-
22- Options:
23- -f, --fastest Select the fastest ProtonVPN server.
24- -r, --random Select a random ProtonVPN server.
25- --cc CODE Determine the country for fastest connect.
26- --sc Connect to the fastest Secure-Core server.
27- --p2p Connect to the fastest torrent server.
28- --tor Connect to the fastest Tor server.
29- -p PROTOCOL Determine the protocol (UDP or TCP).
30- -h, --help Show this help message.
31- -v, --version Display version.
32-
33- Commands:
34- init Initialize a ProtonVPN profile.
35- c, connect Connect to a ProtonVPN server.
36- r, reconnect Reconnect to the last server.
37- d, disconnect Disconnect the current session.
38- s, status Show connection status.
39- configure Change ProtonVPN-CLI configuration.
40- refresh Refresh OpenVPN configuration and server data.
41- examples Print some example commands.
42-
43- Arguments:
44- <servername> Servername (CH#4, CH-US-1, HK5-Tor).
45- """
461# Standard Libraries
472import sys
483import os
516import getpass
527import shutil
538import time
54- # External Libraries
55- from docopt import docopt
9+ import argparse
5610# protonvpn-cli Functions
5711from . import connection
5812from .logger import logger
6317)
6418# Constants
6519from .constants import (
66- CONFIG_DIR , CONFIG_FILE , PASSFILE , USER , VERSION , SPLIT_TUNNEL_FILE
20+ CONFIG_DIR , CONFIG_FILE , PASSFILE , USER , VERSION , SPLIT_TUNNEL_FILE , USAGE
6721)
6822
6923
@@ -88,13 +42,62 @@ def cli():
8842 logger .debug ("USER: {0}" .format (USER ))
8943 logger .debug ("CONFIG_DIR: {0}" .format (CONFIG_DIR ))
9044
91- args = docopt (__doc__ , version = "ProtonVPN-CLI v{0}" .format (VERSION ))
92- logger .debug ("Arguments\n {0}" .format (str (args ).replace ("\n " , "" )))
45+ ProtonVPNCLI ()
46+
47+
48+ class ProtonVPNCLI ():
49+ server_features_dict = dict (
50+ p2p = 4 ,
51+ sc = 1 ,
52+ tor = 2
53+ )
54+
55+ def __init__ (self ):
56+ parser = argparse .ArgumentParser (
57+ prog = "protonvpn" ,
58+ add_help = False
59+ )
60+
61+ parser .add_argument ("command" , nargs = "?" )
62+ parser .add_argument ("-v" , "--version" , required = False , action = "store_true" )
63+ parser .add_argument ("-h" , "--help" , required = False , action = "store_true" )
64+
65+ args = parser .parse_args (sys .argv [1 :2 ])
66+
67+ logger .debug ("Main argument\n {0}" .format (args ))
68+
69+ if args .version :
70+ print ("\n ProtonVPN CLI v.{}" .format (VERSION ))
71+ parser .exit (1 )
72+ elif not args .command or not hasattr (self , args .command ) or args .help :
73+ print (USAGE )
74+ parser .exit (1 )
75+
76+ getattr (self , args .command )()
77+
78+ def init (self ):
79+ """CLI command that intialiazes ProtonVPN profile"""
80+ parser = argparse .ArgumentParser (description = "Initialize ProtonVPN profile" , prog = "protonvpn init" )
81+ parser .add_argument (
82+ "-i" , "--inline" , nargs = 3 , required = False ,
83+ help = "Inline intialize profile. (username password protocol)" , metavar = ""
84+ )
85+
86+ args = parser .parse_args (sys .argv [2 :])
87+ logger .debug ("Sub-arguments\n {0}" .format (args ))
88+
89+ if args .inline :
90+ print ("Please intialize without '-i/--inline' as it is not fully supported yet." )
91+ sys .exit (1 )
9392
94- # Parse arguments
95- if args .get ("init" ):
9693 init_cli ()
97- elif args .get ("c" ) or args .get ("connect" ):
94+
95+ def c (self ):
96+ """Short CLI command for connecting to the VPN"""
97+ self .connect ()
98+
99+ def connect (self ):
100+ """Full CLI command for connecting to the VPN"""
98101 check_root ()
99102 check_init ()
100103
@@ -106,45 +109,97 @@ def cli():
106109 if int (os .environ .get ("PVPN_WAIT" , 0 )) > 0 :
107110 wait_for_network (int (os .environ ["PVPN_WAIT" ]))
108111
109- protocol = args .get ("-p" )
110- if protocol is not None and protocol .lower ().strip () in ["tcp" , "udp" ]:
112+ parser = argparse .ArgumentParser (description = "Connect to ProtonVPN" , prog = "protonvpn c" )
113+ group = parser .add_mutually_exclusive_group ()
114+ group .add_argument ("servername" , nargs = "?" , help = "Servername (CH#4, CH-US-1, HK5-Tor)." , metavar = "" )
115+ group .add_argument ("-f" , "--fastest" , help = "Connect to the fastest ProtonVPN server." , action = "store_true" )
116+ group .add_argument ("-r" , "--random" , help = "Connect to a random ProtonVPN server." , action = "store_true" )
117+ group .add_argument ("--cc" , help = "Connect to the specified country code (SE, PT, BR, AR)." , metavar = "" )
118+ group .add_argument ("--sc" , help = "Connect to the fastest Secure-Core server." , action = "store_true" )
119+ group .add_argument ("--p2p" , help = "Connect to the fastest torrent server." , action = "store_true" )
120+ group .add_argument ("--tor" , help = "Connect to the fastest Tor server." , action = "store_true" )
121+ parser .add_argument (
122+ "-p" , "--protocol" , help = "Connect via specified protocol." ,
123+ choices = ["udp" , "tcp" ], metavar = "" , type = str .lower
124+ )
125+
126+ args = parser .parse_args (sys .argv [2 :])
127+ logger .debug ("Sub-arguments:\n {0}" .format (args ))
128+
129+ protocol = args .protocol
130+ if protocol and protocol .lower ().strip () in ["tcp" , "udp" ]:
111131 protocol = protocol .lower ().strip ()
112132
113- if args .get ( "-- random" ) :
133+ if args .random :
114134 connection .random_c (protocol )
115- elif args .get ( "-- fastest" ) :
135+ elif args .fastest :
116136 connection .fastest (protocol )
117- elif args .get ("<servername>" ):
118- connection .direct (args .get ("<servername>" ), protocol )
119- elif args .get ("--cc" ) is not None :
120- connection .country_f (args .get ("--cc" ), protocol )
121- # Features: 1: Secure-Core, 2: Tor, 4: P2P
122- elif args .get ("--p2p" ):
123- connection .feature_f (4 , protocol )
124- elif args .get ("--sc" ):
125- connection .feature_f (1 , protocol )
126- elif args .get ("--tor" ):
127- connection .feature_f (2 , protocol )
137+ elif args .servername :
138+ connection .direct (args .servername , protocol )
139+ elif args .cc :
140+ connection .country_f (args .cc , protocol )
141+ elif args .p2p :
142+ connection .feature_f (self .server_features_dict .get ("p2p" , None ), protocol )
143+ elif args .sc :
144+ connection .feature_f (self .server_features_dict .get ("sc" , None ), protocol )
145+ elif args .tor :
146+ connection .feature_f (self .server_features_dict .get ("tor" , None ), protocol )
128147 else :
129148 connection .dialog ()
130- elif args .get ("r" ) or args .get ("reconnect" ):
149+
150+ def r (self ):
151+ """Short CLI command to reconnect to the last connected VPN Server"""
152+ self .reconnect ()
153+
154+ def reconnect (self ):
155+ """Full CLI command to reconnect to the last connected VPN Server"""
131156 check_root ()
132157 check_init ()
133158 connection .reconnect ()
134- elif args .get ("d" ) or args .get ("disconnect" ):
159+
160+ def d (self ):
161+ """Short CLI command to disconnect the VPN if a connection is present"""
162+ self .disconnect ()
163+
164+ def disconnect (self ):
165+ """Full CLI command to disconnect the VPN if a connection is present"""
135166 check_root ()
136167 check_init ()
137168 connection .disconnect ()
138- elif args .get ("s" ) or args .get ("status" ):
169+
170+ def s (self ):
171+ """Short CLI command to display the current VPN status"""
172+ self .status ()
173+
174+ def status (self ):
175+ """Full CLI command to display the current VPN status"""
139176 connection .status ()
140- elif args .get ("configure" ):
177+
178+ def cf (self ):
179+ """Short CLI command to change single configuration values"""
180+ self .configure ()
181+
182+ def configure (self ):
183+ """Full CLI command to change single configuration values"""
141184 check_root ()
142185 check_init ()
143186 configure_cli ()
144- elif args .get ("refresh" ):
187+
188+ def rf (self ):
189+ """Short CLI command to refresh server list"""
190+ self .refresh ()
191+
192+ def refresh (self ):
193+ """Full CLI command to refresh server list"""
145194 check_init ()
146195 pull_server_data (force = True )
147- elif args .get ("examples" ):
196+
197+ def ex (self ):
198+ """Short CLI command to display usage examples"""
199+ self .examples ()
200+
201+ def examples (self ):
202+ """Full CLI command to display usage examples"""
148203 print_examples ()
149204
150205
0 commit comments