From 318b73dd57b71dfb87fabef9c21ce99f1c2b222e Mon Sep 17 00:00:00 2001 From: Kevin Trocolli Date: Sat, 1 Jul 2023 01:08:54 -0400 Subject: [PATCH] finale: finish porting request data from aqua --- titles/mai2/base.py | 92 +++++++++++++---- titles/mai2/dx.py | 21 ---- titles/mai2/schema/profile.py | 182 +++++++++++++++++++++++++++++----- titles/mai2/schema/score.py | 39 +++++--- 4 files changed, 258 insertions(+), 76 deletions(-) diff --git a/titles/mai2/base.py b/titles/mai2/base.py index ef15abe..ae12e81 100644 --- a/titles/mai2/base.py +++ b/titles/mai2/base.py @@ -112,12 +112,12 @@ class Mai2Base: return {"returnCode": 1, "apiName": "UpsertClientTestmodeApi"} def handle_get_user_preview_api_request(self, data: Dict) -> Dict: - p = self.data.profile.get_profile_detail(data["userId"], self.version) - o = self.data.profile.get_profile_option(data["userId"], self.version) - if p is None or o is None: + p = self.data.profile.get_profile_detail(data["userId"], self.version, True) + w = self.data.profile.get_web_option(data["userId"], self.version) + if p is None or w is None: return {} # Register profile = p._asdict() - option = o._asdict() + web_opt = w._asdict() return { "userId": data["userId"], @@ -127,16 +127,15 @@ class Mai2Base: "lastLoginDate": profile["lastLoginDate"], "lastPlayDate": profile["lastPlayDate"], "playerRating": profile["playerRating"], - "nameplateId": 0, # Unused + "nameplateId": profile["nameplateId"], "frameId": profile["frameId"], "iconId": profile["iconId"], - "trophyId": 0, # Unused - "partnerId": profile["partnerId"], - "dispRate": option["dispRate"], # 0: all, 1: dispRate, 2: dispDan, 3: hide - "dispRank": 0, # TODO - "dispHomeRanker": 0, # TODO - "dispTotalLv": 0, # TODO - "totalLv": 0, # TODO + "trophyId": profile["trophyId"], + "dispRate": web_opt["dispRate"], # 0: all, 1: dispRate, 2: dispDan, 3: hide + "dispRank": web_opt["dispRank"], + "dispHomeRanker": web_opt["dispHomeRanker"], + "dispTotalLv": web_opt["dispTotalLv"], + "totalLv": profile["totalLv"], } def handle_user_login_api_request(self, data: Dict) -> Dict: @@ -188,11 +187,34 @@ class Mai2Base: upsert = data["upsertUserAll"] if "userData" in upsert and len(upsert["userData"]) > 0: - upsert["userData"][0]["isNetMember"] = 1 upsert["userData"][0].pop("accessCode") + upsert["userData"][0].pop("userId") + self.data.profile.put_profile_detail( - user_id, self.version, upsert["userData"][0] + user_id, self.version, upsert["userData"][0], False ) + + if "UserWebOption" in upsert and len(upsert["UserWebOption"]) > 0: + upsert["UserWebOption"][0]["isNetMember"] = True + self.data.profile.put_web_option( + user_id, self.version, upsert["UserWebOption"][0] + ) + + if "userGradeStatusList" in upsert and len(upsert["userGradeStatusList"]) > 0: + self.data.profile.put_web_option( + user_id, self.version, upsert["userGradeStatusList"][0] + ) + + if "userBossList" in upsert and len(upsert["userBossList"]) > 0: + self.data.profile.put_boss_list( + user_id, self.version, upsert["userBossList"][0] + ) + + if "userPlaylogList" in upsert and len(upsert["userPlaylogList"]) > 0: + for playlog in upsert["userPlaylogList"]: + self.data.score.put_playlog( + user_id, self.version, playlog + ) if "userExtend" in upsert and len(upsert["userExtend"]) > 0: self.data.profile.put_profile_extend( @@ -201,11 +223,14 @@ class Mai2Base: if "userGhost" in upsert: for ghost in upsert["userGhost"]: - self.data.profile.put_profile_extend(user_id, self.version, ghost) + self.data.profile.put_profile_ghost(user_id, self.version, ghost) + + if "userRecentRatingList" in upsert: + self.data.profile.put_recent_rating(user_id, self.version, upsert["userRecentRatingList"]) if "userOption" in upsert and len(upsert["userOption"]) > 0: self.data.profile.put_profile_option( - user_id, self.version, upsert["userOption"][0] + user_id, self.version, upsert["userOption"][0], False ) if "userRatingList" in upsert and len(upsert["userRatingList"]) > 0: @@ -305,7 +330,7 @@ class Mai2Base: return {"returnCode": 1} def handle_get_user_data_api_request(self, data: Dict) -> Dict: - profile = self.data.profile.get_profile_detail(data["userId"], self.version) + profile = self.data.profile.get_profile_detail(data["userId"], self.version, False) if profile is None: return @@ -329,7 +354,7 @@ class Mai2Base: return {"userId": data["userId"], "userExtend": extend_dict} def handle_get_user_option_api_request(self, data: Dict) -> Dict: - options = self.data.profile.get_profile_option(data["userId"], self.version) + options = self.data.profile.get_profile_option(data["userId"], self.version, False) if options is None: return @@ -399,6 +424,25 @@ class Mai2Base: "userChargeList": user_charge_list, } + def handle_get_user_present_api_request(self, data: Dict) -> Dict: + return { "userId": data.get("userId", 0), "length": 0, "userPresentList": []} + + def handle_get_transfer_friend_api_request(self, data: Dict) -> Dict: + return {} + + def handle_get_user_present_event_api_request(self, data: Dict) -> Dict: + return { "userId": data.get("userId", 0), "length": 0, "userPresentEventList": []} + + def handle_get_user_boss_api_request(self, data: Dict) -> Dict: + b = self.data.profile.get_boss_list(data["userId"]) + if b is None: + return { "userId": data.get("userId", 0), "userBossData": {}} + boss_lst = b._asdict() + boss_lst.pop("id") + boss_lst.pop("user") + + return { "userId": data.get("userId", 0), "userBossData": boss_lst} + def handle_get_user_item_api_request(self, data: Dict) -> Dict: kind = int(data["nextIndex"] / 10000000000) next_idx = int(data["nextIndex"] % 10000000000) @@ -435,6 +479,8 @@ class Mai2Base: tmp = chara._asdict() tmp.pop("id") tmp.pop("user") + tmp.pop("awakening") + tmp.pop("useCount") chara_list.append(tmp) return {"userId": data["userId"], "userCharacterList": chara_list} @@ -468,6 +514,16 @@ class Mai2Base: return {"userId": data["userId"], "userGhost": ghost_dict} + def handle_get_user_recent_rating_api_request(self, data: Dict) -> Dict: + rating = self.data.profile.get_recent_rating(data["userId"]) + if rating is None: + return + + r = rating._asdict() + lst = r.get("userRecentRatingList", []) + + return {"userId": data["userId"], "length": len(lst), "userRecentRatingList": lst} + def handle_get_user_rating_api_request(self, data: Dict) -> Dict: rating = self.data.profile.get_profile_rating(data["userId"], self.version) if rating is None: diff --git a/titles/mai2/dx.py b/titles/mai2/dx.py index 9ac7067..266332e 100644 --- a/titles/mai2/dx.py +++ b/titles/mai2/dx.py @@ -75,27 +75,6 @@ class Mai2DX(Mai2Base): else 0, # New with uni+ } - def handle_user_login_api_request(self, data: Dict) -> Dict: - profile = self.data.profile.get_profile_detail(data["userId"], self.version) - - if profile is not None: - lastLoginDate = profile["lastLoginDate"] - loginCt = profile["playCount"] - - if "regionId" in data: - self.data.profile.put_profile_region(data["userId"], data["regionId"]) - else: - loginCt = 0 - lastLoginDate = "2017-12-05 07:00:00.0" - - return { - "returnCode": 1, - "lastLoginDate": lastLoginDate, - "loginCount": loginCt, - "consecutiveLoginCount": 0, # We don't really have a way to track this... - "loginId": loginCt, # Used with the playlog! - } - def handle_upload_user_playlog_api_request(self, data: Dict) -> Dict: user_id = data["userId"] playlog = data["userPlaylog"] diff --git a/titles/mai2/schema/profile.py b/titles/mai2/schema/profile.py index eb0da73..950fd99 100644 --- a/titles/mai2/schema/profile.py +++ b/titles/mai2/schema/profile.py @@ -423,42 +423,80 @@ activity = Table( ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False, ), - Column("kind", Integer, nullable=False), - Column("activityId", Integer, nullable=False), - Column("param1", Integer, nullable=False), - Column("param2", Integer, nullable=False), - Column("param3", Integer, nullable=False), - Column("param4", Integer, nullable=False), - Column("sortNumber", Integer, nullable=False), + Column("kind", Integer), + Column("activityId", Integer), + Column("param1", Integer), + Column("param2", Integer), + Column("param3", Integer), + Column("param4", Integer), + Column("sortNumber", Integer), UniqueConstraint("user", "kind", "activityId", name="mai2_profile_activity_uk"), mysql_charset="utf8mb4", ) +boss_list = Table( + "mai2_profile_boss_list", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False), + Column("pandoraFlagList0", Integer), + Column("pandoraFlagList1", Integer), + Column("pandoraFlagList2", Integer), + Column("pandoraFlagList3", Integer), + Column("pandoraFlagList4", Integer), + Column("pandoraFlagList5", Integer), + Column("pandoraFlagList6", Integer), + Column("emblemFlagList", Integer), + UniqueConstraint("user", name="mai2_profile_boss_list_uk"), + mysql_charset="utf8mb4", +) + +recent_rating = Table( + "mai2_profile_recent_rating", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False), + Column("userRecentRatingList", Integer), + UniqueConstraint("user", name="mai2_profile_recent_rating_uk"), + mysql_charset="utf8mb4", +) class Mai2ProfileData(BaseData): def put_profile_detail( - self, user_id: int, version: int, detail_data: Dict + self, user_id: int, version: int, detail_data: Dict, is_dx: bool = True ) -> Optional[Row]: detail_data["user"] = user_id detail_data["version"] = version - sql = insert(detail).values(**detail_data) + + if is_dx: + sql = insert(detail).values(**detail_data) + else: + sql = insert(detail_old).values(**detail_data) conflict = sql.on_duplicate_key_update(**detail_data) result = self.execute(conflict) if result is None: self.logger.warn( - f"put_profile: Failed to create profile! user_id {user_id}" + f"put_profile: Failed to create profile! user_id {user_id} is_dx {is_dx}" ) return None return result.lastrowid - def get_profile_detail(self, user_id: int, version: int) -> Optional[Row]: - sql = ( - select(detail) - .where(and_(detail.c.user == user_id, detail.c.version <= version)) - .order_by(detail.c.version.desc()) - ) + def get_profile_detail(self, user_id: int, version: int, is_dx: bool = True) -> Optional[Row]: + if is_dx: + sql = ( + select(detail) + .where(and_(detail.c.user == user_id, detail.c.version <= version)) + .order_by(detail.c.version.desc()) + ) + + else: + sql = ( + select(detail_old) + .where(and_(detail_old.c.user == user_id, detail_old.c.version <= version)) + .order_by(detail_old.c.version.desc()) + ) result = self.execute(sql) if result is None: @@ -520,26 +558,36 @@ class Mai2ProfileData(BaseData): return result.fetchone() def put_profile_option( - self, user_id: int, version: int, option_data: Dict + self, user_id: int, version: int, option_data: Dict, is_dx: bool = True ) -> Optional[int]: option_data["user"] = user_id option_data["version"] = version - sql = insert(option).values(**option_data) + if is_dx: + sql = insert(option).values(**option_data) + else: + sql = insert(option_old).values(**option_data) conflict = sql.on_duplicate_key_update(**option_data) result = self.execute(conflict) if result is None: - self.logger.warn(f"put_profile_option: failed to update! {user_id}") + self.logger.warn(f"put_profile_option: failed to update! {user_id} is_dx {is_dx}") return None return result.lastrowid - def get_profile_option(self, user_id: int, version: int) -> Optional[Row]: - sql = ( - select(option) - .where(and_(option.c.user == user_id, option.c.version <= version)) - .order_by(option.c.version.desc()) - ) + def get_profile_option(self, user_id: int, version: int, is_dx: bool = True) -> Optional[Row]: + if is_dx: + sql = ( + select(option) + .where(and_(option.c.user == user_id, option.c.version <= version)) + .order_by(option.c.version.desc()) + ) + else: + sql = ( + select(option_old) + .where(and_(option_old.c.user == user_id, option_old.c.version <= version)) + .order_by(option_old.c.version.desc()) + ) result = self.execute(sql) if result is None: @@ -629,3 +677,87 @@ class Mai2ProfileData(BaseData): if result is None: return None return result.fetchall() + + def put_web_option(self, user_id: int, web_opts: Dict) -> Optional[int]: + sql = insert(web_opt).values(**web_opts) + + conflict = sql.on_duplicate_key_update(**web_opts) + + result = self.execute(conflict) + if result is None: + self.logger.warn( + f"put_web_option: failed to update! user_id: {user_id}" + ) + return None + return result.lastrowid + + def get_web_option(self, user_id: int) -> Optional[Row]: + sql = web_opt.select(web_opt.c.user == user_id) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def put_grade_status(self, user_id: int, grade_stat: Dict) -> Optional[int]: + sql = insert(grade_status).values(**grade_stat) + + conflict = sql.on_duplicate_key_update(**grade_stat) + + result = self.execute(conflict) + if result is None: + self.logger.warn( + f"put_grade_status: failed to update! user_id: {user_id}" + ) + return None + return result.lastrowid + + def get_grade_status(self, user_id: int) -> Optional[Row]: + sql = grade_status.select(grade_status.c.user == user_id) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def put_boss_list(self, user_id: int, boss_stat: Dict) -> Optional[int]: + sql = insert(boss_list).values(**boss_stat) + + conflict = sql.on_duplicate_key_update(**boss_stat) + + result = self.execute(conflict) + if result is None: + self.logger.warn( + f"put_boss_list: failed to update! user_id: {user_id}" + ) + return None + return result.lastrowid + + def get_boss_list(self, user_id: int) -> Optional[Row]: + sql = boss_list.select(boss_list.c.user == user_id) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def put_recent_rating(self, user_id: int, rr: Dict) -> Optional[int]: + sql = insert(recent_rating).values(**rr) + + conflict = sql.on_duplicate_key_update(**rr) + + result = self.execute(conflict) + if result is None: + self.logger.warn( + f"put_recent_rating: failed to update! user_id: {user_id}" + ) + return None + return result.lastrowid + + def get_recent_rating(self, user_id: int) -> Optional[Row]: + sql = recent_rating.select(recent_rating.c.user == user_id) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() \ No newline at end of file diff --git a/titles/mai2/schema/score.py b/titles/mai2/schema/score.py index b754eb6..6b25d14 100644 --- a/titles/mai2/schema/score.py +++ b/titles/mai2/schema/score.py @@ -273,28 +273,39 @@ best_score_old = Table( ) class Mai2ScoreData(BaseData): - def put_best_score(self, user_id: int, score_data: Dict) -> Optional[int]: + def put_best_score(self, user_id: int, score_data: Dict, is_dx: bool = True) -> Optional[int]: score_data["user"] = user_id - sql = insert(best_score).values(**score_data) + if is_dx: + sql = insert(best_score).values(**score_data) + else: + sql = insert(best_score_old).values(**score_data) conflict = sql.on_duplicate_key_update(**score_data) result = self.execute(conflict) if result is None: self.logger.error( - f"put_best_score: Failed to insert best score! user_id {user_id}" + f"put_best_score: Failed to insert best score! user_id {user_id} is_dx {is_dx}" ) return None return result.lastrowid @cached(2) - def get_best_scores(self, user_id: int, song_id: int = None) -> Optional[List[Row]]: - sql = best_score.select( - and_( - best_score.c.user == user_id, - (best_score.c.song_id == song_id) if song_id is not None else True, + def get_best_scores(self, user_id: int, song_id: int = None, is_dx: bool = True) -> Optional[List[Row]]: + if is_dx: + sql = best_score.select( + and_( + best_score.c.user == user_id, + (best_score.c.song_id == song_id) if song_id is not None else True, + ) + ) + else: + sql = best_score_old.select( + and_( + best_score_old.c.user == user_id, + (best_score_old.c.song_id == song_id) if song_id is not None else True, + ) ) - ) result = self.execute(sql) if result is None: @@ -317,15 +328,19 @@ class Mai2ScoreData(BaseData): return None return result.fetchone() - def put_playlog(self, user_id: int, playlog_data: Dict) -> Optional[int]: + def put_playlog(self, user_id: int, playlog_data: Dict, is_dx: bool = True) -> Optional[int]: playlog_data["user"] = user_id - sql = insert(playlog).values(**playlog_data) + + if is_dx: + sql = insert(playlog).values(**playlog_data) + else: + sql = insert(playlog_old).values(**playlog_data) conflict = sql.on_duplicate_key_update(**playlog_data) result = self.execute(conflict) if result is None: - self.logger.error(f"put_playlog: Failed to insert! user_id {user_id}") + self.logger.error(f"put_playlog: Failed to insert! user_id {user_id} is_dx {is_dx}") return None return result.lastrowid