diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..39d0179 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "ms-python.vscode-pylance", + "ms-python.python", + "ms-python.debugpy", + "charliermarsh.ruff", + "davidanson.vscode-markdownlint", + "esbenp.prettier-vscode" + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index ebe8cb3..e2cbfda 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,7 +6,7 @@ "configurations": [ { "name": "Python: 現在のファイル", - "type": "python", + "type": "debugpy", "request": "launch", "program": "${file}", "console": "integratedTerminal", @@ -14,7 +14,7 @@ }, { "name": "DMMGamePlayerFastLauncher", - "type": "python", + "type": "debugpy", "request": "launch", "program": "DMMGamePlayerFastLauncher/DMMGamePlayerFastLauncher.py", "console": "integratedTerminal", @@ -25,7 +25,7 @@ }, { "name": "GameLauncher", - "type": "python", + "type": "debugpy", "request": "launch", "program": "DMMGamePlayerFastLauncher/DMMGamePlayerFastLauncher.py", "console": "integratedTerminal", @@ -37,7 +37,7 @@ }, { "name": "LaunchLauncher", - "type": "python", + "type": "debugpy", "request": "launch", "program": "DMMGamePlayerFastLauncher/DMMGamePlayerFastLauncher.py", "console": "integratedTerminal", diff --git a/.vscode/settings.json b/.vscode/settings.json index 5fefd11..1cf313c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,17 +1,12 @@ { - "flake8.args": ["--ignore=E501,E731"], "markdownlint.config": { "MD033": false }, "python.analysis.typeCheckingMode": "basic", "editor.codeActionsOnSave": { - "source.organizeImports": true + "source.organizeImports": "explicit", + "source.fixAll": "explicit", }, - "black-formatter.args": ["--line-length=180"], - "[json]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "files.exclude": { "**/__pycache__": true, "**/build": true, @@ -20,4 +15,4 @@ "**/*.spec": true, "**/.venv": true } -} +} \ No newline at end of file diff --git a/DMMGamePlayerFastLauncher/DMMGamePlayerFastLauncher.py b/DMMGamePlayerFastLauncher/DMMGamePlayerFastLauncher.py index 974ff5c..a59b5c4 100644 --- a/DMMGamePlayerFastLauncher/DMMGamePlayerFastLauncher.py +++ b/DMMGamePlayerFastLauncher/DMMGamePlayerFastLauncher.py @@ -8,7 +8,7 @@ import i18n from app import App from coloredlogs import ColoredFormatter -from component.logger import StyleScheme, TkinkerLogger +from component.logger import LoggingHandlerMask, StyleScheme, TkinkerLogger from launch import GameLauncher, LanchLauncher from lib.DGPSessionV2 import DgpSessionV2 from models.setting_data import AppConfig @@ -36,7 +36,8 @@ def loder(master: LanchLauncher): handlers.append(handler) if AppConfig.DATA.debug_window.get() and not any([isinstance(x, LoggingHandler) for x in logging.getLogger().handlers]): - handler = LoggingHandler(TkinkerLogger(master).create().box, scheme=StyleScheme) + handle = LoggingHandlerMask if AppConfig.DATA.mask_token.get() else LoggingHandler + handler = handle(TkinkerLogger(master).create().box, scheme=StyleScheme) handler.setFormatter(ColoredFormatter("[%(levelname)s] [%(asctime)s] %(message)s")) handlers.append(handler) @@ -114,4 +115,3 @@ def loder(master: LanchLauncher): lanch.mainloop() else: raise Exception("type error") - raise Exception("type error") diff --git a/DMMGamePlayerFastLauncher/component/component.py b/DMMGamePlayerFastLauncher/component/component.py index 36c7878..8fb5db8 100644 --- a/DMMGamePlayerFastLauncher/component/component.py +++ b/DMMGamePlayerFastLauncher/component/component.py @@ -6,9 +6,8 @@ import customtkinter as ctk import i18n from component.var import PathVar -from customtkinter import CTkBaseClass, CTkButton, CTkCheckBox, CTkEntry, CTkFrame, CTkLabel, CTkOptionMenu, CTkProgressBar, CTkToplevel +from customtkinter import CTkBaseClass, CTkButton, CTkCheckBox, CTkEntry, CTkFrame, CTkLabel, CTkOptionMenu, CTkProgressBar, CTkToplevel, Variable from customtkinter import ThemeManager as CTkm -from customtkinter import Variable class LabelComponent(CTkFrame): diff --git a/DMMGamePlayerFastLauncher/component/logger.py b/DMMGamePlayerFastLauncher/component/logger.py index b743781..7b2cf24 100644 --- a/DMMGamePlayerFastLauncher/component/logger.py +++ b/DMMGamePlayerFastLauncher/component/logger.py @@ -1,6 +1,8 @@ +import re + import customtkinter as ctk from customtkinter import CTkTextbox, CTkToplevel -from tkinter_colored_logging_handlers.main import ColorSchemeLight, StyleSchemeBase +from tkinter_colored_logging_handlers import ColorSchemeLight, LoggingHandler, StyleSchemeBase class StyleScheme(StyleSchemeBase, ColorSchemeLight): @@ -23,3 +25,10 @@ def __init__(self, master): def create(self): self.box.pack(fill=ctk.BOTH, padx=10, pady=(0, 10), expand=True) return self + + +class LoggingHandlerMask(LoggingHandler): + def format(self, record): + formated = super().format(record) + formated = re.sub(r"(?<=\=)[0-9a-zA-Z]{32,}", lambda x: f"\033[31m[CENSORED {len(x.group())}]\033[0m", formated) + return formated diff --git a/DMMGamePlayerFastLauncher/models/setting_data.py b/DMMGamePlayerFastLauncher/models/setting_data.py index 6b7f1e3..cd84865 100644 --- a/DMMGamePlayerFastLauncher/models/setting_data.py +++ b/DMMGamePlayerFastLauncher/models/setting_data.py @@ -5,6 +5,7 @@ from component.variable_base import VariableBase from lib.DGPSessionV2 import DgpSessionV2 from static.env import Env +from utils.utils import get_default_locale @dataclass @@ -17,12 +18,13 @@ class SettingData(VariableBase): dmm_proxy_http: StringVar = field(default_factory=StringVar) dmm_proxy_https: StringVar = field(default_factory=StringVar) dmm_proxy_socks: StringVar = field(default_factory=StringVar) - lang: StringVar = field(default_factory=lambda: StringVar(value="ja")) + lang: StringVar = field(default_factory=lambda: StringVar(value=get_default_locale()[0])) theme: StringVar = field(default_factory=lambda: StringVar(value="blue")) appearance_mode: StringVar = field(default_factory=lambda: StringVar(value="dark")) window_scaling: DoubleVar = field(default_factory=lambda: DoubleVar(value=1.0)) debug_window: BooleanVar = field(default_factory=lambda: BooleanVar(value=False)) output_logfile: BooleanVar = field(default_factory=lambda: BooleanVar(value=False)) + mask_token: BooleanVar = field(default_factory=lambda: BooleanVar(value=True)) def update(self): DgpSessionV2.DGP5_PATH = self.dmm_game_player_program_folder.get_path() diff --git a/DMMGamePlayerFastLauncher/static/env.py b/DMMGamePlayerFastLauncher/static/env.py index bedec0a..9821d8d 100644 --- a/DMMGamePlayerFastLauncher/static/env.py +++ b/DMMGamePlayerFastLauncher/static/env.py @@ -8,7 +8,7 @@ class Env(Dump): - VERSION = "v5.3.0" + VERSION = "v5.4.0" RELEASE_VERSION = requests.get(UrlConfig.RELEASE_API).json().get("tag_name", VERSION) DEVELOP: bool = os.environ.get("ENV") == "DEVELOP" diff --git a/DMMGamePlayerFastLauncher/static/loder.py b/DMMGamePlayerFastLauncher/static/loder.py index b879267..d59167e 100644 --- a/DMMGamePlayerFastLauncher/static/loder.py +++ b/DMMGamePlayerFastLauncher/static/loder.py @@ -2,6 +2,7 @@ from models.setting_data import AppConfig, DeviceData, SettingData from static.config import DataPathConfig +from utils.utils import get_supported_lang def config_loder(): @@ -19,5 +20,8 @@ def config_loder(): with open(DataPathConfig.DEVICE, "w+", encoding="utf-8") as f: json.dump(AppConfig.DEVICE.to_dict(), f) + if AppConfig.DATA.lang.get() not in [x[0] for x in get_supported_lang()]: + AppConfig.DATA.lang.set("en_US") + AppConfig.DATA.update() AppConfig.DEVICE.update() diff --git a/DMMGamePlayerFastLauncher/tab/account.py b/DMMGamePlayerFastLauncher/tab/account.py index 838856b..6f62cc4 100644 --- a/DMMGamePlayerFastLauncher/tab/account.py +++ b/DMMGamePlayerFastLauncher/tab/account.py @@ -241,7 +241,9 @@ def create(self): for key, value in hardware.items(): EntryComponent(self, text=key, variable=StringVar(value=value), state=ctk.DISABLED).create() - command = lambda id=hardware["hardware_manage_id"]: self.delete_callback(id) + def command(id=hardware["hardware_manage_id"]): + return self.delete_callback(id) + CTkButton(self, text=i18n.t("app.account.delete"), command=command).pack(fill=ctk.X, pady=10) PaddingComponent(self, height=20).create() diff --git a/DMMGamePlayerFastLauncher/tab/setting.py b/DMMGamePlayerFastLauncher/tab/setting.py index 17cdd56..bca37b1 100644 --- a/DMMGamePlayerFastLauncher/tab/setting.py +++ b/DMMGamePlayerFastLauncher/tab/setting.py @@ -10,6 +10,7 @@ from lib.toast import ToastController, error_toast from models.setting_data import AppConfig, DeviceData, SettingData from static.config import AssetsPathConfig, DataPathConfig +from utils.utils import get_supported_lang class SettingTab(CTkFrame): @@ -46,7 +47,7 @@ def __init__(self, master: CTkBaseClass): super().__init__(master, fg_color="transparent") self.toast = ToastController(self) self.data = AppConfig.DATA - self.lang = [(y, i18n.t("app.language", locale=y)) for y in [x.suffixes[0][1:] for x in AssetsPathConfig.I18N.iterdir()]] + self.lang = get_supported_lang() self.theme = [x.stem for x in AssetsPathConfig.THEMES.iterdir()] @@ -72,6 +73,7 @@ def create(self): PaddingComponent(self, height=5).create() CheckBoxComponent(self, text=i18n.t("app.setting.debug_window"), variable=self.data.debug_window).create() CheckBoxComponent(self, text=i18n.t("app.setting.output_logfile"), variable=self.data.output_logfile).create() + CheckBoxComponent(self, text=i18n.t("app.setting.mask_token"), variable=self.data.mask_token).create() PaddingComponent(self, height=5).create() CTkButton(self, text=i18n.t("app.setting.save"), command=self.save_callback).pack(fill=ctk.X, pady=10) diff --git a/DMMGamePlayerFastLauncher/tab/shortcut.py b/DMMGamePlayerFastLauncher/tab/shortcut.py index f4f756e..d57891e 100644 --- a/DMMGamePlayerFastLauncher/tab/shortcut.py +++ b/DMMGamePlayerFastLauncher/tab/shortcut.py @@ -14,7 +14,7 @@ from models.shortcut_data import LauncherShortcutData, ShortcutData from static.config import DataPathConfig from static.env import Env -from utils.utils import children_destroy, file_create +from utils.utils import children_destroy, file_create, get_default_locale # ===== Shortcut Sub Menu ===== @@ -160,7 +160,15 @@ def get_game_info(self) -> tuple[str, Path, bool]: title = title.replace(":", "").replace("*", "").replace("?", "") title = title.replace('"', "").replace("<", "").replace(">", "").replace("|", "") - return title, game_path.joinpath(data["exec_file_name"]), data["is_administrator"] + file = game_path.joinpath(data["exec_file_name"]) + + if get_default_locale()[1] == "cp932": + return (title, file, data["is_administrator"]) + + if all(ord(c) < 128 for c in title): + return (title, file, data["is_administrator"]) + + return (self.filename.get(), file, data["is_administrator"]) class ShortcutCreate(ShortcutBase): diff --git a/DMMGamePlayerFastLauncher/utils/utils.py b/DMMGamePlayerFastLauncher/utils/utils.py index 62d840e..db89d34 100644 --- a/DMMGamePlayerFastLauncher/utils/utils.py +++ b/DMMGamePlayerFastLauncher/utils/utils.py @@ -1,8 +1,10 @@ +import locale from pathlib import Path from tkinter import Misc -from typing import Optional, TypeVar +from typing import Optional, Tuple, TypeVar import i18n +from static.config import AssetsPathConfig T = TypeVar("T") @@ -28,3 +30,16 @@ def file_create(path: Path, name: str): raise FileExistsError(i18n.t("app.utils.file_exists", name=name)) else: path.touch() + + +def get_supported_lang() -> list[tuple[str, str]]: + return [(y, i18n.t("app.language", locale=y)) for y in [x.suffixes[0][1:] for x in AssetsPathConfig.I18N.iterdir()]] + + +def get_default_locale() -> Tuple[str, str]: + lang, encoding = locale.getdefaultlocale() + if lang not in [x[0] for x in get_supported_lang()]: + lang = "en" + if encoding is None: + encoding = "utf-8" + return lang, encoding diff --git a/a.py b/a.py deleted file mode 100644 index 1f7ab38..0000000 --- a/a.py +++ /dev/null @@ -1,49 +0,0 @@ -from pathlib import Path - -from DMMGamePlayerFastLauncher.lib.DgpSessionWrap import DgpSessionWrap - -session = DgpSessionWrap.read_cookies(Path("data/account/a.bytes")) - - -json = {} -res = session.post_dgp( - "https://apidgp-gameplayer.games.dmm.com/v5/hardwarelist", json=json, verify=False -) -print(res.json()) - - -# json = { -# "mac_address": "00:00:00:00:00:00", -# "hdd_serial": "00000000", -# "motherboard": "00000000", -# "user_os": "win", -# } -# res = session.post_dgp("https://apidgp-gameplayer.games.dmm.com/v5/hardwarecode", json=json, verify=False) -# print(res.json()) - -# json = { -# "mac_address": "00:00:00:00:00:00", -# "hdd_serial": "00000000", -# "motherboard": "00000000", -# "user_os": "win", -# "hardware_name": input("hardware_name: "), -# "auth_code": input("auth_code: "), -# } -# res = session.post_dgp("https://apidgp-gameplayer.games.dmm.com/v5/hardwareconf", json=json, verify=False) -# print(res.json()) - -json = { - "mac_address": "00:00:00:00:00:00", - "hdd_serial": "00000000", - "motherboard": "00000000", - "user_os": "win", - "product_id": "priconner", - "game_type": "GCL", - "game_os": "win", - "launch_type": "LIB", -} - -res = session.post_dgp( - "https://apidgp-gameplayer.games.dmm.com/v5/launch/pkg", json=json, verify=False -) -print(res.json()) diff --git a/assets/i18n/app.en.yml b/assets/i18n/app.en_US.yml similarity index 94% rename from assets/i18n/app.en.yml rename to assets/i18n/app.en_US.yml index 2ff94ab..42cea91 100644 --- a/assets/i18n/app.en.yml +++ b/assets/i18n/app.en_US.yml @@ -1,4 +1,4 @@ -en: +en_US: title: DMMGamePlayer Fast Launcher language: English @@ -22,7 +22,9 @@ en: shortcut: filename: File Name - filename_tooltip: Please provide any name for this shortcut. + filename_tooltip: |- + Please provide any name for this shortcut. + Using non-alphanumeric characters may cause problems. product_id: Select product_id product_id_tooltip: | @@ -73,7 +75,9 @@ en: Importing will log you out of DMMGamePlayer 5. Do not log in directly with an imported account in DMMGamePlayer 5. - filename_tooltip: Please provide any name for this account. + filename_tooltip: |- + Please provide any name for this account. + Using non-alphanumeric characters may cause problems. import: Import filename: File Name filename_not_entered: File name is not entered. @@ -130,6 +134,7 @@ en: window_scaling: Window Scaling debug_window: Show Debug Window output_logfile: Log to File + mask_token: Hide tokens on the log device_detail: |- Configure device information for device authentication. diff --git a/assets/i18n/app.ja.yml b/assets/i18n/app.ja_JP.yml similarity index 93% rename from assets/i18n/app.ja.yml rename to assets/i18n/app.ja_JP.yml index 7571209..53b7b47 100644 --- a/assets/i18n/app.ja.yml +++ b/assets/i18n/app.ja_JP.yml @@ -1,4 +1,4 @@ -ja: +ja_JP: title: DMMGamePlayer Fast Launcher language: 日本語 @@ -22,7 +22,9 @@ ja: shortcut: filename: ファイル名 - filename_tooltip: このショートカットに任意の名前を付けてください。 + filename_tooltip: |- + このショートカットに任意の名前を付けてください。 + 半角英数字以外を使用すると問題が発生する可能性があります。 product_id: product_idの選択 product_id_tooltip: |- @@ -75,7 +77,9 @@ ja: インポートをするとDMMGamePlayer5からログアウトされます。 インポート済みのアカウントで直接起動した DMMGamePlayer5 でログインをしないでください。 - filename_tooltip: このアカウントに任意の名前を付けてください。 + filename_tooltip: |- + このアカウントに任意の名前を付けてください。 + 半角英数字以外を使用すると問題が発生する可能性があります。 import: インポート filename: ファイル名 filename_not_entered: ファイル名が入力されていません。 @@ -131,6 +135,7 @@ ja: window_scaling: ウィンドウの拡大率 debug_window: デバッグウィンドウを表示する output_logfile: ログをファイルで出力する + mask_token: ログ上のトークンを隠す device_detail: |- デバイス認証に使用するデバイス情報を設定します。 diff --git a/assets/i18n/app.zh_CN.yml b/assets/i18n/app.zh_CN.yml index 16ef34f..8c54e9a 100644 --- a/assets/i18n/app.zh_CN.yml +++ b/assets/i18n/app.zh_CN.yml @@ -25,9 +25,9 @@ zh_CN: filename_tooltip: 请为此快捷方式提供任何名称。 product_id: 选择 product_id - product_id_tooltip: | + product_id_tooltip: |- product_id 是 DMM 用于识别游戏的 ID。 - + 非英数字字符的使用可能导致问题。 account_create_detail: |- 创建一个用于快速启动 DMMGamePlayer 的快捷方式。 请在“帐户”选项卡中选择您创建的帐户。 @@ -72,7 +72,9 @@ zh_CN: 导入操作将注销 DMMGamePlayer 5。 请勿直接在 DMMGamePlayer 5 中使用已导入的帐户登录。 - filename_tooltip: 请为此帐户提供任何名称。 + filename_tooltip: |- + 请为此帐户提供任何名称。 + 非英数字字符的使用可能导致问题。 import: 导入 filename: 文件名 filename_not_entered: 未输入文件名。 @@ -129,6 +131,7 @@ zh_CN: window_scaling: 窐口缩放比例 debug_window: 显示调试窗口 output_logfile: 以文件形式记录日志 + mask_token: 隐藏日志上的令牌 device_detail: |- 配置用于设备认证的设备信息。 diff --git a/assets/i18n/app.zh_TW.yml b/assets/i18n/app.zh_TW.yml index 2aef0a2..ffc025e 100644 --- a/assets/i18n/app.zh_TW.yml +++ b/assets/i18n/app.zh_TW.yml @@ -25,8 +25,9 @@ zh_TW: filename_tooltip: 請為此快捷方式提供任何名稱。 product_id: 選擇 product_id - product_id_tooltip: | + product_id_tooltip: |- product_id 是 DMM 用來識別遊戲的 ID。 + 非英數字元的使用可能導致問題。 account_create_detail: |- 創建一個用於快速啟動 DMMGamePlayer 的快捷方式。 @@ -72,7 +73,9 @@ zh_TW: 匯入操作將登出 DMMGamePlayer 5。 請勿直接在 DMMGamePlayer 5 中使用已匯入的帳戶登錄。 - filename_tooltip: 請為此帳戶提供任何名稱。 + filename_tooltip: |- + 請為此帳戶提供任何名稱。 + 非英數字元的使用可能導致問題。 import: 匯入 filename: 檔案名稱 filename_not_entered: 未輸入檔案名稱。 @@ -129,6 +132,7 @@ zh_TW: window_scaling: 窐口縮放比例 debug_window: 顯示除錯窗口 output_logfile: 以文件形式記錄日誌 + mask_token: 隱藏日誌上的令牌 device_detail: |- 設定用於設備認證的設備信息。 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..0e1692d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[tool.ruff] +target-version = "py310" +line-length = 180 \ No newline at end of file diff --git a/setup.iss b/setup.iss index 85680f3..54bc116 100644 --- a/setup.iss +++ b/setup.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "DMMGamePlayerFastLauncher" -#define MyAppVersion "5.3.0" +#define MyAppVersion "5.4.0" #define MyAppPublisher "yuki" #define MyAppURL "https://github.com/fa0311/DMMGamePlayerFastLauncher" #define MyAppExeName "DMMGamePlayerFastLauncher.exe" diff --git a/tools/build.ps1 b/tools/build.ps1 index af64eba..3516817 100644 --- a/tools/build.ps1 +++ b/tools/build.ps1 @@ -1,4 +1,3 @@ -black *.py pip freeze > requirements.txt python .\tools\build.py diff --git a/tools/i18n.py b/tools/i18n.py index 39c5c51..3748859 100644 --- a/tools/i18n.py +++ b/tools/i18n.py @@ -19,9 +19,9 @@ def in_py(key): def i18n_flatten(data: dict[str, Any], parent: str) -> list[str]: res = [] for k, v in data.items(): - if type(v) is dict: + if isinstance(v, dict): res.extend(i18n_flatten(v, f"{parent}.{k}")) - elif type(v) is str: + elif isinstance(v, str): res.append(f"{parent}.{k}") return res