diff --git a/main.py b/main.py index 5be59e8..2468bc0 100644 --- a/main.py +++ b/main.py @@ -265,22 +265,18 @@ def main(): # ── LAN sharing configuration ──────────────────────────────────────── lan_sharing = config.get("lan_sharing", False) + listen_host = config.get("listen_host", "127.0.0.1") if lan_sharing: # If LAN sharing is enabled and host is still localhost, change to all interfaces - if config.get("listen_host", "127.0.0.1") == "127.0.0.1": + if listen_host == "127.0.0.1": config["listen_host"] = "0.0.0.0" + listen_host = "0.0.0.0" log.info("LAN sharing enabled — listening on all interfaces") - log.info("HTTP proxy : %s:%d", - config.get("listen_host", "127.0.0.1"), - config.get("listen_port", 8080)) - if config.get("socks5_enabled", True): - log.info("SOCKS5 proxy : %s:%d", - config.get("socks5_host", config.get("listen_host", "127.0.0.1")), - config.get("socks5_port", 1080)) - - # Log LAN access addresses if sharing is enabled - if lan_sharing: + # If either explicit LAN sharing is enabled or we bind to all interfaces, + # print concrete IPv4 addresses users can use on other devices. + lan_mode = lan_sharing or listen_host in ("0.0.0.0", "::") + if lan_mode: socks_port = config.get("socks5_port", 1080) if config.get("socks5_enabled", True) else None log_lan_access(config.get("listen_port", 8080), socks_port) diff --git a/src/logging_utils.py b/src/logging_utils.py index 423cfee..55162d7 100644 --- a/src/logging_utils.py +++ b/src/logging_utils.py @@ -124,7 +124,7 @@ class PrettyFormatter(logging.Formatter): def _fmt_time(self, record: logging.LogRecord) -> str: t = time.localtime(record.created) ms = int((record.created - int(record.created)) * 1000) - return f"{time.strftime('%H:%M:%S', t)}.{ms:03d}" + return f"{time.strftime('%H:%M:%S', t)}" def _fmt_level(self, levelname: str) -> str: label = LEVEL_LABEL.get(levelname, levelname[:5].ljust(5)) @@ -227,7 +227,7 @@ def _install_asyncio_noise_filter() -> None: def print_banner(version: str, *, stream=None) -> None: - """Print a compact startup banner with color fallbacks.""" + """Print a polished startup banner with color fallbacks.""" stream = stream or sys.stderr color = _supports_color(stream) @@ -235,14 +235,36 @@ def print_banner(version: str, *, stream=None) -> None: return code if color else "" title = "MasterHttpRelayVPN" - subtitle = f"Domain-Fronted Apps Script Relay · v{version}" - bar = "─" * (len(title) + len(subtitle) + 7) + subtitle = "Domain-Fronted Apps Script Relay" + version_tag = f"v{version}" - print(f"{c(DIM)}{c(FG_GRAY)}{bar}{c(RESET)}", file=stream) - print( - f" {c(BOLD)}{c(FG_CYAN)}{title}{c(RESET)}" - f" {c(DIM)}·{c(RESET)} {c(FG_GRAY)}{subtitle}{c(RESET)}", - file=stream, - ) - print(f"{c(DIM)}{c(FG_GRAY)}{bar}{c(RESET)}", file=stream) + left = f" {title} " + center = f" {subtitle} " + right = f" {version_tag} " + inner_width = max(68, len(left) + len(center) + len(right) + 2) + + gap = inner_width - (len(left) + len(center) + len(right)) + left_gap = gap // 2 + right_gap = gap - left_gap + + top = "╭" + ("─" * inner_width) + "╮" + mid = "│" + left + (" " * left_gap) + center + (" " * right_gap) + right + "│" + bot = "╰" + ("─" * inner_width) + "╯" + + if color: + top = f"{DIM}{FG_GRAY}{top}{RESET}" + bot = f"{DIM}{FG_GRAY}{bot}{RESET}" + mid = ( + f"{DIM}{FG_GRAY}│{RESET}" + f"{BOLD}{FG_CYAN}{left}{RESET}" + f"{' ' * left_gap}" + f"{FG_GRAY}{center}{RESET}" + f"{' ' * right_gap}" + f"{BOLD}{FG_TEAL}{right}{RESET}" + f"{DIM}{FG_GRAY}│{RESET}" + ) + + print(top, file=stream) + print(mid, file=stream) + print(bot, file=stream) stream.flush()