p / Client /main.py
q6's picture
S
52fadc8
import os
import runpy
import sys
from typing import Dict, Sequence, Tuple
ROOT_DIR = os.path.abspath(os.path.dirname(__file__))
SCRIPTS_DIR = os.path.join(ROOT_DIR, "Scripts")
EXTRACT_DIR = os.path.join(SCRIPTS_DIR, "Extract Pixiv")
RESET = "\x1b[0m"
BOLD = "\x1b[1m"
FG_PRIMARY = "\x1b[38;5;81m"
FG_ACCENT = "\x1b[38;5;214m"
FG_MUTED = "\x1b[38;5;245m"
FG_OK = "\x1b[38;5;120m"
FG_ERROR = "\x1b[38;5;203m"
RULE = "-" * 56
EXIT_KEYS = {"q", "quit", "exit"}
MENU_SECTIONS: Sequence[Tuple[str, Sequence[Tuple[str, str, str]]]] = (
(
"Extract Pixiv",
(
("1", "Search (all tags)", os.path.join(EXTRACT_DIR, "search.py")),
("2", "Search (AI only)", os.path.join(EXTRACT_DIR, "ai_search.py")),
("3", "Search (real only)", os.path.join(EXTRACT_DIR, "real_search.py")),
("4", "Users", os.path.join(EXTRACT_DIR, "user.py")),
),
),
(
"Hunt",
(
("5", "Hunt", os.path.join(SCRIPTS_DIR, "hunt.py")),
("6", "Scan existing exif", os.path.join(SCRIPTS_DIR, "scan_existing_exif.py")),
),
),
(
"Maintenance",
(
("7", "Clear text logs", os.path.join(SCRIPTS_DIR, "clear_texts.py")),
("8", "Clear DB empty rows", os.path.join(SCRIPTS_DIR, "clear_db.py")),
("9", "Clear images (except Stash)", os.path.join(SCRIPTS_DIR, "clear_images.py")),
),
),
)
ACTION_MAP: Dict[str, Tuple[str, str]] = {
key: (label, path)
for _, items in MENU_SECTIONS
for key, label, path in items
}
def style(text: str, *codes: str) -> str:
if not codes:
return text
return "".join(codes) + text + RESET
def print_menu() -> None:
print(style("Pixif", FG_PRIMARY, BOLD))
print(style(RULE, FG_MUTED))
for section, items in MENU_SECTIONS:
print(style(section, FG_ACCENT, BOLD))
for key, label, _ in items:
print(f" {style(key, FG_PRIMARY, BOLD)} {label}")
print(style(RULE, FG_MUTED))
print(f" {style('q', FG_MUTED)} Quit")
def run_script(path: str) -> int:
if not os.path.isfile(path):
print(style(f"Missing: {path}", FG_ERROR))
return 1
original_cwd = os.getcwd()
original_sys_path = list(sys.path)
script_dir = os.path.dirname(path)
sys.path.insert(0, script_dir)
if ROOT_DIR not in sys.path:
sys.path.insert(0, ROOT_DIR)
try:
os.chdir(ROOT_DIR)
try:
runpy.run_path(path, run_name="__main__")
except SystemExit as exc:
if isinstance(exc.code, int):
return exc.code
return 0
return 0
except KeyboardInterrupt:
print(style("Cancelled.", FG_ERROR))
return 130
except Exception as exc:
print(style(f"Error: {exc}", FG_ERROR))
return 1
finally:
os.chdir(original_cwd)
sys.path[:] = original_sys_path
def main() -> int:
os.chdir(ROOT_DIR)
while True:
print_menu()
choice = input(style("Select an option: ", FG_MUTED)).strip().lower()
if choice in EXIT_KEYS:
return 0
action = ACTION_MAP.get(choice)
if not action:
print(style("Unknown option.", FG_ERROR))
continue
label, path = action
print(style(f"Running {label}...", FG_PRIMARY, BOLD))
code = run_script(path)
if code == 0:
print(style("Done.", FG_OK))
else:
print(style(f"Exit code: {code}", FG_ERROR))
input(style("Press Enter to return to menu.", FG_MUTED))
if __name__ == "__main__":
raise SystemExit(main())