Skip to content

Commit 9f4fee3

Browse files
authored
Merge pull request #176 from fa0311/develop-v6
update 6.3.0
2 parents 948eae8 + e73da69 commit 9f4fee3

File tree

17 files changed

+150
-52
lines changed

17 files changed

+150
-52
lines changed

DMMGamePlayerFastLauncher/DMMGamePlayerFastLauncher.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ def loder(master: LanchLauncher):
2525
DataPathConfig.ACCOUNT_SHORTCUT.mkdir(exist_ok=True, parents=True)
2626
DataPathConfig.SHORTCUT.mkdir(exist_ok=True, parents=True)
2727
DataPathConfig.SCHTASKS.mkdir(exist_ok=True, parents=True)
28+
DataPathConfig.BROWSER_PROFILE.mkdir(exist_ok=True, parents=True)
29+
DataPathConfig.BROWSER_CONFIG.mkdir(exist_ok=True, parents=True)
2830

2931
config_loder()
3032
i18n.load_path.append(str(AssetsPathConfig.I18N))

DMMGamePlayerFastLauncher/component/component.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,9 @@ class PathComponentBase(EntryComponent):
182182

183183
def __init__(self, *args, **kwargs):
184184
super().__init__(*args, **kwargs)
185-
self.command.append((i18n.t("app.component.reference"), self.reference_callback))
185+
self.command.append((i18n.t("app.component.reference"), lambda v: self.reference_callback(v)))
186186

187-
def reference_callback(self, variable: PathVar):
187+
def reference_callback(self, variable: Variable):
188188
raise NotImplementedError
189189

190190

DMMGamePlayerFastLauncher/component/tab_menu.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ def add(self, text: str, callback: Callable):
3535
btn.pack(pady=2, padx=4)
3636

3737
if self.selected == row:
38-
self.callback_wrapper(callback, row=row)
39-
self.first = False
38+
self.render(callback, row=row)
4039
self.row += 1
4140

4241
def callback_wrapper(self, callback, row):
43-
children_destroy(self.body_master)
42+
if self.selected != row:
43+
self.render(callback, row)
44+
45+
def render(self, callback, row):
4446
for key, child in enumerate(self.tab_master.winfo_children()):
4547
if key == row:
4648
self.selected = key
@@ -57,6 +59,7 @@ def callback_wrapper(self, callback, row):
5759
)
5860
child.update()
5961

62+
children_destroy(self.body_master)
6063
callback(self.body_master)
6164

6265
def is_dark(self):

DMMGamePlayerFastLauncher/component/variable_base.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import json
2+
from pathlib import Path
13
from tkinter import Variable
24

35

@@ -13,3 +15,13 @@ def from_dict(cls, obj: dict[str, str]):
1315
default = cls().__dict__
1416
item = [(k, v(value=obj.get(k, default[k].get()))) for k, v in cls.__annotations__.items()]
1517
return cls(**dict(item))
18+
19+
@classmethod
20+
def from_path(cls, path: Path):
21+
with open(path, "r", encoding="utf-8") as f:
22+
data = json.load(f)
23+
return cls.from_dict(data)
24+
25+
def write_path(self, path: Path):
26+
with open(path, "w", encoding="utf-8") as f:
27+
json.dump(self.to_dict(), f, ensure_ascii=False, indent=4)

DMMGamePlayerFastLauncher/launch.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import json
21
import logging
32
import subprocess
43
import sys
@@ -19,11 +18,12 @@
1918
from lib.thread import threading_wrapper
2019
from lib.toast import ErrorWindow
2120
from models.setting_data import AppConfig
22-
from models.shortcut_data import LauncherShortcutData, ShortcutData
21+
from models.shortcut_data import BrowserConfigData, LauncherShortcutData, ShortcutData
2322
from static.config import DataPathConfig
2423
from static.constant import Constant
2524
from static.env import Env
2625
from tab.home import HomeTab
26+
from utils.utils import get_driver, login_driver
2727

2828

2929
class GameLauncher(CTk):
@@ -56,14 +56,30 @@ def thread(self, id: str, kill: bool = False, force_non_uac: bool = False):
5656

5757
def launch(self, id: str, kill: bool = False, force_non_uac: bool = False):
5858
path = DataPathConfig.SHORTCUT.joinpath(id).with_suffix(".json")
59-
with open(path, "r", encoding="utf-8") as f:
60-
data = ShortcutData.from_dict(json.load(f))
59+
data = ShortcutData.from_path(path)
6160

6261
if data.account_path.get() == Constant.ALWAYS_EXTRACT_FROM_DMM:
6362
session = DgpSessionWrap.read_dgp()
6463
else:
6564
account_path = DataPathConfig.ACCOUNT.joinpath(data.account_path.get()).with_suffix(".bytes")
65+
browser_config_path = DataPathConfig.BROWSER_CONFIG.joinpath(data.account_path.get()).with_suffix(".json")
6666
session = DgpSessionWrap.read_cookies(account_path)
67+
if browser_config_path.exists():
68+
browser_config = BrowserConfigData.from_path(browser_config_path)
69+
profile_path = DataPathConfig.BROWSER_PROFILE.joinpath(browser_config.profile_name.get()).absolute()
70+
userdata = session.post_dgp(DgpSessionWrap.USER_INFO).json()
71+
if userdata["result_code"] != 100 or True:
72+
res = session.post_dgp(DgpSessionWrap.LOGIN_URL, json={"prompt": ""}).json()
73+
if res["result_code"] != 100:
74+
raise Exception(res["error"])
75+
driver = get_driver(browser_config.browser.get(), profile_path)
76+
code = login_driver(res["data"]["url"], driver)
77+
driver.quit()
78+
res = session.post_dgp(DgpSessionWrap.ACCESS_TOKEN, json={"code": code}).json()
79+
if res["result_code"] != 100:
80+
raise Exception(res["error"])
81+
session.actauth = {"accessToken": res["data"]["access_token"]}
82+
session.write_bytes(str(account_path))
6783

6884
dgp_config = session.get_config()
6985
game = [x for x in dgp_config["contents"] if x["productId"] == data.product_id.get()][0]
@@ -174,8 +190,7 @@ def launch(self, id: str):
174190
raise Exception(i18n.t("app.lib.dmm_already_running"))
175191

176192
path = DataPathConfig.ACCOUNT_SHORTCUT.joinpath(id).with_suffix(".json")
177-
with open(path, "r", encoding="utf-8") as f:
178-
data = LauncherShortcutData.from_dict(json.load(f))
193+
data = LauncherShortcutData.from_path(path)
179194

180195
account_path = DataPathConfig.ACCOUNT.joinpath(data.account_path.get()).with_suffix(".bytes")
181196

DMMGamePlayerFastLauncher/lib/DGPSessionV2.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ class DgpSessionV2:
8383
HARDWARE_CONF = API_DGP.format("/v5/hardwareconf")
8484
HARDWARE_LIST = API_DGP.format("/v5/hardwarelist")
8585
HARDWARE_REJECT = API_DGP.format("/v5/hardwarereject")
86+
USER_INFO = API_DGP.format("/v5/userinfo")
87+
CHECK_ACCESS_TOKEN = API_DGP.format("/v5/auth/accesstoken/check")
8688
ACCESS_TOKEN = API_DGP.format("/v5/auth/accesstoken/issue")
8789
LOGIN_URL = API_DGP.format("/v5/auth/login/url")
8890
SIGNED_URL = "https://cdn-gameplayer.games.dmm.com/product/*"
@@ -188,6 +190,8 @@ def lunch(self, product_id: str, game_type: str) -> requests.Response:
188190
url = self.LAUNCH_CL
189191
elif game_type == "AMAIN":
190192
url = self.LAUNCH_PKG
193+
elif game_type == "GMAIN":
194+
url = self.LAUNCH_PKG
191195
else:
192196
raise Exception("Unknown game_type: " + game_type + " " + product_id)
193197
json = {

DMMGamePlayerFastLauncher/models/shortcut_data.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import uuid
12
from dataclasses import dataclass, field
23
from tkinter import BooleanVar, StringVar
34

@@ -20,3 +21,9 @@ class ShortcutData(VariableBase):
2021
class LauncherShortcutData(VariableBase):
2122
account_path: PathVar = field(default_factory=PathVar)
2223
dgp_args: StringVar = field(default_factory=StringVar)
24+
25+
26+
@dataclass
27+
class BrowserConfigData(VariableBase):
28+
browser: StringVar = field(default_factory=StringVar)
29+
profile_name: StringVar = field(default_factory=lambda: StringVar(value=uuid.uuid4().hex))

DMMGamePlayerFastLauncher/static/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ class DataPathConfig(Dump):
88
ACCOUNT = DATA.joinpath("account")
99
ACCOUNT_SHORTCUT = DATA.joinpath("account_shortcut")
1010
SHORTCUT = DATA.joinpath("shortcut")
11+
BROWSER_PROFILE = DATA.joinpath("browser_profile")
12+
BROWSER_CONFIG = DATA.joinpath("browser_config")
1113
LOG = DATA.joinpath("log")
1214
APP_CONFIG = DATA.joinpath("config.json")
1315
SCHTASKS = DATA.joinpath("schtasks")

DMMGamePlayerFastLauncher/static/env.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99

1010
class Env(Dump):
11-
VERSION = "v6.2.3"
11+
VERSION = "v6.3.0"
1212
RELEASE_VERSION = requests.get(UrlConfig.RELEASE_API).json().get("tag_name", VERSION)
1313

1414
DEVELOP: bool = os.environ.get("ENV") == "DEVELOP"

DMMGamePlayerFastLauncher/tab/account.py

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
import time
2-
import urllib.parse
31
from pathlib import Path
4-
from tkinter import StringVar
5-
from typing import TypeVar
2+
from tkinter import BooleanVar, StringVar
3+
from typing import Callable, Optional, TypeVar
64

75
import customtkinter as ctk
86
import i18n
9-
from component.component import EntryComponent, OptionMenuComponent, OptionMenuTupleComponent, PaddingComponent
7+
from component.component import CheckBoxComponent, EntryComponent, OptionMenuComponent, OptionMenuTupleComponent, PaddingComponent
108
from component.tab_menu import TabMenuComponent
119
from customtkinter import CTkBaseClass, CTkButton, CTkFrame, CTkLabel, CTkScrollableFrame
1210
from lib.DGPSessionWrap import DgpSessionWrap
1311
from lib.toast import ToastController, error_toast
14-
from selenium import webdriver
12+
from models.shortcut_data import BrowserConfigData
1513
from static.config import DataPathConfig
1614
from static.constant import Constant
17-
from utils.utils import children_destroy, file_create
15+
from utils.utils import children_destroy, file_create, get_driver, login_driver
1816

1917
T = TypeVar("T")
2018

@@ -94,35 +92,27 @@ def callback(self):
9492
class AccountBrowserImport(CTkScrollableFrame):
9593
toast: ToastController
9694
name: StringVar
97-
browser: StringVar
95+
data: BrowserConfigData
9896

9997
def __init__(self, master: CTkBaseClass):
10098
super().__init__(master, fg_color="transparent")
10199
self.toast = ToastController(self)
102100
self.name = StringVar()
103-
self.browser = StringVar()
101+
self.auto_refresh = BooleanVar(value=True)
102+
self.data = BrowserConfigData()
104103

105104
def create(self):
106105
CTkLabel(self, text=i18n.t("app.account.import_browser_detail"), justify=ctk.LEFT).pack(anchor=ctk.W)
107106
text = i18n.t("app.account.filename")
108107
tooltip = i18n.t("app.account.filename_tooltip")
109108
EntryComponent(self, text=text, tooltip=tooltip, required=True, variable=self.name, alnum_only=True).create()
109+
CheckBoxComponent(self, text=i18n.t("app.account.auto_refresh"), variable=self.auto_refresh).create()
110110
text = i18n.t("app.account.browser_select")
111111
tooltip = i18n.t("app.account.browser_select_tooltip")
112-
OptionMenuComponent(self, text=text, tooltip=tooltip, values=["Chrome", "Edge", "Firefox"], variable=self.browser).create()
112+
OptionMenuComponent(self, text=text, tooltip=tooltip, values=["Chrome", "Edge", "Firefox"], variable=self.data.browser).create()
113113
CTkButton(self, text=i18n.t("app.account.import_browser"), command=self.callback).pack(fill=ctk.X, pady=10)
114114
return self
115115

116-
def get_driver(self):
117-
if self.browser.get() == "Chrome":
118-
return webdriver.Chrome()
119-
elif self.browser.get() == "Edge":
120-
return webdriver.Edge()
121-
elif self.browser.get() == "Firefox":
122-
return webdriver.Firefox()
123-
else:
124-
raise Exception(i18n.t("app.account.browser_not_selected"))
125-
126116
@error_toast
127117
def callback(self):
128118
path = DataPathConfig.ACCOUNT.joinpath(self.name.get()).with_suffix(".bytes")
@@ -137,19 +127,20 @@ def callback(self):
137127
res = session.post_dgp(DgpSessionWrap.LOGIN_URL, json={"prompt": ""}).json()
138128
if res["result_code"] != 100:
139129
raise Exception(res["error"])
140-
driver = self.get_driver()
141-
driver.get(res["data"]["url"])
142-
parsed_url = urllib.parse.urlparse(driver.current_url)
143-
while not (parsed_url.netloc == "webdgp-gameplayer.games.dmm.com" and parsed_url.path == "/login/success"):
144-
time.sleep(0.2)
145-
parsed_url = urllib.parse.urlparse(driver.current_url)
130+
131+
profile_path = DataPathConfig.BROWSER_PROFILE.joinpath(self.data.profile_name.get()).absolute()
132+
driver = get_driver(self.data.browser.get(), profile_path)
133+
code = login_driver(res["data"]["url"], driver)
146134
driver.quit()
147-
code = urllib.parse.parse_qs(parsed_url.query)["code"][0]
148135
res = session.post_dgp(DgpSessionWrap.ACCESS_TOKEN, json={"code": code}).json()
149136
if res["result_code"] != 100:
150137
raise Exception(res["error"])
151138
session.actauth = {"accessToken": res["data"]["access_token"]}
152139
session.write_bytes(str(path))
140+
if self.auto_refresh.get():
141+
config_path = DataPathConfig.BROWSER_CONFIG.joinpath(self.name.get()).with_suffix(".json")
142+
file_create(config_path, name=i18n.t("app.account.filename"))
143+
self.data.write_path(config_path)
153144
self.toast.info(i18n.t("app.account.import_browser_success"))
154145

155146

@@ -159,6 +150,7 @@ class AccountEdit(CTkScrollableFrame):
159150
filename: StringVar
160151
body: CTkFrame
161152
body_var: dict[str, StringVar]
153+
browser_config: Optional[BrowserConfigData]
162154
body_filename: StringVar
163155

164156
def __init__(self, master: CTkBaseClass):
@@ -167,6 +159,7 @@ def __init__(self, master: CTkBaseClass):
167159
self.values = [x.stem for x in DataPathConfig.ACCOUNT.iterdir() if x.suffix == ".bytes"]
168160
self.filename = StringVar()
169161
self.body_var = {}
162+
self.browser_config = None
170163
self.body_filename = StringVar()
171164

172165
def create(self):
@@ -190,6 +183,13 @@ def select_callback(self, value: str):
190183
for key in session.actauth.keys():
191184
self.body_var[key] = StringVar(value=session.actauth[key] or "")
192185
EntryComponent(self.body, text=key, variable=self.body_var[key]).create()
186+
config_path = DataPathConfig.BROWSER_CONFIG.joinpath(self.filename.get()).with_suffix(".json")
187+
if config_path.exists():
188+
self.browser_config = BrowserConfigData.from_path(config_path)
189+
PaddingComponent(self.body, height=20).create()
190+
EntryComponent(self.body, text="browser", variable=self.browser_config.browser).create()
191+
EntryComponent(self.body, text="profile_name", variable=self.browser_config.profile_name).create()
192+
193193
CTkButton(self.body, text=i18n.t("app.account.save"), command=self.save_callback).pack(fill=ctk.X, pady=10)
194194
CTkButton(self.body, text=i18n.t("app.account.delete"), command=self.delete_callback).pack(fill=ctk.X)
195195

@@ -202,19 +202,34 @@ def save_callback(self):
202202

203203
path = DataPathConfig.ACCOUNT.joinpath(self.filename.get()).with_suffix(".bytes")
204204
body_path = DataPathConfig.ACCOUNT.joinpath(self.body_filename.get()).with_suffix(".bytes")
205+
config_path = DataPathConfig.BROWSER_CONFIG.joinpath(self.filename.get()).with_suffix(".json")
206+
config_body_path = DataPathConfig.BROWSER_CONFIG.joinpath(self.body_filename.get()).with_suffix(".json")
207+
208+
def check_file(callback: Callable[[], None]):
209+
if self.browser_config:
210+
callback()
205211

206212
def write():
207213
session = DgpSessionWrap.read_cookies((Path(path)))
208214
for key in session.actauth.keys():
209215
session.actauth[key] = self.body_var[key].get()
210-
session.write_bytes(str(Path(body_path)))
216+
session.write_bytes(str(body_path))
217+
if self.browser_config:
218+
self.browser_config.write_path(config_body_path)
211219

212220
if path == body_path:
213221
write()
214222
else:
215-
file_create(body_path, name=i18n.t("app.account.filename"))
216-
write()
223+
try:
224+
file_create(body_path, name=i18n.t("app.account.filename"))
225+
check_file(lambda: file_create(config_body_path, name=i18n.t("app.account.filename")))
226+
write()
227+
except Exception as e:
228+
body_path.unlink()
229+
config_body_path.unlink()
230+
raise e
217231
path.unlink()
232+
check_file(lambda: config_path.unlink())
218233
self.values.remove(self.filename.get())
219234
self.values.append(self.body_filename.get())
220235
self.filename.set(self.body_filename.get())

0 commit comments

Comments
 (0)