2023-02-16 06:06:42 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
|
|
import yaml
|
|
|
|
from os import path, mkdir, access, W_OK
|
|
|
|
from core import *
|
|
|
|
|
2023-02-17 07:02:21 +01:00
|
|
|
from twisted.web import server, resource
|
2023-02-16 06:06:42 +01:00
|
|
|
from twisted.internet import reactor, endpoints
|
2023-02-17 07:02:21 +01:00
|
|
|
from twisted.web.http import Request
|
|
|
|
from routes import Mapper
|
2023-02-16 06:06:42 +01:00
|
|
|
|
2023-02-17 07:02:21 +01:00
|
|
|
class HttpDispatcher(resource.Resource):
|
|
|
|
def __init__(self, cfg: CoreConfig, config_dir: str):
|
|
|
|
super().__init__()
|
|
|
|
self.config = cfg
|
|
|
|
self.isLeaf = True
|
|
|
|
self.map_get = Mapper()
|
|
|
|
self.map_post = Mapper()
|
|
|
|
|
|
|
|
self.allnet = AllnetServlet(cfg, config_dir)
|
|
|
|
self.title = TitleServlet(cfg, config_dir)
|
2023-02-17 07:37:59 +01:00
|
|
|
self.mucha = MuchaServlet(cfg)
|
2023-02-17 07:02:21 +01:00
|
|
|
|
|
|
|
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_billing', '/request', controller="allnet", action='handle_billing_request', conditions=dict(method=['POST']))
|
|
|
|
|
2023-02-17 07:37:59 +01:00
|
|
|
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']))
|
|
|
|
|
2023-02-17 07:02:21 +01:00
|
|
|
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..."))
|
|
|
|
|
|
|
|
def render_POST(self, request: Request) -> bytes:
|
|
|
|
test = self.map_get.match(request.uri.decode())
|
|
|
|
if test is None:
|
|
|
|
return b""
|
|
|
|
|
|
|
|
controller = getattr(self, test["controller"], None)
|
|
|
|
if controller is None:
|
|
|
|
return b""
|
|
|
|
|
|
|
|
handler = getattr(controller, test["action"], None)
|
|
|
|
if handler is None:
|
|
|
|
return b""
|
|
|
|
|
|
|
|
url_vars = test
|
|
|
|
url_vars.pop("controller")
|
|
|
|
url_vars.pop("action")
|
|
|
|
|
|
|
|
if len(url_vars) > 0:
|
|
|
|
ret = handler(request, url_vars)
|
|
|
|
else:
|
|
|
|
ret = handler(request)
|
|
|
|
|
|
|
|
if type(ret) == str:
|
|
|
|
return ret.encode()
|
|
|
|
elif type(ret) == bytes:
|
|
|
|
return ret
|
|
|
|
else:
|
|
|
|
return b""
|
|
|
|
|
|
|
|
def render_POST(self, request: Request) -> bytes:
|
|
|
|
test = self.map_post.match(request.uri.decode())
|
|
|
|
if test is None:
|
|
|
|
return b""
|
|
|
|
|
|
|
|
controller = getattr(self, test["controller"], None)
|
|
|
|
if controller is None:
|
|
|
|
return b""
|
|
|
|
|
|
|
|
handler = getattr(controller, test["action"], None)
|
|
|
|
if handler is None:
|
|
|
|
return b""
|
|
|
|
|
|
|
|
url_vars = test
|
|
|
|
url_vars.pop("controller")
|
|
|
|
url_vars.pop("action")
|
|
|
|
ret = handler(request, url_vars)
|
|
|
|
|
|
|
|
if type(ret) == str:
|
|
|
|
return ret.encode()
|
|
|
|
elif type(ret) == bytes:
|
|
|
|
return ret
|
|
|
|
else:
|
|
|
|
return b""
|
|
|
|
|
2023-02-16 06:06:42 +01:00
|
|
|
if __name__ == "__main__":
|
|
|
|
parser = argparse.ArgumentParser(description="ARTEMiS main entry point")
|
|
|
|
parser.add_argument("--config", "-c", type=str, default="config", help="Configuration folder")
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
if not path.exists(f"{args.config}/core.yaml"):
|
|
|
|
print(f"The config folder you specified ({args.config}) does not exist or does not contain core.yaml.\nDid you copy the example folder?")
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
cfg: CoreConfig = CoreConfig()
|
|
|
|
cfg.update(yaml.safe_load(open(f"{args.config}/core.yaml")))
|
|
|
|
|
|
|
|
if not path.exists(cfg.server.log_dir):
|
|
|
|
mkdir(cfg.server.log_dir)
|
|
|
|
|
|
|
|
if not access(cfg.server.log_dir, W_OK):
|
|
|
|
print(f"Log directory {cfg.server.log_dir} NOT writable, please check permissions")
|
|
|
|
exit(1)
|
|
|
|
|
2023-02-16 23:13:41 +01:00
|
|
|
if not cfg.aimedb.key:
|
2023-02-16 06:06:42 +01:00
|
|
|
print("!!AIMEDB KEY BLANK, SET KEY IN CORE.YAML!!")
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
print(f"ARTEMiS starting in {'develop' if cfg.server.is_develop else 'production'} mode")
|
|
|
|
|
|
|
|
allnet_server_str = f"tcp:{cfg.allnet.port}:interface={cfg.server.listen_address}"
|
2023-02-16 23:13:41 +01:00
|
|
|
title_server_str = f"tcp:{cfg.title.port}:interface={cfg.server.listen_address}"
|
2023-02-16 06:06:42 +01:00
|
|
|
adb_server_str = f"tcp:{cfg.aimedb.port}:interface={cfg.server.listen_address}"
|
|
|
|
|
|
|
|
billing_server_str = f"tcp:{cfg.billing.port}:interface={cfg.server.listen_address}"
|
|
|
|
if cfg.server.is_develop:
|
|
|
|
billing_server_str = f"ssl:{cfg.billing.port}:interface={cfg.server.listen_address}"\
|
|
|
|
f":privateKey={cfg.billing.ssl_key}:certKey={cfg.billing.ssl_cert}"
|
|
|
|
|
2023-02-17 07:02:21 +01:00
|
|
|
dispatcher = HttpDispatcher(cfg, args.config)
|
|
|
|
|
2023-02-16 23:13:41 +01:00
|
|
|
endpoints.serverFromString(reactor, allnet_server_str).listen(server.Site(dispatcher))
|
2023-02-16 06:06:42 +01:00
|
|
|
endpoints.serverFromString(reactor, adb_server_str).listen(AimedbFactory(cfg))
|
|
|
|
|
|
|
|
if cfg.billing.port > 0:
|
2023-02-16 23:13:41 +01:00
|
|
|
endpoints.serverFromString(reactor, billing_server_str).listen(server.Site(dispatcher))
|
2023-02-16 06:06:42 +01:00
|
|
|
|
|
|
|
if cfg.title.port > 0:
|
2023-02-16 23:13:41 +01:00
|
|
|
endpoints.serverFromString(reactor, title_server_str).listen(server.Site(dispatcher))
|
2023-02-16 06:06:42 +01:00
|
|
|
|
|
|
|
reactor.run() # type: ignore
|