Skip to content

Commit bfcbacd

Browse files
committed
Add argument --not-check-update
`get_stats_display` now width default terminal size 80
1 parent 4932e09 commit bfcbacd

1 file changed

Lines changed: 83 additions & 73 deletions

File tree

src/main.py

Lines changed: 83 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232

3333
__version__ = "2.1"
3434

35-
os.system("")
36-
3735

3836
class 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

6968
class 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

12011208
class 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

12891296
class 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

Comments
 (0)