From 3613f4dbd24fe542699d3e4f110fc51e8e7d7786 Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Wed, 20 Mar 2024 21:42:38 +0100 Subject: [PATCH] mai2: BUDDiES support added --- .../81e44dd6047a_mai2_buddies_support.py | 68 +++++++++++++++++++ docs/game_specific_info.md | 2 + readme.md | 1 + titles/cm/read.py | 7 +- titles/mai2/buddies.py | 32 +++++++++ titles/mai2/const.py | 2 + titles/mai2/dx.py | 3 + titles/mai2/index.py | 6 +- titles/mai2/schema/profile.py | 2 + titles/mai2/schema/score.py | 37 +++++++++- 10 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 core/data/alembic/versions/81e44dd6047a_mai2_buddies_support.py create mode 100644 titles/mai2/buddies.py diff --git a/core/data/alembic/versions/81e44dd6047a_mai2_buddies_support.py b/core/data/alembic/versions/81e44dd6047a_mai2_buddies_support.py new file mode 100644 index 0000000..04d2217 --- /dev/null +++ b/core/data/alembic/versions/81e44dd6047a_mai2_buddies_support.py @@ -0,0 +1,68 @@ +"""mai2_buddies_support + +Revision ID: 81e44dd6047a +Revises: d8950c7ce2fc +Create Date: 2024-03-12 19:10:37.063907 + +""" + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +# revision identifiers, used by Alembic. +revision = "81e44dd6047a" +down_revision = "6a7e8277763b" +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_table( + "mai2_playlog_2p", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("user", sa.Integer(), nullable=False), + sa.Column("userId1", sa.Integer(), nullable=True), + sa.Column("userId2", sa.Integer(), nullable=True), + sa.Column("userName1", sa.String(length=25), nullable=True), + sa.Column("userName2", sa.String(length=25), nullable=True), + sa.Column("regionId", sa.Integer(), nullable=True), + sa.Column("placeId", sa.Integer(), nullable=True), + sa.Column("user2pPlaylogDetailList", sa.JSON(), nullable=True), + sa.ForeignKeyConstraint( + ["user"], ["aime_user.id"], onupdate="cascade", ondelete="cascade" + ), + sa.PrimaryKeyConstraint("id"), + mysql_charset="utf8mb4", + ) + + op.add_column( + "mai2_playlog", + sa.Column( + "extBool1", sa.Boolean(), nullable=True, server_default=sa.text("NULL") + ), + ) + + op.add_column( + "mai2_profile_detail", + sa.Column( + "renameCredit", sa.Integer(), nullable=True, server_default=sa.text("NULL") + ), + ) + op.add_column( + "mai2_profile_detail", + sa.Column( + "currentPlayCount", + sa.Integer(), + nullable=True, + server_default=sa.text("NULL"), + ), + ) + + +def downgrade(): + op.drop_table("mai2_playlog_2p") + + op.drop_column("mai2_playlog", "extBool1") + op.drop_column("mai2_profile_detail", "renameCredit") + op.drop_column("mai2_profile_detail", "currentPlayCount") diff --git a/docs/game_specific_info.md b/docs/game_specific_info.md index ab2daab..8b04697 100644 --- a/docs/game_specific_info.md +++ b/docs/game_specific_info.md @@ -192,6 +192,7 @@ Config file is located in `config/cxb.yaml`. | SDEZ | 18 | maimai DX UNiVERSE PLUS | | SDEZ | 19 | maimai DX FESTiVAL | | SDEZ | 20 | maimai DX FESTiVAL PLUS | +| SDEZ | 21 | maimai DX BUDDiES | ### Importer @@ -406,6 +407,7 @@ After that, on next login the present should be received (or whenever it suppose * UNiVERSE PLUS: Yes * FESTiVAL: Yes (added in A031) * FESTiVAL PLUS: Yes (added in A035) + * BUDDiES: Yes (added in A039) * O.N.G.E.K.I. bright MEMORY: Yes diff --git a/readme.md b/readme.md index 1226784..114fef5 100644 --- a/readme.md +++ b/readme.md @@ -47,6 +47,7 @@ Games listed below have been tested and confirmed working. Only game versions ol + UNiVERSE PLUS + FESTiVAL + FESTiVAL PLUS + + BUDDiES + O.N.G.E.K.I. + SUMMER diff --git a/titles/cm/read.py b/titles/cm/read.py index 0e2c841..2b5ec8a 100644 --- a/titles/cm/read.py +++ b/titles/cm/read.py @@ -206,6 +206,7 @@ class CardMakerReader(BaseReader): "1.25": Mai2Constants.VER_MAIMAI_DX_UNIVERSE_PLUS, "1.30": Mai2Constants.VER_MAIMAI_DX_FESTIVAL, "1.35": Mai2Constants.VER_MAIMAI_DX_FESTIVAL_PLUS, + "1.40": Mai2Constants.VER_MAIMAI_DX_BUDDIES, } for root, dirs, files in os.walk(base_dir): @@ -225,12 +226,6 @@ class CardMakerReader(BaseReader): True if troot.find("disable").text == "false" else False ) - # check if a date is part of the name and disable the - # card if it is - enabled = ( - False if re.search(r"\d{2}/\d{2}/\d{2}", name) else enabled - ) - await self.mai2_data.static.put_card( version, card_id, name, enabled=enabled ) diff --git a/titles/mai2/buddies.py b/titles/mai2/buddies.py new file mode 100644 index 0000000..f04b215 --- /dev/null +++ b/titles/mai2/buddies.py @@ -0,0 +1,32 @@ +from typing import Dict + +from core.config import CoreConfig +from titles.mai2.festivalplus import Mai2FestivalPlus +from titles.mai2.const import Mai2Constants +from titles.mai2.config import Mai2Config + + +class Mai2Buddies(Mai2FestivalPlus): + def __init__(self, cfg: CoreConfig, game_cfg: Mai2Config) -> None: + super().__init__(cfg, game_cfg) + self.version = Mai2Constants.VER_MAIMAI_DX_BUDDIES + + async def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict: + user_data = await super().handle_cm_get_user_preview_api_request(data) + + # hardcode lastDataVersion for CardMaker + user_data["lastDataVersion"] = "1.40.00" + return user_data + + async def handle_get_user_new_item_api_request(self, data: Dict) -> Dict: + # TODO: Added in 1.41, implement this? + user_id = data["userId"] + version = data.get("version", 1041000) + user_playlog_list = data.get("userPlaylogList", []) + + return { + "userId": user_id, + "itemKind": -1, + "itemId": -1, + } + diff --git a/titles/mai2/const.py b/titles/mai2/const.py index a4c29db..92e00e7 100644 --- a/titles/mai2/const.py +++ b/titles/mai2/const.py @@ -53,6 +53,7 @@ class Mai2Constants: VER_MAIMAI_DX_UNIVERSE_PLUS = 18 VER_MAIMAI_DX_FESTIVAL = 19 VER_MAIMAI_DX_FESTIVAL_PLUS = 20 + VER_MAIMAI_DX_BUDDIES = 21 VERSION_STRING = ( "maimai", @@ -76,6 +77,7 @@ class Mai2Constants: "maimai DX UNiVERSE PLUS", "maimai DX FESTiVAL", "maimai DX FESTiVAL PLUS", + "maimai DX BUDDiES" ) @classmethod diff --git a/titles/mai2/dx.py b/titles/mai2/dx.py index fff39f2..837fb8f 100644 --- a/titles/mai2/dx.py +++ b/titles/mai2/dx.py @@ -212,6 +212,9 @@ class Mai2DX(Mai2Base): ), ) await self.data.item.put_friend_season_ranking(user_id, fsr) + + if "user2pPlaylog" in upsert: + await self.data.score.put_playlog_2p(user_id, upsert["user2pPlaylog"]) return {"returnCode": 1, "apiName": "UpsertUserAllApi"} diff --git a/titles/mai2/index.py b/titles/mai2/index.py index 2ee4cae..df167f0 100644 --- a/titles/mai2/index.py +++ b/titles/mai2/index.py @@ -25,6 +25,7 @@ from .universe import Mai2Universe from .universeplus import Mai2UniversePlus from .festival import Mai2Festival from .festivalplus import Mai2FestivalPlus +from .buddies import Mai2Buddies class Mai2Servlet(BaseServlet): @@ -58,6 +59,7 @@ class Mai2Servlet(BaseServlet): Mai2UniversePlus, Mai2Festival, Mai2FestivalPlus, + Mai2Buddies ] self.logger = logging.getLogger("mai2") @@ -257,8 +259,10 @@ class Mai2Servlet(BaseServlet): internal_ver = Mai2Constants.VER_MAIMAI_DX_UNIVERSE_PLUS elif version >= 130 and version < 135: # FESTiVAL internal_ver = Mai2Constants.VER_MAIMAI_DX_FESTIVAL - elif version >= 135: # FESTiVAL PLUS + elif version >= 135 and version < 140: # FESTiVAL PLUS internal_ver = Mai2Constants.VER_MAIMAI_DX_FESTIVAL_PLUS + elif version >= 140: # BUDDiES + internal_ver = Mai2Constants.VER_MAIMAI_DX_BUDDIES if ( request.headers.get("Mai-Encoding") is not None diff --git a/titles/mai2/schema/profile.py b/titles/mai2/schema/profile.py index b4cdbd8..8f1d5f3 100644 --- a/titles/mai2/schema/profile.py +++ b/titles/mai2/schema/profile.py @@ -40,6 +40,8 @@ detail = Table( Column("charaLockSlot", JSON), Column("contentBit", BigInteger), Column("playCount", Integer), + Column("currentPlayCount", Integer), # new with buddies + Column("renameCredit", Integer), # new with buddies Column("mapStock", Integer), # new with fes+ Column("eventWatchedDate", String(25)), Column("lastGameId", String(25)), diff --git a/titles/mai2/schema/score.py b/titles/mai2/schema/score.py index 51dcc18..d13faae 100644 --- a/titles/mai2/schema/score.py +++ b/titles/mai2/schema/score.py @@ -145,11 +145,34 @@ playlog = Table( Column("isNewFree", Boolean), Column("extNum1", Integer), Column("extNum2", Integer), - Column("extNum4", Integer, server_default="0"), + Column("extNum4", Integer), + Column("extBool1", Boolean), # new with buddies Column("trialPlayAchievement", Integer), mysql_charset="utf8mb4", ) +# new with buddies +playlog_2p = Table( + "mai2_playlog_2p", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column( + "user", + ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), + nullable=False, + ), + # TODO: ForeignKey to aime_user? + Column("userId1", Integer), + Column("userId2", Integer), + # TODO: ForeignKey to mai2_profile_detail? + Column("userName1", String(25)), + Column("userName2", String(25)), + Column("regionId", Integer), + Column("placeId", Integer), + Column("user2pPlaylogDetailList", JSON), + mysql_charset="utf8mb4", +) + course = Table( "mai2_score_course", metadata, @@ -343,6 +366,18 @@ class Mai2ScoreData(BaseData): self.logger.error(f"put_playlog: Failed to insert! user_id {user_id} is_dx {is_dx}") return None return result.lastrowid + + async def put_playlog_2p(self, user_id: int, playlog_2p_data: Dict) -> Optional[int]: + playlog_2p_data["user"] = user_id + sql = insert(playlog_2p).values(**playlog_2p_data) + + conflict = sql.on_duplicate_key_update(**playlog_2p_data) + + result = await self.execute(conflict) + if result is None: + self.logger.error(f"put_playlog_2p: Failed to insert! user_id {user_id}") + return None + return result.lastrowid async def put_course(self, user_id: int, course_data: Dict) -> Optional[int]: course_data["user"] = user_id