3232
3333__version__ = "2.1"
3434
35- os .system ("" )
36-
3735
3836class ConnectionInfo :
3937 """Class to store connection information"""
@@ -64,6 +62,7 @@ def __init__(self):
6462 self .no_blacklist = False
6563 self .auto_blacklist = False
6664 self .quiet = False
65+ self .not_check_update = True
6766
6867
6968class IBlacklistManager (ABC ):
@@ -285,7 +284,7 @@ def emit(self, record):
285284 )
286285 error_handler .setFormatter (
287286 logging .Formatter (
288- "[%(asctime)s][%(levelname)s]: %(message)s" , "%Y-%m-%d %H:%M:%S"
287+ "[%(asctime)s][%(levelname)s] %(message)s" , "%Y-%m-%d %H:%M:%S"
289288 )
290289 )
291290 error_handler .setLevel (logging .ERROR )
@@ -414,6 +413,12 @@ def update_speeds(self) -> None:
414413 def get_stats_display (self ) -> str :
415414 """Get formatted statistics display"""
416415
416+ if sys .stdout .isatty ():
417+ console_width = os .get_terminal_size ().columns
418+ else :
419+ console_width = 80
420+ # self.logger.debug("console_width=", console_width)
421+
417422 col_width = 30
418423
419424 conns_stat = f"\033 [97mTotal: \033 [93m{ self .total_connections } \033 [0m" .ljust (
@@ -470,17 +475,15 @@ def get_stats_display(self) -> str:
470475 )
471476 )
472477
473- title = "STATISTICS"
478+ title = " STATISTICS "
474479
475- top_border = f"\033 [92m{ '═' * 36 } { title } { '═' * 36 } \033 [0m"
476- line_conns = f"\033 [92m { 'Conns' .ljust (8 )} :\033 [0m { conns_stat } \033 [0m"
477- line_traffic = f"\033 [92m { 'Traffic' .ljust (8 )} :\033 [0m { traffic_stat } \033 [0m"
478- line_speed = f"\033 [92m { 'Speed' .ljust (8 )} :\033 [0m { speed_stat } \033 [0m"
479- bottom_border = f"\033 [92m{ '═' * ( 36 * 2 + len ( title ) + 2 ) } \033 [0m"
480+ top_border = f"\033 [92m{ title . center ( console_width , '=' ) } \033 [0m"
481+ line_conns = f"\033 [92m{ 'Conns' .ljust (8 )} :\033 [0m { conns_stat } \033 [0m"
482+ line_traffic = f"\033 [92m{ 'Traffic' .ljust (8 )} :\033 [0m { traffic_stat } \033 [0m"
483+ line_speed = f"\033 [92m{ 'Speed' .ljust (8 )} :\033 [0m { speed_stat } \033 [0m"
484+ bottom_border = f"\033 [92m{ '═' * console_width } \033 [0m"
480485
481- return (
482- f"{ top_border } \n { line_conns } \n { line_traffic } \n { line_speed } \n { bottom_border } "
483- )
486+ return '\n ' .join ((top_border , line_conns , line_traffic , line_speed , bottom_border ))
484487
485488 @staticmethod
486489 def format_size (size : int ) -> str :
@@ -910,6 +913,7 @@ async def check_for_updates(self):
910913
911914 def sync_check ():
912915 try :
916+ # self.logger.debug("Check for updates")
913917 req = Request (
914918 "https://gvcoder09.github.io/nodpi_site/api/v1/update_info.json" ,
915919 )
@@ -929,7 +933,7 @@ def sync_check():
929933 if latest_version :
930934 self .update_available = latest_version
931935 self .update_event .set ()
932- return f"\033 [93m[UPDATE]: Available new version: v{ latest_version } \033 [97m"
936+ return f"\033 [93m[UPDATE] Available new version: v{ latest_version } \033 [97m"
933937 except Exception :
934938 pass
935939 finally :
@@ -939,19 +943,20 @@ def sync_check():
939943 async def print_banner (self ) -> None :
940944 """Print startup banner"""
941945
942- self .update_check_task = asyncio .create_task (self .check_for_updates ())
946+ if not self .config .not_check_update :
947+ self .update_check_task = asyncio .create_task (self .check_for_updates ())
943948
944- try :
945- await asyncio .wait_for (self .update_event .wait (), timeout = 2.0 )
946- except asyncio .TimeoutError :
947- if self .update_check_task and not self .update_check_task .done ():
948- self .update_check_task .cancel ()
949- try :
950- await self .update_check_task
951- except asyncio .CancelledError :
952- pass
949+ try :
950+ await asyncio .wait_for (self .update_event .wait (), timeout = 2.0 )
951+ except asyncio .TimeoutError :
952+ if self .update_check_task and not self .update_check_task .done ():
953+ self .update_check_task .cancel ()
954+ try :
955+ await self .update_check_task
956+ except asyncio .CancelledError :
957+ pass
953958
954- self .logger .info ("\033 ]0;NoDPI\007 " )
959+ # self.logger.info("\033]0;NoDPI\007")
955960
956961 if sys .platform == "win32" :
957962 os .system ("mode con: lines=33" )
@@ -960,6 +965,7 @@ async def print_banner(self) -> None:
960965 console_width = os .get_terminal_size ().columns
961966 else :
962967 console_width = 80
968+ # self.logger.debug("console_width=", console_width)
963969
964970 disclaimer = (
965971 "DISCLAIMER. The developer and/or supplier of this software "
@@ -979,7 +985,7 @@ async def print_banner(self) -> None:
979985
980986 left_padding = (console_width - 76 ) // 2
981987
982- self .logger .info ("\n \n \n " )
988+ # self.logger.info("\n\n\n")
983989 self .logger .info (
984990 "\033 [91m" + " " * left_padding + "╔" + "═" * 72 + "╗" + "\033 [0m"
985991 )
@@ -997,83 +1003,83 @@ async def print_banner(self) -> None:
9971003
9981004 time .sleep (1 )
9991005
1000- update_message = None
1001- if self .update_check_task and self .update_check_task .done ():
1002- try :
1003- update_message = self .update_check_task .result ()
1004- except (asyncio .CancelledError , Exception ):
1005- pass
1006-
1007- self .logger .info ("\033 [2J\033 [H" )
1006+ # self.logger.info("\033[2J\033[H")
10081007
10091008 self .logger .info (
1010- """
1011- \033 [92m ██████ █████ ██████████ ███████████ █████
1009+ """\033 [92m
1010+ ██████ █████ ██████████ ███████████ █████
10121011 ░░██████ ░░███ ░░███░░░░███ ░░███░░░░░███░░███
10131012 ░███░███ ░███ ██████ ░███ ░░███ ░███ ░███ ░███
10141013 ░███░░███░███ ███░░███ ░███ ░███ ░██████████ ░███
10151014 ░███ ░░██████ ░███ ░███ ░███ ░███ ░███░░░░░░ ░███
10161015 ░███ ░░█████ ░███ ░███ ░███ ███ ░███ ░███
10171016 █████ ░░█████░░██████ ██████████ █████ █████
1018- ░░░░░ ░░░░░ ░░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░\033 [0m
1019- """
1017+ ░░░░░ ░░░░░ ░░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░
1018+ \033 [0m """
10201019 )
1021- self .logger .info (f"\033 [92mVersion: { __version__ } " .center (50 ))
1020+ self .logger .info (f"\033 [92mVersion: { __version__ } " .center (console_width ))
10221021 self .logger .info (
10231022 "\033 [97m" +
1024- "Enjoy watching! / Наслаждайтесь просмотром!" .center (50 )
1023+ "Enjoy watching! / Наслаждайтесь просмотром!" .center (console_width )
10251024 )
10261025
1027- self .logger .info ("\n " )
1026+ # self.logger.info("\n")
10281027
1029- if update_message :
1030- self .logger .info (update_message )
1028+ if not self .config .not_check_update :
1029+ update_message = None
1030+ if self .update_check_task and self .update_check_task .done ():
1031+ try :
1032+ update_message = self .update_check_task .result ()
1033+ except (asyncio .CancelledError , Exception ):
1034+ pass
1035+ if update_message :
1036+ self .logger .info (update_message )
10311037
10321038 self .logger .info (
1033- f"\033 [92m[INFO]: \033 [97m Proxy is running on { self .config .host } :{ self .config .port } at { datetime .now ().strftime ('%H:%M on %Y-%m-%d' )} "
1039+ f"\033 [92m[INFO]\033 [97m Proxy is running on { self .config .host } :{ self .config .port } at { datetime .now ().strftime ('%H:%M on %Y-%m-%d' )} "
10341040 )
10351041 self .logger .info (
1036- f"\033 [92m[INFO]: \033 [97m The selected fragmentation method: { self .config .fragment_method } "
1042+ f"\033 [92m[INFO]\033 [97m The selected fragmentation method: { self .config .fragment_method } "
10371043 )
10381044
1039- self .logger .info ("" )
1045+ # self.logger.info("")
10401046 if isinstance (self .blacklist_manager , NoBlacklistManager ):
10411047 self .logger .info (
1042- "\033 [92m[INFO]: \033 [97m Blacklist is disabled. All domains will be subject to unblocking."
1048+ "\033 [92m[INFO]\033 [97m Blacklist is disabled. All domains will be subject to unblocking."
10431049 )
10441050 elif isinstance (self .blacklist_manager , AutoBlacklistManager ):
10451051 self .logger .info (
1046- "\033 [92m[INFO]: \033 [97m Auto-blacklist is enabled" )
1052+ "\033 [92m[INFO]\033 [97m Auto-blacklist is enabled" )
10471053 else :
10481054 self .logger .info (
1049- f"\033 [92m[INFO]: \033 [97m Blacklist contains { len (self .blacklist_manager .blocked )} domains"
1055+ f"\033 [92m[INFO]\033 [97m Blacklist contains { len (self .blacklist_manager .blocked )} domains"
10501056 )
10511057 self .logger .info (
1052- f"\033 [92m[INFO]: \033 [97m Path to blacklist: '{ os .path .normpath (self .config .blacklist_file )} '"
1058+ f"\033 [92m[INFO]\033 [97m Path to blacklist: '{ os .path .normpath (self .config .blacklist_file )} '"
10531059 )
10541060
1055- self .logger .info ("" )
1061+ # self.logger.info("")
10561062 if self .config .log_error_file :
10571063 self .logger .info (
1058- f"\033 [92m[INFO]: \033 [97m Error logging is enabled. Path to error log: '{ self .config .log_error_file } '"
1064+ f"\033 [92m[INFO]\033 [97m Error logging is enabled. Path to error log: '{ self .config .log_error_file } '"
10591065 )
10601066 else :
10611067 self .logger .info (
1062- "\033 [92m[INFO]: \033 [97m Error logging is disabled" )
1068+ "\033 [92m[INFO]\033 [97m Error logging is disabled" )
10631069
10641070 if self .config .log_access_file :
10651071 self .logger .info (
1066- f"\033 [92m[INFO]: \033 [97m Access logging is enabled. Path to access log: '{ self .config .log_access_file } '"
1072+ f"\033 [92m[INFO]\033 [97m Access logging is enabled. Path to access log: '{ self .config .log_access_file } '"
10671073 )
10681074 else :
10691075 self .logger .info (
1070- "\033 [92m[INFO]: \033 [97m Access logging is disabled" )
1076+ "\033 [92m[INFO]\033 [97m Access logging is disabled" )
10711077
1072- self .logger .info ("" )
1078+ # self.logger.info("")
10731079 self .logger .info (
1074- "\033 [92m[INFO]: \033 [97m To stop the proxy, press Ctrl+C twice"
1080+ "\033 [92m[INFO]\033 [97m To stop the proxy, press Ctrl+C twice"
10751081 )
1076- self .logger .info ("" )
1082+ # self.logger.info("")
10771083
10781084 async def display_stats (self ) -> None :
10791085 """Display live statistics"""
@@ -1100,7 +1106,7 @@ async def run(self) -> None:
11001106 )
11011107 except OSError :
11021108 self .logger .error (
1103- f"\033 [91m[ERROR]: Failed to start proxy on this address ({ self .config .host } :{ self .config .port } ). It looks like the port is already in use\033 [0m"
1109+ f"\033 [91m[ERROR] Failed to start proxy on this address ({ self .config .host } :{ self .config .port } ). It looks like the port is already in use\033 [0m"
11041110 )
11051111 sys .exit (1 )
11061112
@@ -1133,7 +1139,7 @@ def create(config: ProxyConfig, logger: ILogger) -> IBlacklistManager:
11331139 try :
11341140 return FileBlacklistManager (config )
11351141 except FileNotFoundError as e :
1136- logger .error (f"\033 [91m[ERROR]: { e } \033 [0m" )
1142+ logger .error (f"\033 [91m[ERROR] { e } \033 [0m" )
11371143 sys .exit (1 )
11381144
11391145
@@ -1155,6 +1161,7 @@ def load_from_args(args) -> ProxyConfig:
11551161 config .no_blacklist = args .no_blacklist
11561162 config .auto_blacklist = args .autoblacklist
11571163 config .quiet = args .quiet
1164+ config .not_check_update = args .not_check_update
11581165 return config
11591166
11601167
@@ -1182,20 +1189,20 @@ def manage_autostart(action: str = "install") -> None:
11821189 f'"{ exe_path } " --blacklist "{ os .path .dirname (exe_path )} /blacklist.txt"' ,
11831190 )
11841191 print (
1185- f"\033 [92m[INFO]: \033 [97m Added to autostart: { exe_path } " )
1192+ f"\033 [92m[INFO]\033 [97m Added to autostart: { exe_path } " )
11861193
11871194 elif action == "uninstall" :
11881195 try :
11891196 with winreg .OpenKey (key , reg_path , 0 , winreg .KEY_WRITE ) as regkey :
11901197 winreg .DeleteValue (regkey , app_name )
1191- print ("\033 [92m[INFO]: \033 [97m Removed from autostart" )
1198+ print ("\033 [92m[INFO]\033 [97m Removed from autostart" )
11921199 except FileNotFoundError :
1193- print ("\033 [91m[ERROR]: Not found in autostart\033 [0m" )
1200+ print ("\033 [91m[ERROR] Not found in autostart\033 [0m" )
11941201
11951202 except PermissionError :
1196- print ("\033 [91m[ERROR]: Access denied. Run as administrator\033 [0m" )
1203+ print ("\033 [91m[ERROR] Access denied. Run as administrator\033 [0m" )
11971204 except Exception as e :
1198- print (f"\033 [91m[ERROR]: Autostart operation failed: { e } \033 [0m" )
1205+ print (f"\033 [91m[ERROR] Autostart operation failed: { e } \033 [0m" )
11991206
12001207
12011208class LinuxAutostartManager (IAutostartManager ):
@@ -1248,15 +1255,15 @@ def manage_autostart(action: str = "install") -> None:
12481255 )
12491256
12501257 print (
1251- f"\033 [92m[INFO]: \033 [97m Service installed and started: { service_name } "
1258+ f"\033 [92m[INFO]\033 [97m Service installed and started: { service_name } "
12521259 )
1253- print ("\033 [93m[NOTE]: \033 [97m Service will auto-start on login" )
1260+ print ("\033 [93m[NOTE]\033 [97m Service will auto-start on login" )
12541261
12551262 except subprocess .CalledProcessError as e :
1256- print (f"\033 [91m[ERROR]: Systemd command failed: { e } \033 [0m" )
1263+ print (f"\033 [91m[ERROR] Systemd command failed: { e } \033 [0m" )
12571264 except Exception as e :
12581265 print (
1259- f"\033 [91m[ERROR]: Autostart operation failed: { e } \033 [0m" )
1266+ f"\033 [91m[ERROR] Autostart operation failed: { e } \033 [0m" )
12601267
12611268 elif action == "uninstall" :
12621269 try :
@@ -1277,13 +1284,13 @@ def manage_autostart(action: str = "install") -> None:
12771284 subprocess .run (
12781285 ["systemctl" , "--user" , "daemon-reload" ], check = True )
12791286
1280- print ("\033 [92m[INFO]: \033 [97m Service removed from autostart" )
1287+ print ("\033 [92m[INFO]\033 [97m Service removed from autostart" )
12811288
12821289 except subprocess .CalledProcessError as e :
1283- print (f"\033 [91m[ERROR]: Systemd command failed: { e } \033 [0m" )
1290+ print (f"\033 [91m[ERROR] Systemd command failed: { e } \033 [0m" )
12841291 except Exception as e :
12851292 print (
1286- f"\033 [91m[ERROR]: Autostart operation failed: { e } \033 [0m" )
1293+ f"\033 [91m[ERROR] Autostart operation failed: { e } \033 [0m" )
12871294
12881295
12891296class ProxyApplication :
@@ -1335,6 +1342,9 @@ def parse_args():
13351342 parser .add_argument (
13361343 "-q" , "--quiet" , action = "store_true" , help = "Remove UI output"
13371344 )
1345+ parser .add_argument (
1346+ "--not-check-update" , action = "store_true" , help = "Do not check for updates"
1347+ )
13381348
13391349 autostart_group = parser .add_mutually_exclusive_group ()
13401350 autostart_group .add_argument (
@@ -1373,7 +1383,7 @@ async def run(cls):
13731383 sys .exit (0 )
13741384 else :
13751385 print (
1376- "\033 [91m[ERROR]: Autostart works only in executable version\033 [0m"
1386+ "\033 [91m[ERROR] Autostart works only in executable version\033 [0m"
13771387 )
13781388 sys .exit (1 )
13791389
@@ -1395,7 +1405,7 @@ async def run(cls):
13951405 except asyncio .CancelledError :
13961406 await proxy .shutdown ()
13971407 logger .info (
1398- "\n " * 6 + "\033 [92m[INFO]: \033 [97m Shutting down proxy..." )
1408+ "\n " * 6 + "\033 [92m[INFO]\033 [97m Shutting down proxy..." )
13991409 try :
14001410 if sys .platform == "win32" :
14011411 os .system ("mode con: lines=3000" )
0 commit comments