5 Commits

Author SHA1 Message Date
Dniel97
f39317301b mai2: fixed update script, added mai2 heredity, fixed cards import 2023-07-15 22:51:54 +02:00
Dniel97
389784ce82 Merge remote-tracking branch 'origin/develop' into fork_develop 2023-07-15 22:47:05 +02:00
Kevin Trocolli
2f13596885 fix db ignoring port in config, createing database no longer runs over version 2023-07-15 00:15:14 -04:00
Kevin Trocolli
85b73e634d mucha: add DownloadState 2023-07-12 00:41:53 -04:00
Midorica
09c4f8cda4 Async request to CXB profile loading 2023-07-08 18:44:02 -04:00
15 changed files with 280 additions and 346 deletions

View File

@@ -27,9 +27,9 @@ class Data:
if self.config.database.sha2_password: if self.config.database.sha2_password:
passwd = sha256(self.config.database.password.encode()).digest() passwd = sha256(self.config.database.password.encode()).digest()
self.__url = f"{self.config.database.protocol}://{self.config.database.username}:{passwd.hex()}@{self.config.database.host}/{self.config.database.name}?charset=utf8mb4" self.__url = f"{self.config.database.protocol}://{self.config.database.username}:{passwd.hex()}@{self.config.database.host}:{self.config.database.port}/{self.config.database.name}?charset=utf8mb4"
else: else:
self.__url = f"{self.config.database.protocol}://{self.config.database.username}:{self.config.database.password}@{self.config.database.host}/{self.config.database.name}?charset=utf8mb4" self.__url = f"{self.config.database.protocol}://{self.config.database.username}:{self.config.database.password}@{self.config.database.host}:{self.config.database.port}/{self.config.database.name}?charset=utf8mb4"
if Data.engine is None: if Data.engine is None:
Data.engine = create_engine(self.__url, pool_recycle=3600) Data.engine = create_engine(self.__url, pool_recycle=3600)
@@ -94,7 +94,7 @@ class Data:
game_mod.database(self.config) game_mod.database(self.config)
metadata.create_all(self.__engine.connect()) metadata.create_all(self.__engine.connect())
self.base.set_schema_ver( self.base.touch_schema_ver(
game_mod.current_schema_version, game_mod.game_codes[0] game_mod.current_schema_version, game_mod.game_codes[0]
) )

View File

@@ -103,6 +103,18 @@ class BaseData:
return row["version"] return row["version"]
def touch_schema_ver(self, ver: int, game: str = "CORE") -> Optional[int]:
sql = insert(schema_ver).values(game=game, version=ver)
conflict = sql.on_duplicate_key_update(version=schema_ver.c.version)
result = self.execute(conflict)
if result is None:
self.logger.error(
f"Failed to update schema version for game {game} (v{ver})"
)
return None
return result.lastrowid
def set_schema_ver(self, ver: int, game: str = "CORE") -> Optional[int]: def set_schema_ver(self, ver: int, game: str = "CORE") -> Optional[int]:
sql = insert(schema_ver).values(game=game, version=ver) sql = insert(schema_ver).values(game=game, version=ver)
conflict = sql.on_duplicate_key_update(version=ver) conflict = sql.on_duplicate_key_update(version=ver)

View File

@@ -51,7 +51,7 @@ ALTER TABLE mai2_item_favorite MODIFY COLUMN itemKind int(11) NOT NULL;
ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN seasonId int(11) NOT NULL; ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN seasonId int(11) NOT NULL;
ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN point int(11) NOT NULL; ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN point int(11) NOT NULL;
ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN rank int(11) NOT NULL; ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN `rank` int(11) NOT NULL;
ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN rewardGet tinyint(1) NOT NULL; ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN rewardGet tinyint(1) NOT NULL;
ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN userName varchar(8) NOT NULL; ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN userName varchar(8) NOT NULL;

View File

@@ -35,7 +35,7 @@ ALTER TABLE mai2_item_favorite MODIFY COLUMN itemKind int(11) NULL;
ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN seasonId int(11) NULL; ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN seasonId int(11) NULL;
ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN point int(11) NULL; ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN point int(11) NULL;
ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN rank int(11) NULL; ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN `rank` int(11) NULL;
ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN rewardGet tinyint(1) NULL; ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN rewardGet tinyint(1) NULL;
ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN userName varchar(8) NULL; ALTER TABLE mai2_item_friend_season_ranking MODIFY COLUMN userName varchar(8) NULL;

View File

@@ -4,6 +4,7 @@ from logging.handlers import TimedRotatingFileHandler
from twisted.web import resource from twisted.web import resource
from twisted.web.http import Request from twisted.web.http import Request
from datetime import datetime from datetime import datetime
from Crypto.Cipher import Blowfish
import pytz import pytz
from core import CoreConfig from core import CoreConfig
@@ -56,18 +57,22 @@ class MuchaServlet:
self.logger.error( self.logger.error(
f"Error processing mucha request {request.content.getvalue()}" f"Error processing mucha request {request.content.getvalue()}"
) )
return b"" return b"RESULTS=000"
req = MuchaAuthRequest(req_dict) req = MuchaAuthRequest(req_dict)
self.logger.debug(f"Mucha request {vars(req)}")
self.logger.info(f"Boardauth request from {client_ip} for {req.gameVer}") self.logger.info(f"Boardauth request from {client_ip} for {req.gameVer}")
self.logger.debug(f"Mucha request {vars(req)}")
if req.gameCd not in self.mucha_registry: if req.gameCd not in self.mucha_registry:
self.logger.warn(f"Unknown gameCd {req.gameCd}") self.logger.warn(f"Unknown gameCd {req.gameCd}")
return b"" return b"RESULTS=000"
# TODO: Decrypt S/N # TODO: Decrypt S/N
#cipher = Blowfish.new(req.sendDate.encode(), Blowfish.MODE_ECB)
#sn_decrypt = cipher.decrypt(bytes.fromhex(req.serialNum))
#self.logger.debug(f"Decrypt SN to {sn_decrypt.hex()}")
resp = MuchaAuthResponse( resp = MuchaAuthResponse(
f"{self.config.mucha.hostname}{':' + str(self.config.allnet.port) if self.config.server.is_develop else ''}" f"{self.config.mucha.hostname}{':' + str(self.config.allnet.port) if self.config.server.is_develop else ''}"
) )
@@ -84,22 +89,37 @@ class MuchaServlet:
self.logger.error( self.logger.error(
f"Error processing mucha request {request.content.getvalue()}" f"Error processing mucha request {request.content.getvalue()}"
) )
return b"" return b"RESULTS=000"
req = MuchaUpdateRequest(req_dict) req = MuchaUpdateRequest(req_dict)
self.logger.debug(f"Mucha request {vars(req)}")
self.logger.info(f"Updatecheck request from {client_ip} for {req.gameVer}") self.logger.info(f"Updatecheck request from {client_ip} for {req.gameVer}")
self.logger.debug(f"Mucha request {vars(req)}")
if req.gameCd not in self.mucha_registry: if req.gameCd not in self.mucha_registry:
self.logger.warn(f"Unknown gameCd {req.gameCd}") self.logger.warn(f"Unknown gameCd {req.gameCd}")
return b"" return b"RESULTS=000"
resp = MuchaUpdateResponseStub(req.gameVer) resp = MuchaUpdateResponse(req.gameVer, f"{self.config.mucha.hostname}{':' + str(self.config.allnet.port) if self.config.server.is_develop else ''}")
self.logger.debug(f"Mucha response {vars(resp)}") self.logger.debug(f"Mucha response {vars(resp)}")
return self.mucha_postprocess(vars(resp)) return self.mucha_postprocess(vars(resp))
def handle_dlstate(self, request: Request, _: Dict) -> bytes:
req_dict = self.mucha_preprocess(request.content.getvalue())
client_ip = Utils.get_ip_addr(request)
if req_dict is None:
self.logger.error(
f"Error processing mucha request {request.content.getvalue()}"
)
return b""
req = MuchaDownloadStateRequest(req_dict)
self.logger.info(f"DownloadState request from {client_ip} for {req.gameCd} -> {req.updateVer}")
self.logger.debug(f"request {vars(req)}")
return b"RESULTS=001"
def mucha_preprocess(self, data: bytes) -> Optional[Dict]: def mucha_preprocess(self, data: bytes) -> Optional[Dict]:
try: try:
ret: Dict[str, Any] = {} ret: Dict[str, Any] = {}
@@ -203,21 +223,56 @@ class MuchaUpdateRequest:
class MuchaUpdateResponse: class MuchaUpdateResponse:
def __init__(self, game_ver: str, mucha_url: str) -> None: def __init__(self, game_ver: str, mucha_url: str) -> None:
self.RESULTS = "001" self.RESULTS = "001"
self.EXE_VER = game_ver
self.UPDATE_VER_1 = game_ver self.UPDATE_VER_1 = game_ver
self.UPDATE_URL_1 = f"https://{mucha_url}/updUrl1/" self.UPDATE_URL_1 = f"http://{mucha_url}/updUrl1/"
self.UPDATE_SIZE_1 = "0" self.UPDATE_SIZE_1 = "20"
self.UPDATE_CRC_1 = "0000000000000000"
self.CHECK_URL_1 = f"https://{mucha_url}/checkUrl/" self.CHECK_CRC_1 = "0000000000000000"
self.EXE_VER_1 = game_ver self.CHECK_URL_1 = f"http://{mucha_url}/checkUrl/"
self.CHECK_SIZE_1 = "20"
self.INFO_SIZE_1 = "0" self.INFO_SIZE_1 = "0"
self.COM_SIZE_1 = "0" self.COM_SIZE_1 = "0"
self.COM_TIME_1 = "0" self.COM_TIME_1 = "0"
self.LAN_INFO_SIZE_1 = "0" self.LAN_INFO_SIZE_1 = "0"
self.USER_ID = "" self.USER_ID = ""
self.PASSWORD = "" self.PASSWORD = ""
"""
RESULTS
EXE_VER
UPDATE_VER_%d
UPDATE_URL_%d
UPDATE_SIZE_%d
CHECK_CRC_%d
CHECK_URL_%d
CHECK_SIZE_%d
INFO_SIZE_1
COM_SIZE_1
COM_TIME_1
LAN_INFO_SIZE_1
USER_ID
PASSWORD
"""
class MuchaUpdateResponseStub: class MuchaUpdateResponseStub:
def __init__(self, game_ver: str) -> None: def __init__(self, game_ver: str) -> None:
self.RESULTS = "001" self.RESULTS = "001"
self.UPDATE_VER_1 = game_ver self.UPDATE_VER_1 = game_ver
class MuchaDownloadStateRequest:
def __init__(self, request: Dict) -> None:
self.gameCd = request.get("gameCd", "")
self.updateVer = request.get("updateVer", "")
self.serialNum = request.get("serialNum", "")
self.fileSize = request.get("fileSize", "")
self.compFileSize = request.get("compFileSize", "")
self.boardId = request.get("boardId", "")
self.placeId = request.get("placeId", "")
self.storeRouterIp = request.get("storeRouterIp", "")

View File

@@ -113,6 +113,13 @@ class HttpDispatcher(resource.Resource):
action="handle_updatecheck", action="handle_updatecheck",
conditions=dict(method=["POST"]), conditions=dict(method=["POST"]),
) )
self.map_post.connect(
"mucha_dlstate",
"/mucha/downloadstate.do",
controller="mucha",
action="handle_dlstate",
conditions=dict(method=["POST"]),
)
self.map_get.connect( self.map_get.connect(
"title_get", "title_get",

View File

@@ -129,6 +129,6 @@ class CardMakerServlet:
if resp is None: if resp is None:
resp = {"returnCode": 1} resp = {"returnCode": 1}
self.logger.info(f"Response {resp}") self.logger.debug(f"Response {resp}")
return zlib.compress(json.dumps(resp, ensure_ascii=False).encode("utf-8")) return zlib.compress(json.dumps(resp, ensure_ascii=False).encode("utf-8"))

View File

@@ -89,8 +89,7 @@ class CardMakerReader(BaseReader):
version_ids = { version_ids = {
"v2_00": ChuniConstants.VER_CHUNITHM_NEW, "v2_00": ChuniConstants.VER_CHUNITHM_NEW,
"v2_05": ChuniConstants.VER_CHUNITHM_NEW_PLUS, "v2_05": ChuniConstants.VER_CHUNITHM_NEW_PLUS,
# Chunithm SUN, ignore for now "v2_10": ChuniConstants.VER_CHUNITHM_SUN,
"v2_10": ChuniConstants.VER_CHUNITHM_NEW_PLUS + 1,
} }
for root, dirs, files in os.walk(base_dir): for root, dirs, files in os.walk(base_dir):
@@ -138,8 +137,7 @@ class CardMakerReader(BaseReader):
version_ids = { version_ids = {
"v2_00": ChuniConstants.VER_CHUNITHM_NEW, "v2_00": ChuniConstants.VER_CHUNITHM_NEW,
"v2_05": ChuniConstants.VER_CHUNITHM_NEW_PLUS, "v2_05": ChuniConstants.VER_CHUNITHM_NEW_PLUS,
# Chunithm SUN, ignore for now "v2_10": ChuniConstants.VER_CHUNITHM_SUN,
"v2_10": ChuniConstants.VER_CHUNITHM_NEW_PLUS + 1,
} }
for root, dirs, files in os.walk(base_dir): for root, dirs, files in os.walk(base_dir):
@@ -226,6 +224,12 @@ class CardMakerReader(BaseReader):
True if troot.find("disable").text == "false" else False True if troot.find("disable").text == "false" else False
) )
# check if a date is part of the name and disable the
# card if it is
enabled = (
False if re.search(r"\d{2}/\d{2}/\d{2}", name) else enabled
)
self.mai2_data.static.put_card( self.mai2_data.static.put_card(
version, card_id, name, enabled=enabled version, card_id, name, enabled=enabled
) )

View File

@@ -11,6 +11,7 @@ from titles.cxb.config import CxbConfig
from titles.cxb.const import CxbConstants from titles.cxb.const import CxbConstants
from titles.cxb.database import CxbData from titles.cxb.database import CxbData
from threading import Thread
class CxbBase: class CxbBase:
def __init__(self, cfg: CoreConfig, game_cfg: CxbConfig) -> None: def __init__(self, cfg: CoreConfig, game_cfg: CxbConfig) -> None:
@@ -54,6 +55,151 @@ class CxbBase:
self.logger.warn(f"User {data['login']['authid']} does not have a profile") self.logger.warn(f"User {data['login']['authid']} does not have a profile")
return {} return {}
def task_generateCoupon(index, data1):
# Coupons
for i in range(500, 510):
index.append(str(i))
couponid = int(i) - 500
dataValue = [
{
"couponId": str(couponid),
"couponNum": "1",
"couponLog": [],
}
]
data1.append(
b64encode(
bytes(json.dumps(dataValue[0], separators=(",", ":")), "utf-8")
).decode("utf-8")
)
def task_generateShopListTitle(index, data1):
# ShopList_Title
for i in range(200000, 201451):
index.append(str(i))
shopid = int(i) - 200000
dataValue = [
{
"shopId": shopid,
"shopState": "2",
"isDisable": "t",
"isDeleted": "f",
"isSpecialFlag": "f",
}
]
data1.append(
b64encode(
bytes(json.dumps(dataValue[0], separators=(",", ":")), "utf-8")
).decode("utf-8")
)
def task_generateShopListIcon(index, data1):
# ShopList_Icon
for i in range(202000, 202264):
index.append(str(i))
shopid = int(i) - 200000
dataValue = [
{
"shopId": shopid,
"shopState": "2",
"isDisable": "t",
"isDeleted": "f",
"isSpecialFlag": "f",
}
]
data1.append(
b64encode(
bytes(json.dumps(dataValue[0], separators=(",", ":")), "utf-8")
).decode("utf-8")
)
def task_generateStories(index, data1):
# Stories
for i in range(900000, 900003):
index.append(str(i))
storyid = int(i) - 900000
dataValue = [
{
"storyId": storyid,
"unlockState1": ["t"] * 10,
"unlockState2": ["t"] * 10,
"unlockState3": ["t"] * 10,
"unlockState4": ["t"] * 10,
"unlockState5": ["t"] * 10,
"unlockState6": ["t"] * 10,
"unlockState7": ["t"] * 10,
"unlockState8": ["t"] * 10,
"unlockState9": ["t"] * 10,
"unlockState10": ["t"] * 10,
"unlockState11": ["t"] * 10,
"unlockState12": ["t"] * 10,
"unlockState13": ["t"] * 10,
"unlockState14": ["t"] * 10,
"unlockState15": ["t"] * 10,
"unlockState16": ["t"] * 10,
}
]
data1.append(
b64encode(
bytes(json.dumps(dataValue[0], separators=(",", ":")), "utf-8")
).decode("utf-8")
)
def task_generateScoreData(song, index, data1):
song_data = song["data"]
songCode = []
songCode.append(
{
"mcode": song_data["mcode"],
"musicState": song_data["musicState"],
"playCount": song_data["playCount"],
"totalScore": song_data["totalScore"],
"highScore": song_data["highScore"],
"everHighScore": song_data["everHighScore"]
if "everHighScore" in song_data
else ["0", "0", "0", "0", "0"],
"clearRate": song_data["clearRate"],
"rankPoint": song_data["rankPoint"],
"normalCR": song_data["normalCR"]
if "normalCR" in song_data
else ["0", "0", "0", "0", "0"],
"survivalCR": song_data["survivalCR"]
if "survivalCR" in song_data
else ["0", "0", "0", "0", "0"],
"ultimateCR": song_data["ultimateCR"]
if "ultimateCR" in song_data
else ["0", "0", "0", "0", "0"],
"nohopeCR": song_data["nohopeCR"]
if "nohopeCR" in song_data
else ["0", "0", "0", "0", "0"],
"combo": song_data["combo"],
"coupleUserId": song_data["coupleUserId"],
"difficulty": song_data["difficulty"],
"isFullCombo": song_data["isFullCombo"],
"clearGaugeType": song_data["clearGaugeType"],
"fieldType": song_data["fieldType"],
"gameType": song_data["gameType"],
"grade": song_data["grade"],
"unlockState": song_data["unlockState"],
"extraState": song_data["extraState"],
}
)
index.append(song_data["index"])
data1.append(
b64encode(
bytes(json.dumps(songCode[0], separators=(",", ":")), "utf-8")
).decode("utf-8")
)
def task_generateIndexData(versionindex):
try:
v_profile = self.data.profile.get_profile_index(0, uid, self.version)
v_profile_data = v_profile["data"]
versionindex.append(int(v_profile_data["appVersion"]))
except:
versionindex.append("10400")
def handle_action_loadrange_request(self, data: Dict) -> Dict: def handle_action_loadrange_request(self, data: Dict) -> Dict:
range_start = data["loadrange"]["range"][0] range_start = data["loadrange"]["range"][0]
range_end = data["loadrange"]["range"][1] range_end = data["loadrange"]["range"][1]
@@ -107,146 +253,29 @@ class CxbBase:
900000 = Stories 900000 = Stories
""" """
# Coupons # Async threads to generate the response
for i in range(500, 510): thread_Coupon = Thread(target=CxbBase.task_generateCoupon(index, data1))
index.append(str(i)) thread_ShopListTitle = Thread(target=CxbBase.task_generateShopListTitle(index, data1))
couponid = int(i) - 500 thread_ShopListIcon = Thread(target=CxbBase.task_generateShopListIcon(index, data1))
dataValue = [ thread_Stories = Thread(target=CxbBase.task_generateStories(index, data1))
{
"couponId": str(couponid),
"couponNum": "1",
"couponLog": [],
}
]
data1.append(
b64encode(
bytes(json.dumps(dataValue[0], separators=(",", ":")), "utf-8")
).decode("utf-8")
)
# ShopList_Title thread_Coupon.start()
for i in range(200000, 201451): thread_ShopListTitle.start()
index.append(str(i)) thread_ShopListIcon.start()
shopid = int(i) - 200000 thread_Stories.start()
dataValue = [
{
"shopId": shopid,
"shopState": "2",
"isDisable": "t",
"isDeleted": "f",
"isSpecialFlag": "f",
}
]
data1.append(
b64encode(
bytes(json.dumps(dataValue[0], separators=(",", ":")), "utf-8")
).decode("utf-8")
)
# ShopList_Icon thread_Coupon.join()
for i in range(202000, 202264): thread_ShopListTitle.join()
index.append(str(i)) thread_ShopListIcon.join()
shopid = int(i) - 200000 thread_Stories.join()
dataValue = [
{
"shopId": shopid,
"shopState": "2",
"isDisable": "t",
"isDeleted": "f",
"isSpecialFlag": "f",
}
]
data1.append(
b64encode(
bytes(json.dumps(dataValue[0], separators=(",", ":")), "utf-8")
).decode("utf-8")
)
# Stories
for i in range(900000, 900003):
index.append(str(i))
storyid = int(i) - 900000
dataValue = [
{
"storyId": storyid,
"unlockState1": ["t"] * 10,
"unlockState2": ["t"] * 10,
"unlockState3": ["t"] * 10,
"unlockState4": ["t"] * 10,
"unlockState5": ["t"] * 10,
"unlockState6": ["t"] * 10,
"unlockState7": ["t"] * 10,
"unlockState8": ["t"] * 10,
"unlockState9": ["t"] * 10,
"unlockState10": ["t"] * 10,
"unlockState11": ["t"] * 10,
"unlockState12": ["t"] * 10,
"unlockState13": ["t"] * 10,
"unlockState14": ["t"] * 10,
"unlockState15": ["t"] * 10,
"unlockState16": ["t"] * 10,
}
]
data1.append(
b64encode(
bytes(json.dumps(dataValue[0], separators=(",", ":")), "utf-8")
).decode("utf-8")
)
for song in songs: for song in songs:
song_data = song["data"] thread_ScoreData = Thread(target=CxbBase.task_generateScoreData(song, index, data1))
songCode = [] thread_ScoreData.start()
songCode.append(
{
"mcode": song_data["mcode"],
"musicState": song_data["musicState"],
"playCount": song_data["playCount"],
"totalScore": song_data["totalScore"],
"highScore": song_data["highScore"],
"everHighScore": song_data["everHighScore"]
if "everHighScore" in song_data
else ["0", "0", "0", "0", "0"],
"clearRate": song_data["clearRate"],
"rankPoint": song_data["rankPoint"],
"normalCR": song_data["normalCR"]
if "normalCR" in song_data
else ["0", "0", "0", "0", "0"],
"survivalCR": song_data["survivalCR"]
if "survivalCR" in song_data
else ["0", "0", "0", "0", "0"],
"ultimateCR": song_data["ultimateCR"]
if "ultimateCR" in song_data
else ["0", "0", "0", "0", "0"],
"nohopeCR": song_data["nohopeCR"]
if "nohopeCR" in song_data
else ["0", "0", "0", "0", "0"],
"combo": song_data["combo"],
"coupleUserId": song_data["coupleUserId"],
"difficulty": song_data["difficulty"],
"isFullCombo": song_data["isFullCombo"],
"clearGaugeType": song_data["clearGaugeType"],
"fieldType": song_data["fieldType"],
"gameType": song_data["gameType"],
"grade": song_data["grade"],
"unlockState": song_data["unlockState"],
"extraState": song_data["extraState"],
}
)
index.append(song_data["index"])
data1.append(
b64encode(
bytes(json.dumps(songCode[0], separators=(",", ":")), "utf-8")
).decode("utf-8")
)
for v in index: for v in index:
try: thread_IndexData = Thread(target=CxbBase.task_generateIndexData(versionindex))
v_profile = self.data.profile.get_profile_index(0, uid, self.version) thread_IndexData.start()
v_profile_data = v_profile["data"]
versionindex.append(int(v_profile_data["appVersion"]))
except:
versionindex.append("10400")
return {"index": index, "data": data1, "version": versionindex} return {"index": index, "data": data1, "version": versionindex}

View File

@@ -568,176 +568,3 @@ class Mai2DX(Mai2Base):
"nextIndex": next_index, "nextIndex": next_index,
"userMusicList": [{"userMusicDetailList": music_detail_list}], "userMusicList": [{"userMusicDetailList": music_detail_list}],
} }
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile_detail(data["userId"], self.version)
if p is None:
return {}
return {
"userName": p["userName"],
"rating": p["playerRating"],
# hardcode lastDataVersion for CardMaker 1.34
"lastDataVersion": "1.20.00",
"isLogin": False,
"isExistSellingCard": False,
}
def handle_cm_get_user_data_api_request(self, data: Dict) -> Dict:
# user already exists, because the preview checks that already
p = self.data.profile.get_profile_detail(data["userId"], self.version)
cards = self.data.card.get_user_cards(data["userId"])
if cards is None or len(cards) == 0:
# This should never happen
self.logger.error(
f"handle_get_user_data_api_request: Internal error - No cards found for user id {data['userId']}"
)
return {}
# get the dict representation of the row so we can modify values
user_data = p._asdict()
# remove the values the game doesn't want
user_data.pop("id")
user_data.pop("user")
user_data.pop("version")
return {"userId": data["userId"], "userData": user_data}
def handle_cm_login_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1}
def handle_cm_logout_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1}
def handle_cm_get_selling_card_api_request(self, data: Dict) -> Dict:
selling_cards = self.data.static.get_enabled_cards(self.version)
if selling_cards is None:
return {"length": 0, "sellingCardList": []}
selling_card_list = []
for card in selling_cards:
tmp = card._asdict()
tmp.pop("id")
tmp.pop("version")
tmp.pop("cardName")
tmp.pop("enabled")
tmp["startDate"] = datetime.strftime(tmp["startDate"], "%Y-%m-%d %H:%M:%S")
tmp["endDate"] = datetime.strftime(tmp["endDate"], "%Y-%m-%d %H:%M:%S")
tmp["noticeStartDate"] = datetime.strftime(
tmp["noticeStartDate"], "%Y-%m-%d %H:%M:%S"
)
tmp["noticeEndDate"] = datetime.strftime(
tmp["noticeEndDate"], "%Y-%m-%d %H:%M:%S"
)
selling_card_list.append(tmp)
return {"length": len(selling_card_list), "sellingCardList": selling_card_list}
def handle_cm_get_user_card_api_request(self, data: Dict) -> Dict:
user_cards = self.data.item.get_cards(data["userId"])
if user_cards is None:
return {"returnCode": 1, "length": 0, "nextIndex": 0, "userCardList": []}
max_ct = data["maxCount"]
next_idx = data["nextIndex"]
start_idx = next_idx
end_idx = max_ct + start_idx
if len(user_cards[start_idx:]) > max_ct:
next_idx += max_ct
else:
next_idx = 0
card_list = []
for card in user_cards:
tmp = card._asdict()
tmp.pop("id")
tmp.pop("user")
tmp["startDate"] = datetime.strftime(tmp["startDate"], "%Y-%m-%d %H:%M:%S")
tmp["endDate"] = datetime.strftime(tmp["endDate"], "%Y-%m-%d %H:%M:%S")
card_list.append(tmp)
return {
"returnCode": 1,
"length": len(card_list[start_idx:end_idx]),
"nextIndex": next_idx,
"userCardList": card_list[start_idx:end_idx],
}
def handle_cm_get_user_item_api_request(self, data: Dict) -> Dict:
super().handle_get_user_item_api_request(data)
def handle_cm_get_user_character_api_request(self, data: Dict) -> Dict:
characters = self.data.item.get_characters(data["userId"])
chara_list = []
for chara in characters:
chara_list.append(
{
"characterId": chara["characterId"],
# no clue why those values are even needed
"point": 0,
"count": 0,
"level": chara["level"],
"nextAwake": 0,
"nextAwakePercent": 0,
"favorite": False,
"awakening": chara["awakening"],
"useCount": chara["useCount"],
}
)
return {
"returnCode": 1,
"length": len(chara_list),
"userCharacterList": chara_list,
}
def handle_cm_get_user_card_print_error_api_request(self, data: Dict) -> Dict:
return {"length": 0, "userPrintDetailList": []}
def handle_cm_upsert_user_print_api_request(self, data: Dict) -> Dict:
user_id = data["userId"]
upsert = data["userPrintDetail"]
# set a random card serial number
serial_id = "".join([str(randint(0, 9)) for _ in range(20)])
user_card = upsert["userCard"]
self.data.item.put_card(
user_id,
user_card["cardId"],
user_card["cardTypeId"],
user_card["charaId"],
user_card["mapId"],
)
# properly format userPrintDetail for the database
upsert.pop("userCard")
upsert.pop("serialId")
upsert["printDate"] = datetime.strptime(upsert["printDate"], "%Y-%m-%d")
self.data.item.put_user_print_detail(user_id, serial_id, upsert)
return {
"returnCode": 1,
"orderId": 0,
"serialId": serial_id,
"startDate": "2018-01-01 00:00:00",
"endDate": "2038-01-01 00:00:00",
}
def handle_cm_upsert_user_printlog_api_request(self, data: Dict) -> Dict:
return {
"returnCode": 1,
"orderId": 0,
"serialId": data["userPrintlog"]["serialId"],
}
def handle_cm_upsert_buy_card_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1}

View File

@@ -1,12 +1,12 @@
from typing import Dict from typing import Dict
from core.config import CoreConfig from core.config import CoreConfig
from titles.mai2.dx import Mai2DX from titles.mai2.universeplus import Mai2UniversePlus
from titles.mai2.const import Mai2Constants from titles.mai2.const import Mai2Constants
from titles.mai2.config import Mai2Config from titles.mai2.config import Mai2Config
class Mai2Festival(Mai2DX): class Mai2Festival(Mai2UniversePlus):
def __init__(self, cfg: CoreConfig, game_cfg: Mai2Config) -> None: def __init__(self, cfg: CoreConfig, game_cfg: Mai2Config) -> None:
super().__init__(cfg, game_cfg) super().__init__(cfg, game_cfg)
self.version = Mai2Constants.VER_MAIMAI_DX_FESTIVAL self.version = Mai2Constants.VER_MAIMAI_DX_FESTIVAL
@@ -14,7 +14,7 @@ class Mai2Festival(Mai2DX):
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict: def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = super().handle_cm_get_user_preview_api_request(data) user_data = super().handle_cm_get_user_preview_api_request(data)
# hardcode lastDataVersion for CardMaker 1.36 # hardcode lastDataVersion for CardMaker 1.35
user_data["lastDataVersion"] = "1.30.00" user_data["lastDataVersion"] = "1.30.00"
return user_data return user_data

View File

@@ -4,12 +4,12 @@ import pytz
import json import json
from core.config import CoreConfig from core.config import CoreConfig
from titles.mai2.dx import Mai2DX from titles.mai2.dxplus import Mai2DXPlus
from titles.mai2.config import Mai2Config from titles.mai2.config import Mai2Config
from titles.mai2.const import Mai2Constants from titles.mai2.const import Mai2Constants
class Mai2Splash(Mai2DX): class Mai2Splash(Mai2DXPlus):
def __init__(self, cfg: CoreConfig, game_cfg: Mai2Config) -> None: def __init__(self, cfg: CoreConfig, game_cfg: Mai2Config) -> None:
super().__init__(cfg, game_cfg) super().__init__(cfg, game_cfg)
self.version = Mai2Constants.VER_MAIMAI_DX_SPLASH self.version = Mai2Constants.VER_MAIMAI_DX_SPLASH

View File

@@ -4,12 +4,12 @@ import pytz
import json import json
from core.config import CoreConfig from core.config import CoreConfig
from titles.mai2.dx import Mai2DX from titles.mai2.splash import Mai2Splash
from titles.mai2.config import Mai2Config from titles.mai2.config import Mai2Config
from titles.mai2.const import Mai2Constants from titles.mai2.const import Mai2Constants
class Mai2SplashPlus(Mai2DX): class Mai2SplashPlus(Mai2Splash):
def __init__(self, cfg: CoreConfig, game_cfg: Mai2Config) -> None: def __init__(self, cfg: CoreConfig, game_cfg: Mai2Config) -> None:
super().__init__(cfg, game_cfg) super().__init__(cfg, game_cfg)
self.version = Mai2Constants.VER_MAIMAI_DX_SPLASH_PLUS self.version = Mai2Constants.VER_MAIMAI_DX_SPLASH_PLUS

View File

@@ -5,12 +5,12 @@ import pytz
import json import json
from core.config import CoreConfig from core.config import CoreConfig
from titles.mai2.dx import Mai2DX from titles.mai2.splashplus import Mai2SplashPlus
from titles.mai2.const import Mai2Constants from titles.mai2.const import Mai2Constants
from titles.mai2.config import Mai2Config from titles.mai2.config import Mai2Config
class Mai2Universe(Mai2DX): class Mai2Universe(Mai2SplashPlus):
def __init__(self, cfg: CoreConfig, game_cfg: Mai2Config) -> None: def __init__(self, cfg: CoreConfig, game_cfg: Mai2Config) -> None:
super().__init__(cfg, game_cfg) super().__init__(cfg, game_cfg)
self.version = Mai2Constants.VER_MAIMAI_DX_UNIVERSE self.version = Mai2Constants.VER_MAIMAI_DX_UNIVERSE
@@ -70,13 +70,13 @@ class Mai2Universe(Mai2DX):
tmp.pop("cardName") tmp.pop("cardName")
tmp.pop("enabled") tmp.pop("enabled")
tmp["startDate"] = datetime.strftime(tmp["startDate"], "%Y-%m-%d %H:%M:%S") tmp["startDate"] = datetime.strftime(tmp["startDate"], Mai2Constants.DATE_TIME_FORMAT)
tmp["endDate"] = datetime.strftime(tmp["endDate"], "%Y-%m-%d %H:%M:%S") tmp["endDate"] = datetime.strftime(tmp["endDate"], Mai2Constants.DATE_TIME_FORMAT)
tmp["noticeStartDate"] = datetime.strftime( tmp["noticeStartDate"] = datetime.strftime(
tmp["noticeStartDate"], "%Y-%m-%d %H:%M:%S" tmp["noticeStartDate"], Mai2Constants.DATE_TIME_FORMAT
) )
tmp["noticeEndDate"] = datetime.strftime( tmp["noticeEndDate"] = datetime.strftime(
tmp["noticeEndDate"], "%Y-%m-%d %H:%M:%S" tmp["noticeEndDate"], Mai2Constants.DATE_TIME_FORMAT
) )
selling_card_list.append(tmp) selling_card_list.append(tmp)

View File

@@ -1,12 +1,12 @@
from typing import Dict from typing import Dict
from core.config import CoreConfig from core.config import CoreConfig
from titles.mai2.dx import Mai2DX from titles.mai2.universe import Mai2Universe
from titles.mai2.const import Mai2Constants from titles.mai2.const import Mai2Constants
from titles.mai2.config import Mai2Config from titles.mai2.config import Mai2Config
class Mai2UniversePlus(Mai2DX): class Mai2UniversePlus(Mai2Universe):
def __init__(self, cfg: CoreConfig, game_cfg: Mai2Config) -> None: def __init__(self, cfg: CoreConfig, game_cfg: Mai2Config) -> None:
super().__init__(cfg, game_cfg) super().__init__(cfg, game_cfg)
self.version = Mai2Constants.VER_MAIMAI_DX_UNIVERSE_PLUS self.version = Mai2Constants.VER_MAIMAI_DX_UNIVERSE_PLUS