Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 3 additions & 16 deletions pyclashbot/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import locale
import multiprocessing as mp
import os
import subprocess
from multiprocessing import Event, Queue
from os.path import expandvars, join
Expand Down Expand Up @@ -39,6 +38,7 @@ def _setlocale_safe(category: int, loc: str | None = None) -> str:
from pyclashbot.utils.cli_config import arg_parser
from pyclashbot.utils.discord_rpc import DiscordRPCManager
from pyclashbot.utils.logger import Logger, initalize_pylogging, log_dir
from pyclashbot.utils.open_folder import open_folder
from pyclashbot.utils.platform import is_macos

if TYPE_CHECKING:
Expand Down Expand Up @@ -207,25 +207,12 @@ def handle_process_finished(

def open_recordings_folder() -> None:
folder_path = join(expandvars("%localappdata%"), "programs", "py-clash-bot", "recordings")
os.makedirs(folder_path, exist_ok=True)
try:
os.startfile(folder_path)
except AttributeError:
# Non-Windows fallback
import subprocess

subprocess.Popen(["xdg-open", folder_path])
open_folder(folder_path)


def open_logs_folder() -> None:
folder_path = log_dir
os.makedirs(folder_path, exist_ok=True)
try:
os.startfile(folder_path)
except AttributeError:
import subprocess

subprocess.Popen(["xdg-open", folder_path])
open_folder(folder_path)


class BotApplication:
Expand Down
45 changes: 35 additions & 10 deletions pyclashbot/utils/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
import zipfile
from functools import wraps
from os import listdir, makedirs, remove
from os.path import exists, getmtime, join
from os.path import basename, exists, getmtime, join

from pyclashbot.utils.machine_info import MACHINE_INFO
from pyclashbot.utils.platform import get_log_dir
from pyclashbot.utils.versioning import __version__

Expand All @@ -35,21 +34,40 @@ def compress_logs() -> None:
"a" if exists(archive_name) else "w",
) as archive:
for log in logs[:-LOGS_TO_KEEP]:
archive.write(log, log.split("\\")[-1])
# Use basename so this works on all platforms (Windows, macOS, Linux)
archive.write(log, basename(log))
remove(log)


def initalize_pylogging() -> None:
"""Method to be called once to initalize python logging"""
if not exists(log_dir):
makedirs(log_dir)
logging.basicConfig(
filename=log_name,
encoding="utf-8",
level=logging.DEBUG,
format="%(levelname)s:%(asctime)s %(message)s",
)

root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)

# Ensure we always have a file handler, even if something logged earlier (which would
# make logging.basicConfig(...) a no-op).
already_has_log_file = False
for handler in root_logger.handlers:
if isinstance(handler, logging.FileHandler):
try:
if handler.baseFilename == log_name:
already_has_log_file = True
break
except Exception:
continue

if not already_has_log_file:
file_handler = logging.FileHandler(log_name, encoding="utf-8")
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(logging.Formatter("%(levelname)s:%(asctime)s %(message)s"))
root_logger.addHandler(file_handler)

logging.info("Logging initialized for %s", __version__)
logging.info("Log directory: %s", log_dir)
logging.info("Current log file: %s", log_name)
logging.info(
"""
____ _ _ ___ __ __ ___ _ _ ____ _____ ____
Expand All @@ -60,12 +78,19 @@ def initalize_pylogging() -> None:
)
logging.info(
"Machine Info: \n%s",
pprint.pformat(MACHINE_INFO, sort_dicts=False, indent=4),
pprint.pformat(_get_machine_info(), sort_dicts=False, indent=4),
)

compress_logs()


def _get_machine_info() -> dict:
# Delayed import to avoid logging before handlers are installed.
from pyclashbot.utils.machine_info import MACHINE_INFO

return MACHINE_INFO


class Logger:
"""Class for logging. Allows for cross-thread, console and file logging.

Expand Down
29 changes: 29 additions & 0 deletions pyclashbot/utils/open_folder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Open folders in the OS file explorer (Finder/Explorer/etc)."""

from __future__ import annotations

import logging
import os
import subprocess

from pyclashbot.utils.platform import is_macos, is_windows


def open_folder(folder_path: str) -> None:
"""Open a folder in the platform's file explorer."""
os.makedirs(folder_path, exist_ok=True)

try:
if is_windows():
os.startfile(folder_path) # type: ignore[attr-defined]
return

if is_macos():
subprocess.Popen(["open", folder_path])
else:
subprocess.Popen(["xdg-open", folder_path])
except FileNotFoundError as exc:
logging.error("Folder opener command not found when opening %s: %s", folder_path, exc)
except Exception as exc:
# Log but don't crash the UI
logging.error("Failed to open folder %s: %s", folder_path, exc)
Loading