forked from Hay1tsme/artemis
Merge pull request 'maimai DX FESTiVAL PLUS support' (#44) from Dniel97/artemis:mai2_festival_plus into develop
Reviewed-on: Hay1tsme/artemis#44
This commit is contained in:
commit
46f83b9925
@ -1,6 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
Documenting updates to ARTEMiS, to be updated every time the master branch is pushed to.
|
Documenting updates to ARTEMiS, to be updated every time the master branch is pushed to.
|
||||||
|
|
||||||
|
## 20231015
|
||||||
|
### maimai DX
|
||||||
|
+ Added support for FESTiVAL PLUS
|
||||||
|
|
||||||
|
### Card Maker
|
||||||
|
+ Added support for maimai DX FESTiVAL PLUS
|
||||||
|
|
||||||
## 20230716
|
## 20230716
|
||||||
### General
|
### General
|
||||||
+ Docker files added (#19)
|
+ Docker files added (#19)
|
||||||
|
10
core/data/schema/versions/SDEZ_7_rollback.sql
Normal file
10
core/data/schema/versions/SDEZ_7_rollback.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ALTER TABLE mai2_profile_detail
|
||||||
|
DROP COLUMN mapStock;
|
||||||
|
|
||||||
|
ALTER TABLE mai2_profile_extend
|
||||||
|
DROP COLUMN selectResultScoreViewType;
|
||||||
|
|
||||||
|
ALTER TABLE mai2_profile_option
|
||||||
|
DROP COLUMN outFrameType,
|
||||||
|
DROP COLUMN touchVolume,
|
||||||
|
DROP COLUMN breakSlideVolume;
|
10
core/data/schema/versions/SDEZ_8_upgrade.sql
Normal file
10
core/data/schema/versions/SDEZ_8_upgrade.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ALTER TABLE mai2_profile_detail
|
||||||
|
ADD mapStock INT NULL AFTER playCount;
|
||||||
|
|
||||||
|
ALTER TABLE mai2_profile_extend
|
||||||
|
ADD selectResultScoreViewType INT NULL AFTER selectResultDetails;
|
||||||
|
|
||||||
|
ALTER TABLE mai2_profile_option
|
||||||
|
ADD outFrameType INT NULL AFTER dispCenter,
|
||||||
|
ADD touchVolume INT NULL AFTER slideVolume,
|
||||||
|
ADD breakSlideVolume INT NULL AFTER slideVolume;
|
@ -194,18 +194,19 @@ For versions pre-dx
|
|||||||
| SDBM | 5 | maimai ORANGE PLUS |
|
| SDBM | 5 | maimai ORANGE PLUS |
|
||||||
| SDCQ | 6 | maimai PiNK |
|
| SDCQ | 6 | maimai PiNK |
|
||||||
| SDCQ | 7 | maimai PiNK PLUS |
|
| SDCQ | 7 | maimai PiNK PLUS |
|
||||||
| SDDK | 8 | maimai MURASAKI |
|
| SDDK | 8 | maimai MURASAKi |
|
||||||
| SDDK | 9 | maimai MURASAKI PLUS |
|
| SDDK | 9 | maimai MURASAKi PLUS |
|
||||||
| SDDZ | 10 | maimai MILK |
|
| SDDZ | 10 | maimai MiLK |
|
||||||
| SDDZ | 11 | maimai MILK PLUS |
|
| SDDZ | 11 | maimai MiLK PLUS |
|
||||||
| SDEY | 12 | maimai FiNALE |
|
| SDEY | 12 | maimai FiNALE |
|
||||||
| SDEZ | 13 | maimai DX |
|
| SDEZ | 13 | maimai DX |
|
||||||
| SDEZ | 14 | maimai DX PLUS |
|
| SDEZ | 14 | maimai DX PLUS |
|
||||||
| SDEZ | 15 | maimai DX Splash |
|
| SDEZ | 15 | maimai DX Splash |
|
||||||
| SDEZ | 16 | maimai DX Splash PLUS |
|
| SDEZ | 16 | maimai DX Splash PLUS |
|
||||||
| SDEZ | 17 | maimai DX Universe |
|
| SDEZ | 17 | maimai DX UNiVERSE |
|
||||||
| SDEZ | 18 | maimai DX Universe PLUS |
|
| SDEZ | 18 | maimai DX UNiVERSE PLUS |
|
||||||
| SDEZ | 19 | maimai DX Festival |
|
| SDEZ | 19 | maimai DX FESTiVAL |
|
||||||
|
| SDEZ | 20 | maimai DX FESTiVAL PLUS |
|
||||||
|
|
||||||
### Importer
|
### Importer
|
||||||
|
|
||||||
@ -347,15 +348,21 @@ python dbutils.py --game SDDT upgrade
|
|||||||
|
|
||||||
### Support status
|
### Support status
|
||||||
|
|
||||||
* Card Maker 1.30:
|
#### Card Maker 1.30:
|
||||||
* CHUNITHM NEW!!: Yes
|
* CHUNITHM NEW!!: Yes
|
||||||
* maimai DX UNiVERSE: Yes
|
* maimai DX UNiVERSE: Yes
|
||||||
* O.N.G.E.K.I. bright: Yes
|
* O.N.G.E.K.I. bright: Yes
|
||||||
|
|
||||||
* Card Maker 1.35:
|
#### Card Maker 1.35:
|
||||||
* CHUNITHM SUN: Yes (NEW PLUS!! up to A032)
|
* CHUNITHM:
|
||||||
* maimai DX FESTiVAL: Yes (up to A035) (UNiVERSE PLUS up to A031)
|
* NEW!!: Yes
|
||||||
* O.N.G.E.K.I. bright MEMORY: Yes
|
* NEW PLUS!!: Yes (added in A028)
|
||||||
|
* SUN: Yes (added in A032)
|
||||||
|
* maimai DX:
|
||||||
|
* UNiVERSE PLUS: Yes
|
||||||
|
* FESTiVAL: Yes (added in A031)
|
||||||
|
* FESTiVAL PLUS: Yes (added in A035)
|
||||||
|
* O.N.G.E.K.I. bright MEMORY: Yes
|
||||||
|
|
||||||
|
|
||||||
### Importer
|
### Importer
|
||||||
|
@ -11,7 +11,7 @@ Games listed below have been tested and confirmed working. Only game versions ol
|
|||||||
+ All versions + omnimix
|
+ All versions + omnimix
|
||||||
|
|
||||||
+ maimai DX
|
+ maimai DX
|
||||||
+ All versions up to FESTiVAL
|
+ All versions up to FESTiVAL PLUS
|
||||||
|
|
||||||
+ Hatsune Miku: Project DIVA Arcade
|
+ Hatsune Miku: Project DIVA Arcade
|
||||||
+ All versions
|
+ All versions
|
||||||
|
@ -205,6 +205,7 @@ class CardMakerReader(BaseReader):
|
|||||||
"1.20": Mai2Constants.VER_MAIMAI_DX_UNIVERSE,
|
"1.20": Mai2Constants.VER_MAIMAI_DX_UNIVERSE,
|
||||||
"1.25": Mai2Constants.VER_MAIMAI_DX_UNIVERSE_PLUS,
|
"1.25": Mai2Constants.VER_MAIMAI_DX_UNIVERSE_PLUS,
|
||||||
"1.30": Mai2Constants.VER_MAIMAI_DX_FESTIVAL,
|
"1.30": Mai2Constants.VER_MAIMAI_DX_FESTIVAL,
|
||||||
|
"1.35": Mai2Constants.VER_MAIMAI_DX_FESTIVAL_PLUS,
|
||||||
}
|
}
|
||||||
|
|
||||||
for root, dirs, files in os.walk(base_dir):
|
for root, dirs, files in os.walk(base_dir):
|
||||||
|
@ -16,4 +16,4 @@ game_codes = [
|
|||||||
Mai2Constants.GAME_CODE_GREEN,
|
Mai2Constants.GAME_CODE_GREEN,
|
||||||
Mai2Constants.GAME_CODE,
|
Mai2Constants.GAME_CODE,
|
||||||
]
|
]
|
||||||
current_schema_version = 7
|
current_schema_version = 8
|
||||||
|
@ -20,13 +20,13 @@ class Mai2Constants:
|
|||||||
|
|
||||||
DATE_TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
|
DATE_TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
|
||||||
|
|
||||||
GAME_CODE = "SBXL"
|
GAME_CODE = "SBXL"
|
||||||
GAME_CODE_GREEN = "SBZF"
|
GAME_CODE_GREEN = "SBZF"
|
||||||
GAME_CODE_ORANGE = "SDBM"
|
GAME_CODE_ORANGE = "SDBM"
|
||||||
GAME_CODE_PINK = "SDCQ"
|
GAME_CODE_PINK = "SDCQ"
|
||||||
GAME_CODE_MURASAKI = "SDDK"
|
GAME_CODE_MURASAKI = "SDDK"
|
||||||
GAME_CODE_MILK = "SDDZ"
|
GAME_CODE_MILK = "SDDZ"
|
||||||
GAME_CODE_FINALE = "SDEY"
|
GAME_CODE_FINALE = "SDEY"
|
||||||
GAME_CODE_DX = "SDEZ"
|
GAME_CODE_DX = "SDEZ"
|
||||||
|
|
||||||
CONFIG_NAME = "mai2.yaml"
|
CONFIG_NAME = "mai2.yaml"
|
||||||
@ -52,6 +52,7 @@ class Mai2Constants:
|
|||||||
VER_MAIMAI_DX_UNIVERSE = 17
|
VER_MAIMAI_DX_UNIVERSE = 17
|
||||||
VER_MAIMAI_DX_UNIVERSE_PLUS = 18
|
VER_MAIMAI_DX_UNIVERSE_PLUS = 18
|
||||||
VER_MAIMAI_DX_FESTIVAL = 19
|
VER_MAIMAI_DX_FESTIVAL = 19
|
||||||
|
VER_MAIMAI_DX_FESTIVAL_PLUS = 20
|
||||||
|
|
||||||
VERSION_STRING = (
|
VERSION_STRING = (
|
||||||
"maimai",
|
"maimai",
|
||||||
@ -66,7 +67,7 @@ class Mai2Constants:
|
|||||||
"maimai MURASAKi PLUS",
|
"maimai MURASAKi PLUS",
|
||||||
"maimai MiLK",
|
"maimai MiLK",
|
||||||
"maimai MiLK PLUS",
|
"maimai MiLK PLUS",
|
||||||
"maimai FiNALE",
|
"maimai FiNALE",
|
||||||
"maimai DX",
|
"maimai DX",
|
||||||
"maimai DX PLUS",
|
"maimai DX PLUS",
|
||||||
"maimai DX Splash",
|
"maimai DX Splash",
|
||||||
@ -74,6 +75,7 @@ class Mai2Constants:
|
|||||||
"maimai DX UNiVERSE",
|
"maimai DX UNiVERSE",
|
||||||
"maimai DX UNiVERSE PLUS",
|
"maimai DX UNiVERSE PLUS",
|
||||||
"maimai DX FESTiVAL",
|
"maimai DX FESTiVAL",
|
||||||
|
"maimai DX FESTiVAL PLUS",
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -542,8 +542,43 @@ class Mai2DX(Mai2Base):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def handle_get_user_region_api_request(self, data: Dict) -> Dict:
|
def handle_get_user_region_api_request(self, data: Dict) -> Dict:
|
||||||
|
"""
|
||||||
|
class UserRegionList:
|
||||||
|
regionId: int
|
||||||
|
playCount: int
|
||||||
|
created: str
|
||||||
|
"""
|
||||||
return {"userId": data["userId"], "length": 0, "userRegionList": []}
|
return {"userId": data["userId"], "length": 0, "userRegionList": []}
|
||||||
|
|
||||||
|
def handle_get_user_rival_data_api_request(self, data: Dict) -> Dict:
|
||||||
|
user_id = data["userId"]
|
||||||
|
rival_id = data["rivalId"]
|
||||||
|
|
||||||
|
"""
|
||||||
|
class UserRivalData:
|
||||||
|
rivalId: int
|
||||||
|
rivalName: str
|
||||||
|
"""
|
||||||
|
return {"userId": user_id, "userRivalData": {}}
|
||||||
|
|
||||||
|
def handle_get_user_rival_music_api_request(self, data: Dict) -> Dict:
|
||||||
|
user_id = data["userId"]
|
||||||
|
rival_id = data["rivalId"]
|
||||||
|
next_idx = data["nextIndex"]
|
||||||
|
rival_music_levels = data["userRivalMusicLevelList"]
|
||||||
|
|
||||||
|
"""
|
||||||
|
class UserRivalMusicList:
|
||||||
|
class UserRivalMusicDetailList:
|
||||||
|
level: int
|
||||||
|
achievement: int
|
||||||
|
deluxscoreMax: int
|
||||||
|
|
||||||
|
musicId: int
|
||||||
|
userRivalMusicDetailList: list[UserRivalMusicDetailList]
|
||||||
|
"""
|
||||||
|
return {"userId": user_id, "nextIndex": 0, "userRivalMusicList": []}
|
||||||
|
|
||||||
def handle_get_user_music_api_request(self, data: Dict) -> Dict:
|
def handle_get_user_music_api_request(self, data: Dict) -> Dict:
|
||||||
user_id = data.get("userId", 0)
|
user_id = data.get("userId", 0)
|
||||||
next_index = data.get("nextIndex", 0)
|
next_index = data.get("nextIndex", 0)
|
||||||
|
@ -14,7 +14,7 @@ class Mai2Festival(Mai2UniversePlus):
|
|||||||
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
|
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
|
||||||
user_data = super().handle_cm_get_user_preview_api_request(data)
|
user_data = super().handle_cm_get_user_preview_api_request(data)
|
||||||
|
|
||||||
# hardcode lastDataVersion for CardMaker 1.35
|
# hardcode lastDataVersion for CardMaker
|
||||||
user_data["lastDataVersion"] = "1.30.00"
|
user_data["lastDataVersion"] = "1.30.00"
|
||||||
return user_data
|
return user_data
|
||||||
|
|
||||||
@ -25,7 +25,13 @@ class Mai2Festival(Mai2UniversePlus):
|
|||||||
return user_login
|
return user_login
|
||||||
|
|
||||||
def handle_get_user_recommend_rate_music_api_request(self, data: Dict) -> Dict:
|
def handle_get_user_recommend_rate_music_api_request(self, data: Dict) -> Dict:
|
||||||
|
"""
|
||||||
|
userRecommendRateMusicIdList: list[int]
|
||||||
|
"""
|
||||||
return {"userId": data["userId"], "userRecommendRateMusicIdList": []}
|
return {"userId": data["userId"], "userRecommendRateMusicIdList": []}
|
||||||
|
|
||||||
def handle_get_user_recommend_select_music_api_request(self, data: Dict) -> Dict:
|
def handle_get_user_recommend_select_music_api_request(self, data: Dict) -> Dict:
|
||||||
|
"""
|
||||||
|
userRecommendSelectionMusicIdList: list[int]
|
||||||
|
"""
|
||||||
return {"userId": data["userId"], "userRecommendSelectionMusicIdList": []}
|
return {"userId": data["userId"], "userRecommendSelectionMusicIdList": []}
|
||||||
|
38
titles/mai2/festivalplus.py
Normal file
38
titles/mai2/festivalplus.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from core.config import CoreConfig
|
||||||
|
from titles.mai2.festival import Mai2Festival
|
||||||
|
from titles.mai2.const import Mai2Constants
|
||||||
|
from titles.mai2.config import Mai2Config
|
||||||
|
|
||||||
|
|
||||||
|
class Mai2FestivalPlus(Mai2Festival):
|
||||||
|
def __init__(self, cfg: CoreConfig, game_cfg: Mai2Config) -> None:
|
||||||
|
super().__init__(cfg, game_cfg)
|
||||||
|
self.version = Mai2Constants.VER_MAIMAI_DX_FESTIVAL_PLUS
|
||||||
|
|
||||||
|
def handle_cm_get_user_preview_api_request(self, data: Dict) -> Dict:
|
||||||
|
user_data = super().handle_cm_get_user_preview_api_request(data)
|
||||||
|
|
||||||
|
# hardcode lastDataVersion for CardMaker
|
||||||
|
user_data["lastDataVersion"] = "1.35.00"
|
||||||
|
return user_data
|
||||||
|
|
||||||
|
def handle_get_user_favorite_item_api_request(self, data: Dict) -> Dict:
|
||||||
|
user_id = data.get("userId", 0)
|
||||||
|
kind = data.get("kind", 2)
|
||||||
|
next_index = data.get("nextIndex", 0)
|
||||||
|
max_ct = data.get("maxCount", 100)
|
||||||
|
is_all = data.get("isAllFavoriteItem", False)
|
||||||
|
|
||||||
|
"""
|
||||||
|
class userFavoriteItemList:
|
||||||
|
orderId: int
|
||||||
|
id: int
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"userId": user_id,
|
||||||
|
"kind": kind,
|
||||||
|
"nextIndex": 0,
|
||||||
|
"userFavoriteItemList": [],
|
||||||
|
}
|
@ -23,6 +23,7 @@ from titles.mai2.splashplus import Mai2SplashPlus
|
|||||||
from titles.mai2.universe import Mai2Universe
|
from titles.mai2.universe import Mai2Universe
|
||||||
from titles.mai2.universeplus import Mai2UniversePlus
|
from titles.mai2.universeplus import Mai2UniversePlus
|
||||||
from titles.mai2.festival import Mai2Festival
|
from titles.mai2.festival import Mai2Festival
|
||||||
|
from titles.mai2.festivalplus import Mai2FestivalPlus
|
||||||
|
|
||||||
|
|
||||||
class Mai2Servlet:
|
class Mai2Servlet:
|
||||||
@ -47,7 +48,7 @@ class Mai2Servlet:
|
|||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
Mai2Finale,
|
Mai2Finale,
|
||||||
Mai2DX,
|
Mai2DX,
|
||||||
Mai2DXPlus,
|
Mai2DXPlus,
|
||||||
Mai2Splash,
|
Mai2Splash,
|
||||||
@ -55,6 +56,7 @@ class Mai2Servlet:
|
|||||||
Mai2Universe,
|
Mai2Universe,
|
||||||
Mai2UniversePlus,
|
Mai2UniversePlus,
|
||||||
Mai2Festival,
|
Mai2Festival,
|
||||||
|
Mai2FestivalPlus,
|
||||||
]
|
]
|
||||||
|
|
||||||
self.logger = logging.getLogger("mai2")
|
self.logger = logging.getLogger("mai2")
|
||||||
@ -110,22 +112,34 @@ class Mai2Servlet:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
if self.game_cfg.uploads.photos and self.game_cfg.uploads.photos_dir and not path.exists(self.game_cfg.uploads.photos_dir):
|
if (
|
||||||
|
self.game_cfg.uploads.photos
|
||||||
|
and self.game_cfg.uploads.photos_dir
|
||||||
|
and not path.exists(self.game_cfg.uploads.photos_dir)
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
mkdir(self.game_cfg.uploads.photos_dir)
|
mkdir(self.game_cfg.uploads.photos_dir)
|
||||||
except Exception:
|
except Exception:
|
||||||
self.logger.error(f"Failed to make photo upload directory at {self.game_cfg.uploads.photos_dir}")
|
self.logger.error(
|
||||||
|
f"Failed to make photo upload directory at {self.game_cfg.uploads.photos_dir}"
|
||||||
|
)
|
||||||
|
|
||||||
if self.game_cfg.uploads.movies and self.game_cfg.uploads.movies_dir and not path.exists(self.game_cfg.uploads.movies_dir):
|
if (
|
||||||
|
self.game_cfg.uploads.movies
|
||||||
|
and self.game_cfg.uploads.movies_dir
|
||||||
|
and not path.exists(self.game_cfg.uploads.movies_dir)
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
mkdir(self.game_cfg.uploads.movies_dir)
|
mkdir(self.game_cfg.uploads.movies_dir)
|
||||||
except Exception:
|
except Exception:
|
||||||
self.logger.error(f"Failed to make movie upload directory at {self.game_cfg.uploads.movies_dir}")
|
self.logger.error(
|
||||||
|
f"Failed to make movie upload directory at {self.game_cfg.uploads.movies_dir}"
|
||||||
|
)
|
||||||
|
|
||||||
def render_POST(self, request: Request, version: int, url_path: str) -> bytes:
|
def render_POST(self, request: Request, version: int, url_path: str) -> bytes:
|
||||||
if url_path.lower() == "ping":
|
if url_path.lower() == "ping":
|
||||||
return zlib.compress(b'{"returnCode": "1"}')
|
return zlib.compress(b'{"returnCode": "1"}')
|
||||||
|
|
||||||
elif url_path.startswith("api/movie/"):
|
elif url_path.startswith("api/movie/"):
|
||||||
self.logger.info(f"Movie data: {url_path} - {request.content.getvalue()}")
|
self.logger.info(f"Movie data: {url_path} - {request.content.getvalue()}")
|
||||||
return b""
|
return b""
|
||||||
@ -140,18 +154,20 @@ class Mai2Servlet:
|
|||||||
if request.uri.startswith(b"/SDEZ"):
|
if request.uri.startswith(b"/SDEZ"):
|
||||||
if version < 105: # 1.0
|
if version < 105: # 1.0
|
||||||
internal_ver = Mai2Constants.VER_MAIMAI_DX
|
internal_ver = Mai2Constants.VER_MAIMAI_DX
|
||||||
elif version >= 105 and version < 110: # Plus
|
elif version >= 105 and version < 110: # PLUS
|
||||||
internal_ver = Mai2Constants.VER_MAIMAI_DX_PLUS
|
internal_ver = Mai2Constants.VER_MAIMAI_DX_PLUS
|
||||||
elif version >= 110 and version < 115: # Splash
|
elif version >= 110 and version < 115: # Splash
|
||||||
internal_ver = Mai2Constants.VER_MAIMAI_DX_SPLASH
|
internal_ver = Mai2Constants.VER_MAIMAI_DX_SPLASH
|
||||||
elif version >= 115 and version < 120: # Splash Plus
|
elif version >= 115 and version < 120: # Splash PLUS
|
||||||
internal_ver = Mai2Constants.VER_MAIMAI_DX_SPLASH_PLUS
|
internal_ver = Mai2Constants.VER_MAIMAI_DX_SPLASH_PLUS
|
||||||
elif version >= 120 and version < 125: # Universe
|
elif version >= 120 and version < 125: # UNiVERSE
|
||||||
internal_ver = Mai2Constants.VER_MAIMAI_DX_UNIVERSE
|
internal_ver = Mai2Constants.VER_MAIMAI_DX_UNIVERSE
|
||||||
elif version >= 125 and version < 130: # Universe Plus
|
elif version >= 125 and version < 130: # UNiVERSE PLUS
|
||||||
internal_ver = Mai2Constants.VER_MAIMAI_DX_UNIVERSE_PLUS
|
internal_ver = Mai2Constants.VER_MAIMAI_DX_UNIVERSE_PLUS
|
||||||
elif version >= 130: # Festival
|
elif version >= 130 and version < 135: # FESTiVAL
|
||||||
internal_ver = Mai2Constants.VER_MAIMAI_DX_FESTIVAL
|
internal_ver = Mai2Constants.VER_MAIMAI_DX_FESTIVAL
|
||||||
|
elif version >= 135: # FESTiVAL PLUS
|
||||||
|
internal_ver = Mai2Constants.VER_MAIMAI_DX_FESTIVAL_PLUS
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if version < 110: # 1.0
|
if version < 110: # 1.0
|
||||||
@ -180,15 +196,20 @@ class Mai2Servlet:
|
|||||||
internal_ver = Mai2Constants.VER_MAIMAI_MILK_PLUS
|
internal_ver = Mai2Constants.VER_MAIMAI_MILK_PLUS
|
||||||
elif version >= 197: # Finale
|
elif version >= 197: # Finale
|
||||||
internal_ver = Mai2Constants.VER_MAIMAI_FINALE
|
internal_ver = Mai2Constants.VER_MAIMAI_FINALE
|
||||||
|
|
||||||
if request.getHeader('Mai-Encoding') is not None or request.getHeader('X-Mai-Encoding') is not None:
|
if (
|
||||||
|
request.getHeader("Mai-Encoding") is not None
|
||||||
|
or request.getHeader("X-Mai-Encoding") is not None
|
||||||
|
):
|
||||||
# The has is some flavor of MD5 of the endpoint with a constant bolted onto the end of it.
|
# The has is some flavor of MD5 of the endpoint with a constant bolted onto the end of it.
|
||||||
# See cake.dll's Obfuscator function for details. Hopefully most DLL edits will remove
|
# See cake.dll's Obfuscator function for details. Hopefully most DLL edits will remove
|
||||||
# these two(?) headers to not cause issues, but given the general quality of SEGA data...
|
# these two(?) headers to not cause issues, but given the general quality of SEGA data...
|
||||||
enc_ver = request.getHeader('Mai-Encoding')
|
enc_ver = request.getHeader("Mai-Encoding")
|
||||||
if enc_ver is None:
|
if enc_ver is None:
|
||||||
enc_ver = request.getHeader('X-Mai-Encoding')
|
enc_ver = request.getHeader("X-Mai-Encoding")
|
||||||
self.logger.debug(f"Encryption v{enc_ver} - User-Agent: {request.getHeader('User-Agent')}")
|
self.logger.debug(
|
||||||
|
f"Encryption v{enc_ver} - User-Agent: {request.getHeader('User-Agent')}"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
unzip = zlib.decompress(req_raw)
|
unzip = zlib.decompress(req_raw)
|
||||||
@ -231,10 +252,12 @@ class Mai2Servlet:
|
|||||||
self.logger.debug(f"v{version} GET {url_path}")
|
self.logger.debug(f"v{version} GET {url_path}")
|
||||||
url_split = url_path.split("/")
|
url_split = url_path.split("/")
|
||||||
|
|
||||||
if (url_split[0] == "api" and url_split[1] == "movie") or url_split[0] == "movie":
|
if (url_split[0] == "api" and url_split[1] == "movie") or url_split[
|
||||||
|
0
|
||||||
|
] == "movie":
|
||||||
if url_split[2] == "moviestart":
|
if url_split[2] == "moviestart":
|
||||||
return json.dumps({"moviestart":{"status":"OK"}}).encode()
|
return json.dumps({"moviestart": {"status": "OK"}}).encode()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
request.setResponseCode(404)
|
request.setResponseCode(404)
|
||||||
return b""
|
return b""
|
||||||
@ -251,20 +274,24 @@ class Mai2Servlet:
|
|||||||
elif url_split[1].startswith("friend"):
|
elif url_split[1].startswith("friend"):
|
||||||
self.logger.info(f"v{version} old server friend inquire")
|
self.logger.info(f"v{version} old server friend inquire")
|
||||||
return zlib.compress(b"{}")
|
return zlib.compress(b"{}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
request.setResponseCode(404)
|
request.setResponseCode(404)
|
||||||
return b""
|
return b""
|
||||||
|
|
||||||
elif url_split[0] == "usbdl":
|
elif url_split[0] == "usbdl":
|
||||||
if url_split[1] == "CONNECTIONTEST":
|
if url_split[1] == "CONNECTIONTEST":
|
||||||
self.logger.info(f"v{version} usbdl server test")
|
self.logger.info(f"v{version} usbdl server test")
|
||||||
return b""
|
return b""
|
||||||
|
|
||||||
elif self.game_cfg.deliver.udbdl_enable and path.exists(f"{self.game_cfg.deliver.content_folder}/usb/{url_split[-1]}"):
|
elif self.game_cfg.deliver.udbdl_enable and path.exists(
|
||||||
with open(f"{self.game_cfg.deliver.content_folder}/usb/{url_split[-1]}", 'rb') as f:
|
f"{self.game_cfg.deliver.content_folder}/usb/{url_split[-1]}"
|
||||||
|
):
|
||||||
|
with open(
|
||||||
|
f"{self.game_cfg.deliver.content_folder}/usb/{url_split[-1]}", "rb"
|
||||||
|
) as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
request.setResponseCode(404)
|
request.setResponseCode(404)
|
||||||
return b""
|
return b""
|
||||||
@ -272,12 +299,18 @@ class Mai2Servlet:
|
|||||||
elif url_split[0] == "deliver":
|
elif url_split[0] == "deliver":
|
||||||
file = url_split[len(url_split) - 1]
|
file = url_split[len(url_split) - 1]
|
||||||
self.logger.info(f"v{version} {file} deliver inquire")
|
self.logger.info(f"v{version} {file} deliver inquire")
|
||||||
self.logger.debug(f"{self.game_cfg.deliver.content_folder}/net_deliver/{file}")
|
self.logger.debug(
|
||||||
|
f"{self.game_cfg.deliver.content_folder}/net_deliver/{file}"
|
||||||
if self.game_cfg.deliver.enable and path.exists(f"{self.game_cfg.deliver.content_folder}/net_deliver/{file}"):
|
)
|
||||||
with open(f"{self.game_cfg.deliver.content_folder}/net_deliver/{file}", 'rb') as f:
|
|
||||||
|
if self.game_cfg.deliver.enable and path.exists(
|
||||||
|
f"{self.game_cfg.deliver.content_folder}/net_deliver/{file}"
|
||||||
|
):
|
||||||
|
with open(
|
||||||
|
f"{self.game_cfg.deliver.content_folder}/net_deliver/{file}", "rb"
|
||||||
|
) as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
request.setResponseCode(404)
|
request.setResponseCode(404)
|
||||||
return b""
|
return b""
|
||||||
|
@ -333,7 +333,7 @@ class Mai2ItemData(BaseData):
|
|||||||
if result is None:
|
if result is None:
|
||||||
return None
|
return None
|
||||||
return result.fetchone()
|
return result.fetchone()
|
||||||
|
|
||||||
def put_character_(self, user_id: int, char_data: Dict) -> Optional[int]:
|
def put_character_(self, user_id: int, char_data: Dict) -> Optional[int]:
|
||||||
char_data["user"] = user_id
|
char_data["user"] = user_id
|
||||||
sql = insert(character).values(**char_data)
|
sql = insert(character).values(**char_data)
|
||||||
@ -489,6 +489,8 @@ class Mai2ItemData(BaseData):
|
|||||||
else:
|
else:
|
||||||
sql = card.select(and_(card.c.user == user_id, card.c.cardKind == kind))
|
sql = card.select(and_(card.c.user == user_id, card.c.cardKind == kind))
|
||||||
|
|
||||||
|
sql = sql.order_by(card.c.startDate.desc())
|
||||||
|
|
||||||
result = self.execute(sql)
|
result = self.execute(sql)
|
||||||
if result is None:
|
if result is None:
|
||||||
return None
|
return None
|
||||||
|
@ -40,6 +40,7 @@ detail = Table(
|
|||||||
Column("charaLockSlot", JSON),
|
Column("charaLockSlot", JSON),
|
||||||
Column("contentBit", BigInteger),
|
Column("contentBit", BigInteger),
|
||||||
Column("playCount", Integer),
|
Column("playCount", Integer),
|
||||||
|
Column("mapStock", Integer), # new with fes+
|
||||||
Column("eventWatchedDate", String(25)),
|
Column("eventWatchedDate", String(25)),
|
||||||
Column("lastGameId", String(25)),
|
Column("lastGameId", String(25)),
|
||||||
Column("lastRomVersion", String(25)),
|
Column("lastRomVersion", String(25)),
|
||||||
@ -100,7 +101,7 @@ detail = Table(
|
|||||||
)
|
)
|
||||||
|
|
||||||
detail_old = Table(
|
detail_old = Table(
|
||||||
"maimai_profile_detail",
|
"maimai_profile_detail",
|
||||||
metadata,
|
metadata,
|
||||||
Column("id", Integer, primary_key=True, nullable=False),
|
Column("id", Integer, primary_key=True, nullable=False),
|
||||||
Column(
|
Column(
|
||||||
@ -216,6 +217,7 @@ extend = Table(
|
|||||||
Column("isPhotoAgree", Boolean),
|
Column("isPhotoAgree", Boolean),
|
||||||
Column("isGotoCodeRead", Boolean),
|
Column("isGotoCodeRead", Boolean),
|
||||||
Column("selectResultDetails", Boolean),
|
Column("selectResultDetails", Boolean),
|
||||||
|
Column("selectResultScoreViewType", Integer), # new with fes+
|
||||||
Column("sortCategorySetting", Integer),
|
Column("sortCategorySetting", Integer),
|
||||||
Column("sortMusicSetting", Integer),
|
Column("sortMusicSetting", Integer),
|
||||||
Column("selectedCardList", JSON),
|
Column("selectedCardList", JSON),
|
||||||
@ -251,6 +253,7 @@ option = Table(
|
|||||||
Column("touchSize", Integer),
|
Column("touchSize", Integer),
|
||||||
Column("starRotate", Integer),
|
Column("starRotate", Integer),
|
||||||
Column("dispCenter", Integer),
|
Column("dispCenter", Integer),
|
||||||
|
Column("outFrameType", Integer), # new with fes+
|
||||||
Column("dispChain", Integer),
|
Column("dispChain", Integer),
|
||||||
Column("dispRate", Integer),
|
Column("dispRate", Integer),
|
||||||
Column("dispBar", Integer),
|
Column("dispBar", Integer),
|
||||||
@ -276,6 +279,8 @@ option = Table(
|
|||||||
Column("exVolume", Integer),
|
Column("exVolume", Integer),
|
||||||
Column("slideSe", Integer),
|
Column("slideSe", Integer),
|
||||||
Column("slideVolume", Integer),
|
Column("slideVolume", Integer),
|
||||||
|
Column("breakSlideVolume", Integer), # new with fes+
|
||||||
|
Column("touchVolume", Integer), # new with fes+
|
||||||
Column("touchHoldVolume", Integer),
|
Column("touchHoldVolume", Integer),
|
||||||
Column("damageSeVolume", Integer),
|
Column("damageSeVolume", Integer),
|
||||||
Column("headPhoneVolume", Integer),
|
Column("headPhoneVolume", Integer),
|
||||||
@ -438,7 +443,11 @@ boss = Table(
|
|||||||
"maimai_profile_boss",
|
"maimai_profile_boss",
|
||||||
metadata,
|
metadata,
|
||||||
Column("id", Integer, primary_key=True, nullable=False),
|
Column("id", Integer, primary_key=True, nullable=False),
|
||||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
Column(
|
||||||
|
"user",
|
||||||
|
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||||
|
nullable=False,
|
||||||
|
),
|
||||||
Column("pandoraFlagList0", Integer),
|
Column("pandoraFlagList0", Integer),
|
||||||
Column("pandoraFlagList1", Integer),
|
Column("pandoraFlagList1", Integer),
|
||||||
Column("pandoraFlagList2", Integer),
|
Column("pandoraFlagList2", Integer),
|
||||||
@ -455,23 +464,32 @@ recent_rating = Table(
|
|||||||
"maimai_profile_recent_rating",
|
"maimai_profile_recent_rating",
|
||||||
metadata,
|
metadata,
|
||||||
Column("id", Integer, primary_key=True, nullable=False),
|
Column("id", Integer, primary_key=True, nullable=False),
|
||||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
Column(
|
||||||
|
"user",
|
||||||
|
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||||
|
nullable=False,
|
||||||
|
),
|
||||||
Column("userRecentRatingList", JSON),
|
Column("userRecentRatingList", JSON),
|
||||||
UniqueConstraint("user", name="mai2_profile_recent_rating_uk"),
|
UniqueConstraint("user", name="mai2_profile_recent_rating_uk"),
|
||||||
mysql_charset="utf8mb4",
|
mysql_charset="utf8mb4",
|
||||||
)
|
)
|
||||||
|
|
||||||
consec_logins = Table(
|
consec_logins = Table(
|
||||||
"mai2_profile_consec_logins",
|
"mai2_profile_consec_logins",
|
||||||
metadata,
|
metadata,
|
||||||
Column("id", Integer, primary_key=True, nullable=False),
|
Column("id", Integer, primary_key=True, nullable=False),
|
||||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
|
Column(
|
||||||
|
"user",
|
||||||
|
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||||
|
nullable=False,
|
||||||
|
),
|
||||||
Column("version", Integer, nullable=False),
|
Column("version", Integer, nullable=False),
|
||||||
Column("logins", Integer),
|
Column("logins", Integer),
|
||||||
UniqueConstraint("user", "version", name="mai2_profile_consec_logins_uk"),
|
UniqueConstraint("user", "version", name="mai2_profile_consec_logins_uk"),
|
||||||
mysql_charset="utf8mb4",
|
mysql_charset="utf8mb4",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Mai2ProfileData(BaseData):
|
class Mai2ProfileData(BaseData):
|
||||||
def put_profile_detail(
|
def put_profile_detail(
|
||||||
self, user_id: int, version: int, detail_data: Dict, is_dx: bool = True
|
self, user_id: int, version: int, detail_data: Dict, is_dx: bool = True
|
||||||
@ -494,18 +512,22 @@ class Mai2ProfileData(BaseData):
|
|||||||
return None
|
return None
|
||||||
return result.lastrowid
|
return result.lastrowid
|
||||||
|
|
||||||
def get_profile_detail(self, user_id: int, version: int, is_dx: bool = True) -> Optional[Row]:
|
def get_profile_detail(
|
||||||
|
self, user_id: int, version: int, is_dx: bool = True
|
||||||
|
) -> Optional[Row]:
|
||||||
if is_dx:
|
if is_dx:
|
||||||
sql = (
|
sql = (
|
||||||
select(detail)
|
select(detail)
|
||||||
.where(and_(detail.c.user == user_id, detail.c.version <= version))
|
.where(and_(detail.c.user == user_id, detail.c.version <= version))
|
||||||
.order_by(detail.c.version.desc())
|
.order_by(detail.c.version.desc())
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
sql = (
|
sql = (
|
||||||
select(detail_old)
|
select(detail_old)
|
||||||
.where(and_(detail_old.c.user == user_id, detail_old.c.version <= version))
|
.where(
|
||||||
|
and_(detail_old.c.user == user_id, detail_old.c.version <= version)
|
||||||
|
)
|
||||||
.order_by(detail_old.c.version.desc())
|
.order_by(detail_old.c.version.desc())
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -582,11 +604,15 @@ class Mai2ProfileData(BaseData):
|
|||||||
|
|
||||||
result = self.execute(conflict)
|
result = self.execute(conflict)
|
||||||
if result is None:
|
if result is None:
|
||||||
self.logger.warning(f"put_profile_option: failed to update! {user_id} is_dx {is_dx}")
|
self.logger.warning(
|
||||||
|
f"put_profile_option: failed to update! {user_id} is_dx {is_dx}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
return result.lastrowid
|
return result.lastrowid
|
||||||
|
|
||||||
def get_profile_option(self, user_id: int, version: int, is_dx: bool = True) -> Optional[Row]:
|
def get_profile_option(
|
||||||
|
self, user_id: int, version: int, is_dx: bool = True
|
||||||
|
) -> Optional[Row]:
|
||||||
if is_dx:
|
if is_dx:
|
||||||
sql = (
|
sql = (
|
||||||
select(option)
|
select(option)
|
||||||
@ -596,7 +622,9 @@ class Mai2ProfileData(BaseData):
|
|||||||
else:
|
else:
|
||||||
sql = (
|
sql = (
|
||||||
select(option_old)
|
select(option_old)
|
||||||
.where(and_(option_old.c.user == user_id, option_old.c.version <= version))
|
.where(
|
||||||
|
and_(option_old.c.user == user_id, option_old.c.version <= version)
|
||||||
|
)
|
||||||
.order_by(option_old.c.version.desc())
|
.order_by(option_old.c.version.desc())
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -689,7 +717,9 @@ class Mai2ProfileData(BaseData):
|
|||||||
return None
|
return None
|
||||||
return result.fetchall()
|
return result.fetchall()
|
||||||
|
|
||||||
def put_web_option(self, user_id: int, version: int, web_opts: Dict) -> Optional[int]:
|
def put_web_option(
|
||||||
|
self, user_id: int, version: int, web_opts: Dict
|
||||||
|
) -> Optional[int]:
|
||||||
web_opts["user"] = user_id
|
web_opts["user"] = user_id
|
||||||
web_opts["version"] = version
|
web_opts["version"] = version
|
||||||
sql = insert(web_opt).values(**web_opts)
|
sql = insert(web_opt).values(**web_opts)
|
||||||
@ -698,14 +728,14 @@ class Mai2ProfileData(BaseData):
|
|||||||
|
|
||||||
result = self.execute(conflict)
|
result = self.execute(conflict)
|
||||||
if result is None:
|
if result is None:
|
||||||
self.logger.warning(
|
self.logger.warning(f"put_web_option: failed to update! user_id: {user_id}")
|
||||||
f"put_web_option: failed to update! user_id: {user_id}"
|
|
||||||
)
|
|
||||||
return None
|
return None
|
||||||
return result.lastrowid
|
return result.lastrowid
|
||||||
|
|
||||||
def get_web_option(self, user_id: int, version: int) -> Optional[Row]:
|
def get_web_option(self, user_id: int, version: int) -> Optional[Row]:
|
||||||
sql = web_opt.select(and_(web_opt.c.user == user_id, web_opt.c.version == version))
|
sql = web_opt.select(
|
||||||
|
and_(web_opt.c.user == user_id, web_opt.c.version == version)
|
||||||
|
)
|
||||||
|
|
||||||
result = self.execute(sql)
|
result = self.execute(sql)
|
||||||
if result is None:
|
if result is None:
|
||||||
@ -725,7 +755,7 @@ class Mai2ProfileData(BaseData):
|
|||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
return result.lastrowid
|
return result.lastrowid
|
||||||
|
|
||||||
def get_grade_status(self, user_id: int) -> Optional[Row]:
|
def get_grade_status(self, user_id: int) -> Optional[Row]:
|
||||||
sql = grade_status.select(grade_status.c.user == user_id)
|
sql = grade_status.select(grade_status.c.user == user_id)
|
||||||
|
|
||||||
@ -742,12 +772,10 @@ class Mai2ProfileData(BaseData):
|
|||||||
|
|
||||||
result = self.execute(conflict)
|
result = self.execute(conflict)
|
||||||
if result is None:
|
if result is None:
|
||||||
self.logger.warning(
|
self.logger.warning(f"put_boss_list: failed to update! user_id: {user_id}")
|
||||||
f"put_boss_list: failed to update! user_id: {user_id}"
|
|
||||||
)
|
|
||||||
return None
|
return None
|
||||||
return result.lastrowid
|
return result.lastrowid
|
||||||
|
|
||||||
def get_boss_list(self, user_id: int) -> Optional[Row]:
|
def get_boss_list(self, user_id: int) -> Optional[Row]:
|
||||||
sql = boss.select(boss.c.user == user_id)
|
sql = boss.select(boss.c.user == user_id)
|
||||||
|
|
||||||
@ -759,7 +787,7 @@ class Mai2ProfileData(BaseData):
|
|||||||
def put_recent_rating(self, user_id: int, rr: Dict) -> Optional[int]:
|
def put_recent_rating(self, user_id: int, rr: Dict) -> Optional[int]:
|
||||||
sql = insert(recent_rating).values(user=user_id, userRecentRatingList=rr)
|
sql = insert(recent_rating).values(user=user_id, userRecentRatingList=rr)
|
||||||
|
|
||||||
conflict = sql.on_duplicate_key_update({'userRecentRatingList': rr})
|
conflict = sql.on_duplicate_key_update({"userRecentRatingList": rr})
|
||||||
|
|
||||||
result = self.execute(conflict)
|
result = self.execute(conflict)
|
||||||
if result is None:
|
if result is None:
|
||||||
@ -768,7 +796,7 @@ class Mai2ProfileData(BaseData):
|
|||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
return result.lastrowid
|
return result.lastrowid
|
||||||
|
|
||||||
def get_recent_rating(self, user_id: int) -> Optional[Row]:
|
def get_recent_rating(self, user_id: int) -> Optional[Row]:
|
||||||
sql = recent_rating.select(recent_rating.c.user == user_id)
|
sql = recent_rating.select(recent_rating.c.user == user_id)
|
||||||
|
|
||||||
@ -776,27 +804,25 @@ class Mai2ProfileData(BaseData):
|
|||||||
if result is None:
|
if result is None:
|
||||||
return None
|
return None
|
||||||
return result.fetchone()
|
return result.fetchone()
|
||||||
|
|
||||||
def add_consec_login(self, user_id: int, version: int) -> None:
|
|
||||||
sql = insert(consec_logins).values(
|
|
||||||
user=user_id,
|
|
||||||
version=version,
|
|
||||||
logins=1
|
|
||||||
)
|
|
||||||
|
|
||||||
conflict = sql.on_duplicate_key_update(
|
def add_consec_login(self, user_id: int, version: int) -> None:
|
||||||
logins=consec_logins.c.logins + 1
|
sql = insert(consec_logins).values(user=user_id, version=version, logins=1)
|
||||||
)
|
|
||||||
|
conflict = sql.on_duplicate_key_update(logins=consec_logins.c.logins + 1)
|
||||||
|
|
||||||
result = self.execute(conflict)
|
result = self.execute(conflict)
|
||||||
if result is None:
|
if result is None:
|
||||||
self.logger.error(f"Failed to update consecutive login count for user {user_id} version {version}")
|
self.logger.error(
|
||||||
|
f"Failed to update consecutive login count for user {user_id} version {version}"
|
||||||
|
)
|
||||||
|
|
||||||
def get_consec_login(self, user_id: int, version: int) -> Optional[Row]:
|
def get_consec_login(self, user_id: int, version: int) -> Optional[Row]:
|
||||||
sql = select(consec_logins).where(and_(
|
sql = select(consec_logins).where(
|
||||||
consec_logins.c.user==user_id,
|
and_(
|
||||||
consec_logins.c.version==version,
|
consec_logins.c.user == user_id,
|
||||||
))
|
consec_logins.c.version == version,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
result = self.execute(sql)
|
result = self.execute(sql)
|
||||||
if result is None:
|
if result is None:
|
||||||
@ -804,12 +830,12 @@ class Mai2ProfileData(BaseData):
|
|||||||
return result.fetchone()
|
return result.fetchone()
|
||||||
|
|
||||||
def reset_consec_login(self, user_id: int, version: int) -> Optional[Row]:
|
def reset_consec_login(self, user_id: int, version: int) -> Optional[Row]:
|
||||||
sql = consec_logins.update(and_(
|
sql = consec_logins.update(
|
||||||
consec_logins.c.user==user_id,
|
and_(
|
||||||
consec_logins.c.version==version,
|
consec_logins.c.user == user_id,
|
||||||
)).values(
|
consec_logins.c.version == version,
|
||||||
logins=1
|
)
|
||||||
)
|
).values(logins=1)
|
||||||
|
|
||||||
result = self.execute(sql)
|
result = self.execute(sql)
|
||||||
if result is None:
|
if result is None:
|
||||||
|
@ -23,10 +23,11 @@ class Mai2Universe(Mai2SplashPlus):
|
|||||||
return {
|
return {
|
||||||
"userName": p["userName"],
|
"userName": p["userName"],
|
||||||
"rating": p["playerRating"],
|
"rating": p["playerRating"],
|
||||||
# hardcode lastDataVersion for CardMaker 1.34
|
# hardcode lastDataVersion for CardMaker
|
||||||
"lastDataVersion": "1.20.00",
|
"lastDataVersion": "1.20.00",
|
||||||
|
# checks if the user is still logged in
|
||||||
"isLogin": False,
|
"isLogin": False,
|
||||||
"isExistSellingCard": False,
|
"isExistSellingCard": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
def handle_cm_get_user_data_api_request(self, data: Dict) -> Dict:
|
def handle_cm_get_user_data_api_request(self, data: Dict) -> Dict:
|
||||||
@ -70,8 +71,12 @@ class Mai2Universe(Mai2SplashPlus):
|
|||||||
tmp.pop("cardName")
|
tmp.pop("cardName")
|
||||||
tmp.pop("enabled")
|
tmp.pop("enabled")
|
||||||
|
|
||||||
tmp["startDate"] = datetime.strftime(tmp["startDate"], Mai2Constants.DATE_TIME_FORMAT)
|
tmp["startDate"] = datetime.strftime(
|
||||||
tmp["endDate"] = datetime.strftime(tmp["endDate"], Mai2Constants.DATE_TIME_FORMAT)
|
tmp["startDate"], Mai2Constants.DATE_TIME_FORMAT
|
||||||
|
)
|
||||||
|
tmp["endDate"] = datetime.strftime(
|
||||||
|
tmp["endDate"], Mai2Constants.DATE_TIME_FORMAT
|
||||||
|
)
|
||||||
tmp["noticeStartDate"] = datetime.strftime(
|
tmp["noticeStartDate"] = datetime.strftime(
|
||||||
tmp["noticeStartDate"], Mai2Constants.DATE_TIME_FORMAT
|
tmp["noticeStartDate"], Mai2Constants.DATE_TIME_FORMAT
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user