-
Notifications
You must be signed in to change notification settings - Fork 42
/
main.py
137 lines (100 loc) · 4.26 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import asyncio
import logging
import random
import uuid
import json
import aiohttp
import os
from ms.base import MSRPCChannel
from ms.rpc import Lobby
import ms.protocol_pb2 as pb
uid = os.getenv("UID", "default_uid")
token = os.getenv("TOKEN", "default_token")
deviceId = f"web|{uid}"
MS_HOST = "https://game.mahjongsoul.com/"
PASSPORT_HOST = "https://passport.mahjongsoul.com/"
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
async def main():
lobby, channel, version_to_force, accessTokenFromPassport = await connect()
await login(lobby, version_to_force, accessTokenFromPassport)
await channel.close()
async def connect():
async with aiohttp.ClientSession() as session:
async with session.get("{}version.json".format(MS_HOST)) as res:
version = await res.json()
logging.info(f"Version: {version}")
version = version["version"]
version_to_force = version.replace(".w", "")
async with session.get("{}v{}/config.json".format(MS_HOST, version)) as res:
config = await res.json()
logging.info(f"Config: {config}")
url = config["ip"][0]["region_urls"][0]["url"]
passport_url = config["yo_service_url"][0]
print(passport_url)
async with session.get(url + "?service=ws-gateway&protocol=ws&ssl=true") as res:
servers = await res.json()
# mjjpgs.mahjongsoul.com:9663
logging.info(f"Available servers: {servers}")
servers = servers["servers"]
server = random.choice(servers)
endpoint = "wss://{}/gateway".format(server)
async with session.post(
passport_url + "/user/login/",
data={
"uid": uid,
"token": token,
"deviceId": deviceId,
},
) as res:
passport = await res.json()
accessTokenFromPassport = passport["accessToken"]
logging.info(f"Chosen endpoint: {endpoint}")
channel = MSRPCChannel(endpoint)
lobby = Lobby(channel)
await channel.connect(MS_HOST)
logging.info("Connection was established")
return lobby, channel, version_to_force, accessTokenFromPassport
async def login(lobby, version_to_force, accessTokenFromPassport):
logging.info("Login with username and password")
heartBeat = pb.ReqHeatBeat()
heartBeat.no_operation_counter = 1
hbRes = await lobby.heatbeat(heartBeat) # heartbeat는 로그인하기 전에 임의적으로 몇번 통신함
reqFromSoulLess = pb.ReqOauth2Auth()
reqFromSoulLess.type = 7
reqFromSoulLess.code = accessTokenFromPassport
reqFromSoulLess.uid = uid
reqFromSoulLess.client_version_string = f"web-{version_to_force}"
res = await lobby.oauth2_auth(reqFromSoulLess)
token = res.access_token
if not token:
logging.error("Login Error:")
logging.error(res)
return False
# reqOauth2Check = pb.ReqOauth2Check()
# reqOauth2Check.type = 7
# reqOauth2Check.access_token = token
# resOauth2Check = await lobby.oauth2_check(reqOauth2Check)
# print(resOauth2Check)
# if not resOauth2Check.has_account:
# print("Invalid access token")
# return False
reqOauth2Login = pb.ReqOauth2Login()
reqOauth2Login.type = 7
reqOauth2Login.access_token = token
reqOauth2Login.reconnect = False
reqOauth2Login.device.is_browser = True
uuid_key = str(uuid.uuid1())
reqOauth2Login.random_key = uuid_key
reqOauth2Login.client_version_string = f"web-{version_to_force}"
reqOauth2Login.gen_access_token = False
reqOauth2Login.currency_platforms.append(2)
resOauth2Login = await lobby.oauth2_login(reqOauth2Login)
reqPayMonthTicket = pb.ReqCommon()
resPayMonthTicket = await lobby.pay_month_ticket(reqPayMonthTicket)
print(resPayMonthTicket)
reqFetchMonthTicketInfo = pb.ReqCommon()
resFetchMonthTicketInfo = await lobby.fetch_month_ticket_info(reqFetchMonthTicketInfo)
print(resFetchMonthTicketInfo)
return True
if __name__ == "__main__":
asyncio.run(main())