@@ -6,6 +6,10 @@ use std::{
66use reqwest:: { Client , Error } ;
77use colored:: * ;
88
9+ use serde_json:: Value ;
10+ use semver:: { Version } ;
11+
12+ /// Reusable function that just prints success messages to the console
913fn print_info ( text : & str , is_secondary : bool ) {
1014 if is_secondary {
1115 println ! ( "{}" , text. green( ) . italic( ) . dimmed( ) ) ;
@@ -14,7 +18,7 @@ fn print_info(text: &str, is_secondary: bool) {
1418 } ;
1519}
1620
17-
21+ /// Prints the AdGuardian ASCII art to console
1822fn print_ascii_art ( ) {
1923 let art = r"
2024 █████╗ ██████╗ ██████╗ ██╗ ██╗ █████╗ ██████╗ ██████╗ ██╗ █████╗ ███╗ ██╗
@@ -30,19 +34,22 @@ fn print_ascii_art() {
3034 print_info ( "For documentation and support, please visit: https://github.com/lissy93/adguardian-term\n " , true ) ;
3135}
3236
33- fn print_error ( address : & str , error : Option < & Error > ) {
37+ /// Print error message, along with (optional) stack trace, then exit
38+ fn print_error ( message : & str , sub_message : & str , error : Option < & Error > ) {
3439 eprintln ! (
35- "{}{}" ,
36- format!( "Failed to connect to AdGuard at {}" , address ) . red( ) ,
40+ "{}{}{} " ,
41+ format!( "{}" , message ) . red( ) ,
3742 match error {
3843 Some ( err) => format!( "\n {}" , err) . red( ) . dimmed( ) ,
3944 None => "" . red( ) . dimmed( ) ,
4045 } ,
46+ format!( "\n {}" , sub_message) . yellow( ) ,
4147 ) ;
42- eprintln ! ( "{}\n {}" , "\n Please check your environmental variables and try again." . yellow( ) , "Exiting..." . blue( ) ) ;
43- }
4448
49+ std:: process:: exit ( 1 ) ;
50+ }
4551
52+ /// Given a key, get the value from the environmental variables, and print it to the console
4653fn get_env ( key : & str ) -> Result < String , env:: VarError > {
4754 env:: var ( key) . map ( |v| {
4855 println ! (
@@ -58,6 +65,39 @@ fn get_env(key: &str) -> Result<String, env::VarError> {
5865 } )
5966}
6067
68+ /// Given a possibly undefined version number, check if it's present and supported
69+ fn check_version ( version : Option < & str > ) {
70+ let min_version = Version :: parse ( "0.107.29" ) . unwrap ( ) ;
71+
72+ match version {
73+ Some ( version_str) => {
74+ let adguard_version = Version :: parse ( & version_str[ 1 ..] ) . unwrap ( ) ;
75+
76+ if adguard_version < min_version {
77+ print_error (
78+ "AdGuard Home version is too old, and is now unsupported" ,
79+ format ! ( "You're running AdGuard {}. Please upgrade to v{} or later." , version_str, min_version. to_string( ) ) . as_str ( ) ,
80+ None ,
81+ ) ;
82+ }
83+ } ,
84+ None => {
85+ print_error (
86+ "Unsupported AdGuard Home version" ,
87+ format ! (
88+ concat!(
89+ "Failed to get the version number of your AdGuard Home instance.\n " ,
90+ "This usually means you're running an old, and unsupported version.\n " ,
91+ "Please upgrade to v{} or later."
92+ ) , min_version. to_string( )
93+ ) . as_str ( ) ,
94+ None ,
95+ ) ;
96+ }
97+ }
98+ }
99+
100+ /// With the users specified AdGuard details, verify the connection (exit on fail)
61101async fn verify_connection (
62102 client : & Client ,
63103 ip : String ,
@@ -82,16 +122,44 @@ async fn verify_connection(
82122 . send ( )
83123 . await {
84124 Ok ( res) if res. status ( ) . is_success ( ) => {
85- println ! ( "{}" , "AdGuard connection successful!\n " . green( ) ) ;
125+ // Get version string (if present), and check if valid - exit if not
126+ let body: Value = res. json ( ) . await ?;
127+ check_version ( body[ "version" ] . as_str ( ) ) ;
128+ // All good! Print success message :)
129+ let safe_version = body[ "version" ] . as_str ( ) . unwrap_or ( "mystery version" ) ;
130+ println ! ( "{}" , format!( "AdGuard ({}) connection successful!\n " , safe_version) . green( ) ) ;
86131 Ok ( ( ) )
87132 }
88- Ok ( _) | Err ( _) => {
89- print_error ( & format ! ( "{}:{}" , ip, port) , None ) ;
90- std:: process:: exit ( 1 ) ;
133+ // Connection failed to authenticate. Print error and exit
134+ Ok ( _) => {
135+ print_error (
136+ & format ! ( "Authentication with AdGuard at {}:{} failed" , ip, port) ,
137+ "Please check your environmental variables and try again." ,
138+ None ,
139+ ) ;
140+ Ok ( ( ) )
141+ } ,
142+ // Connection failed to establish. Print error and exit
143+ Err ( e) => {
144+ print_error (
145+ & format ! ( "Failed to connect to AdGuard at: {}:{}" , ip, port) ,
146+ "Please check your environmental variables and try again." ,
147+ Some ( & e) ,
148+ ) ;
149+ Ok ( ( ) )
91150 }
92151 }
93152}
94153
154+ /// Initiate the welcome script
155+ /// This function will:
156+ /// - Print the AdGuardian ASCII art
157+ /// - Check for the required environmental variables
158+ /// - Prompt the user to enter any missing variables
159+ /// - Verify the connection to the AdGuard instance
160+ /// - Verify authentication is successful
161+ /// - Verify the AdGuard Home version is supported
162+ /// - Then either print a success message, or show instructions to fix and exit
95163pub async fn welcome ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
96164 print_ascii_art ( ) ;
97165 println ! ( "{}" , "Starting initialization checks..." . blue( ) ) ;
@@ -138,11 +206,13 @@ pub async fn welcome() -> Result<(), Box<dyn std::error::Error>> {
138206 }
139207 }
140208
209+ // Grab the values of the (now set) environmental variables
141210 let ip = get_env ( "ADGUARD_IP" ) ?;
142211 let port = get_env ( "ADGUARD_PORT" ) ?;
143212 let protocol = get_env ( "ADGUARD_PROTOCOL" ) ?;
144213 let username = get_env ( "ADGUARD_USERNAME" ) ?;
145214 let password = get_env ( "ADGUARD_PASSWORD" ) ?;
146215
216+ // Verify that we can connect, authenticate, and that version is supported (exit on failure)
147217 verify_connection ( & client, ip, port, protocol, username, password) . await
148218}
0 commit comments