mucha: add shop info
This commit is contained in:
parent
66c9548dd2
commit
9a021d4005
131
core/mucha.py
131
core/mucha.py
@ -2,6 +2,7 @@ from typing import Dict, Any, Optional
|
|||||||
import logging, coloredlogs
|
import logging, coloredlogs
|
||||||
from logging.handlers import TimedRotatingFileHandler
|
from logging.handlers import TimedRotatingFileHandler
|
||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
|
from starlette.responses import PlainTextResponse
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from Crypto.Cipher import Blowfish
|
from Crypto.Cipher import Blowfish
|
||||||
import pytz
|
import pytz
|
||||||
@ -9,9 +10,11 @@ import pytz
|
|||||||
from .config import CoreConfig
|
from .config import CoreConfig
|
||||||
from .utils import Utils
|
from .utils import Utils
|
||||||
from .title import TitleServlet
|
from .title import TitleServlet
|
||||||
|
from .data import Data
|
||||||
|
from .const import *
|
||||||
|
|
||||||
class MuchaServlet:
|
class MuchaServlet:
|
||||||
mucha_registry: Dict[str, str] = {}
|
mucha_registry: Dict[str, Dict[str, str]] = {}
|
||||||
def __init__(self, cfg: CoreConfig, cfg_dir: str) -> None:
|
def __init__(self, cfg: CoreConfig, cfg_dir: str) -> None:
|
||||||
self.config = cfg
|
self.config = cfg
|
||||||
self.config_dir = cfg_dir
|
self.config_dir = cfg_dir
|
||||||
@ -35,94 +38,150 @@ class MuchaServlet:
|
|||||||
|
|
||||||
self.logger.setLevel(cfg.mucha.loglevel)
|
self.logger.setLevel(cfg.mucha.loglevel)
|
||||||
coloredlogs.install(level=cfg.mucha.loglevel, logger=self.logger, fmt=log_fmt_str)
|
coloredlogs.install(level=cfg.mucha.loglevel, logger=self.logger, fmt=log_fmt_str)
|
||||||
|
|
||||||
|
self.data = Data(cfg)
|
||||||
|
|
||||||
for _, mod in TitleServlet.title_registry.items():
|
for _, mod in TitleServlet.title_registry.items():
|
||||||
if hasattr(mod, "get_mucha_info"):
|
enabled, game_cds, netids = mod.get_mucha_info(self.config, self.config_dir)
|
||||||
enabled, game_cds, netid_prefixes = mod.get_mucha_info(
|
print(game_cds)
|
||||||
self.config, self.config_dir
|
if enabled:
|
||||||
)
|
for x in range(len(game_cds)):
|
||||||
if enabled:
|
self.mucha_registry[game_cds[x]] = { "netid_prefix": netids[x] }
|
||||||
for x in range(len(game_cds)):
|
|
||||||
self.mucha_registry[game_cds[x]] = netid_prefixes[x]
|
|
||||||
|
|
||||||
self.logger.info(f"Serving {len(self.mucha_registry)} games")
|
self.logger.info(f"Serving {len(self.mucha_registry)} games")
|
||||||
|
|
||||||
async def handle_boardauth(self, request: Request) -> bytes:
|
async def handle_boardauth(self, request: Request) -> bytes:
|
||||||
req_raw = await request.body()
|
bod = await request.body()
|
||||||
req_dict = self.mucha_preprocess(req_raw)
|
req_dict = self.mucha_preprocess(bod)
|
||||||
client_ip = Utils.get_ip_addr(request)
|
client_ip = Utils.get_ip_addr(request)
|
||||||
|
|
||||||
if req_dict is None:
|
if req_dict is None:
|
||||||
self.logger.error(
|
self.logger.error(
|
||||||
f"Error processing mucha boardauth request {req_raw}"
|
f"Error processing mucha request {bod}"
|
||||||
)
|
)
|
||||||
return b""
|
return PlainTextResponse("RESULTS=000")
|
||||||
|
|
||||||
req = MuchaAuthRequest(req_dict)
|
req = MuchaAuthRequest(req_dict)
|
||||||
self.logger.info(f"Boardauth request from {client_ip} for {req.gameVer}")
|
|
||||||
self.logger.debug(f"Mucha request {vars(req)}")
|
self.logger.debug(f"Mucha request {vars(req)}")
|
||||||
|
|
||||||
|
if not req.gameCd or not req.gameVer or not req.sendDate or not req.countryCd or not req.serialNum:
|
||||||
|
self.logger.warn(f"Missing required fields - {vars(req)}")
|
||||||
|
return PlainTextResponse("RESULTS=000")
|
||||||
|
|
||||||
if req.gameCd not in self.mucha_registry:
|
minfo = self.mucha_registry.get(req.gameCd, {})
|
||||||
self.logger.warning(f"Unknown gameCd {req.gameCd}")
|
|
||||||
return b"RESULTS=000"
|
if not minfo:
|
||||||
|
self.logger.warning(f"Unknown gameCd {req.gameCd} from {client_ip}")
|
||||||
|
return PlainTextResponse("RESULTS=000")
|
||||||
|
|
||||||
# TODO: Decrypt S/N
|
|
||||||
b_key = b""
|
b_key = b""
|
||||||
for x in range(8):
|
for x in range(8):
|
||||||
b_key += req.sendDate[(x - 1) & 7].encode()
|
b_key += req.sendDate[(x - 1) & 7].encode()
|
||||||
|
|
||||||
|
b_iv = b_key # what the fuck namco
|
||||||
|
|
||||||
cipher = Blowfish.new(b_key, Blowfish.MODE_ECB)
|
cipher = Blowfish.new(b_key, Blowfish.MODE_CBC, b_iv)
|
||||||
sn_decrypt = cipher.decrypt(bytes.fromhex(req.serialNum))
|
try:
|
||||||
self.logger.debug(f"Decrypt SN to {sn_decrypt.hex()}")
|
sn_decrypt = cipher.decrypt(bytes.fromhex(req.serialNum))[:12].decode()
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"Decrypt SN {req.serialNum} failed! - {e}")
|
||||||
|
return PlainTextResponse("RESULTS=000")
|
||||||
|
|
||||||
|
self.logger.info(f"Boardauth request from {sn_decrypt} ({client_ip}) for {req.gameVer}")
|
||||||
|
|
||||||
resp = MuchaAuthResponse(
|
resp = MuchaAuthResponse(
|
||||||
f"{self.config.server.hostname}{':' + str(self.config.server.port) if self.config.server.is_develop else ''}"
|
f"{self.config.server.hostname}{':' + str(self.config.server.port) if not self.config.server.is_using_proxy else ''}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#netid = minfo.get('netid_prefix', "ABxN") + sn_decrypt[5:]
|
||||||
|
netid = minfo.get('netid_prefix', "ABxN") + "3190001"
|
||||||
|
|
||||||
|
cab = await self.data.arcade.get_machine(netid)
|
||||||
|
if cab:
|
||||||
|
arcade = await self.data.arcade.get_arcade(cab['id'])
|
||||||
|
if not arcade:
|
||||||
|
self.logger.error(f"Failed to get arcade with id {cab['id']}")
|
||||||
|
return PlainTextResponse("RESULTS=000")
|
||||||
|
|
||||||
|
resp.AREA_0 = arcade["region_id"] or AllnetJapanRegionId.AICHI.name
|
||||||
|
resp.AREA_0_EN = arcade["region_id"] or AllnetJapanRegionId.AICHI.name
|
||||||
|
resp.AREA_FULL_0 = arcade["region_id"] or AllnetJapanRegionId.AICHI.name
|
||||||
|
resp.AREA_FULL_0_EN = arcade["region_id"] or AllnetJapanRegionId.AICHI.name
|
||||||
|
|
||||||
|
resp.AREA_1 = arcade["country"] or cab['country'] or AllnetCountryCode.JAPAN.value
|
||||||
|
resp.AREA_1_EN = arcade["country"] or cab['country'] or AllnetCountryCode.JAPAN.value
|
||||||
|
resp.AREA_FULL_1 = arcade["country"] or cab['country'] or AllnetCountryCode.JAPAN.value
|
||||||
|
resp.AREA_FULL_1_EN = arcade["country"] or cab['country'] or AllnetCountryCode.JAPAN.value
|
||||||
|
|
||||||
|
resp.AREA_2 = arcade["city"] if arcade["city"] else ""
|
||||||
|
resp.AREA_2_EN = arcade["city"] if arcade["city"] else ""
|
||||||
|
resp.AREA_FULL_2 = arcade["city"] if arcade["city"] else ""
|
||||||
|
resp.AREA_FULL_2_EN = arcade["city"] if arcade["city"] else ""
|
||||||
|
|
||||||
|
resp.AREA_3 = ""
|
||||||
|
resp.AREA_3_EN = ""
|
||||||
|
resp.AREA_FULL_3 = ""
|
||||||
|
resp.AREA_FULL_3_EN = ""
|
||||||
|
|
||||||
|
resp.PREFECTURE_ID = arcade['region_id']
|
||||||
|
resp.COUNTRY_CD = arcade['country'] or cab['country'] or AllnetCountryCode.JAPAN.value
|
||||||
|
resp.PLACE_ID = req.placeId if req.placeId else f"{arcade['country'] or cab['country'] or AllnetCountryCode.JAPAN.value}{arcade['id']:04X}"
|
||||||
|
resp.SHOP_NAME = arcade['name']
|
||||||
|
resp.SHOP_NAME_EN = arcade['name']
|
||||||
|
resp.SHOP_NICKNAME = arcade['nickname']
|
||||||
|
resp.SHOP_NICKNAME_EN = arcade['nickname']
|
||||||
|
|
||||||
|
elif self.config.server.allow_unregistered_serials:
|
||||||
|
self.logger.info(f"Allow unknown serial {netid} ({sn_decrypt}) to auth")
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.logger.warn(f'Auth failed for NetID {netid}')
|
||||||
|
return PlainTextResponse("RESULTS=000")
|
||||||
|
|
||||||
self.logger.debug(f"Mucha response {vars(resp)}")
|
self.logger.debug(f"Mucha response {vars(resp)}")
|
||||||
|
|
||||||
return self.mucha_postprocess(vars(resp))
|
return PlainTextResponse(self.mucha_postprocess(vars(resp)))
|
||||||
|
|
||||||
async def handle_updatecheck(self, request: Request) -> bytes:
|
async def handle_updatecheck(self, request: Request) -> bytes:
|
||||||
req_raw = await request.body()
|
bod = await request.body()
|
||||||
req_dict = self.mucha_preprocess(req_raw)
|
req_dict = self.mucha_preprocess(bod)
|
||||||
client_ip = Utils.get_ip_addr(request)
|
client_ip = Utils.get_ip_addr(request)
|
||||||
|
|
||||||
if req_dict is None:
|
if req_dict is None:
|
||||||
self.logger.error(
|
self.logger.error(
|
||||||
f"Error processing mucha updatecheck request {req_raw}"
|
f"Error processing mucha request {bod}"
|
||||||
)
|
)
|
||||||
return b""
|
return PlainTextResponse("RESULTS=000")
|
||||||
|
|
||||||
req = MuchaUpdateRequest(req_dict)
|
req = MuchaUpdateRequest(req_dict)
|
||||||
self.logger.info(f"Updatecheck request from {client_ip} for {req.gameVer}")
|
self.logger.info(f"Updatecheck request from {req.serialNum} ({client_ip}) for {req.gameVer}")
|
||||||
self.logger.debug(f"Mucha request {vars(req)}")
|
self.logger.debug(f"Mucha request {vars(req)}")
|
||||||
|
|
||||||
if req.gameCd not in self.mucha_registry:
|
if req.gameCd not in self.mucha_registry:
|
||||||
self.logger.warning(f"Unknown gameCd {req.gameCd}")
|
self.logger.warning(f"Unknown gameCd {req.gameCd}")
|
||||||
return b"RESULTS=000"
|
return PlainTextResponse("RESULTS=000")
|
||||||
|
|
||||||
resp = MuchaUpdateResponse(req.gameVer, f"{self.config.server.hostname}{':' + str(self.config.server.port) if self.config.server.is_develop else ''}")
|
resp = MuchaUpdateResponse(req.gameVer, f"{self.config.server.hostname}{':' + str(self.config.server.port) if not self.config.server.is_using_proxy else ''}")
|
||||||
|
|
||||||
self.logger.debug(f"Mucha response {vars(resp)}")
|
self.logger.debug(f"Mucha response {vars(resp)}")
|
||||||
|
|
||||||
return self.mucha_postprocess(vars(resp))
|
return PlainTextResponse(self.mucha_postprocess(vars(resp)))
|
||||||
|
|
||||||
async def handle_dlstate(self, request: Request) -> bytes:
|
async def handle_dlstate(self, request: Request) -> bytes:
|
||||||
req_raw = await request.body()
|
bod = await request.body()
|
||||||
req_dict = self.mucha_preprocess(req_raw)
|
req_dict = self.mucha_preprocess(bod)
|
||||||
client_ip = Utils.get_ip_addr(request)
|
client_ip = Utils.get_ip_addr(request)
|
||||||
|
|
||||||
if req_dict is None:
|
if req_dict is None:
|
||||||
self.logger.error(
|
self.logger.error(
|
||||||
f"Error processing mucha dlstate request {req_raw}"
|
f"Error processing mucha request {bod}"
|
||||||
)
|
)
|
||||||
return b""
|
return PlainTextResponse("RESULTS=000")
|
||||||
|
|
||||||
req = MuchaDownloadStateRequest(req_dict)
|
req = MuchaDownloadStateRequest(req_dict)
|
||||||
self.logger.info(f"DownloadState request from {client_ip} for {req.gameCd} -> {req.updateVer}")
|
self.logger.info(f"DownloadState request from {req.serialNum} ({client_ip}) for {req.gameCd} -> {req.updateVer}")
|
||||||
self.logger.debug(f"request {vars(req)}")
|
self.logger.debug(f"request {vars(req)}")
|
||||||
return b"RESULTS=001"
|
return PlainTextResponse("RESULTS=001")
|
||||||
|
|
||||||
def mucha_preprocess(self, data: bytes) -> Optional[Dict]:
|
def mucha_preprocess(self, data: bytes) -> Optional[Dict]:
|
||||||
try:
|
try:
|
||||||
|
Loading…
Reference in New Issue
Block a user