feat: dzgui 7 alpha

This commit is contained in:
aclist committed 2025-12-08 17:32:25 +09:00
1 parent 1acdbd58c5
commit 2e5b771137
150 files changed
+10359

No files matched your search

View File
Whitespace-only changes.
+72
View File
@@ -0,0 +1,72 @@
import json
import shlex
from pathlib import Path
"""
Convert legacy dztuirc to config.json
"""
class UnsupportedKey(Exception):
pass
def str2bool(string: str) -> bool:
s = string.lower()
match s:
case "":
return False
case "0":
return False
case "1" | "2":
return True
case "false":
return False
case "true":
return True
case _:
raise UnsupportedKey(f"The key {s} is not a valid config key.")
def rc2json(file: Path) -> str:
with open(file, "r") as f:
lex = shlex.shlex(f.read())
lex.whitespace += "="
d = {}
ips: list[str] = []
toggles = ["auto_install", "debug", "fullscreen"]
deprecated = ["staging_dir", "src_path", "steam_path"]
while True:
tok = lex.get_token()
ntok = lex.get_token()
if ntok is not None:
ntok = ntok.strip('""')
if tok in deprecated:
continue
elif tok in toggles:
ntok = str2bool(ntok)
elif tok == "preferred_client":
tok = "client"
elif tok == "api_key":
tok = "bm_api"
elif tok == "ip_list":
while True:
ntok = lex.get_token().strip('""')
if ntok == ")":
break
ips.append(ntok)
continue
if not tok:
break
d[tok] = ntok
d["ip_list"] = ips
d["use_miles"] = False
return json.dumps(d, indent=2)
+42
View File
@@ -0,0 +1,42 @@
import shutil
import textwrap
from pathlib import Path
def write_desktop_file(share_path: Path) -> None:
template = f"""\
[Desktop Entry]
Version=1.0
Type=Application
Terminal=false
Exec={share_path}/launch.sh
Name=DZGUI
Comment=dzgui
Icon={share_path}/dzgui
Categories=Game"""
file = share_path / "dzgui.desktop"
file.write_text(textwrap.dedent(template))
def write_shim_file(share_path: Path) -> None:
# FIXME: expects sys.prefix to be a venv
file = share_path / "launch.sh"
template=f"""\
source {venv}/bin/activate
python3.13 dzgui
"""
try:
file.write_text(textwrap.dedent(template))
f.chmod(f.stat().st_mode | stat.S_IEXEC)
except OSError:
logger.critical(e)
return
clear_old_path()
write_desktop_file(share_path)
def clear_old_path() -> None:
home = Path.home()
path = home / ".local/share/dzgui"
shutil.rmtree(path)
+97
View File
@@ -0,0 +1,97 @@
import gzip
import logging
import re
import requests
import shutil
from pathlib import Path
from dzgui.const.constants import REQUEST_TIMEOUT
from dzgui.const.endpoints import DB_IP
logger = logging.getLogger(__name__)
def find_download_url(url: str) -> str | None:
res = requests.get(url, timeout=REQUEST_TIMEOUT)
res.raise_for_status()
reg = r'ref=[\'"]([^\'">]+.csv.gz)'
urls = re.findall(reg, res.text)
if len(urls) < 1:
return None
return str(urls[0])
def get_ipdb(ips_path: Path) -> None:
url = find_download_url(DB_IP)
if url is None:
return
date = find_date(url)
month_file = ips_path.parent / ".month"
if month_file.exists() is True:
old_date = month_file.read_text().rstrip("\n")
if old_date == date:
logger.info(f"IP DB date matches: {date}")
return
# TODO: log additional output
logger.info(f"Fetching IPDB for {date} from {url}")
try:
tmp = serialize(url)
except Exception as e:
logger.critical(e)
return
logger.info(f"Extracting {tmp}")
unzip(tmp, ips_path)
logger.info("Stripping IPv6 records")
try:
strip_ipv6(ips_path)
except Exception as e:
logger.critical(e)
return
with open(month_file, "w") as f:
f.write(date)
logger.info(f"Wrote {date} to {month_file}")
def find_date(url: str) -> str:
date = re.sub(r"(dbip-city-lite-)(.*)(.csv.gz)", r"\2", url)
date = date.split("/")[-1]
return date
def unzip(tmp: Path, ips_path: Path) -> None:
with gzip.open(tmp, "rb") as f:
with open(ips_path, "wb") as outfile:
shutil.copyfileobj(f, outfile)
tmp.unlink()
def serialize(url: str) -> Path:
with requests.get(url, stream=True) as r:
r.raise_for_status()
filename = "ips.csv.gz"
tmp = Path("/tmp") / filename
with open(tmp, "wb") as f:
shutil.copyfileobj(r.raw, f)
return tmp
# TODO: optimize this function
# consider using grep
# cf. grep -vE "^[a-z0-9]{4}:" | grep -v "::" > "$ip_file"
def strip_ipv6(path: Path) -> None:
ips = []
with open(path, "r") as f:
s = f.read()
reg = r"^\d{1,3}\..*"
ips = re.findall(reg, s, re.MULTILINE)
assert ips[0].split(",")[0] == "0.0.0.0"
assert ips[-1].split(",")[0] == "224.0.0.0"
with open(path, "w") as f:
for ip in ips:
f.write(ip + "\n")
+60
View File
@@ -0,0 +1,60 @@
from typing import Any
from pathlib import Path
from dzgui.util._json import read_json
from dzgui.const.enum import Preferences
from dzgui.const.constants import STEAM_CMD, FLATPAK_RUN_CMD, FLATPAK_SANDBOX
class ConfigFileError(Exception):
pass
def lookup(path: Path, enum: Preferences) -> Any:
if path.is_file() is False:
raise ConfigFileError("Not a valid file")
key = enum_to_key(enum)
config = get_config(path)
try:
return config[key]
except KeyError:
return None
def get_config(path: Path) -> dict:
# TODO: is this being called twice?
try:
json = read_json(path)
except Exception as e:
raise e
return json
def get_favorites(path: Path) -> list[str]:
try:
conf = get_config(path)
except Exception as e:
pass
return conf["ip_list"]
def is_in_favs(record: str, path: Path) -> bool:
favs = get_favorites(path)
if record in favs:
return True
return False
def enum_to_key(enum: Preferences) -> str:
return enum.dict["key"]
def get_client_index(client: str) -> int:
if client == STEAM_CMD:
return 0
elif client == FLATPAK_RUN_CMD:
return 1
else:
return 2
+10
View File
@@ -0,0 +1,10 @@
import shutil
from pathlib import Path
def uninstall(path: Path) -> None
# TODO: use xdg object?
# partial/full (keep config?)
# -u removes state, log
# XDG_SHARE_HOME/dzgui
# XDG_STATE_HOME/dzgui
# XDG_DATA_HOME/dzgui
+25
View File
@@ -0,0 +1,25 @@
from pathlib import Path
from dzgui.const.enum import Preferences
from dzgui.config.query import get_config, enum_to_key
from dzgui.util._json import write_json
# TEST: parametrize writing config values and checking config output in test
def toggle_config(path: Path, key: Preferences) -> None:
real_key = enum_to_key(key)
try:
conf = get_config(path)
cur_val = conf[real_key]
conf[real_key] = not cur_val
write_json(conf, path)
except Exception as e:
raise e
def write_config(path: Path, key: Preferences, value: str) -> None:
real_key = enum_to_key(key)
try:
conf = get_config(path)
conf[real_key] = value
write_json(conf, path)
except Exception as e:
raise e
+12
View File
@@ -0,0 +1,12 @@
from dataclasses import dataclass
from dzgui.config.xdg import Xdg
from dzgui.util.ip import Coords
@dataclass(slots=True, frozen=True)
class UserPrefs:
is_steam_deck: bool
is_game_mode: bool
coords: Coords | None
version: str
allow_updates: bool
paths: Xdg
+90
View File
@@ -0,0 +1,90 @@
import os
from pathlib import Path
from dataclasses import dataclass
from dzgui.const.constants import APP_NAME_LOWER, DEBUG_LOG, SYSTEM_LOG
@dataclass
class Xdg:
config: Path
columns: Path
notes: Path
resolution: Path
history: Path
version: Path
system: Path
debug: Path
ips: Path
def is_writeable(path_str: str) -> bool:
if path_str is None:
return False
path = Path(path_str)
if not path.exists():
try:
path.mkdir(parents=True)
except OSError:
return False
path.unlink()
return True
try:
file = Path(path / "temp")
with open(file, "w") as f:
f.write("")
except Exception:
return False
file.unlink()
return True
def get_xdg_paths() -> dict:
home = Path.home()
xdg_paths = {
"XDG_CONFIG_HOME": home / ".config",
"XDG_STATE_HOME": home / ".local" / "state",
"XDG_DATA_HOME": home / ".local" / "share",
"XDG_CACHE_HOME": home / ".cache",
}
resolved_paths = {}
for path in xdg_paths:
rp = os.environ.get(path)
resolved_paths[path] = Path(rp) / APP_NAME_LOWER if is_writeable(rp) else xdg_paths[path] / APP_NAME_LOWER
return resolved_paths
def parse_filepaths(xdg: dict) -> Xdg:
# cache = xdg["XDG_CACHE_HOME"]
# data = xdg["XDG_DATA_HOME"]
config = xdg["XDG_CONFIG_HOME"]
state = xdg["XDG_STATE_HOME"]
config = config / "config.json"
system = state / "logs" / SYSTEM_LOG
debug = state / "logs" / DEBUG_LOG
columns = state / "dzg.cols.json"
notes = state / "dzg.notes.json"
resolution = state / "dzg.res.json"
history = state / "dzg.history"
versions = state / "dzg.versions"
ips = state / "ips.csv"
return Xdg(
config,
columns,
notes,
resolution,
history,
versions,
system,
debug,
ips,
)