3
2
forked from Dniel97/artemis
artemis/core/mucha.py

230 lines
7.5 KiB
Python
Raw Normal View History

2023-03-05 03:46:26 +00:00
from typing import Dict, Any, Optional, List
import logging, coloredlogs
from logging.handlers import TimedRotatingFileHandler
from twisted.web import resource
from twisted.web.http import Request
from datetime import datetime
import pytz
from core import CoreConfig
2023-03-05 03:46:26 +00:00
from core.utils import Utils
2023-03-09 16:38:58 +00:00
class MuchaServlet:
2023-03-09 16:38:58 +00:00
def __init__(self, cfg: CoreConfig, cfg_dir: str) -> None:
self.config = cfg
2023-03-05 03:46:26 +00:00
self.config_dir = cfg_dir
self.mucha_registry: List[str] = []
2023-03-09 16:38:58 +00:00
self.logger = logging.getLogger("mucha")
log_fmt_str = "[%(asctime)s] Mucha | %(levelname)s | %(message)s"
log_fmt = logging.Formatter(log_fmt_str)
2023-03-09 16:38:58 +00:00
fileHandler = TimedRotatingFileHandler(
"{0}/{1}.log".format(self.config.server.log_dir, "mucha"),
when="d",
backupCount=10,
)
fileHandler.setFormatter(log_fmt)
2023-03-09 16:38:58 +00:00
consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(log_fmt)
self.logger.addHandler(fileHandler)
self.logger.addHandler(consoleHandler)
2023-03-09 16:38:58 +00:00
self.logger.setLevel(logging.INFO)
coloredlogs.install(level=logging.INFO, logger=self.logger, fmt=log_fmt_str)
2023-03-05 03:46:26 +00:00
all_titles = Utils.get_all_titles()
for _, mod in all_titles.items():
if hasattr(mod, "index") and hasattr(mod.index, "get_mucha_info"):
2023-03-09 16:38:58 +00:00
enabled, game_cd = mod.index.get_mucha_info(
self.config, self.config_dir
)
2023-03-05 03:46:26 +00:00
if enabled:
self.mucha_registry.append(game_cd)
2023-03-09 16:38:58 +00:00
self.logger.info(
f"Serving {len(self.mucha_registry)} games on port {self.config.mucha.port}"
)
2023-03-05 03:46:26 +00:00
2023-02-19 04:12:40 +00:00
def handle_boardauth(self, request: Request, _: Dict) -> bytes:
req_dict = self.mucha_preprocess(request.content.getvalue())
client_ip = Utils.get_ip_addr(request)
if req_dict is None:
2023-03-09 16:38:58 +00:00
self.logger.error(
f"Error processing mucha request {request.content.getvalue()}"
)
return b""
req = MuchaAuthRequest(req_dict)
2023-02-21 21:46:43 +00:00
self.logger.debug(f"Mucha request {vars(req)}")
2023-03-09 16:38:58 +00:00
self.logger.info(
f"Boardauth request from {client_ip} for {req.gameVer}"
2023-03-09 16:38:58 +00:00
)
2023-03-05 03:46:26 +00:00
if req.gameCd not in self.mucha_registry:
self.logger.warn(f"Unknown gameCd {req.gameCd}")
return b""
2023-03-05 16:42:03 +00:00
# TODO: Decrypt S/N
2023-03-09 16:38:58 +00:00
resp = MuchaAuthResponse(
f"{self.config.mucha.hostname}{':' + str(self.config.mucha.port) if self.config.server.is_develop else ''}"
2023-03-09 16:38:58 +00:00
)
2023-02-21 21:46:43 +00:00
self.logger.debug(f"Mucha response {vars(resp)}")
return self.mucha_postprocess(vars(resp))
2023-03-09 16:38:58 +00:00
2023-02-19 04:12:40 +00:00
def handle_updatecheck(self, request: Request, _: Dict) -> bytes:
req_dict = self.mucha_preprocess(request.content.getvalue())
client_ip = Utils.get_ip_addr(request)
if req_dict is None:
2023-03-09 16:38:58 +00:00
self.logger.error(
f"Error processing mucha request {request.content.getvalue()}"
)
return b""
req = MuchaUpdateRequest(req_dict)
2023-02-21 21:46:43 +00:00
self.logger.debug(f"Mucha request {vars(req)}")
2023-03-09 16:38:58 +00:00
self.logger.info(
f"Updatecheck request from {client_ip} for {req.gameVer}"
2023-03-09 16:38:58 +00:00
)
2023-03-05 03:46:26 +00:00
if req.gameCd not in self.mucha_registry:
self.logger.warn(f"Unknown gameCd {req.gameCd}")
return b""
2023-02-21 21:46:43 +00:00
2023-03-05 14:43:05 +00:00
resp = MuchaUpdateResponseStub(req.gameVer)
2023-02-21 21:46:43 +00:00
self.logger.debug(f"Mucha response {vars(resp)}")
return self.mucha_postprocess(vars(resp))
def mucha_preprocess(self, data: bytes) -> Optional[Dict]:
try:
ret: Dict[str, Any] = {}
2023-03-09 16:38:58 +00:00
for x in data.decode().split("&"):
kvp = x.split("=")
if len(kvp) == 2:
ret[kvp[0]] = kvp[1]
return ret
2023-03-09 16:38:58 +00:00
except:
self.logger.error(f"Error processing mucha request {data}")
return None
def mucha_postprocess(self, data: dict) -> Optional[bytes]:
try:
urlencode = ""
2023-03-09 16:38:58 +00:00
for k, v in data.items():
urlencode += f"{k}={v}&"
return urlencode.encode()
except:
self.logger.error("Error processing mucha response")
return None
2023-03-09 16:38:58 +00:00
class MuchaAuthRequest:
def __init__(self, request: Dict) -> None:
2023-03-09 17:17:10 +00:00
# gameCd + boardType + countryCd + version
self.gameVer = request.get("gameVer", "")
self.sendDate = request.get("sendDate", "") # %Y%m%d
self.serialNum = request.get("serialNum", "")
self.gameCd = request.get("gameCd", "")
self.boardType = request.get("boardType", "")
self.boardId = request.get("boardId", "")
self.mac = request.get("mac", "")
self.placeId = request.get("placeId", "")
self.storeRouterIp = request.get("storeRouterIp", "")
self.countryCd = request.get("countryCd", "")
self.useToken = request.get("useToken", "")
self.allToken = request.get("allToken", "")
2023-03-09 16:38:58 +00:00
class MuchaAuthResponse:
def __init__(self, mucha_url: str) -> None:
2023-03-09 16:38:58 +00:00
self.RESULTS = "001"
self.AUTH_INTERVAL = "86400"
self.SERVER_TIME = datetime.strftime(datetime.now(), "%Y%m%d%H%M")
self.UTC_SERVER_TIME = datetime.strftime(datetime.now(pytz.UTC), "%Y%m%d%H%M")
2023-03-09 16:38:58 +00:00
self.CHARGE_URL = f"https://{mucha_url}/charge/"
self.FILE_URL = f"https://{mucha_url}/file/"
self.URL_1 = f"https://{mucha_url}/url1/"
self.URL_2 = f"https://{mucha_url}/url2/"
self.URL_3 = f"https://{mucha_url}/url3/"
2023-03-09 16:38:58 +00:00
self.PLACE_ID = "JPN123"
self.COUNTRY_CD = "JPN"
self.SHOP_NAME = "TestShop!"
self.SHOP_NICKNAME = "TestShop"
self.AREA_0 = "008"
self.AREA_1 = "009"
self.AREA_2 = "010"
self.AREA_3 = "011"
self.AREA_FULL_0 = ""
self.AREA_FULL_1 = ""
self.AREA_FULL_2 = ""
self.AREA_FULL_3 = ""
2023-03-09 16:38:58 +00:00
self.SHOP_NAME_EN = "TestShop!"
self.SHOP_NICKNAME_EN = "TestShop"
self.AREA_0_EN = "008"
self.AREA_1_EN = "009"
self.AREA_2_EN = "010"
self.AREA_3_EN = "011"
self.AREA_FULL_0_EN = ""
self.AREA_FULL_1_EN = ""
self.AREA_FULL_2_EN = ""
self.AREA_FULL_3_EN = ""
2023-03-09 16:38:58 +00:00
self.PREFECTURE_ID = "1"
self.EXPIRATION_DATE = "null"
self.USE_TOKEN = "0"
self.CONSUME_TOKEN = "0"
self.DONGLE_FLG = "1"
self.FORCE_BOOT = "0"
2023-03-09 16:38:58 +00:00
class MuchaUpdateRequest:
def __init__(self, request: Dict) -> None:
2023-03-09 17:17:10 +00:00
self.gameVer = request.get("gameVer", "")
self.gameCd = request.get("gameCd", "")
self.serialNum = request.get("serialNum", "")
self.countryCd = request.get("countryCd", "")
self.placeId = request.get("placeId", "")
self.storeRouterIp = request.get("storeRouterIp", "")
2023-03-09 16:38:58 +00:00
class MuchaUpdateResponse:
def __init__(self, game_ver: str, mucha_url: str) -> None:
self.RESULTS = "001"
self.UPDATE_VER_1 = game_ver
self.UPDATE_URL_1 = f"https://{mucha_url}/updUrl1/"
self.UPDATE_SIZE_1 = "0"
self.UPDATE_CRC_1 = "0000000000000000"
self.CHECK_URL_1 = f"https://{mucha_url}/checkUrl/"
self.EXE_VER_1 = game_ver
self.INFO_SIZE_1 = "0"
self.COM_SIZE_1 = "0"
self.COM_TIME_1 = "0"
self.LAN_INFO_SIZE_1 = "0"
self.USER_ID = ""
self.PASSWORD = ""
2023-03-05 14:43:05 +00:00
2023-03-09 16:38:58 +00:00
class MuchaUpdateResponseStub:
2023-03-05 14:43:05 +00:00
def __init__(self, game_ver: str) -> None:
self.RESULTS = "001"
self.UPDATE_VER_1 = game_ver