forked from Hay1tsme/artemis
add mucha handler, fix CXB log duplication
This commit is contained in:
parent
7e3396a7ff
commit
9ee155792e
@ -3,3 +3,4 @@ from core.allnet import AllnetServlet
|
|||||||
from core.aimedb import AimedbFactory
|
from core.aimedb import AimedbFactory
|
||||||
from core.title import TitleServlet
|
from core.title import TitleServlet
|
||||||
from core.utils import Utils
|
from core.utils import Utils
|
||||||
|
from core.mucha import MuchaServlet
|
||||||
|
@ -11,7 +11,7 @@ from core.config import CoreConfig
|
|||||||
from core.data import Data
|
from core.data import Data
|
||||||
from core.utils import Utils
|
from core.utils import Utils
|
||||||
|
|
||||||
class AllnetServlet():
|
class AllnetServlet:
|
||||||
def __init__(self, core_cfg: CoreConfig, cfg_folder: str):
|
def __init__(self, core_cfg: CoreConfig, cfg_folder: str):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.config = core_cfg
|
self.config = core_cfg
|
||||||
|
@ -157,6 +157,34 @@ class AimedbConfig:
|
|||||||
def key(self) -> str:
|
def key(self) -> str:
|
||||||
return CoreConfig.get_config_field(self.__config, 'core', 'aimedb', 'key', default="")
|
return CoreConfig.get_config_field(self.__config, 'core', 'aimedb', 'key', default="")
|
||||||
|
|
||||||
|
class MuchaConfig:
|
||||||
|
def __init__(self, parent_config: "CoreConfig") -> None:
|
||||||
|
self.__config = parent_config
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enable(self) -> int:
|
||||||
|
return CoreConfig.get_config_field(self.__config, 'core', 'mucha', 'enable', default=False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def loglevel(self) -> int:
|
||||||
|
return CoreConfig.str_to_loglevel(CoreConfig.get_config_field(self.__config, 'core', 'mucha', 'loglevel', default="info"))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hostname(self) -> str:
|
||||||
|
return CoreConfig.get_config_field(self.__config, 'core', 'mucha', 'hostname', default="localhost")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def port(self) -> int:
|
||||||
|
return CoreConfig.get_config_field(self.__config, 'core', 'mucha', 'port', default=8444)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ssl_cert(self) -> str:
|
||||||
|
return CoreConfig.get_config_field(self.__config, 'core', 'mucha', 'ssl_cert', default="cert/server.pem")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def signing_key(self) -> str:
|
||||||
|
return CoreConfig.get_config_field(self.__config, 'core', 'mucha', 'signing_key', default="cert/billing.key")
|
||||||
|
|
||||||
class CoreConfig(dict):
|
class CoreConfig(dict):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.server = ServerConfig(self)
|
self.server = ServerConfig(self)
|
||||||
|
163
core/mucha.py
Normal file
163
core/mucha.py
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
from typing import Dict, Any, Optional
|
||||||
|
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.config import CoreConfig
|
||||||
|
|
||||||
|
class MuchaServlet:
|
||||||
|
def __init__(self, cfg: CoreConfig) -> None:
|
||||||
|
self.config = cfg
|
||||||
|
|
||||||
|
self.logger = logging.getLogger('mucha')
|
||||||
|
log_fmt_str = "[%(asctime)s] Mucha | %(levelname)s | %(message)s"
|
||||||
|
log_fmt = logging.Formatter(log_fmt_str)
|
||||||
|
|
||||||
|
fileHandler = TimedRotatingFileHandler("{0}/{1}.log".format(self.config.server.log_dir, "mucha"), when="d", backupCount=10)
|
||||||
|
fileHandler.setFormatter(log_fmt)
|
||||||
|
|
||||||
|
consoleHandler = logging.StreamHandler()
|
||||||
|
consoleHandler.setFormatter(log_fmt)
|
||||||
|
|
||||||
|
self.logger.addHandler(fileHandler)
|
||||||
|
self.logger.addHandler(consoleHandler)
|
||||||
|
|
||||||
|
self.logger.setLevel(logging.INFO)
|
||||||
|
coloredlogs.install(level=logging.INFO, logger=self.logger, fmt=log_fmt_str)
|
||||||
|
|
||||||
|
def handle_boardauth(self, request: Request) -> bytes:
|
||||||
|
req_dict = self.mucha_preprocess(request.content.getvalue())
|
||||||
|
if req_dict is None:
|
||||||
|
self.logger.error(f"Error processing mucha request {request.content.getvalue()}")
|
||||||
|
return b""
|
||||||
|
|
||||||
|
req = MuchaAuthRequest(req_dict)
|
||||||
|
self.logger.info(f"Mucha request {vars(req)}")
|
||||||
|
resp = MuchaAuthResponse(mucha_url=f"{self.config.mucha.hostname}:{self.config.mucha.port}")
|
||||||
|
self.logger.info(f"Mucha response {vars(resp)}")
|
||||||
|
|
||||||
|
return self.mucha_postprocess(vars(resp))
|
||||||
|
|
||||||
|
def handle_updatecheck(self, request: Request) -> bytes:
|
||||||
|
req_dict = self.mucha_preprocess(request.content.getvalue())
|
||||||
|
if req_dict is None:
|
||||||
|
self.logger.error(f"Error processing mucha request {request.content.getvalue()}")
|
||||||
|
return b""
|
||||||
|
|
||||||
|
req = MuchaUpdateRequest(req_dict)
|
||||||
|
self.logger.info(f"Mucha request {vars(req)}")
|
||||||
|
resp = MuchaUpdateResponse(mucha_url=f"{self.config.mucha.hostname}:{self.config.mucha.port}")
|
||||||
|
self.logger.info(f"Mucha response {vars(resp)}")
|
||||||
|
|
||||||
|
return self.mucha_postprocess(vars(resp))
|
||||||
|
|
||||||
|
def mucha_preprocess(self, data: bytes) -> Optional[Dict]:
|
||||||
|
try:
|
||||||
|
ret: Dict[str, Any] = {}
|
||||||
|
|
||||||
|
for x in data.decode().split('&'):
|
||||||
|
kvp = x.split('=')
|
||||||
|
if len(kvp) == 2:
|
||||||
|
ret[kvp[0]] = kvp[1]
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
except:
|
||||||
|
self.logger.error(f"Error processing mucha request {data}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def mucha_postprocess(self, data: dict) -> Optional[bytes]:
|
||||||
|
try:
|
||||||
|
urlencode = ""
|
||||||
|
for k,v in data.items():
|
||||||
|
urlencode += f"{k}={v}&"
|
||||||
|
|
||||||
|
return urlencode.encode()
|
||||||
|
|
||||||
|
except:
|
||||||
|
self.logger.error("Error processing mucha response")
|
||||||
|
return None
|
||||||
|
|
||||||
|
class MuchaAuthRequest():
|
||||||
|
def __init__(self, request: Dict) -> None:
|
||||||
|
self.gameVer = "" if "gameVer" not in request else request["gameVer"]
|
||||||
|
self.sendDate = "" if "sendDate" not in request else request["sendDate"]
|
||||||
|
self.serialNum = "" if "serialNum" not in request else request["serialNum"]
|
||||||
|
self.gameCd = "" if "gameCd" not in request else request["gameCd"]
|
||||||
|
self.boardType = "" if "boardType" not in request else request["boardType"]
|
||||||
|
self.boardId = "" if "boardId" not in request else request["boardId"]
|
||||||
|
self.placeId = "" if "placeId" not in request else request["placeId"]
|
||||||
|
self.storeRouterIp = "" if "storeRouterIp" not in request else request["storeRouterIp"]
|
||||||
|
self.countryCd = "" if "countryCd" not in request else request["countryCd"]
|
||||||
|
self.useToken = "" if "useToken" not in request else request["useToken"]
|
||||||
|
self.allToken = "" if "allToken" not in request else request["allToken"]
|
||||||
|
|
||||||
|
class MuchaAuthResponse():
|
||||||
|
def __init__(self, mucha_url: str = "localhost") -> None:
|
||||||
|
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")
|
||||||
|
|
||||||
|
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/"
|
||||||
|
|
||||||
|
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 = ""
|
||||||
|
|
||||||
|
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 = ""
|
||||||
|
|
||||||
|
self.PREFECTURE_ID = "1"
|
||||||
|
self.EXPIRATION_DATE = "null"
|
||||||
|
self.USE_TOKEN = "0"
|
||||||
|
self.CONSUME_TOKEN = "0"
|
||||||
|
self.DONGLE_FLG = "1"
|
||||||
|
self.FORCE_BOOT = "0"
|
||||||
|
|
||||||
|
class MuchaUpdateRequest():
|
||||||
|
def __init__(self, request: Dict) -> None:
|
||||||
|
self.gameVer = "" if "gameVer" not in request else request["gameVer"]
|
||||||
|
self.gameCd = "" if "gameCd" not in request else request["gameCd"]
|
||||||
|
self.serialNum = "" if "serialNum" not in request else request["serialNum"]
|
||||||
|
self.countryCd = "" if "countryCd" not in request else request["countryCd"]
|
||||||
|
self.placeId = "" if "placeId" not in request else request["placeId"]
|
||||||
|
self.storeRouterIp = "" if "storeRouterIp" not in request else request["storeRouterIp"]
|
||||||
|
|
||||||
|
class MuchaUpdateResponse():
|
||||||
|
def __init__(self, game_ver: str = "PKFN0JPN01.01", mucha_url: str = "localhost") -> 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"
|
@ -51,16 +51,25 @@ class TitleServlet():
|
|||||||
self.logger.info(f"Serving {len(globals()['game_registry'])} game codes")
|
self.logger.info(f"Serving {len(globals()['game_registry'])} game codes")
|
||||||
|
|
||||||
def render_GET(self, request: Request, endpoints: dict) -> bytes:
|
def render_GET(self, request: Request, endpoints: dict) -> bytes:
|
||||||
print(endpoints)
|
code = endpoints["game"]
|
||||||
|
if code not in self.title_registry:
|
||||||
|
self.logger.warn(f"Unknown game code {code}")
|
||||||
|
|
||||||
|
index = self.title_registry[code]
|
||||||
|
if not hasattr(index, "render_GET"):
|
||||||
|
self.logger.warn(f"{code} does not dispatch GET")
|
||||||
|
return b""
|
||||||
|
|
||||||
|
return index.render_GET(request, endpoints["version"], endpoints["endpoint"])
|
||||||
|
|
||||||
def render_POST(self, request: Request, endpoints: dict) -> bytes:
|
def render_POST(self, request: Request, endpoints: dict) -> bytes:
|
||||||
print(endpoints)
|
|
||||||
code = endpoints["game"]
|
code = endpoints["game"]
|
||||||
if code not in self.title_registry:
|
if code not in self.title_registry:
|
||||||
self.logger.warn(f"Unknown game code {code}")
|
self.logger.warn(f"Unknown game code {code}")
|
||||||
|
|
||||||
index = self.title_registry[code]
|
index = self.title_registry[code]
|
||||||
if not hasattr(index, "render_POST"):
|
if not hasattr(index, "render_POST"):
|
||||||
self.logger.warn(f"{code} does not dispatch on POST")
|
self.logger.warn(f"{code} does not dispatch POST")
|
||||||
|
return b""
|
||||||
|
|
||||||
return index.render_POST(request, endpoints["version"], endpoints["endpoint"])
|
return index.render_POST(request, endpoints["version"], endpoints["endpoint"])
|
||||||
|
@ -43,3 +43,11 @@ aimedb:
|
|||||||
loglevel: "info"
|
loglevel: "info"
|
||||||
port: 22345
|
port: 22345
|
||||||
key: ""
|
key: ""
|
||||||
|
|
||||||
|
mucha:
|
||||||
|
enable: False
|
||||||
|
hostname: "localhost"
|
||||||
|
loglevel: "info"
|
||||||
|
port: 8444
|
||||||
|
ssl_key: "cert/server.key"
|
||||||
|
ssl_cert: "cert/server.pem"
|
||||||
|
4
index.py
4
index.py
@ -19,11 +19,15 @@ class HttpDispatcher(resource.Resource):
|
|||||||
|
|
||||||
self.allnet = AllnetServlet(cfg, config_dir)
|
self.allnet = AllnetServlet(cfg, config_dir)
|
||||||
self.title = TitleServlet(cfg, config_dir)
|
self.title = TitleServlet(cfg, config_dir)
|
||||||
|
self.mucha = MuchaServlet(cfg)
|
||||||
|
|
||||||
self.map_post.connect('allnet_poweron', '/sys/servlet/PowerOn', controller="allnet", action='handle_poweron', conditions=dict(method=['POST']))
|
self.map_post.connect('allnet_poweron', '/sys/servlet/PowerOn', controller="allnet", action='handle_poweron', conditions=dict(method=['POST']))
|
||||||
self.map_post.connect('allnet_downloadorder', '/sys/servlet/DownloadOrder', controller="allnet", action='handle_dlorder', conditions=dict(method=['POST']))
|
self.map_post.connect('allnet_downloadorder', '/sys/servlet/DownloadOrder', controller="allnet", action='handle_dlorder', conditions=dict(method=['POST']))
|
||||||
self.map_post.connect('allnet_billing', '/request', controller="allnet", action='handle_billing_request', conditions=dict(method=['POST']))
|
self.map_post.connect('allnet_billing', '/request', controller="allnet", action='handle_billing_request', conditions=dict(method=['POST']))
|
||||||
|
|
||||||
|
self.map_post.connect('mucha_boardauth', '/mucha/boardauth.do', controller="mucha", action='handle_boardauth', conditions=dict(method=['POST']))
|
||||||
|
self.map_post.connect('mucha_updatacheck', '/mucha/updatacheck.do', controller="mucha", action='handle_updatacheck', conditions=dict(method=['POST']))
|
||||||
|
|
||||||
self.map_get.connect("title_get", "/{game}/{version}/{endpoint:.*?}", controller="title", action="render_GET", requirements=dict(game=R"S..."))
|
self.map_get.connect("title_get", "/{game}/{version}/{endpoint:.*?}", controller="title", action="render_GET", requirements=dict(game=R"S..."))
|
||||||
self.map_post.connect("title_post", "/{game}/{version}/{endpoint:.*?}", controller="title", action="render_POST", requirements=dict(game=R"S..."))
|
self.map_post.connect("title_post", "/{game}/{version}/{endpoint:.*?}", controller="title", action="render_POST", requirements=dict(game=R"S..."))
|
||||||
|
|
||||||
|
@ -25,21 +25,23 @@ class CxbServlet(resource.Resource):
|
|||||||
self.game_cfg.update(yaml.safe_load(open(f"{cfg_dir}/cxb.yaml")))
|
self.game_cfg.update(yaml.safe_load(open(f"{cfg_dir}/cxb.yaml")))
|
||||||
|
|
||||||
self.logger = logging.getLogger("cxb")
|
self.logger = logging.getLogger("cxb")
|
||||||
log_fmt_str = "[%(asctime)s] CXB | %(levelname)s | %(message)s"
|
if not hasattr(self.logger, "inited"):
|
||||||
log_fmt = logging.Formatter(log_fmt_str)
|
log_fmt_str = "[%(asctime)s] CXB | %(levelname)s | %(message)s"
|
||||||
fileHandler = TimedRotatingFileHandler("{0}/{1}.log".format(self.core_cfg.server.log_dir, "cxb"), encoding='utf8',
|
log_fmt = logging.Formatter(log_fmt_str)
|
||||||
when="d", backupCount=10)
|
fileHandler = TimedRotatingFileHandler("{0}/{1}.log".format(self.core_cfg.server.log_dir, "cxb"), encoding='utf8',
|
||||||
|
when="d", backupCount=10)
|
||||||
|
|
||||||
fileHandler.setFormatter(log_fmt)
|
fileHandler.setFormatter(log_fmt)
|
||||||
|
|
||||||
consoleHandler = logging.StreamHandler()
|
consoleHandler = logging.StreamHandler()
|
||||||
consoleHandler.setFormatter(log_fmt)
|
consoleHandler.setFormatter(log_fmt)
|
||||||
|
|
||||||
self.logger.addHandler(fileHandler)
|
self.logger.addHandler(fileHandler)
|
||||||
self.logger.addHandler(consoleHandler)
|
self.logger.addHandler(consoleHandler)
|
||||||
|
|
||||||
self.logger.setLevel(self.game_cfg.server.loglevel)
|
self.logger.setLevel(self.game_cfg.server.loglevel)
|
||||||
coloredlogs.install(level=self.game_cfg.server.loglevel, logger=self.logger, fmt=log_fmt_str)
|
coloredlogs.install(level=self.game_cfg.server.loglevel, logger=self.logger, fmt=log_fmt_str)
|
||||||
|
self.logger.inited = True
|
||||||
|
|
||||||
self.versions = [
|
self.versions = [
|
||||||
CxbRev(core_cfg, self.game_cfg),
|
CxbRev(core_cfg, self.game_cfg),
|
||||||
|
Loading…
Reference in New Issue
Block a user