Merge branch 'develop' into idac

This commit is contained in:
Dniel97
2024-03-12 14:33:25 +01:00
203 changed files with 9242 additions and 5355 deletions
+6 -5
View File
@@ -1,10 +1,11 @@
from titles.chuni.index import ChuniServlet
from titles.chuni.const import ChuniConstants
from titles.chuni.database import ChuniData
from titles.chuni.read import ChuniReader
from .index import ChuniServlet
from .const import ChuniConstants
from .database import ChuniData
from .read import ChuniReader
from .frontend import ChuniFrontend
index = ChuniServlet
database = ChuniData
reader = ChuniReader
frontend = ChuniFrontend
game_codes = [ChuniConstants.GAME_CODE, ChuniConstants.GAME_CODE_NEW, ChuniConstants.GAME_CODE_INT]
current_schema_version = 5
+2 -2
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
+2 -2
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
+2 -2
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
+2 -2
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
+105 -107
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"],
@@ -608,16 +608,14 @@ class ChuniBase:
if len(song_list) >= max_ct:
break
try:
while song_list[-1]["userMusicDetailList"][0]["musicId"] == music_detail[x + 1]["musicId"]:
music = music_detail[x + 1]._asdict()
music.pop("user")
music.pop("id")
song_list[-1]["userMusicDetailList"].append(music)
song_list[-1]["length"] += 1
x += 1
except IndexError:
pass
for songIdx in range(len(song_list)):
for recordIdx in range(x+1, len(music_detail)):
if song_list[songIdx]["userMusicDetailList"][0]["musicId"] == music_detail[recordIdx]["musicId"]:
music = music_detail[recordIdx]._asdict()
music.pop("user")
music.pop("id")
song_list[songIdx]["userMusicDetailList"].append(music)
song_list[songIdx]["length"] += 1
if len(song_list) >= max_ct:
next_idx += len(song_list)
@@ -631,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")
@@ -640,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")
@@ -652,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"]
)
@@ -694,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"],
@@ -709,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"],
@@ -717,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 == "":
@@ -752,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,
@@ -760,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,
@@ -784,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,
@@ -792,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,
@@ -809,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"]
@@ -821,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"]:
@@ -883,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"]
@@ -891,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"]
@@ -902,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
)
@@ -929,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": []},
+22
View File
@@ -89,6 +89,27 @@ class ChuniCryptoConfig:
self.__config, "chuni", "crypto", "encrypted_only", default=False
)
class ChuniMatchingConfig:
def __init__(self, parent_config: "ChuniConfig") -> None:
self.__config = parent_config
@property
def enable(self) -> bool:
return CoreConfig.get_config_field(
self.__config, "chuni", "matching", "enable", default=False
)
@property
def match_time_limit(self) -> int:
return CoreConfig.get_config_field(
self.__config, "chuni", "matching", "match_time_limit", default=60
)
@property
def match_error_limit(self) -> int:
return CoreConfig.get_config_field(
self.__config, "chuni", "matching", "match_error_limit", default=9999
)
class ChuniConfig(dict):
def __init__(self) -> None:
@@ -97,3 +118,4 @@ class ChuniConfig(dict):
self.mods = ChuniModsConfig(self)
self.version = ChuniVersionConfig(self)
self.crypto = ChuniCryptoConfig(self)
self.matching = ChuniMatchingConfig(self)
+2 -2
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
+2 -2
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
+83
View File
@@ -0,0 +1,83 @@
from typing import List
from starlette.routing import Route
from starlette.requests import Request
from starlette.responses import Response, RedirectResponse
from os import path
import yaml
import jinja2
from core.frontend import FE_Base, UserSession
from core.config import CoreConfig
from .database import ChuniData
from .config import ChuniConfig
from .const import ChuniConstants
class ChuniFrontend(FE_Base):
def __init__(
self, cfg: CoreConfig, environment: jinja2.Environment, cfg_dir: str
) -> None:
super().__init__(cfg, environment)
self.data = ChuniData(cfg)
self.game_cfg = ChuniConfig()
if path.exists(f"{cfg_dir}/{ChuniConstants.CONFIG_NAME}"):
self.game_cfg.update(
yaml.safe_load(open(f"{cfg_dir}/{ChuniConstants.CONFIG_NAME}"))
)
self.nav_name = "Chunithm"
def get_routes(self) -> List[Route]:
return [
Route("/", self.render_GET, methods=['GET']),
Route("/update.name", self.update_name, methods=['POST']),
]
async def render_GET(self, request: Request) -> bytes:
template = self.environment.get_template(
"titles/chuni/templates/chuni_index.jinja"
)
usr_sesh = self.validate_session(request)
if not usr_sesh:
usr_sesh = UserSession()
return Response(template.render(
title=f"{self.core_config.server.name} | {self.nav_name}",
game_list=self.environment.globals["game_list"],
sesh=vars(usr_sesh)
), media_type="text/html; charset=utf-8")
async def update_name(self, request: Request) -> bytes:
usr_sesh = self.validate_session(request)
if not usr_sesh:
return RedirectResponse("/gate/", 303)
new_name: str = request.query_params.get('new_name', '')
new_name_full = ""
if not new_name:
return RedirectResponse("/gate/?e=4", 303)
if len(new_name) > 8:
return RedirectResponse("/gate/?e=8", 303)
for x in new_name: # FIXME: This will let some invalid characters through atm
o = ord(x)
try:
if o == 0x20:
new_name_full += chr(0x3000)
elif o < 0x7F and o > 0x20:
new_name_full += chr(o + 0xFEE0)
elif o <= 0x7F:
self.logger.warn(f"Invalid ascii character {o:02X}")
return RedirectResponse("/gate/?e=4", 303)
else:
new_name_full += x
except Exception as e:
self.logger.error(f"Something went wrong parsing character {o:04X} - {e}")
return RedirectResponse("/gate/?e=4", 303)
if not await self.data.profile.update_name(usr_sesh, new_name_full):
return RedirectResponse("/gate/?e=999", 303)
return RedirectResponse("/gate/?s=1", 303)
+28 -30
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))
+87 -73
View File
@@ -5,12 +5,12 @@ from typing import Dict
import pytz
from core.config import CoreConfig
from core.utils import Utils
from titles.chuni.const import ChuniConstants
from titles.chuni.database import ChuniData
from titles.chuni.base import ChuniBase
from titles.chuni.config import ChuniConfig
class ChuniNew(ChuniBase):
ITEM_TYPE = {"character": 20, "story": 21, "card": 22}
@@ -22,8 +22,18 @@ class ChuniNew(ChuniBase):
self.logger = logging.getLogger("chuni")
self.game = ChuniConstants.GAME_CODE
self.version = ChuniConstants.VER_CHUNITHM_NEW
def _interal_ver_to_intver(self) -> str:
if self.version == ChuniConstants.VER_CHUNITHM_NEW:
return "200"
if self.version == ChuniConstants.VER_CHUNITHM_NEW_PLUS:
return "205"
if self.version == ChuniConstants.VER_CHUNITHM_SUN:
return "210"
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(
@@ -55,6 +65,7 @@ class ChuniNew(ChuniBase):
# create strings for use in gameSetting
reboot_start = reboot_start_time.strftime(self.date_time_format)
reboot_end = reboot_end_time.strftime(self.date_time_format)
t_port = Utils.get_title_port(self.core_cfg)
return {
"gameSetting": {
"isMaintenance": False,
@@ -67,31 +78,31 @@ class ChuniNew(ChuniBase):
"maxCountMusic": 300,
"matchStartTime": match_start,
"matchEndTime": match_end,
"matchTimeLimit": 60,
"matchErrorLimit": 9999,
"matchTimeLimit": self.game_cfg.matching.match_time_limit,
"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}:{self.core_cfg.title.port}/SDHD/200/ChuniServlet/",
"matchingUriX": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/200/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/200/ChuniServlet/",
"reflectorUri": f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/200/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:
@@ -102,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"]
)
@@ -153,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 {}
@@ -166,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 = []
@@ -202,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:
@@ -226,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 {}
@@ -251,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": []}
@@ -270,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:
@@ -305,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
)
@@ -327,13 +338,13 @@ class ChuniNew(ChuniBase):
"userCardPrintStateList": card_print_state_list,
}
def handle_cm_get_user_character_api_request(self, data: Dict) -> Dict:
return super().handle_get_user_character_api_request(data)
async def handle_cm_get_user_character_api_request(self, data: Dict) -> Dict:
return await super().handle_get_user_character_api_request(data)
def handle_cm_get_user_item_api_request(self, data: Dict) -> Dict:
return super().handle_get_user_item_api_request(data)
async def handle_cm_get_user_item_api_request(self, data: Dict) -> Dict:
return await 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
@@ -351,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):
@@ -375,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"]
@@ -385,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"]
@@ -393,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,
@@ -412,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 = []
@@ -430,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,
@@ -438,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"]
@@ -454,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,
@@ -463,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"]
@@ -471,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
@@ -511,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"]
@@ -526,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,
@@ -543,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?
@@ -553,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,
@@ -568,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"}
@@ -588,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,
@@ -601,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"]
@@ -627,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,
@@ -647,4 +658,7 @@ class ChuniNew(ChuniBase):
"matchingMemberInfoList": [current_member] + diff_members,
}
return {"matchingWaitState": matching_wait}
return {
"roomId": data["roomId"],
"matchingWaitState": matching_wait
}
+3 -25
View File
@@ -1,40 +1,18 @@
from typing import Dict, Any
from core.utils import Utils
from core.config import CoreConfig
from titles.chuni.new import ChuniNew
from titles.chuni.const import ChuniConstants
from titles.chuni.config import ChuniConfig
class ChuniNewPlus(ChuniNew):
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_NEW_PLUS
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["romVersion"] = self.game_cfg.version.version(self.version)[
"rom"
]
ret["gameSetting"]["dataVersion"] = self.game_cfg.version.version(self.version)[
"data"
]
ret["gameSetting"][
"matchingUri"
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
ret["gameSetting"][
"matchingUriX"
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
ret["gameSetting"][
"udpHolePunchUri"
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
ret["gameSetting"][
"reflectorUri"
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
return ret
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"
+2 -2
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
+2 -2
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
+17 -17
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
)
+54 -54
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(
+62 -51
View File
@@ -395,7 +395,18 @@ team = Table(
class ChuniProfileData(BaseData):
def put_profile_data(
async def update_name(self, user_id: int, new_name: str) -> bool:
sql = profile.update(profile.c.user == user_id).values(
userName=new_name
)
result = await self.execute(sql)
if result is None:
self.logger.warning(f"Failed to set user {user_id} name to {new_name}")
return False
return True
async def put_profile_data(
self, aime_id: int, version: int, profile_data: Dict
) -> Optional[int]:
profile_data["user"] = aime_id
@@ -407,26 +418,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 +445,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 +460,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 +469,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 +477,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 +496,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 +520,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 +536,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 +544,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 +560,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 +569,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 +595,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 +636,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 +677,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 +691,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(
@@ -697,7 +708,7 @@ class ChuniProfileData(BaseData):
)
return 0
total_play_count = 0;
total_play_count = 0
for row in playcount_sql:
total_play_count += row[0]
return {
+16 -16
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()
+52 -52
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()
+2 -2
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
+2 -2
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
+2 -20
View File
@@ -11,26 +11,8 @@ class ChuniSun(ChuniNewPlus):
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_SUN
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["romVersion"] = self.game_cfg.version.version(self.version)["rom"]
ret["gameSetting"]["dataVersion"] = self.game_cfg.version.version(self.version)["data"]
ret["gameSetting"][
"matchingUri"
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/210/ChuniServlet/"
ret["gameSetting"][
"matchingUriX"
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/210/ChuniServlet/"
ret["gameSetting"][
"udpHolePunchUri"
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/210/ChuniServlet/"
ret["gameSetting"][
"reflectorUri"
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/210/ChuniServlet/"
return ret
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"
+2 -20
View File
@@ -11,26 +11,8 @@ class ChuniSunPlus(ChuniSun):
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_SUN_PLUS
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["romVersion"] = self.game_cfg.version.version(self.version)["rom"]
ret["gameSetting"]["dataVersion"] = self.game_cfg.version.version(self.version)["data"]
ret["gameSetting"][
"matchingUri"
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/215/ChuniServlet/"
ret["gameSetting"][
"matchingUriX"
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/215/ChuniServlet/"
ret["gameSetting"][
"udpHolePunchUri"
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/215/ChuniServlet/"
ret["gameSetting"][
"reflectorUri"
] = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDHD/215/ChuniServlet/"
return ret
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"
+43
View File
@@ -0,0 +1,43 @@
{% extends "core/templates/index.jinja" %}
{% block content %}
<h1>Chunithm</h1>
{% if profile is defined and profile is not none and profile.id > 0 %}
<script type="text/javascript">
function toggle_new_name_form() {
let frm = document.getElementById("new_name_form");
let btn = document.getElementById("btn_toggle_form");
if (frm.style['display'] != "") {
frm.style['display'] = "";
frm.style['max-height'] = "";
btn.innerText = "Cancel";
} else {
frm.style['display'] = "none";
frm.style['max-height'] = "0px";
btn.innerText = "Edit";
}
}
</script>
<h3>Profile for {{ profile.userName }}&nbsp;<button onclick="toggle_new_name_form()" class="btn btn-secondary" id="btn_toggle_form">Edit</button></h3>
{% if error is defined %}
{% include "core/templates/widgets/err_banner.jinja" %}
{% endif %}
{% if success is defined and success == 1 %}
<div style="background-color: #00AA00; padding: 20px; margin-bottom: 10px; width: 15%;">
Update successful
</div>
{% endif %}
<form style="max-width: 33%; display: none; max-height: 0px;" action="/game/chuni/update.name" method="post" id="new_name_form">
<div class="mb-3">
<label for="new_name" class="form-label">New Trainer Name</label>
<input type="text" class="form-control" id="new_name" name="new_name" aria-describedby="new_name_help" maxlength="14">
<div id="new_name_help" class="form-text">Must be 14 characters or less</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% elif sesh is defined and sesh is not none and sesh.user_id > 0 %}
No profile information found for this account.
{% else %}
Login to view profile information.
{% endif %}
{% endblock content %}
-3
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
+7 -7
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"}
+2 -2
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
+18 -19
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, methods=['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,20 +113,20 @@ 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)
resp = handler(req_data)
resp = await handler(req_data)
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")))
+23 -23
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",
@@ -59,14 +59,14 @@ class CardMakerReader(BaseReader):
if self.bin_dir is not None:
data_dir = self._get_card_maker_directory(self.bin_dir)
self.read_chuni_card(f"{data_dir}/CHU/Data/A000/card")
self.read_chuni_gacha(f"{data_dir}/CHU/Data/A000/gacha")
await self.read_chuni_card(f"{data_dir}/CHU/Data/A000/card")
await self.read_chuni_gacha(f"{data_dir}/CHU/Data/A000/gacha")
self.read_mai2_card(f"{data_dir}/MAI/Data/A000/card")
await self.read_mai2_card(f"{data_dir}/MAI/Data/A000/card")
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,
-1
View File
@@ -7,4 +7,3 @@ index = CxbServlet
database = CxbData
reader = CxbReader
game_codes = [CxbConstants.GAME_CODE]
current_schema_version = 1
+38 -38
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": ""}
+6
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):
+40 -43
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}",
f"{proto}://{self.core_cfg.server.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)
+14 -19
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,
+65 -60
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,9 +45,9 @@ 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:
with open(r"titles/cxb/data/rev/MusicArchiveList.csv") as music:
lines = music.readlines()
for line in lines:
line_split = line.split(",")
@@ -56,10 +56,10 @@ 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"
r"titles/cxb/data/rev/Item/ItemArchiveList_Icon.csv", encoding="shift-jis"
) as item:
lines = item.readlines()
for line in lines:
@@ -67,10 +67,10 @@ 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"
r"titles/cxb/data/rev/Item/ItemArchiveList_SkinNotes.csv", encoding="utf-8"
) as item:
lines = item.readlines()
for line in lines:
@@ -78,10 +78,10 @@ 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"
r"titles/cxb/data/rev/Item/ItemArchiveList_SkinEffect.csv", encoding="utf-8"
) as item:
lines = item.readlines()
for line in lines:
@@ -89,10 +89,10 @@ 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"
r"titles/cxb/data/rev/Item/ItemArchiveList_SkinBg.csv", encoding="utf-8"
) as item:
lines = item.readlines()
for line in lines:
@@ -100,10 +100,10 @@ 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"
r"titles/cxb/data/rev/Item/ItemList_Title.csv", encoding="shift-jis"
) as item:
lines = item.readlines()
for line in lines:
@@ -111,10 +111,10 @@ 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"
r"titles/cxb/data/rev/Shop/ShopList_Music.csv", encoding="shift-jis"
) as shop:
lines = shop.readlines()
for line in lines:
@@ -122,10 +122,10 @@ 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"
r"titles/cxb/data/rev/Shop/ShopList_Icon.csv", encoding="shift-jis"
) as shop:
lines = shop.readlines()
for line in lines:
@@ -133,83 +133,88 @@ 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"
r"titles/cxb/data/rev/Shop/ShopList_Title.csv", encoding="shift-jis"
) as shop:
lines = shop.readlines()
for line in lines:
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"
r"titles/cxb/data/rev/Shop/ShopList_Sale.csv", encoding="shift-jis"
) as shop:
lines = shop.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
def handle_data_extra_stage_list_request(self, data: Dict) -> Dict:
return {"data": ""}
async def handle_data_extra_stage_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/data/rev/ExtraStageList.csv", encoding="shift-jis") as stage:
lines = stage.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return {"data": ret_str}
@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(
rf"titles/cxb/data/rss/Ex000{extra_num}.csv", encoding="shift-jis"
rf"titles/cxb/data/rev/Ex000{extra_num}.csv", encoding="shift-jis"
) as stage:
lines = stage.readlines()
for line in lines:
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:
with open(r"titles/cxb/data/rev/NewsList.csv", encoding="UTF-8") as news:
lines = news.readlines()
for line in lines:
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:
with open(r"titles/cxb/data/rev/License_Offline.csv", encoding="UTF-8") as lic:
lines = lic.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
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"
r"titles/cxb/data/rev/Course/CourseList.csv", encoding="UTF-8"
) as course:
lines = course.readlines()
for line in lines:
@@ -217,12 +222,12 @@ 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 = ""
with open(
rf"titles/cxb/data/rss/Course/Cs000{extra_num}.csv", encoding="shift-jis"
rf"titles/cxb/data/rev/Course/Cs000{extra_num}.csv", encoding="shift-jis"
) as course:
lines = course.readlines()
for line in lines:
@@ -230,77 +235,77 @@ 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"
r"titles/cxb/data/rev/MissionList.csv", encoding="shift-jis"
) as mission:
lines = mission.readlines()
for line in lines:
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"
r"titles/cxb/data/rev/Event/EventArchiveList.csv", encoding="shift-jis"
) as mission:
lines = mission.readlines()
for line in lines:
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"
r"titles/cxb/data/rev/Event/EventStampList.csv", encoding="shift-jis"
) as event:
lines = event.readlines()
for line in lines:
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}
+31 -31
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"}
+31 -31
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"}
+4 -4
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()
+6 -6
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()
+12 -12
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()
+6 -6
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()
-1
View File
@@ -7,4 +7,3 @@ index = DivaServlet
database = DivaData
reader = DivaReader
game_codes = [DivaConstants.GAME_CODE]
current_schema_version = 6
+87 -88
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"]
)
+18 -28
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}")
+14 -14
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,
+5 -5
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
+4 -4
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()
+5 -5
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
+6 -6
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()

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