URL Slash 0 (Off) and 0.0.0.0

This commit is contained in:
drmext 2023-09-23 09:25:52 +00:00
parent 789c28f198
commit 08b57088b0
No known key found for this signature in database
GPG Key ID: F1ED48FFE79A6961
7 changed files with 139 additions and 35 deletions

View File

@ -4,15 +4,15 @@ e-amusement server using [FastAPI](https://github.com/tiangolo/fastapi) and [Tin
for experimental local testing and playing for experimental local testing and playing
**don't host it publicly as-is** **don't host it publicly as-is. security and privacy features aren't implemented. tinydb can't handle many users.**
## Instructions ## Instructions
1. Install [python](https://www.python.org/ftp/python/3.11.4/python-3.11.4-amd64.exe) with "Add python.exe to PATH" checked 1. Install [python](https://www.python.org/ftp/python/3.11.5/python-3.11.5-amd64.exe) with "Add python.exe to PATH" checked
1. Run [start.bat (Windows)](start.bat) or [start.sh (Linux)](start.sh) 1. Run [start.bat (Windows)](start.bat) or [start.sh (Linux)](start.sh)
1. Edit prop/ea3-config.xml services *url* and url_slash *1* 1. Set services *url* in tools or prop/ea3-config.xml
## Playable Games ## Playable Games
@ -39,7 +39,7 @@ for experimental local testing and playing
## Troubleshooting ## Troubleshooting
- **URL Slash 1 (On)** must be enabled in tools or ea3-config - Set **URL Slash 1 (On)** in tools or ea3-config [if a supported game breaks without it](modules/__init__.py#L44)
- GITADORA requires `mdb_*.xml` copied to the server folder - GITADORA requires `mdb_*.xml` copied to the server folder

View File

@ -2,6 +2,9 @@ from importlib import util
from os import path from os import path
from glob import glob from glob import glob
from fastapi import APIRouter, Request
from typing import Optional
routers = [] routers = []
for module_path in [ for module_path in [
f f
@ -15,3 +18,64 @@ for module_path in [
router = getattr(module, "router", None) router = getattr(module, "router", None)
if router is not None: if router is not None:
routers.append(router) routers.append(router)
if path.basename(module_path) != "api.py":
for obj in dir(module):
globals()[obj] = module.__dict__[obj]
router = APIRouter(tags=["slashless_forwarder"])
@router.post("/core_fwdr")
async def forward_core(
request: Request,
f: Optional[str] = None,
module: Optional[str] = None,
method: Optional[str] = None,
):
if f != None:
module, method = f.split(".")
find_response = globals()[f"{module}_{method}"]
return await find_response(request)
@router.post("/fwdr")
async def forward_game(
request: Request,
model: Optional[str] = None,
f: Optional[str] = None,
module: Optional[str] = None,
method: Optional[str] = None,
):
if f != None:
module, method = f.split(".")
game_code = model.split(":")[0]
# TODO: check for more edge cases
try:
if game_code == "MDX" and module == "eventlog" or module == "eventlog_2":
find_response = globals()[f"ddr_{module}_{method}"]
elif game_code == "REC":
find_response = globals()[f"drs_{module}_{method}"]
elif game_code == "KFC" and module == "eventlog":
find_response = globals()[f"sdvx_{module}_{method}"]
elif game_code == "M32":
if module == "lobby":
find_response = globals()[f"gitadora_{module}_{method}"]
else:
gd_module = module.split("_")
find_response = globals()[f"gitadora_{gd_module[-1]}_{method}"]
return await find_response(gd_module[0], request)
else:
find_response = globals()[f"{module}_{method}".lower()]
except KeyError:
print("Try URL Slash 1 (On) if this game is supported.")
return Response(status_code=404)
return await find_response(request)
routers.append(router)

View File

@ -35,7 +35,7 @@ def get_common(ddr_id, game_version, idx):
@router.post("/{gameinfo}/playerdata/usergamedata_advanced") @router.post("/{gameinfo}/playerdata/usergamedata_advanced")
async def usergamedata_advanced(request: Request): async def playerdata_usergamedata_advanced(request: Request):
request_info = await core_process_request(request) request_info = await core_process_request(request)
game_version = request_info["game_version"] game_version = request_info["game_version"]
is_omni = True if request_info["rev"] == "O" else False is_omni = True if request_info["rev"] == "O" else False
@ -541,7 +541,7 @@ async def usergamedata_advanced(request: Request):
@router.post("/{gameinfo}/playerdata/usergamedata_recv") @router.post("/{gameinfo}/playerdata/usergamedata_recv")
async def usergamedata_recv(request: Request): async def playerdata_usergamedata_recv(request: Request):
request_info = await core_process_request(request) request_info = await core_process_request(request)
game_version = request_info["game_version"] game_version = request_info["game_version"]
@ -651,7 +651,7 @@ async def usergamedata_recv(request: Request):
@router.post("/{gameinfo}/playerdata/usergamedata_send") @router.post("/{gameinfo}/playerdata/usergamedata_send")
async def usergamedata_send(request: Request): async def playerdata_usergamedata_send(request: Request):
request_info = await core_process_request(request) request_info = await core_process_request(request)
game_version = request_info["game_version"] game_version = request_info["game_version"]

View File

@ -35,7 +35,7 @@ def get_common(ddr_id, game_version, idx):
@router.post("/{gameinfo}/playerdata_2/usergamedata_advanced") @router.post("/{gameinfo}/playerdata_2/usergamedata_advanced")
async def usergamedata_advanced(request: Request): async def playerdata_2_usergamedata_advanced(request: Request):
request_info = await core_process_request(request) request_info = await core_process_request(request)
game_version = request_info["game_version"] game_version = request_info["game_version"]
is_omni = True if request_info["rev"] == "O" else False is_omni = True if request_info["rev"] == "O" else False
@ -578,7 +578,7 @@ async def usergamedata_advanced(request: Request):
@router.post("/{gameinfo}/playerdata_2/usergamedata_recv") @router.post("/{gameinfo}/playerdata_2/usergamedata_recv")
async def usergamedata_recv(request: Request): async def playerdata_2_usergamedata_recv(request: Request):
request_info = await core_process_request(request) request_info = await core_process_request(request)
game_version = request_info["game_version"] game_version = request_info["game_version"]
@ -688,7 +688,7 @@ async def usergamedata_recv(request: Request):
@router.post("/{gameinfo}/playerdata_2/usergamedata_send") @router.post("/{gameinfo}/playerdata_2/usergamedata_send")
async def usergamedata_send(request: Request): async def playerdata_2_usergamedata_send(request: Request):
request_info = await core_process_request(request) request_info = await core_process_request(request)
game_version = request_info["game_version"] game_version = request_info["game_version"]

View File

@ -17,7 +17,7 @@ async def iidx30gamesystem_systeminfo(request: Request):
unlock = () unlock = ()
# force unlock LM exclusives to complete unlock all songs server side # force unlock LM exclusives to complete unlock all songs server side
# this makes LM exclusive folder disappear, so just use hex edits # this makes LM exclusive folder disappear, so just use hex edits
# unlock = (28073, 28008, 29095, 29094, 29027, 30077, 30076, 30098) # unlock = (28073, 28008, 29095, 29094, 29027, 30077, 30076, 30098, 30106, 30107, 30028, 30064, 30027)
current_time = round(time()) current_time = round(time())

View File

@ -274,7 +274,7 @@ async def iidx30pc_get(request: Request):
tour_id=i, tour_id=i,
progress=50, # set to 49 to see WT folders, 50 is completed/hidden progress=50, # set to 49 to see WT folders, 50 is completed/hidden
) )
for i in range(13) for i in range(16)
], ],
), ),
E.lightning_setting( E.lightning_setting(
@ -433,6 +433,8 @@ async def iidx30pc_get(request: Request):
E.valkyrie_linkage(music_list_1=-1, music_list_2=-1, music_list_3=-1), E.valkyrie_linkage(music_list_1=-1, music_list_2=-1, music_list_3=-1),
E.bemani_song_battle(music_list=-1), E.bemani_song_battle(music_list=-1),
E.bemani_mixup(music_list=-1), E.bemani_mixup(music_list=-1),
E.ccj_linkage(music_list=-1),
E.triple_tribe(music_list=-1),
E.achievements( E.achievements(
E.trophy(profile.get("achievements_trophy", [])[:10], __type="s64"), E.trophy(profile.get("achievements_trophy", [])[:10], __type="s64"),
pack=profile.get("achievements_pack_id", 0), pack=profile.get("achievements_pack_id", 0),
@ -787,6 +789,7 @@ async def iidx30pc_common(request: Request):
# E.fps_fix(), # E.fps_fix(),
# E.save_unsync_log(), # E.save_unsync_log(),
E.tourism_booster(), E.tourism_booster(),
E.ameto_event(),
expire=600, expire=600,
) )
) )

View File

@ -1,9 +1,10 @@
from urllib.parse import urlunparse, urlencode from urllib.parse import urlparse, urlunparse, urlencode
import uvicorn import uvicorn
import ujson as json import ujson as json
from os import name, path from os import name, path
from typing import Optional
from fastapi import FastAPI, Request, Response from fastapi import FastAPI, Request, Response
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
@ -16,16 +17,24 @@ import utils.card as conv
from core_common import core_process_request, core_prepare_response, E from core_common import core_process_request, core_prepare_response, E
import socket
def urlpathjoin(parts, sep="/"): def urlpathjoin(parts, sep="/"):
return sep + sep.join([x.lstrip(sep) for x in parts]) return sep + sep.join([x.lstrip(sep) for x in parts])
server_address = f"{config.ip}:{config.port}" loopback = "127.0.0.1"
server_services_url = urlunparse(
("http", server_address, config.services_prefix, None, None, None) server_addresses = []
) for host in ("localhost", config.ip, socket.gethostname()):
keepalive_address = "127.0.0.1" server_addresses.append(f"{host}:{config.port}")
server_services_urls = []
for server_address in server_addresses:
server_services_urls.append(
urlunparse(("http", server_address, config.services_prefix, None, None, None))
)
settings = {} settings = {}
for s in ( for s in (
@ -85,23 +94,36 @@ if __name__ == "__main__":
) )
print() print()
print("\033[1mGame Config\033[0m:") print("\033[1mGame Config\033[0m:")
print(f"<services>\033[92m{server_services_url}\033[0m</services>") for server_services_url in server_services_urls:
print('<url_slash __type="bool">\033[92m1\033[0m</url_slash>') print(f"<services>\033[92m{server_services_url}\033[0m</services>")
print("<!-- url_slash \033[92m0\033[0m or \033[92m1\033[0m -->")
# print('<url_slash __type="bool">\033[92m0\033[0m</url_slash>')
# print('<url_slash __type="bool">\033[92m1\033[0m</url_slash>')
print() print()
if webui: if webui:
print("\033[1mWeb Interface\033[0m:") print("\033[1mWeb Interface\033[0m:")
print(f"http://{server_address}/webui/") for server_address in server_addresses:
print(f"http://{server_address}/webui/")
print() print()
print("\033[1mSource Repository\033[0m:") print("\033[1mSource Repository\033[0m:")
print("https://github.com/drmext/MonkeyBusiness") print("https://github.com/drmext/MonkeyBusiness")
print() print()
uvicorn.run("pyeamu:app", host=config.ip, port=config.port, reload=True) uvicorn.run("pyeamu:app", host="0.0.0.0", port=config.port, reload=True)
@app.post(urlpathjoin([config.services_prefix]))
@app.post(urlpathjoin([config.services_prefix, "/{gameinfo}/services/get"])) @app.post(urlpathjoin([config.services_prefix, "/{gameinfo}/services/get"]))
async def services_get(request: Request): async def services_get(
request: Request,
model: Optional[str] = None,
f: Optional[str] = None,
module: Optional[str] = None,
method: Optional[str] = None,
):
request_info = await core_process_request(request) request_info = await core_process_request(request)
request_address = f"{urlparse(str(request.url)).netloc}:{config.port}"
services = {} services = {}
for service in modules.routers: for service in modules.routers:
@ -114,24 +136,42 @@ async def services_get(request: Request):
if model_whitelist and request_info["model"] not in model_whitelist: if model_whitelist and request_info["model"] not in model_whitelist:
continue continue
if (
service.tags
and service.tags[0].startswith("api_")
or service.tags[0] == "slashless_forwarder"
):
continue
k = (service.tags[0] if service.tags else service.prefix).strip("/") k = (service.tags[0] if service.tags else service.prefix).strip("/")
if k not in services: if f == "services.get" or module == "services" and method == "get":
services[k] = urlunparse( if service.prefix == "/core":
("http", server_address, service.prefix, None, None, None) non_slash_prefix = "/core_fwdr"
) else:
non_slash_prefix = "/fwdr"
if k not in services:
services[k] = urlunparse(
("http", request_address, non_slash_prefix, None, None, None)
)
# url_slash
else:
if k not in services:
services[k] = urlunparse(
("http", request_address, service.prefix, None, None, None)
)
keepalive_params = { keepalive_params = {
"pa": keepalive_address, "pa": loopback,
"ia": keepalive_address, "ia": loopback,
"ga": keepalive_address, "ga": loopback,
"ma": keepalive_address, "ma": loopback,
"t1": 2, "t1": 2,
"t2": 10, "t2": 10,
} }
services["keepalive"] = urlunparse( services["keepalive"] = urlunparse(
( (
"http", "http",
keepalive_address, loopback,
"/keepalive", "/keepalive",
None, None,
urlencode(keepalive_params), urlencode(keepalive_params),
@ -139,9 +179,6 @@ async def services_get(request: Request):
) )
) )
services["ntp"] = urlunparse(("ntp", "pool.ntp.org", "/", None, None, None)) services["ntp"] = urlunparse(("ntp", "pool.ntp.org", "/", None, None, None))
services["services"] = urlunparse(
("http", server_address, "/core", None, None, None)
)
response = E.response( response = E.response(
E.services( E.services(