forked from Hay1tsme/artemis
let black do it's magic
This commit is contained in:
@ -5,12 +5,13 @@ from titles.chuni.base import ChuniBase
|
||||
from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
|
||||
class ChuniAir(ChuniBase):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
self.version = ChuniConstants.VER_CHUNITHM_AIR
|
||||
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["dataVersion"] = "1.10.00"
|
||||
return ret
|
||||
return ret
|
||||
|
@ -5,12 +5,13 @@ from titles.chuni.base import ChuniBase
|
||||
from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
|
||||
class ChuniAirPlus(ChuniBase):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
self.version = ChuniConstants.VER_CHUNITHM_AIR_PLUS
|
||||
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["dataVersion"] = "1.15.00"
|
||||
return ret
|
||||
return ret
|
||||
|
@ -7,12 +7,13 @@ from titles.chuni.base import ChuniBase
|
||||
from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
|
||||
class ChuniAmazon(ChuniBase):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
self.version = ChuniConstants.VER_CHUNITHM_AMAZON
|
||||
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["dataVersion"] = "1.30.00"
|
||||
return ret
|
||||
|
@ -7,12 +7,13 @@ from titles.chuni.base import ChuniBase
|
||||
from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
|
||||
class ChuniAmazonPlus(ChuniBase):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
self.version = ChuniConstants.VER_CHUNITHM_AMAZON_PLUS
|
||||
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["dataVersion"] = "1.35.00"
|
||||
return ret
|
||||
|
@ -11,7 +11,8 @@ from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.database import ChuniData
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
class ChuniBase():
|
||||
|
||||
class ChuniBase:
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
self.core_cfg = core_cfg
|
||||
self.game_cfg = game_cfg
|
||||
@ -22,32 +23,31 @@ class ChuniBase():
|
||||
self.version = ChuniConstants.VER_CHUNITHM
|
||||
|
||||
def handle_game_login_api_request(self, data: Dict) -> Dict:
|
||||
#self.data.base.log_event("chuni", "login", logging.INFO, {"version": self.version, "user": data["userId"]})
|
||||
return { "returnCode": 1 }
|
||||
|
||||
# self.data.base.log_event("chuni", "login", logging.INFO, {"version": self.version, "user": data["userId"]})
|
||||
return {"returnCode": 1}
|
||||
|
||||
def handle_game_logout_api_request(self, data: Dict) -> Dict:
|
||||
#self.data.base.log_event("chuni", "logout", logging.INFO, {"version": self.version, "user": data["userId"]})
|
||||
return { "returnCode": 1 }
|
||||
# self.data.base.log_event("chuni", "logout", logging.INFO, {"version": self.version, "user": data["userId"]})
|
||||
return {"returnCode": 1}
|
||||
|
||||
def handle_get_game_charge_api_request(self, data: Dict) -> Dict:
|
||||
game_charge_list = self.data.static.get_enabled_charges(self.version)
|
||||
|
||||
charges = []
|
||||
for x in range(len(game_charge_list)):
|
||||
charges.append({
|
||||
"orderId": x,
|
||||
"chargeId": game_charge_list[x]["chargeId"],
|
||||
"price": 1,
|
||||
"startDate": "2017-12-05 07:00:00.0",
|
||||
"endDate": "2099-12-31 00:00:00.0",
|
||||
"salePrice": 1,
|
||||
"saleStartDate": "2017-12-05 07:00:00.0",
|
||||
"saleEndDate": "2099-12-31 00:00:00.0"
|
||||
})
|
||||
return {
|
||||
"length": len(charges),
|
||||
"gameChargeList": charges
|
||||
}
|
||||
for x in range(len(game_charge_list)):
|
||||
charges.append(
|
||||
{
|
||||
"orderId": x,
|
||||
"chargeId": game_charge_list[x]["chargeId"],
|
||||
"price": 1,
|
||||
"startDate": "2017-12-05 07:00:00.0",
|
||||
"endDate": "2099-12-31 00:00:00.0",
|
||||
"salePrice": 1,
|
||||
"saleStartDate": "2017-12-05 07:00:00.0",
|
||||
"saleEndDate": "2099-12-31 00:00:00.0",
|
||||
}
|
||||
)
|
||||
return {"length": len(charges), "gameChargeList": charges}
|
||||
|
||||
def handle_get_game_event_api_request(self, data: Dict) -> Dict:
|
||||
game_events = self.data.static.get_enabled_events(self.version)
|
||||
@ -62,26 +62,30 @@ class ChuniBase():
|
||||
event_list.append(tmp)
|
||||
|
||||
return {
|
||||
"type": data["type"],
|
||||
"length": len(event_list),
|
||||
"gameEventList": event_list
|
||||
"type": data["type"],
|
||||
"length": len(event_list),
|
||||
"gameEventList": event_list,
|
||||
}
|
||||
|
||||
def handle_get_game_idlist_api_request(self, data: Dict) -> Dict:
|
||||
return { "type": data["type"], "length": 0, "gameIdlistList": [] }
|
||||
return {"type": data["type"], "length": 0, "gameIdlistList": []}
|
||||
|
||||
def handle_get_game_message_api_request(self, data: Dict) -> Dict:
|
||||
return { "type": data["type"], "length": "0", "gameMessageList": [] }
|
||||
return {"type": data["type"], "length": "0", "gameMessageList": []}
|
||||
|
||||
def handle_get_game_ranking_api_request(self, data: Dict) -> Dict:
|
||||
return { "type": data["type"], "gameRankingList": [] }
|
||||
return {"type": data["type"], "gameRankingList": []}
|
||||
|
||||
def handle_get_game_sale_api_request(self, data: Dict) -> Dict:
|
||||
return { "type": data["type"], "length": 0, "gameSaleList": [] }
|
||||
return {"type": data["type"], "length": 0, "gameSaleList": []}
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
reboot_start = datetime.strftime(datetime.now() - timedelta(hours=4), self.date_time_format)
|
||||
reboot_end = datetime.strftime(datetime.now() - timedelta(hours=3), self.date_time_format)
|
||||
reboot_start = datetime.strftime(
|
||||
datetime.now() - timedelta(hours=4), self.date_time_format
|
||||
)
|
||||
reboot_end = datetime.strftime(
|
||||
datetime.now() - timedelta(hours=3), self.date_time_format
|
||||
)
|
||||
return {
|
||||
"gameSetting": {
|
||||
"dataVersion": "1.00.00",
|
||||
@ -94,15 +98,17 @@ class ChuniBase():
|
||||
"maxCountItem": 300,
|
||||
"maxCountMusic": 300,
|
||||
},
|
||||
"isDumpUpload": "false",
|
||||
"isAou": "false",
|
||||
"isDumpUpload": "false",
|
||||
"isAou": "false",
|
||||
}
|
||||
|
||||
def handle_get_user_activity_api_request(self, data: Dict) -> Dict:
|
||||
user_activity_list = self.data.profile.get_profile_activity(data["userId"], data["kind"])
|
||||
|
||||
user_activity_list = self.data.profile.get_profile_activity(
|
||||
data["userId"], data["kind"]
|
||||
)
|
||||
|
||||
activity_list = []
|
||||
|
||||
|
||||
for activity in user_activity_list:
|
||||
tmp = activity._asdict()
|
||||
tmp.pop("user")
|
||||
@ -111,15 +117,16 @@ class ChuniBase():
|
||||
activity_list.append(tmp)
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"length": len(activity_list),
|
||||
"kind": data["kind"],
|
||||
"userActivityList": activity_list
|
||||
"userId": data["userId"],
|
||||
"length": len(activity_list),
|
||||
"kind": data["kind"],
|
||||
"userActivityList": activity_list,
|
||||
}
|
||||
|
||||
def handle_get_user_character_api_request(self, data: Dict) -> Dict:
|
||||
characters = self.data.item.get_characters(data["userId"])
|
||||
if characters is None: return {}
|
||||
if characters is None:
|
||||
return {}
|
||||
next_idx = -1
|
||||
|
||||
characterList = []
|
||||
@ -131,15 +138,17 @@ class ChuniBase():
|
||||
|
||||
if len(characterList) >= int(data["maxCount"]):
|
||||
break
|
||||
|
||||
if len(characterList) >= int(data["maxCount"]) and len(characters) > int(data["maxCount"]) + int(data["nextIndex"]):
|
||||
|
||||
if len(characterList) >= int(data["maxCount"]) and len(characters) > int(
|
||||
data["maxCount"]
|
||||
) + int(data["nextIndex"]):
|
||||
next_idx = int(data["maxCount"]) + int(data["nextIndex"]) + 1
|
||||
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userId": data["userId"],
|
||||
"length": len(characterList),
|
||||
"nextIndex": next_idx,
|
||||
"userCharacterList": characterList
|
||||
"nextIndex": next_idx,
|
||||
"userCharacterList": characterList,
|
||||
}
|
||||
|
||||
def handle_get_user_charge_api_request(self, data: Dict) -> Dict:
|
||||
@ -153,21 +162,21 @@ class ChuniBase():
|
||||
charge_list.append(tmp)
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userId": data["userId"],
|
||||
"length": len(charge_list),
|
||||
"userChargeList": charge_list
|
||||
"userChargeList": charge_list,
|
||||
}
|
||||
|
||||
def handle_get_user_course_api_request(self, data: Dict) -> Dict:
|
||||
user_course_list = self.data.score.get_courses(data["userId"])
|
||||
if user_course_list is None:
|
||||
if user_course_list is None:
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userId": data["userId"],
|
||||
"length": 0,
|
||||
"nextIndex": -1,
|
||||
"userCourseList": []
|
||||
"nextIndex": -1,
|
||||
"userCourseList": [],
|
||||
}
|
||||
|
||||
|
||||
course_list = []
|
||||
next_idx = int(data["nextIndex"])
|
||||
max_ct = int(data["maxCount"])
|
||||
@ -180,51 +189,48 @@ class ChuniBase():
|
||||
|
||||
if len(user_course_list) >= max_ct:
|
||||
break
|
||||
|
||||
|
||||
if len(user_course_list) >= max_ct:
|
||||
next_idx = next_idx + max_ct
|
||||
else:
|
||||
next_idx = -1
|
||||
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userId": data["userId"],
|
||||
"length": len(course_list),
|
||||
"nextIndex": next_idx,
|
||||
"userCourseList": course_list
|
||||
"nextIndex": next_idx,
|
||||
"userCourseList": course_list,
|
||||
}
|
||||
|
||||
def handle_get_user_data_api_request(self, data: Dict) -> Dict:
|
||||
p = self.data.profile.get_profile_data(data["userId"], self.version)
|
||||
if p is None: return {}
|
||||
if p is None:
|
||||
return {}
|
||||
|
||||
profile = p._asdict()
|
||||
profile.pop("id")
|
||||
profile.pop("user")
|
||||
profile.pop("version")
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userData": profile
|
||||
}
|
||||
return {"userId": data["userId"], "userData": profile}
|
||||
|
||||
def handle_get_user_data_ex_api_request(self, data: Dict) -> Dict:
|
||||
p = self.data.profile.get_profile_data_ex(data["userId"], self.version)
|
||||
if p is None: return {}
|
||||
if p is None:
|
||||
return {}
|
||||
|
||||
profile = p._asdict()
|
||||
profile.pop("id")
|
||||
profile.pop("user")
|
||||
profile.pop("version")
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userDataEx": profile
|
||||
}
|
||||
return {"userId": data["userId"], "userDataEx": profile}
|
||||
|
||||
def handle_get_user_duel_api_request(self, data: Dict) -> Dict:
|
||||
user_duel_list = self.data.item.get_duels(data["userId"])
|
||||
if user_duel_list is None: return {}
|
||||
|
||||
if user_duel_list is None:
|
||||
return {}
|
||||
|
||||
duel_list = []
|
||||
for duel in user_duel_list:
|
||||
tmp = duel._asdict()
|
||||
@ -233,18 +239,18 @@ class ChuniBase():
|
||||
duel_list.append(tmp)
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userId": data["userId"],
|
||||
"length": len(duel_list),
|
||||
"userDuelList": duel_list
|
||||
"userDuelList": duel_list,
|
||||
}
|
||||
|
||||
def handle_get_user_favorite_item_api_request(self, data: Dict) -> Dict:
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userId": data["userId"],
|
||||
"length": 0,
|
||||
"kind": data["kind"],
|
||||
"nextIndex": -1,
|
||||
"userFavoriteItemList": []
|
||||
"kind": data["kind"],
|
||||
"nextIndex": -1,
|
||||
"userFavoriteItemList": [],
|
||||
}
|
||||
|
||||
def handle_get_user_favorite_music_api_request(self, data: Dict) -> Dict:
|
||||
@ -252,22 +258,23 @@ class ChuniBase():
|
||||
This is handled via the webui, which we don't have right now
|
||||
"""
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"length": 0,
|
||||
"userFavoriteMusicList": []
|
||||
}
|
||||
return {"userId": data["userId"], "length": 0, "userFavoriteMusicList": []}
|
||||
|
||||
def handle_get_user_item_api_request(self, data: Dict) -> Dict:
|
||||
kind = int(int(data["nextIndex"]) / 10000000000)
|
||||
next_idx = int(int(data["nextIndex"]) % 10000000000)
|
||||
user_item_list = self.data.item.get_items(data["userId"], kind)
|
||||
|
||||
if user_item_list is None or len(user_item_list) == 0:
|
||||
return {"userId": data["userId"], "nextIndex": -1, "itemKind": kind, "userItemList": []}
|
||||
if user_item_list is None or len(user_item_list) == 0:
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"nextIndex": -1,
|
||||
"itemKind": kind,
|
||||
"userItemList": [],
|
||||
}
|
||||
|
||||
items: list[Dict[str, Any]] = []
|
||||
for i in range(next_idx, len(user_item_list)):
|
||||
for i in range(next_idx, len(user_item_list)):
|
||||
tmp = user_item_list[i]._asdict()
|
||||
tmp.pop("user")
|
||||
tmp.pop("id")
|
||||
@ -277,38 +284,47 @@ class ChuniBase():
|
||||
|
||||
xout = kind * 10000000000 + next_idx + len(items)
|
||||
|
||||
if len(items) < int(data["maxCount"]): nextIndex = 0
|
||||
else: nextIndex = xout
|
||||
if len(items) < int(data["maxCount"]):
|
||||
nextIndex = 0
|
||||
else:
|
||||
nextIndex = xout
|
||||
|
||||
return {"userId": data["userId"], "nextIndex": nextIndex, "itemKind": kind, "length": len(items), "userItemList": items}
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"nextIndex": nextIndex,
|
||||
"itemKind": kind,
|
||||
"length": len(items),
|
||||
"userItemList": items,
|
||||
}
|
||||
|
||||
def handle_get_user_login_bonus_api_request(self, data: Dict) -> Dict:
|
||||
"""
|
||||
Unsure how to get this to trigger...
|
||||
"""
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userId": data["userId"],
|
||||
"length": 2,
|
||||
"userLoginBonusList": [
|
||||
{
|
||||
"presetId": '10',
|
||||
"bonusCount": '0',
|
||||
"lastUpdateDate": "1970-01-01 09:00:00",
|
||||
"isWatched": "true"
|
||||
"presetId": "10",
|
||||
"bonusCount": "0",
|
||||
"lastUpdateDate": "1970-01-01 09:00:00",
|
||||
"isWatched": "true",
|
||||
},
|
||||
{
|
||||
"presetId": '20',
|
||||
"bonusCount": '0',
|
||||
"lastUpdateDate": "1970-01-01 09:00:00",
|
||||
"isWatched": "true"
|
||||
"presetId": "20",
|
||||
"bonusCount": "0",
|
||||
"lastUpdateDate": "1970-01-01 09:00:00",
|
||||
"isWatched": "true",
|
||||
},
|
||||
]
|
||||
],
|
||||
}
|
||||
|
||||
def handle_get_user_map_api_request(self, data: Dict) -> Dict:
|
||||
user_map_list = self.data.item.get_maps(data["userId"])
|
||||
if user_map_list is None: return {}
|
||||
|
||||
if user_map_list is None:
|
||||
return {}
|
||||
|
||||
map_list = []
|
||||
for map in user_map_list:
|
||||
tmp = map._asdict()
|
||||
@ -317,19 +333,19 @@ class ChuniBase():
|
||||
map_list.append(tmp)
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userId": data["userId"],
|
||||
"length": len(map_list),
|
||||
"userMapList": map_list
|
||||
"userMapList": map_list,
|
||||
}
|
||||
|
||||
def handle_get_user_music_api_request(self, data: Dict) -> Dict:
|
||||
music_detail = self.data.score.get_scores(data["userId"])
|
||||
if music_detail is None:
|
||||
if music_detail is None:
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"length": 0,
|
||||
"userId": data["userId"],
|
||||
"length": 0,
|
||||
"nextIndex": -1,
|
||||
"userMusicList": [] #240
|
||||
"userMusicList": [], # 240
|
||||
}
|
||||
song_list = []
|
||||
next_idx = int(data["nextIndex"])
|
||||
@ -340,66 +356,60 @@ class ChuniBase():
|
||||
tmp = music_detail[x]._asdict()
|
||||
tmp.pop("user")
|
||||
tmp.pop("id")
|
||||
|
||||
|
||||
for song in song_list:
|
||||
if song["userMusicDetailList"][0]["musicId"] == tmp["musicId"]:
|
||||
found = True
|
||||
song["userMusicDetailList"].append(tmp)
|
||||
song["length"] = len(song["userMusicDetailList"])
|
||||
|
||||
|
||||
if not found:
|
||||
song_list.append({
|
||||
"length": 1,
|
||||
"userMusicDetailList": [tmp]
|
||||
})
|
||||
|
||||
song_list.append({"length": 1, "userMusicDetailList": [tmp]})
|
||||
|
||||
if len(song_list) >= max_ct:
|
||||
break
|
||||
|
||||
|
||||
if len(song_list) >= max_ct:
|
||||
next_idx += max_ct
|
||||
else:
|
||||
next_idx = 0
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"length": len(song_list),
|
||||
"userId": data["userId"],
|
||||
"length": len(song_list),
|
||||
"nextIndex": next_idx,
|
||||
"userMusicList": song_list #240
|
||||
"userMusicList": song_list, # 240
|
||||
}
|
||||
|
||||
def handle_get_user_option_api_request(self, data: Dict) -> Dict:
|
||||
p = self.data.profile.get_profile_option(data["userId"])
|
||||
|
||||
|
||||
option = p._asdict()
|
||||
option.pop("id")
|
||||
option.pop("user")
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userGameOption": option
|
||||
}
|
||||
return {"userId": data["userId"], "userGameOption": option}
|
||||
|
||||
def handle_get_user_option_ex_api_request(self, data: Dict) -> Dict:
|
||||
p = self.data.profile.get_profile_option_ex(data["userId"])
|
||||
|
||||
|
||||
option = p._asdict()
|
||||
option.pop("id")
|
||||
option.pop("user")
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userGameOptionEx": option
|
||||
}
|
||||
return {"userId": data["userId"], "userGameOptionEx": option}
|
||||
|
||||
def read_wtf8(self, src):
|
||||
return bytes([ord(c) for c in src]).decode("utf-8")
|
||||
|
||||
def handle_get_user_preview_api_request(self, data: Dict) -> Dict:
|
||||
profile = self.data.profile.get_profile_preview(data["userId"], self.version)
|
||||
if profile is None: return None
|
||||
profile_character = self.data.item.get_character(data["userId"], profile["characterId"])
|
||||
|
||||
if profile is None:
|
||||
return None
|
||||
profile_character = self.data.item.get_character(
|
||||
data["userId"], profile["characterId"]
|
||||
)
|
||||
|
||||
if profile_character is None:
|
||||
chara = {}
|
||||
else:
|
||||
@ -408,8 +418,8 @@ class ChuniBase():
|
||||
chara.pop("user")
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
# Current Login State
|
||||
"userId": data["userId"],
|
||||
# Current Login State
|
||||
"isLogin": False,
|
||||
"lastLoginDate": profile["lastPlayDate"],
|
||||
# User Profile
|
||||
@ -421,14 +431,14 @@ class ChuniBase():
|
||||
"lastGameId": profile["lastGameId"],
|
||||
"lastRomVersion": profile["lastRomVersion"],
|
||||
"lastDataVersion": profile["lastDataVersion"],
|
||||
"lastPlayDate": profile["lastPlayDate"],
|
||||
"trophyId": profile["trophyId"],
|
||||
"lastPlayDate": profile["lastPlayDate"],
|
||||
"trophyId": profile["trophyId"],
|
||||
"nameplateId": profile["nameplateId"],
|
||||
# Current Selected Character
|
||||
"userCharacter": chara,
|
||||
# User Game Options
|
||||
"playerLevel": profile["playerLevel"],
|
||||
"rating": profile["rating"],
|
||||
"playerLevel": profile["playerLevel"],
|
||||
"rating": profile["rating"],
|
||||
"headphone": profile["headphone"],
|
||||
"chargeState": "1",
|
||||
"userNameEx": profile["userName"],
|
||||
@ -436,7 +446,7 @@ class ChuniBase():
|
||||
|
||||
def handle_get_user_recent_rating_api_request(self, data: Dict) -> Dict:
|
||||
recet_rating_list = self.data.profile.get_profile_recent_rating(data["userId"])
|
||||
if recet_rating_list is None:
|
||||
if recet_rating_list is None:
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"length": 0,
|
||||
@ -459,11 +469,8 @@ class ChuniBase():
|
||||
|
||||
def handle_get_user_team_api_request(self, data: Dict) -> Dict:
|
||||
# TODO: Team
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"teamId": 0
|
||||
}
|
||||
|
||||
return {"userId": data["userId"], "teamId": 0}
|
||||
|
||||
def handle_get_team_course_setting_api_request(self, data: Dict) -> Dict:
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
@ -486,19 +493,30 @@ class ChuniBase():
|
||||
|
||||
if "userData" in upsert:
|
||||
try:
|
||||
upsert["userData"][0]["userName"] = self.read_wtf8(upsert["userData"][0]["userName"])
|
||||
except: pass
|
||||
upsert["userData"][0]["userName"] = self.read_wtf8(
|
||||
upsert["userData"][0]["userName"]
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
self.data.profile.put_profile_data(user_id, self.version, upsert["userData"][0])
|
||||
self.data.profile.put_profile_data(
|
||||
user_id, self.version, upsert["userData"][0]
|
||||
)
|
||||
if "userDataEx" in upsert:
|
||||
self.data.profile.put_profile_data_ex(user_id, self.version, upsert["userDataEx"][0])
|
||||
self.data.profile.put_profile_data_ex(
|
||||
user_id, self.version, upsert["userDataEx"][0]
|
||||
)
|
||||
if "userGameOption" in upsert:
|
||||
self.data.profile.put_profile_option(user_id, upsert["userGameOption"][0])
|
||||
if "userGameOptionEx" in upsert:
|
||||
self.data.profile.put_profile_option_ex(user_id, upsert["userGameOptionEx"][0])
|
||||
self.data.profile.put_profile_option_ex(
|
||||
user_id, upsert["userGameOptionEx"][0]
|
||||
)
|
||||
if "userRecentRatingList" in upsert:
|
||||
self.data.profile.put_profile_recent_rating(user_id, upsert["userRecentRatingList"])
|
||||
|
||||
self.data.profile.put_profile_recent_rating(
|
||||
user_id, upsert["userRecentRatingList"]
|
||||
)
|
||||
|
||||
if "userCharacterList" in upsert:
|
||||
for character in upsert["userCharacterList"]:
|
||||
self.data.item.put_character(user_id, character)
|
||||
@ -514,7 +532,7 @@ class ChuniBase():
|
||||
if "userDuelList" in upsert:
|
||||
for duel in upsert["userDuelList"]:
|
||||
self.data.item.put_duel(user_id, duel)
|
||||
|
||||
|
||||
if "userItemList" in upsert:
|
||||
for item in upsert["userItemList"]:
|
||||
self.data.item.put_item(user_id, item)
|
||||
@ -522,23 +540,23 @@ class ChuniBase():
|
||||
if "userActivityList" in upsert:
|
||||
for activity in upsert["userActivityList"]:
|
||||
self.data.profile.put_profile_activity(user_id, activity)
|
||||
|
||||
|
||||
if "userChargeList" in upsert:
|
||||
for charge in upsert["userChargeList"]:
|
||||
self.data.profile.put_profile_charge(user_id, charge)
|
||||
|
||||
|
||||
if "userMusicDetailList" in upsert:
|
||||
for song in upsert["userMusicDetailList"]:
|
||||
self.data.score.put_score(user_id, song)
|
||||
|
||||
|
||||
if "userPlaylogList" in upsert:
|
||||
for playlog in upsert["userPlaylogList"]:
|
||||
self.data.score.put_playlog(user_id, playlog)
|
||||
|
||||
|
||||
if "userTeamPoint" in upsert:
|
||||
# TODO: team stuff
|
||||
pass
|
||||
|
||||
|
||||
if "userMapAreaList" in upsert:
|
||||
for map_area in upsert["userMapAreaList"]:
|
||||
self.data.item.put_map_area(user_id, map_area)
|
||||
@ -551,22 +569,22 @@ class ChuniBase():
|
||||
for emoney in upsert["userEmoneyList"]:
|
||||
self.data.profile.put_profile_emoney(user_id, emoney)
|
||||
|
||||
return { "returnCode": "1" }
|
||||
return {"returnCode": "1"}
|
||||
|
||||
def handle_upsert_user_chargelog_api_request(self, data: Dict) -> Dict:
|
||||
return { "returnCode": "1" }
|
||||
return {"returnCode": "1"}
|
||||
|
||||
def handle_upsert_client_bookkeeping_api_request(self, data: Dict) -> Dict:
|
||||
return { "returnCode": "1" }
|
||||
return {"returnCode": "1"}
|
||||
|
||||
def handle_upsert_client_develop_api_request(self, data: Dict) -> Dict:
|
||||
return { "returnCode": "1" }
|
||||
return {"returnCode": "1"}
|
||||
|
||||
def handle_upsert_client_error_api_request(self, data: Dict) -> Dict:
|
||||
return { "returnCode": "1" }
|
||||
return {"returnCode": "1"}
|
||||
|
||||
def handle_upsert_client_setting_api_request(self, data: Dict) -> Dict:
|
||||
return { "returnCode": "1" }
|
||||
return {"returnCode": "1"}
|
||||
|
||||
def handle_upsert_client_testmode_api_request(self, data: Dict) -> Dict:
|
||||
return { "returnCode": "1" }
|
||||
return {"returnCode": "1"}
|
||||
|
@ -1,36 +1,49 @@
|
||||
from core.config import CoreConfig
|
||||
from typing import Dict
|
||||
|
||||
class ChuniServerConfig():
|
||||
|
||||
class ChuniServerConfig:
|
||||
def __init__(self, parent_config: "ChuniConfig") -> None:
|
||||
self.__config = parent_config
|
||||
|
||||
|
||||
@property
|
||||
def enable(self) -> bool:
|
||||
return CoreConfig.get_config_field(self.__config, 'chuni', 'server', 'enable', default=True)
|
||||
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "chuni", "server", "enable", default=True
|
||||
)
|
||||
|
||||
@property
|
||||
def loglevel(self) -> int:
|
||||
return CoreConfig.str_to_loglevel(CoreConfig.get_config_field(self.__config, 'chuni', 'server', 'loglevel', default="info"))
|
||||
return CoreConfig.str_to_loglevel(
|
||||
CoreConfig.get_config_field(
|
||||
self.__config, "chuni", "server", "loglevel", default="info"
|
||||
)
|
||||
)
|
||||
|
||||
class ChuniCryptoConfig():
|
||||
|
||||
class ChuniCryptoConfig:
|
||||
def __init__(self, parent_config: "ChuniConfig") -> None:
|
||||
self.__config = parent_config
|
||||
|
||||
|
||||
@property
|
||||
def keys(self) -> Dict:
|
||||
"""
|
||||
in the form of:
|
||||
internal_version: [key, iv]
|
||||
internal_version: [key, iv]
|
||||
all values are hex strings
|
||||
"""
|
||||
return CoreConfig.get_config_field(self.__config, 'chuni', 'crypto', 'keys', default={})
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "chuni", "crypto", "keys", default={}
|
||||
)
|
||||
|
||||
@property
|
||||
def encrypted_only(self) -> bool:
|
||||
return CoreConfig.get_config_field(self.__config, 'chuni', 'crypto', 'encrypted_only', default=False)
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "chuni", "crypto", "encrypted_only", default=False
|
||||
)
|
||||
|
||||
|
||||
class ChuniConfig(dict):
|
||||
def __init__(self) -> None:
|
||||
self.server = ChuniServerConfig(self)
|
||||
self.crypto = ChuniCryptoConfig(self)
|
||||
self.crypto = ChuniCryptoConfig(self)
|
||||
|
@ -1,4 +1,4 @@
|
||||
class ChuniConstants():
|
||||
class ChuniConstants:
|
||||
GAME_CODE = "SDBT"
|
||||
GAME_CODE_NEW = "SDHD"
|
||||
|
||||
@ -8,7 +8,7 @@ class ChuniConstants():
|
||||
VER_CHUNITHM_PLUS = 1
|
||||
VER_CHUNITHM_AIR = 2
|
||||
VER_CHUNITHM_AIR_PLUS = 3
|
||||
VER_CHUNITHM_STAR = 4
|
||||
VER_CHUNITHM_STAR = 4
|
||||
VER_CHUNITHM_STAR_PLUS = 5
|
||||
VER_CHUNITHM_AMAZON = 6
|
||||
VER_CHUNITHM_AMAZON_PLUS = 7
|
||||
@ -18,8 +18,21 @@ class ChuniConstants():
|
||||
VER_CHUNITHM_NEW = 11
|
||||
VER_CHUNITHM_NEW_PLUS = 12
|
||||
|
||||
VERSION_NAMES = ["Chunithm", "Chunithm+", "Chunithm Air", "Chunithm Air+", "Chunithm Star", "Chunithm Star+", "Chunithm Amazon",
|
||||
"Chunithm Amazon+", "Chunithm Crystal", "Chunithm Crystal+", "Chunithm Paradise", "Chunithm New!!", "Chunithm New!!+"]
|
||||
VERSION_NAMES = [
|
||||
"Chunithm",
|
||||
"Chunithm+",
|
||||
"Chunithm Air",
|
||||
"Chunithm Air+",
|
||||
"Chunithm Star",
|
||||
"Chunithm Star+",
|
||||
"Chunithm Amazon",
|
||||
"Chunithm Amazon+",
|
||||
"Chunithm Crystal",
|
||||
"Chunithm Crystal+",
|
||||
"Chunithm Paradise",
|
||||
"Chunithm New!!",
|
||||
"Chunithm New!!+",
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def game_ver_to_string(cls, ver: int):
|
||||
|
@ -7,12 +7,13 @@ from titles.chuni.base import ChuniBase
|
||||
from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
|
||||
class ChuniCrystal(ChuniBase):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
self.version = ChuniConstants.VER_CHUNITHM_CRYSTAL
|
||||
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["dataVersion"] = "1.40.00"
|
||||
return ret
|
||||
|
@ -7,12 +7,13 @@ from titles.chuni.base import ChuniBase
|
||||
from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
|
||||
class ChuniCrystalPlus(ChuniBase):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
self.version = ChuniConstants.VER_CHUNITHM_CRYSTAL_PLUS
|
||||
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["dataVersion"] = "1.45.00"
|
||||
return ret
|
||||
|
@ -2,6 +2,7 @@ from core.data import Data
|
||||
from core.config import CoreConfig
|
||||
from titles.chuni.schema import *
|
||||
|
||||
|
||||
class ChuniData(Data):
|
||||
def __init__(self, cfg: CoreConfig) -> None:
|
||||
super().__init__(cfg)
|
||||
@ -9,4 +10,4 @@ class ChuniData(Data):
|
||||
self.item = ChuniItemData(cfg, self.session)
|
||||
self.profile = ChuniProfileData(cfg, self.session)
|
||||
self.score = ChuniScoreData(cfg, self.session)
|
||||
self.static = ChuniStaticData(cfg, self.session)
|
||||
self.static = ChuniStaticData(cfg, self.session)
|
||||
|
@ -28,12 +28,15 @@ from titles.chuni.paradise import ChuniParadise
|
||||
from titles.chuni.new import ChuniNew
|
||||
from titles.chuni.newplus import ChuniNewPlus
|
||||
|
||||
class ChuniServlet():
|
||||
|
||||
class ChuniServlet:
|
||||
def __init__(self, core_cfg: CoreConfig, cfg_dir: str) -> None:
|
||||
self.core_cfg = core_cfg
|
||||
self.game_cfg = ChuniConfig()
|
||||
if path.exists(f"{cfg_dir}/{ChuniConstants.CONFIG_NAME}"):
|
||||
self.game_cfg.update(yaml.safe_load(open(f"{cfg_dir}/{ChuniConstants.CONFIG_NAME}")))
|
||||
self.game_cfg.update(
|
||||
yaml.safe_load(open(f"{cfg_dir}/{ChuniConstants.CONFIG_NAME}"))
|
||||
)
|
||||
|
||||
self.versions = [
|
||||
ChuniBase(core_cfg, self.game_cfg),
|
||||
@ -56,33 +59,47 @@ class ChuniServlet():
|
||||
if not hasattr(self.logger, "inited"):
|
||||
log_fmt_str = "[%(asctime)s] Chunithm | %(levelname)s | %(message)s"
|
||||
log_fmt = logging.Formatter(log_fmt_str)
|
||||
fileHandler = TimedRotatingFileHandler("{0}/{1}.log".format(self.core_cfg.server.log_dir, "chuni"), encoding='utf8',
|
||||
when="d", backupCount=10)
|
||||
fileHandler = TimedRotatingFileHandler(
|
||||
"{0}/{1}.log".format(self.core_cfg.server.log_dir, "chuni"),
|
||||
encoding="utf8",
|
||||
when="d",
|
||||
backupCount=10,
|
||||
)
|
||||
|
||||
fileHandler.setFormatter(log_fmt)
|
||||
|
||||
|
||||
consoleHandler = logging.StreamHandler()
|
||||
consoleHandler.setFormatter(log_fmt)
|
||||
|
||||
self.logger.addHandler(fileHandler)
|
||||
self.logger.addHandler(consoleHandler)
|
||||
|
||||
|
||||
self.logger.setLevel(self.game_cfg.server.loglevel)
|
||||
coloredlogs.install(level=self.game_cfg.server.loglevel, logger=self.logger, fmt=log_fmt_str)
|
||||
coloredlogs.install(
|
||||
level=self.game_cfg.server.loglevel, logger=self.logger, fmt=log_fmt_str
|
||||
)
|
||||
self.logger.inited = True
|
||||
|
||||
@classmethod
|
||||
def get_allnet_info(cls, game_code: str, core_cfg: CoreConfig, cfg_dir: str) -> Tuple[bool, str, str]:
|
||||
def get_allnet_info(
|
||||
cls, game_code: str, core_cfg: CoreConfig, cfg_dir: str
|
||||
) -> Tuple[bool, str, str]:
|
||||
game_cfg = ChuniConfig()
|
||||
if path.exists(f"{cfg_dir}/{ChuniConstants.CONFIG_NAME}"):
|
||||
game_cfg.update(yaml.safe_load(open(f"{cfg_dir}/{ChuniConstants.CONFIG_NAME}")))
|
||||
game_cfg.update(
|
||||
yaml.safe_load(open(f"{cfg_dir}/{ChuniConstants.CONFIG_NAME}"))
|
||||
)
|
||||
|
||||
if not game_cfg.server.enable:
|
||||
return (False, "", "")
|
||||
|
||||
|
||||
if core_cfg.server.is_develop:
|
||||
return (True, f"http://{core_cfg.title.hostname}:{core_cfg.title.port}/{game_code}/$v/", "")
|
||||
|
||||
return (
|
||||
True,
|
||||
f"http://{core_cfg.title.hostname}:{core_cfg.title.port}/{game_code}/$v/",
|
||||
"",
|
||||
)
|
||||
|
||||
return (True, f"http://{core_cfg.title.hostname}/{game_code}/$v/", "")
|
||||
|
||||
def render_POST(self, request: Request, version: int, url_path: str) -> bytes:
|
||||
@ -95,67 +112,75 @@ class ChuniServlet():
|
||||
internal_ver = 0
|
||||
endpoint = url_split[len(url_split) - 1]
|
||||
|
||||
if version < 105: # 1.0
|
||||
if version < 105: # 1.0
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM
|
||||
elif version >= 105 and version < 110: # Plus
|
||||
elif version >= 105 and version < 110: # Plus
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_PLUS
|
||||
elif version >= 110 and version < 115: # Air
|
||||
elif version >= 110 and version < 115: # Air
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_AIR
|
||||
elif version >= 115 and version < 120: # Air Plus
|
||||
elif version >= 115 and version < 120: # Air Plus
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_AIR_PLUS
|
||||
elif version >= 120 and version < 125: # Star
|
||||
elif version >= 120 and version < 125: # Star
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_STAR
|
||||
elif version >= 125 and version < 130: # Star Plus
|
||||
elif version >= 125 and version < 130: # Star Plus
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_STAR_PLUS
|
||||
elif version >= 130 and version < 135: # Amazon
|
||||
elif version >= 130 and version < 135: # Amazon
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_AMAZON
|
||||
elif version >= 135 and version < 140: # Amazon Plus
|
||||
elif version >= 135 and version < 140: # Amazon Plus
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_AMAZON_PLUS
|
||||
elif version >= 140 and version < 145: # Crystal
|
||||
elif version >= 140 and version < 145: # Crystal
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_CRYSTAL
|
||||
elif version >= 145 and version < 150: # Crystal Plus
|
||||
elif version >= 145 and version < 150: # Crystal Plus
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_CRYSTAL_PLUS
|
||||
elif version >= 150 and version < 200: # Paradise
|
||||
elif version >= 150 and version < 200: # Paradise
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_PARADISE
|
||||
elif version >= 200 and version < 205: # New
|
||||
elif version >= 200 and version < 205: # New
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_NEW
|
||||
elif version >= 205 and version < 210: # New Plus
|
||||
elif version >= 205 and version < 210: # New Plus
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_NEW_PLUS
|
||||
|
||||
if all(c in string.hexdigits for c in endpoint) and len(endpoint) == 32:
|
||||
# If we get a 32 character long hex string, it's a hash and we're
|
||||
# doing encrypted. The likelyhood of false positives is low but
|
||||
# If we get a 32 character long hex string, it's a hash and we're
|
||||
# doing encrypted. The likelyhood of false positives is low but
|
||||
# technically not 0
|
||||
endpoint = request.getHeader("User-Agent").split("#")[0]
|
||||
try:
|
||||
crypt = AES.new(
|
||||
bytes.fromhex(self.game_cfg.crypto.keys[str(internal_ver)][0]),
|
||||
AES.MODE_CBC,
|
||||
bytes.fromhex(self.game_cfg.crypto.keys[str(internal_ver)][1])
|
||||
bytes.fromhex(self.game_cfg.crypto.keys[str(internal_ver)][0]),
|
||||
AES.MODE_CBC,
|
||||
bytes.fromhex(self.game_cfg.crypto.keys[str(internal_ver)][1]),
|
||||
)
|
||||
|
||||
req_raw = crypt.decrypt(req_raw)
|
||||
|
||||
except:
|
||||
self.logger.error(f"Failed to decrypt v{version} request to {endpoint} -> {req_raw}")
|
||||
self.logger.error(
|
||||
f"Failed to decrypt v{version} request to {endpoint} -> {req_raw}"
|
||||
)
|
||||
return zlib.compress(b'{"stat": "0"}')
|
||||
|
||||
encrtped = True
|
||||
|
||||
|
||||
if not encrtped and self.game_cfg.crypto.encrypted_only:
|
||||
self.logger.error(f"Unencrypted v{version} {endpoint} request, but config is set to encrypted only: {req_raw}")
|
||||
self.logger.error(
|
||||
f"Unencrypted v{version} {endpoint} request, but config is set to encrypted only: {req_raw}"
|
||||
)
|
||||
return zlib.compress(b'{"stat": "0"}')
|
||||
|
||||
try:
|
||||
try:
|
||||
unzip = zlib.decompress(req_raw)
|
||||
|
||||
|
||||
except zlib.error as e:
|
||||
self.logger.error(f"Failed to decompress v{version} {endpoint} request -> {e}")
|
||||
self.logger.error(
|
||||
f"Failed to decompress v{version} {endpoint} request -> {e}"
|
||||
)
|
||||
return b""
|
||||
|
||||
|
||||
req_data = json.loads(unzip)
|
||||
|
||||
self.logger.info(f"v{version} {endpoint} request from {request.getClientAddress().host}")
|
||||
|
||||
self.logger.info(
|
||||
f"v{version} {endpoint} request from {request.getClientAddress().host}"
|
||||
)
|
||||
self.logger.debug(req_data)
|
||||
|
||||
func_to_find = "handle_" + inflection.underscore(endpoint) + "_request"
|
||||
@ -163,9 +188,8 @@ class ChuniServlet():
|
||||
if not hasattr(self.versions[internal_ver], func_to_find):
|
||||
self.logger.warning(f"Unhandled v{version} request {endpoint}")
|
||||
resp = {"returnCode": 1}
|
||||
|
||||
else:
|
||||
|
||||
else:
|
||||
try:
|
||||
handler = getattr(self.versions[internal_ver], func_to_find)
|
||||
resp = handler(req_data)
|
||||
@ -173,23 +197,23 @@ class ChuniServlet():
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error handling v{version} method {endpoint} - {e}")
|
||||
return zlib.compress(b'{"stat": "0"}')
|
||||
|
||||
|
||||
if resp == None:
|
||||
resp = {'returnCode': 1}
|
||||
|
||||
resp = {"returnCode": 1}
|
||||
|
||||
self.logger.debug(f"Response {resp}")
|
||||
|
||||
|
||||
zipped = zlib.compress(json.dumps(resp, ensure_ascii=False).encode("utf-8"))
|
||||
|
||||
|
||||
if not encrtped:
|
||||
return zipped
|
||||
|
||||
padded = pad(zipped, 16)
|
||||
|
||||
crypt = AES.new(
|
||||
bytes.fromhex(self.game_cfg.crypto.keys[str(internal_ver)][0]),
|
||||
AES.MODE_CBC,
|
||||
bytes.fromhex(self.game_cfg.crypto.keys[str(internal_ver)][1])
|
||||
bytes.fromhex(self.game_cfg.crypto.keys[str(internal_ver)][0]),
|
||||
AES.MODE_CBC,
|
||||
bytes.fromhex(self.game_cfg.crypto.keys[str(internal_ver)][1]),
|
||||
)
|
||||
|
||||
return crypt.encrypt(padded)
|
||||
|
@ -9,13 +9,9 @@ from titles.chuni.database import ChuniData
|
||||
from titles.chuni.base import ChuniBase
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
class ChuniNew(ChuniBase):
|
||||
|
||||
ITEM_TYPE = {
|
||||
"character": 20,
|
||||
"story": 21,
|
||||
"card": 22
|
||||
}
|
||||
class ChuniNew(ChuniBase):
|
||||
ITEM_TYPE = {"character": 20, "story": 21, "card": 22}
|
||||
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
self.core_cfg = core_cfg
|
||||
@ -25,12 +21,20 @@ class ChuniNew(ChuniBase):
|
||||
self.logger = logging.getLogger("chuni")
|
||||
self.game = ChuniConstants.GAME_CODE
|
||||
self.version = ChuniConstants.VER_CHUNITHM_NEW
|
||||
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
match_start = datetime.strftime(datetime.now() - timedelta(hours=10), self.date_time_format)
|
||||
match_end = datetime.strftime(datetime.now() + timedelta(hours=10), self.date_time_format)
|
||||
reboot_start = datetime.strftime(datetime.now() - timedelta(hours=11), self.date_time_format)
|
||||
reboot_end = datetime.strftime(datetime.now() - timedelta(hours=10), self.date_time_format)
|
||||
match_start = datetime.strftime(
|
||||
datetime.now() - timedelta(hours=10), self.date_time_format
|
||||
)
|
||||
match_end = datetime.strftime(
|
||||
datetime.now() + timedelta(hours=10), self.date_time_format
|
||||
)
|
||||
reboot_start = datetime.strftime(
|
||||
datetime.now() - timedelta(hours=11), self.date_time_format
|
||||
)
|
||||
reboot_end = datetime.strftime(
|
||||
datetime.now() - timedelta(hours=10), self.date_time_format
|
||||
)
|
||||
return {
|
||||
"gameSetting": {
|
||||
"isMaintenance": "false",
|
||||
@ -52,16 +56,16 @@ class ChuniNew(ChuniBase):
|
||||
"udpHolePunchUri": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/200/ChuniServlet/",
|
||||
"reflectorUri": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/200/ChuniServlet/",
|
||||
},
|
||||
"isDumpUpload": "false",
|
||||
"isAou": "false",
|
||||
"isDumpUpload": "false",
|
||||
"isAou": "false",
|
||||
}
|
||||
|
||||
|
||||
def handle_delete_token_api_request(self, data: Dict) -> Dict:
|
||||
return { "returnCode": "1" }
|
||||
|
||||
return {"returnCode": "1"}
|
||||
|
||||
def handle_create_token_api_request(self, data: Dict) -> Dict:
|
||||
return { "returnCode": "1" }
|
||||
|
||||
return {"returnCode": "1"}
|
||||
|
||||
def handle_get_user_map_area_api_request(self, data: Dict) -> Dict:
|
||||
user_map_areas = self.data.item.get_map_areas(data["userId"])
|
||||
|
||||
@ -72,32 +76,29 @@ class ChuniNew(ChuniBase):
|
||||
tmp.pop("user")
|
||||
map_areas.append(tmp)
|
||||
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"userMapAreaList": map_areas
|
||||
}
|
||||
|
||||
return {"userId": data["userId"], "userMapAreaList": map_areas}
|
||||
|
||||
def handle_get_user_symbol_chat_setting_api_request(self, data: Dict) -> Dict:
|
||||
return {
|
||||
"userId": data["userId"],
|
||||
"symbolCharInfoList": []
|
||||
}
|
||||
return {"userId": data["userId"], "symbolCharInfoList": []}
|
||||
|
||||
def handle_get_user_preview_api_request(self, data: Dict) -> Dict:
|
||||
profile = self.data.profile.get_profile_preview(data["userId"], self.version)
|
||||
if profile is None: return None
|
||||
profile_character = self.data.item.get_character(data["userId"], profile["characterId"])
|
||||
|
||||
if profile is None:
|
||||
return None
|
||||
profile_character = self.data.item.get_character(
|
||||
data["userId"], profile["characterId"]
|
||||
)
|
||||
|
||||
if profile_character is None:
|
||||
chara = {}
|
||||
else:
|
||||
chara = profile_character._asdict()
|
||||
chara.pop("id")
|
||||
chara.pop("user")
|
||||
|
||||
|
||||
data1 = {
|
||||
"userId": data["userId"],
|
||||
# Current Login State
|
||||
"userId": data["userId"],
|
||||
# Current Login State
|
||||
"isLogin": False,
|
||||
"lastLoginDate": profile["lastPlayDate"],
|
||||
# User Profile
|
||||
@ -109,14 +110,14 @@ class ChuniNew(ChuniBase):
|
||||
"lastGameId": profile["lastGameId"],
|
||||
"lastRomVersion": profile["lastRomVersion"],
|
||||
"lastDataVersion": profile["lastDataVersion"],
|
||||
"lastPlayDate": profile["lastPlayDate"],
|
||||
"lastPlayDate": profile["lastPlayDate"],
|
||||
"emoneyBrandId": 0,
|
||||
"trophyId": profile["trophyId"],
|
||||
"trophyId": profile["trophyId"],
|
||||
# Current Selected Character
|
||||
"userCharacter": chara,
|
||||
# User Game Options
|
||||
"playerLevel": profile["playerLevel"],
|
||||
"rating": profile["rating"],
|
||||
"playerLevel": profile["playerLevel"],
|
||||
"rating": profile["rating"],
|
||||
"headphone": profile["headphone"],
|
||||
"chargeState": 0,
|
||||
"userNameEx": "0",
|
||||
|
@ -7,17 +7,26 @@ from titles.chuni.new import ChuniNew
|
||||
from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
|
||||
class ChuniNewPlus(ChuniNew):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
self.version = ChuniConstants.VER_CHUNITHM_NEW_PLUS
|
||||
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["romVersion"] = "2.05.00"
|
||||
ret["gameSetting"]["dataVersion"] = "2.05.00"
|
||||
ret["gameSetting"]["matchingUri"] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||
ret["gameSetting"]["matchingUriX"] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||
ret["gameSetting"]["udpHolePunchUri"] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||
ret["gameSetting"]["reflectorUri"] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||
ret["gameSetting"][
|
||||
"matchingUri"
|
||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||
ret["gameSetting"][
|
||||
"matchingUriX"
|
||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||
ret["gameSetting"][
|
||||
"udpHolePunchUri"
|
||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||
ret["gameSetting"][
|
||||
"reflectorUri"
|
||||
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
|
||||
return ret
|
||||
|
@ -7,12 +7,13 @@ from titles.chuni.base import ChuniBase
|
||||
from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
|
||||
class ChuniParadise(ChuniBase):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
self.version = ChuniConstants.VER_CHUNITHM_PARADISE
|
||||
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["dataVersion"] = "1.50.00"
|
||||
return ret
|
||||
|
@ -5,12 +5,13 @@ from titles.chuni.base import ChuniBase
|
||||
from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
|
||||
class ChuniPlus(ChuniBase):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
self.version = ChuniConstants.VER_CHUNITHM_PLUS
|
||||
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["dataVersion"] = "1.05.00"
|
||||
return ret
|
||||
return ret
|
||||
|
@ -7,48 +7,60 @@ from core.config import CoreConfig
|
||||
from titles.chuni.database import ChuniData
|
||||
from titles.chuni.const import ChuniConstants
|
||||
|
||||
|
||||
class ChuniReader(BaseReader):
|
||||
def __init__(self, config: CoreConfig, version: int, bin_dir: Optional[str], opt_dir: Optional[str], extra: Optional[str]) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
config: CoreConfig,
|
||||
version: int,
|
||||
bin_dir: Optional[str],
|
||||
opt_dir: Optional[str],
|
||||
extra: Optional[str],
|
||||
) -> None:
|
||||
super().__init__(config, version, bin_dir, opt_dir, extra)
|
||||
self.data = ChuniData(config)
|
||||
|
||||
try:
|
||||
self.logger.info(f"Start importer for {ChuniConstants.game_ver_to_string(version)}")
|
||||
self.logger.info(
|
||||
f"Start importer for {ChuniConstants.game_ver_to_string(version)}"
|
||||
)
|
||||
except IndexError:
|
||||
self.logger.error(f"Invalid chunithm version {version}")
|
||||
exit(1)
|
||||
|
||||
|
||||
def read(self) -> None:
|
||||
data_dirs = []
|
||||
if self.bin_dir is not None:
|
||||
data_dirs += self.get_data_directories(self.bin_dir)
|
||||
|
||||
|
||||
if self.opt_dir is not None:
|
||||
data_dirs += self.get_data_directories(self.opt_dir)
|
||||
|
||||
data_dirs += self.get_data_directories(self.opt_dir)
|
||||
|
||||
for dir in data_dirs:
|
||||
self.logger.info(f"Read from {dir}")
|
||||
self.read_events(f"{dir}/event")
|
||||
self.read_music(f"{dir}/music")
|
||||
self.read_charges(f"{dir}/chargeItem")
|
||||
self.read_avatar(f"{dir}/avatarAccessory")
|
||||
|
||||
|
||||
def read_events(self, evt_dir: str) -> None:
|
||||
for root, dirs, files in walk(evt_dir):
|
||||
for dir in dirs:
|
||||
if path.exists(f"{root}/{dir}/Event.xml"):
|
||||
with open(f"{root}/{dir}/Event.xml", 'rb') as fp:
|
||||
with open(f"{root}/{dir}/Event.xml", "rb") as fp:
|
||||
bytedata = fp.read()
|
||||
strdata = bytedata.decode('UTF-8')
|
||||
strdata = bytedata.decode("UTF-8")
|
||||
|
||||
xml_root = ET.fromstring(strdata)
|
||||
for name in xml_root.findall('name'):
|
||||
id = name.find('id').text
|
||||
name = name.find('str').text
|
||||
for substances in xml_root.findall('substances'):
|
||||
event_type = substances.find('type').text
|
||||
|
||||
result = self.data.static.put_event(self.version, id, event_type, name)
|
||||
for name in xml_root.findall("name"):
|
||||
id = name.find("id").text
|
||||
name = name.find("str").text
|
||||
for substances in xml_root.findall("substances"):
|
||||
event_type = substances.find("type").text
|
||||
|
||||
result = self.data.static.put_event(
|
||||
self.version, id, event_type, name
|
||||
)
|
||||
if result is not None:
|
||||
self.logger.info(f"Inserted event {id}")
|
||||
else:
|
||||
@ -58,73 +70,90 @@ class ChuniReader(BaseReader):
|
||||
for root, dirs, files in walk(music_dir):
|
||||
for dir in dirs:
|
||||
if path.exists(f"{root}/{dir}/Music.xml"):
|
||||
with open(f"{root}/{dir}/Music.xml", 'rb') as fp:
|
||||
with open(f"{root}/{dir}/Music.xml", "rb") as fp:
|
||||
bytedata = fp.read()
|
||||
strdata = bytedata.decode('UTF-8')
|
||||
strdata = bytedata.decode("UTF-8")
|
||||
|
||||
xml_root = ET.fromstring(strdata)
|
||||
for name in xml_root.findall('name'):
|
||||
song_id = name.find('id').text
|
||||
title = name.find('str').text
|
||||
for name in xml_root.findall("name"):
|
||||
song_id = name.find("id").text
|
||||
title = name.find("str").text
|
||||
|
||||
for artistName in xml_root.findall('artistName'):
|
||||
artist = artistName.find('str').text
|
||||
for artistName in xml_root.findall("artistName"):
|
||||
artist = artistName.find("str").text
|
||||
|
||||
for genreNames in xml_root.findall('genreNames'):
|
||||
for list_ in genreNames.findall('list'):
|
||||
for StringID in list_.findall('StringID'):
|
||||
genre = StringID.find('str').text
|
||||
for genreNames in xml_root.findall("genreNames"):
|
||||
for list_ in genreNames.findall("list"):
|
||||
for StringID in list_.findall("StringID"):
|
||||
genre = StringID.find("str").text
|
||||
|
||||
for jaketFile in xml_root.findall('jaketFile'): #nice typo, SEGA
|
||||
jacket_path = jaketFile.find('path').text
|
||||
for jaketFile in xml_root.findall("jaketFile"): # nice typo, SEGA
|
||||
jacket_path = jaketFile.find("path").text
|
||||
|
||||
for fumens in xml_root.findall("fumens"):
|
||||
for MusicFumenData in fumens.findall("MusicFumenData"):
|
||||
fumen_path = MusicFumenData.find("file").find("path")
|
||||
|
||||
for fumens in xml_root.findall('fumens'):
|
||||
for MusicFumenData in fumens.findall('MusicFumenData'):
|
||||
fumen_path = MusicFumenData.find('file').find("path")
|
||||
|
||||
if fumen_path is not None:
|
||||
chart_id = MusicFumenData.find('type').find('id').text
|
||||
chart_id = MusicFumenData.find("type").find("id").text
|
||||
if chart_id == "4":
|
||||
level = float(xml_root.find("starDifType").text)
|
||||
we_chara = xml_root.find("worldsEndTagName").find("str").text
|
||||
we_chara = (
|
||||
xml_root.find("worldsEndTagName")
|
||||
.find("str")
|
||||
.text
|
||||
)
|
||||
else:
|
||||
level = float(f"{MusicFumenData.find('level').text}.{MusicFumenData.find('levelDecimal').text}")
|
||||
level = float(
|
||||
f"{MusicFumenData.find('level').text}.{MusicFumenData.find('levelDecimal').text}"
|
||||
)
|
||||
we_chara = None
|
||||
|
||||
|
||||
result = self.data.static.put_music(
|
||||
self.version,
|
||||
song_id,
|
||||
chart_id,
|
||||
chart_id,
|
||||
title,
|
||||
artist,
|
||||
level,
|
||||
genre,
|
||||
jacket_path,
|
||||
we_chara
|
||||
we_chara,
|
||||
)
|
||||
|
||||
if result is not None:
|
||||
self.logger.info(f"Inserted music {song_id} chart {chart_id}")
|
||||
self.logger.info(
|
||||
f"Inserted music {song_id} chart {chart_id}"
|
||||
)
|
||||
else:
|
||||
self.logger.warn(f"Failed to insert music {song_id} chart {chart_id}")
|
||||
self.logger.warn(
|
||||
f"Failed to insert music {song_id} chart {chart_id}"
|
||||
)
|
||||
|
||||
def read_charges(self, charge_dir: str) -> None:
|
||||
for root, dirs, files in walk(charge_dir):
|
||||
for dir in dirs:
|
||||
if path.exists(f"{root}/{dir}/ChargeItem.xml"):
|
||||
with open(f"{root}/{dir}/ChargeItem.xml", 'rb') as fp:
|
||||
with open(f"{root}/{dir}/ChargeItem.xml", "rb") as fp:
|
||||
bytedata = fp.read()
|
||||
strdata = bytedata.decode('UTF-8')
|
||||
strdata = bytedata.decode("UTF-8")
|
||||
|
||||
xml_root = ET.fromstring(strdata)
|
||||
for name in xml_root.findall('name'):
|
||||
id = name.find('id').text
|
||||
name = name.find('str').text
|
||||
expirationDays = xml_root.find('expirationDays').text
|
||||
consumeType = xml_root.find('consumeType').text
|
||||
sellingAppeal = bool(xml_root.find('sellingAppeal').text)
|
||||
for name in xml_root.findall("name"):
|
||||
id = name.find("id").text
|
||||
name = name.find("str").text
|
||||
expirationDays = xml_root.find("expirationDays").text
|
||||
consumeType = xml_root.find("consumeType").text
|
||||
sellingAppeal = bool(xml_root.find("sellingAppeal").text)
|
||||
|
||||
result = self.data.static.put_charge(self.version, id, name, expirationDays, consumeType, sellingAppeal)
|
||||
result = self.data.static.put_charge(
|
||||
self.version,
|
||||
id,
|
||||
name,
|
||||
expirationDays,
|
||||
consumeType,
|
||||
sellingAppeal,
|
||||
)
|
||||
|
||||
if result is not None:
|
||||
self.logger.info(f"Inserted charge {id}")
|
||||
@ -135,21 +164,23 @@ class ChuniReader(BaseReader):
|
||||
for root, dirs, files in walk(avatar_dir):
|
||||
for dir in dirs:
|
||||
if path.exists(f"{root}/{dir}/AvatarAccessory.xml"):
|
||||
with open(f"{root}/{dir}/AvatarAccessory.xml", 'rb') as fp:
|
||||
with open(f"{root}/{dir}/AvatarAccessory.xml", "rb") as fp:
|
||||
bytedata = fp.read()
|
||||
strdata = bytedata.decode('UTF-8')
|
||||
strdata = bytedata.decode("UTF-8")
|
||||
|
||||
xml_root = ET.fromstring(strdata)
|
||||
for name in xml_root.findall('name'):
|
||||
id = name.find('id').text
|
||||
name = name.find('str').text
|
||||
category = xml_root.find('category').text
|
||||
for image in xml_root.findall('image'):
|
||||
iconPath = image.find('path').text
|
||||
for texture in xml_root.findall('texture'):
|
||||
texturePath = texture.find('path').text
|
||||
for name in xml_root.findall("name"):
|
||||
id = name.find("id").text
|
||||
name = name.find("str").text
|
||||
category = xml_root.find("category").text
|
||||
for image in xml_root.findall("image"):
|
||||
iconPath = image.find("path").text
|
||||
for texture in xml_root.findall("texture"):
|
||||
texturePath = texture.find("path").text
|
||||
|
||||
result = self.data.static.put_avatar(self.version, id, name, category, iconPath, texturePath)
|
||||
result = self.data.static.put_avatar(
|
||||
self.version, id, name, category, iconPath, texturePath
|
||||
)
|
||||
|
||||
if result is not None:
|
||||
self.logger.info(f"Inserted avatarAccessory {id}")
|
||||
|
@ -3,4 +3,4 @@ from titles.chuni.schema.score import ChuniScoreData
|
||||
from titles.chuni.schema.item import ChuniItemData
|
||||
from titles.chuni.schema.static import ChuniStaticData
|
||||
|
||||
__all__ = ["ChuniProfileData", "ChuniScoreData", "ChuniItemData", "ChuniStaticData"]
|
||||
__all__ = ["ChuniProfileData", "ChuniScoreData", "ChuniItemData", "ChuniStaticData"]
|
||||
|
@ -13,7 +13,11 @@ character = Table(
|
||||
"chuni_item_character",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("characterId", Integer),
|
||||
Column("level", Integer),
|
||||
Column("param1", Integer),
|
||||
@ -26,27 +30,35 @@ character = Table(
|
||||
Column("assignIllust", Integer),
|
||||
Column("exMaxLv", Integer),
|
||||
UniqueConstraint("user", "characterId", name="chuni_item_character_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
item = Table(
|
||||
"chuni_item_item",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("itemId", Integer),
|
||||
Column("itemKind", Integer),
|
||||
Column("stock", Integer),
|
||||
Column("isValid", Boolean),
|
||||
UniqueConstraint("user", "itemId", "itemKind", name="chuni_item_item_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
duel = Table(
|
||||
"chuni_item_duel",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("duelId", Integer),
|
||||
Column("progress", Integer),
|
||||
Column("point", Integer),
|
||||
@ -57,14 +69,18 @@ duel = Table(
|
||||
Column("param3", Integer),
|
||||
Column("param4", Integer),
|
||||
UniqueConstraint("user", "duelId", name="chuni_item_duel_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
map = Table(
|
||||
"chuni_item_map",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("mapId", Integer),
|
||||
Column("position", Integer),
|
||||
Column("isClear", Boolean),
|
||||
@ -72,17 +88,21 @@ map = Table(
|
||||
Column("routeNumber", Integer),
|
||||
Column("eventId", Integer),
|
||||
Column("rate", Integer),
|
||||
Column("statusCount", Integer),
|
||||
Column("statusCount", Integer),
|
||||
Column("isValid", Boolean),
|
||||
UniqueConstraint("user", "mapId", name="chuni_item_map_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
map_area = Table(
|
||||
"chuni_item_map_area",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("mapAreaId", Integer),
|
||||
Column("rate", Integer),
|
||||
Column("isClear", Boolean),
|
||||
@ -91,9 +111,10 @@ map_area = Table(
|
||||
Column("statusCount", Integer),
|
||||
Column("remainGridCount", Integer),
|
||||
UniqueConstraint("user", "mapAreaId", name="chuni_item_map_area_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
|
||||
class ChuniItemData(BaseData):
|
||||
def put_character(self, user_id: int, character_data: Dict) -> Optional[int]:
|
||||
character_data["user"] = user_id
|
||||
@ -104,24 +125,26 @@ class ChuniItemData(BaseData):
|
||||
conflict = sql.on_duplicate_key_update(**character_data)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
def get_character(self, user_id: int, character_id: int) -> Optional[Dict]:
|
||||
sql = select(character).where(and_(
|
||||
character.c.user == user_id,
|
||||
character.c.characterId == character_id
|
||||
))
|
||||
|
||||
sql = select(character).where(
|
||||
and_(character.c.user == user_id, character.c.characterId == character_id)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
|
||||
def get_characters(self, user_id: int) -> Optional[List[Row]]:
|
||||
sql = select(character).where(character.c.user == user_id)
|
||||
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
def put_item(self, user_id: int, item_data: Dict) -> Optional[int]:
|
||||
@ -133,22 +156,23 @@ class ChuniItemData(BaseData):
|
||||
conflict = sql.on_duplicate_key_update(**item_data)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
def get_items(self, user_id: int, kind: int = None) -> Optional[List[Row]]:
|
||||
if kind is None:
|
||||
sql = select(item).where(item.c.user == user_id)
|
||||
else:
|
||||
sql = select(item).where(and_(
|
||||
item.c.user == user_id,
|
||||
item.c.itemKind == kind
|
||||
))
|
||||
|
||||
sql = select(item).where(
|
||||
and_(item.c.user == user_id, item.c.itemKind == kind)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
|
||||
def put_duel(self, user_id: int, duel_data: Dict) -> Optional[int]:
|
||||
duel_data["user"] = user_id
|
||||
|
||||
@ -158,14 +182,16 @@ class ChuniItemData(BaseData):
|
||||
conflict = sql.on_duplicate_key_update(**duel_data)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
def get_duels(self, user_id: int) -> Optional[List[Row]]:
|
||||
sql = select(duel).where(duel.c.user == user_id)
|
||||
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
def put_map(self, user_id: int, map_data: Dict) -> Optional[int]:
|
||||
@ -177,16 +203,18 @@ class ChuniItemData(BaseData):
|
||||
conflict = sql.on_duplicate_key_update(**map_data)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
def get_maps(self, user_id: int) -> Optional[List[Row]]:
|
||||
sql = select(map).where(map.c.user == user_id)
|
||||
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
|
||||
def put_map_area(self, user_id: int, map_area_data: Dict) -> Optional[int]:
|
||||
map_area_data["user"] = user_id
|
||||
|
||||
@ -196,12 +224,14 @@ class ChuniItemData(BaseData):
|
||||
conflict = sql.on_duplicate_key_update(**map_area_data)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
|
||||
def get_map_areas(self, user_id: int) -> Optional[List[Row]]:
|
||||
sql = select(map_area).where(map_area.c.user == user_id)
|
||||
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
return result.fetchall()
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
@ -13,7 +13,11 @@ profile = Table(
|
||||
"chuni_profile_data",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("version", Integer, nullable=False),
|
||||
Column("exp", Integer),
|
||||
Column("level", Integer),
|
||||
@ -62,7 +66,7 @@ profile = Table(
|
||||
Column("firstTutorialCancelNum", Integer),
|
||||
Column("totalAdvancedHighScore", Integer),
|
||||
Column("masterTutorialCancelNum", Integer),
|
||||
Column("ext1", Integer), # Added in chunew
|
||||
Column("ext1", Integer), # Added in chunew
|
||||
Column("ext2", Integer),
|
||||
Column("ext3", Integer),
|
||||
Column("ext4", Integer),
|
||||
@ -71,16 +75,20 @@ profile = Table(
|
||||
Column("ext7", Integer),
|
||||
Column("ext8", Integer),
|
||||
Column("ext9", Integer),
|
||||
Column("ext10", Integer),
|
||||
Column("ext10", Integer),
|
||||
Column("extStr1", String(255)),
|
||||
Column("extStr2", String(255)),
|
||||
Column("extLong1", Integer),
|
||||
Column("extLong2", Integer),
|
||||
Column("mapIconId", Integer),
|
||||
Column("compatibleCmVersion", String(25)),
|
||||
Column("medal", Integer),
|
||||
Column("medal", Integer),
|
||||
Column("voiceId", Integer),
|
||||
Column("teamId", Integer, ForeignKey("chuni_profile_team.id", ondelete="SET NULL", onupdate="SET NULL")),
|
||||
Column(
|
||||
"teamId",
|
||||
Integer,
|
||||
ForeignKey("chuni_profile_team.id", ondelete="SET NULL", onupdate="SET NULL"),
|
||||
),
|
||||
Column("avatarBack", Integer, server_default="0"),
|
||||
Column("avatarFace", Integer, server_default="0"),
|
||||
Column("eliteRankPoint", Integer, server_default="0"),
|
||||
@ -121,14 +129,18 @@ profile = Table(
|
||||
Column("netBattleEndState", Integer, server_default="0"),
|
||||
Column("avatarHead", Integer, server_default="0"),
|
||||
UniqueConstraint("user", "version", name="chuni_profile_profile_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
profile_ex = Table(
|
||||
"chuni_profile_data_ex",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("version", Integer, nullable=False),
|
||||
Column("ext1", Integer),
|
||||
Column("ext2", Integer),
|
||||
@ -165,14 +177,18 @@ profile_ex = Table(
|
||||
Column("mapIconId", Integer),
|
||||
Column("compatibleCmVersion", String(25)),
|
||||
UniqueConstraint("user", "version", name="chuni_profile_data_ex_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
option = Table(
|
||||
"chuni_profile_option",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("speed", Integer),
|
||||
Column("bgInfo", Integer),
|
||||
Column("rating", Integer),
|
||||
@ -195,7 +211,7 @@ option = Table(
|
||||
Column("successSkill", Integer),
|
||||
Column("successSlideHold", Integer),
|
||||
Column("successTapTimbre", Integer),
|
||||
Column("ext1", Integer), # Added in chunew
|
||||
Column("ext1", Integer), # Added in chunew
|
||||
Column("ext2", Integer),
|
||||
Column("ext3", Integer),
|
||||
Column("ext4", Integer),
|
||||
@ -224,14 +240,18 @@ option = Table(
|
||||
Column("playTimingOffset", Integer, server_default="0"),
|
||||
Column("fieldWallPosition_120", Integer, server_default="0"),
|
||||
UniqueConstraint("user", name="chuni_profile_option_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
option_ex = Table(
|
||||
"chuni_profile_option_ex",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("ext1", Integer),
|
||||
Column("ext2", Integer),
|
||||
Column("ext3", Integer),
|
||||
@ -253,51 +273,69 @@ option_ex = Table(
|
||||
Column("ext19", Integer),
|
||||
Column("ext20", Integer),
|
||||
UniqueConstraint("user", name="chuni_profile_option_ex_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
recent_rating = Table(
|
||||
"chuni_profile_recent_rating",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("recentRating", JSON),
|
||||
UniqueConstraint("user", name="chuni_profile_recent_rating_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
region = Table(
|
||||
"chuni_profile_region",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("regionId", Integer),
|
||||
Column("playCount", Integer),
|
||||
UniqueConstraint("user", "regionId", name="chuni_profile_region_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
activity = Table(
|
||||
"chuni_profile_activity",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("kind", Integer),
|
||||
Column("activityId", Integer), # Reminder: Change this to ID in base.py or the game will be sad
|
||||
Column(
|
||||
"activityId", Integer
|
||||
), # Reminder: Change this to ID in base.py or the game will be sad
|
||||
Column("sortNumber", Integer),
|
||||
Column("param1", Integer),
|
||||
Column("param2", Integer),
|
||||
Column("param3", Integer),
|
||||
Column("param4", Integer),
|
||||
UniqueConstraint("user", "kind", "activityId", name="chuni_profile_activity_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
charge = Table(
|
||||
"chuni_profile_charge",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("chargeId", Integer),
|
||||
Column("stock", Integer),
|
||||
Column("purchaseDate", String(25)),
|
||||
@ -306,14 +344,18 @@ charge = Table(
|
||||
Column("param2", Integer),
|
||||
Column("paramDate", String(25)),
|
||||
UniqueConstraint("user", "chargeId", name="chuni_profile_charge_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
emoney = Table(
|
||||
"chuni_profile_emoney",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("ext1", Integer),
|
||||
Column("ext2", Integer),
|
||||
Column("ext3", Integer),
|
||||
@ -321,20 +363,24 @@ emoney = Table(
|
||||
Column("emoneyBrand", Integer),
|
||||
Column("emoneyCredit", Integer),
|
||||
UniqueConstraint("user", "emoneyBrand", name="chuni_profile_emoney_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
overpower = Table(
|
||||
"chuni_profile_overpower",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("genreId", Integer),
|
||||
Column("difficulty", Integer),
|
||||
Column("rate", Integer),
|
||||
Column("point", Integer),
|
||||
UniqueConstraint("user", "genreId", "difficulty", name="chuni_profile_emoney_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
team = Table(
|
||||
@ -343,18 +389,21 @@ team = Table(
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("teamName", String(255)),
|
||||
Column("teamPoint", Integer),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
|
||||
class ChuniProfileData(BaseData):
|
||||
def put_profile_data(self, aime_id: int, version: int, profile_data: Dict) -> Optional[int]:
|
||||
def put_profile_data(
|
||||
self, aime_id: int, version: int, profile_data: Dict
|
||||
) -> Optional[int]:
|
||||
profile_data["user"] = aime_id
|
||||
profile_data["version"] = version
|
||||
if "accessCode" in profile_data:
|
||||
profile_data.pop("accessCode")
|
||||
|
||||
|
||||
profile_data = self.fix_bools(profile_data)
|
||||
|
||||
|
||||
sql = insert(profile).values(**profile_data)
|
||||
conflict = sql.on_duplicate_key_update(**profile_data)
|
||||
result = self.execute(conflict)
|
||||
@ -363,51 +412,64 @@ class ChuniProfileData(BaseData):
|
||||
self.logger.warn(f"put_profile_data: Failed to update! aime_id: {aime_id}")
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
|
||||
def get_profile_preview(self, aime_id: int, version: int) -> Optional[Row]:
|
||||
sql = select([profile, option]).join(option, profile.c.user == option.c.user).filter(
|
||||
and_(profile.c.user == aime_id, profile.c.version == version)
|
||||
sql = (
|
||||
select([profile, option])
|
||||
.join(option, profile.c.user == option.c.user)
|
||||
.filter(and_(profile.c.user == aime_id, profile.c.version == version))
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
def get_profile_data(self, aime_id: int, version: int) -> Optional[Row]:
|
||||
sql = select(profile).where(and_(
|
||||
profile.c.user == aime_id,
|
||||
profile.c.version == version,
|
||||
))
|
||||
sql = select(profile).where(
|
||||
and_(
|
||||
profile.c.user == aime_id,
|
||||
profile.c.version == version,
|
||||
)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
def put_profile_data_ex(self, aime_id: int, version: int, profile_ex_data: Dict) -> Optional[int]:
|
||||
|
||||
def put_profile_data_ex(
|
||||
self, aime_id: int, version: int, profile_ex_data: Dict
|
||||
) -> Optional[int]:
|
||||
profile_ex_data["user"] = aime_id
|
||||
profile_ex_data["version"] = version
|
||||
if "accessCode" in profile_ex_data:
|
||||
profile_ex_data.pop("accessCode")
|
||||
|
||||
|
||||
sql = insert(profile_ex).values(**profile_ex_data)
|
||||
conflict = sql.on_duplicate_key_update(**profile_ex_data)
|
||||
result = self.execute(conflict)
|
||||
|
||||
if result is None:
|
||||
self.logger.warn(f"put_profile_data_ex: Failed to update! aime_id: {aime_id}")
|
||||
self.logger.warn(
|
||||
f"put_profile_data_ex: Failed to update! aime_id: {aime_id}"
|
||||
)
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
|
||||
def get_profile_data_ex(self, aime_id: int, version: int) -> Optional[Row]:
|
||||
sql = select(profile_ex).where(and_(
|
||||
profile_ex.c.user == aime_id,
|
||||
profile_ex.c.version == version,
|
||||
))
|
||||
sql = select(profile_ex).where(
|
||||
and_(
|
||||
profile_ex.c.user == aime_id,
|
||||
profile_ex.c.version == version,
|
||||
)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
|
||||
def put_profile_option(self, aime_id: int, option_data: Dict) -> Optional[int]:
|
||||
option_data["user"] = aime_id
|
||||
|
||||
@ -416,7 +478,9 @@ class ChuniProfileData(BaseData):
|
||||
result = self.execute(conflict)
|
||||
|
||||
if result is None:
|
||||
self.logger.warn(f"put_profile_option: Failed to update! aime_id: {aime_id}")
|
||||
self.logger.warn(
|
||||
f"put_profile_option: Failed to update! aime_id: {aime_id}"
|
||||
)
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
@ -424,18 +488,23 @@ class ChuniProfileData(BaseData):
|
||||
sql = select(option).where(option.c.user == aime_id)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
def put_profile_option_ex(self, aime_id: int, option_ex_data: Dict) -> Optional[int]:
|
||||
|
||||
def put_profile_option_ex(
|
||||
self, aime_id: int, option_ex_data: Dict
|
||||
) -> Optional[int]:
|
||||
option_ex_data["user"] = aime_id
|
||||
|
||||
|
||||
sql = insert(option_ex).values(**option_ex_data)
|
||||
conflict = sql.on_duplicate_key_update(**option_ex_data)
|
||||
result = self.execute(conflict)
|
||||
|
||||
if result is None:
|
||||
self.logger.warn(f"put_profile_option_ex: Failed to update! aime_id: {aime_id}")
|
||||
self.logger.warn(
|
||||
f"put_profile_option_ex: Failed to update! aime_id: {aime_id}"
|
||||
)
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
@ -443,27 +512,32 @@ class ChuniProfileData(BaseData):
|
||||
sql = select(option_ex).where(option_ex.c.user == aime_id)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
def put_profile_recent_rating(self, aime_id: int, recent_rating_data: List[Dict]) -> Optional[int]:
|
||||
def put_profile_recent_rating(
|
||||
self, aime_id: int, recent_rating_data: List[Dict]
|
||||
) -> Optional[int]:
|
||||
sql = insert(recent_rating).values(
|
||||
user = aime_id,
|
||||
recentRating = recent_rating_data
|
||||
user=aime_id, recentRating=recent_rating_data
|
||||
)
|
||||
conflict = sql.on_duplicate_key_update(recentRating = recent_rating_data)
|
||||
conflict = sql.on_duplicate_key_update(recentRating=recent_rating_data)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None:
|
||||
self.logger.warn(f"put_profile_recent_rating: Failed to update! aime_id: {aime_id}")
|
||||
self.logger.warn(
|
||||
f"put_profile_recent_rating: Failed to update! aime_id: {aime_id}"
|
||||
)
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
|
||||
def get_profile_recent_rating(self, aime_id: int) -> Optional[Row]:
|
||||
sql = select(recent_rating).where(recent_rating.c.user == aime_id)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
def put_profile_activity(self, aime_id: int, activity_data: Dict) -> Optional[int]:
|
||||
@ -471,35 +545,39 @@ class ChuniProfileData(BaseData):
|
||||
activity_data["user"] = aime_id
|
||||
activity_data["activityId"] = activity_data["id"]
|
||||
activity_data.pop("id")
|
||||
|
||||
|
||||
sql = insert(activity).values(**activity_data)
|
||||
conflict = sql.on_duplicate_key_update(**activity_data)
|
||||
result = self.execute(conflict)
|
||||
|
||||
if result is None:
|
||||
self.logger.warn(f"put_profile_activity: Failed to update! aime_id: {aime_id}")
|
||||
self.logger.warn(
|
||||
f"put_profile_activity: Failed to update! aime_id: {aime_id}"
|
||||
)
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
def get_profile_activity(self, aime_id: int, kind: int) -> Optional[List[Row]]:
|
||||
sql = select(activity).where(and_(
|
||||
activity.c.user == aime_id,
|
||||
activity.c.kind == kind
|
||||
))
|
||||
sql = select(activity).where(
|
||||
and_(activity.c.user == aime_id, activity.c.kind == kind)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
def put_profile_charge(self, aime_id: int, charge_data: Dict) -> Optional[int]:
|
||||
charge_data["user"] = aime_id
|
||||
|
||||
|
||||
sql = insert(charge).values(**charge_data)
|
||||
conflict = sql.on_duplicate_key_update(**charge_data)
|
||||
result = self.execute(conflict)
|
||||
|
||||
if result is None:
|
||||
self.logger.warn(f"put_profile_charge: Failed to update! aime_id: {aime_id}")
|
||||
self.logger.warn(
|
||||
f"put_profile_charge: Failed to update! aime_id: {aime_id}"
|
||||
)
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
@ -507,9 +585,10 @@ class ChuniProfileData(BaseData):
|
||||
sql = select(charge).where(charge.c.user == aime_id)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
|
||||
def add_profile_region(self, aime_id: int, region_id: int) -> Optional[int]:
|
||||
pass
|
||||
|
||||
@ -523,29 +602,35 @@ class ChuniProfileData(BaseData):
|
||||
conflict = sql.on_duplicate_key_update(**emoney_data)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
|
||||
def get_profile_emoney(self, aime_id: int) -> Optional[List[Row]]:
|
||||
sql = select(emoney).where(emoney.c.user == aime_id)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
def put_profile_overpower(self, aime_id: int, overpower_data: Dict) -> Optional[int]:
|
||||
def put_profile_overpower(
|
||||
self, aime_id: int, overpower_data: Dict
|
||||
) -> Optional[int]:
|
||||
overpower_data["user"] = aime_id
|
||||
|
||||
sql = insert(overpower).values(**overpower_data)
|
||||
conflict = sql.on_duplicate_key_update(**overpower_data)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
|
||||
def get_profile_overpower(self, aime_id: int) -> Optional[List[Row]]:
|
||||
sql = select(overpower).where(overpower.c.user == aime_id)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
@ -13,7 +13,11 @@ course = Table(
|
||||
"chuni_score_course",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("courseId", Integer),
|
||||
Column("classId", Integer),
|
||||
Column("playCount", Integer),
|
||||
@ -33,14 +37,18 @@ course = Table(
|
||||
Column("orderId", Integer),
|
||||
Column("playerRating", Integer),
|
||||
UniqueConstraint("user", "courseId", name="chuni_score_course_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
best_score = Table(
|
||||
"chuni_score_best",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("musicId", Integer),
|
||||
Column("level", Integer),
|
||||
Column("playCount", Integer),
|
||||
@ -60,14 +68,18 @@ best_score = Table(
|
||||
Column("ext1", Integer),
|
||||
Column("theoryCount", Integer),
|
||||
UniqueConstraint("user", "musicId", "level", name="chuni_score_best_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
playlog = Table(
|
||||
"chuni_score_playlog",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("orderId", Integer),
|
||||
Column("sortNumber", Integer),
|
||||
Column("placeId", Integer),
|
||||
@ -122,15 +134,17 @@ playlog = Table(
|
||||
Column("charaIllustId", Integer),
|
||||
Column("romVersion", String(255)),
|
||||
Column("judgeHeaven", Integer),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
|
||||
class ChuniScoreData(BaseData):
|
||||
def get_courses(self, aime_id: int) -> Optional[Row]:
|
||||
sql = select(course).where(course.c.user == aime_id)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
def put_course(self, aime_id: int, course_data: Dict) -> Optional[int]:
|
||||
@ -141,16 +155,18 @@ class ChuniScoreData(BaseData):
|
||||
conflict = sql.on_duplicate_key_update(**course_data)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
|
||||
def get_scores(self, aime_id: int) -> Optional[Row]:
|
||||
sql = select(best_score).where(best_score.c.user == aime_id)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
|
||||
def put_score(self, aime_id: int, score_data: Dict) -> Optional[int]:
|
||||
score_data["user"] = aime_id
|
||||
score_data = self.fix_bools(score_data)
|
||||
@ -159,16 +175,18 @@ class ChuniScoreData(BaseData):
|
||||
conflict = sql.on_duplicate_key_update(**score_data)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
def get_playlogs(self, aime_id: int) -> Optional[Row]:
|
||||
sql = select(playlog).where(playlog.c.user == aime_id)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
|
||||
def put_playlog(self, aime_id: int, playlog_data: Dict) -> Optional[int]:
|
||||
playlog_data["user"] = aime_id
|
||||
playlog_data = self.fix_bools(playlog_data)
|
||||
@ -177,5 +195,6 @@ class ChuniScoreData(BaseData):
|
||||
conflict = sql.on_duplicate_key_update(**playlog_data)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
@ -19,7 +19,7 @@ events = Table(
|
||||
Column("name", String(255)),
|
||||
Column("enabled", Boolean, server_default="1"),
|
||||
UniqueConstraint("version", "eventId", name="chuni_static_events_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
music = Table(
|
||||
@ -30,13 +30,13 @@ music = Table(
|
||||
Column("songId", Integer),
|
||||
Column("chartId", Integer),
|
||||
Column("title", String(255)),
|
||||
Column("artist", String(255)),
|
||||
Column("artist", String(255)),
|
||||
Column("level", Float),
|
||||
Column("genre", String(255)),
|
||||
Column("jacketPath", String(255)),
|
||||
Column("worldsEndTag", String(7)),
|
||||
UniqueConstraint("version", "songId", "chartId", name="chuni_static_music_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
charge = Table(
|
||||
@ -51,7 +51,7 @@ charge = Table(
|
||||
Column("sellingAppeal", Boolean),
|
||||
Column("enabled", Boolean, server_default="1"),
|
||||
UniqueConstraint("version", "chargeId", name="chuni_static_charge_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
avatar = Table(
|
||||
@ -65,159 +65,203 @@ avatar = Table(
|
||||
Column("iconPath", String(255)),
|
||||
Column("texturePath", String(255)),
|
||||
UniqueConstraint("version", "avatarAccessoryId", name="chuni_static_avatar_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
|
||||
class ChuniStaticData(BaseData):
|
||||
def put_event(self, version: int, event_id: int, type: int, name: str) -> Optional[int]:
|
||||
def put_event(
|
||||
self, version: int, event_id: int, type: int, name: str
|
||||
) -> Optional[int]:
|
||||
sql = insert(events).values(
|
||||
version = version,
|
||||
eventId = event_id,
|
||||
type = type,
|
||||
name = name
|
||||
version=version, eventId=event_id, type=type, name=name
|
||||
)
|
||||
|
||||
conflict = sql.on_duplicate_key_update(
|
||||
name = name
|
||||
)
|
||||
conflict = sql.on_duplicate_key_update(name=name)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
def update_event(self, version: int, event_id: int, enabled: bool) -> Optional[bool]:
|
||||
sql = events.update(and_(events.c.version == version, events.c.eventId == event_id)).values(
|
||||
enabled = enabled
|
||||
)
|
||||
|
||||
def update_event(
|
||||
self, version: int, event_id: int, enabled: bool
|
||||
) -> Optional[bool]:
|
||||
sql = events.update(
|
||||
and_(events.c.version == version, events.c.eventId == event_id)
|
||||
).values(enabled=enabled)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None:
|
||||
self.logger.warn(f"update_event: failed to update event! version: {version}, event_id: {event_id}, enabled: {enabled}")
|
||||
if result is None:
|
||||
self.logger.warn(
|
||||
f"update_event: failed to update event! version: {version}, event_id: {event_id}, enabled: {enabled}"
|
||||
)
|
||||
return None
|
||||
|
||||
event = self.get_event(version, event_id)
|
||||
if event is None:
|
||||
self.logger.warn(f"update_event: failed to fetch event {event_id} after updating")
|
||||
self.logger.warn(
|
||||
f"update_event: failed to fetch event {event_id} after updating"
|
||||
)
|
||||
return None
|
||||
return event["enabled"]
|
||||
|
||||
def get_event(self, version: int, event_id: int) -> Optional[Row]:
|
||||
sql = select(events).where(and_(events.c.version == version, events.c.eventId == event_id))
|
||||
|
||||
sql = select(events).where(
|
||||
and_(events.c.version == version, events.c.eventId == event_id)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
def get_enabled_events(self, version: int) -> Optional[List[Row]]:
|
||||
sql = select(events).where(and_(events.c.version == version, events.c.enabled == True))
|
||||
sql = select(events).where(
|
||||
and_(events.c.version == version, events.c.enabled == True)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
def get_events(self, version: int) -> Optional[List[Row]]:
|
||||
sql = select(events).where(events.c.version == version)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
def put_music(self, version: int, song_id: int, chart_id: int, title: int, artist: str,
|
||||
level: float, genre: str, jacketPath: str, we_tag: str) -> Optional[int]:
|
||||
|
||||
def put_music(
|
||||
self,
|
||||
version: int,
|
||||
song_id: int,
|
||||
chart_id: int,
|
||||
title: int,
|
||||
artist: str,
|
||||
level: float,
|
||||
genre: str,
|
||||
jacketPath: str,
|
||||
we_tag: str,
|
||||
) -> Optional[int]:
|
||||
sql = insert(music).values(
|
||||
version = version,
|
||||
songId = song_id,
|
||||
chartId = chart_id,
|
||||
title = title,
|
||||
artist = artist,
|
||||
level = level,
|
||||
genre = genre,
|
||||
jacketPath = jacketPath,
|
||||
worldsEndTag = we_tag,
|
||||
version=version,
|
||||
songId=song_id,
|
||||
chartId=chart_id,
|
||||
title=title,
|
||||
artist=artist,
|
||||
level=level,
|
||||
genre=genre,
|
||||
jacketPath=jacketPath,
|
||||
worldsEndTag=we_tag,
|
||||
)
|
||||
|
||||
conflict = sql.on_duplicate_key_update(
|
||||
title = title,
|
||||
artist = artist,
|
||||
level = level,
|
||||
genre = genre,
|
||||
jacketPath = jacketPath,
|
||||
worldsEndTag = we_tag,
|
||||
title=title,
|
||||
artist=artist,
|
||||
level=level,
|
||||
genre=genre,
|
||||
jacketPath=jacketPath,
|
||||
worldsEndTag=we_tag,
|
||||
)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
def put_charge(self, version: int, charge_id: int, name: str, expiration_days: int,
|
||||
consume_type: int, selling_appeal: bool) -> Optional[int]:
|
||||
|
||||
def put_charge(
|
||||
self,
|
||||
version: int,
|
||||
charge_id: int,
|
||||
name: str,
|
||||
expiration_days: int,
|
||||
consume_type: int,
|
||||
selling_appeal: bool,
|
||||
) -> Optional[int]:
|
||||
sql = insert(charge).values(
|
||||
version = version,
|
||||
chargeId = charge_id,
|
||||
name = name,
|
||||
expirationDays = expiration_days,
|
||||
consumeType = consume_type,
|
||||
sellingAppeal = selling_appeal,
|
||||
version=version,
|
||||
chargeId=charge_id,
|
||||
name=name,
|
||||
expirationDays=expiration_days,
|
||||
consumeType=consume_type,
|
||||
sellingAppeal=selling_appeal,
|
||||
)
|
||||
|
||||
conflict = sql.on_duplicate_key_update(
|
||||
name = name,
|
||||
expirationDays = expiration_days,
|
||||
consumeType = consume_type,
|
||||
sellingAppeal = selling_appeal,
|
||||
name=name,
|
||||
expirationDays=expiration_days,
|
||||
consumeType=consume_type,
|
||||
sellingAppeal=selling_appeal,
|
||||
)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
|
||||
def get_enabled_charges(self, version: int) -> Optional[List[Row]]:
|
||||
sql = select(charge).where(and_(
|
||||
charge.c.version == version,
|
||||
charge.c.enabled == True
|
||||
))
|
||||
sql = select(charge).where(
|
||||
and_(charge.c.version == version, charge.c.enabled == True)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
|
||||
def get_charges(self, version: int) -> Optional[List[Row]]:
|
||||
sql = select(charge).where(charge.c.version == version)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
def get_music_chart(self, version: int, song_id: int, chart_id: int) -> Optional[List[Row]]:
|
||||
sql = select(music).where(and_(
|
||||
music.c.version == version,
|
||||
music.c.songId == song_id,
|
||||
music.c.chartId == chart_id
|
||||
))
|
||||
def get_music_chart(
|
||||
self, version: int, song_id: int, chart_id: int
|
||||
) -> Optional[List[Row]]:
|
||||
sql = select(music).where(
|
||||
and_(
|
||||
music.c.version == version,
|
||||
music.c.songId == song_id,
|
||||
music.c.chartId == chart_id,
|
||||
)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
def put_avatar(self, version: int, avatarAccessoryId: int, name: str, category: int, iconPath: str, texturePath: str) -> Optional[int]:
|
||||
def put_avatar(
|
||||
self,
|
||||
version: int,
|
||||
avatarAccessoryId: int,
|
||||
name: str,
|
||||
category: int,
|
||||
iconPath: str,
|
||||
texturePath: str,
|
||||
) -> Optional[int]:
|
||||
sql = insert(avatar).values(
|
||||
version = version,
|
||||
avatarAccessoryId = avatarAccessoryId,
|
||||
name = name,
|
||||
category = category,
|
||||
iconPath = iconPath,
|
||||
texturePath = texturePath,
|
||||
version=version,
|
||||
avatarAccessoryId=avatarAccessoryId,
|
||||
name=name,
|
||||
category=category,
|
||||
iconPath=iconPath,
|
||||
texturePath=texturePath,
|
||||
)
|
||||
|
||||
conflict = sql.on_duplicate_key_update(
|
||||
name = name,
|
||||
category = category,
|
||||
iconPath = iconPath,
|
||||
texturePath = texturePath,
|
||||
name=name,
|
||||
category=category,
|
||||
iconPath=iconPath,
|
||||
texturePath=texturePath,
|
||||
)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
if result is None:
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
|
@ -5,12 +5,13 @@ from titles.chuni.base import ChuniBase
|
||||
from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
|
||||
class ChuniStar(ChuniBase):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
self.version = ChuniConstants.VER_CHUNITHM_STAR
|
||||
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["dataVersion"] = "1.20.00"
|
||||
return ret
|
||||
return ret
|
||||
|
@ -5,12 +5,13 @@ from titles.chuni.base import ChuniBase
|
||||
from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.config import ChuniConfig
|
||||
|
||||
|
||||
class ChuniStarPlus(ChuniBase):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
self.version = ChuniConstants.VER_CHUNITHM_STAR_PLUS
|
||||
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["dataVersion"] = "1.25.00"
|
||||
return ret
|
||||
return ret
|
||||
|
Reference in New Issue
Block a user