forked from Hay1tsme/artemis
chuni: fix encrypted hash, update unlock challenge req
This commit is contained in:
@ -1,20 +1,22 @@
|
||||
from starlette.requests import Request
|
||||
from starlette.routing import Route
|
||||
from starlette.responses import Response
|
||||
import asyncio
|
||||
import re
|
||||
import logging
|
||||
import coloredlogs
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
import zlib
|
||||
import yaml
|
||||
import json
|
||||
import inflection
|
||||
import string
|
||||
from os import path
|
||||
from typing import Tuple, Dict, List
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
from starlette.requests import Request
|
||||
from starlette.routing import Route
|
||||
from starlette.responses import Response
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import pad
|
||||
from Crypto.Protocol.KDF import PBKDF2
|
||||
from Crypto.Hash import SHA1
|
||||
from os import path
|
||||
from typing import Tuple, Dict, List
|
||||
|
||||
from core import CoreConfig, Utils
|
||||
from core.title import BaseServlet
|
||||
@ -39,6 +41,7 @@ from .luminous import ChuniLuminous
|
||||
from .luminousplus import ChuniLuminousPlus
|
||||
from .verse import ChuniVerse
|
||||
|
||||
|
||||
class ChuniServlet(BaseServlet):
|
||||
def __init__(self, core_cfg: CoreConfig, cfg_dir: str) -> None:
|
||||
super().__init__(core_cfg, cfg_dir)
|
||||
@ -156,10 +159,7 @@ class ChuniServlet(BaseServlet):
|
||||
and version_idx >= ChuniConstants.VER_CHUNITHM_NEW
|
||||
):
|
||||
method_fixed += "C3Exp"
|
||||
elif (
|
||||
isinstance(version, str)
|
||||
and version.endswith("_chn")
|
||||
):
|
||||
elif isinstance(version, str) and version.endswith("_chn"):
|
||||
method_fixed += "Chn"
|
||||
|
||||
hash = PBKDF2(
|
||||
@ -170,7 +170,8 @@ class ChuniServlet(BaseServlet):
|
||||
hmac_hash_module=SHA1,
|
||||
)
|
||||
|
||||
hashed_name = hash.hex()[:32] # truncate unused bytes like the game does
|
||||
# truncate unused bytes like the game does
|
||||
hashed_name = hash.hex()[:32]
|
||||
self.hash_table[version][hashed_name] = method_fixed
|
||||
|
||||
self.logger.debug(
|
||||
@ -192,7 +193,9 @@ class ChuniServlet(BaseServlet):
|
||||
|
||||
return True
|
||||
|
||||
def get_allnet_info(self, game_code: str, game_ver: int, keychip: str) -> Tuple[str, str]:
|
||||
def get_allnet_info(
|
||||
self, game_code: str, game_ver: int, keychip: str
|
||||
) -> Tuple[str, str]:
|
||||
title_port_int = Utils.get_title_port(self.core_cfg)
|
||||
title_port_ssl_int = Utils.get_title_port_ssl(self.core_cfg)
|
||||
|
||||
@ -216,8 +219,16 @@ class ChuniServlet(BaseServlet):
|
||||
|
||||
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']),
|
||||
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:
|
||||
@ -274,7 +285,9 @@ class ChuniServlet(BaseServlet):
|
||||
elif game_code == "SDGS": # Int
|
||||
if version < 105: # SUPERSTAR
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_CRYSTAL_PLUS
|
||||
elif version >= 105 and version < 110: # SUPERSTAR PLUS *Cursed but needed due to different encryption key
|
||||
elif (
|
||||
version >= 105 and version < 110
|
||||
): # SUPERSTAR PLUS *Cursed but needed due to different encryption key
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_PARADISE
|
||||
elif version >= 110 and version < 115: # NEW
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_NEW
|
||||
@ -291,7 +304,9 @@ class ChuniServlet(BaseServlet):
|
||||
elif game_code == "SDHJ": # Chn
|
||||
if version < 110: # NEW
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_NEW
|
||||
elif version >= 110 and version < 120: # NEW *Cursed but needed due to different encryption key
|
||||
elif (
|
||||
version >= 110 and version < 120
|
||||
): # NEW *Cursed but needed due to different encryption key
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_NEW_PLUS
|
||||
elif version >= 120: # LUMINOUS
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM_LUMINOUS
|
||||
@ -381,7 +396,7 @@ class ChuniServlet(BaseServlet):
|
||||
else:
|
||||
endpoint = endpoint
|
||||
|
||||
func_to_find = "handle_" + inflection.underscore(endpoint) + "_request"
|
||||
func_to_find = "handle_" + self.strict_underscore(endpoint) + "_request"
|
||||
handler_cls = self.versions[internal_ver](self.core_cfg, self.game_cfg)
|
||||
|
||||
if not hasattr(handler_cls, func_to_find):
|
||||
@ -419,3 +434,9 @@ class ChuniServlet(BaseServlet):
|
||||
)
|
||||
|
||||
return Response(crypt.encrypt(padded))
|
||||
|
||||
def strict_underscore(self, name: str) -> str:
|
||||
# Insert underscores between *all* capital letters
|
||||
name = re.sub(r"([A-Z])([A-Z])", r"\1_\2", name)
|
||||
return inflection.underscore(name)
|
||||
|
||||
|
@ -61,7 +61,7 @@ class ChuniVerse(ChuniLuminousPlus):
|
||||
"gameCourseLevelList": game_course_level_list,
|
||||
}
|
||||
|
||||
async def handle_get_game_uc_condition_api_request(self, data: Dict) -> Dict:
|
||||
async def handle_get_game_u_c_condition_api_request(self, data: Dict) -> Dict:
|
||||
unlock_challenges = await self.data.static.get_unlock_challenges(self.version)
|
||||
game_unlock_challenge_condition_list = []
|
||||
|
||||
@ -84,8 +84,8 @@ class ChuniVerse(ChuniLuminousPlus):
|
||||
unlock_condition = conditions.get(
|
||||
unlock_challenge_id,
|
||||
{
|
||||
"type": 3, # always unlocked
|
||||
"conditionId": 0,
|
||||
"type": MapAreaConditionType.ALWAYS_UNLOCKED.value, # always unlocked
|
||||
"conditionId": -1,
|
||||
},
|
||||
)
|
||||
|
||||
@ -114,7 +114,7 @@ class ChuniVerse(ChuniLuminousPlus):
|
||||
"gameUnlockChallengeConditionList": game_unlock_challenge_condition_list,
|
||||
}
|
||||
|
||||
async def handle_get_user_uc_api_request(self, data: Dict) -> Dict:
|
||||
async def handle_get_user_u_c_api_request(self, data: Dict) -> Dict:
|
||||
user_id = data["userId"]
|
||||
|
||||
user_unlock_challenges = await self.data.item.get_unlock_challenges(
|
||||
@ -167,7 +167,9 @@ class ChuniVerse(ChuniLuminousPlus):
|
||||
|
||||
# try adding recommendations in order of: title → artist → genre
|
||||
for field in ("title", "artist", "genre"):
|
||||
await self._add_recommendations(field, user_rec_music_set, music_info_list, rec_limit)
|
||||
await self._add_recommendations(
|
||||
field, user_rec_music_set, music_info_list, rec_limit
|
||||
)
|
||||
if len(user_rec_music_set) >= rec_limit:
|
||||
break
|
||||
|
||||
@ -220,9 +222,7 @@ class ChuniVerse(ChuniLuminousPlus):
|
||||
excluding music IDs already in the user's recent ratings and recommendations.
|
||||
"""
|
||||
# Collect all existing songId to exclude from recommendations
|
||||
existing_music_ids = {
|
||||
info["songId"] for info in music_info_list
|
||||
}
|
||||
existing_music_ids = {info["songId"] for info in music_info_list}
|
||||
|
||||
for music_info in music_info_list:
|
||||
if len(user_rec_music_set) >= limit:
|
||||
|
Reference in New Issue
Block a user