Merge branch 'starlette_cleanup' into develop

This commit is contained in:
Kevin Trocolli
2024-01-11 20:24:59 -05:00
177 changed files with 5251 additions and 4978 deletions

View File

@@ -7,4 +7,3 @@ index = ChuniServlet
database = ChuniData
reader = ChuniReader
game_codes = [ChuniConstants.GAME_CODE, ChuniConstants.GAME_CODE_NEW, ChuniConstants.GAME_CODE_INT]
current_schema_version = 5

View File

@@ -11,7 +11,7 @@ class ChuniAir(ChuniBase):
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)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.10.00"
return ret

View File

@@ -11,7 +11,7 @@ class ChuniAirPlus(ChuniBase):
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)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.15.00"
return ret

View File

@@ -13,7 +13,7 @@ class ChuniAmazon(ChuniBase):
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)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.30.00"
return ret

View File

@@ -13,7 +13,7 @@ class ChuniAmazonPlus(ChuniBase):
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)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.35.00"
return ret

View File

@@ -22,7 +22,7 @@ class ChuniBase:
self.game = ChuniConstants.GAME_CODE
self.version = ChuniConstants.VER_CHUNITHM
def handle_game_login_api_request(self, data: Dict) -> Dict:
async def handle_game_login_api_request(self, data: Dict) -> Dict:
"""
Handles the login bonus logic, required for the game because
getUserLoginBonus gets called after getUserItem and therefore the
@@ -38,20 +38,20 @@ class ChuniBase:
return {"returnCode": 1}
user_id = data["userId"]
login_bonus_presets = self.data.static.get_login_bonus_presets(self.version)
login_bonus_presets = await self.data.static.get_login_bonus_presets(self.version)
for preset in login_bonus_presets:
# check if a user already has some pogress and if not add the
# login bonus entry
user_login_bonus = self.data.item.get_login_bonus(
user_login_bonus = await self.data.item.get_login_bonus(
user_id, self.version, preset["presetId"]
)
if user_login_bonus is None:
self.data.item.put_login_bonus(
await self.data.item.put_login_bonus(
user_id, self.version, preset["presetId"]
)
# yeah i'm lazy
user_login_bonus = self.data.item.get_login_bonus(
user_login_bonus = await self.data.item.get_login_bonus(
user_id, self.version, preset["presetId"]
)
@@ -67,7 +67,7 @@ class ChuniBase:
bonus_count = user_login_bonus["bonusCount"] + 1
last_update_date = datetime.now()
all_login_boni = self.data.static.get_login_bonus(
all_login_boni = await self.data.static.get_login_bonus(
self.version, preset["presetId"]
)
@@ -91,13 +91,13 @@ class ChuniBase:
is_finished = True
# grab the item for the corresponding day
login_item = self.data.static.get_login_bonus_by_required_days(
login_item = await self.data.static.get_login_bonus_by_required_days(
self.version, preset["presetId"], bonus_count
)
if login_item is not None:
# now add the present to the database so the
# handle_get_user_item_api_request can grab them
self.data.item.put_item(
await self.data.item.put_item(
user_id,
{
"itemId": login_item["presentId"],
@@ -107,7 +107,7 @@ class ChuniBase:
},
)
self.data.item.put_login_bonus(
await self.data.item.put_login_bonus(
user_id,
self.version,
preset["presetId"],
@@ -119,12 +119,12 @@ class ChuniBase:
return {"returnCode": 1}
def handle_game_logout_api_request(self, data: Dict) -> Dict:
async 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}
def handle_get_game_charge_api_request(self, data: Dict) -> Dict:
game_charge_list = self.data.static.get_enabled_charges(self.version)
async def handle_get_game_charge_api_request(self, data: Dict) -> Dict:
game_charge_list = await self.data.static.get_enabled_charges(self.version)
if game_charge_list is None or len(game_charge_list) == 0:
return {"length": 0, "gameChargeList": []}
@@ -145,8 +145,8 @@ class ChuniBase:
)
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)
async def handle_get_game_event_api_request(self, data: Dict) -> Dict:
game_events = await self.data.static.get_enabled_events(self.version)
if game_events is None or len(game_events) == 0:
self.logger.warning("No enabled events, did you run the reader?")
@@ -177,10 +177,10 @@ class ChuniBase:
"gameEventList": event_list,
}
def handle_get_game_idlist_api_request(self, data: Dict) -> Dict:
async def handle_get_game_idlist_api_request(self, data: Dict) -> Dict:
return {"type": data["type"], "length": 0, "gameIdlistList": []}
def handle_get_game_message_api_request(self, data: Dict) -> Dict:
async def handle_get_game_message_api_request(self, data: Dict) -> Dict:
return {
"type": data["type"],
"length": 1,
@@ -193,14 +193,14 @@ class ChuniBase:
}]
}
def handle_get_game_ranking_api_request(self, data: Dict) -> Dict:
rankings = self.data.score.get_rankings(self.version)
async def handle_get_game_ranking_api_request(self, data: Dict) -> Dict:
rankings = await self.data.score.get_rankings(self.version)
return {"type": data["type"], "gameRankingList": rankings}
def handle_get_game_sale_api_request(self, data: Dict) -> Dict:
async def handle_get_game_sale_api_request(self, data: Dict) -> Dict:
return {"type": data["type"], "length": 0, "gameSaleList": []}
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
# if reboot start/end time is not defined use the default behavior of being a few hours ago
if self.core_cfg.title.reboot_start_time == "" or self.core_cfg.title.reboot_end_time == "":
reboot_start = datetime.strftime(
@@ -240,8 +240,8 @@ class ChuniBase:
"isDumpUpload": "false",
"isAou": "false",
}
def handle_get_user_activity_api_request(self, data: Dict) -> Dict:
user_activity_list = self.data.profile.get_profile_activity(
async def handle_get_user_activity_api_request(self, data: Dict) -> Dict:
user_activity_list = await self.data.profile.get_profile_activity(
data["userId"], data["kind"]
)
@@ -261,8 +261,8 @@ class ChuniBase:
"userActivityList": activity_list,
}
def handle_get_user_character_api_request(self, data: Dict) -> Dict:
characters = self.data.item.get_characters(data["userId"])
async def handle_get_user_character_api_request(self, data: Dict) -> Dict:
characters = await self.data.item.get_characters(data["userId"])
if characters is None:
return {
"userId": data["userId"],
@@ -296,8 +296,8 @@ class ChuniBase:
"userCharacterList": character_list,
}
def handle_get_user_charge_api_request(self, data: Dict) -> Dict:
user_charge_list = self.data.profile.get_profile_charge(data["userId"])
async def handle_get_user_charge_api_request(self, data: Dict) -> Dict:
user_charge_list = await self.data.profile.get_profile_charge(data["userId"])
charge_list = []
for charge in user_charge_list:
@@ -312,15 +312,15 @@ class ChuniBase:
"userChargeList": charge_list,
}
def handle_get_user_recent_player_api_request(self, data: Dict) -> Dict:
async def handle_get_user_recent_player_api_request(self, data: Dict) -> Dict:
return {
"userId": data["userId"],
"length": 0,
"userRecentPlayerList": [], # playUserId, playUserName, playDate, friendPoint
}
def handle_get_user_course_api_request(self, data: Dict) -> Dict:
user_course_list = self.data.score.get_courses(data["userId"])
async def handle_get_user_course_api_request(self, data: Dict) -> Dict:
user_course_list = await self.data.score.get_courses(data["userId"])
if user_course_list is None:
return {
"userId": data["userId"],
@@ -354,8 +354,8 @@ class ChuniBase:
"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)
async def handle_get_user_data_api_request(self, data: Dict) -> Dict:
p = await self.data.profile.get_profile_data(data["userId"], self.version)
if p is None:
return {}
@@ -366,8 +366,8 @@ class ChuniBase:
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)
async def handle_get_user_data_ex_api_request(self, data: Dict) -> Dict:
p = await self.data.profile.get_profile_data_ex(data["userId"], self.version)
if p is None:
return {}
@@ -378,8 +378,8 @@ class ChuniBase:
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"])
async def handle_get_user_duel_api_request(self, data: Dict) -> Dict:
user_duel_list = await self.data.item.get_duels(data["userId"])
if user_duel_list is None:
return {}
@@ -396,8 +396,8 @@ class ChuniBase:
"userDuelList": duel_list,
}
def handle_get_user_rival_data_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_rival(data["rivalId"])
async def handle_get_user_rival_data_api_request(self, data: Dict) -> Dict:
p = await self.data.profile.get_rival(data["rivalId"])
if p is None:
return {}
userRivalData = {
@@ -409,14 +409,14 @@ class ChuniBase:
"userRivalData": userRivalData
}
def handle_get_user_rival_music_api_request(self, data: Dict) -> Dict:
async def handle_get_user_rival_music_api_request(self, data: Dict) -> Dict:
rival_id = data["rivalId"]
next_index = int(data["nextIndex"])
max_count = int(data["maxCount"])
user_rival_music_list = []
# Fetch all the rival music entries for the user
all_entries = self.data.score.get_rival_music(rival_id)
all_entries = await self.data.score.get_rival_music(rival_id)
# Process the entries based on max_count and nextIndex
for music in all_entries:
@@ -462,12 +462,12 @@ class ChuniBase:
return result
def handle_get_user_favorite_item_api_request(self, data: Dict) -> Dict:
async def handle_get_user_favorite_item_api_request(self, data: Dict) -> Dict:
user_fav_item_list = []
# still needs to be implemented on WebUI
# 1: Music, 2: User, 3: Character
fav_list = self.data.item.get_all_favorites(
fav_list = await self.data.item.get_all_favorites(
data["userId"], self.version, fav_kind=int(data["kind"])
)
if fav_list is not None:
@@ -482,17 +482,17 @@ class ChuniBase:
"userFavoriteItemList": user_fav_item_list,
}
def handle_get_user_favorite_music_api_request(self, data: Dict) -> Dict:
async def handle_get_user_favorite_music_api_request(self, data: Dict) -> Dict:
"""
This is handled via the webui, which we don't have right now
"""
return {"userId": data["userId"], "length": 0, "userFavoriteMusicList": []}
def handle_get_user_item_api_request(self, data: Dict) -> Dict:
async 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)
user_item_list = await self.data.item.get_items(data["userId"], kind)
if user_item_list is None or len(user_item_list) == 0:
return {
@@ -526,9 +526,9 @@ class ChuniBase:
"userItemList": items,
}
def handle_get_user_login_bonus_api_request(self, data: Dict) -> Dict:
async def handle_get_user_login_bonus_api_request(self, data: Dict) -> Dict:
user_id = data["userId"]
user_login_bonus = self.data.item.get_all_login_bonus(user_id, self.version)
user_login_bonus = await self.data.item.get_all_login_bonus(user_id, self.version)
# ignore the loginBonus request if its disabled in config
if user_login_bonus is None or not self.game_cfg.mods.use_login_bonus:
return {"userId": user_id, "length": 0, "userLoginBonusList": []}
@@ -552,8 +552,8 @@ class ChuniBase:
"userLoginBonusList": user_login_list,
}
def handle_get_user_map_api_request(self, data: Dict) -> Dict:
user_map_list = self.data.item.get_maps(data["userId"])
async def handle_get_user_map_api_request(self, data: Dict) -> Dict:
user_map_list = await self.data.item.get_maps(data["userId"])
if user_map_list is None:
return {}
@@ -570,8 +570,8 @@ class ChuniBase:
"userMapList": map_list,
}
def handle_get_user_music_api_request(self, data: Dict) -> Dict:
music_detail = self.data.score.get_scores(data["userId"])
async def handle_get_user_music_api_request(self, data: Dict) -> Dict:
music_detail = await self.data.score.get_scores(data["userId"])
if music_detail is None:
return {
"userId": data["userId"],
@@ -629,8 +629,8 @@ class ChuniBase:
"userMusicList": song_list, # 240
}
def handle_get_user_option_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile_option(data["userId"])
async def handle_get_user_option_api_request(self, data: Dict) -> Dict:
p = await self.data.profile.get_profile_option(data["userId"])
option = p._asdict()
option.pop("id")
@@ -638,8 +638,8 @@ class ChuniBase:
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"])
async def handle_get_user_option_ex_api_request(self, data: Dict) -> Dict:
p = await self.data.profile.get_profile_option_ex(data["userId"])
option = p._asdict()
option.pop("id")
@@ -650,11 +650,11 @@ class ChuniBase:
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)
async def handle_get_user_preview_api_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile_preview(data["userId"], self.version)
if profile is None:
return None
profile_character = self.data.item.get_character(
profile_character = await self.data.item.get_character(
data["userId"], profile["characterId"]
)
@@ -692,8 +692,8 @@ class ChuniBase:
"userNameEx": profile["userName"],
}
def handle_get_user_recent_rating_api_request(self, data: Dict) -> Dict:
recent_rating_list = self.data.profile.get_profile_recent_rating(data["userId"])
async def handle_get_user_recent_rating_api_request(self, data: Dict) -> Dict:
recent_rating_list = await self.data.profile.get_profile_recent_rating(data["userId"])
if recent_rating_list is None:
return {
"userId": data["userId"],
@@ -707,7 +707,7 @@ class ChuniBase:
"userRecentRatingList": recent_rating_list["recentRating"],
}
def handle_get_user_region_api_request(self, data: Dict) -> Dict:
async def handle_get_user_region_api_request(self, data: Dict) -> Dict:
# TODO: Region
return {
"userId": data["userId"],
@@ -715,22 +715,22 @@ class ChuniBase:
"userRegionList": [],
}
def handle_get_user_team_api_request(self, data: Dict) -> Dict:
async def handle_get_user_team_api_request(self, data: Dict) -> Dict:
# Default values
team_id = 65535
team_name = self.game_cfg.team.team_name
team_rank = 0
# Get user profile
profile = self.data.profile.get_profile_data(data["userId"], self.version)
profile = await self.data.profile.get_profile_data(data["userId"], self.version)
if profile and profile["teamId"]:
# Get team by id
team = self.data.profile.get_team_by_id(profile["teamId"])
team = await self.data.profile.get_team_by_id(profile["teamId"])
if team:
team_id = team["id"]
team_name = team["teamName"]
team_rank = self.data.profile.get_team_rank(team["id"])
team_rank = await self.data.profile.get_team_rank(team["id"])
# Don't return anything if no team name has been defined for defaults and there is no team set for the player
if not profile["teamId"] and team_name == "":
@@ -750,7 +750,7 @@ class ChuniBase:
},
}
def handle_get_team_course_setting_api_request(self, data: Dict) -> Dict:
async def handle_get_team_course_setting_api_request(self, data: Dict) -> Dict:
return {
"userId": data["userId"],
"length": 0,
@@ -758,7 +758,7 @@ class ChuniBase:
"teamCourseSettingList": [],
}
def handle_get_team_course_setting_api_request_proto(self, data: Dict) -> Dict:
async def handle_get_team_course_setting_api_request_proto(self, data: Dict) -> Dict:
return {
"userId": data["userId"],
"length": 1,
@@ -782,7 +782,7 @@ class ChuniBase:
],
}
def handle_get_team_course_rule_api_request(self, data: Dict) -> Dict:
async def handle_get_team_course_rule_api_request(self, data: Dict) -> Dict:
return {
"userId": data["userId"],
"length": 0,
@@ -790,7 +790,7 @@ class ChuniBase:
"teamCourseRuleList": []
}
def handle_get_team_course_rule_api_request_proto(self, data: Dict) -> Dict:
async def handle_get_team_course_rule_api_request_proto(self, data: Dict) -> Dict:
return {
"userId": data["userId"],
"length": 1,
@@ -807,7 +807,7 @@ class ChuniBase:
],
}
def handle_upsert_user_all_api_request(self, data: Dict) -> Dict:
async def handle_upsert_user_all_api_request(self, data: Dict) -> Dict:
upsert = data["upsertUserAll"]
user_id = data["userId"]
@@ -819,58 +819,58 @@ class ChuniBase:
except Exception:
pass
self.data.profile.put_profile_data(
await self.data.profile.put_profile_data(
user_id, self.version, upsert["userData"][0]
)
if "userDataEx" in upsert:
self.data.profile.put_profile_data_ex(
await 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])
await self.data.profile.put_profile_option(user_id, upsert["userGameOption"][0])
if "userGameOptionEx" in upsert:
self.data.profile.put_profile_option_ex(
await self.data.profile.put_profile_option_ex(
user_id, upsert["userGameOptionEx"][0]
)
if "userRecentRatingList" in upsert:
self.data.profile.put_profile_recent_rating(
await 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)
await self.data.item.put_character(user_id, character)
if "userMapList" in upsert:
for map in upsert["userMapList"]:
self.data.item.put_map(user_id, map)
await self.data.item.put_map(user_id, map)
if "userCourseList" in upsert:
for course in upsert["userCourseList"]:
self.data.score.put_course(user_id, course)
await self.data.score.put_course(user_id, course)
if "userDuelList" in upsert:
for duel in upsert["userDuelList"]:
self.data.item.put_duel(user_id, duel)
await 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)
await self.data.item.put_item(user_id, item)
if "userActivityList" in upsert:
for activity in upsert["userActivityList"]:
self.data.profile.put_profile_activity(user_id, activity)
await 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)
await 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)
await self.data.score.put_score(user_id, song)
if "userPlaylogList" in upsert:
for playlog in upsert["userPlaylogList"]:
@@ -881,7 +881,7 @@ class ChuniBase:
playlog["playedUserName2"] = self.read_wtf8(playlog["playedUserName2"])
if playlog["playedUserName3"] is not None:
playlog["playedUserName3"] = self.read_wtf8(playlog["playedUserName3"])
self.data.score.put_playlog(user_id, playlog, self.version)
await self.data.score.put_playlog(user_id, playlog, self.version)
if "userTeamPoint" in upsert:
team_points = upsert["userTeamPoint"]
@@ -889,7 +889,7 @@ class ChuniBase:
for tp in team_points:
if tp["teamId"] != '65535':
# Fetch the current team data
current_team = self.data.profile.get_team_by_id(tp["teamId"])
current_team = await self.data.profile.get_team_by_id(tp["teamId"])
# Calculate the new teamPoint
new_team_point = int(tp["teamPoint"]) + current_team["teamPoint"]
@@ -900,24 +900,24 @@ class ChuniBase:
}
# Update the team data
self.data.profile.update_team(tp["teamId"], team_data)
await self.data.profile.update_team(tp["teamId"], team_data)
except:
pass # Probably a better way to catch if the team is not set yet (new profiles), but let's just pass
if "userMapAreaList" in upsert:
for map_area in upsert["userMapAreaList"]:
self.data.item.put_map_area(user_id, map_area)
await self.data.item.put_map_area(user_id, map_area)
if "userOverPowerList" in upsert:
for overpower in upsert["userOverPowerList"]:
self.data.profile.put_profile_overpower(user_id, overpower)
await self.data.profile.put_profile_overpower(user_id, overpower)
if "userEmoneyList" in upsert:
for emoney in upsert["userEmoneyList"]:
self.data.profile.put_profile_emoney(user_id, emoney)
await self.data.profile.put_profile_emoney(user_id, emoney)
if "userLoginBonusList" in upsert:
for login in upsert["userLoginBonusList"]:
self.data.item.put_login_bonus(
await self.data.item.put_login_bonus(
user_id, self.version, login["presetId"], isWatched=True
)
@@ -927,28 +927,28 @@ class ChuniBase:
return {"returnCode": "1"}
def handle_upsert_user_chargelog_api_request(self, data: Dict) -> Dict:
async def handle_upsert_user_chargelog_api_request(self, data: Dict) -> Dict:
# add tickets after they got bought, this makes sure the tickets are
# still valid after an unsuccessful logout
self.data.profile.put_profile_charge(data["userId"], data["userCharge"])
await self.data.profile.put_profile_charge(data["userId"], data["userCharge"])
return {"returnCode": "1"}
def handle_upsert_client_bookkeeping_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_bookkeeping_api_request(self, data: Dict) -> Dict:
return {"returnCode": "1"}
def handle_upsert_client_develop_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_develop_api_request(self, data: Dict) -> Dict:
return {"returnCode": "1"}
def handle_upsert_client_error_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_error_api_request(self, data: Dict) -> Dict:
return {"returnCode": "1"}
def handle_upsert_client_setting_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_setting_api_request(self, data: Dict) -> Dict:
return {"returnCode": "1"}
def handle_upsert_client_testmode_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_testmode_api_request(self, data: Dict) -> Dict:
return {"returnCode": "1"}
def handle_get_user_net_battle_data_api_request(self, data: Dict) -> Dict:
async def handle_get_user_net_battle_data_api_request(self, data: Dict) -> Dict:
return {
"userId": data["userId"],
"userNetBattleData": {"recentNBSelectMusicList": []},

View File

@@ -13,7 +13,7 @@ class ChuniCrystal(ChuniBase):
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)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.40.00"
return ret

View File

@@ -13,7 +13,7 @@ class ChuniCrystalPlus(ChuniBase):
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)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.45.00"
return ret

View File

@@ -1,4 +1,6 @@
from twisted.web.http import Request
from starlette.requests import Request
from starlette.routing import Route
from starlette.responses import Response
import logging, coloredlogs
from logging.handlers import TimedRotatingFileHandler
import zlib
@@ -33,7 +35,6 @@ from .newplus import ChuniNewPlus
from .sun import ChuniSun
from .sunplus import ChuniSunPlus
class ChuniServlet(BaseServlet):
def __init__(self, core_cfg: CoreConfig, cfg_dir: str) -> None:
super().__init__(core_cfg, cfg_dir)
@@ -124,15 +125,6 @@ class ChuniServlet(BaseServlet):
f"Hashed v{version} method {method_fixed} with {bytes.fromhex(keys[2])} to get {hash.hex()}"
)
def get_endpoint_matchers(self) -> Tuple[List[Tuple[str, str, Dict]], List[Tuple[str, str, Dict]]]:
return (
[],
[
("render_POST", "/{game}/{version}/ChuniServlet/{endpoint}", {}),
("render_POST", "/{game}/{version}/ChuniServlet/MatchingServer/{endpoint}", {})
]
)
@classmethod
def is_game_enabled(
cls, game_code: str, core_cfg: CoreConfig, cfg_dir: str
@@ -150,19 +142,25 @@ class ChuniServlet(BaseServlet):
def get_allnet_info(self, game_code: str, game_ver: int, keychip: str) -> Tuple[str, str]:
if not self.core_cfg.server.is_using_proxy and Utils.get_title_port(self.core_cfg) != 80:
return (f"http://{self.core_cfg.title.hostname}:{Utils.get_title_port(self.core_cfg)}/{game_code}/{game_ver}/", self.core_cfg.title.hostname)
return (f"http://{self.core_cfg.server.hostname}:{Utils.get_title_port(self.core_cfg)}/{game_code}/{game_ver}/", self.core_cfg.server.hostname)
return (f"http://{self.core_cfg.title.hostname}/{game_code}/{game_ver}/", self.core_cfg.title.hostname)
return (f"http://{self.core_cfg.server.hostname}/{game_code}/{game_ver}/", self.core_cfg.server.hostname)
def render_POST(self, request: Request, game_code: str, matchers: Dict) -> bytes:
endpoint = matchers['endpoint']
version = int(matchers['version'])
game_code = matchers['game']
def get_routes(self) -> List[Route]:
return [
Route("/{game:str}/{version:int}/ChuniServlet/{endpoint:str}", self.render_POST, methods=['POST']),
Route("/{game:str}/{version:int}/ChuniServlet/MatchingServer/{endpoint:str}", self.render_POST, methods=['POST']),
]
async def render_POST(self, request: Request) -> bytes:
endpoint: str = request.path_params.get('endpoint')
version: int = request.path_params.get('version')
game_code: str = request.path_params.get('game')
if endpoint.lower() == "ping":
return zlib.compress(b'{"returnCode": "1"}')
return Response(zlib.compress(b'{"returnCode": "1"}'))
req_raw = request.content.getvalue()
req_raw = await request.body()
encrtped = False
internal_ver = 0
@@ -201,7 +199,7 @@ class ChuniServlet(BaseServlet):
internal_ver = ChuniConstants.VER_CHUNITHM_SUN_PLUS
elif game_code == "SDGS": # Int
if version < 110: # SUPERSTAR
internal_ver = ChuniConstants.PARADISE
internal_ver = ChuniConstants.VER_CHUNITHM_PARADISE # FIXME: Not sure what was intended to go here? was just "PARADISE"
elif version >= 110 and version < 115: # NEW
internal_ver = ChuniConstants.VER_CHUNITHM_NEW
elif version >= 115 and version < 120: # NEW PLUS!!
@@ -216,20 +214,20 @@ class ChuniServlet(BaseServlet):
# doing encrypted. The likelyhood of false positives is low but
# technically not 0
if internal_ver < ChuniConstants.VER_CHUNITHM_NEW:
endpoint = request.getHeader("User-Agent").split("#")[0]
endpoint = request.headers.get("User-Agent").split("#")[0]
else:
if internal_ver not in self.hash_table:
self.logger.error(
f"v{version} does not support encryption or no keys entered"
)
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
elif endpoint.lower() not in self.hash_table[internal_ver]:
self.logger.error(
f"No hash found for v{version} endpoint {endpoint}"
)
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
endpoint = self.hash_table[internal_ver][endpoint.lower()]
@@ -246,7 +244,7 @@ class ChuniServlet(BaseServlet):
self.logger.error(
f"Failed to decrypt v{version} request to {endpoint} -> {e}"
)
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
encrtped = True
@@ -258,7 +256,7 @@ class ChuniServlet(BaseServlet):
self.logger.error(
f"Unencrypted v{version} {endpoint} request, but config is set to encrypted only: {req_raw}"
)
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
try:
unzip = zlib.decompress(req_raw)
@@ -267,7 +265,7 @@ class ChuniServlet(BaseServlet):
self.logger.error(
f"Failed to decompress v{version} {endpoint} request -> {e}"
)
return b""
return Response(zlib.compress(b'{"stat": "0"}'))
req_data = json.loads(unzip)
@@ -285,11 +283,11 @@ class ChuniServlet(BaseServlet):
else:
try:
handler = getattr(handler_cls, func_to_find)
resp = handler(req_data)
resp = await handler(req_data)
except Exception as e:
self.logger.error(f"Error handling v{version} method {endpoint} - {e}")
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
if resp == None:
resp = {"returnCode": 1}
@@ -299,7 +297,7 @@ class ChuniServlet(BaseServlet):
zipped = zlib.compress(json.dumps(resp, ensure_ascii=False).encode("utf-8"))
if not encrtped:
return zipped
return Response(zipped)
padded = pad(zipped, 16)
@@ -309,4 +307,4 @@ class ChuniServlet(BaseServlet):
bytes.fromhex(self.game_cfg.crypto.keys[internal_ver][1]),
)
return crypt.encrypt(padded)
return Response(crypt.encrypt(padded))

View File

@@ -33,7 +33,7 @@ class ChuniNew(ChuniBase):
if self.version == ChuniConstants.VER_CHUNITHM_SUN_PLUS:
return "215"
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
# use UTC time and convert it to JST time by adding +9
# matching therefore starts one hour before and lasts for 8 hours
match_start = datetime.strftime(
@@ -82,27 +82,27 @@ class ChuniNew(ChuniBase):
"matchErrorLimit": self.game_cfg.matching.match_error_limit,
"romVersion": self.game_cfg.version.version(self.version)["rom"],
"dataVersion": self.game_cfg.version.version(self.version)["data"],
"matchingUri": f"http://{self.core_cfg.title.hostname}:{t_port}/SDHD/{self._interal_ver_to_intver()}/ChuniServlet/",
"matchingUriX": f"http://{self.core_cfg.title.hostname}:{t_port}/SDHD/{self._interal_ver_to_intver()}/ChuniServlet/",
"matchingUri": f"http://{self.core_cfg.server.hostname}:{t_port}/SDHD/{self._interal_ver_to_intver()}/ChuniServlet/",
"matchingUriX": f"http://{self.core_cfg.server.hostname}:{t_port}/SDHD/{self._interal_ver_to_intver()}/ChuniServlet/",
# might be really important for online battle to connect the cabs via UDP port 50201
"udpHolePunchUri": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/{self._interal_ver_to_intver()}/ChuniServlet/",
"reflectorUri": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/{self._interal_ver_to_intver()}/ChuniServlet/",
"udpHolePunchUri": f"http://{self.core_cfg.server.hostname}:{self.core_cfg.server.port}/SDHD/{self._interal_ver_to_intver()}/ChuniServlet/",
"reflectorUri": f"http://{self.core_cfg.server.hostname}:{self.core_cfg.server.port}/SDHD/{self._interal_ver_to_intver()}/ChuniServlet/",
},
"isDumpUpload": False,
"isAou": False,
}
def handle_remove_token_api_request(self, data: Dict) -> Dict:
async def handle_remove_token_api_request(self, data: Dict) -> Dict:
return {"returnCode": "1"}
def handle_delete_token_api_request(self, data: Dict) -> Dict:
async def handle_delete_token_api_request(self, data: Dict) -> Dict:
return {"returnCode": "1"}
def handle_create_token_api_request(self, data: Dict) -> Dict:
async def handle_create_token_api_request(self, data: Dict) -> Dict:
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"])
async def handle_get_user_map_area_api_request(self, data: Dict) -> Dict:
user_map_areas = await self.data.item.get_map_areas(data["userId"])
map_areas = []
for map_area in user_map_areas:
@@ -113,14 +113,14 @@ class ChuniNew(ChuniBase):
return {"userId": data["userId"], "userMapAreaList": map_areas}
def handle_get_user_symbol_chat_setting_api_request(self, data: Dict) -> Dict:
async def handle_get_user_symbol_chat_setting_api_request(self, data: Dict) -> Dict:
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)
async def handle_get_user_preview_api_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile_preview(data["userId"], self.version)
if profile is None:
return None
profile_character = self.data.item.get_character(
profile_character = await self.data.item.get_character(
data["userId"], profile["characterId"]
)
@@ -164,8 +164,8 @@ class ChuniNew(ChuniBase):
}
return data1
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile_data(data["userId"], self.version)
async def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
p = await self.data.profile.get_profile_data(data["userId"], self.version)
if p is None:
return {}
@@ -177,17 +177,17 @@ class ChuniNew(ChuniBase):
"isLogin": False,
}
def handle_printer_login_api_request(self, data: Dict) -> Dict:
async def handle_printer_login_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1}
def handle_printer_logout_api_request(self, data: Dict) -> Dict:
async def handle_printer_logout_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1}
def handle_get_game_gacha_api_request(self, data: Dict) -> Dict:
async def handle_get_game_gacha_api_request(self, data: Dict) -> Dict:
"""
returns all current active banners (gachas)
"""
game_gachas = self.data.static.get_gachas(self.version)
game_gachas = await self.data.static.get_gachas(self.version)
# clean the database rows
game_gacha_list = []
@@ -213,11 +213,11 @@ class ChuniNew(ChuniBase):
"registIdList": [],
}
def handle_get_game_gacha_card_by_id_api_request(self, data: Dict) -> Dict:
async def handle_get_game_gacha_card_by_id_api_request(self, data: Dict) -> Dict:
"""
returns all valid cards for a given gachaId
"""
game_gacha_cards = self.data.static.get_gacha_cards(data["gachaId"])
game_gacha_cards = await self.data.static.get_gacha_cards(data["gachaId"])
game_gacha_card_list = []
for gacha_card in game_gacha_cards:
@@ -237,8 +237,8 @@ class ChuniNew(ChuniBase):
"ssrBookCalcList": [],
}
def handle_cm_get_user_data_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile_data(data["userId"], self.version)
async def handle_cm_get_user_data_api_request(self, data: Dict) -> Dict:
p = await self.data.profile.get_profile_data(data["userId"], self.version)
if p is None:
return {}
@@ -262,8 +262,8 @@ class ChuniNew(ChuniBase):
],
}
def handle_get_user_gacha_api_request(self, data: Dict) -> Dict:
user_gachas = self.data.item.get_user_gachas(data["userId"])
async def handle_get_user_gacha_api_request(self, data: Dict) -> Dict:
user_gachas = await self.data.item.get_user_gachas(data["userId"])
if user_gachas is None:
return {"userId": data["userId"], "length": 0, "userGachaList": []}
@@ -281,8 +281,8 @@ class ChuniNew(ChuniBase):
"userGachaList": user_gacha_list,
}
def handle_get_user_printed_card_api_request(self, data: Dict) -> Dict:
user_print_list = self.data.item.get_user_print_states(
async def handle_get_user_printed_card_api_request(self, data: Dict) -> Dict:
user_print_list = await self.data.item.get_user_print_states(
data["userId"], has_completed=True
)
if user_print_list is None:
@@ -316,10 +316,10 @@ class ChuniNew(ChuniBase):
"userPrintedCardList": print_list,
}
def handle_get_user_card_print_error_api_request(self, data: Dict) -> Dict:
async def handle_get_user_card_print_error_api_request(self, data: Dict) -> Dict:
user_id = data["userId"]
user_print_states = self.data.item.get_user_print_states(
user_print_states = await self.data.item.get_user_print_states(
user_id, has_completed=False
)
@@ -338,13 +338,13 @@ class ChuniNew(ChuniBase):
"userCardPrintStateList": card_print_state_list,
}
def handle_cm_get_user_character_api_request(self, data: Dict) -> Dict:
async def handle_cm_get_user_character_api_request(self, data: Dict) -> Dict:
return super().handle_get_user_character_api_request(data)
def handle_cm_get_user_item_api_request(self, data: Dict) -> Dict:
async def handle_cm_get_user_item_api_request(self, data: Dict) -> Dict:
return super().handle_get_user_item_api_request(data)
def handle_roll_gacha_api_request(self, data: Dict) -> Dict:
async def handle_roll_gacha_api_request(self, data: Dict) -> Dict:
"""
Handle a gacha roll API request, with:
gachaId: the gachaId where the cards should be pulled from
@@ -362,14 +362,14 @@ class ChuniNew(ChuniBase):
# characterId should be returned
if chara_id != -1:
# get the
card = self.data.static.get_gacha_card_by_character(gacha_id, chara_id)
card = await self.data.static.get_gacha_card_by_character(gacha_id, chara_id)
tmp = card._asdict()
tmp.pop("id")
rolled_cards.append(tmp)
else:
gacha_cards = self.data.static.get_gacha_cards(gacha_id)
gacha_cards = await self.data.static.get_gacha_cards(gacha_id)
# get the card id for each roll
for _ in range(num_rolls):
@@ -386,7 +386,7 @@ class ChuniNew(ChuniBase):
return {"length": len(rolled_cards), "gameGachaCardList": rolled_cards}
def handle_cm_upsert_user_gacha_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_user_gacha_api_request(self, data: Dict) -> Dict:
upsert = data["cmUpsertUserGacha"]
user_id = data["userId"]
place_id = data["placeId"]
@@ -396,7 +396,7 @@ class ChuniNew(ChuniBase):
user_data.pop("rankUpChallengeResults")
user_data.pop("userEmoney")
self.data.profile.put_profile_data(user_id, self.version, user_data)
await self.data.profile.put_profile_data(user_id, self.version, user_data)
# save the user gacha
user_gacha = upsert["userGacha"]
@@ -404,16 +404,16 @@ class ChuniNew(ChuniBase):
user_gacha.pop("gachaId")
user_gacha.pop("dailyGachaDate")
self.data.item.put_user_gacha(user_id, gacha_id, user_gacha)
await self.data.item.put_user_gacha(user_id, gacha_id, user_gacha)
# save all user items
if "userItemList" in upsert:
for item in upsert["userItemList"]:
self.data.item.put_item(user_id, item)
await self.data.item.put_item(user_id, item)
# add every gamegachaCard to database
for card in upsert["gameGachaCardList"]:
self.data.item.put_user_print_state(
await self.data.item.put_user_print_state(
user_id,
hasCompleted=False,
placeId=place_id,
@@ -423,7 +423,7 @@ class ChuniNew(ChuniBase):
# retrieve every game gacha card which has been added in order to get
# the orderId for the next request
user_print_states = self.data.item.get_user_print_states_by_gacha(
user_print_states = await self.data.item.get_user_print_states_by_gacha(
user_id, gacha_id, has_completed=False
)
card_print_state_list = []
@@ -441,7 +441,7 @@ class ChuniNew(ChuniBase):
"userCardPrintStateList": card_print_state_list,
}
def handle_cm_upsert_user_printlog_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_user_printlog_api_request(self, data: Dict) -> Dict:
return {
"returnCode": 1,
"orderId": 0,
@@ -449,7 +449,7 @@ class ChuniNew(ChuniBase):
"apiName": "CMUpsertUserPrintlogApi",
}
def handle_cm_upsert_user_print_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_user_print_api_request(self, data: Dict) -> Dict:
user_print_detail = data["userPrintDetail"]
user_id = data["userId"]
@@ -465,7 +465,7 @@ class ChuniNew(ChuniBase):
)
# add the entry to the user print table with the random serialId
self.data.item.put_user_print_detail(user_id, serial_id, user_print_detail)
await self.data.item.put_user_print_detail(user_id, serial_id, user_print_detail)
return {
"returnCode": 1,
@@ -474,7 +474,7 @@ class ChuniNew(ChuniBase):
"apiName": "CMUpsertUserPrintApi",
}
def handle_cm_upsert_user_print_subtract_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_user_print_subtract_api_request(self, data: Dict) -> Dict:
upsert = data["userCardPrintState"]
user_id = data["userId"]
place_id = data["placeId"]
@@ -482,37 +482,37 @@ class ChuniNew(ChuniBase):
# save all user items
if "userItemList" in data:
for item in data["userItemList"]:
self.data.item.put_item(user_id, item)
await self.data.item.put_item(user_id, item)
# set the card print state to success and use the orderId as the key
self.data.item.put_user_print_state(
await self.data.item.put_user_print_state(
user_id, id=upsert["orderId"], hasCompleted=True
)
return {"returnCode": "1", "apiName": "CMUpsertUserPrintSubtractApi"}
def handle_cm_upsert_user_print_cancel_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_user_print_cancel_api_request(self, data: Dict) -> Dict:
order_ids = data["orderIdList"]
user_id = data["userId"]
# set the card print state to success and use the orderId as the key
for order_id in order_ids:
self.data.item.put_user_print_state(user_id, id=order_id, hasCompleted=True)
await self.data.item.put_user_print_state(user_id, id=order_id, hasCompleted=True)
return {"returnCode": "1", "apiName": "CMUpsertUserPrintCancelApi"}
def handle_ping_request(self, data: Dict) -> Dict:
async def handle_ping_request(self, data: Dict) -> Dict:
# matchmaking ping request
return {"returnCode": "1"}
def handle_begin_matching_api_request(self, data: Dict) -> Dict:
async def handle_begin_matching_api_request(self, data: Dict) -> Dict:
room_id = 1
# check if there is a free matching room
matching_room = self.data.item.get_oldest_free_matching(self.version)
matching_room = await self.data.item.get_oldest_free_matching(self.version)
if matching_room is None:
# grab the latest roomId and add 1 for the new room
newest_matching = self.data.item.get_newest_matching(self.version)
newest_matching = await self.data.item.get_newest_matching(self.version)
if newest_matching is not None:
room_id = newest_matching["roomId"] + 1
@@ -522,12 +522,12 @@ class ChuniNew(ChuniBase):
# create the new room with room_id and the current user id (host)
# user id is required for the countdown later on
self.data.item.put_matching(
await self.data.item.put_matching(
self.version, room_id, [new_member], user_id=new_member["userId"]
)
# get the newly created matching room
matching_room = self.data.item.get_matching(self.version, room_id)
matching_room = await self.data.item.get_matching(self.version, room_id)
else:
# a room already exists, so just add the new member to it
matching_member_list = matching_room["matchingMemberInfoList"]
@@ -537,7 +537,7 @@ class ChuniNew(ChuniBase):
matching_member_list.append(new_member)
# add the updated room to the database, make sure to set isFull correctly!
self.data.item.put_matching(
await self.data.item.put_matching(
self.version,
matching_room["roomId"],
matching_member_list,
@@ -554,8 +554,8 @@ class ChuniNew(ChuniBase):
return {"roomId": 1, "matchingWaitState": matching_wait}
def handle_end_matching_api_request(self, data: Dict) -> Dict:
matching_room = self.data.item.get_matching(self.version, data["roomId"])
async def handle_end_matching_api_request(self, data: Dict) -> Dict:
matching_room = await self.data.item.get_matching(self.version, data["roomId"])
members = matching_room["matchingMemberInfoList"]
# only set the host user to role 1 every other to 0?
@@ -564,7 +564,7 @@ class ChuniNew(ChuniBase):
for m in members
]
self.data.item.put_matching(
await self.data.item.put_matching(
self.version,
matching_room["roomId"],
members,
@@ -579,13 +579,13 @@ class ChuniNew(ChuniBase):
# no idea, maybe to differentiate between CPUs and real players?
"matchingMemberRoleList": role_list,
# TCP/UDP connection?
"reflectorUri": f"{self.core_cfg.title.hostname}",
"reflectorUri": f"{self.core_cfg.server.hostname}",
}
def handle_remove_matching_member_api_request(self, data: Dict) -> Dict:
async def handle_remove_matching_member_api_request(self, data: Dict) -> Dict:
# get all matching rooms, because Chuni only returns the userId
# not the actual roomId
matching_rooms = self.data.item.get_all_matchings(self.version)
matching_rooms = await self.data.item.get_all_matchings(self.version)
if matching_rooms is None:
return {"returnCode": "1"}
@@ -599,10 +599,10 @@ class ChuniNew(ChuniBase):
# if the last user got removed, delete the matching room
if len(new_members) <= 0:
self.data.item.delete_matching(self.version, room["roomId"])
await self.data.item.delete_matching(self.version, room["roomId"])
else:
# remove the user from the room
self.data.item.put_matching(
await self.data.item.put_matching(
self.version,
room["roomId"],
new_members,
@@ -612,10 +612,10 @@ class ChuniNew(ChuniBase):
return {"returnCode": "1"}
def handle_get_matching_state_api_request(self, data: Dict) -> Dict:
async def handle_get_matching_state_api_request(self, data: Dict) -> Dict:
polling_interval = 1
# get the current active room
matching_room = self.data.item.get_matching(self.version, data["roomId"])
matching_room = await self.data.item.get_matching(self.version, data["roomId"])
members = matching_room["matchingMemberInfoList"]
rest_sec = matching_room["restMSec"]
@@ -638,7 +638,7 @@ class ChuniNew(ChuniBase):
current_member["userName"] = self.read_wtf8(current_member["userName"])
members[i] = current_member
self.data.item.put_matching(
await self.data.item.put_matching(
self.version,
data["roomId"],
members,

View File

@@ -11,8 +11,8 @@ class ChuniNewPlus(ChuniNew):
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_NEW_PLUS
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = super().handle_cm_get_user_preview_api_request(data)
async def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = await super().handle_cm_get_user_preview_api_request(data)
# hardcode lastDataVersion for CardMaker 1.35 A028
user_data["lastDataVersion"] = "2.05.00"

View File

@@ -13,7 +13,7 @@ class ChuniParadise(ChuniBase):
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)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.50.00"
return ret

View File

@@ -11,7 +11,7 @@ class ChuniPlus(ChuniBase):
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)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.05.00"
return ret

View File

@@ -28,7 +28,7 @@ class ChuniReader(BaseReader):
self.logger.error(f"Invalid chunithm version {version}")
exit(1)
def read(self) -> None:
async def read(self) -> None:
data_dirs = []
if self.bin_dir is not None:
data_dirs += self.get_data_directories(self.bin_dir)
@@ -38,13 +38,13 @@ class ChuniReader(BaseReader):
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")
self.read_login_bonus(f"{dir}/")
await self.read_events(f"{dir}/event")
await self.read_music(f"{dir}/music")
await self.read_charges(f"{dir}/chargeItem")
await self.read_avatar(f"{dir}/avatarAccessory")
await self.read_login_bonus(f"{dir}/")
def read_login_bonus(self, root_dir: str) -> None:
async def read_login_bonus(self, root_dir: str) -> None:
for root, dirs, files in walk(f"{root_dir}loginBonusPreset"):
for dir in dirs:
if path.exists(f"{root}/{dir}/LoginBonusPreset.xml"):
@@ -60,7 +60,7 @@ class ChuniReader(BaseReader):
True if xml_root.find("disableFlag").text == "false" else False
)
result = self.data.static.put_login_bonus_preset(
result = await self.data.static.put_login_bonus_preset(
self.version, id, name, is_enabled
)
@@ -98,7 +98,7 @@ class ChuniReader(BaseReader):
bonus_root.find("loginBonusCategoryType").text
)
result = self.data.static.put_login_bonus(
result = await self.data.static.put_login_bonus(
self.version,
id,
bonus_id,
@@ -117,7 +117,7 @@ class ChuniReader(BaseReader):
f"Failed to insert login bonus {bonus_id}"
)
def read_events(self, evt_dir: str) -> None:
async 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"):
@@ -132,7 +132,7 @@ class ChuniReader(BaseReader):
for substances in xml_root.findall("substances"):
event_type = substances.find("type").text
result = self.data.static.put_event(
result = await self.data.static.put_event(
self.version, id, event_type, name
)
if result is not None:
@@ -140,7 +140,7 @@ class ChuniReader(BaseReader):
else:
self.logger.warning(f"Failed to insert event {id}")
def read_music(self, music_dir: str) -> None:
async def read_music(self, music_dir: str) -> None:
for root, dirs, files in walk(music_dir):
for dir in dirs:
if path.exists(f"{root}/{dir}/Music.xml"):
@@ -185,7 +185,7 @@ class ChuniReader(BaseReader):
)
we_chara = None
result = self.data.static.put_music(
result = await self.data.static.put_music(
self.version,
song_id,
chart_id,
@@ -206,7 +206,7 @@ class ChuniReader(BaseReader):
f"Failed to insert music {song_id} chart {chart_id}"
)
def read_charges(self, charge_dir: str) -> None:
async 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"):
@@ -222,7 +222,7 @@ class ChuniReader(BaseReader):
consumeType = xml_root.find("consumeType").text
sellingAppeal = bool(xml_root.find("sellingAppeal").text)
result = self.data.static.put_charge(
result = await self.data.static.put_charge(
self.version,
id,
name,
@@ -236,7 +236,7 @@ class ChuniReader(BaseReader):
else:
self.logger.warning(f"Failed to insert charge {id}")
def read_avatar(self, avatar_dir: str) -> None:
async def read_avatar(self, avatar_dir: str) -> None:
for root, dirs, files in walk(avatar_dir):
for dir in dirs:
if path.exists(f"{root}/{dir}/AvatarAccessory.xml"):
@@ -254,7 +254,7 @@ class ChuniReader(BaseReader):
for texture in xml_root.findall("texture"):
texturePath = texture.find("path").text
result = self.data.static.put_avatar(
result = await self.data.static.put_avatar(
self.version, id, name, category, iconPath, texturePath
)

View File

@@ -245,7 +245,7 @@ matching = Table(
class ChuniItemData(BaseData):
def get_oldest_free_matching(self, version: int) -> Optional[Row]:
async def get_oldest_free_matching(self, version: int) -> Optional[Row]:
sql = matching.select(
and_(
matching.c.version == version,
@@ -253,46 +253,46 @@ class ChuniItemData(BaseData):
)
).order_by(matching.c.roomId.asc())
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_newest_matching(self, version: int) -> Optional[Row]:
async def get_newest_matching(self, version: int) -> Optional[Row]:
sql = matching.select(
and_(
matching.c.version == version
)
).order_by(matching.c.roomId.desc())
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_all_matchings(self, version: int) -> Optional[List[Row]]:
async def get_all_matchings(self, version: int) -> Optional[List[Row]]:
sql = matching.select(
and_(
matching.c.version == version
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_matching(self, version: int, room_id: int) -> Optional[Row]:
async def get_matching(self, version: int, room_id: int) -> Optional[Row]:
sql = matching.select(
and_(matching.c.version == version, matching.c.roomId == room_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_matching(
async def put_matching(
self,
version: int,
room_id: int,
@@ -314,22 +314,22 @@ class ChuniItemData(BaseData):
restMSec=rest_sec, matchingMemberInfoList=matching_member_info_list
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def delete_matching(self, version: int, room_id: int):
async def delete_matching(self, version: int, room_id: int):
sql = delete(matching).where(
and_(matching.c.roomId == room_id, matching.c.version == version)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.lastrowid
def get_all_favorites(
async def get_all_favorites(
self, user_id: int, version: int, fav_kind: int = 1
) -> Optional[List[Row]]:
sql = favorite.select(
@@ -340,12 +340,12 @@ class ChuniItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_login_bonus(
async def put_login_bonus(
self, user_id: int, version: int, preset_id: int, **login_bonus_data
) -> Optional[int]:
sql = insert(login_bonus).values(
@@ -354,12 +354,12 @@ class ChuniItemData(BaseData):
conflict = sql.on_duplicate_key_update(presetId=preset_id, **login_bonus_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_all_login_bonus(
async def get_all_login_bonus(
self, user_id: int, version: int, is_finished: bool = False
) -> Optional[List[Row]]:
sql = login_bonus.select(
@@ -370,12 +370,12 @@ class ChuniItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_login_bonus(
async def get_login_bonus(
self, user_id: int, version: int, preset_id: int
) -> Optional[Row]:
sql = login_bonus.select(
@@ -386,12 +386,12 @@ class ChuniItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_character(self, user_id: int, character_data: Dict) -> Optional[int]:
async def put_character(self, user_id: int, character_data: Dict) -> Optional[int]:
character_data["user"] = user_id
character_data = self.fix_bools(character_data)
@@ -399,30 +399,30 @@ class ChuniItemData(BaseData):
sql = insert(character).values(**character_data)
conflict = sql.on_duplicate_key_update(**character_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_character(self, user_id: int, character_id: int) -> Optional[Dict]:
async 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)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_characters(self, user_id: int) -> Optional[List[Row]]:
async def get_characters(self, user_id: int) -> Optional[List[Row]]:
sql = select(character).where(character.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_item(self, user_id: int, item_data: Dict) -> Optional[int]:
async def put_item(self, user_id: int, item_data: Dict) -> Optional[int]:
item_data["user"] = user_id
item_data = self.fix_bools(item_data)
@@ -430,12 +430,12 @@ class ChuniItemData(BaseData):
sql = insert(item).values(**item_data)
conflict = sql.on_duplicate_key_update(**item_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_items(self, user_id: int, kind: int = None) -> Optional[List[Row]]:
async 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:
@@ -443,12 +443,12 @@ class ChuniItemData(BaseData):
and_(item.c.user == user_id, item.c.itemKind == kind)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_duel(self, user_id: int, duel_data: Dict) -> Optional[int]:
async def put_duel(self, user_id: int, duel_data: Dict) -> Optional[int]:
duel_data["user"] = user_id
duel_data = self.fix_bools(duel_data)
@@ -456,20 +456,20 @@ class ChuniItemData(BaseData):
sql = insert(duel).values(**duel_data)
conflict = sql.on_duplicate_key_update(**duel_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_duels(self, user_id: int) -> Optional[List[Row]]:
async def get_duels(self, user_id: int) -> Optional[List[Row]]:
sql = select(duel).where(duel.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_map(self, user_id: int, map_data: Dict) -> Optional[int]:
async def put_map(self, user_id: int, map_data: Dict) -> Optional[int]:
map_data["user"] = user_id
map_data = self.fix_bools(map_data)
@@ -477,20 +477,20 @@ class ChuniItemData(BaseData):
sql = insert(map).values(**map_data)
conflict = sql.on_duplicate_key_update(**map_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_maps(self, user_id: int) -> Optional[List[Row]]:
async def get_maps(self, user_id: int) -> Optional[List[Row]]:
sql = select(map).where(map.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_map_area(self, user_id: int, map_area_data: Dict) -> Optional[int]:
async def put_map_area(self, user_id: int, map_area_data: Dict) -> Optional[int]:
map_area_data["user"] = user_id
map_area_data = self.fix_bools(map_area_data)
@@ -498,28 +498,28 @@ class ChuniItemData(BaseData):
sql = insert(map_area).values(**map_area_data)
conflict = sql.on_duplicate_key_update(**map_area_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_map_areas(self, user_id: int) -> Optional[List[Row]]:
async 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)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_user_gachas(self, aime_id: int) -> Optional[List[Row]]:
async def get_user_gachas(self, aime_id: int) -> Optional[List[Row]]:
sql = gacha.select(gacha.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_user_gacha(
async def put_user_gacha(
self, aime_id: int, gacha_id: int, gacha_data: Dict
) -> Optional[int]:
sql = insert(gacha).values(user=aime_id, gachaId=gacha_id, **gacha_data)
@@ -527,14 +527,14 @@ class ChuniItemData(BaseData):
conflict = sql.on_duplicate_key_update(
user=aime_id, gachaId=gacha_id, **gacha_data
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_user_gacha: Failed to insert! aime_id: {aime_id}")
return None
return result.lastrowid
def get_user_print_states(
async def get_user_print_states(
self, aime_id: int, has_completed: bool = False
) -> Optional[List[Row]]:
sql = print_state.select(
@@ -544,12 +544,12 @@ class ChuniItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_user_print_states_by_gacha(
async def get_user_print_states_by_gacha(
self, aime_id: int, gacha_id: int, has_completed: bool = False
) -> Optional[List[Row]]:
sql = print_state.select(
@@ -560,16 +560,16 @@ class ChuniItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_user_print_state(self, aime_id: int, **print_data) -> Optional[int]:
async def put_user_print_state(self, aime_id: int, **print_data) -> Optional[int]:
sql = insert(print_state).values(user=aime_id, **print_data)
conflict = sql.on_duplicate_key_update(user=aime_id, **print_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
@@ -578,7 +578,7 @@ class ChuniItemData(BaseData):
return None
return result.lastrowid
def put_user_print_detail(
async def put_user_print_detail(
self, aime_id: int, serial_id: str, user_print_data: Dict
) -> Optional[int]:
sql = insert(print_detail).values(
@@ -586,7 +586,7 @@ class ChuniItemData(BaseData):
)
conflict = sql.on_duplicate_key_update(user=aime_id, **user_print_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(

View File

@@ -395,7 +395,7 @@ team = Table(
class ChuniProfileData(BaseData):
def put_profile_data(
async def put_profile_data(
self, aime_id: int, version: int, profile_data: Dict
) -> Optional[int]:
profile_data["user"] = aime_id
@@ -407,26 +407,26 @@ class ChuniProfileData(BaseData):
sql = insert(profile).values(**profile_data)
conflict = sql.on_duplicate_key_update(**profile_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(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]:
async 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))
).order_by(profile.c.version.desc())
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_profile_data(self, aime_id: int, version: int) -> Optional[Row]:
async def get_profile_data(self, aime_id: int, version: int) -> Optional[Row]:
sql = select(profile).where(
and_(
profile.c.user == aime_id,
@@ -434,12 +434,12 @@ class ChuniProfileData(BaseData):
)
).order_by(profile.c.version.desc())
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_data_ex(
async def put_profile_data_ex(
self, aime_id: int, version: int, profile_ex_data: Dict
) -> Optional[int]:
profile_ex_data["user"] = aime_id
@@ -449,7 +449,7 @@ class ChuniProfileData(BaseData):
sql = insert(profile_ex).values(**profile_ex_data)
conflict = sql.on_duplicate_key_update(**profile_ex_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
@@ -458,7 +458,7 @@ class ChuniProfileData(BaseData):
return None
return result.lastrowid
def get_profile_data_ex(self, aime_id: int, version: int) -> Optional[Row]:
async 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,
@@ -466,17 +466,17 @@ class ChuniProfileData(BaseData):
)
).order_by(profile_ex.c.version.desc())
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_option(self, aime_id: int, option_data: Dict) -> Optional[int]:
async def put_profile_option(self, aime_id: int, option_data: Dict) -> Optional[int]:
option_data["user"] = aime_id
sql = insert(option).values(**option_data)
conflict = sql.on_duplicate_key_update(**option_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
@@ -485,22 +485,22 @@ class ChuniProfileData(BaseData):
return None
return result.lastrowid
def get_profile_option(self, aime_id: int) -> Optional[Row]:
async def get_profile_option(self, aime_id: int) -> Optional[Row]:
sql = select(option).where(option.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_option_ex(
async 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)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
@@ -509,15 +509,15 @@ class ChuniProfileData(BaseData):
return None
return result.lastrowid
def get_profile_option_ex(self, aime_id: int) -> Optional[Row]:
async def get_profile_option_ex(self, aime_id: int) -> Optional[Row]:
sql = select(option_ex).where(option_ex.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_recent_rating(
async def put_profile_recent_rating(
self, aime_id: int, recent_rating_data: List[Dict]
) -> Optional[int]:
sql = insert(recent_rating).values(
@@ -525,7 +525,7 @@ class ChuniProfileData(BaseData):
)
conflict = sql.on_duplicate_key_update(recentRating=recent_rating_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_profile_recent_rating: Failed to update! aime_id: {aime_id}"
@@ -533,15 +533,15 @@ class ChuniProfileData(BaseData):
return None
return result.lastrowid
def get_profile_recent_rating(self, aime_id: int) -> Optional[Row]:
async 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)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_activity(self, aime_id: int, activity_data: Dict) -> Optional[int]:
async def put_profile_activity(self, aime_id: int, activity_data: Dict) -> Optional[int]:
# The game just uses "id" but we need to distinguish that from the db column "id"
activity_data["user"] = aime_id
activity_data["activityId"] = activity_data["id"]
@@ -549,7 +549,7 @@ class ChuniProfileData(BaseData):
sql = insert(activity).values(**activity_data)
conflict = sql.on_duplicate_key_update(**activity_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
@@ -558,24 +558,24 @@ class ChuniProfileData(BaseData):
return None
return result.lastrowid
def get_profile_activity(self, aime_id: int, kind: int) -> Optional[List[Row]]:
async 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))
.order_by(activity.c.sortNumber.desc()) # to get the last played track
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_profile_charge(self, aime_id: int, charge_data: Dict) -> Optional[int]:
async 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)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
@@ -584,40 +584,40 @@ class ChuniProfileData(BaseData):
return None
return result.lastrowid
def get_profile_charge(self, aime_id: int) -> Optional[List[Row]]:
async def get_profile_charge(self, aime_id: int) -> Optional[List[Row]]:
sql = select(charge).where(charge.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def add_profile_region(self, aime_id: int, region_id: int) -> Optional[int]:
async def add_profile_region(self, aime_id: int, region_id: int) -> Optional[int]:
pass
def get_profile_regions(self, aime_id: int) -> Optional[List[Row]]:
async def get_profile_regions(self, aime_id: int) -> Optional[List[Row]]:
pass
def put_profile_emoney(self, aime_id: int, emoney_data: Dict) -> Optional[int]:
async def put_profile_emoney(self, aime_id: int, emoney_data: Dict) -> Optional[int]:
emoney_data["user"] = aime_id
sql = insert(emoney).values(**emoney_data)
conflict = sql.on_duplicate_key_update(**emoney_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_profile_emoney(self, aime_id: int) -> Optional[List[Row]]:
async def get_profile_emoney(self, aime_id: int) -> Optional[List[Row]]:
sql = select(emoney).where(emoney.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_profile_overpower(
async def put_profile_overpower(
self, aime_id: int, overpower_data: Dict
) -> Optional[int]:
overpower_data["user"] = aime_id
@@ -625,31 +625,31 @@ class ChuniProfileData(BaseData):
sql = insert(overpower).values(**overpower_data)
conflict = sql.on_duplicate_key_update(**overpower_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_profile_overpower(self, aime_id: int) -> Optional[List[Row]]:
async def get_profile_overpower(self, aime_id: int) -> Optional[List[Row]]:
sql = select(overpower).where(overpower.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_team_by_id(self, team_id: int) -> Optional[Row]:
async def get_team_by_id(self, team_id: int) -> Optional[Row]:
sql = select(team).where(team.c.id == team_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_team_rank(self, team_id: int) -> int:
async def get_team_rank(self, team_id: int) -> int:
# Normal ranking system, likely the one used in the real servers
# Query all teams sorted by 'teamPoint'
result = self.execute(
result = await self.execute(
select(team.c.id).order_by(team.c.teamPoint.desc())
)
@@ -666,13 +666,13 @@ class ChuniProfileData(BaseData):
# RIP scaled team ranking. Gone, but forgotten
# def get_team_rank_scaled(self, team_id: int) -> int:
def update_team(self, team_id: int, team_data: Dict) -> bool:
async def update_team(self, team_id: int, team_data: Dict) -> bool:
team_data["id"] = team_id
sql = insert(team).values(**team_data)
conflict = sql.on_duplicate_key_update(**team_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(
@@ -680,16 +680,16 @@ class ChuniProfileData(BaseData):
)
return False
return True
def get_rival(self, rival_id: int) -> Optional[Row]:
async def get_rival(self, rival_id: int) -> Optional[Row]:
sql = select(profile).where(profile.c.user == rival_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_overview(self) -> Dict:
async def get_overview(self) -> Dict:
# Fetch and add up all the playcounts
playcount_sql = self.execute(select(profile.c.playCount))
playcount_sql = await self.execute(select(profile.c.playCount))
if playcount_sql is None:
self.logger.warn(

View File

@@ -142,55 +142,55 @@ playlog = Table(
class ChuniScoreData(BaseData):
def get_courses(self, aime_id: int) -> Optional[Row]:
async def get_courses(self, aime_id: int) -> Optional[Row]:
sql = select(course).where(course.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_course(self, aime_id: int, course_data: Dict) -> Optional[int]:
async def put_course(self, aime_id: int, course_data: Dict) -> Optional[int]:
course_data["user"] = aime_id
course_data = self.fix_bools(course_data)
sql = insert(course).values(**course_data)
conflict = sql.on_duplicate_key_update(**course_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_scores(self, aime_id: int) -> Optional[Row]:
async def get_scores(self, aime_id: int) -> Optional[Row]:
sql = select(best_score).where(best_score.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_score(self, aime_id: int, score_data: Dict) -> Optional[int]:
async def put_score(self, aime_id: int, score_data: Dict) -> Optional[int]:
score_data["user"] = aime_id
score_data = self.fix_bools(score_data)
sql = insert(best_score).values(**score_data)
conflict = sql.on_duplicate_key_update(**score_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_playlogs(self, aime_id: int) -> Optional[Row]:
async def get_playlogs(self, aime_id: int) -> Optional[Row]:
sql = select(playlog).where(playlog.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_playlog(self, aime_id: int, playlog_data: Dict, version: int) -> Optional[int]:
async def put_playlog(self, aime_id: int, playlog_data: Dict, version: int) -> Optional[int]:
# Calculate the ROM version that should be inserted into the DB, based on the version of the ggame being inserted
# We only need from Version 10 (Plost) and back, as newer versions include romVersion in their upsert
# This matters both for gameRankings, as well as a future DB update to keep version data separate
@@ -216,12 +216,12 @@ class ChuniScoreData(BaseData):
sql = insert(playlog).values(**playlog_data)
conflict = sql.on_duplicate_key_update(**playlog_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_rankings(self, version: int) -> Optional[List[Dict]]:
async def get_rankings(self, version: int) -> Optional[List[Dict]]:
# Calculates the ROM version that should be fetched for rankings, based on the game version being retrieved
# This prevents tracks that are not accessible in your version from counting towards the 10 results
romVer = {
@@ -241,7 +241,7 @@ class ChuniScoreData(BaseData):
0: "1.00%"
}
sql = select([playlog.c.musicId.label('id'), func.count(playlog.c.musicId).label('point')]).where((playlog.c.level != 4) & (playlog.c.romVersion.like(romVer.get(version, "%")))).group_by(playlog.c.musicId).order_by(func.count(playlog.c.musicId).desc()).limit(10)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
@@ -249,10 +249,10 @@ class ChuniScoreData(BaseData):
rows = result.fetchall()
return [dict(row) for row in rows]
def get_rival_music(self, rival_id: int) -> Optional[List[Dict]]:
async def get_rival_music(self, rival_id: int) -> Optional[List[Dict]]:
sql = select(best_score).where(best_score.c.user == rival_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()

View File

@@ -175,7 +175,7 @@ login_bonus = Table(
class ChuniStaticData(BaseData):
def put_login_bonus(
async def put_login_bonus(
self,
version: int,
preset_id: int,
@@ -207,12 +207,12 @@ class ChuniStaticData(BaseData):
loginBonusCategoryType=login_bonus_category_type,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_login_bonus(
async def get_login_bonus(
self,
version: int,
preset_id: int,
@@ -224,12 +224,12 @@ class ChuniStaticData(BaseData):
)
).order_by(login_bonus.c.needLoginDayCount.desc())
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_login_bonus_by_required_days(
async def get_login_bonus_by_required_days(
self, version: int, preset_id: int, need_login_day_count: int
) -> Optional[Row]:
sql = login_bonus.select(
@@ -240,12 +240,12 @@ class ChuniStaticData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_login_bonus_preset(
async def put_login_bonus_preset(
self, version: int, preset_id: int, preset_name: str, is_enabled: bool
) -> Optional[int]:
sql = insert(login_bonus_preset).values(
@@ -259,12 +259,12 @@ class ChuniStaticData(BaseData):
presetName=preset_name, isEnabled=is_enabled
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_login_bonus_presets(
async def get_login_bonus_presets(
self, version: int, is_enabled: bool = True
) -> Optional[List[Row]]:
sql = login_bonus_preset.select(
@@ -274,12 +274,12 @@ class ChuniStaticData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_event(
async def put_event(
self, version: int, event_id: int, type: int, name: str
) -> Optional[int]:
sql = insert(events).values(
@@ -288,19 +288,19 @@ class ChuniStaticData(BaseData):
conflict = sql.on_duplicate_key_update(name=name)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def update_event(
async 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)
result = await self.execute(sql)
if result is None:
self.logger.warning(
f"update_event: failed to update event! version: {version}, event_id: {event_id}, enabled: {enabled}"
@@ -315,35 +315,35 @@ class ChuniStaticData(BaseData):
return None
return event["enabled"]
def get_event(self, version: int, event_id: int) -> Optional[Row]:
async 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)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_enabled_events(self, version: int) -> Optional[List[Row]]:
async def get_enabled_events(self, version: int) -> Optional[List[Row]]:
sql = select(events).where(
and_(events.c.version == version, events.c.enabled == True)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_events(self, version: int) -> Optional[List[Row]]:
async def get_events(self, version: int) -> Optional[List[Row]]:
sql = select(events).where(events.c.version == version)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_music(
async def put_music(
self,
version: int,
song_id: int,
@@ -376,12 +376,12 @@ class ChuniStaticData(BaseData):
worldsEndTag=we_tag,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def put_charge(
async def put_charge(
self,
version: int,
charge_id: int,
@@ -406,38 +406,38 @@ class ChuniStaticData(BaseData):
sellingAppeal=selling_appeal,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_enabled_charges(self, version: int) -> Optional[List[Row]]:
async def get_enabled_charges(self, version: int) -> Optional[List[Row]]:
sql = select(charge).where(
and_(charge.c.version == version, charge.c.enabled == True)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_charges(self, version: int) -> Optional[List[Row]]:
async def get_charges(self, version: int) -> Optional[List[Row]]:
sql = select(charge).where(charge.c.version == version)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_music(self, version: int) -> Optional[List[Row]]:
async def get_music(self, version: int) -> Optional[List[Row]]:
sql = music.select(music.c.version <= version)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_music_chart(
async def get_music_chart(
self, version: int, song_id: int, chart_id: int
) -> Optional[List[Row]]:
sql = select(music).where(
@@ -448,21 +448,21 @@ class ChuniStaticData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_song(self, music_id: int) -> Optional[Row]:
async def get_song(self, music_id: int) -> Optional[Row]:
sql = music.select(music.c.id == music_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_avatar(
async def put_avatar(
self,
version: int,
avatarAccessoryId: int,
@@ -487,12 +487,12 @@ class ChuniStaticData(BaseData):
texturePath=texturePath,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def put_gacha(
async def put_gacha(
self,
version: int,
gacha_id: int,
@@ -513,33 +513,33 @@ class ChuniStaticData(BaseData):
**gacha_data,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"Failed to insert gacha! gacha_id {gacha_id}")
return None
return result.lastrowid
def get_gachas(self, version: int) -> Optional[List[Dict]]:
async def get_gachas(self, version: int) -> Optional[List[Dict]]:
sql = gachas.select(gachas.c.version <= version).order_by(
gachas.c.gachaId.asc()
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_gacha(self, version: int, gacha_id: int) -> Optional[Dict]:
async def get_gacha(self, version: int, gacha_id: int) -> Optional[Dict]:
sql = gachas.select(
and_(gachas.c.version <= version, gachas.c.gachaId == gacha_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_gacha_card(
async def put_gacha_card(
self, gacha_id: int, card_id: int, **gacha_card
) -> Optional[int]:
sql = insert(gacha_cards).values(gachaId=gacha_id, cardId=card_id, **gacha_card)
@@ -548,21 +548,21 @@ class ChuniStaticData(BaseData):
gachaId=gacha_id, cardId=card_id, **gacha_card
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"Failed to insert gacha card! gacha_id {gacha_id}")
return None
return result.lastrowid
def get_gacha_cards(self, gacha_id: int) -> Optional[List[Dict]]:
async def get_gacha_cards(self, gacha_id: int) -> Optional[List[Dict]]:
sql = gacha_cards.select(gacha_cards.c.gachaId == gacha_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_gacha_card_by_character(
async def get_gacha_card_by_character(
self, gacha_id: int, chara_id: int
) -> Optional[Dict]:
sql_sub = (
@@ -574,26 +574,26 @@ class ChuniStaticData(BaseData):
and_(gacha_cards.c.gachaId == gacha_id, gacha_cards.c.cardId == sql_sub)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_card(self, version: int, card_id: int, **card_data) -> Optional[int]:
async def put_card(self, version: int, card_id: int, **card_data) -> Optional[int]:
sql = insert(cards).values(version=version, cardId=card_id, **card_data)
conflict = sql.on_duplicate_key_update(**card_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"Failed to insert card! card_id {card_id}")
return None
return result.lastrowid
def get_card(self, version: int, card_id: int) -> Optional[Dict]:
async def get_card(self, version: int, card_id: int) -> Optional[Dict]:
sql = cards.select(and_(cards.c.version <= version, cards.c.cardId == card_id))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()

View File

@@ -11,7 +11,7 @@ class ChuniStar(ChuniBase):
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)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.20.00"
return ret

View File

@@ -11,7 +11,7 @@ class ChuniStarPlus(ChuniBase):
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)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.25.00"
return ret

View File

@@ -11,8 +11,8 @@ class ChuniSun(ChuniNewPlus):
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_SUN
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = super().handle_cm_get_user_preview_api_request(data)
async def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = await super().handle_cm_get_user_preview_api_request(data)
# hardcode lastDataVersion for CardMaker 1.35 A032
user_data["lastDataVersion"] = "2.10.00"

View File

@@ -11,8 +11,8 @@ class ChuniSunPlus(ChuniSun):
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_SUN_PLUS
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = super().handle_cm_get_user_preview_api_request(data)
async def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = await super().handle_cm_get_user_preview_api_request(data)
# I don't know if lastDataVersion is going to matter, I don't think CardMaker 1.35 works this far up
user_data["lastDataVersion"] = "2.15.00"

View File

@@ -6,7 +6,4 @@ from titles.cm.database import CardMakerData
index = CardMakerServlet
reader = CardMakerReader
database = CardMakerData
game_codes = [CardMakerConstants.GAME_CODE]
current_schema_version = 1

View File

@@ -29,11 +29,11 @@ class CardMakerBase:
def _parse_int_ver(version: str) -> str:
return version.replace(".", "")[:3]
def handle_get_game_connect_api_request(self, data: Dict) -> Dict:
async def handle_get_game_connect_api_request(self, data: Dict) -> Dict:
if not self.core_cfg.server.is_using_proxy and Utils.get_title_port(self.core_cfg) != 80:
uri = f"http://{self.core_cfg.title.hostname}:{Utils.get_title_port(self.core_cfg)}"
uri = f"http://{self.core_cfg.server.hostname}:{Utils.get_title_port(self.core_cfg)}"
else:
uri = f"http://{self.core_cfg.title.hostname}"
uri = f"http://{self.core_cfg.server.hostname}"
# grab the dict with all games version numbers from user config
games_ver = self.game_cfg.version.version(self.version)
@@ -62,7 +62,7 @@ class CardMakerBase:
],
}
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
# if reboot start/end time is not defined use the default behavior of being a few hours ago
if self.core_cfg.title.reboot_start_time == "" or self.core_cfg.title.reboot_end_time == "":
reboot_start = datetime.strftime(
@@ -110,11 +110,11 @@ class CardMakerBase:
"isAou": False,
}
def handle_get_client_bookkeeping_api_request(self, data: Dict) -> Dict:
async def handle_get_client_bookkeeping_api_request(self, data: Dict) -> Dict:
return {"placeId": data["placeId"], "length": 0, "clientBookkeepingList": []}
def handle_upsert_client_setting_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_setting_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "UpsertClientSettingApi"}
def handle_upsert_client_bookkeeping_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_bookkeeping_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "UpsertClientBookkeepingApi"}

View File

@@ -12,7 +12,7 @@ class CardMaker135(CardMakerBase):
super().__init__(core_cfg, game_cfg)
self.version = CardMakerConstants.VER_CARD_MAKER_135
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.35.00"
return ret

View File

@@ -5,10 +5,11 @@ import string
import logging
import coloredlogs
import zlib
from starlette.routing import Route
from starlette.responses import Response
from starlette.requests import Request
from os import path
from typing import Tuple, List, Dict
from twisted.web.http import Request
from typing import List
from logging.handlers import TimedRotatingFileHandler
from core.config import CoreConfig
@@ -19,7 +20,6 @@ from .const import CardMakerConstants
from .base import CardMakerBase
from .cm135 import CardMaker135
class CardMakerServlet(BaseServlet):
def __init__(self, core_cfg: CoreConfig, cfg_dir: str) -> None:
super().__init__(core_cfg, cfg_dir)
@@ -72,16 +72,15 @@ class CardMakerServlet(BaseServlet):
return True
def get_endpoint_matchers(self) -> Tuple[List[Tuple[str, str, Dict]], List[Tuple[str, str, Dict]]]:
return (
[],
[("render_POST", "/SDED/{version}/{endpoint}", {})]
)
def render_POST(self, request: Request, game_code: str, matchers: Dict) -> bytes:
version = int(matchers['version'])
endpoint = matchers['endpoint']
req_raw = request.content.getvalue()
def get_routes(self) -> List[Route]:
return [
Route("/SDED/{version:int}/{endpoint:str}", self.render_POST)
]
async def render_POST(self, request: Request) -> bytes:
version: int = request.path_params.get('version')
endpoint: str = request.path_params.get('endpoint')
req_raw = await request.body()
internal_ver = 0
client_ip = Utils.get_ip_addr(request)
@@ -103,7 +102,7 @@ class CardMakerServlet(BaseServlet):
self.logger.error(
f"Failed to decompress v{version} {endpoint} request -> {e}"
)
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
req_data = json.loads(unzip)
@@ -114,7 +113,7 @@ class CardMakerServlet(BaseServlet):
if not hasattr(self.versions[internal_ver], func_to_find):
self.logger.warning(f"Unhandled v{version} request {endpoint}")
return zlib.compress(b'{"returnCode": 1}')
return Response(zlib.compress(b'{"returnCode": 1}'))
try:
handler = getattr(self.versions[internal_ver], func_to_find)
@@ -123,11 +122,11 @@ class CardMakerServlet(BaseServlet):
except Exception as e:
self.logger.error(f"Error handling v{version} method {endpoint} - {e}")
raise
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
if resp is None:
resp = {"returnCode": 1}
self.logger.debug(f"Response {resp}")
return zlib.compress(json.dumps(resp, ensure_ascii=False).encode("utf-8"))
return Response(zlib.compress(json.dumps(resp, ensure_ascii=False).encode("utf-8")))

View File

@@ -50,7 +50,7 @@ class CardMakerReader(BaseReader):
):
return f"{root}/{dir}"
def read(self) -> None:
async def read(self) -> None:
static_datas = {
"static_gachas.csv": "read_ongeki_gacha_csv",
"static_gacha_cards.csv": "read_ongeki_gacha_card_csv",
@@ -66,7 +66,7 @@ class CardMakerReader(BaseReader):
for file, func in static_datas.items():
if os.path.exists(f"{self.bin_dir}/MU3/{file}"):
read_csv = getattr(CardMakerReader, func)
read_csv(self, f"{self.bin_dir}/MU3/{file}")
await read_csv(self, f"{self.bin_dir}/MU3/{file}")
else:
self.logger.warning(
f"Couldn't find {file} file in {self.bin_dir}, skipping"
@@ -78,12 +78,12 @@ class CardMakerReader(BaseReader):
# ONGEKI (MU3) cnnot easily access the bin data(A000.pac)
# so only opt_dir will work for now
for dir in data_dirs:
self.read_chuni_card(f"{dir}/CHU/card")
self.read_chuni_gacha(f"{dir}/CHU/gacha")
self.read_mai2_card(f"{dir}/MAI/card")
self.read_ongeki_gacha(f"{dir}/MU3/gacha")
await self.read_chuni_card(f"{dir}/CHU/card")
await self.read_chuni_gacha(f"{dir}/CHU/gacha")
await self.read_mai2_card(f"{dir}/MAI/card")
await self.read_ongeki_gacha(f"{dir}/MU3/gacha")
def read_chuni_card(self, base_dir: str) -> None:
async def read_chuni_card(self, base_dir: str) -> None:
self.logger.info(f"Reading cards from {base_dir}...")
version_ids = {
@@ -114,7 +114,7 @@ class CardMakerReader(BaseReader):
chain = int(troot.find("chain").text)
skill_name = troot.find("skillName").text
self.chuni_data.static.put_card(
await self.chuni_data.static.put_card(
version,
card_id,
charaName=chara_name,
@@ -131,7 +131,7 @@ class CardMakerReader(BaseReader):
self.logger.info(f"Added chuni card {card_id}")
def read_chuni_gacha(self, base_dir: str) -> None:
async def read_chuni_gacha(self, base_dir: str) -> None:
self.logger.info(f"Reading gachas from {base_dir}...")
version_ids = {
@@ -158,7 +158,7 @@ class CardMakerReader(BaseReader):
True if troot.find("ceilingType").text == "1" else False
)
self.chuni_data.static.put_gacha(
await self.chuni_data.static.put_gacha(
version,
gacha_id,
name,
@@ -181,7 +181,7 @@ class CardMakerReader(BaseReader):
True if gacha_card.find("pickup").text == "1" else False
)
self.chuni_data.static.put_gacha_card(
await self.chuni_data.static.put_gacha_card(
gacha_id,
card_id,
weight=weight,
@@ -193,7 +193,7 @@ class CardMakerReader(BaseReader):
f"Added chuni card {card_id} to gacha {gacha_id}"
)
def read_mai2_card(self, base_dir: str) -> None:
async def read_mai2_card(self, base_dir: str) -> None:
self.logger.info(f"Reading cards from {base_dir}...")
version_ids = {
@@ -231,18 +231,18 @@ class CardMakerReader(BaseReader):
False if re.search(r"\d{2}/\d{2}/\d{2}", name) else enabled
)
self.mai2_data.static.put_card(
await self.mai2_data.static.put_card(
version, card_id, name, enabled=enabled
)
self.logger.info(f"Added mai2 card {card_id}")
def read_ongeki_gacha_csv(self, file_path: str) -> None:
async def read_ongeki_gacha_csv(self, file_path: str) -> None:
self.logger.info(f"Reading gachas from {file_path}...")
with open(file_path, encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
self.ongeki_data.static.put_gacha(
await self.ongeki_data.static.put_gacha(
row["version"],
row["gachaId"],
row["gachaName"],
@@ -254,13 +254,13 @@ class CardMakerReader(BaseReader):
self.logger.info(f"Added ongeki gacha {row['gachaId']}")
def read_ongeki_gacha_card_csv(self, file_path: str) -> None:
async def read_ongeki_gacha_card_csv(self, file_path: str) -> None:
self.logger.info(f"Reading gacha cards from {file_path}...")
with open(file_path, encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
self.ongeki_data.static.put_gacha_card(
await self.ongeki_data.static.put_gacha_card(
row["gachaId"],
row["cardId"],
rarity=row["rarity"],
@@ -271,7 +271,7 @@ class CardMakerReader(BaseReader):
self.logger.info(f"Added ongeki card {row['cardId']} to gacha")
def read_ongeki_gacha(self, base_dir: str) -> None:
async def read_ongeki_gacha(self, base_dir: str) -> None:
self.logger.info(f"Reading gachas from {base_dir}...")
# assuming some GachaKinds based on the GachaType
@@ -294,7 +294,7 @@ class CardMakerReader(BaseReader):
# skip already existing gachas
if (
self.ongeki_data.static.get_gacha(
await self.ongeki_data.static.get_gacha(
OngekiConstants.VER_ONGEKI_BRIGHT_MEMORY, gacha_id
)
is not None
@@ -320,7 +320,7 @@ class CardMakerReader(BaseReader):
is_ceiling = 1
max_select_point = 33
self.ongeki_data.static.put_gacha(
await self.ongeki_data.static.put_gacha(
version,
gacha_id,
name,

View File

@@ -7,4 +7,3 @@ index = CxbServlet
database = CxbData
reader = CxbReader
game_codes = [CxbConstants.GAME_CODE]
current_schema_version = 1

View File

@@ -28,14 +28,14 @@ class CxbBase:
return []
def handle_action_rpreq_request(self, data: Dict) -> Dict:
async def handle_action_rpreq_request(self, data: Dict) -> Dict:
return {}
def handle_action_hitreq_request(self, data: Dict) -> Dict:
async def handle_action_hitreq_request(self, data: Dict) -> Dict:
return {"data": []}
def handle_auth_usercheck_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile_index(
async def handle_auth_usercheck_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile_index(
0, data["usercheck"]["authid"], self.version
)
if profile is not None:
@@ -45,12 +45,12 @@ class CxbBase:
self.logger.info(f"No profile for aime id {data['usercheck']['authid']}")
return {"exist": "false", "logout": "true"}
def handle_auth_entry_request(self, data: Dict) -> Dict:
async def handle_auth_entry_request(self, data: Dict) -> Dict:
self.logger.info(f"New profile for {data['entry']['authid']}")
return {"token": data["entry"]["authid"], "uid": data["entry"]["authid"]}
def handle_auth_login_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile_index(
async def handle_auth_login_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile_index(
0, data["login"]["authid"], self.version
)
@@ -198,14 +198,14 @@ class CxbBase:
).decode("utf-8")
)
def handle_action_loadrange_request(self, data: Dict) -> Dict:
async def handle_action_loadrange_request(self, data: Dict) -> Dict:
range_start = data["loadrange"]["range"][0]
range_end = data["loadrange"]["range"][1]
uid = data["loadrange"]["uid"]
self.logger.info(f"Load data for {uid}")
profile = self.data.profile.get_profile(uid, self.version)
songs = self.data.score.get_best_scores(uid)
profile = await self.data.profile.get_profile(uid, self.version)
songs = await self.data.score.get_best_scores(uid)
data1 = []
index = []
@@ -271,7 +271,7 @@ class CxbBase:
thread_ScoreData = Thread(target=CxbBase.task_generateScoreData(song, index, data1))
thread_ScoreData.start()
v_profile = self.data.profile.get_profile_index(0, uid, self.version)
v_profile = await self.data.profile.get_profile_index(0, uid, self.version)
v_profile_data = v_profile["data"]
for _, data in enumerate(profile):
@@ -282,7 +282,7 @@ class CxbBase:
return {"index": index, "data": data1, "version": versionindex}
def handle_action_saveindex_request(self, data: Dict) -> Dict:
async def handle_action_saveindex_request(self, data: Dict) -> Dict:
save_data = data["saveindex"]
try:
@@ -300,11 +300,11 @@ class CxbBase:
for value in data["saveindex"]["data"]:
if "playedUserId" in value[1]:
self.data.profile.put_profile(
await self.data.profile.put_profile(
data["saveindex"]["uid"], self.version, value[0], value[1]
)
if "mcode" not in value[1]:
self.data.profile.put_profile(
await self.data.profile.put_profile(
data["saveindex"]["uid"], self.version, value[0], value[1]
)
if "shopId" in value:
@@ -335,7 +335,7 @@ class CxbBase:
"index": value[0],
}
)
self.data.score.put_best_score(
await self.data.score.put_best_score(
data["saveindex"]["uid"],
song_json["mcode"],
self.version,
@@ -360,32 +360,32 @@ class CxbBase:
for index, value in enumerate(data["saveindex"]["data"]):
if int(data["saveindex"]["index"][index]) == 101:
self.data.profile.put_profile(
await self.data.profile.put_profile(
aimeId, self.version, data["saveindex"]["index"][index], value
)
if (
int(data["saveindex"]["index"][index]) >= 700000
and int(data["saveindex"]["index"][index]) <= 701000
):
self.data.profile.put_profile(
await self.data.profile.put_profile(
aimeId, self.version, data["saveindex"]["index"][index], value
)
if (
int(data["saveindex"]["index"][index]) >= 500
and int(data["saveindex"]["index"][index]) <= 510
):
self.data.profile.put_profile(
await self.data.profile.put_profile(
aimeId, self.version, data["saveindex"]["index"][index], value
)
if "playedUserId" in value:
self.data.profile.put_profile(
await self.data.profile.put_profile(
aimeId,
self.version,
data["saveindex"]["index"][index],
json.loads(value),
)
if "mcode" not in value and "normalCR" not in value:
self.data.profile.put_profile(
await self.data.profile.put_profile(
aimeId,
self.version,
data["saveindex"]["index"][index],
@@ -437,16 +437,16 @@ class CxbBase:
}
)
self.data.score.put_best_score(
await self.data.score.put_best_score(
aimeId, data1["mcode"], self.version, indexSongList[i], songCode[0]
)
i += 1
return {}
def handle_action_sprankreq_request(self, data: Dict) -> Dict:
async def handle_action_sprankreq_request(self, data: Dict) -> Dict:
uid = data["sprankreq"]["uid"]
self.logger.info(f"Get best rankings for {uid}")
p = self.data.score.get_best_rankings(uid)
p = await self.data.score.get_best_rankings(uid)
rankList: List[Dict[str, Any]] = []
@@ -475,16 +475,16 @@ class CxbBase:
"rankx": [1, 1, 1],
}
def handle_action_getadv_request(self, data: Dict) -> Dict:
async def handle_action_getadv_request(self, data: Dict) -> Dict:
return {"data": [{"r": "1", "i": "100300", "c": "20"}]}
def handle_action_getmsg_request(self, data: Dict) -> Dict:
async def handle_action_getmsg_request(self, data: Dict) -> Dict:
return {"msgs": []}
def handle_auth_logout_request(self, data: Dict) -> Dict:
async def handle_auth_logout_request(self, data: Dict) -> Dict:
return {"auth": True}
def handle_action_rankreg_request(self, data: Dict) -> Dict:
async def handle_action_rankreg_request(self, data: Dict) -> Dict:
uid = data["rankreg"]["uid"]
self.logger.info(f"Put {len(data['rankreg']['data'])} rankings for {uid}")
@@ -492,7 +492,7 @@ class CxbBase:
# REV S2
if "clear" in rid:
try:
self.data.score.put_ranking(
await self.data.score.put_ranking(
user_id=uid,
rev_id=int(rid["rid"]),
song_id=int(rid["sc"][1]),
@@ -500,7 +500,7 @@ class CxbBase:
clear=rid["clear"],
)
except Exception:
self.data.score.put_ranking(
await self.data.score.put_ranking(
user_id=uid,
rev_id=int(rid["rid"]),
song_id=0,
@@ -510,7 +510,7 @@ class CxbBase:
# REV
else:
try:
self.data.score.put_ranking(
await self.data.score.put_ranking(
user_id=uid,
rev_id=int(rid["rid"]),
song_id=int(rid["sc"][1]),
@@ -518,7 +518,7 @@ class CxbBase:
clear=0,
)
except Exception:
self.data.score.put_ranking(
await self.data.score.put_ranking(
user_id=uid,
rev_id=int(rid["rid"]),
song_id=0,
@@ -527,15 +527,15 @@ class CxbBase:
)
return {}
def handle_action_addenergy_request(self, data: Dict) -> Dict:
async def handle_action_addenergy_request(self, data: Dict) -> Dict:
uid = data["addenergy"]["uid"]
self.logger.info(f"Add energy to user {uid}")
profile = self.data.profile.get_profile_index(0, uid, self.version)
profile = await self.data.profile.get_profile_index(0, uid, self.version)
data1 = profile["data"]
p = self.data.item.get_energy(uid)
p = await self.data.item.get_energy(uid)
if not p:
self.data.item.put_energy(uid, 5)
await self.data.item.put_energy(uid, 5)
return {
"class": data1["myClass"],
@@ -548,7 +548,7 @@ class CxbBase:
energy = p["energy"]
newenergy = int(energy) + 5
self.data.item.put_energy(uid, newenergy)
await self.data.item.put_energy(uid, newenergy)
if int(energy) <= 995:
array.append(
@@ -570,10 +570,10 @@ class CxbBase:
)
return array[0]
def handle_action_eventreq_request(self, data: Dict) -> Dict:
async def handle_action_eventreq_request(self, data: Dict) -> Dict:
self.logger.info(data)
return {"eventreq": ""}
def handle_action_stampreq_request(self, data: Dict) -> Dict:
async def handle_action_stampreq_request(self, data: Dict) -> Dict:
self.logger.info(data)
return {"stampreq": ""}

View File

@@ -18,6 +18,12 @@ class CxbServerConfig:
self.__config, "cxb", "server", "loglevel", default="info"
)
)
@property
def use_https(self) -> bool:
return CoreConfig.get_config_field(
self.__config, "cxb", "server", "use_https", default=True
)
class CxbConfig(dict):

View File

@@ -1,4 +1,6 @@
from twisted.web.http import Request
from starlette.requests import Request
from starlette.routing import Route
from starlette.responses import Response, JSONResponse
import traceback
import sys
import yaml
@@ -11,7 +13,7 @@ from typing import Dict, Tuple, List
from os import path
from core.config import CoreConfig
from core.title import BaseServlet
from core.title import BaseServlet, JSONResponseNoASCII
from core.utils import Utils
from .config import CxbConfig
from .const import CxbConstants
@@ -62,6 +64,14 @@ class CxbServlet(BaseServlet):
CxbRevSunriseS2(core_cfg, self.game_cfg),
]
def get_routes(self) -> List[Route]:
return [
Route("/data", self.handle_data, methods=['POST']),
Route("/action", self.handle_action, methods=['POST']),
Route("/v2/action", self.handle_action, methods=['POST']),
Route("/auth", self.handle_auth, methods=['POST']),
]
@classmethod
def is_game_enabled(cls, game_code: str, core_cfg: CoreConfig, cfg_dir: str) -> bool:
game_cfg = CxbConfig()
@@ -79,35 +89,22 @@ class CxbServlet(BaseServlet):
title_port_int = Utils.get_title_port(self.core_cfg)
title_port_ssl_int = Utils.get_title_port_ssl(self.core_cfg)
proto = "https" if title_port_ssl_int != 443 else "http"
proto = "https" if self.game_cfg.server.use_https else "http"
if proto == "https":
t_port = f":{title_port_ssl_int}" if title_port_ssl_int and not self.core_cfg.server.is_using_proxy else ""
t_port = f":{title_port_ssl_int}" if title_port_ssl_int != 443 else ""
else:
t_port = f":{title_port_int}" if title_port_int and not self.core_cfg.server.is_using_proxy else ""
t_port = f":{title_port_int}" if title_port_int != 80 else ""
return (
f"{proto}://{self.core_cfg.title.hostname}{t_port}",
"",
)
def get_endpoint_matchers(self) -> Tuple[List[Tuple[str, str, Dict]], List[Tuple[str, str, Dict]]]:
return (
[],
[
("handle_data", "/data", {}),
("handle_action", "/action", {}),
("handle_action", "/v2/action", {}),
("handle_auth", "/auth", {}),
]
)
def preprocess(self, req: Request) -> Dict:
try:
req_bytes = req.content.getvalue()
except:
req_bytes = req.content.read() # Can we just use this one?
async def preprocess(self, req: Request) -> Dict:
req_bytes = await req.body()
try:
req_json: Dict = json.loads(req_bytes)
@@ -126,8 +123,8 @@ class CxbServlet(BaseServlet):
return req_json
def handle_data(self, request: Request, game_code: str, matchers: Dict) -> bytes:
req_json = self.preprocess(request)
async def handle_data(self, request: Request) -> bytes:
req_json = await self.preprocess(request)
func_to_find = "handle_data_"
version_string = "Base"
internal_ver = 0
@@ -135,7 +132,7 @@ class CxbServlet(BaseServlet):
if req_json == {}:
self.logger.warning(f"Empty json request to /data")
return b""
return Response()
subcmd = list(req_json.keys())[0]
if subcmd == "dldate":
@@ -145,14 +142,14 @@ class CxbServlet(BaseServlet):
or "filetype" not in req_json["dldate"]
):
self.logger.warning(f"Malformed dldate request: {req_json}")
return b""
return Response()
filetype = req_json["dldate"]["filetype"]
filetype_split = filetype.split("/")
if len(filetype_split) < 2 or not filetype_split[0].isnumeric():
self.logger.warning(f"Malformed dldate request: {req_json}")
return b""
return Response()
version = int(filetype_split[0])
filename = filetype_split[len(filetype_split) - 1]
@@ -184,7 +181,7 @@ class CxbServlet(BaseServlet):
if not hasattr(self.versions[internal_ver], func_to_find):
self.logger.warn(f"{version_string} has no handler for filetype {filetype} / {func_to_find}")
return({"data":""})
return JSONResponse({"data":""})
self.logger.info(f"{version_string} request for filetype {filetype}")
self.logger.debug(req_json)
@@ -192,7 +189,7 @@ class CxbServlet(BaseServlet):
handler = getattr(self.versions[internal_ver], func_to_find)
try:
resp = handler(req_json)
resp = await handler(req_json)
except Exception as e:
self.logger.error(f"Error handling request for file {filetype} - {e}")
@@ -201,19 +198,19 @@ class CxbServlet(BaseServlet):
traceback.print_exception(tp, val, tb, limit=1)
with open("{0}/{1}.log".format(self.core_cfg.server.log_dir, "cxb"), "a") as f:
traceback.print_exception(tp, val, tb, limit=1, file=f)
return ""
return Response()
self.logger.debug(f"{version_string} Response {resp}")
return json.dumps(resp, ensure_ascii=False).encode("utf-8")
return JSONResponseNoASCII(resp)
def handle_action(self, request: Request, game_code: str, matchers: Dict) -> bytes:
req_json = self.preprocess(request)
async def handle_action(self, request: Request) -> bytes:
req_json = await self.preprocess(request)
subcmd = list(req_json.keys())[0]
func_to_find = f"handle_action_{subcmd}_request"
if not hasattr(self.versions[0], func_to_find):
self.logger.warn(f"No handler for action {subcmd} request")
return ""
return Response()
self.logger.info(f"Action {subcmd} Request")
self.logger.debug(req_json)
@@ -221,7 +218,7 @@ class CxbServlet(BaseServlet):
handler = getattr(self.versions[0], func_to_find)
try:
resp = handler(req_json)
resp = await handler(req_json)
except Exception as e:
self.logger.error(f"Error handling action {subcmd} request - {e}")
@@ -230,19 +227,19 @@ class CxbServlet(BaseServlet):
traceback.print_exception(tp, val, tb, limit=1)
with open("{0}/{1}.log".format(self.core_cfg.server.log_dir, "cxb"), "a") as f:
traceback.print_exception(tp, val, tb, limit=1, file=f)
return ""
return Response()
self.logger.debug(f"Response {resp}")
return json.dumps(resp, ensure_ascii=False).encode("utf-8")
return JSONResponseNoASCII(resp)
def handle_auth(self, request: Request, game_code: str, matchers: Dict) -> bytes:
req_json = self.preprocess(request)
async def handle_auth(self, request: Request) -> bytes:
req_json = await self.preprocess(request)
subcmd = list(req_json.keys())[0]
func_to_find = f"handle_auth_{subcmd}_request"
if not hasattr(self.versions[0], func_to_find):
self.logger.warn(f"No handler for auth {subcmd} request")
return ""
return Response()
self.logger.info(f"Action {subcmd} Request")
self.logger.debug(req_json)
@@ -250,7 +247,7 @@ class CxbServlet(BaseServlet):
handler = getattr(self.versions[0], func_to_find)
try:
resp = handler(req_json)
resp = await handler(req_json)
except Exception as e:
self.logger.error(f"Error handling auth {subcmd} request - {e}")
@@ -259,7 +256,7 @@ class CxbServlet(BaseServlet):
traceback.print_exception(tp, val, tb, limit=1)
with open("{0}/{1}.log".format(self.core_cfg.server.log_dir, "cxb"), "a") as f:
traceback.print_exception(tp, val, tb, limit=1, file=f)
return ""
return Response()
self.logger.debug(f"Response {resp}")
return json.dumps(resp, ensure_ascii=False).encode("utf-8")
return JSONResponseNoASCII(resp)

View File

@@ -1,6 +1,5 @@
from typing import Optional, Dict, List
from os import walk, path
import urllib
from typing import Optional
from os import path
import csv
from read import BaseReader
@@ -8,7 +7,6 @@ from core.config import CoreConfig
from titles.cxb.database import CxbData
from titles.cxb.const import CxbConstants
class CxbReader(BaseReader):
def __init__(
self,
@@ -29,17 +27,14 @@ class CxbReader(BaseReader):
self.logger.error(f"Invalid project cxb version {version}")
exit(1)
def read(self) -> None:
pull_bin_ram = True
async def read(self) -> None:
if path.exists(self.bin_dir):
await self.read_csv(self.bin_dir)
else:
self.logger.warn(f"{self.bin_dir} does not exist, nothing to import")
if not path.exists(f"{self.bin_dir}"):
self.logger.warning(f"Couldn't find csv file in {self.bin_dir}, skipping")
pull_bin_ram = False
if pull_bin_ram:
self.read_csv(f"{self.bin_dir}")
def read_csv(self, bin_dir: str) -> None:
async def read_csv(self, bin_dir: str) -> None:
self.logger.info(f"Read csv from {bin_dir}")
try:
@@ -55,7 +50,7 @@ class CxbReader(BaseReader):
if not "N/A" in row["standard"]:
self.logger.info(f"Added song {song_id} chart 0")
self.data.static.put_music(
await self.data.static.put_music(
self.version,
song_id,
index,
@@ -71,7 +66,7 @@ class CxbReader(BaseReader):
)
if not "N/A" in row["hard"]:
self.logger.info(f"Added song {song_id} chart 1")
self.data.static.put_music(
await self.data.static.put_music(
self.version,
song_id,
index,
@@ -83,7 +78,7 @@ class CxbReader(BaseReader):
)
if not "N/A" in row["master"]:
self.logger.info(f"Added song {song_id} chart 2")
self.data.static.put_music(
await self.data.static.put_music(
self.version,
song_id,
index,
@@ -97,7 +92,7 @@ class CxbReader(BaseReader):
)
if not "N/A" in row["unlimited"]:
self.logger.info(f"Added song {song_id} chart 3")
self.data.static.put_music(
await self.data.static.put_music(
self.version,
song_id,
index,
@@ -113,7 +108,7 @@ class CxbReader(BaseReader):
)
if not "N/A" in row["easy"]:
self.logger.info(f"Added song {song_id} chart 4")
self.data.static.put_music(
await self.data.static.put_music(
self.version,
song_id,
index,

View File

@@ -17,15 +17,15 @@ class CxbRev(CxbBase):
super().__init__(cfg, game_cfg)
self.version = CxbConstants.VER_CROSSBEATS_REV
def handle_data_path_list_request(self, data: Dict) -> Dict:
async def handle_data_path_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_putlog_request(self, data: Dict) -> Dict:
async def handle_data_putlog_request(self, data: Dict) -> Dict:
if data["putlog"]["type"] == "ResultLog":
score_data = json.loads(data["putlog"]["data"])
userid = score_data["usid"]
self.data.score.put_playlog(
await self.data.score.put_playlog(
userid,
score_data["mcode"],
score_data["difficulty"],
@@ -45,7 +45,7 @@ class CxbRev(CxbBase):
return {"data": True}
@cached(lifetime=86400)
def handle_data_music_list_request(self, data: Dict) -> Dict:
async def handle_data_music_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/data/rss/MusicArchiveList.csv") as music:
lines = music.readlines()
@@ -56,7 +56,7 @@ class CxbRev(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_item_list_icon_request(self, data: Dict) -> Dict:
async def handle_data_item_list_icon_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ItemListIcon\r\n"
with open(
r"titles/cxb/data/rss/Item/ItemArchiveList_Icon.csv", encoding="utf-8"
@@ -67,7 +67,7 @@ class CxbRev(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_item_list_skin_notes_request(self, data: Dict) -> Dict:
async def handle_data_item_list_skin_notes_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ItemListSkinNotes\r\n"
with open(
r"titles/cxb/data/rss/Item/ItemArchiveList_SkinNotes.csv", encoding="utf-8"
@@ -78,7 +78,7 @@ class CxbRev(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_item_list_skin_effect_request(self, data: Dict) -> Dict:
async def handle_data_item_list_skin_effect_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ItemListSkinEffect\r\n"
with open(
r"titles/cxb/data/rss/Item/ItemArchiveList_SkinEffect.csv", encoding="utf-8"
@@ -89,7 +89,7 @@ class CxbRev(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_item_list_skin_bg_request(self, data: Dict) -> Dict:
async def handle_data_item_list_skin_bg_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ItemListSkinBg\r\n"
with open(
r"titles/cxb/data/rss/Item/ItemArchiveList_SkinBg.csv", encoding="utf-8"
@@ -100,7 +100,7 @@ class CxbRev(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_item_list_title_request(self, data: Dict) -> Dict:
async def handle_data_item_list_title_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ItemListTitle\r\n"
with open(
r"titles/cxb/data/rss/Item/ItemList_Title.csv", encoding="shift-jis"
@@ -111,7 +111,7 @@ class CxbRev(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_shop_list_music_request(self, data: Dict) -> Dict:
async def handle_data_shop_list_music_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ShopListMusic\r\n"
with open(
r"titles/cxb/data/rss/Shop/ShopList_Music.csv", encoding="shift-jis"
@@ -122,7 +122,7 @@ class CxbRev(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_shop_list_icon_request(self, data: Dict) -> Dict:
async def handle_data_shop_list_icon_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ShopListIcon\r\n"
with open(
r"titles/cxb/data/rss/Shop/ShopList_Icon.csv", encoding="shift-jis"
@@ -133,7 +133,7 @@ class CxbRev(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_shop_list_title_request(self, data: Dict) -> Dict:
async def handle_data_shop_list_title_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ShopListTitle\r\n"
with open(
r"titles/cxb/data/rss/Shop/ShopList_Title.csv", encoding="shift-jis"
@@ -143,17 +143,17 @@ class CxbRev(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_shop_list_skin_hud_request(self, data: Dict) -> Dict:
async def handle_data_shop_list_skin_hud_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_shop_list_skin_arrow_request(self, data: Dict) -> Dict:
async def handle_data_shop_list_skin_arrow_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_shop_list_skin_hit_request(self, data: Dict) -> Dict:
async def handle_data_shop_list_skin_hit_request(self, data: Dict) -> Dict:
return {"data": ""}
@cached(lifetime=86400)
def handle_data_shop_list_sale_request(self, data: Dict) -> Dict:
async def handle_data_shop_list_sale_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ShopListSale\r\n"
with open(
r"titles/cxb/data/rss/Shop/ShopList_Sale.csv", encoding="shift-jis"
@@ -163,11 +163,11 @@ class CxbRev(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_extra_stage_list_request(self, data: Dict) -> Dict:
async def handle_data_extra_stage_list_request(self, data: Dict) -> Dict:
return {"data": ""}
@cached(lifetime=86400)
def handle_data_exxxxx_request(self, data: Dict) -> Dict:
async def handle_data_exxxxx_request(self, data: Dict) -> Dict:
extra_num = int(data["dldate"]["filetype"][-4:])
ret_str = ""
with open(
@@ -178,14 +178,14 @@ class CxbRev(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_bonus_list10100_request(self, data: Dict) -> Dict:
async def handle_data_bonus_list10100_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_free_coupon_request(self, data: Dict) -> Dict:
async def handle_data_free_coupon_request(self, data: Dict) -> Dict:
return {"data": ""}
@cached(lifetime=86400)
def handle_data_news_list_request(self, data: Dict) -> Dict:
async def handle_data_news_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/data/rss/NewsList.csv", encoding="UTF-8") as news:
lines = news.readlines()
@@ -193,11 +193,11 @@ class CxbRev(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_tips_request(self, data: Dict) -> Dict:
async def handle_data_tips_request(self, data: Dict) -> Dict:
return {"data": ""}
@cached(lifetime=86400)
def handle_data_license_request(self, data: Dict) -> Dict:
async def handle_data_license_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/data/rss/License_Offline.csv", encoding="UTF-8") as lic:
lines = lic.readlines()
@@ -206,7 +206,7 @@ class CxbRev(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_course_list_request(self, data: Dict) -> Dict:
async def handle_data_course_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(
r"titles/cxb/data/rss/Course/CourseList.csv", encoding="UTF-8"
@@ -217,7 +217,7 @@ class CxbRev(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_csxxxx_request(self, data: Dict) -> Dict:
async def handle_data_csxxxx_request(self, data: Dict) -> Dict:
# Removed the CSVs since the format isnt quite right
extra_num = int(data["dldate"]["filetype"][-4:])
ret_str = ""
@@ -230,7 +230,7 @@ class CxbRev(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_mission_list_request(self, data: Dict) -> Dict:
async def handle_data_mission_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(
r"titles/cxb/data/rss/MissionList.csv", encoding="shift-jis"
@@ -240,14 +240,14 @@ class CxbRev(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_mission_bonus_request(self, data: Dict) -> Dict:
async def handle_data_mission_bonus_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_unlimited_mission_request(self, data: Dict) -> Dict:
async def handle_data_unlimited_mission_request(self, data: Dict) -> Dict:
return {"data": ""}
@cached(lifetime=86400)
def handle_data_event_list_request(self, data: Dict) -> Dict:
async def handle_data_event_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(
r"titles/cxb/data/rss/Event/EventArchiveList.csv", encoding="shift-jis"
@@ -257,39 +257,39 @@ class CxbRev(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_event_music_list_request(self, data: Dict) -> Dict:
async def handle_data_event_music_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_event_mission_list_request(self, data: Dict) -> Dict:
async def handle_data_event_mission_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_event_achievement_single_high_score_list_request(
async def handle_data_event_achievement_single_high_score_list_request(
self, data: Dict
) -> Dict:
return {"data": ""}
def handle_data_event_achievement_single_accumulation_request(
async def handle_data_event_achievement_single_accumulation_request(
self, data: Dict
) -> Dict:
return {"data": ""}
def handle_data_event_ranking_high_score_list_request(self, data: Dict) -> Dict:
async def handle_data_event_ranking_high_score_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_event_ranking_accumulation_list_request(self, data: Dict) -> Dict:
async def handle_data_event_ranking_accumulation_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_event_ranking_stamp_list_request(self, data: Dict) -> Dict:
async def handle_data_event_ranking_stamp_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_event_ranking_store_list_request(self, data: Dict) -> Dict:
async def handle_data_event_ranking_store_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_event_ranking_area_list_request(self, data: Dict) -> Dict:
async def handle_data_event_ranking_area_list_request(self, data: Dict) -> Dict:
return {"data": ""}
@cached(lifetime=86400)
def handle_data_event_stamp_list_request(self, data: Dict) -> Dict:
async def handle_data_event_stamp_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(
r"titles/cxb/data/rss/Event/EventStampList.csv", encoding="shift-jis"
@@ -299,8 +299,8 @@ class CxbRev(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_event_stamp_map_list_csxxxx_request(self, data: Dict) -> Dict:
async def handle_data_event_stamp_map_list_csxxxx_request(self, data: Dict) -> Dict:
return {"data": "1,2,1,1,2,3,9,5,6,7,8,9,10,\r\n"}
def handle_data_server_state_request(self, data: Dict) -> Dict:
async def handle_data_server_state_request(self, data: Dict) -> Dict:
return {"data": True}

View File

@@ -17,11 +17,11 @@ class CxbRevSunriseS1(CxbBase):
super().__init__(cfg, game_cfg)
self.version = CxbConstants.VER_CROSSBEATS_REV_SUNRISE_S1
def handle_data_path_list_request(self, data: Dict) -> Dict:
async def handle_data_path_list_request(self, data: Dict) -> Dict:
return {"data": ""}
@cached(lifetime=86400)
def handle_data_music_list_request(self, data: Dict) -> Dict:
async def handle_data_music_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/data/rss1/MusicArchiveList.csv") as music:
lines = music.readlines()
@@ -32,7 +32,7 @@ class CxbRevSunriseS1(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_item_list_detail_request(self, data: Dict) -> Dict:
async def handle_data_item_list_detail_request(self, data: Dict) -> Dict:
# ItemListIcon load
ret_str = "#ItemListIcon\r\n"
with open(
@@ -54,7 +54,7 @@ class CxbRevSunriseS1(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_shop_list_detail_request(self, data: Dict) -> Dict:
async def handle_data_shop_list_detail_request(self, data: Dict) -> Dict:
# ShopListIcon load
ret_str = "#ShopListIcon\r\n"
with open(
@@ -119,26 +119,26 @@ class CxbRevSunriseS1(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_extra_stage_list_request(self, data: Dict) -> Dict:
async def handle_data_extra_stage_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_exxxxx_request(self, data: Dict) -> Dict:
async def handle_data_exxxxx_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_one_more_extra_list_request(self, data: Dict) -> Dict:
async def handle_data_one_more_extra_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_bonus_list10100_request(self, data: Dict) -> Dict:
async def handle_data_bonus_list10100_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_oexxxx_request(self, data: Dict) -> Dict:
async def handle_data_oexxxx_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_free_coupon_request(self, data: Dict) -> Dict:
async def handle_data_free_coupon_request(self, data: Dict) -> Dict:
return {"data": ""}
@cached(lifetime=86400)
def handle_data_news_list_request(self, data: Dict) -> Dict:
async def handle_data_news_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/data/rss1/NewsList.csv", encoding="UTF-8") as news:
lines = news.readlines()
@@ -146,14 +146,14 @@ class CxbRevSunriseS1(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_tips_request(self, data: Dict) -> Dict:
async def handle_data_tips_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_release_info_list_request(self, data: Dict) -> Dict:
async def handle_data_release_info_list_request(self, data: Dict) -> Dict:
return {"data": ""}
@cached(lifetime=86400)
def handle_data_random_music_list_request(self, data: Dict) -> Dict:
async def handle_data_random_music_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/data/rss1/MusicArchiveList.csv") as music:
lines = music.readlines()
@@ -167,7 +167,7 @@ class CxbRevSunriseS1(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_license_request(self, data: Dict) -> Dict:
async def handle_data_license_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/data/rss1/License.csv", encoding="UTF-8") as licenses:
lines = licenses.readlines()
@@ -176,7 +176,7 @@ class CxbRevSunriseS1(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_course_list_request(self, data: Dict) -> Dict:
async def handle_data_course_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(
r"titles/cxb/data/rss1/Course/CourseList.csv", encoding="UTF-8"
@@ -187,7 +187,7 @@ class CxbRevSunriseS1(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_csxxxx_request(self, data: Dict) -> Dict:
async def handle_data_csxxxx_request(self, data: Dict) -> Dict:
extra_num = int(data["dldate"]["filetype"][-4:])
ret_str = ""
with open(
@@ -198,16 +198,16 @@ class CxbRevSunriseS1(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_mission_list_request(self, data: Dict) -> Dict:
async def handle_data_mission_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_mission_bonus_request(self, data: Dict) -> Dict:
async def handle_data_mission_bonus_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_unlimited_mission_request(self, data: Dict) -> Dict:
async def handle_data_unlimited_mission_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_partner_list_request(self, data: Dict) -> Dict:
async def handle_data_partner_list_request(self, data: Dict) -> Dict:
ret_str = ""
# Lord forgive me for the sins I am about to commit
for i in range(0, 10):
@@ -226,7 +226,7 @@ class CxbRevSunriseS1(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_partnerxxxx_request(self, data: Dict) -> Dict:
async def handle_data_partnerxxxx_request(self, data: Dict) -> Dict:
partner_num = int(data["dldate"]["filetype"][-4:])
ret_str = f"{partner_num},,{partner_num},1,10000,\r\n"
with open(r"titles/cxb/data/rss1/Partner0000.csv") as partner:
@@ -235,13 +235,13 @@ class CxbRevSunriseS1(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_server_state_request(self, data: Dict) -> Dict:
async def handle_data_server_state_request(self, data: Dict) -> Dict:
return {"data": True}
def handle_data_settings_request(self, data: Dict) -> Dict:
async def handle_data_settings_request(self, data: Dict) -> Dict:
return {"data": "2,\r\n"}
def handle_data_story_list_request(self, data: Dict) -> Dict:
async def handle_data_story_list_request(self, data: Dict) -> Dict:
# story id, story name, game version, start time, end time, course arc, unlock flag, song mcode for menu
ret_str = "\r\n"
ret_str += (
@@ -253,23 +253,23 @@ class CxbRevSunriseS1(CxbBase):
ret_str += f"st0002,REMNANT,10104,1502127790,4096483201,Cs1000,-1,overcl,\r\n"
return {"data": ret_str}
def handle_data_stxxxx_request(self, data: Dict) -> Dict:
async def handle_data_stxxxx_request(self, data: Dict) -> Dict:
story_num = int(data["dldate"]["filetype"][-4:])
ret_str = ""
for i in range(1, 11):
ret_str += f"{i},st000{story_num}_{i-1},,,,,,,,,,,,,,,,1,,-1,1,\r\n"
return {"data": ret_str}
def handle_data_event_stamp_list_request(self, data: Dict) -> Dict:
async def handle_data_event_stamp_list_request(self, data: Dict) -> Dict:
return {"data": "Cs1032,1,1,1,1,1,1,1,1,1,1,\r\n"}
def handle_data_premium_list_request(self, data: Dict) -> Dict:
async def handle_data_premium_list_request(self, data: Dict) -> Dict:
return {"data": "1,,,,10,,,,,99,,,,,,,,,100,,\r\n"}
def handle_data_event_list_request(self, data: Dict) -> Dict:
async def handle_data_event_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_event_detail_list_request(self, data: Dict) -> Dict:
async def handle_data_event_detail_list_request(self, data: Dict) -> Dict:
event_id = data["dldate"]["filetype"].split("/")[2]
if "EventStampMapListCs1002" in event_id:
return {"data": "1,2,1,1,2,3,9,5,6,7,8,9,10,\r\n"}
@@ -278,7 +278,7 @@ class CxbRevSunriseS1(CxbBase):
else:
return {"data": ""}
def handle_data_event_stamp_map_list_csxxxx_request(self, data: Dict) -> Dict:
async def handle_data_event_stamp_map_list_csxxxx_request(self, data: Dict) -> Dict:
event_id = data["dldate"]["filetype"].split("/")[2]
if "EventStampMapListCs1002" in event_id:
return {"data": "1,2,1,1,2,3,9,5,6,7,8,9,10,\r\n"}

View File

@@ -17,11 +17,11 @@ class CxbRevSunriseS2(CxbBase):
super().__init__(cfg, game_cfg)
self.version = CxbConstants.VER_CROSSBEATS_REV_SUNRISE_S2_OMNI
def handle_data_path_list_request(self, data: Dict) -> Dict:
async def handle_data_path_list_request(self, data: Dict) -> Dict:
return {"data": ""}
@cached(lifetime=86400)
def handle_data_music_list_request(self, data: Dict) -> Dict:
async def handle_data_music_list_request(self, data: Dict) -> Dict:
version = data["dldate"]["filetype"].split("/")[0]
ret_str = ""
@@ -41,7 +41,7 @@ class CxbRevSunriseS2(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_item_list_detail_request(self, data: Dict) -> Dict:
async def handle_data_item_list_detail_request(self, data: Dict) -> Dict:
# ItemListIcon load
ret_str = "#ItemListIcon\r\n"
with open(
@@ -63,7 +63,7 @@ class CxbRevSunriseS2(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_shop_list_detail_request(self, data: Dict) -> Dict:
async def handle_data_shop_list_detail_request(self, data: Dict) -> Dict:
# ShopListIcon load
ret_str = "#ShopListIcon\r\n"
with open(
@@ -128,7 +128,7 @@ class CxbRevSunriseS2(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_extra_stage_list_request(self, data: Dict) -> Dict:
async def handle_data_extra_stage_list_request(self, data: Dict) -> Dict:
ret_str=""
with open(r"titles/cxb/data/rss2/ExtraStageList.csv") as extra:
lines = extra.readlines()
@@ -136,19 +136,19 @@ class CxbRevSunriseS2(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
def handle_data_exxxxx_request(self, data: Dict) -> Dict:
async def handle_data_exxxxx_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_one_more_extra_list_request(self, data: Dict) -> Dict:
async def handle_data_one_more_extra_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_bonus_list10100_request(self, data: Dict) -> Dict:
async def handle_data_bonus_list10100_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_oexxxx_request(self, data: Dict) -> Dict:
async def handle_data_oexxxx_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_free_coupon_request(self, data: Dict) -> Dict:
async def handle_data_free_coupon_request(self, data: Dict) -> Dict:
ret_str=""
with open(r"titles/cxb/data/rss2/FreeCoupon.csv") as coupon:
lines = coupon.readlines()
@@ -157,7 +157,7 @@ class CxbRevSunriseS2(CxbBase):
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_news_list_request(self, data: Dict) -> Dict:
async def handle_data_news_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/data/rss2/NewsList.csv", encoding="UTF-8") as news:
lines = news.readlines()
@@ -165,14 +165,14 @@ class CxbRevSunriseS2(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_tips_request(self, data: Dict) -> Dict:
async def handle_data_tips_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_release_info_list_request(self, data: Dict) -> Dict:
async def handle_data_release_info_list_request(self, data: Dict) -> Dict:
return {"data": ""}
@cached(lifetime=86400)
def handle_data_random_music_list_request(self, data: Dict) -> Dict:
async def handle_data_random_music_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/data/rss2/MusicArchiveList.csv") as music:
lines = music.readlines()
@@ -186,7 +186,7 @@ class CxbRevSunriseS2(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_license_request(self, data: Dict) -> Dict:
async def handle_data_license_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/data/rss2/License.csv", encoding="UTF-8") as licenses:
lines = licenses.readlines()
@@ -195,7 +195,7 @@ class CxbRevSunriseS2(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_course_list_request(self, data: Dict) -> Dict:
async def handle_data_course_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(
r"titles/cxb/data/rss2/Course/CourseList.csv", encoding="UTF-8"
@@ -206,7 +206,7 @@ class CxbRevSunriseS2(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_csxxxx_request(self, data: Dict) -> Dict:
async def handle_data_csxxxx_request(self, data: Dict) -> Dict:
extra_num = int(data["dldate"]["filetype"][-4:])
ret_str = ""
with open(
@@ -217,16 +217,16 @@ class CxbRevSunriseS2(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_mission_list_request(self, data: Dict) -> Dict:
async def handle_data_mission_list_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_mission_bonus_request(self, data: Dict) -> Dict:
async def handle_data_mission_bonus_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_unlimited_mission_request(self, data: Dict) -> Dict:
async def handle_data_unlimited_mission_request(self, data: Dict) -> Dict:
return {"data": ""}
def handle_data_partner_list_request(self, data: Dict) -> Dict:
async def handle_data_partner_list_request(self, data: Dict) -> Dict:
ret_str = ""
# Lord forgive me for the sins I am about to commit
for i in range(0, 10):
@@ -245,7 +245,7 @@ class CxbRevSunriseS2(CxbBase):
return {"data": ret_str}
@cached(lifetime=86400)
def handle_data_partnerxxxx_request(self, data: Dict) -> Dict:
async def handle_data_partnerxxxx_request(self, data: Dict) -> Dict:
partner_num = int(data["dldate"]["filetype"][-4:])
ret_str = f"{partner_num},,{partner_num},1,10000,\r\n"
with open(r"titles/cxb/data/rss2/Partner0000.csv") as partner:
@@ -254,13 +254,13 @@ class CxbRevSunriseS2(CxbBase):
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_server_state_request(self, data: Dict) -> Dict:
async def handle_data_server_state_request(self, data: Dict) -> Dict:
return {"data": True}
def handle_data_settings_request(self, data: Dict) -> Dict:
async def handle_data_settings_request(self, data: Dict) -> Dict:
return {"data": "2,\r\n"}
def handle_data_story_list_request(self, data: Dict) -> Dict:
async def handle_data_story_list_request(self, data: Dict) -> Dict:
# story id, story name, game version, start time, end time, course arc, unlock flag, song mcode for menu
ret_str = "\r\n"
ret_str += (
@@ -272,7 +272,7 @@ class CxbRevSunriseS2(CxbBase):
ret_str += f"st0002,REMNANT,10104,1502127790,4096483201,Cs1000,-1,overcl,\r\n"
return {"data": ret_str}
def handle_data_stxxxx_request(self, data: Dict) -> Dict:
async def handle_data_stxxxx_request(self, data: Dict) -> Dict:
story_num = int(data["dldate"]["filetype"][-4:])
ret_str = ""
# Each stories appears to have 10 pieces based on the wiki but as on how they are set.... no clue
@@ -280,18 +280,18 @@ class CxbRevSunriseS2(CxbBase):
ret_str += f"{i},st000{story_num}_{i-1},,,,,,,,,,,,,,,,1,,-1,1,\r\n"
return {"data": ret_str}
def handle_data_event_stamp_list_request(self, data: Dict) -> Dict:
async def handle_data_event_stamp_list_request(self, data: Dict) -> Dict:
return {"data": "Cs1002,1,1,1,1,1,1,1,1,1,1,\r\n"}
def handle_data_premium_list_request(self, data: Dict) -> Dict:
async def handle_data_premium_list_request(self, data: Dict) -> Dict:
return {"data": "1,,,,10,,,,,99,,,,,,,,,100,,\r\n"}
def handle_data_event_list_request(self, data: Dict) -> Dict:
async def handle_data_event_list_request(self, data: Dict) -> Dict:
return {
"data": "Cs4001,0,10000,1601510400,1604188799,1,nv2006,1,\r\nCs4005,0,10000,1609459200,1615766399,1,nv2006,1,\r\n"
}
def handle_data_event_detail_list_request(self, data: Dict) -> Dict:
async def handle_data_event_detail_list_request(self, data: Dict) -> Dict:
event_id = data["dldate"]["filetype"].split("/")[2]
if "Cs4001" in event_id:
return {
@@ -308,7 +308,7 @@ class CxbRevSunriseS2(CxbBase):
else:
return {"data": ""}
def handle_data_event_stamp_map_list_csxxxx_request(self, data: Dict) -> Dict:
async def handle_data_event_stamp_map_list_csxxxx_request(self, data: Dict) -> Dict:
event_id = data["dldate"]["filetype"].split("/")[2]
if "EventStampMapListCs1002" in event_id:
return {"data": "1,2,1,1,2,3,9,5,6,7,8,9,10,\r\n"}

View File

@@ -19,12 +19,12 @@ energy = Table(
class CxbItemData(BaseData):
def put_energy(self, user_id: int, rev_energy: int) -> Optional[int]:
async def put_energy(self, user_id: int, rev_energy: int) -> Optional[int]:
sql = insert(energy).values(user=user_id, energy=rev_energy)
conflict = sql.on_duplicate_key_update(energy=rev_energy)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.error(
f"{__name__} failed to insert item! user: {user_id}, energy: {rev_energy}"
@@ -33,10 +33,10 @@ class CxbItemData(BaseData):
return result.lastrowid
def get_energy(self, user_id: int) -> Optional[Dict]:
async def get_energy(self, user_id: int) -> Optional[Dict]:
sql = energy.select(and_(energy.c.user == user_id))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()

View File

@@ -21,7 +21,7 @@ profile = Table(
class CxbProfileData(BaseData):
def put_profile(
async def put_profile(
self, user_id: int, version: int, index: int, data: JSON
) -> Optional[int]:
sql = insert(profile).values(
@@ -30,7 +30,7 @@ class CxbProfileData(BaseData):
conflict = sql.on_duplicate_key_update(index=index, data=data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.error(
f"{__name__} failed to update! user: {user_id}, index: {index}, data: {data}"
@@ -39,7 +39,7 @@ class CxbProfileData(BaseData):
return result.lastrowid
def get_profile(self, aime_id: int, version: int) -> Optional[List[Dict]]:
async def get_profile(self, aime_id: int, version: int) -> Optional[List[Dict]]:
"""
Given a game version and either a profile or aime id, return the profile
"""
@@ -47,12 +47,12 @@ class CxbProfileData(BaseData):
and_(profile.c.version == version, profile.c.user == aime_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_profile_index(
async def get_profile_index(
self, index: int, aime_id: int = None, version: int = None
) -> Optional[Dict]:
"""
@@ -72,7 +72,7 @@ class CxbProfileData(BaseData):
)
return None
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()

View File

@@ -58,7 +58,7 @@ ranking = Table(
class CxbScoreData(BaseData):
def put_best_score(
async def put_best_score(
self,
user_id: int,
song_mcode: str,
@@ -79,7 +79,7 @@ class CxbScoreData(BaseData):
conflict = sql.on_duplicate_key_update(data=sql.inserted.data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.error(
f"{__name__} failed to insert best score! profile: {user_id}, song: {song_mcode}, data: {data}"
@@ -88,7 +88,7 @@ class CxbScoreData(BaseData):
return result.lastrowid
def put_playlog(
async def put_playlog(
self,
user_id: int,
song_mcode: str,
@@ -125,7 +125,7 @@ class CxbScoreData(BaseData):
combo=combo,
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.error(
f"{__name__} failed to insert playlog! profile: {user_id}, song: {song_mcode}, chart: {chart_id}"
@@ -134,7 +134,7 @@ class CxbScoreData(BaseData):
return result.lastrowid
def put_ranking(
async def put_ranking(
self, user_id: int, rev_id: int, song_id: int, score: int, clear: int
) -> Optional[int]:
"""
@@ -151,7 +151,7 @@ class CxbScoreData(BaseData):
conflict = sql.on_duplicate_key_update(score=score)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.error(
f"{__name__} failed to insert ranking log! profile: {user_id}, score: {score}, clear: {clear}"
@@ -160,28 +160,28 @@ class CxbScoreData(BaseData):
return result.lastrowid
def get_best_score(self, user_id: int, song_mcode: int) -> Optional[Dict]:
async def get_best_score(self, user_id: int, song_mcode: int) -> Optional[Dict]:
sql = score.select(
and_(score.c.user == user_id, score.c.song_mcode == song_mcode)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_best_scores(self, user_id: int) -> Optional[Dict]:
async def get_best_scores(self, user_id: int) -> Optional[Dict]:
sql = score.select(score.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_best_rankings(self, user_id: int) -> Optional[List[Dict]]:
async def get_best_rankings(self, user_id: int) -> Optional[List[Dict]]:
sql = ranking.select(ranking.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()

View File

@@ -29,7 +29,7 @@ music = Table(
class CxbStaticData(BaseData):
def put_music(
async def put_music(
self,
version: int,
mcode: str,
@@ -55,12 +55,12 @@ class CxbStaticData(BaseData):
title=title, artist=artist, category=category, level=level
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_music(
async def get_music(
self, version: int, song_id: Optional[int] = None
) -> Optional[List[Row]]:
if song_id is None:
@@ -73,12 +73,12 @@ class CxbStaticData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_music_chart(
async def get_music_chart(
self, version: int, song_id: int, chart_id: int
) -> Optional[List[Row]]:
sql = select(music).where(
@@ -89,7 +89,7 @@ class CxbStaticData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()

View File

@@ -7,4 +7,3 @@ index = DivaServlet
database = DivaData
reader = DivaReader
game_codes = [DivaConstants.GAME_CODE]
current_schema_version = 6

View File

@@ -1,8 +1,7 @@
import datetime
from typing import Any, List, Dict
from typing import Dict
import logging
import json
import urllib
import urllib.parse
from threading import Thread
from core.config import CoreConfig
@@ -24,13 +23,13 @@ class DivaBase:
dt = datetime.datetime.now()
self.time_lut = urllib.parse.quote(dt.strftime("%Y-%m-%d %H:%M:%S:16.0"))
def handle_test_request(self, data: Dict) -> Dict:
async def handle_test_request(self, data: Dict) -> Dict:
return ""
def handle_game_init_request(self, data: Dict) -> Dict:
async def handle_game_init_request(self, data: Dict) -> Dict:
return f""
def handle_attend_request(self, data: Dict) -> Dict:
async def handle_attend_request(self, data: Dict) -> Dict:
encoded = "&"
params = {
"atnd_prm1": "0,1,1,0,0,0,1,0,100,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
@@ -44,7 +43,7 @@ class DivaBase:
return encoded
def handle_ping_request(self, data: Dict) -> Dict:
async def handle_ping_request(self, data: Dict) -> Dict:
encoded = "&"
params = {
"ping_b_msg": f"Welcome to {self.core_cfg.server.name} network!",
@@ -89,7 +88,7 @@ class DivaBase:
return encoded
def handle_pv_list_request(self, data: Dict) -> Dict:
async def handle_pv_list_request(self, data: Dict) -> Dict:
pvlist = ""
with open(r"titles/diva/data/PvList0.dat", encoding="utf-8") as shop:
lines = shop.readlines()
@@ -126,10 +125,10 @@ class DivaBase:
return response
def handle_shop_catalog_request(self, data: Dict) -> Dict:
async def handle_shop_catalog_request(self, data: Dict) -> Dict:
catalog = ""
shopList = self.data.static.get_enabled_shops(self.version)
shopList = await self.data.static.get_enabled_shops(self.version)
if not shopList:
with open(r"titles/diva/data/ShopCatalog.dat", encoding="utf-8") as shop:
lines = shop.readlines()
@@ -164,9 +163,9 @@ class DivaBase:
return response
def handle_buy_module_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile(data["pd_id"], self.version)
module = self.data.static.get_enabled_shop(self.version, int(data["mdl_id"]))
async def handle_buy_module_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile(data["pd_id"], self.version)
module = await self.data.static.get_enabled_shop(self.version, int(data["mdl_id"]))
# make sure module is available to purchase
if not module:
@@ -178,11 +177,11 @@ class DivaBase:
new_vcld_pts = profile["vcld_pts"] - int(data["mdl_price"])
self.data.profile.update_profile(profile["user"], vcld_pts=new_vcld_pts)
self.data.module.put_module(data["pd_id"], self.version, data["mdl_id"])
await self.data.profile.update_profile(profile["user"], vcld_pts=new_vcld_pts)
await self.data.module.put_module(data["pd_id"], self.version, data["mdl_id"])
# generate the mdl_have string
mdl_have = self.data.module.get_modules_have_string(data["pd_id"], self.version)
mdl_have = await self.data.module.get_modules_have_string(data["pd_id"], self.version)
response = "&shp_rslt=1"
response += f"&mdl_id={data['mdl_id']}"
@@ -191,10 +190,10 @@ class DivaBase:
return response
def handle_cstmz_itm_ctlg_request(self, data: Dict) -> Dict:
async def handle_cstmz_itm_ctlg_request(self, data: Dict) -> Dict:
catalog = ""
itemList = self.data.static.get_enabled_items(self.version)
itemList = await self.data.static.get_enabled_items(self.version)
if not itemList:
with open(r"titles/diva/data/ItemCatalog.dat", encoding="utf-8") as item:
lines = item.readlines()
@@ -229,9 +228,9 @@ class DivaBase:
return response
def handle_buy_cstmz_itm_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile(data["pd_id"], self.version)
item = self.data.static.get_enabled_item(
async def handle_buy_cstmz_itm_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile(data["pd_id"], self.version)
item = await self.data.static.get_enabled_item(
self.version, int(data["cstmz_itm_id"])
)
@@ -246,14 +245,14 @@ class DivaBase:
new_vcld_pts = profile["vcld_pts"] - int(data["cstmz_itm_price"])
# save new Vocaloid Points balance
self.data.profile.update_profile(profile["user"], vcld_pts=new_vcld_pts)
await self.data.profile.update_profile(profile["user"], vcld_pts=new_vcld_pts)
self.data.customize.put_customize_item(
await self.data.customize.put_customize_item(
data["pd_id"], self.version, data["cstmz_itm_id"]
)
# generate the cstmz_itm_have string
cstmz_itm_have = self.data.customize.get_customize_items_have_string(
cstmz_itm_have = await self.data.customize.get_customize_items_have_string(
data["pd_id"], self.version
)
@@ -264,7 +263,7 @@ class DivaBase:
return response
def handle_festa_info_request(self, data: Dict) -> Dict:
async def handle_festa_info_request(self, data: Dict) -> Dict:
encoded = "&"
params = {
"fi_id": "1,2",
@@ -287,7 +286,7 @@ class DivaBase:
return encoded
def handle_contest_info_request(self, data: Dict) -> Dict:
async def handle_contest_info_request(self, data: Dict) -> Dict:
response = ""
response += f"&ci_lut={self.time_lut}"
@@ -295,10 +294,10 @@ class DivaBase:
return response
def handle_qst_inf_request(self, data: Dict) -> Dict:
async def handle_qst_inf_request(self, data: Dict) -> Dict:
quest = ""
questList = self.data.static.get_enabled_quests(self.version)
questList = await self.data.static.get_enabled_quests(self.version)
if not questList:
with open(r"titles/diva/data/QuestInfo.dat", encoding="utf-8") as shop:
lines = shop.readlines()
@@ -345,45 +344,45 @@ class DivaBase:
return response
def handle_nv_ranking_request(self, data: Dict) -> Dict:
async def handle_nv_ranking_request(self, data: Dict) -> Dict:
return f""
def handle_ps_ranking_request(self, data: Dict) -> Dict:
async def handle_ps_ranking_request(self, data: Dict) -> Dict:
return f""
def handle_ng_word_request(self, data: Dict) -> Dict:
async def handle_ng_word_request(self, data: Dict) -> Dict:
return f""
def handle_rmt_wp_list_request(self, data: Dict) -> Dict:
async def handle_rmt_wp_list_request(self, data: Dict) -> Dict:
return f""
def handle_pv_def_chr_list_request(self, data: Dict) -> Dict:
async def handle_pv_def_chr_list_request(self, data: Dict) -> Dict:
return f""
def handle_pv_ng_mdl_list_request(self, data: Dict) -> Dict:
async def handle_pv_ng_mdl_list_request(self, data: Dict) -> Dict:
return f""
def handle_cstmz_itm_ng_mdl_lst_request(self, data: Dict) -> Dict:
async def handle_cstmz_itm_ng_mdl_lst_request(self, data: Dict) -> Dict:
return f""
def handle_banner_info_request(self, data: Dict) -> Dict:
async def handle_banner_info_request(self, data: Dict) -> Dict:
return f""
def handle_banner_data_request(self, data: Dict) -> Dict:
async def handle_banner_data_request(self, data: Dict) -> Dict:
return f""
def handle_cm_ply_info_request(self, data: Dict) -> Dict:
async def handle_cm_ply_info_request(self, data: Dict) -> Dict:
return f""
def handle_pstd_h_ctrl_request(self, data: Dict) -> Dict:
async def handle_pstd_h_ctrl_request(self, data: Dict) -> Dict:
return f""
def handle_pstd_item_ng_lst_request(self, data: Dict) -> Dict:
async def handle_pstd_item_ng_lst_request(self, data: Dict) -> Dict:
return f""
def handle_pre_start_request(self, data: Dict) -> str:
profile = self.data.profile.get_profile(data["aime_id"], self.version)
profile_shop = self.data.item.get_shop(data["aime_id"], self.version)
async def handle_pre_start_request(self, data: Dict) -> str:
profile = await self.data.profile.get_profile(data["aime_id"], self.version)
profile_shop = await self.data.item.get_shop(data["aime_id"], self.version)
if profile is None:
return f"&ps_result=-3"
@@ -422,29 +421,29 @@ class DivaBase:
return response
def handle_registration_request(self, data: Dict) -> Dict:
self.data.profile.create_profile(
async def handle_registration_request(self, data: Dict) -> Dict:
await self.data.profile.create_profile(
self.version, data["aime_id"], data["player_name"]
)
return f"&cd_adm_result=1&pd_id={data['aime_id']}"
def handle_start_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile(data["pd_id"], self.version)
profile_shop = self.data.item.get_shop(data["pd_id"], self.version)
async def handle_start_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile(data["pd_id"], self.version)
profile_shop = await self.data.item.get_shop(data["pd_id"], self.version)
if profile is None:
return
mdl_have = "F" * 250
# generate the mdl_have string if "unlock_all_modules" is disabled
if not self.game_config.mods.unlock_all_modules:
mdl_have = self.data.module.get_modules_have_string(
mdl_have = await self.data.module.get_modules_have_string(
data["pd_id"], self.version
)
cstmz_itm_have = "F" * 250
# generate the cstmz_itm_have string if "unlock_all_items" is disabled
if not self.game_config.mods.unlock_all_items:
cstmz_itm_have = self.data.customize.get_customize_items_have_string(
cstmz_itm_have = await self.data.customize.get_customize_items_have_string(
data["pd_id"], self.version
)
@@ -525,7 +524,7 @@ class DivaBase:
}
# get clear status from user scores
pv_records = self.data.score.get_best_scores(data["pd_id"])
pv_records = await self.data.score.get_best_scores(data["pd_id"])
clear_status = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"
if pv_records is not None:
@@ -583,11 +582,11 @@ class DivaBase:
return response
def handle_pd_unlock_request(self, data: Dict) -> Dict:
async def handle_pd_unlock_request(self, data: Dict) -> Dict:
return f""
def handle_spend_credit_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile(data["pd_id"], self.version)
async def handle_spend_credit_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile(data["pd_id"], self.version)
if profile is None:
return
@@ -664,30 +663,30 @@ class DivaBase:
return pv_result
def task_generateScoreData(self, data: Dict, pd_by_pv_id, song):
async def task_generateScoreData(self, data: Dict, pd_by_pv_id, song):
if int(song) > 0:
# the request do not send a edition so just perform a query best score and ranking for each edition.
# 0=ORIGINAL, 1=EXTRA
pd_db_song_0 = self.data.score.get_best_user_score(
pd_db_song_0 = await self.data.score.get_best_user_score(
data["pd_id"], int(song), data["difficulty"], edition=0
)
pd_db_song_1 = self.data.score.get_best_user_score(
pd_db_song_1 = await self.data.score.get_best_user_score(
data["pd_id"], int(song), data["difficulty"], edition=1
)
pd_db_ranking_0, pd_db_ranking_1 = None, None
if pd_db_song_0:
pd_db_ranking_0 = self.data.score.get_global_ranking(
pd_db_ranking_0 = await self.data.score.get_global_ranking(
data["pd_id"], int(song), data["difficulty"], edition=0
)
if pd_db_song_1:
pd_db_ranking_1 = self.data.score.get_global_ranking(
pd_db_ranking_1 = await self.data.score.get_global_ranking(
data["pd_id"], int(song), data["difficulty"], edition=1
)
pd_db_customize = self.data.pv_customize.get_pv_customize(
pd_db_customize = await self.data.pv_customize.get_pv_customize(
data["pd_id"], int(song)
)
@@ -705,7 +704,7 @@ class DivaBase:
pd_by_pv_id.append(urllib.parse.quote(f"{song}***"))
pd_by_pv_id.append(",")
def handle_get_pv_pd_request(self, data: Dict) -> Dict:
async def handle_get_pv_pd_request(self, data: Dict) -> Dict:
song_id = data["pd_pv_id_lst"].split(",")
pv = ""
@@ -713,7 +712,7 @@ class DivaBase:
pd_by_pv_id = []
for song in song_id:
thread_ScoreData = Thread(target=self.task_generateScoreData(data, pd_by_pv_id, song))
thread_ScoreData = Thread(target=await self.task_generateScoreData(data, pd_by_pv_id, song))
threads.append(thread_ScoreData)
for x in threads:
@@ -732,11 +731,11 @@ class DivaBase:
return response
def handle_stage_start_request(self, data: Dict) -> Dict:
async def handle_stage_start_request(self, data: Dict) -> Dict:
return f""
def handle_stage_result_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile(data["pd_id"], self.version)
async def handle_stage_result_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile(data["pd_id"], self.version)
pd_song_list = data["stg_ply_pv_id"].split(",")
pd_song_difficulty = data["stg_difficulty"].split(",")
@@ -754,14 +753,14 @@ class DivaBase:
for index, value in enumerate(pd_song_list):
if "-1" not in pd_song_list[index]:
profile_pd_db_song = self.data.score.get_best_user_score(
profile_pd_db_song = await self.data.score.get_best_user_score(
data["pd_id"],
pd_song_list[index],
pd_song_difficulty[index],
pd_song_edition[index],
)
if profile_pd_db_song is None:
self.data.score.put_best_score(
await self.data.score.put_best_score(
data["pd_id"],
self.version,
pd_song_list[index],
@@ -778,7 +777,7 @@ class DivaBase:
pd_song_worst_cnt[index],
pd_song_max_combo[index],
)
self.data.score.put_playlog(
await self.data.score.put_playlog(
data["pd_id"],
self.version,
pd_song_list[index],
@@ -796,7 +795,7 @@ class DivaBase:
pd_song_max_combo[index],
)
elif int(pd_song_max_score[index]) >= int(profile_pd_db_song["score"]):
self.data.score.put_best_score(
await self.data.score.put_best_score(
data["pd_id"],
self.version,
pd_song_list[index],
@@ -813,7 +812,7 @@ class DivaBase:
pd_song_worst_cnt[index],
pd_song_max_combo[index],
)
self.data.score.put_playlog(
await self.data.score.put_playlog(
data["pd_id"],
self.version,
pd_song_list[index],
@@ -831,7 +830,7 @@ class DivaBase:
pd_song_max_combo[index],
)
elif int(pd_song_max_score[index]) != int(profile_pd_db_song["score"]):
self.data.score.put_playlog(
await self.data.score.put_playlog(
data["pd_id"],
self.version,
pd_song_list[index],
@@ -852,7 +851,7 @@ class DivaBase:
# Profile saving based on registration list
# Calculate new level
best_scores = self.data.score.get_best_scores(data["pd_id"])
best_scores = await self.data.score.get_best_scores(data["pd_id"])
total_atn_pnt = 0
for best_score in best_scores:
@@ -866,7 +865,7 @@ class DivaBase:
response += f"&lv_pnt_old={int(profile['lv_pnt'])}"
# update the profile and commit changes to the db
self.data.profile.update_profile(
await self.data.profile.update_profile(
profile["user"],
lv_num=new_level,
lv_pnt=new_level_pnt,
@@ -914,16 +913,16 @@ class DivaBase:
return response
def handle_end_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile(data["pd_id"], self.version)
async def handle_end_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile(data["pd_id"], self.version)
self.data.profile.update_profile(
await self.data.profile.update_profile(
profile["user"], my_qst_id=data["my_qst_id"], my_qst_sts=data["my_qst_sts"]
)
return f""
def handle_shop_exit_request(self, data: Dict) -> Dict:
self.data.item.put_shop(
async def handle_shop_exit_request(self, data: Dict) -> Dict:
await self.data.item.put_shop(
data["pd_id"],
self.version,
data["mdl_eqp_cmn_ary"],
@@ -931,7 +930,7 @@ class DivaBase:
data["ms_itm_flg_cmn_ary"],
)
if int(data["use_pv_mdl_eqp"]) == 1:
self.data.pv_customize.put_pv_customize(
await self.data.pv_customize.put_pv_customize(
data["pd_id"],
self.version,
data["ply_pv_id"],
@@ -940,7 +939,7 @@ class DivaBase:
data["ms_itm_flg_pv_ary"],
)
else:
self.data.pv_customize.put_pv_customize(
await self.data.pv_customize.put_pv_customize(
data["pd_id"],
self.version,
data["ply_pv_id"],
@@ -952,8 +951,8 @@ class DivaBase:
response = "&shp_rslt=1"
return response
def handle_card_procedure_request(self, data: Dict) -> str:
profile = self.data.profile.get_profile(data["aime_id"], self.version)
async def handle_card_procedure_request(self, data: Dict) -> str:
profile = await self.data.profile.get_profile(data["aime_id"], self.version)
if profile is None:
return "&cd_adm_result=0"
@@ -972,8 +971,8 @@ class DivaBase:
return response
def handle_change_name_request(self, data: Dict) -> str:
profile = self.data.profile.get_profile(data["pd_id"], self.version)
async def handle_change_name_request(self, data: Dict) -> str:
profile = await self.data.profile.get_profile(data["pd_id"], self.version)
# make sure user has enough Vocaloid Points
if profile["vcld_pts"] < int(data["chg_name_price"]):
@@ -981,7 +980,7 @@ class DivaBase:
# update the vocaloid points and player name
new_vcld_pts = profile["vcld_pts"] - int(data["chg_name_price"])
self.data.profile.update_profile(
await self.data.profile.update_profile(
profile["user"], player_name=data["player_name"], vcld_pts=new_vcld_pts
)
@@ -992,15 +991,15 @@ class DivaBase:
return response
def handle_change_passwd_request(self, data: Dict) -> str:
profile = self.data.profile.get_profile(data["pd_id"], self.version)
async def handle_change_passwd_request(self, data: Dict) -> str:
profile = await self.data.profile.get_profile(data["pd_id"], self.version)
# TODO: return correct error number instead of 0
if data["passwd"] != profile["passwd"]:
return "&cd_adm_result=0"
# set password to true and update the saved password
self.data.profile.update_profile(
await self.data.profile.update_profile(
profile["user"], passwd_stat=1, passwd=data["new_passwd"]
)

View File

@@ -1,4 +1,6 @@
from twisted.web.http import Request
from starlette.requests import Request
from starlette.responses import PlainTextResponse
from starlette.routing import Route
import yaml
import logging, coloredlogs
from logging.handlers import TimedRotatingFileHandler
@@ -51,17 +53,16 @@ class DivaServlet(BaseServlet):
level=self.game_cfg.server.loglevel, logger=self.logger, fmt=log_fmt_str
)
def get_endpoint_matchers(self) -> Tuple[List[Tuple[str, str, Dict]], List[Tuple[str, str, Dict]]]:
return (
[],
[("render_POST", "/DivaServlet/", {})]
)
def get_routes(self) -> List[Route]:
return [
Route("/DivaServlet/", self.render_POST, methods=['POST'])
]
def get_allnet_info(self, game_code: str, game_ver: int, keychip: str) -> Tuple[str, str]:
if not self.core_cfg.server.is_using_proxy and Utils.get_title_port(self.core_cfg) != 80:
return (f"http://{self.core_cfg.title.hostname}:{Utils.get_title_port(self.core_cfg)}/DivaServlet/", self.core_cfg.title.hostname)
return (f"http://{self.core_cfg.server.hostname}:{Utils.get_title_port(self.core_cfg)}/DivaServlet/", self.core_cfg.server.hostname)
return (f"http://{self.core_cfg.title.hostname}/DivaServlet/", self.core_cfg.title.hostname)
return (f"http://{self.core_cfg.server.hostname}/DivaServlet/", self.core_cfg.server.hostname)
@classmethod
def is_game_enabled(
@@ -78,9 +79,9 @@ class DivaServlet(BaseServlet):
return True
def render_POST(self, request: Request, game_code: str, matchers: Dict) -> bytes:
req_raw = request.content.getvalue()
url_header = request.getAllHeaders()
async def render_POST(self, request: Request, game_code: str, matchers: Dict) -> bytes:
req_raw = await request.body()
url_header = request.headers
# Ping Dispatch
if "THIS_STRING_SEPARATES" in str(url_header):
@@ -103,9 +104,7 @@ class DivaServlet(BaseServlet):
self.logger.debug(
f"Response cmd={bin_req_data['cmd']}&req_id={bin_req_data['req_id']}&stat=ok{resp}"
)
return f"cmd={bin_req_data['cmd']}&req_id={bin_req_data['req_id']}&stat=ok{resp}".encode(
"utf-8"
)
return PlainTextResponse(f"cmd={bin_req_data['cmd']}&req_id={bin_req_data['req_id']}&stat=ok{resp}")
# Main Dispatch
json_string = json.dumps(
@@ -122,7 +121,7 @@ class DivaServlet(BaseServlet):
) # Decompressing the gzip
except zlib.error as e:
self.logger.error(f"Failed to defalte! {e} -> {gz_string}")
return "stat=0"
return PlainTextResponse("stat=0")
req_kvp = urllib.parse.unquote(url_data)
req_data = {}
@@ -141,27 +140,18 @@ class DivaServlet(BaseServlet):
# Load the requests
try:
handler = getattr(self.base, func_to_find)
resp = handler(req_data)
resp = await handler(req_data)
except AttributeError as e:
self.logger.warning(f"Unhandled {req_data['cmd']} request {e}")
return f"cmd={req_data['cmd']}&req_id={req_data['req_id']}&stat=ok".encode(
"utf-8"
)
return PlainTextResponse(f"cmd={req_data['cmd']}&req_id={req_data['req_id']}&stat=ok")
except Exception as e:
self.logger.error(f"Error handling method {func_to_find} {e}")
return f"cmd={req_data['cmd']}&req_id={req_data['req_id']}&stat=ok".encode(
"utf-8"
)
return PlainTextResponse(f"cmd={req_data['cmd']}&req_id={req_data['req_id']}&stat=ok")
request.responseHeaders.addRawHeader(b"content-type", b"text/plain")
self.logger.debug(
f"Response cmd={req_data['cmd']}&req_id={req_data['req_id']}&stat=ok{resp}"
)
return (
f"cmd={req_data['cmd']}&req_id={req_data['req_id']}&stat=ok{resp}".encode(
"utf-8"
)
)
return PlainTextResponse(f"cmd={req_data['cmd']}&req_id={req_data['req_id']}&stat=ok{resp}")

View File

@@ -28,7 +28,7 @@ class DivaReader(BaseReader):
self.logger.error(f"Invalid project diva version {version}")
exit(1)
def read(self) -> None:
async def read(self) -> None:
pull_bin_ram = True
pull_bin_rom = True
pull_opt_rom = True
@@ -48,14 +48,14 @@ class DivaReader(BaseReader):
self.logger.warning("No option directory specified, skipping")
if pull_bin_ram:
self.read_ram(f"{self.bin_dir}/ram")
await self.read_ram(f"{self.bin_dir}/ram")
if pull_bin_rom:
self.read_rom(f"{self.bin_dir}/rom")
await self.read_rom(f"{self.bin_dir}/rom")
if pull_opt_rom:
for dir in opt_dirs:
self.read_rom(f"{dir}/rom")
await self.read_rom(f"{dir}/rom")
def read_ram(self, ram_root_dir: str) -> None:
async def read_ram(self, ram_root_dir: str) -> None:
self.logger.info(f"Read RAM from {ram_root_dir}")
if path.exists(f"{ram_root_dir}/databank"):
@@ -91,7 +91,7 @@ class DivaReader(BaseReader):
f"Added shop item {split[x+0]}"
)
self.data.static.put_shop(
await self.data.static.put_shop(
self.version,
split[x + 0],
split[x + 2],
@@ -109,7 +109,7 @@ class DivaReader(BaseReader):
for x in range(0, len(split), 7):
self.logger.info(f"Added item {split[x+0]}")
self.data.static.put_items(
await self.data.static.put_items(
self.version,
split[x + 0],
split[x + 2],
@@ -123,7 +123,7 @@ class DivaReader(BaseReader):
elif file.startswith("QuestInfo") and len(split) >= 9:
self.logger.info(f"Added quest {split[0]}")
self.data.static.put_quests(
await self.data.static.put_quests(
self.version,
split[0],
split[6],
@@ -141,7 +141,7 @@ class DivaReader(BaseReader):
else:
self.logger.warning(f"Databank folder not found in {ram_root_dir}, skipping")
def read_rom(self, rom_root_dir: str) -> None:
async def read_rom(self, rom_root_dir: str) -> None:
self.logger.info(f"Read ROM from {rom_root_dir}")
pv_list: Dict[str, Dict] = {}
@@ -199,7 +199,7 @@ class DivaReader(BaseReader):
diff = pv_data["difficulty"]["easy"]["0"]["level"].split("_")
self.logger.info(f"Added song {song_id} chart 0")
self.data.static.put_music(
await self.data.static.put_music(
self.version,
song_id,
0,
@@ -220,7 +220,7 @@ class DivaReader(BaseReader):
diff = pv_data["difficulty"]["normal"]["0"]["level"].split("_")
self.logger.info(f"Added song {song_id} chart 1")
self.data.static.put_music(
await self.data.static.put_music(
self.version,
song_id,
1,
@@ -238,7 +238,7 @@ class DivaReader(BaseReader):
diff = pv_data["difficulty"]["hard"]["0"]["level"].split("_")
self.logger.info(f"Added song {song_id} chart 2")
self.data.static.put_music(
await self.data.static.put_music(
self.version,
song_id,
2,
@@ -257,7 +257,7 @@ class DivaReader(BaseReader):
diff = pv_data["difficulty"]["extreme"]["0"]["level"].split("_")
self.logger.info(f"Added song {song_id} chart 3")
self.data.static.put_music(
await self.data.static.put_music(
self.version,
song_id,
3,
@@ -275,7 +275,7 @@ class DivaReader(BaseReader):
diff = pv_data["difficulty"]["extreme"]["1"]["level"].split("_")
self.logger.info(f"Added song {song_id} chart 4")
self.data.static.put_music(
await self.data.static.put_music(
self.version,
song_id,
4,

View File

@@ -25,10 +25,10 @@ customize = Table(
class DivaCustomizeItemData(BaseData):
def put_customize_item(self, aime_id: int, version: int, item_id: int) -> None:
async def put_customize_item(self, aime_id: int, version: int, item_id: int) -> None:
sql = insert(customize).values(version=version, user=aime_id, item_id=item_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.error(
f"{__name__} Failed to insert diva profile customize item! aime id: {aime_id} item: {item_id}"
@@ -36,7 +36,7 @@ class DivaCustomizeItemData(BaseData):
return None
return result.lastrowid
def get_customize_items(self, aime_id: int, version: int) -> Optional[List[Dict]]:
async def get_customize_items(self, aime_id: int, version: int) -> Optional[List[Dict]]:
"""
Given a game version and an aime id, return all the customize items, not used directly
"""
@@ -44,12 +44,12 @@ class DivaCustomizeItemData(BaseData):
and_(customize.c.version == version, customize.c.user == aime_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_customize_items_have_string(self, aime_id: int, version: int) -> str:
async def get_customize_items_have_string(self, aime_id: int, version: int) -> str:
"""
Given a game version and an aime id, return the cstmz_itm_have hex string
required for diva directly

View File

@@ -26,7 +26,7 @@ shop = Table(
class DivaItemData(BaseData):
def put_shop(
async def put_shop(
self,
aime_id: int,
version: int,
@@ -48,7 +48,7 @@ class DivaItemData(BaseData):
ms_itm_flg_ary=ms_itm_flg_ary,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.error(
f"{__name__} Failed to insert diva profile! aime id: {aime_id} array: {mdl_eqp_ary}"
@@ -56,13 +56,13 @@ class DivaItemData(BaseData):
return None
return result.lastrowid
def get_shop(self, aime_id: int, version: int) -> Optional[List[Dict]]:
async def get_shop(self, aime_id: int, version: int) -> Optional[List[Dict]]:
"""
Given a game version and either a profile or aime id, return the profile
"""
sql = shop.select(and_(shop.c.version == version, shop.c.user == aime_id))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()

View File

@@ -23,10 +23,10 @@ module = Table(
class DivaModuleData(BaseData):
def put_module(self, aime_id: int, version: int, module_id: int) -> None:
async def put_module(self, aime_id: int, version: int, module_id: int) -> None:
sql = insert(module).values(version=version, user=aime_id, module_id=module_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.error(
f"{__name__} Failed to insert diva profile module! aime id: {aime_id} module: {module_id}"
@@ -34,18 +34,18 @@ class DivaModuleData(BaseData):
return None
return result.lastrowid
def get_modules(self, aime_id: int, version: int) -> Optional[List[Dict]]:
async def get_modules(self, aime_id: int, version: int) -> Optional[List[Dict]]:
"""
Given a game version and an aime id, return all the modules, not used directly
"""
sql = module.select(and_(module.c.version == version, module.c.user == aime_id))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_modules_have_string(self, aime_id: int, version: int) -> str:
async def get_modules_have_string(self, aime_id: int, version: int) -> str:
"""
Given a game version and an aime id, return the mdl_have hex string
required for diva directly

View File

@@ -70,7 +70,7 @@ profile = Table(
class DivaProfileData(BaseData):
def create_profile(
async def create_profile(
self, version: int, aime_id: int, player_name: str
) -> Optional[int]:
"""
@@ -82,7 +82,7 @@ class DivaProfileData(BaseData):
conflict = sql.on_duplicate_key_update(player_name=sql.inserted.player_name)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.error(
f"{__name__} Failed to insert diva profile! aime id: {aime_id} username: {player_name}"
@@ -90,21 +90,21 @@ class DivaProfileData(BaseData):
return None
return result.lastrowid
def update_profile(self, aime_id: int, **profile_args) -> None:
async def update_profile(self, aime_id: int, **profile_args) -> None:
"""
Given an aime_id update the profile corresponding to the arguments
which are the diva_profile Columns
"""
sql = profile.update(profile.c.user == aime_id).values(**profile_args)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.error(
f"update_profile: failed to update profile! profile: {aime_id}"
)
return None
def get_profile(self, aime_id: int, version: int) -> Optional[List[Dict]]:
async def get_profile(self, aime_id: int, version: int) -> Optional[List[Dict]]:
"""
Given a game version and either a profile or aime id, return the profile
"""
@@ -112,7 +112,7 @@ class DivaProfileData(BaseData):
and_(profile.c.version == version, profile.c.user == aime_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()

View File

@@ -39,7 +39,7 @@ pv_customize = Table(
class DivaPvCustomizeData(BaseData):
def put_pv_customize(
async def put_pv_customize(
self,
aime_id: int,
version: int,
@@ -64,7 +64,7 @@ class DivaPvCustomizeData(BaseData):
ms_itm_flg_ary=ms_itm_flg_ary,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.error(
f"{__name__} Failed to insert diva pv customize! aime id: {aime_id}"
@@ -72,7 +72,7 @@ class DivaPvCustomizeData(BaseData):
return None
return result.lastrowid
def get_pv_customize(self, aime_id: int, pv_id: int) -> Optional[List[Dict]]:
async def get_pv_customize(self, aime_id: int, pv_id: int) -> Optional[List[Dict]]:
"""
Given either a profile or aime id, return a Pv Customize row
"""
@@ -80,7 +80,7 @@ class DivaPvCustomizeData(BaseData):
and_(pv_customize.c.user == aime_id, pv_customize.c.pv_id == pv_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()

View File

@@ -57,7 +57,7 @@ playlog = Table(
class DivaScoreData(BaseData):
def put_best_score(
async def put_best_score(
self,
user_id: int,
game_version: int,
@@ -109,7 +109,7 @@ class DivaScoreData(BaseData):
max_combo=max_combo,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.error(
f"{__name__} failed to insert best score! profile: {user_id}, song: {song_id}"
@@ -118,7 +118,7 @@ class DivaScoreData(BaseData):
return result.lastrowid
def put_playlog(
async def put_playlog(
self,
user_id: int,
game_version: int,
@@ -157,7 +157,7 @@ class DivaScoreData(BaseData):
max_combo=max_combo,
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.error(
f"{__name__} failed to insert playlog! profile: {user_id}, song: {song_id}, chart: {difficulty}"
@@ -166,7 +166,7 @@ class DivaScoreData(BaseData):
return result.lastrowid
def get_best_user_score(
async def get_best_user_score(
self, user_id: int, pv_id: int, difficulty: int, edition: int
) -> Optional[Row]:
sql = score.select(
@@ -178,12 +178,12 @@ class DivaScoreData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_top3_scores(
async def get_top3_scores(
self, pv_id: int, difficulty: int, edition: int
) -> Optional[List[Row]]:
sql = (
@@ -198,12 +198,12 @@ class DivaScoreData(BaseData):
.limit(3)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_global_ranking(
async def get_global_ranking(
self, user_id: int, pv_id: int, difficulty: int, edition: int
) -> Optional[List[Row]]:
# get the subquery max score of a user with pv_id, difficulty and
@@ -227,15 +227,15 @@ class DivaScoreData(BaseData):
score.c.edition == edition,
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_best_scores(self, user_id: int) -> Optional[List[Row]]:
async def get_best_scores(self, user_id: int) -> Optional[List[Row]]:
sql = score.select(score.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()

View File

@@ -83,7 +83,7 @@ items = Table(
class DivaStaticData(BaseData):
def put_quests(
async def put_quests(
self,
version: int,
questId: int,
@@ -111,22 +111,22 @@ class DivaStaticData(BaseData):
conflict = sql.on_duplicate_key_update(name=name)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_enabled_quests(self, version: int) -> Optional[List[Row]]:
async def get_enabled_quests(self, version: int) -> Optional[List[Row]]:
sql = select(quests).where(
and_(quests.c.version == version, quests.c.quest_enable == True)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_shop(
async def put_shop(
self,
version: int,
shopId: int,
@@ -150,12 +150,12 @@ class DivaStaticData(BaseData):
conflict = sql.on_duplicate_key_update(name=name)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_enabled_shop(self, version: int, shopId: int) -> Optional[Row]:
async def get_enabled_shop(self, version: int, shopId: int) -> Optional[Row]:
sql = select(shop).where(
and_(
shop.c.version == version,
@@ -164,22 +164,22 @@ class DivaStaticData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_enabled_shops(self, version: int) -> Optional[List[Row]]:
async def get_enabled_shops(self, version: int) -> Optional[List[Row]]:
sql = select(shop).where(
and_(shop.c.version == version, shop.c.enabled == True)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_items(
async def put_items(
self,
version: int,
itemId: int,
@@ -203,12 +203,12 @@ class DivaStaticData(BaseData):
conflict = sql.on_duplicate_key_update(name=name)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_enabled_item(self, version: int, itemId: int) -> Optional[Row]:
async def get_enabled_item(self, version: int, itemId: int) -> Optional[Row]:
sql = select(items).where(
and_(
items.c.version == version,
@@ -217,22 +217,22 @@ class DivaStaticData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_enabled_items(self, version: int) -> Optional[List[Row]]:
async def get_enabled_items(self, version: int) -> Optional[List[Row]]:
sql = select(items).where(
and_(items.c.version == version, items.c.enabled == True)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_music(
async def put_music(
self,
version: int,
song: int,
@@ -271,12 +271,12 @@ class DivaStaticData(BaseData):
date=date,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
return None
return result.lastrowid
def get_music(
async def get_music(
self, version: int, song_id: Optional[int] = None
) -> Optional[List[Row]]:
if song_id is None:
@@ -289,12 +289,12 @@ class DivaStaticData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_music_chart(
async def get_music_chart(
self, version: int, song_id: int, chart_id: int
) -> Optional[List[Row]]:
sql = select(music).where(
@@ -305,7 +305,7 @@ class DivaStaticData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()

View File

@@ -9,4 +9,3 @@ database = IDACData
reader = IDACReader
frontend = IDACFrontend
game_codes = [IDACConstants.GAME_CODE]
current_schema_version = 1

View File

@@ -1,7 +1,6 @@
import logging
import socket
from twisted.internet.protocol import DatagramProtocol
from socketserver import BaseRequestHandler, TCPServer
from typing import Tuple
@@ -10,19 +9,14 @@ from titles.idac.config import IDACConfig
from titles.idac.database import IDACData
class IDACEchoUDP(DatagramProtocol):
def __init__(self, cfg: CoreConfig, game_cfg: IDACConfig, port: int) -> None:
super().__init__()
self.port = port
self.core_config = cfg
self.game_config = game_cfg
self.logger = logging.getLogger("idac")
class IDACEchoUDP:
def connection_made(self, transport):
self.transport = transport
def datagram_received(self, data, addr):
logging.getLogger('idz').debug(f'Received echo from {addr}')
self.transport.sendto(data, addr)
def datagramReceived(self, data, addr):
self.logger.info(
f"UDP Ping from from {addr[0]}:{addr[1]} -> {self.port} - {data.hex()}"
)
self.transport.write(data, addr)
class IDACEchoTCP(BaseRequestHandler):

View File

@@ -1,12 +1,13 @@
import json
from typing import List
from starlette.routing import Route
from starlette.responses import Response, RedirectResponse
import yaml
import jinja2
from os import path
from twisted.web.util import redirectTo
from twisted.web.http import Request
from twisted.web.server import Session
from starlette.requests import Request
from core.frontend import FE_Base, IUserSession
from core.frontend import FE_Base, UserSession
from core.config import CoreConfig
from titles.idac.database import IDACData
from titles.idac.schema.profile import *
@@ -26,7 +27,8 @@ class IDACFrontend(FE_Base):
self.game_cfg.update(
yaml.safe_load(open(f"{cfg_dir}/{IDACConstants.CONFIG_NAME}"))
)
self.nav_name = "頭文字D THE ARCADE"
#self.nav_name = "頭文字D THE ARCADE"
self.nav_name = "IDAC"
# TODO: Add version list
self.version = IDACConstants.VER_IDAC_SEASON_2
@@ -36,8 +38,13 @@ class IDACFrontend(FE_Base):
25: "full_tune_tickets",
34: "full_tune_fragments",
}
def get_routes(self) -> List[Route]:
return [
Route("/", self.render_GET)
]
def generate_all_tables_json(self, user_id: int):
async def generate_all_tables_json(self, user_id: int):
json_export = {}
idac_tables = {
@@ -73,7 +80,7 @@ class IDACFrontend(FE_Base):
sql = sql.where(table.c.version == self.version)
# lol use the profile connection for items, dirty hack
result = self.data.profile.execute(sql)
result = await self.data.profile.execute(sql)
data_list = result.fetchall()
# add the list to the json export with the correct table name
@@ -86,49 +93,47 @@ class IDACFrontend(FE_Base):
return json.dumps(json_export, indent=4, default=str, ensure_ascii=False)
def render_GET(self, request: Request) -> bytes:
uri: str = request.uri.decode()
async def render_GET(self, request: Request) -> bytes:
uri: str = request.url.path
template = self.environment.get_template(
"titles/idac/frontend/idac_index.jinja"
"titles/idac/templates/idac_index.jinja"
)
sesh: Session = request.getSession()
usr_sesh = IUserSession(sesh)
user_id = usr_sesh.userId
usr_sesh = self.validate_session(request)
if not usr_sesh:
usr_sesh = UserSession()
user_id = usr_sesh.user_id
# user_id = usr_sesh.user_id
# profile export
if uri.startswith("/game/idac/export"):
if user_id == 0:
return redirectTo(b"/game/idac", request)
return RedirectResponse(b"/game/idac", request)
# set the file name, content type and size to download the json
content = self.generate_all_tables_json(user_id).encode("utf-8")
request.responseHeaders.addRawHeader(
b"content-type", b"application/octet-stream"
)
request.responseHeaders.addRawHeader(
b"content-disposition", b"attachment; filename=idac_profile.json"
)
request.responseHeaders.addRawHeader(
b"content-length", str(len(content)).encode("utf-8")
)
content = await self.generate_all_tables_json(user_id).encode("utf-8")
self.logger.info(f"User {user_id} exported their IDAC data")
return content
return Response(
content,
200,
{'content-disposition': 'attachment; filename=idac_profile.json'},
"application/octet-stream"
)
profile_data, tickets, rank = None, None, None
if user_id > 0:
profile_data = self.data.profile.get_profile(user_id, self.version)
ticket_data = self.data.item.get_tickets(user_id)
rank = self.data.profile.get_profile_rank(user_id, self.version)
profile_data = await self.data.profile.get_profile(user_id, self.version)
ticket_data = await self.data.item.get_tickets(user_id)
rank = await self.data.profile.get_profile_rank(user_id, self.version)
tickets = {
self.ticket_names[ticket["ticket_id"]]: ticket["ticket_cnt"]
for ticket in ticket_data
}
if ticket_data:
tickets = {
self.ticket_names[ticket["ticket_id"]]: ticket["ticket_cnt"]
for ticket in ticket_data
}
return template.render(
return Response(template.render(
title=f"{self.core_config.server.name} | {self.nav_name}",
game_list=self.environment.globals["game_list"],
profile=profile_data,
@@ -136,7 +141,4 @@ class IDACFrontend(FE_Base):
rank=rank,
sesh=vars(usr_sesh),
active_page="idac",
).encode("utf-16")
def render_POST(self, request: Request) -> bytes:
pass
))

View File

@@ -1,28 +1,26 @@
import json
import traceback
import inflection
from starlette.routing import Route
from starlette.requests import Request
from starlette.responses import JSONResponse
import yaml
import logging
import coloredlogs
from os import path
from typing import Dict, List, Tuple
from logging.handlers import TimedRotatingFileHandler
from twisted.web import server
from twisted.web.http import Request
from twisted.internet import reactor, endpoints
import asyncio
from core.config import CoreConfig
from core.title import BaseServlet, JSONResponseNoASCII
from core.utils import Utils
from titles.idac.base import IDACBase
from titles.idac.season2 import IDACSeason2
from titles.idac.config import IDACConfig
from titles.idac.const import IDACConstants
from titles.idac.echo import IDACEchoUDP
from titles.idac.matching import IDACMatching
class IDACServlet:
class IDACServlet(BaseServlet):
def __init__(self, core_cfg: CoreConfig, cfg_dir: str) -> None:
self.core_cfg = core_cfg
self.game_cfg = IDACConfig()
@@ -72,12 +70,12 @@ class IDACServlet:
return False
return True
def get_endpoint_matchers(self) -> Tuple[List[Tuple[str, str, Dict]], List[Tuple[str, str, Dict]]]:
return (
[],
[("render_POST", "/SDGT/{version}/initiald/{category}/{endpoint}", {})]
)
def get_routes(self) -> List[Route]:
return [
Route("/{version:int}/initiald/{category:str}/{endpoint:str}", self.render_POST, methods=["POST"]),
Route("/{version:int}/initiald-matching/{endpoint:str}", self.render_matching, methods=["POST"]),
]
def get_allnet_info(
self, game_code: str, game_ver: int, keychip: str
@@ -88,15 +86,15 @@ class IDACServlet:
return (
f"",
# requires http or else it defaults to https
f"http://{self.core_cfg.title.hostname}{t_port}/{game_code}/{game_ver}/",
f"http://{self.core_cfg.server.hostname}{t_port}/{game_ver}/",
)
def render_POST(self, request: Request, game_code: int, matchers: Dict) -> bytes:
req_raw = request.content.getvalue()
async def render_POST(self, request: Request) -> bytes:
req_raw = await request.body()
internal_ver = 0
version = int(matchers['version'])
category = matchers['category']
endpoint = matchers['endpoint']
version: int = request.path_params.get('version')
category: str = request.path_params.get('category')
endpoint: str = request.path_params.get('endpoint')
client_ip = Utils.get_ip_addr(request)
if version >= 100 and version < 140: # IDAC Season 1
@@ -104,7 +102,7 @@ class IDACServlet:
elif version >= 140 and version < 171: # IDAC Season 2
internal_ver = IDACConstants.VER_IDAC_SEASON_2
header_application = self.decode_header(request.getAllHeaders())
header_application = self.decode_header(request.headers.get("application", ""))
req_data = json.loads(req_raw)
@@ -119,27 +117,61 @@ class IDACServlet:
if not hasattr(self.versions[internal_ver], func_to_find):
self.logger.warning(f"Unhandled v{version} request {endpoint}")
return '{"status_code": "0"}'.encode("utf-8")
return JSONResponse('{"status_code": "0"}')
resp = None
try:
handler = getattr(self.versions[internal_ver], func_to_find)
resp = handler(req_data, header_application)
resp = await handler(req_data, header_application)
except Exception as e:
traceback.print_exc()
self.logger.error(f"Error handling v{version} method {endpoint} - {e}")
return '{"status_code": "0"}'.encode("utf-8")
return JSONResponse('{"status_code": "0"}')
if resp is None:
resp = {"status_code": "0"}
self.logger.debug(f"Response {resp}")
return json.dumps(resp, ensure_ascii=False).encode("utf-8")
return JSONResponseNoASCII(resp)
async def render_matching(self, request: Request):
url: str = request.path_params.get("endpoint")
ver: int = request.path_params.get("version")
client_ip = Utils.get_ip_addr(request)
req_data = await request.json()
header_application = self.decode_header(request.headers.get('application', ''))
user_id = int(header_application["session"])
def decode_header(self, data: Dict) -> Dict:
app: str = data[b"application"].decode()
# self.getMatchingStatus(user_id)
self.logger.info(
f"IDAC Matching request from {client_ip}: {url} - {req_data}"
)
resp = {"status_code": "0"}
if url == "/regist":
self.queue = self.queue + 1
elif url == "/status":
if req_data.get("cancel_flag"):
self.queue = self.queue - 1
self.logger.info(
f"IDAC Matching endpoint {client_ip} had quited"
)
resp = {
"status_code": "0",
# Only IPv4 is supported
"host": self.game_config.server.matching_host,
"port": self.game_config.server.matching_p2p,
"room_name": "INDTA",
"state": 1,
}
self.logger.debug(f"Response {resp}")
return JSONResponseNoASCII(resp)
def decode_header(self, app: str) -> Dict:
ret = {}
for x in app.split(", "):
@@ -150,18 +182,13 @@ class IDACServlet:
def setup(self):
if self.game_cfg.server.enable:
endpoints.serverFromString(
reactor,
f"tcp:{self.game_cfg.server.matching}:interface={self.core_cfg.server.listen_address}",
).listen(server.Site(IDACMatching(self.core_cfg, self.game_cfg)))
reactor.listenUDP(
self.game_cfg.server.echo1,
IDACEchoUDP(self.core_cfg, self.game_cfg, self.game_cfg.server.echo1),
)
reactor.listenUDP(
self.game_cfg.server.echo2,
IDACEchoUDP(self.core_cfg, self.game_cfg, self.game_cfg.server.echo2),
loop = asyncio.get_running_loop()
asyncio.create_task(
loop.create_datagram_endpoint(
lambda: IDACEchoUDP(),
local_addr=(self.core_cfg.server.listen_address, self.game_cfg.server.echo1)
)
)
self.logger.info(f"Matching listening on {self.game_cfg.server.matching} with echos on {self.game_cfg.server.echo1} and {self.game_cfg.server.echo2}")
self.logger.info(f"Matching listening on {self.game_cfg.server.matching} with echo on {self.game_cfg.server.echo1}")

View File

@@ -1,72 +0,0 @@
import json
import logging
from typing import Dict
from twisted.web import resource
from core import CoreConfig
from titles.idac.season2 import IDACBase
from titles.idac.config import IDACConfig
class IDACMatching(resource.Resource):
isLeaf = True
def __init__(self, cfg: CoreConfig, game_cfg: IDACConfig) -> None:
self.core_config = cfg
self.game_config = game_cfg
self.base = IDACBase(cfg, game_cfg)
self.logger = logging.getLogger("idac")
self.queue = 0
def get_matching_state(self):
if self.queue >= 1:
self.queue -= 1
return 0
else:
return 1
def render_POST(self, req) -> bytes:
url = req.uri.decode()
req_data = json.loads(req.content.getvalue().decode())
header_application = self.decode_header(req.getAllHeaders())
user_id = int(header_application["session"])
# self.getMatchingStatus(user_id)
self.logger.info(
f"IDAC Matching request from {req.getClientIP()}: {url} - {req_data}"
)
resp = {"status_code": "0"}
if url == "/regist":
self.queue = self.queue + 1
elif url == "/status":
if req_data.get("cancel_flag"):
self.queue = self.queue - 1
self.logger.info(
f"IDAC Matching endpoint {req.getClientIP()} had quited"
)
resp = {
"status_code": "0",
# Only IPv4 is supported
"host": self.game_config.server.matching_host,
"port": self.game_config.server.matching_p2p,
"room_name": "INDTA",
"state": 1,
}
self.logger.debug(f"Response {resp}")
return json.dumps(resp, ensure_ascii=False).encode("utf-8")
def decode_header(self, data: Dict) -> Dict:
app: str = data[b"application"].decode()
ret = {}
for x in app.split(", "):
y = x.split("=")
ret[y[0]] = y[1].replace('"', "")
return ret

View File

@@ -33,7 +33,7 @@ class IDACReader(BaseReader):
self.logger.error(f"Invalid Initial D THE ARCADE version {version}")
exit(1)
def read(self) -> None:
async def read(self) -> None:
if self.bin_dir is None and self.opt_dir is None:
self.logger.error(
(
@@ -59,9 +59,9 @@ class IDACReader(BaseReader):
)
exit(1)
self.read_idac_profile(self.opt_dir)
await self.read_idac_profile(self.opt_dir)
def read_idac_profile(self, file_path: str) -> None:
async def read_idac_profile(self, file_path: str) -> None:
self.logger.info(f"Reading profile from {file_path}...")
# read it as binary to avoid encoding issues
@@ -88,14 +88,14 @@ class IDACReader(BaseReader):
self.logger.info("Exiting...")
exit(0)
user_id = self.data.user.create_user()
user_id = await self.data.user.create_user()
if user_id is None:
self.logger.error("Failed to register user!")
user_id = -1
else:
card_id = self.data.card.create_card(user_id, access_code)
card_id = await self.data.card.create_card(user_id, access_code)
if card_id is None:
self.logger.error("Failed to register card!")
@@ -150,7 +150,7 @@ class IDACReader(BaseReader):
# lol use the profile connection for items, dirty hack
conflict = sql.on_duplicate_key_update(**data)
result = self.data.profile.execute(conflict)
result = await self.data.profile.execute(conflict)
if result is None:
self.logger.error(f"Failed to insert data into table {name}")

View File

@@ -297,7 +297,7 @@ timetrial_event = Table(
class IDACItemData(BaseData):
def get_random_user_car(self, aime_id: int, version: int) -> Optional[List[Row]]:
async def get_random_user_car(self, aime_id: int, version: int) -> Optional[List[Row]]:
sql = (
select(car)
.where(and_(car.c.user == aime_id, car.c.version == version))
@@ -305,20 +305,20 @@ class IDACItemData(BaseData):
.limit(1)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_random_car(self, version: int) -> Optional[List[Row]]:
async def get_random_car(self, version: int) -> Optional[List[Row]]:
sql = select(car).where(car.c.version == version).order_by(func.rand()).limit(1)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_car(
async def get_car(
self, aime_id: int, version: int, style_car_id: int
) -> Optional[List[Row]]:
sql = select(car).where(
@@ -329,12 +329,12 @@ class IDACItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_cars(
async def get_cars(
self, version: int, aime_id: int, only_pickup: bool = False
) -> Optional[List[Row]]:
if only_pickup:
@@ -350,106 +350,106 @@ class IDACItemData(BaseData):
and_(car.c.user == aime_id, car.c.version == version)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_ticket(self, aime_id: int, ticket_id: int) -> Optional[Row]:
async def get_ticket(self, aime_id: int, ticket_id: int) -> Optional[Row]:
sql = select(ticket).where(
ticket.c.user == aime_id, ticket.c.ticket_id == ticket_id
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_tickets(self, aime_id: int) -> Optional[List[Row]]:
async def get_tickets(self, aime_id: int) -> Optional[List[Row]]:
sql = select(ticket).where(ticket.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_story(self, aime_id: int, chapter_id: int) -> Optional[Row]:
async def get_story(self, aime_id: int, chapter_id: int) -> Optional[Row]:
sql = select(story).where(
and_(story.c.user == aime_id, story.c.chapter == chapter_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_stories(self, aime_id: int) -> Optional[List[Row]]:
async def get_stories(self, aime_id: int) -> Optional[List[Row]]:
sql = select(story).where(story.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_story_episodes(self, aime_id: int, chapter_id: int) -> Optional[List[Row]]:
async def get_story_episodes(self, aime_id: int, chapter_id: int) -> Optional[List[Row]]:
sql = select(episode).where(
and_(episode.c.user == aime_id, episode.c.chapter == chapter_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_story_episode(self, aime_id: int, episode_id: int) -> Optional[Row]:
async def get_story_episode(self, aime_id: int, episode_id: int) -> Optional[Row]:
sql = select(episode).where(
and_(episode.c.user == aime_id, episode.c.episode == episode_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_story_episode_difficulties(
async def get_story_episode_difficulties(
self, aime_id: int, episode_id: int
) -> Optional[List[Row]]:
sql = select(difficulty).where(
and_(difficulty.c.user == aime_id, difficulty.c.episode == episode_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_courses(self, aime_id: int) -> Optional[List[Row]]:
async def get_courses(self, aime_id: int) -> Optional[List[Row]]:
sql = select(course).where(course.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_course(self, aime_id: int, course_id: int) -> Optional[Row]:
async def get_course(self, aime_id: int, course_id: int) -> Optional[Row]:
sql = select(course).where(
and_(course.c.user == aime_id, course.c.course_id == course_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_time_trial_courses(self, version: int) -> Optional[List[Row]]:
async def get_time_trial_courses(self, version: int) -> Optional[List[Row]]:
sql = select(trial.c.course_id).where(trial.c.version == version).distinct()
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_time_trial_user_best_time_by_course_car(
async def get_time_trial_user_best_time_by_course_car(
self, version: int, aime_id: int, course_id: int, style_car_id: int
) -> Optional[Row]:
sql = select(trial).where(
@@ -461,12 +461,12 @@ class IDACItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_time_trial_user_best_courses(
async def get_time_trial_user_best_courses(
self, version: int, aime_id: int
) -> Optional[List[Row]]:
# get for a given aime_id the best time for each course
@@ -491,12 +491,12 @@ class IDACItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_time_trial_best_cars_by_course(
async def get_time_trial_best_cars_by_course(
self, version: int, course_id: int, aime_id: Optional[int] = None
) -> Optional[List[Row]]:
subquery = (
@@ -527,12 +527,12 @@ class IDACItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_time_trial_ranking_by_course(
async def get_time_trial_ranking_by_course(
self,
version: int,
course_id: int,
@@ -568,12 +568,12 @@ class IDACItemData(BaseData):
if limit is not None:
sql = sql.limit(limit)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_time_trial_best_ranking_by_course(
async def get_time_trial_best_ranking_by_course(
self, version: int, aime_id: int, course_id: int
) -> Optional[Row]:
sql = (
@@ -589,12 +589,12 @@ class IDACItemData(BaseData):
.limit(1)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_challenge(
async def get_challenge(
self, aime_id: int, vs_type: int, play_difficulty: int
) -> Optional[Row]:
sql = select(challenge).where(
@@ -605,20 +605,20 @@ class IDACItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_challenges(self, aime_id: int) -> Optional[List[Row]]:
async def get_challenges(self, aime_id: int) -> Optional[List[Row]]:
sql = select(challenge).where(challenge.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_best_challenges_by_vs_type(
async def get_best_challenges_by_vs_type(
self, aime_id: int, story_type: int = 4
) -> Optional[List[Row]]:
subquery = (
@@ -653,20 +653,20 @@ class IDACItemData(BaseData):
.order_by(challenge.c.vs_type)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_theory_courses(self, aime_id: int) -> Optional[List[Row]]:
async def get_theory_courses(self, aime_id: int) -> Optional[List[Row]]:
sql = select(theory_course).where(theory_course.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_theory_course_by_powerhouse_lv(
async def get_theory_course_by_powerhouse_lv(
self, aime_id: int, course_id: int, powerhouse_lv: int, count: int = 3
) -> Optional[List[Row]]:
sql = (
@@ -682,40 +682,40 @@ class IDACItemData(BaseData):
.limit(count)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_theory_course(self, aime_id: int, course_id: int) -> Optional[List[Row]]:
async def get_theory_course(self, aime_id: int, course_id: int) -> Optional[List[Row]]:
sql = select(theory_course).where(
and_(
theory_course.c.user == aime_id, theory_course.c.course_id == course_id
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_theory_partners(self, aime_id: int) -> Optional[List[Row]]:
async def get_theory_partners(self, aime_id: int) -> Optional[List[Row]]:
sql = select(theory_partner).where(theory_partner.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_theory_running(self, aime_id: int) -> Optional[List[Row]]:
async def get_theory_running(self, aime_id: int) -> Optional[List[Row]]:
sql = select(theory_running).where(theory_running.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_theory_running_by_course(
async def get_theory_running_by_course(
self, aime_id: int, course_id: int
) -> Optional[Row]:
sql = select(theory_running).where(
@@ -725,32 +725,32 @@ class IDACItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_vs_infos(self, aime_id: int) -> Optional[List[Row]]:
async def get_vs_infos(self, aime_id: int) -> Optional[List[Row]]:
sql = select(vs_info).where(vs_info.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_stamps(self, aime_id: int) -> Optional[List[Row]]:
async def get_stamps(self, aime_id: int) -> Optional[List[Row]]:
sql = select(stamp).where(
and_(
stamp.c.user == aime_id,
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_timetrial_event(self, aime_id: int, timetrial_event_id: int) -> Optional[Row]:
async def get_timetrial_event(self, aime_id: int, timetrial_event_id: int) -> Optional[Row]:
sql = select(timetrial_event).where(
and_(
timetrial_event.c.user == aime_id,
@@ -758,49 +758,49 @@ class IDACItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_car(self, aime_id: int, version: int, car_data: Dict) -> Optional[int]:
async def put_car(self, aime_id: int, version: int, car_data: Dict) -> Optional[int]:
car_data["user"] = aime_id
car_data["version"] = version
sql = insert(car).values(**car_data)
conflict = sql.on_duplicate_key_update(**car_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(f"put_car: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_ticket(self, aime_id: int, ticket_data: Dict) -> Optional[int]:
async def put_ticket(self, aime_id: int, ticket_data: Dict) -> Optional[int]:
ticket_data["user"] = aime_id
sql = insert(ticket).values(**ticket_data)
conflict = sql.on_duplicate_key_update(**ticket_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(f"put_ticket: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_story(self, aime_id: int, story_data: Dict) -> Optional[int]:
async def put_story(self, aime_id: int, story_data: Dict) -> Optional[int]:
story_data["user"] = aime_id
sql = insert(story).values(**story_data)
conflict = sql.on_duplicate_key_update(**story_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(f"put_story: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_story_episode_play_status(
async def put_story_episode_play_status(
self, aime_id: int, chapter_id: int, play_status: int = 1
) -> Optional[int]:
sql = (
@@ -809,7 +809,7 @@ class IDACItemData(BaseData):
.values(play_status=play_status)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.warn(
f"put_story_episode_play_status: Failed to update! aime_id: {aime_id}"
@@ -817,7 +817,7 @@ class IDACItemData(BaseData):
return None
return result.lastrowid
def put_story_episode(
async def put_story_episode(
self, aime_id: int, chapter_id: int, episode_data: Dict
) -> Optional[int]:
episode_data["user"] = aime_id
@@ -825,14 +825,14 @@ class IDACItemData(BaseData):
sql = insert(episode).values(**episode_data)
conflict = sql.on_duplicate_key_update(**episode_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(f"put_story_episode: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_story_episode_difficulty(
async def put_story_episode_difficulty(
self, aime_id: int, episode_id: int, difficulty_data: Dict
) -> Optional[int]:
difficulty_data["user"] = aime_id
@@ -840,7 +840,7 @@ class IDACItemData(BaseData):
sql = insert(difficulty).values(**difficulty_data)
conflict = sql.on_duplicate_key_update(**difficulty_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(
@@ -849,19 +849,19 @@ class IDACItemData(BaseData):
return None
return result.lastrowid
def put_course(self, aime_id: int, course_data: Dict) -> Optional[int]:
async def put_course(self, aime_id: int, course_data: Dict) -> Optional[int]:
course_data["user"] = aime_id
sql = insert(course).values(**course_data)
conflict = sql.on_duplicate_key_update(**course_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(f"put_course: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_time_trial(
async def put_time_trial(
self, version: int, aime_id: int, time_trial_data: Dict
) -> Optional[int]:
time_trial_data["user"] = aime_id
@@ -869,47 +869,47 @@ class IDACItemData(BaseData):
sql = insert(trial).values(**time_trial_data)
conflict = sql.on_duplicate_key_update(**time_trial_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(f"put_time_trial: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_challenge(self, aime_id: int, challenge_data: Dict) -> Optional[int]:
async def put_challenge(self, aime_id: int, challenge_data: Dict) -> Optional[int]:
challenge_data["user"] = aime_id
sql = insert(challenge).values(**challenge_data)
conflict = sql.on_duplicate_key_update(**challenge_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(f"put_challenge: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_theory_course(
async def put_theory_course(
self, aime_id: int, theory_course_data: Dict
) -> Optional[int]:
theory_course_data["user"] = aime_id
sql = insert(theory_course).values(**theory_course_data)
conflict = sql.on_duplicate_key_update(**theory_course_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(f"put_theory_course: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_theory_partner(
async def put_theory_partner(
self, aime_id: int, theory_partner_data: Dict
) -> Optional[int]:
theory_partner_data["user"] = aime_id
sql = insert(theory_partner).values(**theory_partner_data)
conflict = sql.on_duplicate_key_update(**theory_partner_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(
@@ -918,14 +918,14 @@ class IDACItemData(BaseData):
return None
return result.lastrowid
def put_theory_running(
async def put_theory_running(
self, aime_id: int, theory_running_data: Dict
) -> Optional[int]:
theory_running_data["user"] = aime_id
sql = insert(theory_running).values(**theory_running_data)
conflict = sql.on_duplicate_key_update(**theory_running_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(
@@ -934,26 +934,26 @@ class IDACItemData(BaseData):
return None
return result.lastrowid
def put_vs_info(self, aime_id: int, vs_info_data: Dict) -> Optional[int]:
async def put_vs_info(self, aime_id: int, vs_info_data: Dict) -> Optional[int]:
vs_info_data["user"] = aime_id
sql = insert(vs_info).values(**vs_info_data)
conflict = sql.on_duplicate_key_update(**vs_info_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(f"put_vs_info: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_stamp(
async def put_stamp(
self, aime_id: int, stamp_data: Dict
) -> Optional[int]:
stamp_data["user"] = aime_id
sql = insert(stamp).values(**stamp_data)
conflict = sql.on_duplicate_key_update(**stamp_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(
@@ -962,7 +962,7 @@ class IDACItemData(BaseData):
return None
return result.lastrowid
def put_timetrial_event(
async def put_timetrial_event(
self, aime_id: int, time_trial_event_id: int, point: int
) -> Optional[int]:
timetrial_event_data = {
@@ -973,7 +973,7 @@ class IDACItemData(BaseData):
sql = insert(timetrial_event).values(**timetrial_event_data)
conflict = sql.on_duplicate_key_update(**timetrial_event_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(

View File

@@ -253,7 +253,7 @@ class IDACProfileData(BaseData):
)
self.date_time_format_short = "%Y-%m-%d"
def get_profile(self, aime_id: int, version: int) -> Optional[Row]:
async def get_profile(self, aime_id: int, version: int) -> Optional[Row]:
sql = select(profile).where(
and_(
profile.c.user == aime_id,
@@ -261,12 +261,12 @@ class IDACProfileData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_different_random_profiles(
async def get_different_random_profiles(
self, aime_id: int, version: int, count: int = 9
) -> Optional[Row]:
sql = (
@@ -281,36 +281,36 @@ class IDACProfileData(BaseData):
.limit(count)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_profile_config(self, aime_id: int) -> Optional[Row]:
async def get_profile_config(self, aime_id: int) -> Optional[Row]:
sql = select(config).where(
and_(
config.c.user == aime_id,
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_profile_avatar(self, aime_id: int) -> Optional[Row]:
async def get_profile_avatar(self, aime_id: int) -> Optional[Row]:
sql = select(avatar).where(
and_(
avatar.c.user == aime_id,
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_profile_rank(self, aime_id: int, version: int) -> Optional[Row]:
async def get_profile_rank(self, aime_id: int, version: int) -> Optional[Row]:
sql = select(rank).where(
and_(
rank.c.user == aime_id,
@@ -318,12 +318,12 @@ class IDACProfileData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_profile_stock(self, aime_id: int, version: int) -> Optional[Row]:
async def get_profile_stock(self, aime_id: int, version: int) -> Optional[Row]:
sql = select(stock).where(
and_(
stock.c.user == aime_id,
@@ -331,12 +331,12 @@ class IDACProfileData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_profile_theory(self, aime_id: int, version: int) -> Optional[Row]:
async def get_profile_theory(self, aime_id: int, version: int) -> Optional[Row]:
sql = select(theory).where(
and_(
theory.c.user == aime_id,
@@ -344,12 +344,12 @@ class IDACProfileData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile(
async def put_profile(
self, aime_id: int, version: int, profile_data: Dict
) -> Optional[int]:
profile_data["user"] = aime_id
@@ -357,19 +357,19 @@ class IDACProfileData(BaseData):
sql = insert(profile).values(**profile_data)
conflict = sql.on_duplicate_key_update(**profile_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(f"put_profile: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_profile_config(self, aime_id: int, config_data: Dict) -> Optional[int]:
async def put_profile_config(self, aime_id: int, config_data: Dict) -> Optional[int]:
config_data["user"] = aime_id
sql = insert(config).values(**config_data)
conflict = sql.on_duplicate_key_update(**config_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(
@@ -378,12 +378,12 @@ class IDACProfileData(BaseData):
return None
return result.lastrowid
def put_profile_avatar(self, aime_id: int, avatar_data: Dict) -> Optional[int]:
async def put_profile_avatar(self, aime_id: int, avatar_data: Dict) -> Optional[int]:
avatar_data["user"] = aime_id
sql = insert(avatar).values(**avatar_data)
conflict = sql.on_duplicate_key_update(**avatar_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(
@@ -392,7 +392,7 @@ class IDACProfileData(BaseData):
return None
return result.lastrowid
def put_profile_rank(
async def put_profile_rank(
self, aime_id: int, version: int, rank_data: Dict
) -> Optional[int]:
rank_data["user"] = aime_id
@@ -400,14 +400,14 @@ class IDACProfileData(BaseData):
sql = insert(rank).values(**rank_data)
conflict = sql.on_duplicate_key_update(**rank_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(f"put_profile_rank: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_profile_stock(
async def put_profile_stock(
self, aime_id: int, version: int, stock_data: Dict
) -> Optional[int]:
stock_data["user"] = aime_id
@@ -415,14 +415,14 @@ class IDACProfileData(BaseData):
sql = insert(stock).values(**stock_data)
conflict = sql.on_duplicate_key_update(**stock_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(f"put_profile_stock: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_profile_theory(
async def put_profile_theory(
self, aime_id: int, version: int, theory_data: Dict
) -> Optional[int]:
theory_data["user"] = aime_id
@@ -430,7 +430,7 @@ class IDACProfileData(BaseData):
sql = insert(theory).values(**theory_data)
conflict = sql.on_duplicate_key_update(**theory_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warn(

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,13 @@
{% extends "core/frontend/index.jinja" %}
{% extends "core/templates/index.jinja" %}
{% block content %}
<h1 class="mb-3">頭文字D THE ARCADE</h1>
{% if sesh is defined and sesh["userId"] > 0 %}
{% if sesh is defined and sesh["user_id"] > 0 %}
<div class="card mb-3">
<div class="card-body">
<div class="card-body">
{% if profile is defined and profile is not none %}
<div class="card-title">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center">
<h3>{{ sesh["username"] }}'s Profile</h3>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group me-2">
@@ -18,7 +19,6 @@
</div>
</div>
<!--<h4 class="card-subtitle mb-2 text-body-secondary">Card subtitle</h4>-->
{% if profile is defined and profile is not none %}
<div class="row d-flex justify-content-center h-100">
<div class="col col-lg-3 col-12">
<div class="card mb-3">
@@ -128,7 +128,7 @@
</div>
<script type="text/javascript">
{% include "titles/idac/frontend/js/idac_scripts.js" %}
{% include "titles/idac/templates/js/idac_scripts.js" %}
</script>
{% endblock content %}

View File

@@ -5,4 +5,3 @@ from titles.idz.database import IDZData
index = IDZServlet
database = IDZData
game_codes = [IDZConstants.GAME_CODE]
current_schema_version = 1

View File

@@ -1,19 +1,9 @@
from twisted.internet.protocol import DatagramProtocol
import logging
from core.config import CoreConfig
from .config import IDZConfig
class IDZEcho:
def connection_made(self, transport):
self.transport = transport
class IDZEcho(DatagramProtocol):
def __init__(self, cfg: CoreConfig, game_cfg: IDZConfig) -> None:
super().__init__()
self.core_config = cfg
self.game_config = game_cfg
self.logger = logging.getLogger("idz")
def datagramReceived(self, data, addr):
self.logger.debug(
f"Echo from from {addr[0]}:{addr[1]} -> {self.transport.getHost().port} - {data.hex()}"
)
self.transport.write(data, addr)
def datagram_received(self, data, addr):
logging.getLogger('idz').debug(f'Received echo from {addr}')
self.transport.sendto(data, addr)

View File

@@ -24,10 +24,10 @@ class IDZHandlerLoadServerInfo(IDZHandlerBase):
t_port = Utils.get_title_port(self.core_config)
news_str = f"http://{self.core_config.title.hostname}:{t_port}/idz/news/news80**.txt"
err_str = f"http://{self.core_config.title.hostname}:{t_port}/idz/error"
news_str = f"http://{self.core_config.server.hostname}:{t_port}/idz/news/news80**.txt"
err_str = f"http://{self.core_config.server.hostname}:{t_port}/idz/error"
len_hostname = len(self.core_config.title.hostname)
len_hostname = len(self.core_config.server.hostname)
len_news = len(news_str)
len_error = len(err_str)
@@ -36,7 +36,7 @@ class IDZHandlerLoadServerInfo(IDZHandlerBase):
f"{len_hostname}s",
ret,
0x4 + offset,
self.core_config.title.hostname.encode(),
self.core_config.server.hostname.encode(),
)
struct.pack_into("<I", ret, 0x84 + offset, self.game_cfg.ports.userdb)
struct.pack_into("<I", ret, 0x86 + offset, self.game_cfg.ports.userdb + 1)
@@ -45,7 +45,7 @@ class IDZHandlerLoadServerInfo(IDZHandlerBase):
f"{len_hostname}s",
ret,
0x88 + offset,
self.core_config.title.hostname.encode(),
self.core_config.server.hostname.encode(),
)
struct.pack_into("<I", ret, 0x108 + offset, self.game_cfg.ports.match - 1)
struct.pack_into("<I", ret, 0x10A + offset, self.game_cfg.ports.match - 3)
@@ -59,7 +59,7 @@ class IDZHandlerLoadServerInfo(IDZHandlerBase):
f"{len_hostname}s",
ret,
0x114 + offset,
self.core_config.title.hostname.encode(),
self.core_config.server.hostname.encode(),
)
struct.pack_into("<I", ret, 0x194 + offset, self.game_cfg.ports.echo + 2)
@@ -67,7 +67,7 @@ class IDZHandlerLoadServerInfo(IDZHandlerBase):
f"{len_hostname}s",
ret,
0x0199 + offset,
self.core_config.title.hostname.encode(),
self.core_config.server.hostname.encode(),
)
struct.pack_into("<I", ret, 0x0219 + offset, self.game_cfg.ports.echo + 3)
@@ -75,23 +75,23 @@ class IDZHandlerLoadServerInfo(IDZHandlerBase):
f"{len_hostname}s",
ret,
0x021C + offset,
self.core_config.title.hostname.encode(),
self.core_config.server.hostname.encode(),
)
struct.pack_into(
f"{len_hostname}s",
ret,
0x029C + offset,
self.core_config.title.hostname.encode(),
self.core_config.server.hostname.encode(),
)
struct.pack_into(
f"{len_hostname}s",
ret,
0x031C + offset,
self.core_config.title.hostname.encode(),
self.core_config.server.hostname.encode(),
)
struct.pack_into("<I", ret, 0x39C + offset, self.game_cfg.ports.echo)
struct.pack_into("<I", ret, 0x39E + offset, self.game_cfg.ports.echo + 1)
struct.pack_into("<I", ret, 0x39E + offset, self.game_cfg.ports.echo) # TODO: Test
struct.pack_into(f"{len_news}s", ret, 0x03A0 + offset, news_str.encode())
struct.pack_into(f"{len_error}s", ret, 0x0424 + offset, err_str.encode())

View File

@@ -1,19 +1,20 @@
from twisted.web.http import Request
from starlette.requests import Request
from starlette.responses import Response, PlainTextResponse
from starlette.routing import Route
import yaml
import logging
import coloredlogs
from logging.handlers import TimedRotatingFileHandler
from os import path
from typing import Tuple, List, Dict
from twisted.internet import reactor, endpoints
from twisted.web import server, resource
import importlib
import asyncio
from core.config import CoreConfig
from core.title import BaseServlet
from .config import IDZConfig
from .const import IDZConstants
from .userdb import IDZUserDBFactory, IDZKey
from .userdb import IDZUserDB, IDZKey
from .echo import IDZEcho
@@ -83,16 +84,15 @@ class IDZServlet(BaseServlet):
return True
def get_endpoint_matchers(self) -> Tuple[List[Tuple[str, str, Dict]], List[Tuple[str, str, Dict]]]:
return[
[("render_GET", "/idz/news/{endpoint:.*?}", {}),
("render_GET", "/idz/error", {})],
[]
def get_routes(self) -> List[Route]:
return [
Route("/idz/news/{endpoint:str}", self.render_GET),
Route("/idz/error", self.render_GET)
]
def get_allnet_info(self, game_code: str, game_ver: int, keychip: str) -> Tuple[str, str]:
hostname = (
self.core_cfg.title.hostname
self.core_cfg.server.hostname
if not self.game_cfg.server.hostname
else self.game_cfg.server.hostname
)
@@ -135,38 +135,36 @@ class IDZServlet(BaseServlet):
except AttributeError as e:
continue
endpoints.serverFromString(
reactor,
f"tcp:{self.game_cfg.ports.userdb}:interface={self.core_cfg.server.listen_address}",
).listen(
IDZUserDBFactory(self.core_cfg, self.game_cfg, self.rsa_keys, handler_map)
loop = asyncio.get_running_loop()
IDZUserDB(self.core_cfg, self.game_cfg, self.rsa_keys, handler_map)
asyncio.create_task(
loop.create_datagram_endpoint(
lambda: IDZEcho(),
local_addr=(self.core_cfg.server.listen_address, self.game_cfg.ports.echo)
)
)
reactor.listenUDP(
self.game_cfg.ports.echo, IDZEcho(self.core_cfg, self.game_cfg)
asyncio.create_task(
loop.create_datagram_endpoint(
lambda: IDZEcho(),
local_addr=(self.core_cfg.server.listen_address, self.game_cfg.ports.match)
)
)
reactor.listenUDP(
self.game_cfg.ports.echo + 1, IDZEcho(self.core_cfg, self.game_cfg)
)
reactor.listenUDP(
self.game_cfg.ports.match, IDZEcho(self.core_cfg, self.game_cfg)
)
reactor.listenUDP(
self.game_cfg.ports.userdb + 1, IDZEcho(self.core_cfg, self.game_cfg)
asyncio.create_task(
loop.create_datagram_endpoint(
lambda: IDZEcho(),
local_addr=(self.core_cfg.server.listen_address, self.game_cfg.ports.userdb + 1)
)
)
self.logger.info(f"UserDB Listening on port {self.game_cfg.ports.userdb}")
def render_GET(self, request: Request, game_code: str, matchers: Dict) -> bytes:
url_path = matchers['endpoint']
async def render_GET(self, request: Request) -> bytes:
url_path = request.path_params.get('endpoint', '')
if not url_path:
return Response()
self.logger.info(f"IDZ GET request: {url_path}")
request.responseHeaders.setRawHeaders(
"Content-Type", [b"text/plain; charset=utf-8"]
)
request.responseHeaders.setRawHeaders(
"Last-Modified", [b"Sun, 23 Apr 2023 05:33:20 GMT"]
)
news = (
self.game_cfg.server.news
@@ -176,4 +174,4 @@ class IDZServlet(BaseServlet):
news += "\r\n"
news = "1979/01/01 00:00:00 2099/12/31 23:59:59 " + news
return news.encode()
return PlainTextResponse(news, media_type="text/plain; charset=utf-8", headers={"Last-Modified": "Sun, 23 Apr 2023 05:33:20 GMT"})

View File

@@ -1,15 +1,9 @@
from twisted.internet.protocol import Factory, Protocol
import logging, coloredlogs
import logging
from Crypto.Cipher import AES
import struct
from typing import Dict, Optional, List, Type
from twisted.web import server, resource
from twisted.internet import reactor, endpoints
from twisted.web.http import Request
from routes import Mapper
import random
from os import walk
import importlib
import asyncio
from core.config import CoreConfig
from .database import IDZData
@@ -28,7 +22,7 @@ class IDZKey:
self.hashN = hashN
class IDZUserDBProtocol(Protocol):
class IDZUserDB:
def __init__(
self,
core_cfg: CoreConfig,
@@ -45,6 +39,10 @@ class IDZUserDBProtocol(Protocol):
self.version = None
self.version_internal = None
self.skip_next = False
def start(self) -> None:
self.logger.info(f"Start on port {self.config.aimedb.port}")
asyncio.create_task(asyncio.start_server(self.connection_cb, self.config.server.listen_address, self.config.aimedb.port))
def append_padding(self, data: bytes):
"""Appends 0s to the end of the data until it's at the correct size"""
@@ -52,43 +50,54 @@ class IDZUserDBProtocol(Protocol):
padding_size = length[0] - len(data)
data += bytes(padding_size)
return data
async def connection_cb(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
self.logger.debug(f"Connection made from {writer.get_extra_info('peername')[0]}")
while True:
try:
base = 0
def connectionMade(self) -> None:
self.logger.debug(f"{self.transport.getPeer().host} Connected")
base = 0
for i in range(len(self.static_key) - 1):
shift = 8 * i
byte = self.static_key[i]
for i in range(len(self.static_key) - 1):
shift = 8 * i
byte = self.static_key[i]
base |= byte << shift
base |= byte << shift
rsa_key = random.choice(self.rsa_keys)
key_enc: int = pow(base, rsa_key.e, rsa_key.N)
result = (
key_enc.to_bytes(0x40, "little")
+ struct.pack("<I", 0x01020304)
+ rsa_key.hashN.to_bytes(4, "little")
)
rsa_key = random.choice(self.rsa_keys)
key_enc: int = pow(base, rsa_key.e, rsa_key.N)
result = (
key_enc.to_bytes(0x40, "little")
+ struct.pack("<I", 0x01020304)
+ rsa_key.hashN.to_bytes(4, "little")
)
self.logger.debug(f"Send handshake {result.hex()}")
self.logger.debug(f"Send handshake {result.hex()}")
writer.write(result)
await writer.drain()
self.transport.write(result)
data: bytes = await reader.read(4096)
if len(data) == 0:
self.logger.debug("Connection closed")
return
await self.data.Received(data, reader, writer)
await writer.drain()
except ConnectionResetError as e:
self.logger.debug("Connection reset, disconnecting")
return
def connectionLost(self, reason) -> None:
self.logger.debug(
f"{self.transport.getPeer().host} Disconnected - {reason.value}"
)
def dataReceived(self, data: bytes) -> None:
def dataReceived(self, data: bytes, reader: asyncio.StreamReader, writer: asyncio.StreamWriter) -> None:
self.logger.debug(f"Receive data {data.hex()}")
client_ip = writer.get_extra_info('peername')[0]
crypt = AES.new(self.static_key, AES.MODE_ECB)
try:
data_dec = crypt.decrypt(data)
except Exception as e:
self.logger.error(f"Failed to decrypt UserDB request from {self.transport.getPeer().host} because {e} - {data.hex()}")
self.logger.error(f"Failed to decrypt UserDB request from {client_ip} because {e} - {data.hex()}")
self.logger.debug(f"Decrypt data {data_dec.hex()}")
@@ -99,7 +108,7 @@ class IDZUserDBProtocol(Protocol):
self.logger.info(f"Userdb serverbox request {data_dec.hex()}")
self.skip_next = True
self.transport.write(b"\x00")
writer.write(b"\x00")
return
elif magic == 0x01020304:
@@ -119,21 +128,21 @@ class IDZUserDBProtocol(Protocol):
self.version_internal = None
self.logger.debug(
f"Userdb v{self.version} handshake response from {self.transport.getPeer().host}"
f"Userdb v{self.version} handshake response from {client_ip}"
)
return
elif self.skip_next:
self.skip_next = False
self.transport.write(b"\x00")
writer.write(b"\x00")
return
elif self.version is None:
# We didn't get a handshake before, and this isn't one now, so we're up the creek
self.logger.info(
f"Bad UserDB request from from {self.transport.getPeer().host}"
f"Bad UserDB request from from {client_ip}"
)
self.transport.write(b"\x00")
writer.write(b"\x00")
return
cmd = struct.unpack_from("<H", data_dec, 0)[0]
@@ -147,7 +156,7 @@ class IDZUserDBProtocol(Protocol):
handler = handler_cls(self.core_config, self.game_config, self.version_internal)
self.logger.info(
f"Userdb v{self.version} {handler.name} request from {self.transport.getPeer().host}"
f"Userdb v{self.version} {handler.name} request from {client_ip}"
)
response = handler.handle(data_dec)
@@ -156,46 +165,4 @@ class IDZUserDBProtocol(Protocol):
crypt = AES.new(self.static_key, AES.MODE_ECB)
response_enc = crypt.encrypt(response)
self.transport.write(response_enc)
class IDZUserDBFactory(Factory):
protocol = IDZUserDBProtocol
def __init__(
self,
cfg: CoreConfig,
game_cfg: IDZConfig,
keys: List[IDZKey],
handlers: List[Dict],
) -> None:
self.core_config = cfg
self.game_config = game_cfg
self.keys = keys
self.handlers = handlers
def buildProtocol(self, addr):
return IDZUserDBProtocol(
self.core_config, self.game_config, self.keys, self.handlers
)
class IDZUserDBWeb(resource.Resource):
def __init__(self, core_cfg: CoreConfig, game_cfg: IDZConfig):
super().__init__()
self.isLeaf = True
self.core_config = core_cfg
self.game_config = game_cfg
self.logger = logging.getLogger("idz")
def render_POST(self, request: Request) -> bytes:
self.logger.info(
f"IDZUserDBWeb POST from {request.getClientAddress().host} to {request.uri} with data {request.content.getvalue()}"
)
return b""
def render_GET(self, request: Request) -> bytes:
self.logger.info(
f"IDZUserDBWeb GET from {request.getClientAddress().host} to {request.uri}"
)
return b""
writer.write(response_enc)

View File

@@ -16,4 +16,3 @@ game_codes = [
Mai2Constants.GAME_CODE_GREEN,
Mai2Constants.GAME_CODE,
]
current_schema_version = 8

View File

@@ -26,12 +26,12 @@ class Mai2Base:
self.date_time_format = "%Y-%m-%d %H:%M:%S"
if not self.core_config.server.is_using_proxy and Utils.get_title_port(self.core_config) != 80:
self.old_server = f"http://{self.core_config.title.hostname}:{Utils.get_title_port(cfg)}/197/MaimaiServlet/"
self.old_server = f"http://{self.core_config.server.hostname}:{Utils.get_title_port(cfg)}/197/MaimaiServlet/"
else:
self.old_server = f"http://{self.core_config.title.hostname}/197/MaimaiServlet/"
self.old_server = f"http://{self.core_config.server.hostname}/197/MaimaiServlet/"
def handle_get_game_setting_api_request(self, data: Dict):
async def handle_get_game_setting_api_request(self, data: Dict):
# if reboot start/end time is not defined use the default behavior of being a few hours ago
if self.core_config.title.reboot_start_time == "" or self.core_config.title.reboot_end_time == "":
reboot_start = datetime.strftime(
@@ -74,15 +74,15 @@ class Mai2Base:
},
}
def handle_get_game_ranking_api_request(self, data: Dict) -> Dict:
async def handle_get_game_ranking_api_request(self, data: Dict) -> Dict:
return {"length": 0, "gameRankingList": []}
def handle_get_game_tournament_info_api_request(self, data: Dict) -> Dict:
async def handle_get_game_tournament_info_api_request(self, data: Dict) -> Dict:
# TODO: Tournament support
return {"length": 0, "gameTournamentInfoList": []}
def handle_get_game_event_api_request(self, data: Dict) -> Dict:
events = self.data.static.get_enabled_events(self.version)
async def handle_get_game_event_api_request(self, data: Dict) -> Dict:
events = await self.data.static.get_enabled_events(self.version)
events_lst = []
if events is None or not events:
self.logger.warning("No enabled events, did you run the reader?")
@@ -108,11 +108,11 @@ class Mai2Base:
"gameEventList": events_lst,
}
def handle_get_game_ng_music_id_api_request(self, data: Dict) -> Dict:
async def handle_get_game_ng_music_id_api_request(self, data: Dict) -> Dict:
return {"length": 0, "musicIdList": []}
def handle_get_game_charge_api_request(self, data: Dict) -> Dict:
game_charge_list = self.data.static.get_enabled_tickets(self.version, 1)
async def handle_get_game_charge_api_request(self, data: Dict) -> Dict:
game_charge_list = await self.data.static.get_enabled_tickets(self.version, 1)
if game_charge_list is None:
return {"length": 0, "gameChargeList": []}
@@ -130,21 +130,21 @@ class Mai2Base:
return {"length": len(charge_list), "gameChargeList": charge_list}
def handle_upsert_client_setting_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_setting_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "UpsertClientSettingApi"}
def handle_upsert_client_upload_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_upload_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "UpsertClientUploadApi"}
def handle_upsert_client_bookkeeping_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_bookkeeping_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "UpsertClientBookkeepingApi"}
def handle_upsert_client_testmode_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_testmode_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "UpsertClientTestmodeApi"}
def handle_get_user_preview_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile_detail(data["userId"], self.version, False)
w = self.data.profile.get_web_option(data["userId"], self.version)
async def handle_get_user_preview_api_request(self, data: Dict) -> Dict:
p = await self.data.profile.get_profile_detail(data["userId"], self.version, False)
w = await self.data.profile.get_web_option(data["userId"], self.version)
if p is None or w is None:
return {} # Register
profile = p._asdict()
@@ -169,16 +169,16 @@ class Mai2Base:
"totalLv": profile["totalLv"],
}
def handle_user_login_api_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile_detail(data["userId"], self.version)
consec = self.data.profile.get_consec_login(data["userId"], self.version)
async def handle_user_login_api_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile_detail(data["userId"], self.version)
consec = await self.data.profile.get_consec_login(data["userId"], self.version)
if profile is not None:
lastLoginDate = profile["lastLoginDate"]
loginCt = profile["playCount"]
if "regionId" in data:
self.data.profile.put_profile_region(data["userId"], data["regionId"])
await self.data.profile.put_profile_region(data["userId"], data["regionId"])
else:
loginCt = 0
lastLoginDate = "2017-12-05 07:00:00.0"
@@ -193,11 +193,11 @@ class Mai2Base:
if lastlogindate_ < today_midnight:
consec_ct = consec['logins'] + 1
self.data.profile.add_consec_login(data["userId"], self.version)
await self.data.profile.add_consec_login(data["userId"], self.version)
elif lastlogindate_ < yesterday_midnight:
consec_ct = 1
self.data.profile.reset_consec_login(data["userId"], self.version)
await self.data.profile.reset_consec_login(data["userId"], self.version)
else:
consec_ct = consec['logins']
@@ -210,21 +210,21 @@ class Mai2Base:
"consecutiveLoginCount": consec_ct, # Number of consecutive days we've logged in.
}
def handle_upload_user_playlog_api_request(self, data: Dict) -> Dict:
async def handle_upload_user_playlog_api_request(self, data: Dict) -> Dict:
user_id = data["userId"]
playlog = data["userPlaylog"]
self.data.score.put_playlog(user_id, playlog)
await self.data.score.put_playlog(user_id, playlog)
return {"returnCode": 1, "apiName": "UploadUserPlaylogApi"}
def handle_upsert_user_chargelog_api_request(self, data: Dict) -> Dict:
async def handle_upsert_user_chargelog_api_request(self, data: Dict) -> Dict:
user_id = data["userId"]
charge = data["userCharge"]
# remove the ".0" from the date string, festival only?
charge["purchaseDate"] = charge["purchaseDate"].replace(".0", "")
self.data.item.put_charge(
await self.data.item.put_charge(
user_id,
charge["chargeId"],
charge["stock"],
@@ -234,7 +234,7 @@ class Mai2Base:
return {"returnCode": 1, "apiName": "UpsertUserChargelogApi"}
def handle_upsert_user_all_api_request(self, data: Dict) -> Dict:
async def handle_upsert_user_all_api_request(self, data: Dict) -> Dict:
user_id = data["userId"]
upsert = data["upsertUserAll"]
@@ -246,64 +246,64 @@ class Mai2Base:
upsert["userData"][0].pop("accessCode")
upsert["userData"][0].pop("userId")
self.data.profile.put_profile_detail(
await self.data.profile.put_profile_detail(
user_id, self.version, upsert["userData"][0], False
)
if "userWebOption" in upsert and len(upsert["userWebOption"]) > 0:
upsert["userWebOption"][0]["isNetMember"] = True
self.data.profile.put_web_option(
await self.data.profile.put_web_option(
user_id, self.version, upsert["userWebOption"][0]
)
if "userGradeStatusList" in upsert and len(upsert["userGradeStatusList"]) > 0:
self.data.profile.put_grade_status(
await self.data.profile.put_grade_status(
user_id, upsert["userGradeStatusList"][0]
)
if "userBossList" in upsert and len(upsert["userBossList"]) > 0:
self.data.profile.put_boss_list(
await self.data.profile.put_boss_list(
user_id, upsert["userBossList"][0]
)
if "userPlaylogList" in upsert and len(upsert["userPlaylogList"]) > 0:
for playlog in upsert["userPlaylogList"]:
self.data.score.put_playlog(
await self.data.score.put_playlog(
user_id, playlog, False
)
if "userExtend" in upsert and len(upsert["userExtend"]) > 0:
self.data.profile.put_profile_extend(
await self.data.profile.put_profile_extend(
user_id, self.version, upsert["userExtend"][0]
)
if "userGhost" in upsert:
for ghost in upsert["userGhost"]:
self.data.profile.put_profile_ghost(user_id, self.version, ghost)
await self.data.profile.put_profile_ghost(user_id, self.version, ghost)
if "userRecentRatingList" in upsert:
self.data.profile.put_recent_rating(user_id, upsert["userRecentRatingList"])
await self.data.profile.put_recent_rating(user_id, upsert["userRecentRatingList"])
if "userOption" in upsert and len(upsert["userOption"]) > 0:
upsert["userOption"][0].pop("userId")
self.data.profile.put_profile_option(
await self.data.profile.put_profile_option(
user_id, self.version, upsert["userOption"][0], False
)
if "userRatingList" in upsert and len(upsert["userRatingList"]) > 0:
self.data.profile.put_profile_rating(
await self.data.profile.put_profile_rating(
user_id, self.version, upsert["userRatingList"][0]
)
if "userActivityList" in upsert and len(upsert["userActivityList"]) > 0:
for act in upsert["userActivityList"]:
self.data.profile.put_profile_activity(user_id, act)
await self.data.profile.put_profile_activity(user_id, act)
if "userChargeList" in upsert and len(upsert["userChargeList"]) > 0:
for charge in upsert["userChargeList"]:
# remove the ".0" from the date string, festival only?
charge["purchaseDate"] = charge["purchaseDate"].replace(".0", "")
self.data.item.put_charge(
await self.data.item.put_charge(
user_id,
charge["chargeId"],
charge["stock"],
@@ -313,14 +313,14 @@ class Mai2Base:
if "userCharacterList" in upsert and len(upsert["userCharacterList"]) > 0:
for char in upsert["userCharacterList"]:
self.data.item.put_character_(
await self.data.item.put_character_(
user_id,
char
)
if "userItemList" in upsert and len(upsert["userItemList"]) > 0:
for item in upsert["userItemList"]:
self.data.item.put_item(
await self.data.item.put_item(
user_id,
int(item["itemKind"]),
item["itemId"],
@@ -330,7 +330,7 @@ class Mai2Base:
if "userLoginBonusList" in upsert and len(upsert["userLoginBonusList"]) > 0:
for login_bonus in upsert["userLoginBonusList"]:
self.data.item.put_login_bonus(
await self.data.item.put_login_bonus(
user_id,
login_bonus["bonusId"],
login_bonus["point"],
@@ -340,7 +340,7 @@ class Mai2Base:
if "userMapList" in upsert and len(upsert["userMapList"]) > 0:
for map in upsert["userMapList"]:
self.data.item.put_map(
await self.data.item.put_map(
user_id,
map["mapId"],
map["distance"],
@@ -351,15 +351,15 @@ class Mai2Base:
if "userMusicDetailList" in upsert and len(upsert["userMusicDetailList"]) > 0:
for music in upsert["userMusicDetailList"]:
self.data.score.put_best_score(user_id, music, False)
await self.data.score.put_best_score(user_id, music, False)
if "userCourseList" in upsert and len(upsert["userCourseList"]) > 0:
for course in upsert["userCourseList"]:
self.data.score.put_course(user_id, course)
await self.data.score.put_course(user_id, course)
if "userFavoriteList" in upsert and len(upsert["userFavoriteList"]) > 0:
for fav in upsert["userFavoriteList"]:
self.data.item.put_favorite(user_id, fav["kind"], fav["itemIdList"])
await self.data.item.put_favorite(user_id, fav["kind"], fav["itemIdList"])
if (
"userFriendSeasonRankingList" in upsert
@@ -371,15 +371,15 @@ class Mai2Base:
fsr["recordDate"], f"{Mai2Constants.DATE_TIME_FORMAT}.0"
),
)
self.data.item.put_friend_season_ranking(user_id, fsr)
await self.data.item.put_friend_season_ranking(user_id, fsr)
return {"returnCode": 1, "apiName": "UpsertUserAllApi"}
def handle_user_logout_api_request(self, data: Dict) -> Dict:
async def handle_user_logout_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1}
def handle_get_user_data_api_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile_detail(data["userId"], self.version, False)
async def handle_get_user_data_api_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile_detail(data["userId"], self.version, False)
if profile is None:
return
@@ -390,8 +390,8 @@ class Mai2Base:
return {"userId": data["userId"], "userData": profile_dict}
def handle_get_user_extend_api_request(self, data: Dict) -> Dict:
extend = self.data.profile.get_profile_extend(data["userId"], self.version)
async def handle_get_user_extend_api_request(self, data: Dict) -> Dict:
extend = await self.data.profile.get_profile_extend(data["userId"], self.version)
if extend is None:
return
@@ -402,8 +402,8 @@ class Mai2Base:
return {"userId": data["userId"], "userExtend": extend_dict}
def handle_get_user_option_api_request(self, data: Dict) -> Dict:
options = self.data.profile.get_profile_option(data["userId"], self.version, False)
async def handle_get_user_option_api_request(self, data: Dict) -> Dict:
options = await self.data.profile.get_profile_option(data["userId"], self.version, False)
if options is None:
return
@@ -414,8 +414,8 @@ class Mai2Base:
return {"userId": data["userId"], "userOption": options_dict}
def handle_get_user_card_api_request(self, data: Dict) -> Dict:
user_cards = self.data.item.get_cards(data["userId"])
async def handle_get_user_card_api_request(self, data: Dict) -> Dict:
user_cards = await self.data.item.get_cards(data["userId"])
if user_cards is None:
return {"userId": data["userId"], "nextIndex": 0, "userCardList": []}
@@ -448,8 +448,8 @@ class Mai2Base:
"userCardList": card_list[start_idx:end_idx],
}
def handle_get_user_charge_api_request(self, data: Dict) -> Dict:
user_charges = self.data.item.get_charges(data["userId"])
async def handle_get_user_charge_api_request(self, data: Dict) -> Dict:
user_charges = await self.data.item.get_charges(data["userId"])
if user_charges is None:
return {"userId": data["userId"], "length": 0, "userChargeList": []}
@@ -467,17 +467,17 @@ class Mai2Base:
"userChargeList": user_charge_list,
}
def handle_get_user_present_api_request(self, data: Dict) -> Dict:
async def handle_get_user_present_api_request(self, data: Dict) -> Dict:
return { "userId": data.get("userId", 0), "length": 0, "userPresentList": []}
def handle_get_transfer_friend_api_request(self, data: Dict) -> Dict:
async def handle_get_transfer_friend_api_request(self, data: Dict) -> Dict:
return {}
def handle_get_user_present_event_api_request(self, data: Dict) -> Dict:
async def handle_get_user_present_event_api_request(self, data: Dict) -> Dict:
return { "userId": data.get("userId", 0), "length": 0, "userPresentEventList": []}
def handle_get_user_boss_api_request(self, data: Dict) -> Dict:
b = self.data.profile.get_boss_list(data["userId"])
async def handle_get_user_boss_api_request(self, data: Dict) -> Dict:
b = await self.data.profile.get_boss_list(data["userId"])
if b is None:
return { "userId": data.get("userId", 0), "userBossData": {}}
boss_lst = b._asdict()
@@ -486,10 +486,10 @@ class Mai2Base:
return { "userId": data.get("userId", 0), "userBossData": boss_lst}
def handle_get_user_item_api_request(self, data: Dict) -> Dict:
async def handle_get_user_item_api_request(self, data: Dict) -> Dict:
kind = int(data["nextIndex"] / 10000000000)
next_idx = int(data["nextIndex"] % 10000000000)
user_item_list = self.data.item.get_items(data["userId"], kind)
user_item_list = await self.data.item.get_items(data["userId"], kind)
items: List[Dict[str, Any]] = []
for i in range(next_idx, len(user_item_list)):
@@ -514,8 +514,8 @@ class Mai2Base:
"userItemList": items,
}
def handle_get_user_character_api_request(self, data: Dict) -> Dict:
characters = self.data.item.get_characters(data["userId"])
async def handle_get_user_character_api_request(self, data: Dict) -> Dict:
characters = await self.data.item.get_characters(data["userId"])
chara_list = []
for chara in characters:
@@ -528,8 +528,8 @@ class Mai2Base:
return {"userId": data["userId"], "userCharacterList": chara_list}
def handle_get_user_favorite_api_request(self, data: Dict) -> Dict:
favorites = self.data.item.get_favorites(data["userId"], data["itemKind"])
async def handle_get_user_favorite_api_request(self, data: Dict) -> Dict:
favorites = await self.data.item.get_favorites(data["userId"], data["itemKind"])
if favorites is None:
return
@@ -545,8 +545,8 @@ class Mai2Base:
return {"userId": data["userId"], "userFavoriteData": userFavs}
def handle_get_user_ghost_api_request(self, data: Dict) -> Dict:
ghost = self.data.profile.get_profile_ghost(data["userId"], self.version)
async def handle_get_user_ghost_api_request(self, data: Dict) -> Dict:
ghost = await self.data.profile.get_profile_ghost(data["userId"], self.version)
if ghost is None:
return
@@ -557,8 +557,8 @@ class Mai2Base:
return {"userId": data["userId"], "userGhost": ghost_dict}
def handle_get_user_recent_rating_api_request(self, data: Dict) -> Dict:
rating = self.data.profile.get_recent_rating(data["userId"])
async def handle_get_user_recent_rating_api_request(self, data: Dict) -> Dict:
rating = await self.data.profile.get_recent_rating(data["userId"])
if rating is None:
return
@@ -567,8 +567,8 @@ class Mai2Base:
return {"userId": data["userId"], "length": len(lst), "userRecentRatingList": lst}
def handle_get_user_rating_api_request(self, data: Dict) -> Dict:
rating = self.data.profile.get_profile_rating(data["userId"], self.version)
async def handle_get_user_rating_api_request(self, data: Dict) -> Dict:
rating = await self.data.profile.get_profile_rating(data["userId"], self.version)
if rating is None:
return
@@ -579,12 +579,12 @@ class Mai2Base:
return {"userId": data["userId"], "userRating": rating_dict}
def handle_get_user_activity_api_request(self, data: Dict) -> Dict:
async def handle_get_user_activity_api_request(self, data: Dict) -> Dict:
"""
kind 1 is playlist, kind 2 is music list
"""
playlist = self.data.profile.get_profile_activity(data["userId"], 1)
musiclist = self.data.profile.get_profile_activity(data["userId"], 2)
playlist = await self.data.profile.get_profile_activity(data["userId"], 1)
musiclist = await self.data.profile.get_profile_activity(data["userId"], 2)
if playlist is None or musiclist is None:
return
@@ -607,8 +607,8 @@ class Mai2Base:
return {"userActivity": {"playList": plst, "musicList": mlst}}
def handle_get_user_course_api_request(self, data: Dict) -> Dict:
user_courses = self.data.score.get_courses(data["userId"])
async def handle_get_user_course_api_request(self, data: Dict) -> Dict:
user_courses = await self.data.score.get_courses(data["userId"])
if user_courses is None:
return {"userId": data["userId"], "nextIndex": 0, "userCourseList": []}
@@ -621,12 +621,12 @@ class Mai2Base:
return {"userId": data["userId"], "nextIndex": 0, "userCourseList": course_list}
def handle_get_user_portrait_api_request(self, data: Dict) -> Dict:
async def handle_get_user_portrait_api_request(self, data: Dict) -> Dict:
# No support for custom pfps
return {"length": 0, "userPortraitList": []}
def handle_get_user_friend_season_ranking_api_request(self, data: Dict) -> Dict:
friend_season_ranking = self.data.item.get_friend_season_ranking(data["userId"])
async def handle_get_user_friend_season_ranking_api_request(self, data: Dict) -> Dict:
friend_season_ranking = await self.data.item.get_friend_season_ranking(data["userId"])
if friend_season_ranking is None:
return {
"userId": data["userId"],
@@ -661,8 +661,8 @@ class Mai2Base:
"userFriendSeasonRankingList": friend_season_ranking_list,
}
def handle_get_user_map_api_request(self, data: Dict) -> Dict:
maps = self.data.item.get_maps(data["userId"])
async def handle_get_user_map_api_request(self, data: Dict) -> Dict:
maps = await self.data.item.get_maps(data["userId"])
if maps is None:
return {
"userId": data["userId"],
@@ -694,8 +694,8 @@ class Mai2Base:
"userMapList": map_list,
}
def handle_get_user_login_bonus_api_request(self, data: Dict) -> Dict:
login_bonuses = self.data.item.get_login_bonuses(data["userId"])
async def handle_get_user_login_bonus_api_request(self, data: Dict) -> Dict:
login_bonuses = await self.data.item.get_login_bonuses(data["userId"])
if login_bonuses is None:
return {
"userId": data["userId"],
@@ -727,11 +727,11 @@ class Mai2Base:
"userLoginBonusList": login_bonus_list,
}
def handle_get_user_region_api_request(self, data: Dict) -> Dict:
async def handle_get_user_region_api_request(self, data: Dict) -> Dict:
return {"userId": data["userId"], "length": 0, "userRegionList": []}
def handle_get_user_web_option_api_request(self, data: Dict) -> Dict:
w = self.data.profile.get_web_option(data["userId"], self.version)
async def handle_get_user_web_option_api_request(self, data: Dict) -> Dict:
w = await self.data.profile.get_web_option(data["userId"], self.version)
if w is None:
return {"userId": data["userId"], "userWebOption": {}}
@@ -742,11 +742,11 @@ class Mai2Base:
return {"userId": data["userId"], "userWebOption": web_opt}
def handle_get_user_survival_api_request(self, data: Dict) -> Dict:
async def handle_get_user_survival_api_request(self, data: Dict) -> Dict:
return {"userId": data["userId"], "length": 0, "userSurvivalList": []}
def handle_get_user_grade_api_request(self, data: Dict) -> Dict:
g = self.data.profile.get_grade_status(data["userId"])
async def handle_get_user_grade_api_request(self, data: Dict) -> Dict:
g = await self.data.profile.get_grade_status(data["userId"])
if g is None:
return {"userId": data["userId"], "userGradeStatus": {}, "length": 0, "userGradeList": []}
grade_stat = g._asdict()
@@ -755,7 +755,7 @@ class Mai2Base:
return {"userId": data["userId"], "userGradeStatus": grade_stat, "length": 0, "userGradeList": []}
def handle_get_user_music_api_request(self, data: Dict) -> Dict:
async def handle_get_user_music_api_request(self, data: Dict) -> Dict:
user_id = data.get("userId", 0)
next_index = data.get("nextIndex", 0)
max_ct = data.get("maxCount", 50)
@@ -766,7 +766,7 @@ class Mai2Base:
self.logger.warning("handle_get_user_music_api_request: Could not find userid in data, or userId is 0")
return {}
songs = self.data.score.get_best_scores(user_id, is_dx=False)
songs = await self.data.score.get_best_scores(user_id, is_dx=False)
if songs is None:
self.logger.debug("handle_get_user_music_api_request: get_best_scores returned None!")
return {
@@ -794,10 +794,10 @@ class Mai2Base:
"userMusicList": [{"userMusicDetailList": music_detail_list}],
}
def handle_upload_user_portrait_api_request(self, data: Dict) -> Dict:
async def handle_upload_user_portrait_api_request(self, data: Dict) -> Dict:
self.logger.debug(data)
def handle_upload_user_photo_api_request(self, data: Dict) -> Dict:
async def handle_upload_user_photo_api_request(self, data: Dict) -> Dict:
if not self.game_config.uploads.photos or not self.game_config.uploads.photos_dir:
return {'returnCode': 0, 'apiName': 'UploadUserPhotoApi'}

View File

@@ -15,7 +15,7 @@ class Mai2DX(Mai2Base):
super().__init__(cfg, game_cfg)
self.version = Mai2Constants.VER_MAIMAI_DX
def handle_get_game_setting_api_request(self, data: Dict):
async def handle_get_game_setting_api_request(self, data: Dict):
return {
"gameSetting": {
"isMaintenance": False,
@@ -33,9 +33,9 @@ class Mai2DX(Mai2Base):
"isAouAccession": False,
}
def handle_get_user_preview_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile_detail(data["userId"], self.version)
o = self.data.profile.get_profile_option(data["userId"], self.version)
async def handle_get_user_preview_api_request(self, data: Dict) -> Dict:
p = await self.data.profile.get_profile_detail(data["userId"], self.version)
o = await self.data.profile.get_profile_option(data["userId"], self.version)
if p is None or o is None:
return {} # Register
profile = p._asdict()
@@ -69,21 +69,21 @@ class Mai2DX(Mai2Base):
else 0, # New with uni+
}
def handle_upload_user_playlog_api_request(self, data: Dict) -> Dict:
async def handle_upload_user_playlog_api_request(self, data: Dict) -> Dict:
user_id = data["userId"]
playlog = data["userPlaylog"]
self.data.score.put_playlog(user_id, playlog)
await self.data.score.put_playlog(user_id, playlog)
return {"returnCode": 1, "apiName": "UploadUserPlaylogApi"}
def handle_upsert_user_chargelog_api_request(self, data: Dict) -> Dict:
async def handle_upsert_user_chargelog_api_request(self, data: Dict) -> Dict:
user_id = data["userId"]
charge = data["userCharge"]
# remove the ".0" from the date string, festival only?
charge["purchaseDate"] = charge["purchaseDate"].replace(".0", "")
self.data.item.put_charge(
await self.data.item.put_charge(
user_id,
charge["chargeId"],
charge["stock"],
@@ -93,7 +93,7 @@ class Mai2DX(Mai2Base):
return {"returnCode": 1, "apiName": "UpsertUserChargelogApi"}
def handle_upsert_user_all_api_request(self, data: Dict) -> Dict:
async def handle_upsert_user_all_api_request(self, data: Dict) -> Dict:
user_id = data["userId"]
upsert = data["upsertUserAll"]
@@ -104,39 +104,39 @@ class Mai2DX(Mai2Base):
if "userData" in upsert and len(upsert["userData"]) > 0:
upsert["userData"][0]["isNetMember"] = 1
upsert["userData"][0].pop("accessCode")
self.data.profile.put_profile_detail(
await self.data.profile.put_profile_detail(
user_id, self.version, upsert["userData"][0]
)
if "userExtend" in upsert and len(upsert["userExtend"]) > 0:
self.data.profile.put_profile_extend(
await self.data.profile.put_profile_extend(
user_id, self.version, upsert["userExtend"][0]
)
if "userGhost" in upsert:
for ghost in upsert["userGhost"]:
self.data.profile.put_profile_ghost(user_id, self.version, ghost)
await self.data.profile.put_profile_ghost(user_id, self.version, ghost)
if "userOption" in upsert and len(upsert["userOption"]) > 0:
self.data.profile.put_profile_option(
await self.data.profile.put_profile_option(
user_id, self.version, upsert["userOption"][0]
)
if "userRatingList" in upsert and len(upsert["userRatingList"]) > 0:
self.data.profile.put_profile_rating(
await self.data.profile.put_profile_rating(
user_id, self.version, upsert["userRatingList"][0]
)
if "userActivityList" in upsert and len(upsert["userActivityList"]) > 0:
for k, v in upsert["userActivityList"][0].items():
for act in v:
self.data.profile.put_profile_activity(user_id, act)
await self.data.profile.put_profile_activity(user_id, act)
if "userChargeList" in upsert and len(upsert["userChargeList"]) > 0:
for charge in upsert["userChargeList"]:
# remove the ".0" from the date string, festival only?
charge["purchaseDate"] = charge["purchaseDate"].replace(".0", "")
self.data.item.put_charge(
await self.data.item.put_charge(
user_id,
charge["chargeId"],
charge["stock"],
@@ -150,7 +150,7 @@ class Mai2DX(Mai2Base):
if "userCharacterList" in upsert and len(upsert["userCharacterList"]) > 0:
for char in upsert["userCharacterList"]:
self.data.item.put_character(
await self.data.item.put_character(
user_id,
char["characterId"],
char["level"],
@@ -160,7 +160,7 @@ class Mai2DX(Mai2Base):
if "userItemList" in upsert and len(upsert["userItemList"]) > 0:
for item in upsert["userItemList"]:
self.data.item.put_item(
await self.data.item.put_item(
user_id,
int(item["itemKind"]),
item["itemId"],
@@ -170,7 +170,7 @@ class Mai2DX(Mai2Base):
if "userLoginBonusList" in upsert and len(upsert["userLoginBonusList"]) > 0:
for login_bonus in upsert["userLoginBonusList"]:
self.data.item.put_login_bonus(
await self.data.item.put_login_bonus(
user_id,
login_bonus["bonusId"],
login_bonus["point"],
@@ -180,7 +180,7 @@ class Mai2DX(Mai2Base):
if "userMapList" in upsert and len(upsert["userMapList"]) > 0:
for map in upsert["userMapList"]:
self.data.item.put_map(
await self.data.item.put_map(
user_id,
map["mapId"],
map["distance"],
@@ -191,15 +191,15 @@ class Mai2DX(Mai2Base):
if "userMusicDetailList" in upsert and len(upsert["userMusicDetailList"]) > 0:
for music in upsert["userMusicDetailList"]:
self.data.score.put_best_score(user_id, music)
await self.data.score.put_best_score(user_id, music)
if "userCourseList" in upsert and len(upsert["userCourseList"]) > 0:
for course in upsert["userCourseList"]:
self.data.score.put_course(user_id, course)
await self.data.score.put_course(user_id, course)
if "userFavoriteList" in upsert and len(upsert["userFavoriteList"]) > 0:
for fav in upsert["userFavoriteList"]:
self.data.item.put_favorite(user_id, fav["kind"], fav["itemIdList"])
await self.data.item.put_favorite(user_id, fav["kind"], fav["itemIdList"])
if (
"userFriendSeasonRankingList" in upsert
@@ -211,12 +211,12 @@ class Mai2DX(Mai2Base):
fsr["recordDate"], f"{Mai2Constants.DATE_TIME_FORMAT}.0"
),
)
self.data.item.put_friend_season_ranking(user_id, fsr)
await self.data.item.put_friend_season_ranking(user_id, fsr)
return {"returnCode": 1, "apiName": "UpsertUserAllApi"}
def handle_get_user_data_api_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile_detail(data["userId"], self.version)
async def handle_get_user_data_api_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile_detail(data["userId"], self.version)
if profile is None:
return
@@ -227,8 +227,8 @@ class Mai2DX(Mai2Base):
return {"userId": data["userId"], "userData": profile_dict}
def handle_get_user_extend_api_request(self, data: Dict) -> Dict:
extend = self.data.profile.get_profile_extend(data["userId"], self.version)
async def handle_get_user_extend_api_request(self, data: Dict) -> Dict:
extend = await self.data.profile.get_profile_extend(data["userId"], self.version)
if extend is None:
return
@@ -239,8 +239,8 @@ class Mai2DX(Mai2Base):
return {"userId": data["userId"], "userExtend": extend_dict}
def handle_get_user_option_api_request(self, data: Dict) -> Dict:
options = self.data.profile.get_profile_option(data["userId"], self.version)
async def handle_get_user_option_api_request(self, data: Dict) -> Dict:
options = await self.data.profile.get_profile_option(data["userId"], self.version)
if options is None:
return
@@ -251,8 +251,8 @@ class Mai2DX(Mai2Base):
return {"userId": data["userId"], "userOption": options_dict}
def handle_get_user_card_api_request(self, data: Dict) -> Dict:
user_cards = self.data.item.get_cards(data["userId"])
async def handle_get_user_card_api_request(self, data: Dict) -> Dict:
user_cards = await self.data.item.get_cards(data["userId"])
if user_cards is None:
return {"userId": data["userId"], "nextIndex": 0, "userCardList": []}
@@ -285,8 +285,8 @@ class Mai2DX(Mai2Base):
"userCardList": card_list[start_idx:end_idx],
}
def handle_get_user_charge_api_request(self, data: Dict) -> Dict:
user_charges = self.data.item.get_charges(data["userId"])
async def handle_get_user_charge_api_request(self, data: Dict) -> Dict:
user_charges = await self.data.item.get_charges(data["userId"])
if user_charges is None:
return {"userId": data["userId"], "length": 0, "userChargeList": []}
@@ -310,10 +310,10 @@ class Mai2DX(Mai2Base):
"userChargeList": user_charge_list,
}
def handle_get_user_item_api_request(self, data: Dict) -> Dict:
async def handle_get_user_item_api_request(self, data: Dict) -> Dict:
kind = int(data["nextIndex"] / 10000000000)
next_idx = int(data["nextIndex"] % 10000000000)
user_item_list = self.data.item.get_items(data["userId"], kind)
user_item_list = await self.data.item.get_items(data["userId"], kind)
items: List[Dict[str, Any]] = []
for i in range(next_idx, len(user_item_list)):
@@ -338,8 +338,8 @@ class Mai2DX(Mai2Base):
"userItemList": items,
}
def handle_get_user_character_api_request(self, data: Dict) -> Dict:
characters = self.data.item.get_characters(data["userId"])
async def handle_get_user_character_api_request(self, data: Dict) -> Dict:
characters = await self.data.item.get_characters(data["userId"])
chara_list = []
for chara in characters:
@@ -350,8 +350,8 @@ class Mai2DX(Mai2Base):
return {"userId": data["userId"], "userCharacterList": chara_list}
def handle_get_user_favorite_api_request(self, data: Dict) -> Dict:
favorites = self.data.item.get_favorites(data["userId"], data["itemKind"])
async def handle_get_user_favorite_api_request(self, data: Dict) -> Dict:
favorites = await self.data.item.get_favorites(data["userId"], data["itemKind"])
if favorites is None:
return
@@ -367,8 +367,8 @@ class Mai2DX(Mai2Base):
return {"userId": data["userId"], "userFavoriteData": userFavs}
def handle_get_user_ghost_api_request(self, data: Dict) -> Dict:
ghost = self.data.profile.get_profile_ghost(data["userId"], self.version)
async def handle_get_user_ghost_api_request(self, data: Dict) -> Dict:
ghost = await self.data.profile.get_profile_ghost(data["userId"], self.version)
if ghost is None:
return
@@ -379,8 +379,8 @@ class Mai2DX(Mai2Base):
return {"userId": data["userId"], "userGhost": ghost_dict}
def handle_get_user_rating_api_request(self, data: Dict) -> Dict:
rating = self.data.profile.get_profile_rating(data["userId"], self.version)
async def handle_get_user_rating_api_request(self, data: Dict) -> Dict:
rating = await self.data.profile.get_profile_rating(data["userId"], self.version)
if rating is None:
return
@@ -391,12 +391,12 @@ class Mai2DX(Mai2Base):
return {"userId": data["userId"], "userRating": rating_dict}
def handle_get_user_activity_api_request(self, data: Dict) -> Dict:
async def handle_get_user_activity_api_request(self, data: Dict) -> Dict:
"""
kind 1 is playlist, kind 2 is music list
"""
playlist = self.data.profile.get_profile_activity(data["userId"], 1)
musiclist = self.data.profile.get_profile_activity(data["userId"], 2)
playlist = await self.data.profile.get_profile_activity(data["userId"], 1)
musiclist = await self.data.profile.get_profile_activity(data["userId"], 2)
if playlist is None or musiclist is None:
return
@@ -419,8 +419,8 @@ class Mai2DX(Mai2Base):
return {"userActivity": {"playList": plst, "musicList": mlst}}
def handle_get_user_course_api_request(self, data: Dict) -> Dict:
user_courses = self.data.score.get_courses(data["userId"])
async def handle_get_user_course_api_request(self, data: Dict) -> Dict:
user_courses = await self.data.score.get_courses(data["userId"])
if user_courses is None:
return {"userId": data["userId"], "nextIndex": 0, "userCourseList": []}
@@ -433,12 +433,12 @@ class Mai2DX(Mai2Base):
return {"userId": data["userId"], "nextIndex": 0, "userCourseList": course_list}
def handle_get_user_portrait_api_request(self, data: Dict) -> Dict:
async def handle_get_user_portrait_api_request(self, data: Dict) -> Dict:
# No support for custom pfps
return {"length": 0, "userPortraitList": []}
def handle_get_user_friend_season_ranking_api_request(self, data: Dict) -> Dict:
friend_season_ranking = self.data.item.get_friend_season_ranking(data["userId"])
async def handle_get_user_friend_season_ranking_api_request(self, data: Dict) -> Dict:
friend_season_ranking = await self.data.item.get_friend_season_ranking(data["userId"])
if friend_season_ranking is None:
return {
"userId": data["userId"],
@@ -473,8 +473,8 @@ class Mai2DX(Mai2Base):
"userFriendSeasonRankingList": friend_season_ranking_list,
}
def handle_get_user_map_api_request(self, data: Dict) -> Dict:
maps = self.data.item.get_maps(data["userId"])
async def handle_get_user_map_api_request(self, data: Dict) -> Dict:
maps = await self.data.item.get_maps(data["userId"])
if maps is None:
return {
"userId": data["userId"],
@@ -506,8 +506,8 @@ class Mai2DX(Mai2Base):
"userMapList": map_list,
}
def handle_get_user_login_bonus_api_request(self, data: Dict) -> Dict:
login_bonuses = self.data.item.get_login_bonuses(data["userId"])
async def handle_get_user_login_bonus_api_request(self, data: Dict) -> Dict:
login_bonuses = await self.data.item.get_login_bonuses(data["userId"])
if login_bonuses is None:
return {
"userId": data["userId"],
@@ -539,7 +539,7 @@ class Mai2DX(Mai2Base):
"userLoginBonusList": login_bonus_list,
}
def handle_get_user_region_api_request(self, data: Dict) -> Dict:
async def handle_get_user_region_api_request(self, data: Dict) -> Dict:
"""
class UserRegionList:
regionId: int
@@ -548,7 +548,7 @@ class Mai2DX(Mai2Base):
"""
return {"userId": data["userId"], "length": 0, "userRegionList": []}
def handle_get_user_rival_data_api_request(self, data: Dict) -> Dict:
async def handle_get_user_rival_data_api_request(self, data: Dict) -> Dict:
user_id = data["userId"]
rival_id = data["rivalId"]
@@ -559,7 +559,7 @@ class Mai2DX(Mai2Base):
"""
return {"userId": user_id, "userRivalData": {}}
def handle_get_user_rival_music_api_request(self, data: Dict) -> Dict:
async def handle_get_user_rival_music_api_request(self, data: Dict) -> Dict:
user_id = data["userId"]
rival_id = data["rivalId"]
next_idx = data["nextIndex"]
@@ -577,7 +577,7 @@ class Mai2DX(Mai2Base):
"""
return {"userId": user_id, "nextIndex": 0, "userRivalMusicList": []}
def handle_get_user_music_api_request(self, data: Dict) -> Dict:
async def handle_get_user_music_api_request(self, data: Dict) -> Dict:
user_id = data.get("userId", 0)
next_index = data.get("nextIndex", 0)
max_ct = data.get("maxCount", 50)
@@ -588,7 +588,7 @@ class Mai2DX(Mai2Base):
self.logger.warning("handle_get_user_music_api_request: Could not find userid in data, or userId is 0")
return {}
songs = self.data.score.get_best_scores(user_id)
songs = await self.data.score.get_best_scores(user_id)
if songs is None:
self.logger.debug("handle_get_user_music_api_request: get_best_scores returned None!")
return {
@@ -616,8 +616,8 @@ class Mai2DX(Mai2Base):
"userMusicList": [{"userMusicDetailList": music_detail_list}],
}
def handle_user_login_api_request(self, data: Dict) -> Dict:
ret = super().handle_user_login_api_request(data)
async def handle_user_login_api_request(self, data: Dict) -> Dict:
ret = await super().handle_user_login_api_request(data)
if ret is None or not ret:
return ret
ret['loginId'] = ret.get('loginCount', 0)

View File

@@ -11,26 +11,26 @@ class Mai2Festival(Mai2UniversePlus):
super().__init__(cfg, game_cfg)
self.version = Mai2Constants.VER_MAIMAI_DX_FESTIVAL
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = super().handle_cm_get_user_preview_api_request(data)
async def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = await super().handle_cm_get_user_preview_api_request(data)
# hardcode lastDataVersion for CardMaker
user_data["lastDataVersion"] = "1.30.00"
return user_data
def handle_user_login_api_request(self, data: Dict) -> Dict:
user_login = super().handle_user_login_api_request(data)
async def handle_user_login_api_request(self, data: Dict) -> Dict:
user_login = await super().handle_user_login_api_request(data)
# useless?
user_login["Bearer"] = "ARTEMiSTOKEN"
return user_login
def handle_get_user_recommend_rate_music_api_request(self, data: Dict) -> Dict:
async def handle_get_user_recommend_rate_music_api_request(self, data: Dict) -> Dict:
"""
userRecommendRateMusicIdList: list[int]
"""
return {"userId": data["userId"], "userRecommendRateMusicIdList": []}
def handle_get_user_recommend_select_music_api_request(self, data: Dict) -> Dict:
async def handle_get_user_recommend_select_music_api_request(self, data: Dict) -> Dict:
"""
userRecommendSelectionMusicIdList: list[int]
"""

View File

@@ -11,14 +11,14 @@ class Mai2FestivalPlus(Mai2Festival):
super().__init__(cfg, game_cfg)
self.version = Mai2Constants.VER_MAIMAI_DX_FESTIVAL_PLUS
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = super().handle_cm_get_user_preview_api_request(data)
async def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = await super().handle_cm_get_user_preview_api_request(data)
# hardcode lastDataVersion for CardMaker
user_data["lastDataVersion"] = "1.35.00"
return user_data
def handle_get_user_favorite_item_api_request(self, data: Dict) -> Dict:
async def handle_get_user_favorite_item_api_request(self, data: Dict) -> Dict:
user_id = data.get("userId", 0)
kind = data.get("kind", 2)
next_index = data.get("nextIndex", 0)

View File

@@ -1,9 +1,9 @@
from twisted.web.http import Request
from twisted.web.server import NOT_DONE_YET
from starlette.requests import Request
from starlette.responses import Response, JSONResponse
from starlette.routing import Route
import json
import inflection
import yaml
import string
import logging, coloredlogs
import zlib
from logging.handlers import TimedRotatingFileHandler
@@ -101,33 +101,29 @@ class Mai2Servlet(BaseServlet):
return True
def get_endpoint_matchers(self) -> Tuple[List[Tuple[str, str, Dict]], List[Tuple[str, str, Dict]]]:
return (
[
("handle_movie", "/{version}/MaimaiServlet/api/movie/{endpoint}", {}),
("handle_old_srv", "/{version}/MaimaiServlet/old/{endpoint}", {}),
("handle_old_srv_userdata", "/{version}/MaimaiServlet/old/{endpoint}/{placeid}/{keychip}/{userid}", {}),
("handle_old_srv_userdata", "/{version}/MaimaiServlet/old/{endpoint}/{userid}", {}),
("handle_usbdl", "/{version}/MaimaiServlet/usbdl/{endpoint}", {}),
("handle_deliver", "/{version}/MaimaiServlet/deliver/{endpoint}", {}),
],
[
("handle_movie", "/{version}/MaimaiServlet/api/movie/{endpoint}", {}),
("handle_mai", "/{version}/MaimaiServlet/{endpoint}", {}),
("handle_mai2", "/{version}/Maimai2Servlet/{endpoint}", {}),
]
)
def get_routes(self) -> List[Route]:
return [
Route("/{version:int}/MaimaiServlet/api/movie/{endpoint:str}", self.handle_movie, methods=['GET', 'POST']),
Route("/{version:int}/MaimaiServlet/old/{endpoint:str}", self.handle_old_srv),
Route("/{version:int}/MaimaiServlet/old/{endpoint:str}/{placeid:str}/{keychip:str}/{userid:int}", self.handle_old_srv_userdata),
Route("/{version:int}/MaimaiServlet/old/{endpoint:str}/{userid:int}", self.handle_old_srv_userdata),
Route("/{version:int}/MaimaiServlet/old/{endpoint:str}/{userid:int}", self.handle_old_srv_userdata),
Route("/{version:int}/MaimaiServlet/usbdl/{endpoint:str}", self.handle_usbdl),
Route("/{version:int}/MaimaiServlet/deliver/{endpoint:str}", self.handle_deliver),
Route("/{version:int}/MaimaiServlet/{endpoint:str}", self.handle_mai, methods=['POST']),
Route("/{version:int}/Maimai2Servlet/{endpoint:str}", self.handle_mai2, methods=['POST']),
]
def get_allnet_info(self, game_code: str, game_ver: int, keychip: str) -> Tuple[str, str]:
if not self.core_cfg.server.is_using_proxy and Utils.get_title_port(self.core_cfg) != 80:
return (
f"http://{self.core_cfg.title.hostname}:{Utils.get_title_port(self.core_cfg)}/{game_ver}/",
f"{self.core_cfg.title.hostname}",
f"http://{self.core_cfg.server.hostname}:{Utils.get_title_port(self.core_cfg)}/{game_ver}/",
f"{self.core_cfg.server.hostname}",
)
return (
f"http://{self.core_cfg.title.hostname}/{game_ver}/",
f"{self.core_cfg.title.hostname}",
f"http://{self.core_cfg.server.hostname}/{game_ver}/",
f"{self.core_cfg.server.hostname}",
)
def setup(self):
@@ -155,13 +151,22 @@ class Mai2Servlet(BaseServlet):
f"Failed to make movie upload directory at {self.game_cfg.uploads.movies_dir}"
)
def handle_mai(self, request: Request, game_code: str, matchers: Dict) -> bytes:
endpoint = matchers['endpoint']
version = int(matchers['version'])
async def handle_movie(self, request: Request):
return JSONResponse()
async def handle_usbdl(self, request: Request):
return Response("OK")
async def handle_deliver(self, request: Request):
return Response(status_code=404)
async def handle_mai(self, request: Request) -> bytes:
endpoint: str = request.path_params.get('endpoint')
version: int = request.path_params.get('version')
if endpoint.lower() == "ping":
return zlib.compress(b'{"returnCode": "1"}')
return Response(zlib.compress(b'{"returnCode": "1"}'))
req_raw = request.content.getvalue()
req_raw = await request.body()
internal_ver = 0
client_ip = Utils.get_ip_addr(request)
@@ -199,7 +204,7 @@ class Mai2Servlet(BaseServlet):
self.logger.error(
f"Failed to decompress v{version} {endpoint} request -> {e}"
)
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
req_data = json.loads(unzip)
@@ -216,26 +221,26 @@ class Mai2Servlet(BaseServlet):
else:
try:
handler = getattr(handler_cls, func_to_find)
resp = handler(req_data)
resp = await handler(req_data)
except Exception as e:
self.logger.error(f"Error handling v{version} method {endpoint} - {e}")
return zlib.compress(b'{"returnCode": "0"}')
return Response(zlib.compress(b'{"returnCode": "0"}'))
if resp == None:
resp = {"returnCode": 1}
self.logger.debug(f"Response {resp}")
return zlib.compress(json.dumps(resp, ensure_ascii=False).encode("utf-8"))
return Response(zlib.compress(json.dumps(resp, ensure_ascii=False).encode("utf-8")))
def handle_mai2(self, request: Request, game_code: str, matchers: Dict) -> bytes:
endpoint = matchers['endpoint']
version = int(matchers['version'])
async def handle_mai2(self, request: Request) -> bytes:
endpoint: str = request.path_params.get('endpoint')
version: int = request.path_params.get('version')
if endpoint.lower() == "ping":
return zlib.compress(b'{"returnCode": "1"}')
return Response(zlib.compress(b'{"returnCode": "1"}'))
req_raw = request.content.getvalue()
req_raw = await request.body()
internal_ver = 0
client_ip = Utils.get_ip_addr(request)
if version < 105: # 1.0
@@ -256,17 +261,17 @@ class Mai2Servlet(BaseServlet):
internal_ver = Mai2Constants.VER_MAIMAI_DX_FESTIVAL_PLUS
if (
request.getHeader("Mai-Encoding") is not None
or request.getHeader("X-Mai-Encoding") is not None
request.headers.get("Mai-Encoding") is not None
or request.headers.get("X-Mai-Encoding") is not None
):
# The has is some flavor of MD5 of the endpoint with a constant bolted onto the end of it.
# See cake.dll's Obfuscator function for details. Hopefully most DLL edits will remove
# these two(?) headers to not cause issues, but given the general quality of SEGA data...
enc_ver = request.getHeader("Mai-Encoding")
enc_ver = request.headers.get("Mai-Encoding")
if enc_ver is None:
enc_ver = request.getHeader("X-Mai-Encoding")
enc_ver = request.headers.get("X-Mai-Encoding")
self.logger.debug(
f"Encryption v{enc_ver} - User-Agent: {request.getHeader('User-Agent')}"
f"Encryption v{enc_ver} - User-Agent: {request.headers.get('User-Agent')}"
)
try:
@@ -276,7 +281,7 @@ class Mai2Servlet(BaseServlet):
self.logger.error(
f"Failed to decompress v{version} {endpoint} request -> {e}"
)
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
req_data = json.loads(unzip)
@@ -293,80 +298,27 @@ class Mai2Servlet(BaseServlet):
else:
try:
handler = getattr(handler_cls, func_to_find)
resp = handler(req_data)
resp = await handler(req_data)
except Exception as e:
self.logger.error(f"Error handling v{version} method {endpoint} - {e}")
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
if resp == None:
resp = {"returnCode": 1}
self.logger.debug(f"Response {resp}")
return zlib.compress(json.dumps(resp, ensure_ascii=False).encode("utf-8"))
return Response(zlib.compress(json.dumps(resp, ensure_ascii=False).encode("utf-8")))
def handle_old_srv(self, request: Request, game_code: str, matchers: Dict) -> bytes:
endpoint = matchers['endpoint']
version = matchers['version']
async def handle_old_srv(self, request: Request) -> bytes:
endpoint = request.path_params.get('endpoint')
version = request.path_params.get('version')
self.logger.info(f"v{version} old server {endpoint}")
return zlib.compress(b"ok")
return Response(zlib.compress(b"ok"))
def handle_old_srv_userdata(self, request: Request, game_code: str, matchers: Dict) -> bytes:
endpoint = matchers['endpoint']
version = matchers['version']
async def handle_old_srv_userdata(self, request: Request) -> bytes:
endpoint = request.path_params.get('endpoint')
version = request.path_params.get('version')
self.logger.info(f"v{version} old server {endpoint}")
return zlib.compress(b"{}")
def render_GET(self, request: Request, version: int, url_path: str) -> bytes:
self.logger.debug(f"v{version} GET {url_path}")
url_split = url_path.split("/")
if (url_split[0] == "api" and url_split[1] == "movie") or url_split[
0
] == "movie":
if url_split[2] == "moviestart":
return json.dumps({"moviestart": {"status": "OK"}}).encode()
else:
request.setResponseCode(404)
return b""
elif url_split[0] == "usbdl":
if url_split[1] == "CONNECTIONTEST":
self.logger.info(f"v{version} usbdl server test")
return b""
elif self.game_cfg.deliver.udbdl_enable and path.exists(
f"{self.game_cfg.deliver.content_folder}/usb/{url_split[-1]}"
):
with open(
f"{self.game_cfg.deliver.content_folder}/usb/{url_split[-1]}", "rb"
) as f:
return f.read()
else:
request.setResponseCode(404)
return b""
elif url_split[0] == "deliver":
file = url_split[len(url_split) - 1]
self.logger.info(f"v{version} {file} deliver inquire")
self.logger.debug(
f"{self.game_cfg.deliver.content_folder}/net_deliver/{file}"
)
if self.game_cfg.deliver.enable and path.exists(
f"{self.game_cfg.deliver.content_folder}/net_deliver/{file}"
):
with open(
f"{self.game_cfg.deliver.content_folder}/net_deliver/{file}", "rb"
) as f:
return f.read()
else:
request.setResponseCode(404)
return b""
else:
return zlib.compress(b"{}")
return Response(zlib.compress(b"{}"))

View File

@@ -35,7 +35,7 @@ class Mai2Reader(BaseReader):
self.logger.error(f"Invalid maimai DX version {version}")
exit(1)
def read(self) -> None:
async def read(self) -> None:
data_dirs = []
if self.version >= Mai2Constants.VER_MAIMAI_DX:
if self.bin_dir is not None:
@@ -46,10 +46,10 @@ class Mai2Reader(BaseReader):
for dir in data_dirs:
self.logger.info(f"Read from {dir}")
self.get_events(f"{dir}/event")
self.disable_events(f"{dir}/information", f"{dir}/scoreRanking")
self.read_music(f"{dir}/music")
self.read_tickets(f"{dir}/ticket")
await self.get_events(f"{dir}/event")
await self.disable_events(f"{dir}/information", f"{dir}/scoreRanking")
await self.read_music(f"{dir}/music")
await self.read_tickets(f"{dir}/ticket")
else:
if not os.path.exists(f"{self.bin_dir}/tables"):
@@ -70,16 +70,16 @@ class Mai2Reader(BaseReader):
txt_table = self.load_table_raw(f"{self.bin_dir}/tables", "mmtextout_jp.bin", key)
score_table = self.load_table_raw(f"{self.bin_dir}/tables", "mmScore.bin", key)
self.read_old_events(evt_table)
self.read_old_music(score_table, txt_table)
await self.read_old_events(evt_table)
await self.read_old_music(score_table, txt_table)
if self.opt_dir is not None:
evt_table = self.load_table_raw(f"{self.opt_dir}/tables", "mmEvent.bin", key)
txt_table = self.load_table_raw(f"{self.opt_dir}/tables", "mmtextout_jp.bin", key)
score_table = self.load_table_raw(f"{self.opt_dir}/tables", "mmScore.bin", key)
self.read_old_events(evt_table)
self.read_old_music(score_table, txt_table)
await self.read_old_events(evt_table)
await self.read_old_music(score_table, txt_table)
return
@@ -179,7 +179,7 @@ class Mai2Reader(BaseReader):
self.logger.warning("Failed load table content, skipping")
return
def get_events(self, base_dir: str) -> None:
async def get_events(self, base_dir: str) -> None:
self.logger.info(f"Reading events from {base_dir}...")
for root, dirs, files in os.walk(base_dir):
@@ -192,12 +192,12 @@ class Mai2Reader(BaseReader):
id = int(troot.find("name").find("id").text)
event_type = int(troot.find("infoType").text)
self.data.static.put_game_event(
await self.data.static.put_game_event(
self.version, event_type, id, name
)
self.logger.info(f"Added event {id}...")
def disable_events(
async def disable_events(
self, base_information_dir: str, base_score_ranking_dir: str
) -> None:
self.logger.info(f"Reading disabled events from {base_information_dir}...")
@@ -210,7 +210,7 @@ class Mai2Reader(BaseReader):
event_id = int(troot.find("name").find("id").text)
self.data.static.toggle_game_event(
await self.data.static.toggle_game_event(
self.version, event_id, toggle=False
)
self.logger.info(f"Disabled event {event_id}...")
@@ -223,7 +223,7 @@ class Mai2Reader(BaseReader):
event_id = int(troot.find("eventName").find("id").text)
self.data.static.toggle_game_event(
await self.data.static.toggle_game_event(
self.version, event_id, toggle=False
)
self.logger.info(f"Disabled event {event_id}...")
@@ -252,10 +252,10 @@ class Mai2Reader(BaseReader):
22091518,
22091519,
]:
self.data.static.toggle_game_event(self.version, event_id, toggle=False)
await self.data.static.toggle_game_event(self.version, event_id, toggle=False)
self.logger.info(f"Disabled event {event_id}...")
def read_music(self, base_dir: str) -> None:
async def read_music(self, base_dir: str) -> None:
self.logger.info(f"Reading music from {base_dir}...")
for root, dirs, files in os.walk(base_dir):
@@ -285,7 +285,7 @@ class Mai2Reader(BaseReader):
dif.find("notesDesigner").find("str").text
)
self.data.static.put_game_music(
await self.data.static.put_game_music(
self.version,
song_id,
chart_id,
@@ -302,7 +302,7 @@ class Mai2Reader(BaseReader):
f"Added music id {song_id} chart {chart_id}"
)
def read_tickets(self, base_dir: str) -> None:
async def read_tickets(self, base_dir: str) -> None:
self.logger.info(f"Reading tickets from {base_dir}...")
for root, dirs, files in os.walk(base_dir):
@@ -316,12 +316,12 @@ class Mai2Reader(BaseReader):
ticket_type = int(troot.find("ticketKind").find("id").text)
price = int(troot.find("creditNum").text)
self.data.static.put_game_ticket(
await self.data.static.put_game_ticket(
self.version, id, ticket_type, price, name
)
self.logger.info(f"Added ticket {id}...")
def read_old_events(self, events: Optional[List[Dict[str, str]]]) -> None:
async def read_old_events(self, events: Optional[List[Dict[str, str]]]) -> None:
if events is None:
return
@@ -332,12 +332,12 @@ class Mai2Reader(BaseReader):
is_aou = bool(int(event.get('AOU許可', '0')))
name = event.get('comment', f'evt_{evt_id}')
self.data.static.put_game_event(self.version, 0, evt_id, name)
await self.data.static.put_game_event(self.version, 0, evt_id, name)
if not (is_exp or is_aou):
self.data.static.toggle_game_event(self.version, evt_id, False)
await self.data.static.toggle_game_event(self.version, evt_id, False)
def read_old_music(self, scores: Optional[List[Dict[str, str]]], text: Optional[List[Dict[str, str]]]) -> None:
async def read_old_music(self, scores: Optional[List[Dict[str, str]]], text: Optional[List[Dict[str, str]]]) -> None:
if scores is None or text is None:
return
# TODO

View File

@@ -186,7 +186,7 @@ print_detail = Table(
class Mai2ItemData(BaseData):
def put_item(
async def put_item(
self, user_id: int, item_kind: int, item_id: int, stock: int, is_valid: bool
) -> None:
sql = insert(item).values(
@@ -202,7 +202,7 @@ class Mai2ItemData(BaseData):
isValid=is_valid,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_item: failed to insert item! user_id: {user_id}, item_kind: {item_kind}, item_id: {item_id}"
@@ -210,7 +210,7 @@ class Mai2ItemData(BaseData):
return None
return result.lastrowid
def get_items(self, user_id: int, item_kind: int = None) -> Optional[List[Row]]:
async def get_items(self, user_id: int, item_kind: int = None) -> Optional[List[Row]]:
if item_kind is None:
sql = item.select(item.c.user == user_id)
else:
@@ -218,12 +218,12 @@ class Mai2ItemData(BaseData):
and_(item.c.user == user_id, item.c.itemKind == item_kind)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_item(self, user_id: int, item_kind: int, item_id: int) -> Optional[Row]:
async def get_item(self, user_id: int, item_kind: int, item_id: int) -> Optional[Row]:
sql = item.select(
and_(
item.c.user == user_id,
@@ -232,12 +232,12 @@ class Mai2ItemData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_login_bonus(
async def put_login_bonus(
self,
user_id: int,
bonus_id: int,
@@ -259,7 +259,7 @@ class Mai2ItemData(BaseData):
isComplete=is_complete,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_login_bonus: failed to insert item! user_id: {user_id}, bonus_id: {bonus_id}, point: {point}"
@@ -267,25 +267,25 @@ class Mai2ItemData(BaseData):
return None
return result.lastrowid
def get_login_bonuses(self, user_id: int) -> Optional[List[Row]]:
async def get_login_bonuses(self, user_id: int) -> Optional[List[Row]]:
sql = login_bonus.select(login_bonus.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_login_bonus(self, user_id: int, bonus_id: int) -> Optional[Row]:
async def get_login_bonus(self, user_id: int, bonus_id: int) -> Optional[Row]:
sql = login_bonus.select(
and_(login_bonus.c.user == user_id, login_bonus.c.bonus_id == bonus_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_map(
async def put_map(
self,
user_id: int,
map_id: int,
@@ -310,7 +310,7 @@ class Mai2ItemData(BaseData):
isComplete=is_complete,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_map: failed to insert item! user_id: {user_id}, map_id: {map_id}, distance: {distance}"
@@ -318,28 +318,28 @@ class Mai2ItemData(BaseData):
return None
return result.lastrowid
def get_maps(self, user_id: int) -> Optional[List[Row]]:
async def get_maps(self, user_id: int) -> Optional[List[Row]]:
sql = map.select(map.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_map(self, user_id: int, map_id: int) -> Optional[Row]:
async def get_map(self, user_id: int, map_id: int) -> Optional[Row]:
sql = map.select(and_(map.c.user == user_id, map.c.mapId == map_id))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_character_(self, user_id: int, char_data: Dict) -> Optional[int]:
async def put_character_(self, user_id: int, char_data: Dict) -> Optional[int]:
char_data["user"] = user_id
sql = insert(character).values(**char_data)
conflict = sql.on_duplicate_key_update(**char_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_character_: failed to insert item! user_id: {user_id}"
@@ -347,7 +347,7 @@ class Mai2ItemData(BaseData):
return None
return result.lastrowid
def put_character(
async def put_character(
self,
user_id: int,
character_id: int,
@@ -369,7 +369,7 @@ class Mai2ItemData(BaseData):
useCount=use_count,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_character: failed to insert item! user_id: {user_id}, character_id: {character_id}, level: {level}"
@@ -377,33 +377,33 @@ class Mai2ItemData(BaseData):
return None
return result.lastrowid
def get_characters(self, user_id: int) -> Optional[List[Row]]:
async def get_characters(self, user_id: int) -> Optional[List[Row]]:
sql = character.select(character.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_character(self, user_id: int, character_id: int) -> Optional[Row]:
async def get_character(self, user_id: int, character_id: int) -> Optional[Row]:
sql = character.select(
and_(character.c.user == user_id, character.c.character_id == character_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_friend_season_ranking(self, user_id: int) -> Optional[Row]:
async def get_friend_season_ranking(self, user_id: int) -> Optional[Row]:
sql = friend_season_ranking.select(friend_season_ranking.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_friend_season_ranking(
async def put_friend_season_ranking(
self, aime_id: int, friend_season_ranking_data: Dict
) -> Optional[int]:
sql = insert(friend_season_ranking).values(
@@ -411,7 +411,7 @@ class Mai2ItemData(BaseData):
)
conflict = sql.on_duplicate_key_update(**friend_season_ranking_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
@@ -421,7 +421,7 @@ class Mai2ItemData(BaseData):
return None
return result.lastrowid
def put_favorite(
async def put_favorite(
self, user_id: int, kind: int, item_id_list: List[int]
) -> Optional[int]:
sql = insert(favorite).values(
@@ -430,7 +430,7 @@ class Mai2ItemData(BaseData):
conflict = sql.on_duplicate_key_update(item_id_list=item_id_list)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_favorite: failed to insert item! user_id: {user_id}, kind: {kind}"
@@ -438,7 +438,7 @@ class Mai2ItemData(BaseData):
return None
return result.lastrowid
def get_favorites(self, user_id: int, kind: int = None) -> Optional[Row]:
async def get_favorites(self, user_id: int, kind: int = None) -> Optional[Row]:
if kind is None:
sql = favorite.select(favorite.c.user == user_id)
else:
@@ -446,12 +446,12 @@ class Mai2ItemData(BaseData):
and_(favorite.c.user == user_id, favorite.c.itemKind == kind)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_card(
async def put_card(
self,
user_id: int,
card_type_id: int,
@@ -475,7 +475,7 @@ class Mai2ItemData(BaseData):
charaId=chara_id, mapId=map_id, startDate=start_date, endDate=end_date
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_card: failed to insert card! user_id: {user_id}, kind: {card_kind}"
@@ -483,7 +483,7 @@ class Mai2ItemData(BaseData):
return None
return result.lastrowid
def get_cards(self, user_id: int, kind: int = None) -> Optional[Row]:
async def get_cards(self, user_id: int, kind: int = None) -> Optional[Row]:
if kind is None:
sql = card.select(card.c.user == user_id)
else:
@@ -491,12 +491,12 @@ class Mai2ItemData(BaseData):
sql = sql.order_by(card.c.startDate.desc())
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_charge(
async def put_charge(
self,
user_id: int,
charge_id: int,
@@ -516,7 +516,7 @@ class Mai2ItemData(BaseData):
stock=stock, purchaseDate=purchase_date, validDate=valid_date
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_card: failed to insert charge! user_id: {user_id}, chargeId: {charge_id}"
@@ -524,15 +524,15 @@ class Mai2ItemData(BaseData):
return None
return result.lastrowid
def get_charges(self, user_id: int) -> Optional[Row]:
async def get_charges(self, user_id: int) -> Optional[Row]:
sql = charge.select(charge.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_user_print_detail(
async def put_user_print_detail(
self, aime_id: int, serial_id: str, user_print_data: Dict
) -> Optional[int]:
sql = insert(print_detail).values(
@@ -540,7 +540,7 @@ class Mai2ItemData(BaseData):
)
conflict = sql.on_duplicate_key_update(**user_print_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(

View File

@@ -491,7 +491,7 @@ consec_logins = Table(
class Mai2ProfileData(BaseData):
def put_profile_detail(
async def put_profile_detail(
self, user_id: int, version: int, detail_data: Dict, is_dx: bool = True
) -> Optional[Row]:
detail_data["user"] = user_id
@@ -504,7 +504,7 @@ class Mai2ProfileData(BaseData):
conflict = sql.on_duplicate_key_update(**detail_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_profile: Failed to create profile! user_id {user_id} is_dx {is_dx}"
@@ -512,7 +512,7 @@ class Mai2ProfileData(BaseData):
return None
return result.lastrowid
def get_profile_detail(
async def get_profile_detail(
self, user_id: int, version: int, is_dx: bool = True
) -> Optional[Row]:
if is_dx:
@@ -531,12 +531,12 @@ class Mai2ProfileData(BaseData):
.order_by(detail_old.c.version.desc())
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_ghost(
async def put_profile_ghost(
self, user_id: int, version: int, ghost_data: Dict
) -> Optional[int]:
ghost_data["user"] = user_id
@@ -545,25 +545,25 @@ class Mai2ProfileData(BaseData):
sql = insert(ghost).values(**ghost_data)
conflict = sql.on_duplicate_key_update(**ghost_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_profile_ghost: failed to update! {user_id}")
return None
return result.lastrowid
def get_profile_ghost(self, user_id: int, version: int) -> Optional[Row]:
async def get_profile_ghost(self, user_id: int, version: int) -> Optional[Row]:
sql = (
select(ghost)
.where(and_(ghost.c.user == user_id, ghost.c.version_int <= version))
.order_by(ghost.c.version.desc())
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_extend(
async def put_profile_extend(
self, user_id: int, version: int, extend_data: Dict
) -> Optional[int]:
extend_data["user"] = user_id
@@ -572,25 +572,25 @@ class Mai2ProfileData(BaseData):
sql = insert(extend).values(**extend_data)
conflict = sql.on_duplicate_key_update(**extend_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_profile_extend: failed to update! {user_id}")
return None
return result.lastrowid
def get_profile_extend(self, user_id: int, version: int) -> Optional[Row]:
async def get_profile_extend(self, user_id: int, version: int) -> Optional[Row]:
sql = (
select(extend)
.where(and_(extend.c.user == user_id, extend.c.version <= version))
.order_by(extend.c.version.desc())
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_option(
async def put_profile_option(
self, user_id: int, version: int, option_data: Dict, is_dx: bool = True
) -> Optional[int]:
option_data["user"] = user_id
@@ -602,7 +602,7 @@ class Mai2ProfileData(BaseData):
sql = insert(option_old).values(**option_data)
conflict = sql.on_duplicate_key_update(**option_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_profile_option: failed to update! {user_id} is_dx {is_dx}"
@@ -610,7 +610,7 @@ class Mai2ProfileData(BaseData):
return None
return result.lastrowid
def get_profile_option(
async def get_profile_option(
self, user_id: int, version: int, is_dx: bool = True
) -> Optional[Row]:
if is_dx:
@@ -628,12 +628,12 @@ class Mai2ProfileData(BaseData):
.order_by(option_old.c.version.desc())
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_rating(
async def put_profile_rating(
self, user_id: int, version: int, rating_data: Dict
) -> Optional[int]:
rating_data["user"] = user_id
@@ -642,25 +642,25 @@ class Mai2ProfileData(BaseData):
sql = insert(rating).values(**rating_data)
conflict = sql.on_duplicate_key_update(**rating_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_profile_rating: failed to update! {user_id}")
return None
return result.lastrowid
def get_profile_rating(self, user_id: int, version: int) -> Optional[Row]:
async def get_profile_rating(self, user_id: int, version: int) -> Optional[Row]:
sql = (
select(rating)
.where(and_(rating.c.user == user_id, rating.c.version <= version))
.order_by(rating.c.version.desc())
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_region(self, user_id: int, region_id: int) -> Optional[int]:
async def put_profile_region(self, user_id: int, region_id: int) -> Optional[int]:
sql = insert(region).values(
user=user_id,
regionId=region_id,
@@ -669,21 +669,21 @@ class Mai2ProfileData(BaseData):
conflict = sql.on_duplicate_key_update(playCount=region.c.playCount + 1)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_region: failed to update! {user_id}")
return None
return result.lastrowid
def get_regions(self, user_id: int) -> Optional[List[Dict]]:
async def get_regions(self, user_id: int) -> Optional[List[Dict]]:
sql = select(region).where(region.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_profile_activity(self, user_id: int, activity_data: Dict) -> Optional[int]:
async def put_profile_activity(self, user_id: int, activity_data: Dict) -> Optional[int]:
if "id" in activity_data:
activity_data["activityId"] = activity_data["id"]
activity_data.pop("id")
@@ -694,7 +694,7 @@ class Mai2ProfileData(BaseData):
conflict = sql.on_duplicate_key_update(**activity_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_profile_activity: failed to update! user_id: {user_id}"
@@ -702,7 +702,7 @@ class Mai2ProfileData(BaseData):
return None
return result.lastrowid
def get_profile_activity(
async def get_profile_activity(
self, user_id: int, kind: int = None
) -> Optional[List[Row]]:
sql = activity.select(
@@ -712,12 +712,12 @@ class Mai2ProfileData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_web_option(
async def put_web_option(
self, user_id: int, version: int, web_opts: Dict
) -> Optional[int]:
web_opts["user"] = user_id
@@ -726,29 +726,29 @@ class Mai2ProfileData(BaseData):
conflict = sql.on_duplicate_key_update(**web_opts)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_web_option: failed to update! user_id: {user_id}")
return None
return result.lastrowid
def get_web_option(self, user_id: int, version: int) -> Optional[Row]:
async def get_web_option(self, user_id: int, version: int) -> Optional[Row]:
sql = web_opt.select(
and_(web_opt.c.user == user_id, web_opt.c.version == version)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_grade_status(self, user_id: int, grade_stat: Dict) -> Optional[int]:
async def put_grade_status(self, user_id: int, grade_stat: Dict) -> Optional[int]:
grade_stat["user"] = user_id
sql = insert(grade_status).values(**grade_stat)
conflict = sql.on_duplicate_key_update(**grade_stat)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_grade_status: failed to update! user_id: {user_id}"
@@ -756,40 +756,40 @@ class Mai2ProfileData(BaseData):
return None
return result.lastrowid
def get_grade_status(self, user_id: int) -> Optional[Row]:
async def get_grade_status(self, user_id: int) -> Optional[Row]:
sql = grade_status.select(grade_status.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_boss_list(self, user_id: int, boss_stat: Dict) -> Optional[int]:
async def put_boss_list(self, user_id: int, boss_stat: Dict) -> Optional[int]:
boss_stat["user"] = user_id
sql = insert(boss).values(**boss_stat)
conflict = sql.on_duplicate_key_update(**boss_stat)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_boss_list: failed to update! user_id: {user_id}")
return None
return result.lastrowid
def get_boss_list(self, user_id: int) -> Optional[Row]:
async def get_boss_list(self, user_id: int) -> Optional[Row]:
sql = boss.select(boss.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_recent_rating(self, user_id: int, rr: Dict) -> Optional[int]:
async def put_recent_rating(self, user_id: int, rr: Dict) -> Optional[int]:
sql = insert(recent_rating).values(user=user_id, userRecentRatingList=rr)
conflict = sql.on_duplicate_key_update({"userRecentRatingList": rr})
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_recent_rating: failed to update! user_id: {user_id}"
@@ -797,26 +797,26 @@ class Mai2ProfileData(BaseData):
return None
return result.lastrowid
def get_recent_rating(self, user_id: int) -> Optional[Row]:
async def get_recent_rating(self, user_id: int) -> Optional[Row]:
sql = recent_rating.select(recent_rating.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def add_consec_login(self, user_id: int, version: int) -> None:
async def add_consec_login(self, user_id: int, version: int) -> None:
sql = insert(consec_logins).values(user=user_id, version=version, logins=1)
conflict = sql.on_duplicate_key_update(logins=consec_logins.c.logins + 1)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.error(
f"Failed to update consecutive login count for user {user_id} version {version}"
)
def get_consec_login(self, user_id: int, version: int) -> Optional[Row]:
async def get_consec_login(self, user_id: int, version: int) -> Optional[Row]:
sql = select(consec_logins).where(
and_(
consec_logins.c.user == user_id,
@@ -824,12 +824,12 @@ class Mai2ProfileData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def reset_consec_login(self, user_id: int, version: int) -> Optional[Row]:
async def reset_consec_login(self, user_id: int, version: int) -> Optional[Row]:
sql = consec_logins.update(
and_(
consec_logins.c.user == user_id,
@@ -837,7 +837,7 @@ class Mai2ProfileData(BaseData):
)
).values(logins=1)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()

View File

@@ -273,7 +273,7 @@ best_score_old = Table(
)
class Mai2ScoreData(BaseData):
def put_best_score(self, user_id: int, score_data: Dict, is_dx: bool = True) -> Optional[int]:
async def put_best_score(self, user_id: int, score_data: Dict, is_dx: bool = True) -> Optional[int]:
score_data["user"] = user_id
if is_dx:
@@ -282,7 +282,7 @@ class Mai2ScoreData(BaseData):
sql = insert(best_score_old).values(**score_data)
conflict = sql.on_duplicate_key_update(**score_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.error(
f"put_best_score: Failed to insert best score! user_id {user_id} is_dx {is_dx}"
@@ -291,7 +291,7 @@ class Mai2ScoreData(BaseData):
return result.lastrowid
@cached(2)
def get_best_scores(self, user_id: int, song_id: int = None, is_dx: bool = True) -> Optional[List[Row]]:
async def get_best_scores(self, user_id: int, song_id: int = None, is_dx: bool = True) -> Optional[List[Row]]:
if is_dx:
sql = best_score.select(
and_(
@@ -307,12 +307,12 @@ class Mai2ScoreData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_best_score(
async def get_best_score(
self, user_id: int, song_id: int, chart_id: int
) -> Optional[Row]:
sql = best_score.select(
@@ -323,12 +323,12 @@ class Mai2ScoreData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_playlog(self, user_id: int, playlog_data: Dict, is_dx: bool = True) -> Optional[int]:
async def put_playlog(self, user_id: int, playlog_data: Dict, is_dx: bool = True) -> Optional[int]:
playlog_data["user"] = user_id
if is_dx:
@@ -338,28 +338,28 @@ class Mai2ScoreData(BaseData):
conflict = sql.on_duplicate_key_update(**playlog_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.error(f"put_playlog: Failed to insert! user_id {user_id} is_dx {is_dx}")
return None
return result.lastrowid
def put_course(self, user_id: int, course_data: Dict) -> Optional[int]:
async def put_course(self, user_id: int, course_data: Dict) -> Optional[int]:
course_data["user"] = user_id
sql = insert(course).values(**course_data)
conflict = sql.on_duplicate_key_update(**course_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.error(f"put_course: Failed to insert! user_id {user_id}")
return None
return result.lastrowid
def get_courses(self, user_id: int) -> Optional[List[Row]]:
async def get_courses(self, user_id: int) -> Optional[List[Row]]:
sql = course.select(course.c.user == user_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()

View File

@@ -72,7 +72,7 @@ cards = Table(
class Mai2StaticData(BaseData):
def put_game_event(
async def put_game_event(
self, version: int, type: int, event_id: int, name: str
) -> Optional[int]:
sql = insert(event).values(
@@ -84,46 +84,46 @@ class Mai2StaticData(BaseData):
conflict = sql.on_duplicate_key_update(eventId=event_id)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_game_event: Failed to insert event! event_id {event_id} type {type} name {name}"
)
return result.lastrowid
def get_game_events(self, version: int) -> Optional[List[Row]]:
async def get_game_events(self, version: int) -> Optional[List[Row]]:
sql = event.select(event.c.version == version)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_enabled_events(self, version: int) -> Optional[List[Row]]:
async def get_enabled_events(self, version: int) -> Optional[List[Row]]:
sql = select(event).where(
and_(event.c.version == version, event.c.enabled == True)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def toggle_game_event(
async def toggle_game_event(
self, version: int, event_id: int, toggle: bool
) -> Optional[List]:
sql = event.update(
and_(event.c.version == version, event.c.eventId == event_id)
).values(enabled=int(toggle))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.warning(
f"toggle_game_event: Failed to update event! event_id {event_id} toggle {toggle}"
)
return result.last_updated_params()
def put_game_music(
async def put_game_music(
self,
version: int,
song_id: int,
@@ -159,13 +159,13 @@ class Mai2StaticData(BaseData):
noteDesigner=note_designer,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"Failed to insert song {song_id} chart {chart_id}")
return None
return result.lastrowid
def put_game_ticket(
async def put_game_ticket(
self,
version: int,
ticket_id: int,
@@ -185,13 +185,13 @@ class Mai2StaticData(BaseData):
conflict = sql.on_duplicate_key_update(price=ticket_price)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"Failed to insert charge {ticket_id} type {ticket_type}")
return None
return result.lastrowid
def get_enabled_tickets(
async def get_enabled_tickets(
self, version: int, kind: int = None
) -> Optional[List[Row]]:
if kind is not None:
@@ -207,12 +207,12 @@ class Mai2StaticData(BaseData):
and_(ticket.c.version == version, ticket.c.enabled == True)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_music_chart(
async def get_music_chart(
self, version: int, song_id: int, chart_id: int
) -> Optional[List[Row]]:
sql = select(music).where(
@@ -223,28 +223,28 @@ class Mai2StaticData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_card(self, version: int, card_id: int, card_name: str, **card_data) -> int:
async def put_card(self, version: int, card_id: int, card_name: str, **card_data) -> int:
sql = insert(cards).values(
version=version, cardId=card_id, cardName=card_name, **card_data
)
conflict = sql.on_duplicate_key_update(**card_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"Failed to insert card {card_id}")
return None
return result.lastrowid
def get_enabled_cards(self, version: int) -> Optional[List[Row]]:
async def get_enabled_cards(self, version: int) -> Optional[List[Row]]:
sql = cards.select(and_(cards.c.version == version, cards.c.enabled == True))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()

View File

@@ -15,8 +15,8 @@ class Mai2Universe(Mai2SplashPlus):
super().__init__(cfg, game_cfg)
self.version = Mai2Constants.VER_MAIMAI_DX_UNIVERSE
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile_detail(data["userId"], self.version)
async def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
p = await self.data.profile.get_profile_detail(data["userId"], self.version)
if p is None:
return {}
@@ -30,11 +30,11 @@ class Mai2Universe(Mai2SplashPlus):
"isExistSellingCard": True,
}
def handle_cm_get_user_data_api_request(self, data: Dict) -> Dict:
async def handle_cm_get_user_data_api_request(self, data: Dict) -> Dict:
# user already exists, because the preview checks that already
p = self.data.profile.get_profile_detail(data["userId"], self.version)
p = await self.data.profile.get_profile_detail(data["userId"], self.version)
cards = self.data.card.get_user_cards(data["userId"])
cards = await self.data.card.get_user_cards(data["userId"])
if cards is None or len(cards) == 0:
# This should never happen
self.logger.error(
@@ -52,14 +52,14 @@ class Mai2Universe(Mai2SplashPlus):
return {"userId": data["userId"], "userData": user_data}
def handle_cm_login_api_request(self, data: Dict) -> Dict:
async def handle_cm_login_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1}
def handle_cm_logout_api_request(self, data: Dict) -> Dict:
async def handle_cm_logout_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1}
def handle_cm_get_selling_card_api_request(self, data: Dict) -> Dict:
selling_cards = self.data.static.get_enabled_cards(self.version)
async def handle_cm_get_selling_card_api_request(self, data: Dict) -> Dict:
selling_cards = await self.data.static.get_enabled_cards(self.version)
if selling_cards is None:
return {"length": 0, "sellingCardList": []}
@@ -88,8 +88,8 @@ class Mai2Universe(Mai2SplashPlus):
return {"length": len(selling_card_list), "sellingCardList": selling_card_list}
def handle_cm_get_user_card_api_request(self, data: Dict) -> Dict:
user_cards = self.data.item.get_cards(data["userId"])
async def handle_cm_get_user_card_api_request(self, data: Dict) -> Dict:
user_cards = await self.data.item.get_cards(data["userId"])
if user_cards is None:
return {"returnCode": 1, "length": 0, "nextIndex": 0, "userCardList": []}
@@ -124,11 +124,11 @@ class Mai2Universe(Mai2SplashPlus):
"userCardList": card_list[start_idx:end_idx],
}
def handle_cm_get_user_item_api_request(self, data: Dict) -> Dict:
async def handle_cm_get_user_item_api_request(self, data: Dict) -> Dict:
super().handle_get_user_item_api_request(data)
def handle_cm_get_user_character_api_request(self, data: Dict) -> Dict:
characters = self.data.item.get_characters(data["userId"])
async def handle_cm_get_user_character_api_request(self, data: Dict) -> Dict:
characters = await self.data.item.get_characters(data["userId"])
chara_list = []
for chara in characters:
@@ -153,10 +153,10 @@ class Mai2Universe(Mai2SplashPlus):
"userCharacterList": chara_list,
}
def handle_cm_get_user_card_print_error_api_request(self, data: Dict) -> Dict:
async def handle_cm_get_user_card_print_error_api_request(self, data: Dict) -> Dict:
return {"length": 0, "userPrintDetailList": []}
def handle_cm_upsert_user_print_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_user_print_api_request(self, data: Dict) -> Dict:
user_id = data["userId"]
upsert = data["userPrintDetail"]
@@ -168,7 +168,7 @@ class Mai2Universe(Mai2SplashPlus):
end_date = datetime.utcnow() + timedelta(days=15)
user_card = upsert["userCard"]
self.data.item.put_card(
await self.data.item.put_card(
user_id,
user_card["cardId"],
user_card["cardTypeId"],
@@ -180,7 +180,7 @@ class Mai2Universe(Mai2SplashPlus):
)
# get the profile extend to save the new bought card
extend = self.data.profile.get_profile_extend(user_id, self.version)
extend = await self.data.profile.get_profile_extend(user_id, self.version)
if extend:
extend = extend._asdict()
# parse the selectedCardList
@@ -192,14 +192,14 @@ class Mai2Universe(Mai2SplashPlus):
selected_cards.insert(0, user_card["cardTypeId"])
extend["selectedCardList"] = selected_cards
self.data.profile.put_profile_extend(user_id, self.version, extend)
await self.data.profile.put_profile_extend(user_id, self.version, extend)
# properly format userPrintDetail for the database
upsert.pop("userCard")
upsert.pop("serialId")
upsert["printDate"] = datetime.strptime(upsert["printDate"], "%Y-%m-%d")
self.data.item.put_user_print_detail(user_id, serial_id, upsert)
await self.data.item.put_user_print_detail(user_id, serial_id, upsert)
return {
"returnCode": 1,
@@ -209,12 +209,12 @@ class Mai2Universe(Mai2SplashPlus):
"endDate": datetime.strftime(end_date, Mai2Constants.DATE_TIME_FORMAT),
}
def handle_cm_upsert_user_printlog_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_user_printlog_api_request(self, data: Dict) -> Dict:
return {
"returnCode": 1,
"orderId": 0,
"serialId": data["userPrintlog"]["serialId"],
}
def handle_cm_upsert_buy_card_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_buy_card_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1}

View File

@@ -11,8 +11,8 @@ class Mai2UniversePlus(Mai2Universe):
super().__init__(cfg, game_cfg)
self.version = Mai2Constants.VER_MAIMAI_DX_UNIVERSE_PLUS
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = super().handle_cm_get_user_preview_api_request(data)
async def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
user_data = await super().handle_cm_get_user_preview_api_request(data)
# hardcode lastDataVersion for CardMaker 1.35
user_data["lastDataVersion"] = "1.25.00"

View File

@@ -9,4 +9,3 @@ database = OngekiData
reader = OngekiReader
frontend = OngekiFrontend
game_codes = [OngekiConstants.GAME_CODE]
current_schema_version = 6

View File

@@ -103,7 +103,7 @@ class OngekiBase:
self.game = OngekiConstants.GAME_CODE
self.version = OngekiConstants.VER_ONGEKI
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
# if reboot start/end time is not defined use the default behavior of being a few hours ago
if self.core_cfg.title.reboot_start_time == "" or self.core_cfg.title.reboot_end_time == "":
reboot_start = datetime.strftime(
@@ -148,7 +148,7 @@ class OngekiBase:
"isAou": "true",
}
def handle_get_game_idlist_api_request(self, data: Dict) -> Dict:
async def handle_get_game_idlist_api_request(self, data: Dict) -> Dict:
"""
Gets lists of song IDs, either disabled songs or recomended songs depending on type?
"""
@@ -156,8 +156,8 @@ class OngekiBase:
# id - int
return {"type": data["type"], "length": 0, "gameIdlistList": []}
def handle_get_game_ranking_api_request(self, data: Dict) -> Dict:
game_ranking_list = self.data.static.get_ranking_list(self.version)
async def handle_get_game_ranking_api_request(self, data: Dict) -> Dict:
game_ranking_list = await self.data.static.get_ranking_list(self.version)
ranking_list = []
for music in game_ranking_list:
@@ -171,14 +171,14 @@ class OngekiBase:
"gameRankingList": ranking_list,
}
def handle_get_game_point_api_request(self, data: Dict) -> Dict:
get_game_point = self.data.static.get_static_game_point()
async def handle_get_game_point_api_request(self, data: Dict) -> Dict:
get_game_point = await self.data.static.get_static_game_point()
game_point = []
if not get_game_point:
self.logger.info(f"GP table is empty, inserting defaults")
self.data.static.put_static_game_point_defaults()
get_game_point = self.data.static.get_static_game_point()
await self.data.static.put_static_game_point_defaults()
get_game_point = await self.data.static.get_static_game_point()
for gp in get_game_point:
tmp = gp._asdict()
game_point.append(tmp)
@@ -194,17 +194,17 @@ class OngekiBase:
"gamePointList": game_point,
}
def handle_game_login_api_request(self, data: Dict) -> Dict:
async def handle_game_login_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "gameLogin"}
def handle_game_logout_api_request(self, data: Dict) -> Dict:
async def handle_game_logout_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "gameLogout"}
def handle_extend_lock_time_api_request(self, data: Dict) -> Dict:
async def handle_extend_lock_time_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "ExtendLockTimeApi"}
def handle_get_game_reward_api_request(self, data: Dict) -> Dict:
get_game_rewards = self.data.static.get_reward_list(self.version)
async def handle_get_game_reward_api_request(self, data: Dict) -> Dict:
get_game_rewards = await self.data.static.get_reward_list(self.version)
reward_list = []
for reward in get_game_rewards:
@@ -221,8 +221,8 @@ class OngekiBase:
"gameRewardList": reward_list,
}
def handle_get_game_present_api_request(self, data: Dict) -> Dict:
get_present = self.data.static.get_present_list(self.version)
async def handle_get_game_present_api_request(self, data: Dict) -> Dict:
get_present = await self.data.static.get_present_list(self.version)
present_list = []
for present in get_present:
@@ -238,14 +238,14 @@ class OngekiBase:
"gamePresentList": present_list,
}
def handle_get_game_message_api_request(self, data: Dict) -> Dict:
async def handle_get_game_message_api_request(self, data: Dict) -> Dict:
return {"length": 0, "gameMessageList": []}
def handle_get_game_sale_api_request(self, data: Dict) -> Dict:
async def handle_get_game_sale_api_request(self, data: Dict) -> Dict:
return {"length": 0, "gameSaleList": []}
def handle_get_game_tech_music_api_request(self, data: Dict) -> Dict:
music_list = self.data.static.get_tech_music(self.version)
async def handle_get_game_tech_music_api_request(self, data: Dict) -> Dict:
music_list = await self.data.static.get_tech_music(self.version)
prep_music_list = []
for music in music_list:
@@ -262,41 +262,41 @@ class OngekiBase:
"gameTechMusicList": prep_music_list,
}
def handle_upsert_client_setting_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_setting_api_request(self, data: Dict) -> Dict:
if self.core_cfg.server.is_develop:
return {"returnCode": 1, "apiName": "UpsertClientSettingApi"}
client_id = data["clientId"]
client_setting_data = data["clientSetting"]
cab = self.data.arcade.get_machine(client_id)
cab = await self.data.arcade.get_machine(client_id)
if cab is not None:
self.data.static.put_client_setting_data(cab['id'], client_setting_data)
await self.data.static.put_client_setting_data(cab['id'], client_setting_data)
return {"returnCode": 1, "apiName": "UpsertClientSettingApi"}
def handle_upsert_client_testmode_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_testmode_api_request(self, data: Dict) -> Dict:
if self.core_cfg.server.is_develop:
return {"returnCode": 1, "apiName": "UpsertClientTestmodeApi"}
region_id = data["regionId"]
client_testmode_data = data["clientTestmode"]
self.data.static.put_client_testmode_data(region_id, client_testmode_data)
await self.data.static.put_client_testmode_data(region_id, client_testmode_data)
return {"returnCode": 1, "apiName": "UpsertClientTestmodeApi"}
def handle_upsert_client_bookkeeping_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_bookkeeping_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "upsertClientBookkeeping"}
def handle_upsert_client_develop_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_develop_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "upsertClientDevelop"}
def handle_upsert_client_error_api_request(self, data: Dict) -> Dict:
async def handle_upsert_client_error_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "upsertClientError"}
def handle_upsert_user_gplog_api_request(self, data: Dict) -> Dict:
async def handle_upsert_user_gplog_api_request(self, data: Dict) -> Dict:
user = data["userId"]
if user >= 200000000000000: # Account for guest play
user = None
self.data.log.put_gp_log(
await self.data.log.put_gp_log(
user,
data["usedCredit"],
data["placeName"],
@@ -309,11 +309,11 @@ class OngekiBase:
return {"returnCode": 1, "apiName": "UpsertUserGplogApi"}
def handle_extend_lock_time_api_request(self, data: Dict) -> Dict:
async def handle_extend_lock_time_api_request(self, data: Dict) -> Dict:
return {"returnCode": 1, "apiName": "ExtendLockTimeApi"}
def handle_get_game_event_api_request(self, data: Dict) -> Dict:
evts = self.data.static.get_enabled_events(self.version)
async def handle_get_game_event_api_request(self, data: Dict) -> Dict:
evts = await self.data.static.get_enabled_events(self.version)
if evts is None:
return {
@@ -342,7 +342,7 @@ class OngekiBase:
"gameEventList": evt_list,
}
def handle_get_game_id_list_api_request(self, data: Dict) -> Dict:
async def handle_get_game_id_list_api_request(self, data: Dict) -> Dict:
game_idlist: List[str, Any] = [] # 1 to 230 & 8000 to 8050
if data["type"] == 1:
@@ -362,11 +362,11 @@ class OngekiBase:
"gameIdlistList": game_idlist,
}
def handle_get_user_region_api_request(self, data: Dict) -> Dict:
async def handle_get_user_region_api_request(self, data: Dict) -> Dict:
return {"userId": data["userId"], "length": 0, "userRegionList": []}
def handle_get_user_preview_api_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile_preview(data["userId"], self.version)
async def handle_get_user_preview_api_request(self, data: Dict) -> Dict:
profile = await self.data.profile.get_profile_preview(data["userId"], self.version)
if profile is None:
return {
@@ -417,12 +417,12 @@ class OngekiBase:
"isWarningConfirmed": True,
}
def handle_get_user_tech_count_api_request(self, data: Dict) -> Dict:
async def handle_get_user_tech_count_api_request(self, data: Dict) -> Dict:
"""
Gets the number of AB and ABPs a player has per-difficulty (7, 7+, 8, etc)
The game sends this in upsert so we don't have to calculate it all out thankfully
"""
utcl = self.data.score.get_tech_count(data["userId"])
utcl = await self.data.score.get_tech_count(data["userId"])
userTechCountList = []
for tc in utcl:
@@ -436,8 +436,8 @@ class OngekiBase:
"userTechCountList": userTechCountList,
}
def handle_get_user_tech_event_api_request(self, data: Dict) -> Dict:
user_tech_event_list = self.data.item.get_tech_event(self.version, data["userId"])
async def handle_get_user_tech_event_api_request(self, data: Dict) -> Dict:
user_tech_event_list = await self.data.item.get_tech_event(self.version, data["userId"])
if user_tech_event_list is None:
return {}
@@ -455,8 +455,8 @@ class OngekiBase:
"userTechEventList": tech_evt,
}
def handle_get_user_tech_event_ranking_api_request(self, data: Dict) -> Dict:
user_tech_event_ranks = self.data.item.get_tech_event_ranking(self.version, data["userId"])
async def handle_get_user_tech_event_ranking_api_request(self, data: Dict) -> Dict:
user_tech_event_ranks = await self.data.item.get_tech_event_ranking(self.version, data["userId"])
if user_tech_event_ranks is None:
return {
"userId": data["userId"],
@@ -481,8 +481,8 @@ class OngekiBase:
"userTechEventRankingList": evt_ranking,
}
def handle_get_user_kop_api_request(self, data: Dict) -> Dict:
kop_list = self.data.profile.get_kop(data["userId"])
async def handle_get_user_kop_api_request(self, data: Dict) -> Dict:
kop_list = await self.data.profile.get_kop(data["userId"])
if kop_list is None:
return {}
@@ -496,7 +496,7 @@ class OngekiBase:
"userKopList": kop_list,
}
def handle_get_user_music_api_request(self, data: Dict) -> Dict:
async def handle_get_user_music_api_request(self, data: Dict) -> Dict:
song_list = self.util_generate_music_list(data["userId"])
max_ct = data["maxCount"]
next_idx = data["nextIndex"]
@@ -516,9 +516,9 @@ class OngekiBase:
"userMusicList": song_list[start_idx:end_idx],
}
def handle_get_user_item_api_request(self, data: Dict) -> Dict:
async def handle_get_user_item_api_request(self, data: Dict) -> Dict:
kind = data["nextIndex"] / 10000000000
p = self.data.item.get_items(data["userId"], kind)
p = await self.data.item.get_items(data["userId"], kind)
if p is None:
return {
@@ -552,8 +552,8 @@ class OngekiBase:
"userItemList": items,
}
def handle_get_user_option_api_request(self, data: Dict) -> Dict:
o = self.data.profile.get_profile_options(data["userId"])
async def handle_get_user_option_api_request(self, data: Dict) -> Dict:
o = await self.data.profile.get_profile_options(data["userId"])
if o is None:
return {}
@@ -566,12 +566,12 @@ class OngekiBase:
return {"userId": data["userId"], "userOption": user_opts}
def handle_get_user_data_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile_data(data["userId"], self.version)
async def handle_get_user_data_api_request(self, data: Dict) -> Dict:
p = await self.data.profile.get_profile_data(data["userId"], self.version)
if p is None:
return {}
cards = self.data.card.get_user_cards(data["userId"])
cards = await self.data.card.get_user_cards(data["userId"])
if cards is None or len(cards) == 0:
# This should never happen
self.logger.error(
@@ -594,8 +594,8 @@ class OngekiBase:
return {"userId": data["userId"], "userData": user_data}
def handle_get_user_event_ranking_api_request(self, data: Dict) -> Dict:
user_event_ranking_list = self.data.item.get_ranking_event_ranks(self.version, data["userId"])
async def handle_get_user_event_ranking_api_request(self, data: Dict) -> Dict:
user_event_ranking_list = await self.data.item.get_ranking_event_ranks(self.version, data["userId"])
if user_event_ranking_list is None:
return {}
@@ -617,8 +617,8 @@ class OngekiBase:
"userEventRankingList": prep_event_ranking,
}
def handle_get_user_login_bonus_api_request(self, data: Dict) -> Dict:
user_login_bonus_list = self.data.item.get_login_bonuses(data["userId"])
async def handle_get_user_login_bonus_api_request(self, data: Dict) -> Dict:
user_login_bonus_list = await self.data.item.get_login_bonuses(data["userId"])
if user_login_bonus_list is None:
return {}
@@ -635,8 +635,8 @@ class OngekiBase:
"userLoginBonusList": login_bonuses,
}
def handle_get_user_bp_base_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile(
async def handle_get_user_bp_base_request(self, data: Dict) -> Dict:
p = await self.data.profile.get_profile(
self.game, self.version, user_id=data["userId"]
)
if p is None:
@@ -648,8 +648,8 @@ class OngekiBase:
"userBpBaseList": profile["userBpBaseList"],
}
def handle_get_user_recent_rating_api_request(self, data: Dict) -> Dict:
recent_rating = self.data.profile.get_profile_recent_rating(data["userId"])
async def handle_get_user_recent_rating_api_request(self, data: Dict) -> Dict:
recent_rating = await self.data.profile.get_profile_recent_rating(data["userId"])
if recent_rating is None:
return {
"userId": data["userId"],
@@ -665,8 +665,8 @@ class OngekiBase:
"userRecentRatingList": userRecentRatingList,
}
def handle_get_user_activity_api_request(self, data: Dict) -> Dict:
activity = self.data.profile.get_profile_activity(data["userId"], data["kind"])
async def handle_get_user_activity_api_request(self, data: Dict) -> Dict:
activity = await self.data.profile.get_profile_activity(data["userId"], data["kind"])
if activity is None:
return {}
@@ -692,8 +692,8 @@ class OngekiBase:
"userActivityList": user_activity,
}
def handle_get_user_story_api_request(self, data: Dict) -> Dict:
user_stories = self.data.item.get_stories(data["userId"])
async def handle_get_user_story_api_request(self, data: Dict) -> Dict:
user_stories = await self.data.item.get_stories(data["userId"])
if user_stories is None:
return {}
@@ -710,8 +710,8 @@ class OngekiBase:
"userStoryList": story_list,
}
def handle_get_user_chapter_api_request(self, data: Dict) -> Dict:
user_chapters = self.data.item.get_chapters(data["userId"])
async def handle_get_user_chapter_api_request(self, data: Dict) -> Dict:
user_chapters = await self.data.item.get_chapters(data["userId"])
if user_chapters is None:
return {}
@@ -728,15 +728,15 @@ class OngekiBase:
"userChapterList": chapter_list,
}
def handle_get_user_training_room_by_key_api_request(self, data: Dict) -> Dict:
async def handle_get_user_training_room_by_key_api_request(self, data: Dict) -> Dict:
return {
"userId": data["userId"],
"length": 0,
"userTrainingRoomList": [],
}
def handle_get_user_character_api_request(self, data: Dict) -> Dict:
user_characters = self.data.item.get_characters(data["userId"])
async def handle_get_user_character_api_request(self, data: Dict) -> Dict:
user_characters = await self.data.item.get_characters(data["userId"])
if user_characters is None:
return {}
@@ -753,8 +753,8 @@ class OngekiBase:
"userCharacterList": character_list,
}
def handle_get_user_card_api_request(self, data: Dict) -> Dict:
user_cards = self.data.item.get_cards(data["userId"])
async def handle_get_user_card_api_request(self, data: Dict) -> Dict:
user_cards = await self.data.item.get_cards(data["userId"])
if user_cards is None:
return {}
@@ -771,9 +771,9 @@ class OngekiBase:
"userCardList": card_list,
}
def handle_get_user_deck_by_key_api_request(self, data: Dict) -> Dict:
async def handle_get_user_deck_by_key_api_request(self, data: Dict) -> Dict:
# Auth key doesn't matter, it just wants all the decks
decks = self.data.item.get_decks(data["userId"])
decks = await self.data.item.get_decks(data["userId"])
if decks is None:
return {}
@@ -790,8 +790,8 @@ class OngekiBase:
"userDeckList": deck_list,
}
def handle_get_user_trade_item_api_request(self, data: Dict) -> Dict:
user_trade_items = self.data.item.get_trade_items(data["userId"])
async def handle_get_user_trade_item_api_request(self, data: Dict) -> Dict:
user_trade_items = await self.data.item.get_trade_items(data["userId"])
if user_trade_items is None:
return {}
@@ -808,8 +808,8 @@ class OngekiBase:
"userTradeItemList": trade_item_list,
}
def handle_get_user_scenario_api_request(self, data: Dict) -> Dict:
user_scenerio = self.data.item.get_scenerios(data["userId"])
async def handle_get_user_scenario_api_request(self, data: Dict) -> Dict:
user_scenerio = await self.data.item.get_scenerios(data["userId"])
if user_scenerio is None:
return {}
@@ -826,8 +826,8 @@ class OngekiBase:
"userScenarioList": scenerio_list,
}
def handle_get_user_ratinglog_api_request(self, data: Dict) -> Dict:
rating_log = self.data.profile.get_profile_rating_log(data["userId"])
async def handle_get_user_ratinglog_api_request(self, data: Dict) -> Dict:
rating_log = await self.data.profile.get_profile_rating_log(data["userId"])
if rating_log is None:
return {}
@@ -844,8 +844,8 @@ class OngekiBase:
"userRatinglogList": userRatinglogList,
}
def handle_get_user_mission_point_api_request(self, data: Dict) -> Dict:
user_mission_point_list = self.data.item.get_mission_points(self.version, data["userId"])
async def handle_get_user_mission_point_api_request(self, data: Dict) -> Dict:
user_mission_point_list = await self.data.item.get_mission_points(self.version, data["userId"])
if user_mission_point_list is None:
return {}
@@ -864,8 +864,8 @@ class OngekiBase:
"userMissionPointList": mission_point_list,
}
def handle_get_user_event_point_api_request(self, data: Dict) -> Dict:
user_event_point_list = self.data.item.get_event_points(data["userId"])
async def handle_get_user_event_point_api_request(self, data: Dict) -> Dict:
user_event_point_list = await self.data.item.get_event_points(data["userId"])
if user_event_point_list is None:
return {}
@@ -886,8 +886,8 @@ class OngekiBase:
"userEventPointList": event_point_list,
}
def handle_get_user_music_item_api_request(self, data: Dict) -> Dict:
user_music_item_list = self.data.item.get_music_items(data["userId"])
async def handle_get_user_music_item_api_request(self, data: Dict) -> Dict:
user_music_item_list = await self.data.item.get_music_items(data["userId"])
if user_music_item_list is None:
return {}
@@ -904,8 +904,8 @@ class OngekiBase:
"userMusicItemList": music_item_list,
}
def handle_get_user_event_music_api_request(self, data: Dict) -> Dict:
user_evt_music_list = self.data.item.get_event_music(data["userId"])
async def handle_get_user_event_music_api_request(self, data: Dict) -> Dict:
user_evt_music_list = await self.data.item.get_event_music(data["userId"])
if user_evt_music_list is None:
return {}
@@ -922,8 +922,8 @@ class OngekiBase:
"userEventMusicList": evt_music_list,
}
def handle_get_user_boss_api_request(self, data: Dict) -> Dict:
p = self.data.item.get_bosses(data["userId"])
async def handle_get_user_boss_api_request(self, data: Dict) -> Dict:
p = await self.data.item.get_bosses(data["userId"])
if p is None:
return {}
@@ -940,27 +940,27 @@ class OngekiBase:
"userBossList": boss_list,
}
def handle_upsert_user_all_api_request(self, data: Dict) -> Dict:
async def handle_upsert_user_all_api_request(self, data: Dict) -> Dict:
upsert = data["upsertUserAll"]
user_id = data["userId"]
# The isNew fields are new as of Red and up. We just won't use them for now.
if "userData" in upsert and len(upsert["userData"]) > 0:
self.data.profile.put_profile_data(
await self.data.profile.put_profile_data(
user_id, self.version, upsert["userData"][0]
)
if "userOption" in upsert and len(upsert["userOption"]) > 0:
self.data.profile.put_profile_options(user_id, upsert["userOption"][0])
await self.data.profile.put_profile_options(user_id, upsert["userOption"][0])
if "userPlaylogList" in upsert:
for playlog in upsert["userPlaylogList"]:
self.data.score.put_playlog(user_id, playlog)
await self.data.score.put_playlog(user_id, playlog)
if "userActivityList" in upsert:
for act in upsert["userActivityList"]:
self.data.profile.put_profile_activity(
await self.data.profile.put_profile_activity(
user_id,
act["kind"],
act["id"],
@@ -972,111 +972,111 @@ class OngekiBase:
)
if "userRecentRatingList" in upsert:
self.data.profile.put_profile_recent_rating(
await self.data.profile.put_profile_recent_rating(
user_id, upsert["userRecentRatingList"]
)
if "userBpBaseList" in upsert:
self.data.profile.put_profile_bp_list(user_id, upsert["userBpBaseList"])
await self.data.profile.put_profile_bp_list(user_id, upsert["userBpBaseList"])
if "userMusicDetailList" in upsert:
for x in upsert["userMusicDetailList"]:
self.data.score.put_best_score(user_id, x)
await self.data.score.put_best_score(user_id, x)
if "userCharacterList" in upsert:
for x in upsert["userCharacterList"]:
self.data.item.put_character(user_id, x)
await self.data.item.put_character(user_id, x)
if "userCardList" in upsert:
for x in upsert["userCardList"]:
self.data.item.put_card(user_id, x)
await self.data.item.put_card(user_id, x)
if "userDeckList" in upsert:
for x in upsert["userDeckList"]:
self.data.item.put_deck(user_id, x)
await self.data.item.put_deck(user_id, x)
if "userTrainingRoomList" in upsert:
for x in upsert["userTrainingRoomList"]:
self.data.profile.put_training_room(user_id, x)
await self.data.profile.put_training_room(user_id, x)
if "userStoryList" in upsert:
for x in upsert["userStoryList"]:
self.data.item.put_story(user_id, x)
await self.data.item.put_story(user_id, x)
if "userChapterList" in upsert:
for x in upsert["userChapterList"]:
self.data.item.put_chapter(user_id, x)
await self.data.item.put_chapter(user_id, x)
if "userMemoryChapterList" in upsert:
for x in upsert["userMemoryChapterList"]:
self.data.item.put_memorychapter(user_id, x)
await self.data.item.put_memorychapter(user_id, x)
if "userItemList" in upsert:
for x in upsert["userItemList"]:
self.data.item.put_item(user_id, x)
await self.data.item.put_item(user_id, x)
if "userMusicItemList" in upsert:
for x in upsert["userMusicItemList"]:
self.data.item.put_music_item(user_id, x)
await self.data.item.put_music_item(user_id, x)
if "userLoginBonusList" in upsert:
for x in upsert["userLoginBonusList"]:
self.data.item.put_login_bonus(user_id, x)
await self.data.item.put_login_bonus(user_id, x)
if "userEventPointList" in upsert:
for x in upsert["userEventPointList"]:
self.data.item.put_event_point(user_id, self.version, x)
await self.data.item.put_event_point(user_id, self.version, x)
if "userMissionPointList" in upsert:
for x in upsert["userMissionPointList"]:
self.data.item.put_mission_point(user_id, self.version, x)
await self.data.item.put_mission_point(user_id, self.version, x)
if "userRatinglogList" in upsert:
for x in upsert["userRatinglogList"]:
self.data.profile.put_profile_rating_log(
await self.data.profile.put_profile_rating_log(
user_id, x["dataVersion"], x["highestRating"]
)
if "userBossList" in upsert:
for x in upsert["userBossList"]:
self.data.item.put_boss(user_id, x)
await self.data.item.put_boss(user_id, x)
if "userTechCountList" in upsert:
for x in upsert["userTechCountList"]:
self.data.score.put_tech_count(user_id, x)
await self.data.score.put_tech_count(user_id, x)
if "userScenerioList" in upsert:
for x in upsert["userScenerioList"]:
self.data.item.put_scenerio(user_id, x)
await self.data.item.put_scenerio(user_id, x)
if "userTradeItemList" in upsert:
for x in upsert["userTradeItemList"]:
self.data.item.put_trade_item(user_id, x)
await self.data.item.put_trade_item(user_id, x)
if "userEventMusicList" in upsert:
for x in upsert["userEventMusicList"]:
self.data.item.put_event_music(user_id, x)
await self.data.item.put_event_music(user_id, x)
if "userTechEventList" in upsert:
for x in upsert["userTechEventList"]:
self.data.item.put_tech_event(user_id, self.version, x)
await self.data.item.put_tech_event(user_id, self.version, x)
# This should be updated once a day in maintenance window, but for time being we will push the update on each upsert
self.data.item.put_tech_event_ranking(user_id, self.version, x)
await self.data.item.put_tech_event_ranking(user_id, self.version, x)
if "userKopList" in upsert:
for x in upsert["userKopList"]:
self.data.profile.put_kop(user_id, x)
await self.data.profile.put_kop(user_id, x)
return {"returnCode": 1, "apiName": "upsertUserAll"}
def handle_get_user_rival_api_request(self, data: Dict) -> Dict:
async def handle_get_user_rival_api_request(self, data: Dict) -> Dict:
"""
Added in Bright
"""
rival_list = []
user_rivals = self.data.profile.get_rivals(data["userId"])
user_rivals = await self.data.profile.get_rivals(data["userId"])
for rival in user_rivals:
tmp = {}
tmp["rivalUserId"] = rival[0]
@@ -1094,13 +1094,13 @@ class OngekiBase:
"userRivalList": rival_list,
}
def handle_get_user_rival_data_api_request(self, data: Dict) -> Dict:
async def handle_get_user_rival_data_api_request(self, data: Dict) -> Dict:
"""
Added in Bright
"""
rivals = []
for rival in data["userRivalList"]:
name = self.data.profile.get_profile_name(
name = await self.data.profile.get_profile_name(
rival["rivalUserId"], self.version
)
if name is None:
@@ -1112,7 +1112,7 @@ class OngekiBase:
"userRivalDataList": rivals,
}
def handle_get_user_rival_music_api_request(self, data: Dict) -> Dict:
async def handle_get_user_rival_music_api_request(self, data: Dict) -> Dict:
"""
Added in Bright
"""
@@ -1135,8 +1135,8 @@ class OngekiBase:
}
@cached(2)
def util_generate_music_list(self, user_id: int) -> List:
music_detail = self.data.score.get_best_scores(user_id)
async def util_generate_music_list(self, user_id: int) -> List:
music_detail = await self.data.score.get_best_scores(user_id)
song_list = []
for md in music_detail:

View File

@@ -15,19 +15,19 @@ class OngekiBright(OngekiBase):
super().__init__(core_cfg, game_cfg)
self.version = OngekiConstants.VER_ONGEKI_BRIGHT
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.30.00"
ret["gameSetting"]["onlineDataVersion"] = "1.30.00"
return ret
def handle_cm_get_user_data_api_request(self, data: Dict) -> Dict:
async def handle_cm_get_user_data_api_request(self, data: Dict) -> Dict:
# check for a bright profile
p = self.data.profile.get_profile_data(data["userId"], self.version)
p = await self.data.profile.get_profile_data(data["userId"], self.version)
if p is None:
return {}
cards = self.data.card.get_user_cards(data["userId"])
cards = await self.data.card.get_user_cards(data["userId"])
if cards is None or len(cards) == 0:
# This should never happen
self.logger.error(
@@ -55,14 +55,14 @@ class OngekiBright(OngekiBase):
return {"userId": data["userId"], "userData": user_data}
def handle_printer_login_api_request(self, data: Dict):
async def handle_printer_login_api_request(self, data: Dict):
return {"returnCode": 1}
def handle_printer_logout_api_request(self, data: Dict):
async def handle_printer_logout_api_request(self, data: Dict):
return {"returnCode": 1}
def handle_cm_get_user_card_api_request(self, data: Dict) -> Dict:
user_cards = self.data.item.get_cards(data["userId"])
async def handle_cm_get_user_card_api_request(self, data: Dict) -> Dict:
user_cards = await self.data.item.get_cards(data["userId"])
if user_cards is None:
return {}
@@ -90,8 +90,8 @@ class OngekiBright(OngekiBase):
"userCardList": card_list[start_idx:end_idx],
}
def handle_cm_get_user_character_api_request(self, data: Dict) -> Dict:
user_characters = self.data.item.get_characters(data["userId"])
async def handle_cm_get_user_character_api_request(self, data: Dict) -> Dict:
user_characters = await self.data.item.get_characters(data["userId"])
if user_characters is None:
return {
"userId": data["userId"],
@@ -124,8 +124,8 @@ class OngekiBright(OngekiBase):
"userCharacterList": character_list[start_idx:end_idx],
}
def handle_get_user_gacha_api_request(self, data: Dict) -> Dict:
user_gachas = self.data.item.get_user_gachas(data["userId"])
async def handle_get_user_gacha_api_request(self, data: Dict) -> Dict:
user_gachas = await self.data.item.get_user_gachas(data["userId"])
if user_gachas is None:
return {"userId": data["userId"], "length": 0, "userGachaList": []}
@@ -143,12 +143,12 @@ class OngekiBright(OngekiBase):
"userGachaList": user_gacha_list,
}
def handle_cm_get_user_item_api_request(self, data: Dict) -> Dict:
async def handle_cm_get_user_item_api_request(self, data: Dict) -> Dict:
return self.handle_get_user_item_api_request(data)
def handle_cm_get_user_gacha_supply_api_request(self, data: Dict) -> Dict:
async def handle_cm_get_user_gacha_supply_api_request(self, data: Dict) -> Dict:
# not used for now? not sure what it even does
user_gacha_supplies = self.data.item.get_user_gacha_supplies(data["userId"])
user_gacha_supplies = await self.data.item.get_user_gacha_supplies(data["userId"])
if user_gacha_supplies is None:
return {"supplyId": 1, "length": 0, "supplyCardList": []}
@@ -160,7 +160,7 @@ class OngekiBright(OngekiBase):
"supplyCardList": supply_list,
}
def handle_get_game_gacha_api_request(self, data: Dict) -> Dict:
async def handle_get_game_gacha_api_request(self, data: Dict) -> Dict:
"""
returns all current active banners (gachas)
"Select Gacha" requires maxSelectPoint set and isCeiling set to 1
@@ -168,7 +168,7 @@ class OngekiBright(OngekiBase):
game_gachas = []
# for every gacha_id in the OngekiConfig, grab the banner from the db
for gacha_id in self.game_cfg.gachas.enabled_gachas:
game_gacha = self.data.static.get_gacha(self.version, gacha_id)
game_gacha = await self.data.static.get_gacha(self.version, gacha_id)
if game_gacha:
game_gachas.append(game_gacha)
@@ -207,7 +207,7 @@ class OngekiBright(OngekiBase):
"registIdList": [],
}
def handle_roll_gacha_api_request(self, data: Dict) -> Dict:
async def handle_roll_gacha_api_request(self, data: Dict) -> Dict:
"""
Handle a gacha roll API request
"""
@@ -265,26 +265,26 @@ class OngekiBright(OngekiBase):
return self.handle_roll_gacha_api_request(data)
# get a list of cards for each rarity
cards_r = self.data.static.get_cards_by_rarity(self.version, 1)
cards_r = await self.data.static.get_cards_by_rarity(self.version, 1)
cards_sr, cards_ssr = [], []
# free gachas are only allowed to get their specific cards! (R irrelevant)
if gacha_id in {1011, 1012}:
gacha_cards = self.data.static.get_gacha_cards(gacha_id)
gacha_cards = await self.data.static.get_gacha_cards(gacha_id)
for card in gacha_cards:
if card["rarity"] == 3:
cards_sr.append({"cardId": card["cardId"], "rarity": 2})
elif card["rarity"] == 4:
cards_ssr.append({"cardId": card["cardId"], "rarity": 3})
else:
cards_sr = self.data.static.get_cards_by_rarity(self.version, 2)
cards_ssr = self.data.static.get_cards_by_rarity(self.version, 3)
cards_sr = await self.data.static.get_cards_by_rarity(self.version, 2)
cards_ssr = await self.data.static.get_cards_by_rarity(self.version, 3)
# get the promoted cards for that gacha and add them multiple
# times to increase chances by factor chances
chances = 10
gacha_cards = self.data.static.get_gacha_cards(gacha_id)
gacha_cards = await self.data.static.get_gacha_cards(gacha_id)
for card in gacha_cards:
# make sure to add the cards to the corresponding rarity
if card["rarity"] == 2:
@@ -323,7 +323,7 @@ class OngekiBright(OngekiBase):
"gameGachaCardList": game_gacha_card_list,
}
def handle_cm_upsert_user_gacha_api_request(self, data: Dict):
async def handle_cm_upsert_user_gacha_api_request(self, data: Dict):
upsert = data["cmUpsertUserGacha"]
user_id = data["userId"]
@@ -339,7 +339,7 @@ class OngekiBright(OngekiBase):
daily_gacha_date = datetime.strptime("2000-01-01", "%Y-%m-%d")
# check if the user previously rolled the exact same gacha
user_gacha = self.data.item.get_user_gacha(user_id, gacha_id)
user_gacha = await self.data.item.get_user_gacha(user_id, gacha_id)
if user_gacha:
total_gacha_count = user_gacha["totalGachaCnt"]
ceiling_gacha_count = user_gacha["ceilingGachaCnt"]
@@ -358,7 +358,7 @@ class OngekiBright(OngekiBase):
daily_gacha_date = play_date
daily_gacha_cnt = 0
self.data.item.put_user_gacha(
await self.data.item.put_user_gacha(
user_id,
gacha_id,
totalGachaCnt=total_gacha_count + gacha_count,
@@ -375,29 +375,29 @@ class OngekiBright(OngekiBase):
if "userData" in upsert and len(upsert["userData"]) > 0:
# check if the profile is a bright memory profile
p = self.data.profile.get_profile_data(data["userId"], self.version)
p = await self.data.profile.get_profile_data(data["userId"], self.version)
if p is not None:
# save the bright memory profile
self.data.profile.put_profile_data(
await self.data.profile.put_profile_data(
user_id, self.version, upsert["userData"][0]
)
else:
# save the bright profile
self.data.profile.put_profile_data(
await self.data.profile.put_profile_data(
user_id, self.version, upsert["userData"][0]
)
if "userCharacterList" in upsert:
for x in upsert["userCharacterList"]:
self.data.item.put_character(user_id, x)
await self.data.item.put_character(user_id, x)
if "userItemList" in upsert:
for x in upsert["userItemList"]:
self.data.item.put_item(user_id, x)
await self.data.item.put_item(user_id, x)
if "userCardList" in upsert:
for x in upsert["userCardList"]:
self.data.item.put_card(user_id, x)
await self.data.item.put_card(user_id, x)
# TODO?
# if "gameGachaCardList" in upsert:
@@ -405,35 +405,35 @@ class OngekiBright(OngekiBase):
return {"returnCode": 1, "apiName": "CMUpsertUserGachaApi"}
def handle_cm_upsert_user_select_gacha_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_user_select_gacha_api_request(self, data: Dict) -> Dict:
upsert = data["cmUpsertUserSelectGacha"]
user_id = data["userId"]
if "userData" in upsert and len(upsert["userData"]) > 0:
# check if the profile is a bright memory profile
p = self.data.profile.get_profile_data(data["userId"], self.version)
p = await self.data.profile.get_profile_data(data["userId"], self.version)
if p is not None:
# save the bright memory profile
self.data.profile.put_profile_data(
await self.data.profile.put_profile_data(
user_id, self.version, upsert["userData"][0]
)
else:
# save the bright profile
self.data.profile.put_profile_data(
await self.data.profile.put_profile_data(
user_id, self.version, upsert["userData"][0]
)
if "userCharacterList" in upsert:
for x in upsert["userCharacterList"]:
self.data.item.put_character(user_id, x)
await self.data.item.put_character(user_id, x)
if "userCardList" in upsert:
for x in upsert["userCardList"]:
self.data.item.put_card(user_id, x)
await self.data.item.put_card(user_id, x)
if "selectGachaLogList" in data:
for x in data["selectGachaLogList"]:
self.data.item.put_user_gacha(
await self.data.item.put_user_gacha(
user_id,
x["gachaId"],
selectPoint=0,
@@ -442,8 +442,8 @@ class OngekiBright(OngekiBase):
return {"returnCode": 1, "apiName": "cmUpsertUserSelectGacha"}
def handle_get_game_gacha_card_by_id_api_request(self, data: Dict) -> Dict:
game_gacha_cards = self.data.static.get_gacha_cards(data["gachaId"])
async def handle_get_game_gacha_card_by_id_api_request(self, data: Dict) -> Dict:
game_gacha_cards = await self.data.static.get_gacha_cards(data["gachaId"])
if game_gacha_cards == []:
# fallback to be at least able to select that gacha
return {
@@ -522,7 +522,7 @@ class OngekiBright(OngekiBase):
"ssrBookCalcList": [],
}
def handle_get_game_theater_api_request(self, data: Dict) -> Dict:
async def handle_get_game_theater_api_request(self, data: Dict) -> Dict:
"""
shows a banner after every print, not sure what its used for
"""
@@ -548,7 +548,7 @@ class OngekiBright(OngekiBase):
return {"length": 0, "gameTheaterList": [], "registIdList": []}
def handle_cm_upsert_user_print_playlog_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_user_print_playlog_api_request(self, data: Dict) -> Dict:
return {
"returnCode": 1,
"orderId": 0,
@@ -556,7 +556,7 @@ class OngekiBright(OngekiBase):
"apiName": "CMUpsertUserPrintPlaylogApi",
}
def handle_cm_upsert_user_printlog_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_user_printlog_api_request(self, data: Dict) -> Dict:
return {
"returnCode": 1,
"orderId": 0,
@@ -564,7 +564,7 @@ class OngekiBright(OngekiBase):
"apiName": "CMUpsertUserPrintlogApi",
}
def handle_cm_upsert_user_print_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_user_print_api_request(self, data: Dict) -> Dict:
user_print_detail = data["userPrintDetail"]
# generate random serial id
@@ -579,7 +579,7 @@ class OngekiBright(OngekiBase):
)
# add the entry to the user print table with the random serialId
self.data.item.put_user_print_detail(
await self.data.item.put_user_print_detail(
data["userId"], serial_id, user_print_detail
)
@@ -589,27 +589,27 @@ class OngekiBright(OngekiBase):
"apiName": "CMUpsertUserPrintApi",
}
def handle_cm_upsert_user_all_api_request(self, data: Dict) -> Dict:
async def handle_cm_upsert_user_all_api_request(self, data: Dict) -> Dict:
upsert = data["cmUpsertUserAll"]
user_id = data["userId"]
if "userData" in upsert and len(upsert["userData"]) > 0:
# check if the profile is a bright memory profile
p = self.data.profile.get_profile_data(data["userId"], self.version)
p = await self.data.profile.get_profile_data(data["userId"], self.version)
if p is not None:
# save the bright memory profile
self.data.profile.put_profile_data(
await self.data.profile.put_profile_data(
user_id, self.version, upsert["userData"][0]
)
else:
# save the bright profile
self.data.profile.put_profile_data(
await self.data.profile.put_profile_data(
user_id, self.version, upsert["userData"][0]
)
if "userActivityList" in upsert:
for act in upsert["userActivityList"]:
self.data.profile.put_profile_activity(
await self.data.profile.put_profile_activity(
user_id,
act["kind"],
act["id"],
@@ -622,10 +622,10 @@ class OngekiBright(OngekiBase):
if "userItemList" in upsert:
for x in upsert["userItemList"]:
self.data.item.put_item(user_id, x)
await self.data.item.put_item(user_id, x)
if "userCardList" in upsert:
for x in upsert["userCardList"]:
self.data.item.put_card(user_id, x)
await self.data.item.put_card(user_id, x)
return {"returnCode": 1, "apiName": "cmUpsertUserAll"}

View File

@@ -15,8 +15,8 @@ class OngekiBrightMemory(OngekiBright):
super().__init__(core_cfg, game_cfg)
self.version = OngekiConstants.VER_ONGEKI_BRIGHT_MEMORY
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.35.00"
ret["gameSetting"]["onlineDataVersion"] = "1.35.00"
ret["gameSetting"]["maxCountCharacter"] = 50
@@ -27,8 +27,8 @@ class OngekiBrightMemory(OngekiBright):
ret["gameSetting"]["maxCountRivalMusic"] = 300
return ret
def handle_get_user_memory_chapter_api_request(self, data: Dict) -> Dict:
memories = self.data.item.get_memorychapters(data["userId"])
async def handle_get_user_memory_chapter_api_request(self, data: Dict) -> Dict:
memories = await self.data.item.get_memorychapters(data["userId"])
if not memories:
return {
"userId": data["userId"],
@@ -134,5 +134,5 @@ class OngekiBrightMemory(OngekiBright):
"userMemoryChapterList": memory_chp,
}
def handle_get_game_music_release_state_api_request(self, data: Dict) -> Dict:
async def handle_get_game_music_release_state_api_request(self, data: Dict) -> Dict:
return {"techScore": 0, "cardNum": 0}

View File

@@ -1,11 +1,12 @@
from typing import List
from starlette.routing import Route
import yaml
import jinja2
from twisted.web.http import Request
from starlette.requests import Request
from starlette.responses import Response, RedirectResponse
from os import path
from twisted.web.util import redirectTo
from twisted.web.server import Session
from core.frontend import FE_Base, IUserSession
from core.frontend import FE_Base, UserSession
from core.config import CoreConfig
from titles.ongeki.config import OngekiConfig
@@ -27,24 +28,33 @@ class OngekiFrontend(FE_Base):
)
self.nav_name = "O.N.G.E.K.I."
self.version_list = OngekiConstants.VERSION_NAMES
def get_routes(self) -> List[Route]:
return [
Route("/", self.render_GET)
]
def render_GET(self, request: Request) -> bytes:
async def render_GET(self, request: Request) -> bytes:
template = self.environment.get_template(
"titles/ongeki/frontend/ongeki_index.jinja"
"titles/ongeki/templates/ongeki_index.jinja"
)
sesh: Session = request.getSession()
usr_sesh = IUserSession(sesh)
usr_sesh = self.validate_session(request)
if not usr_sesh:
usr_sesh = UserSession()
self.version = usr_sesh.ongeki_version
if getattr(usr_sesh, "userId", 0) != 0:
profile_data =self.data.profile.get_profile_data(usr_sesh.userId, self.version)
rival_list = self.data.profile.get_rivals(usr_sesh.userId)
if usr_sesh.user_id > 0:
profile_data =self.data.profile.get_profile_data(usr_sesh.user_id, self.version)
rival_list = await self.data.profile.get_rivals(usr_sesh.user_id)
rival_data = {
"userRivalList": rival_list,
"userId": usr_sesh.userId
"userId": usr_sesh.user_id
}
rival_info = OngekiBase.handle_get_user_rival_data_api_request(self, rival_data)
return template.render(
# Hay1tsme 01/09/2024: ??????????????????????????????????????????????????????????????
rival_info = await OngekiBase.handle_get_user_rival_data_api_request(self, rival_data)
return Response(template.render(
data=self.data.profile,
title=f"{self.core_config.server.name} | {self.nav_name}",
game_list=self.environment.globals["game_list"],
@@ -54,34 +64,36 @@ class OngekiFrontend(FE_Base):
version_list=self.version_list,
version=self.version,
sesh=vars(usr_sesh)
).encode("utf-16")
))
else:
return redirectTo(b"/gate/", request)
return RedirectResponse("/gate/", 303)
def render_POST(self, request: Request):
async def render_POST(self, request: Request):
uri = request.uri.decode()
sesh: Session = request.getSession()
usr_sesh = IUserSession(sesh)
if hasattr(usr_sesh, "userId"):
usr_sesh = self.validate_session(request)
if not usr_sesh:
usr_sesh = UserSession()
if usr_sesh.user_id > 0:
if uri == "/game/ongeki/rival.add":
rival_id = request.args[b"rivalUserId"][0].decode()
self.data.profile.put_rival(usr_sesh.userId, rival_id)
# self.logger.info(f"{usr_sesh.userId} added a rival")
return redirectTo(b"/game/ongeki/", request)
await self.data.profile.put_rival(usr_sesh.user_id, rival_id)
# self.logger.info(f"{usr_sesh.user_id} added a rival")
return RedirectResponse(b"/game/ongeki/", 303)
elif uri == "/game/ongeki/rival.delete":
rival_id = request.args[b"rivalUserId"][0].decode()
self.data.profile.delete_rival(usr_sesh.userId, rival_id)
await self.data.profile.delete_rival(usr_sesh.user_id, rival_id)
# self.logger.info(f"{response}")
return redirectTo(b"/game/ongeki/", request)
return RedirectResponse(b"/game/ongeki/", 303)
elif uri == "/game/ongeki/version.change":
ongeki_version=request.args[b"version"][0].decode()
if(ongeki_version.isdigit()):
usr_sesh.ongeki_version=int(ongeki_version)
return redirectTo(b"/game/ongeki/", request)
return RedirectResponse("/game/ongeki/", 303)
else:
return b"Something went wrong"
Response("Something went wrong", status_code=500)
else:
return b"User is not logged in"
return RedirectResponse("/gate/", 303)

View File

@@ -1,4 +1,6 @@
from twisted.web.http import Request
from starlette.requests import Request
from starlette.routing import Route
from starlette.responses import Response
import json
import inflection
import yaml
@@ -120,11 +122,10 @@ class OngekiServlet(BaseServlet):
return True
def get_endpoint_matchers(self) -> Tuple[List[Tuple[str, str, Dict]], List[Tuple[str, str, Dict]]]:
return (
[],
[("render_POST", "/SDDT/{version}/{endpoint}", {})]
)
def get_routes(self) -> List[Route]:
return [
Route("/SDDT/{version:int}/{endpoint:str}", self.render_POST, methods=['POST'])
]
def get_allnet_info(self, game_code: str, game_ver: int, keychip: str) -> Tuple[str, str]:
title_port_int = Utils.get_title_port(self.core_cfg)
@@ -132,23 +133,24 @@ class OngekiServlet(BaseServlet):
proto = "https" if self.game_cfg.server.use_https and game_ver >= 120 else "http"
if proto == "https":
t_port = f":{title_port_ssl_int}" if title_port_ssl_int and not self.core_cfg.server.is_using_proxy else ""
t_port = f":{title_port_ssl_int}" if title_port_ssl_int != 443 else ""
else:
t_port = f":{title_port_int}" if title_port_int and not self.core_cfg.server.is_using_proxy else ""
t_port = f":{title_port_int}" if title_port_int != 80 else ""
return (
f"{proto}://{self.core_cfg.title.hostname}{t_port}/{game_code}/{game_ver}/",
f"{self.core_cfg.title.hostname}{t_port}/",
)
def render_POST(self, request: Request, game_code: str, matchers: Dict) -> bytes:
endpoint = matchers['endpoint']
version = int(matchers['version'])
if endpoint.lower() == "ping":
return zlib.compress(b'{"returnCode": 1}')
req_raw = request.content.getvalue()
async def render_POST(self, request: Request) -> bytes:
endpoint: str = request.path_params.get('endpoint', '')
version: int = request.path_params.get('version', 0)
if endpoint.lower() == "ping":
return Response(zlib.compress(b'{"returnCode": 1}'))
req_raw = await request.body()
encrtped = False
internal_ver = 0
client_ip = Utils.get_ip_addr(request)
@@ -178,13 +180,13 @@ class OngekiServlet(BaseServlet):
self.logger.error(
f"v{version} does not support encryption or no keys entered"
)
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
elif endpoint.lower() not in self.hash_table[internal_ver]:
self.logger.error(
f"No hash found for v{version} endpoint {endpoint}"
)
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
endpoint = self.hash_table[internal_ver][endpoint.lower()]
@@ -201,7 +203,7 @@ class OngekiServlet(BaseServlet):
self.logger.error(
f"Failed to decrypt v{version} request to {endpoint} -> {e}"
)
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
encrtped = True
@@ -213,7 +215,7 @@ class OngekiServlet(BaseServlet):
self.logger.error(
f"Unencrypted v{version} {endpoint} request, but config is set to encrypted only: {req_raw}"
)
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
try:
unzip = zlib.decompress(req_raw)
@@ -222,7 +224,7 @@ class OngekiServlet(BaseServlet):
self.logger.error(
f"Failed to decompress v{version} {endpoint} request -> {e}"
)
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
req_data = json.loads(unzip)
@@ -235,15 +237,15 @@ class OngekiServlet(BaseServlet):
if not hasattr(self.versions[internal_ver], func_to_find):
self.logger.warning(f"Unhandled v{version} request {endpoint}")
return zlib.compress(b'{"returnCode": 1}')
return Response(zlib.compress(b'{"returnCode": 1}'))
try:
handler = getattr(self.versions[internal_ver], func_to_find)
resp = handler(req_data)
resp = await handler(req_data)
except Exception as e:
self.logger.error(f"Error handling v{version} method {endpoint} - {e}")
return zlib.compress(b'{"stat": "0"}')
return Response(zlib.compress(b'{"stat": "0"}'))
if resp == None:
resp = {"returnCode": 1}
@@ -253,7 +255,7 @@ class OngekiServlet(BaseServlet):
zipped = zlib.compress(json.dumps(resp, ensure_ascii=False).encode("utf-8"))
if not encrtped or version < 120:
return zipped
return Response(zipped)
padded = pad(zipped, 16)
@@ -263,4 +265,4 @@ class OngekiServlet(BaseServlet):
bytes.fromhex(self.game_cfg.crypto.keys[internal_ver][1]),
)
return crypt.encrypt(padded)
return Response(crypt.encrypt(padded))

View File

@@ -11,8 +11,8 @@ class OngekiPlus(OngekiBase):
super().__init__(core_cfg, game_cfg)
self.version = OngekiConstants.VER_ONGEKI_PLUS
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.05.00"
ret["gameSetting"]["onlineDataVersion"] = "1.05.00"
return ret

View File

@@ -1,16 +1,11 @@
from decimal import Decimal
import logging
import os
import re
import xml.etree.ElementTree as ET
from typing import Any, Dict, List, Optional
from typing import Optional
from read import BaseReader
from core.config import CoreConfig
from titles.ongeki.database import OngekiData
from titles.ongeki.const import OngekiConstants
from titles.ongeki.config import OngekiConfig
class OngekiReader(BaseReader):
def __init__(
@@ -32,7 +27,7 @@ class OngekiReader(BaseReader):
self.logger.error(f"Invalid ongeki version {version}")
exit(1)
def read(self) -> None:
async def read(self) -> None:
data_dirs = []
if self.bin_dir is not None:
data_dirs += self.get_data_directories(self.bin_dir)
@@ -41,12 +36,12 @@ class OngekiReader(BaseReader):
data_dirs += self.get_data_directories(self.opt_dir)
for dir in data_dirs:
self.read_events(f"{dir}/event")
self.read_music(f"{dir}/music")
self.read_card(f"{dir}/card")
self.read_reward(f"{dir}/reward")
await self.read_events(f"{dir}/event")
await self.read_music(f"{dir}/music")
await self.read_card(f"{dir}/card")
await self.read_reward(f"{dir}/reward")
def read_card(self, base_dir: str) -> None:
async def read_card(self, base_dir: str) -> None:
self.logger.info(f"Reading cards from {base_dir}...")
version_ids = {
@@ -70,7 +65,7 @@ class OngekiReader(BaseReader):
# skip already existing cards
if (
self.data.static.get_card(
await self.data.static.get_card(
OngekiConstants.VER_ONGEKI_BRIGHT_MEMORY, card_id
)
is not None
@@ -100,7 +95,7 @@ class OngekiReader(BaseReader):
version = version_ids[troot.find("VersionID").find("id").text]
card_number = troot.find("CardNumberString").text
self.data.static.put_card(
await self.data.static.put_card(
version,
card_id,
name=name,
@@ -117,7 +112,7 @@ class OngekiReader(BaseReader):
)
self.logger.info(f"Added card {card_id}")
def read_events(self, base_dir: str) -> None:
async def read_events(self, base_dir: str) -> None:
self.logger.info(f"Reading events from {base_dir}...")
for root, dirs, files in os.walk(base_dir):
@@ -132,10 +127,10 @@ class OngekiReader(BaseReader):
troot.find("EventType").text
].value
self.data.static.put_event(self.version, id, event_type, name)
await self.data.static.put_event(self.version, id, event_type, name)
self.logger.info(f"Added event {id}")
def read_music(self, base_dir: str) -> None:
async def read_music(self, base_dir: str) -> None:
self.logger.info(f"Reading music from {base_dir}...")
for root, dirs, files in os.walk(base_dir):
@@ -168,12 +163,12 @@ class OngekiReader(BaseReader):
f"{fumens_data.find('FumenConstIntegerPart').text}.{fumens_data.find('FumenConstFractionalPart').text}"
)
self.data.static.put_chart(
await self.data.static.put_chart(
self.version, song_id, chart_id, title, artist, genre, level
)
self.logger.info(f"Added song {song_id} chart {chart_id}")
def read_reward(self, base_dir: str) -> None:
async def read_reward(self, base_dir: str) -> None:
self.logger.info(f"Reading rewards from {base_dir}...")
for root, dirs, files in os.walk(base_dir):
@@ -195,5 +190,5 @@ class OngekiReader(BaseReader):
itemKind = OngekiConstants.REWARD_TYPES[troot.find("ItemType").text].value
itemId = troot.find("RewardItem").find("ItemName").find("id").text
self.data.static.put_reward(self.version, rewardId, rewardname, itemKind, itemId)
await self.data.static.put_reward(self.version, rewardId, rewardname, itemKind, itemId)
self.logger.info(f"Added reward {rewardId}")

View File

@@ -11,8 +11,8 @@ class OngekiRed(OngekiBase):
super().__init__(core_cfg, game_cfg)
self.version = OngekiConstants.VER_ONGEKI_RED
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.20.00"
ret["gameSetting"]["onlineDataVersion"] = "1.20.00"
return ret

View File

@@ -11,8 +11,8 @@ class OngekiRedPlus(OngekiBase):
super().__init__(core_cfg, game_cfg)
self.version = OngekiConstants.VER_ONGEKI_RED_PLUS
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.25.00"
ret["gameSetting"]["onlineDataVersion"] = "1.25.00"
ret["gameSetting"]["maxCountCharacter"] = 50

View File

@@ -339,147 +339,147 @@ print_detail = Table(
)
class OngekiItemData(BaseData):
def put_card(self, aime_id: int, card_data: Dict) -> Optional[int]:
async def put_card(self, aime_id: int, card_data: Dict) -> Optional[int]:
card_data["user"] = aime_id
sql = insert(card).values(**card_data)
conflict = sql.on_duplicate_key_update(**card_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_card: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_cards(self, aime_id: int) -> Optional[List[Dict]]:
async def get_cards(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(card).where(card.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_character(self, aime_id: int, character_data: Dict) -> Optional[int]:
async def put_character(self, aime_id: int, character_data: Dict) -> Optional[int]:
character_data["user"] = aime_id
sql = insert(character).values(**character_data)
conflict = sql.on_duplicate_key_update(**character_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_character: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_characters(self, aime_id: int) -> Optional[List[Dict]]:
async def get_characters(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(character).where(character.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_deck(self, aime_id: int, deck_data: Dict) -> Optional[int]:
async def put_deck(self, aime_id: int, deck_data: Dict) -> Optional[int]:
deck_data["user"] = aime_id
sql = insert(deck).values(**deck_data)
conflict = sql.on_duplicate_key_update(**deck_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_deck: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_deck(self, aime_id: int, deck_id: int) -> Optional[Dict]:
async def get_deck(self, aime_id: int, deck_id: int) -> Optional[Dict]:
sql = select(deck).where(and_(deck.c.user == aime_id, deck.c.deckId == deck_id))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_decks(self, aime_id: int) -> Optional[List[Dict]]:
async def get_decks(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(deck).where(deck.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_boss(self, aime_id: int, boss_data: Dict) -> Optional[int]:
async def put_boss(self, aime_id: int, boss_data: Dict) -> Optional[int]:
boss_data["user"] = aime_id
sql = insert(boss).values(**boss_data)
conflict = sql.on_duplicate_key_update(**boss_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_boss: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_story(self, aime_id: int, story_data: Dict) -> Optional[int]:
async def put_story(self, aime_id: int, story_data: Dict) -> Optional[int]:
story_data["user"] = aime_id
sql = insert(story).values(**story_data)
conflict = sql.on_duplicate_key_update(**story_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_story: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_stories(self, aime_id: int) -> Optional[List[Dict]]:
async def get_stories(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(story).where(story.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_chapter(self, aime_id: int, chapter_data: Dict) -> Optional[int]:
async def put_chapter(self, aime_id: int, chapter_data: Dict) -> Optional[int]:
chapter_data["user"] = aime_id
sql = insert(chapter).values(**chapter_data)
conflict = sql.on_duplicate_key_update(**chapter_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_chapter: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_chapters(self, aime_id: int) -> Optional[List[Dict]]:
async def get_chapters(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(chapter).where(chapter.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_item(self, aime_id: int, item_data: Dict) -> Optional[int]:
async def put_item(self, aime_id: int, item_data: Dict) -> Optional[int]:
item_data["user"] = aime_id
sql = insert(item).values(**item_data)
conflict = sql.on_duplicate_key_update(**item_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_item: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_item(self, aime_id: int, item_id: int, item_kind: int) -> Optional[Dict]:
async def get_item(self, aime_id: int, item_id: int, item_kind: int) -> Optional[Dict]:
sql = select(item).where(and_(item.c.user == aime_id, item.c.itemId == item_id))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_items(self, aime_id: int, item_kind: int = None) -> Optional[List[Dict]]:
async def get_items(self, aime_id: int, item_kind: int = None) -> Optional[List[Dict]]:
if item_kind is None:
sql = select(item).where(item.c.user == aime_id)
else:
@@ -487,73 +487,73 @@ class OngekiItemData(BaseData):
and_(item.c.user == aime_id, item.c.itemKind == item_kind)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_music_item(self, aime_id: int, music_item_data: Dict) -> Optional[int]:
async def put_music_item(self, aime_id: int, music_item_data: Dict) -> Optional[int]:
music_item_data["user"] = aime_id
sql = insert(music_item).values(**music_item_data)
conflict = sql.on_duplicate_key_update(**music_item_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_music_item: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_music_items(self, aime_id: int) -> Optional[List[Dict]]:
async def get_music_items(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(music_item).where(music_item.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_login_bonus(self, aime_id: int, login_bonus_data: Dict) -> Optional[int]:
async def put_login_bonus(self, aime_id: int, login_bonus_data: Dict) -> Optional[int]:
login_bonus_data["user"] = aime_id
sql = insert(login_bonus).values(**login_bonus_data)
conflict = sql.on_duplicate_key_update(**login_bonus_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_login_bonus: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_login_bonuses(self, aime_id: int) -> Optional[List[Dict]]:
async def get_login_bonuses(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(login_bonus).where(login_bonus.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_mission_point(self, aime_id: int, version: int, mission_point_data: Dict) -> Optional[int]:
async def put_mission_point(self, aime_id: int, version: int, mission_point_data: Dict) -> Optional[int]:
mission_point_data["version"] = version
mission_point_data["user"] = aime_id
sql = insert(mission_point).values(**mission_point_data)
conflict = sql.on_duplicate_key_update(**mission_point_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_mission_point: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_mission_points(self, version: int, aime_id: int) -> Optional[List[Dict]]:
async def get_mission_points(self, version: int, aime_id: int) -> Optional[List[Dict]]:
sql = select(mission_point).where(and_(mission_point.c.user == aime_id, mission_point.c.version == version))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_event_point(self, aime_id: int, version: int, event_point_data: Dict) -> Optional[int]:
async def put_event_point(self, aime_id: int, version: int, event_point_data: Dict) -> Optional[int]:
# We update only the newest (type: 1) entry, in official spec game watches for both latest(type:1) and previous (type:2) entries to give an additional info how many ranks has player moved up or down
# This fully featured is on TODO list, at the moment we just update the tables as data comes and give out rank as request comes
event_point_data["user"] = aime_id
@@ -564,95 +564,95 @@ class OngekiItemData(BaseData):
sql = insert(event_point).values(**event_point_data)
conflict = sql.on_duplicate_key_update(**event_point_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_event_point: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_event_points(self, aime_id: int) -> Optional[List[Dict]]:
async def get_event_points(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(event_point).where(event_point.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_scenerio(self, aime_id: int, scenerio_data: Dict) -> Optional[int]:
async def put_scenerio(self, aime_id: int, scenerio_data: Dict) -> Optional[int]:
scenerio_data["user"] = aime_id
sql = insert(scenerio).values(**scenerio_data)
conflict = sql.on_duplicate_key_update(**scenerio_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_scenerio: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_scenerios(self, aime_id: int) -> Optional[List[Dict]]:
async def get_scenerios(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(scenerio).where(scenerio.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_trade_item(self, aime_id: int, trade_item_data: Dict) -> Optional[int]:
async def put_trade_item(self, aime_id: int, trade_item_data: Dict) -> Optional[int]:
trade_item_data["user"] = aime_id
sql = insert(trade_item).values(**trade_item_data)
conflict = sql.on_duplicate_key_update(**trade_item_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_trade_item: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_trade_items(self, aime_id: int) -> Optional[List[Dict]]:
async def get_trade_items(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(trade_item).where(trade_item.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_event_music(self, aime_id: int, event_music_data: Dict) -> Optional[int]:
async def put_event_music(self, aime_id: int, event_music_data: Dict) -> Optional[int]:
event_music_data["user"] = aime_id
sql = insert(event_music).values(**event_music_data)
conflict = sql.on_duplicate_key_update(**event_music_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_event_music: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_event_music(self, aime_id: int) -> Optional[List[Dict]]:
async def get_event_music(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(event_music).where(event_music.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_tech_event(self, aime_id: int, version: int, tech_event_data: Dict) -> Optional[int]:
async def put_tech_event(self, aime_id: int, version: int, tech_event_data: Dict) -> Optional[int]:
tech_event_data["user"] = aime_id
tech_event_data["version"] = version
sql = insert(tech_event).values(**tech_event_data)
conflict = sql.on_duplicate_key_update(**tech_event_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_tech_event: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_tech_event_ranking(self, aime_id: int, version: int, tech_event_data: Dict) -> Optional[int]:
async def put_tech_event_ranking(self, aime_id: int, version: int, tech_event_data: Dict) -> Optional[int]:
tech_event_data["user"] = aime_id
tech_event_data["version"] = version
tech_event_data.pop("isRankingRewarded")
@@ -662,87 +662,87 @@ class OngekiItemData(BaseData):
sql = insert(tech_ranking).values(**tech_event_data)
conflict = sql.on_duplicate_key_update(**tech_event_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_tech_event_ranking: Failed to update ranking! aime_id {aime_id}")
return None
return result.lastrowid
def get_tech_event(self, version: int, aime_id: int) -> Optional[List[Dict]]:
async def get_tech_event(self, version: int, aime_id: int) -> Optional[List[Dict]]:
sql = select(tech_event).where(and_(tech_event.c.user == aime_id, tech_event.c.version == version))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_bosses(self, aime_id: int) -> Optional[List[Dict]]:
async def get_bosses(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(boss).where(boss.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_memorychapter(
async def put_memorychapter(
self, aime_id: int, memorychapter_data: Dict
) -> Optional[int]:
memorychapter_data["user"] = aime_id
sql = insert(memorychapter).values(**memorychapter_data)
conflict = sql.on_duplicate_key_update(**memorychapter_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_memorychapter: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_memorychapters(self, aime_id: int) -> Optional[List[Dict]]:
async def get_memorychapters(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(memorychapter).where(memorychapter.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_user_gacha(self, aime_id: int, gacha_id: int) -> Optional[Row]:
async def get_user_gacha(self, aime_id: int, gacha_id: int) -> Optional[Row]:
sql = gacha.select(and_(gacha.c.user == aime_id, gacha.c.gachaId == gacha_id))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_user_gachas(self, aime_id: int) -> Optional[List[Row]]:
async def get_user_gachas(self, aime_id: int) -> Optional[List[Row]]:
sql = gacha.select(gacha.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_user_gacha_supplies(self, aime_id: int) -> Optional[List[Row]]:
async def get_user_gacha_supplies(self, aime_id: int) -> Optional[List[Row]]:
sql = gacha_supply.select(gacha_supply.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_user_gacha(self, aime_id: int, gacha_id: int, **data) -> Optional[int]:
async def put_user_gacha(self, aime_id: int, gacha_id: int, **data) -> Optional[int]:
sql = insert(gacha).values(user=aime_id, gachaId=gacha_id, **data)
conflict = sql.on_duplicate_key_update(user=aime_id, gachaId=gacha_id, **data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_user_gacha: Failed to insert! aime_id: {aime_id}")
return None
return result.lastrowid
def put_user_print_detail(
async def put_user_print_detail(
self, aime_id: int, serial_id: str, user_print_data: Dict
) -> Optional[int]:
sql = insert(print_detail).values(
@@ -750,7 +750,7 @@ class OngekiItemData(BaseData):
)
conflict = sql.on_duplicate_key_update(user=aime_id, **user_print_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
@@ -760,18 +760,18 @@ class OngekiItemData(BaseData):
return result.lastrowid
def get_ranking_event_ranks(self, version: int, aime_id: int) -> Optional[List[Dict]]:
async def get_ranking_event_ranks(self, version: int, aime_id: int) -> Optional[List[Dict]]:
# Calculates player rank on GameRequest from server, and sends it back, official spec would rank players in maintenance period, on TODO list
sql = select(event_point.c.id, event_point.c.user, event_point.c.eventId, event_point.c.type, func.row_number().over(partition_by=event_point.c.eventId, order_by=event_point.c.point.desc()).label('rank'), event_point.c.date, event_point.c.point).where(event_point.c.version == version)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.error(f"failed to rank aime_id: {aime_id} ranking event positions")
return None
return result.fetchall()
def get_tech_event_ranking(self, version: int, aime_id: int) -> Optional[List[Dict]]:
async def get_tech_event_ranking(self, version: int, aime_id: int) -> Optional[List[Dict]]:
sql = select(tech_ranking.c.id, tech_ranking.c.user, tech_ranking.c.date, tech_ranking.c.eventId, func.row_number().over(partition_by=tech_ranking.c.eventId, order_by=[tech_ranking.c.totalTechScore.desc(),tech_ranking.c.totalPlatinumScore.desc()]).label('rank'), tech_ranking.c.totalTechScore, tech_ranking.c.totalPlatinumScore).where(tech_ranking.c.version == version)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.warning(f"aime_id: {aime_id} has no tech ranking ranks")
return None

View File

@@ -39,7 +39,7 @@ session_log = Table(
class OngekiLogData(BaseData):
def put_gp_log(
async def put_gp_log(
self,
aime_id: Optional[int],
used_credit: int,
@@ -61,7 +61,7 @@ class OngekiLogData(BaseData):
currentGP=current_gp,
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.warning(
f"put_gp_log: Failed to insert GP log! aime_id: {aime_id} kind {kind} pattern {pattern} current_gp {current_gp}"

View File

@@ -255,12 +255,12 @@ class OngekiProfileData(BaseData):
)
self.date_time_format_short = "%Y-%m-%d"
def get_profile_name(self, aime_id: int, version: int) -> Optional[str]:
async def get_profile_name(self, aime_id: int, version: int) -> Optional[str]:
sql = select(profile.c.userName).where(
and_(profile.c.user == aime_id, profile.c.version == version)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
@@ -270,19 +270,19 @@ class OngekiProfileData(BaseData):
return row["userName"]
def get_profile_preview(self, aime_id: int, version: int) -> Optional[Row]:
async 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))
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_profile_data(self, aime_id: int, version: int) -> Optional[Row]:
async def get_profile_data(self, aime_id: int, version: int) -> Optional[Row]:
sql = select(profile).where(
and_(
profile.c.user == aime_id,
@@ -290,40 +290,40 @@ class OngekiProfileData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_profile_options(self, aime_id: int) -> Optional[Row]:
async def get_profile_options(self, aime_id: int) -> Optional[Row]:
sql = select(option).where(
and_(
option.c.user == aime_id,
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_profile_recent_rating(self, aime_id: int) -> Optional[List[Row]]:
async def get_profile_recent_rating(self, aime_id: int) -> Optional[List[Row]]:
sql = select(recent_rating).where(recent_rating.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_profile_rating_log(self, aime_id: int) -> Optional[List[Row]]:
async def get_profile_rating_log(self, aime_id: int) -> Optional[List[Row]]:
sql = select(rating_log).where(rating_log.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_profile_activity(
async def get_profile_activity(
self, aime_id: int, kind: int = None
) -> Optional[List[Row]]:
sql = select(activity).where(
@@ -333,47 +333,47 @@ class OngekiProfileData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_kop(self, aime_id: int) -> Optional[List[Row]]:
async def get_kop(self, aime_id: int) -> Optional[List[Row]]:
sql = select(kop).where(kop.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_rivals(self, aime_id: int) -> Optional[List[Row]]:
async def get_rivals(self, aime_id: int) -> Optional[List[Row]]:
sql = select(rival.c.rivalUserId).where(rival.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_profile_data(self, aime_id: int, version: int, data: Dict) -> Optional[int]:
async def put_profile_data(self, aime_id: int, version: int, data: Dict) -> Optional[int]:
data["user"] = aime_id
data["version"] = version
data.pop("accessCode")
sql = insert(profile).values(**data)
conflict = sql.on_duplicate_key_update(**data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_profile_data: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def put_profile_options(self, aime_id: int, options_data: Dict) -> Optional[int]:
async def put_profile_options(self, aime_id: int, options_data: Dict) -> Optional[int]:
options_data["user"] = aime_id
sql = insert(option).values(**options_data)
conflict = sql.on_duplicate_key_update(**options_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
@@ -382,7 +382,7 @@ class OngekiProfileData(BaseData):
return None
return result.lastrowid
def put_profile_recent_rating(
async def put_profile_recent_rating(
self, aime_id: int, recent_rating_data: List[Dict]
) -> Optional[int]:
sql = insert(recent_rating).values(
@@ -391,7 +391,7 @@ class OngekiProfileData(BaseData):
conflict = sql.on_duplicate_key_update(recentRating=recent_rating_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_profile_recent_rating: failed to update recent rating! aime_id {aime_id}"
@@ -399,12 +399,12 @@ class OngekiProfileData(BaseData):
return None
return result.lastrowid
def put_profile_bp_list(
async def put_profile_bp_list(
self, aime_id: int, bp_base_list: List[Dict]
) -> Optional[int]:
pass
def put_profile_rating_log(
async def put_profile_rating_log(
self, aime_id: int, data_version: str, highest_rating: int
) -> Optional[int]:
sql = insert(rating_log).values(
@@ -413,7 +413,7 @@ class OngekiProfileData(BaseData):
conflict = sql.on_duplicate_key_update(highestRating=highest_rating)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_profile_rating_log: failed to update rating log! aime_id {aime_id} data_version {data_version} highest_rating {highest_rating}"
@@ -421,7 +421,7 @@ class OngekiProfileData(BaseData):
return None
return result.lastrowid
def put_profile_activity(
async def put_profile_activity(
self,
aime_id: int,
kind: int,
@@ -447,7 +447,7 @@ class OngekiProfileData(BaseData):
sortNumber=sort_num, param1=p1, param2=p2, param3=p3, param4=p4
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_profile_activity: failed to put activity! aime_id {aime_id} kind {kind} activity_id {activity_id}"
@@ -455,7 +455,7 @@ class OngekiProfileData(BaseData):
return None
return result.lastrowid
def put_profile_region(self, aime_id: int, region: int, date: str) -> Optional[int]:
async def put_profile_region(self, aime_id: int, region: int, date: str) -> Optional[int]:
sql = insert(activity).values(
user=aime_id, region=region, playCount=1, created=date
)
@@ -464,7 +464,7 @@ class OngekiProfileData(BaseData):
playCount=activity.c.playCount + 1,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_profile_region: failed to update! aime_id {aime_id} region {region}"
@@ -472,45 +472,45 @@ class OngekiProfileData(BaseData):
return None
return result.lastrowid
def put_training_room(self, aime_id: int, room_detail: Dict) -> Optional[int]:
async def put_training_room(self, aime_id: int, room_detail: Dict) -> Optional[int]:
room_detail["user"] = aime_id
sql = insert(training_room).values(**room_detail)
conflict = sql.on_duplicate_key_update(**room_detail)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_best_score: Failed to add score! aime_id: {aime_id}")
return None
return result.lastrowid
def put_kop(self, aime_id: int, kop_data: Dict) -> Optional[int]:
async def put_kop(self, aime_id: int, kop_data: Dict) -> Optional[int]:
kop_data["user"] = aime_id
sql = insert(kop).values(**kop_data)
conflict = sql.on_duplicate_key_update(**kop_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_kop: Failed to add score! aime_id: {aime_id}")
return None
return result.lastrowid
def put_rival(self, aime_id: int, rival_id: int) -> Optional[int]:
async def put_rival(self, aime_id: int, rival_id: int) -> Optional[int]:
sql = insert(rival).values(user=aime_id, rivalUserId=rival_id)
conflict = sql.on_duplicate_key_update(rivalUserId=rival_id)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"put_rival: failed to update! aime_id: {aime_id}, rival_id: {rival_id}"
)
return None
return result.lastrowid
def delete_rival(self, aime_id: int, rival_id: int) -> Optional[int]:
async def delete_rival(self, aime_id: int, rival_id: int) -> Optional[int]:
sql = delete(rival).where(rival.c.user==aime_id, rival.c.rivalUserId==rival_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.error(f"delete_rival: failed to delete! aime_id: {aime_id}, rival_id: {rival_id}")
else:

View File

@@ -128,52 +128,52 @@ tech_count = Table(
class OngekiScoreData(BaseData):
def get_tech_count(self, aime_id: int) -> Optional[List[Dict]]:
async def get_tech_count(self, aime_id: int) -> Optional[List[Dict]]:
return []
def put_tech_count(self, aime_id: int, tech_count_data: Dict) -> Optional[int]:
async def put_tech_count(self, aime_id: int, tech_count_data: Dict) -> Optional[int]:
tech_count_data["user"] = aime_id
sql = insert(tech_count).values(**tech_count_data)
conflict = sql.on_duplicate_key_update(**tech_count_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_tech_count: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_best_scores(self, aime_id: int) -> Optional[List[Dict]]:
async def get_best_scores(self, aime_id: int) -> Optional[List[Dict]]:
sql = select(score_best).where(score_best.c.user == aime_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_best_score(
async def get_best_score(
self, aime_id: int, song_id: int, chart_id: int = None
) -> Optional[List[Dict]]:
return []
def put_best_score(self, aime_id: int, music_detail: Dict) -> Optional[int]:
async def put_best_score(self, aime_id: int, music_detail: Dict) -> Optional[int]:
music_detail["user"] = aime_id
sql = insert(score_best).values(**music_detail)
conflict = sql.on_duplicate_key_update(**music_detail)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"put_best_score: Failed to add score! aime_id: {aime_id}")
return None
return result.lastrowid
def put_playlog(self, aime_id: int, playlog_data: Dict) -> Optional[int]:
async def put_playlog(self, aime_id: int, playlog_data: Dict) -> Optional[int]:
playlog_data["user"] = aime_id
sql = insert(playlog).values(**playlog_data)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.warning(f"put_playlog: Failed to add playlog! aime_id: {aime_id}")
return None

View File

@@ -188,26 +188,26 @@ game_point = Table(
)
class OngekiStaticData(BaseData):
def put_card(self, version: int, card_id: int, **card_data) -> Optional[int]:
async def put_card(self, version: int, card_id: int, **card_data) -> Optional[int]:
sql = insert(cards).values(version=version, cardId=card_id, **card_data)
conflict = sql.on_duplicate_key_update(**card_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"Failed to insert card! card_id {card_id}")
return None
return result.lastrowid
def get_card(self, version: int, card_id: int) -> Optional[Dict]:
async def get_card(self, version: int, card_id: int) -> Optional[Dict]:
sql = cards.select(and_(cards.c.version <= version, cards.c.cardId == card_id))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_card_by_card_number(self, version: int, card_number: str) -> Optional[Dict]:
async def get_card_by_card_number(self, version: int, card_number: str) -> Optional[Dict]:
if not card_number.startswith("[O.N.G.E.K.I.]"):
card_number = f"[O.N.G.E.K.I.]{card_number}"
@@ -215,36 +215,36 @@ class OngekiStaticData(BaseData):
and_(cards.c.version <= version, cards.c.cardNumber == card_number)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_card_by_name(self, version: int, name: str) -> Optional[Dict]:
async def get_card_by_name(self, version: int, name: str) -> Optional[Dict]:
sql = cards.select(and_(cards.c.version <= version, cards.c.name == name))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_cards(self, version: int) -> Optional[List[Dict]]:
async def get_cards(self, version: int) -> Optional[List[Dict]]:
sql = cards.select(cards.c.version <= version)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_cards_by_rarity(self, version: int, rarity: int) -> Optional[List[Dict]]:
async def get_cards_by_rarity(self, version: int, rarity: int) -> Optional[List[Dict]]:
sql = cards.select(and_(cards.c.version <= version, cards.c.rarity == rarity))
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_gacha(
async def put_gacha(
self,
version: int,
gacha_id: int,
@@ -268,33 +268,33 @@ class OngekiStaticData(BaseData):
**gacha_data,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"Failed to insert gacha! gacha_id {gacha_id}")
return None
return result.lastrowid
def get_gacha(self, version: int, gacha_id: int) -> Optional[Dict]:
async def get_gacha(self, version: int, gacha_id: int) -> Optional[Dict]:
sql = gachas.select(
and_(gachas.c.version <= version, gachas.c.gachaId == gacha_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_gachas(self, version: int) -> Optional[List[Dict]]:
async def get_gachas(self, version: int) -> Optional[List[Dict]]:
sql = gachas.select(gachas.c.version == version).order_by(
gachas.c.gachaId.asc()
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_gacha_card(
async def put_gacha_card(
self, gacha_id: int, card_id: int, **gacha_card
) -> Optional[int]:
sql = insert(gacha_cards).values(gachaId=gacha_id, cardId=card_id, **gacha_card)
@@ -303,21 +303,21 @@ class OngekiStaticData(BaseData):
gachaId=gacha_id, cardId=card_id, **gacha_card
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"Failed to insert gacha card! gacha_id {gacha_id}")
return None
return result.lastrowid
def get_gacha_cards(self, gacha_id: int) -> Optional[List[Dict]]:
async def get_gacha_cards(self, gacha_id: int) -> Optional[List[Dict]]:
sql = gacha_cards.select(gacha_cards.c.gachaId == gacha_id)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_event(
async def put_event(
self, version: int, event_id: int, event_type: int, event_name: str
) -> Optional[int]:
sql = insert(events).values(
@@ -332,41 +332,41 @@ class OngekiStaticData(BaseData):
name=event_name,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"Failed to insert event! event_id {event_id}")
return None
return result.lastrowid
def get_event(self, version: int, event_id: int) -> Optional[List[Dict]]:
async def get_event(self, version: int, event_id: int) -> Optional[List[Dict]]:
sql = select(events).where(
and_(events.c.version == version, events.c.eventId == event_id)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_events(self, version: int) -> Optional[List[Dict]]:
async def get_events(self, version: int) -> Optional[List[Dict]]:
sql = select(events).where(events.c.version == version)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_enabled_events(self, version: int) -> Optional[List[Dict]]:
async def get_enabled_events(self, version: int) -> Optional[List[Dict]]:
sql = select(events).where(
and_(events.c.version == version, events.c.enabled == True)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_chart(
async def put_chart(
self,
version: int,
song_id: int,
@@ -393,7 +393,7 @@ class OngekiStaticData(BaseData):
level=level,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(
f"Failed to insert chart! song_id: {song_id}, chart_id: {chart_id}"
@@ -401,15 +401,15 @@ class OngekiStaticData(BaseData):
return None
return result.lastrowid
def get_chart(
async def get_chart(
self, version: int, song_id: int, chart_id: int = None
) -> Optional[List[Dict]]:
pass
def get_music(self, version: int) -> Optional[List[Dict]]:
async def get_music(self, version: int) -> Optional[List[Dict]]:
pass
def get_music_chart(
async def get_music_chart(
self, version: int, song_id: int, chart_id: int
) -> Optional[List[Row]]:
sql = select(music).where(
@@ -420,19 +420,19 @@ class OngekiStaticData(BaseData):
)
)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_ranking_list(self, version: int) -> Optional[List[Dict]]:
async def get_ranking_list(self, version: int) -> Optional[List[Dict]]:
sql = select(music_ranking.c.musicId.label('id'), music_ranking.c.point, music_ranking.c.userName).where(music_ranking.c.version == version)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_reward(self, version: int, rewardId: int, rewardname: str, itemKind: int, itemId: int) -> Optional[int]:
async def put_reward(self, version: int, rewardId: int, rewardname: str, itemKind: int, itemId: int) -> Optional[int]:
sql = insert(rewards).values(
version=version,
rewardId=rewardId,
@@ -443,70 +443,70 @@ class OngekiStaticData(BaseData):
conflict = sql.on_duplicate_key_update(
rewardname=rewardname,
)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"Failed to insert reward! reward_id: {rewardId}")
return None
return result.lastrowid
def get_reward_list(self, version: int) -> Optional[List[Dict]]:
async def get_reward_list(self, version: int) -> Optional[List[Dict]]:
sql = select(rewards).where(rewards.c.version == version)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.warning(f"Failed to load reward list")
return None
return result.fetchall()
def get_present_list(self, version: int) -> Optional[List[Dict]]:
async def get_present_list(self, version: int) -> Optional[List[Dict]]:
sql = select(present).where(present.c.version == version)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.warning(f"Failed to load present list")
return None
return result.fetchall()
def get_tech_music(self, version: int) -> Optional[List[Dict]]:
async def get_tech_music(self, version: int) -> Optional[List[Dict]]:
sql = select(tech_music).where(tech_music.c.version == version)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_client_testmode_data(self, region_id: int, client_testmode_data: Dict) -> Optional[List[Dict]]:
async def put_client_testmode_data(self, region_id: int, client_testmode_data: Dict) -> Optional[List[Dict]]:
sql = insert(client_testmode).values(regionId=region_id, **client_testmode_data)
conflict = sql.on_duplicate_key_update(regionId=region_id, **client_testmode_data)
result = self.execute(conflict)
result = await self.execute(conflict)
if result is None:
self.logger.warning(f"region_id: {region_id} Failed to update ClientTestMode data"),
return None
return result.lastrowid
def put_client_setting_data(self, machine_id: int, client_setting_data: Dict) -> Optional[List[Dict]]:
async def put_client_setting_data(self, machine_id: int, client_setting_data: Dict) -> Optional[List[Dict]]:
sql = machine.update(machine.c.id == machine_id).values(data=client_setting_data)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.warning(f"machine_id: {machine_id} Failed to update ClientSetting data"),
return None
return result.lastrowid
def put_static_game_point_defaults(self) -> Optional[List[Dict]]:
async def put_static_game_point_defaults(self) -> Optional[List[Dict]]:
game_point_defaults = [{"type": 0, "cost": 100},{"type": 1, "cost": 230},{"type": 2, "cost": 370},{"type": 3, "cost": 120},{"type": 4, "cost": 240},{"type": 5, "cost": 360}]
sql = insert(game_point).values(game_point_defaults)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
self.logger.warning(f"Failed to insert default GP table!")
return None
return result.lastrowid
def get_static_game_point(self) -> Optional[List[Dict]]:
async def get_static_game_point(self) -> Optional[List[Dict]]:
sql = select(game_point.c.type, game_point.c.cost, game_point.c.startDate, game_point.c.endDate)
result = self.execute(sql)
result = await self.execute(sql)
if result is None:
return None
return result.fetchall()

View File

@@ -11,8 +11,8 @@ class OngekiSummer(OngekiBase):
super().__init__(core_cfg, game_cfg)
self.version = OngekiConstants.VER_ONGEKI_SUMMER
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.10.00"
ret["gameSetting"]["onlineDataVersion"] = "1.10.00"
return ret

View File

@@ -11,8 +11,8 @@ class OngekiSummerPlus(OngekiBase):
super().__init__(core_cfg, game_cfg)
self.version = OngekiConstants.VER_ONGEKI_SUMMER_PLUS
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
async def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = await super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.15.00"
ret["gameSetting"]["onlineDataVersion"] = "1.15.00"
return ret

View File

@@ -1,7 +1,18 @@
{% extends "core/frontend/index.jinja" %}
{% extends "core/templates/index.jinja" %}
{% block content %}
<style type="text/css">
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
{% if sesh is defined and sesh["userId"] > 0 %}
/* Firefox */
input[type=number] {
-moz-appearance: textfield;
}
</style>
{% if sesh is defined and sesh["user_id"] > 0 %}
<br>
<br>
<br>
@@ -51,31 +62,29 @@
</table>
</div>
<div class="modal fade" id="rival_add" tabindex="-1" aria-labelledby="card_add_label" data-bs-theme="dark" aria-hidden="true">
<form id="rival" action="/game/ongeki/rival.add" method="post">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Note:<br>
Please use the ID show next to your name in the profile page.
<br>
<label for="rivalUserId">ID:&nbsp;</label><input form="rival" id="rivalUserId" name="rivalUserId" maxlength="5" type="number" required>
</div>
<div class="modal-footer">
<input type=submit class="btn btn-primary" type="button" form="rival" value="Add">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add rival</h5>
</div>
<div class="modal-body">
<form id="rival" action="/game/ongeki/rival.add" method="post" style="outline: 0;">
<label class="form-label" for="rivalUserId">Rival ID</label>
<input class="form-control" aria-describedby="rivalIdHelphelp" form="rival" id="rivalUserId" name="rivalUserId" maxlength="5" type="number" required>
<div id="rivalIdHelphelp" class="form-text">Please use the ID show next to your name in the profile page.</div>
</form>
</div>
<div class="modal-footer">
<input type=submit class="btn btn-primary" type="button" form="rival" value="Add">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</form>
</div>
</div>
</div>
<script>
{% include 'titles/ongeki/frontend/js/ongeki_scripts.js' %}
{% include 'titles/ongeki/templates/js/ongeki_scripts.js' %}
</script>
{% else %}
<h2>Not Currently Logged In</h2>

View File

@@ -6,5 +6,4 @@ from .frontend import PokkenFrontend
index = PokkenServlet
database = PokkenData
game_codes = [PokkenConstants.GAME_CODE]
current_schema_version = 1
frontend = PokkenFrontend

View File

@@ -20,21 +20,21 @@ class PokkenBase:
self.data = PokkenData(core_cfg)
self.SUPPORT_SET_NONE = 4294967295
def handle_noop(self, request: Any) -> bytes:
async def handle_noop(self, request: Any) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = request.type
return res.SerializeToString()
def handle_ping(self, request: jackal_pb2.Request) -> bytes:
async def handle_ping(self, request: jackal_pb2.Request) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = jackal_pb2.MessageType.PING
return res.SerializeToString()
def handle_register_pcb(self, request: jackal_pb2.Request) -> bytes:
async def handle_register_pcb(self, request: jackal_pb2.Request) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = jackal_pb2.MessageType.REGISTER_PCB
@@ -61,35 +61,35 @@ class PokkenBase:
"logfilename": "JackalMatchingLibrary.log",
"biwalogfilename": "./biwa.log",
}
regist_pcb.bnp_baseuri = f"{self.core_cfg.title.hostname}/bna"
regist_pcb.bnp_baseuri = f"{self.core_cfg.server.hostname}/bna"
regist_pcb.biwa_setting = json.dumps(biwa_setting)
res.register_pcb.CopyFrom(regist_pcb)
return res.SerializeToString()
def handle_save_ads(self, request: jackal_pb2.Request) -> bytes:
async def handle_save_ads(self, request: jackal_pb2.Request) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = jackal_pb2.MessageType.SAVE_ADS
return res.SerializeToString()
def handle_save_client_log(self, request: jackal_pb2.Request) -> bytes:
async def handle_save_client_log(self, request: jackal_pb2.Request) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = jackal_pb2.MessageType.SAVE_CLIENT_LOG
return res.SerializeToString()
def handle_check_diagnosis(self, request: jackal_pb2.Request) -> bytes:
async def handle_check_diagnosis(self, request: jackal_pb2.Request) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = jackal_pb2.MessageType.CHECK_DIAGNOSIS
return res.SerializeToString()
def handle_load_client_settings(self, request: jackal_pb2.Request) -> bytes:
async def handle_load_client_settings(self, request: jackal_pb2.Request) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = jackal_pb2.MessageType.LOAD_CLIENT_SETTINGS
@@ -112,7 +112,7 @@ class PokkenBase:
return res.SerializeToString()
def handle_load_ranking(self, request: jackal_pb2.Request) -> bytes:
async def handle_load_ranking(self, request: jackal_pb2.Request) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = jackal_pb2.MessageType.LOAD_RANKING
@@ -126,17 +126,17 @@ class PokkenBase:
res.load_ranking.CopyFrom(ranking)
return res.SerializeToString()
def handle_load_user(self, request: jackal_pb2.Request) -> bytes:
async def handle_load_user(self, request: jackal_pb2.Request) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = jackal_pb2.MessageType.LOAD_USER
access_code = request.load_user.access_code
load_usr = jackal_pb2.LoadUserResponseData()
user_id = self.data.card.get_user_id_from_card(access_code)
user_id = await self.data.card.get_user_id_from_card(access_code)
if user_id is None and self.game_cfg.server.auto_register:
user_id = self.data.user.create_user()
card_id = self.data.card.create_card(user_id, access_code)
user_id = await self.data.user.create_user()
card_id = await self.data.card.create_card(user_id, access_code)
self.logger.info(
f"Register new card {access_code} (UserId {user_id}, CardId {card_id})"
@@ -160,7 +160,7 @@ class PokkenBase:
event_achievement_flag
event_achievement_param
"""
profile = self.data.profile.get_profile(user_id)
profile = await self.data.profile.get_profile(user_id)
load_usr.commidserv_result = 1
load_usr.load_hash = 1
load_usr.cardlock_status = False
@@ -169,7 +169,7 @@ class PokkenBase:
load_usr.precedent_release_flag = 0xFFFFFFFF
if profile is None:
profile_id = self.data.profile.create_profile(user_id)
profile_id = await self.data.profile.create_profile(user_id)
profile_dict = {"id": profile_id, "user": user_id}
pokemon_data = []
tutorial_progress = []
@@ -184,7 +184,7 @@ class PokkenBase:
self.logger.info(
f"Card-in user {user_id} (Trainer name {profile_dict.get('trainer_name', '')})"
)
pokemon_data = self.data.profile.get_all_pokemon_data(user_id)
pokemon_data = await self.data.profile.get_all_pokemon_data(user_id)
tutorial_progress = []
rankmatch_progress = []
achievement_flag = []
@@ -287,13 +287,13 @@ class PokkenBase:
res.load_user.CopyFrom(load_usr)
return res.SerializeToString()
def handle_set_bnpassid_lock(self, data: jackal_pb2.Request) -> bytes:
async def handle_set_bnpassid_lock(self, data: jackal_pb2.Request) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = jackal_pb2.MessageType.SET_BNPASSID_LOCK
return res.SerializeToString()
def handle_save_user(self, request: jackal_pb2.Request) -> bytes:
async def handle_save_user(self, request: jackal_pb2.Request) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = jackal_pb2.MessageType.SAVE_USER
@@ -324,22 +324,22 @@ class PokkenBase:
battle = req.battle_data
mon = req.pokemon_data
p = self.data.profile.touch_profile(user_id)
p = await self.data.profile.touch_profile(user_id)
if p is None or not p:
self.data.profile.create_profile(user_id)
await self.data.profile.create_profile(user_id)
if req.trainer_name_pending is not None and req.trainer_name_pending: # we're saving for the first time
self.data.profile.set_profile_name(user_id, req.trainer_name_pending, req.avatar_gender if req.avatar_gender else None)
await self.data.profile.set_profile_name(user_id, req.trainer_name_pending, req.avatar_gender if req.avatar_gender else None)
for tut_flg in req.tutorial_progress_flag:
tut_flgs.append(tut_flg)
self.data.profile.update_profile_tutorial_flags(user_id, tut_flgs)
await self.data.profile.update_profile_tutorial_flags(user_id, tut_flgs)
for ach_flg in req.achievement_flag:
ach_flgs.append(ach_flg)
self.data.profile.update_profile_tutorial_flags(user_id, ach_flg)
await self.data.profile.update_profile_tutorial_flags(user_id, ach_flg)
for evt_flg in req.event_achievement_flag:
evt_flgs.append(evt_flg)
@@ -347,29 +347,29 @@ class PokkenBase:
for evt_param in req.event_achievement_param:
evt_params.append(evt_param)
self.data.profile.update_profile_event(user_id, evt_state, evt_flgs, evt_params, req.last_play_event_id)
await self.data.profile.update_profile_event(user_id, evt_state, evt_flgs, evt_params, req.last_play_event_id)
for reward in req.reward_data:
self.data.item.add_reward(user_id, reward.get_category_id, reward.get_content_id, reward.get_type_id)
await self.data.item.add_reward(user_id, reward.get_category_id, reward.get_content_id, reward.get_type_id)
self.data.profile.add_profile_points(user_id, get_rank_pts, get_money, get_score_pts, grade_max)
await self.data.profile.add_profile_points(user_id, get_rank_pts, get_money, get_score_pts, grade_max)
self.data.profile.update_support_team(user_id, 1, req.support_set_1[0], req.support_set_1[1])
self.data.profile.update_support_team(user_id, 2, req.support_set_2[0], req.support_set_2[1])
self.data.profile.update_support_team(user_id, 3, req.support_set_3[0], req.support_set_3[1])
await self.data.profile.update_support_team(user_id, 1, req.support_set_1[0], req.support_set_1[1])
await self.data.profile.update_support_team(user_id, 2, req.support_set_2[0], req.support_set_2[1])
await self.data.profile.update_support_team(user_id, 3, req.support_set_3[0], req.support_set_3[1])
self.data.profile.put_pokemon(user_id, mon.char_id, mon.illustration_book_no, mon.bp_point_atk, mon.bp_point_res, mon.bp_point_def, mon.bp_point_sp)
self.data.profile.add_pokemon_xp(user_id, mon.char_id, mon.get_pokemon_exp)
await self.data.profile.put_pokemon(user_id, mon.char_id, mon.illustration_book_no, mon.bp_point_atk, mon.bp_point_res, mon.bp_point_def, mon.bp_point_sp)
await self.data.profile.add_pokemon_xp(user_id, mon.char_id, mon.get_pokemon_exp)
for x in range(len(battle.play_mode)):
self.data.profile.put_pokemon_battle_result(
await self.data.profile.put_pokemon_battle_result(
user_id,
mon.char_id,
PokkenConstants.BATTLE_TYPE(battle.play_mode[x]),
PokkenConstants.BATTLE_RESULT(battle.result[x])
)
self.data.profile.put_stats(
await self.data.profile.put_stats(
user_id,
battle.ex_ko_num,
battle.wko_num,
@@ -379,7 +379,7 @@ class PokkenBase:
num_continues
)
self.data.profile.put_extra(
await self.data.profile.put_extra(
user_id,
extra_counter,
evt_reward_get_flg,
@@ -394,38 +394,31 @@ class PokkenBase:
return res.SerializeToString()
def handle_save_ingame_log(self, data: jackal_pb2.Request) -> bytes:
async def handle_save_ingame_log(self, data: jackal_pb2.Request) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = jackal_pb2.MessageType.SAVE_INGAME_LOG
return res.SerializeToString()
def handle_save_charge(self, data: jackal_pb2.Request) -> bytes:
async def handle_save_charge(self, data: jackal_pb2.Request) -> bytes:
res = jackal_pb2.Response()
res.result = 1
res.type = jackal_pb2.MessageType.SAVE_CHARGE
return res.SerializeToString()
def handle_matching_noop(
async def handle_matching_noop(
self, data: Dict = {}, client_ip: str = "127.0.0.1"
) -> Dict:
return {}
def handle_matching_start_matching(
async def handle_matching_start_matching(
self, data: Dict = {}, client_ip: str = "127.0.0.1"
) -> Dict:
return {}
def handle_matching_is_matching(
async def handle_matching_is_matching(
self, data: Dict = {}, client_ip: str = "127.0.0.1"
) -> Dict:
"""
"sessionId":"12345678",
"A":{
"pcb_id": data["data"]["must"]["pcb_id"],
"gip": client_ip
},
"""
return {
"data": {
"sessionId":"12345678",
@@ -437,15 +430,15 @@ class PokkenBase:
}
}
def handle_matching_stop_matching(
async def handle_matching_stop_matching(
self, data: Dict = {}, client_ip: str = "127.0.0.1"
) -> Dict:
return {}
def handle_admission_noop(self, data: Dict, req_ip: str = "127.0.0.1") -> Dict:
async def handle_admission_noop(self, data: Dict, req_ip: str = "127.0.0.1") -> Dict:
return {}
def handle_admission_joinsession(self, data: Dict, req_ip: str = "127.0.0.1") -> Dict:
async def handle_admission_joinsession(self, data: Dict, req_ip: str = "127.0.0.1") -> Dict:
self.logger.info(f"Admission: JoinSession from {req_ip}")
return {
'data': {

Some files were not shown because too many files have changed in this diff Show More