Skip to content

Commit 8222b79

Browse files
authored
Merge pull request #44 from fa0311/develop-v4
v4.5.0
2 parents 5804a02 + 840046a commit 8222b79

File tree

4 files changed

+159
-162
lines changed

4 files changed

+159
-162
lines changed

DMMGamePlayerFastLauncher.py

Lines changed: 154 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,117 @@
33
import argparse
44
import json
55
import glob
6-
import win32crypt
76
import ctypes
87
import random
98
import hashlib
109
import sqlite3
1110
import os
1211
import time
13-
import re
14-
15-
16-
def gen_rand_hex():
17-
return hashlib.sha256(str(random.random()).encode()).hexdigest()
18-
12+
from urllib.parse import urlparse
13+
14+
15+
class DgpSession:
16+
DGP5_PATH: str
17+
HEADERS: dict[str, str]
18+
PROXY: dict[str, str | None]
19+
DGP5_HEADERS: dict[str, str]
20+
DGP5_LAUNCH_PARAMS: dict[str, str]
21+
db: sqlite3.Connection
22+
session: requests.Session
23+
cookies: requests.cookies.RequestsCookieJar
24+
25+
def __init__(self, https_proxy_uri: str | None = None):
26+
requests.packages.urllib3.disable_warnings()
27+
self.DGP5_PATH = os.environ["APPDATA"] + "\\dmmgameplayer5\\"
28+
self.PROXY = {"https": https_proxy_uri}
29+
self.HEADERS = {
30+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
31+
"Upgrade-Insecure-Requests": "1",
32+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36",
33+
}
34+
self.DGP5_HEADERS = {
35+
"Host": "apidgp-gameplayer.games.dmm.com",
36+
"Connection": "keep-alive",
37+
"User-Agent": "DMMGamePlayer5-Win/17.1.2 Electron/17.1.2",
38+
"Client-App": "DMMGamePlayer5",
39+
"Client-version": "17.1.2",
40+
}
41+
self.DGP5_LAUNCH_PARAMS = {
42+
"game_type": "GCL",
43+
"game_os": "win",
44+
"launch_type": "LIB",
45+
"mac_address": self.gen_rand_address(),
46+
"hdd_serial": self.gen_rand_hex(),
47+
"motherboard": self.gen_rand_hex(),
48+
"user_os": "win",
49+
}
50+
self.open()
51+
52+
def gen_rand_hex(self):
53+
return hashlib.sha256(str(random.random()).encode()).hexdigest()
54+
55+
def gen_rand_address(self):
56+
hex = self.gen_rand_hex()
57+
address = ""
58+
for x in range(12):
59+
address += hex[x]
60+
if x % 2 == 1:
61+
address += ":"
62+
return address[:-1]
63+
64+
def write(self):
65+
for cookie_row in self.db.cursor().execute("select * from cookies"):
66+
name = cookie_row[3]
67+
value = self.session.cookies.get(name)
68+
if value != None:
69+
self.db.execute(
70+
f"update cookies set value = '{value}' where name = '{name}'"
71+
)
72+
self.db.commit()
73+
74+
def read(self):
75+
for cookie_row in self.db.cursor().execute("select * from cookies"):
76+
cookie_data = {
77+
"name": cookie_row[3],
78+
"value": cookie_row[4],
79+
"domain": cookie_row[1],
80+
"path": cookie_row[6],
81+
"secure": cookie_row[8],
82+
}
83+
self.session.cookies.set_cookie(
84+
requests.cookies.create_cookie(**cookie_data)
85+
)
1986

20-
def gen_rand_address():
21-
hex = gen_rand_hex()
22-
address = ""
23-
for x in range(12):
24-
address += hex[x]
25-
if x % 2 == 1:
26-
address += ":"
27-
return address[:-1]
87+
def get(self, url: str) -> requests.Response:
88+
return self.session.get(url, headers=self.HEADERS, proxies=self.PROXY)
2889

90+
def post(self, url: str) -> requests.Response:
91+
return self.session.post(url, headers=self.HEADERS, proxies=self.PROXY)
2992

30-
def get_dgp5_session(dgp5_path):
31-
db = sqlite3.connect(dgp5_path + "Network/Cookies").cursor()
32-
session = requests.session()
33-
for cookie_row in db.execute("select * from cookies"):
34-
cookie_data = {
35-
"name": cookie_row[3],
36-
"value": cookie_row[4],
37-
"domain": cookie_row[1],
38-
"path": cookie_row[6],
39-
"secure": cookie_row[8],
40-
}
41-
session.cookies.set_cookie(requests.cookies.create_cookie(**cookie_data))
42-
return session
93+
def lunch(self, url: str, product_id: str) -> requests.Response:
94+
json = {"product_id": product_id}
95+
json.update(self.DGP5_LAUNCH_PARAMS)
96+
return self.session.post(
97+
url,
98+
headers=self.DGP5_HEADERS,
99+
proxies=self.PROXY,
100+
json=json,
101+
verify=False,
102+
)
43103

104+
def get_config(self):
105+
with open(self.DGP5_PATH + "dmmgame.cnf", "r", encoding="utf-8") as f:
106+
config = f.read()
107+
return json.loads(config)
44108

45-
def get_dpg5_config(dgp5_path):
46-
with open(dgp5_path + "dmmgame.cnf", "r", encoding="utf-8") as f:
47-
config = f.read()
48-
return json.loads(config)
109+
def open(self):
110+
self.db = sqlite3.connect(self.DGP5_PATH + "Network/Cookies")
111+
self.session = requests.session()
112+
self.cookies = self.session.cookies
49113

114+
def close(self):
115+
self.db.close()
50116

51-
requests.packages.urllib3.disable_warnings()
52117

53118
argpar = argparse.ArgumentParser(
54119
prog="DMMGamePlayerFastLauncher",
@@ -58,81 +123,36 @@ def get_dpg5_config(dgp5_path):
58123
argpar.add_argument("product_id", default=None)
59124
argpar.add_argument("--game-path", default=None)
60125
argpar.add_argument("--game-args", default=None)
61-
argpar.add_argument("--login-force", action="store_true")
62126
argpar.add_argument("--skip-exception", action="store_true")
63127
argpar.add_argument("--https-proxy-uri", default=None)
64128
argpar.add_argument("--non-request-admin", action="store_true")
65129
arg = argpar.parse_args()
66130

67-
HEADERS = {
68-
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
69-
"Upgrade-Insecure-Requests": "1",
70-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36",
71-
}
72-
73-
PROXY = {"https": arg.https_proxy_uri}
74-
75-
DGP5_HEADERS = {
76-
"Host": "apidgp-gameplayer.games.dmm.com",
77-
"Connection": "keep-alive",
78-
"User-Agent": "DMMGamePlayer5-Win/17.1.2 Electron/17.1.2",
79-
"Client-App": "DMMGamePlayer5",
80-
"Client-version": "17.1.2",
81-
}
82-
DGP5_LAUNCH_PARAMS = {
83-
"product_id": arg.product_id,
84-
"game_type": "GCL",
85-
"game_os": "win",
86-
"launch_type": "LIB",
87-
"mac_address": gen_rand_address(),
88-
"hdd_serial": gen_rand_hex(),
89-
"motherboard": gen_rand_hex(),
90-
"user_os": "win",
91-
}
92-
DGP5_PATH = os.environ["APPDATA"] + "\\dmmgameplayer5\\"
93-
94-
95-
open("cookie.bytes", "a+")
96-
with open("cookie.bytes", "rb") as f:
97-
blob = f.read()
98-
if blob == b"" or arg.login_force:
99-
session = get_dgp5_session(DGP5_PATH)
100-
101-
response = session.get(
102-
"https://www.dmm.com/",
103-
headers=HEADERS,
104-
proxies=PROXY,
105-
).text
106-
107-
reg = '<script{any}id="auto-login"{any}data-encoded="{data}"{any}></script>'.format(any=".*?",data="([0-9a-zA-Z_]*)")
108-
data_encoded = re.findall(reg, response)[0]
109-
110-
response = session.get(
111-
f"https://accounts.dmm.com/service/login/token/=/path={data_encoded}",
112-
headers=HEADERS,
113-
proxies=PROXY,
114-
)
115-
if session.cookies.get("login_session_id") == None:
116-
if not arg.skip_exception:
117-
raise Exception(
118-
"ログインに失敗しました\nDMMGamePlayerを起動してログインし直して下さい"
119-
)
120-
contents = json.dumps(
121-
{
122-
"login_session_id": session.cookies.get("login_session_id"),
123-
"login_secure_id": session.cookies.get("login_secure_id"),
124-
}
125-
)
126-
new_blob = win32crypt.CryptProtectData(
127-
contents.encode(), "DMMGamePlayerFastLauncher"
128-
)
129-
with open("cookie.bytes", "wb") as f:
130-
f.write(new_blob)
131-
else:
132-
_, contents = win32crypt.CryptUnprotectData(blob)
133-
cookie = json.loads(contents)
134131

135-
dpg5_config = get_dpg5_config(DGP5_PATH)
132+
session = DgpSession(arg.https_proxy_uri)
133+
134+
session.read()
135+
url = session.get("https://apidgp-gameplayer.games.dmm.com/v5/loginurl").json()["data"][
136+
"url"
137+
]
138+
token = urlparse(url).path.split("path=")[-1]
139+
140+
141+
session.get(url)
142+
res = session.get(
143+
f"https://accounts.dmm.com/service/login/token/=/path={token}/is_app=false"
144+
)
145+
146+
if session.cookies.get("login_session_id") == None:
147+
if not arg.skip_exception:
148+
raise Exception(
149+
"\n".join(["Login failed.", "Please start DMMGamePlayer and login again."])
150+
)
151+
152+
session.write()
153+
session.close()
154+
155+
dpg5_config = session.get_config()
136156
if arg.game_path is None:
137157
for contents in dpg5_config["contents"]:
138158
if contents["productId"] == arg.product_id:
@@ -156,28 +176,33 @@ def get_dpg5_config(dgp5_path):
156176
break
157177
else:
158178
if not arg.skip_exception:
159-
raise Exception("ゲームのパスの検出に失敗しました")
179+
raise Exception(
180+
"\n".join(
181+
[
182+
"Game path detection failed.",
183+
"Try using --game_path.",
184+
"https://github.com/fa0311/DMMGamePlayerFastLauncher/blob/master/docs/README-advance.md#game-path",
185+
]
186+
)
187+
)
160188
break
161189
else:
162190
if not arg.skip_exception:
163-
raise Exception(
164-
"product_id が無効です\n"
165-
+ " ".join(
191+
message = [
192+
"product_id is invalid.",
193+
"Please select:",
194+
" ".join(
166195
[contents["productId"] for contents in dpg5_config["contents"]]
167-
)
168-
+ "から選択して下さい"
169-
)
196+
),
197+
]
198+
raise Exception("\n".join(message))
170199
else:
171200
game_path = arg.game_path
172201

173-
response = requests.post(
174-
"https://apidgp-gameplayer.games.dmm.com/v5/launch/cl",
175-
cookies=cookie,
176-
headers=DGP5_HEADERS,
177-
json=DGP5_LAUNCH_PARAMS,
178-
verify=False,
179-
proxies=PROXY,
202+
response = session.lunch(
203+
"https://apidgp-gameplayer.games.dmm.com/v5/launch/cl", arg.product_id
180204
).json()
205+
181206
if response["result_code"] == 100:
182207
dmm_args = response["data"]["execute_args"].split(" ")
183208
if arg.game_args is not None:
@@ -197,17 +222,23 @@ def get_dpg5_config(dgp5_path):
197222
None, "runas", game_path, response["data"]["execute_args"], None, 1
198223
)
199224
else:
200-
raise Exception("ゲームが起動しませんでした。管理者権限を許可してください。")
225+
raise Exception(
226+
"Game did not start. Please allow administrative privileges."
227+
)
201228
elif response["data"]["is_administrator"]:
202-
raise Exception("ゲームが起動しませんでした。管理者権限を許可してください。")
229+
raise Exception(
230+
"Game did not start. Please allow administrative privileges."
231+
)
203232
else:
204233
if not arg.skip_exception:
205-
raise Exception("ゲームが起動しませんでした。ゲームにアップデートがある可能性があります。")
234+
raise Exception(
235+
"Game did not start. There may be an update to the game."
236+
)
206237
elif response["result_code"] == 801:
207238
if not arg.skip_exception:
208-
raise Exception("日本国外からのアクセスは禁止されています\n" + json.dumps(response))
239+
raise Exception(
240+
"\n".join(["Access from outside Japan is prohibited", json.dumps(response)])
241+
)
209242
else:
210-
with open("cookie.bytes", "wb") as f:
211-
f.write(b"")
212243
if not arg.skip_exception:
213-
raise Exception("起動にエラーが発生したため修復プログラムを実行しました\n" + json.dumps(response))
244+
raise Exception("\n".join(["Error in startup.", json.dumps(response)]))

0 commit comments

Comments
 (0)