mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 04:01:32 -06:00

zfile.filename is the full path within the archive, so by default zf.extract will maintain that directory structure when extracting. This causes the docs to be placed in the wrong place, as the Javascript code expects them to be placed directly in the game folder.
140 lines
5.2 KiB
Python
140 lines
5.2 KiB
Python
import os
|
|
import multiprocessing
|
|
import logging
|
|
import typing
|
|
|
|
import ModuleUpdate
|
|
|
|
ModuleUpdate.requirements_files.add(os.path.join("WebHostLib", "requirements.txt"))
|
|
ModuleUpdate.update()
|
|
|
|
# in case app gets imported by something like gunicorn
|
|
import Utils
|
|
import settings
|
|
|
|
Utils.local_path.cached_path = os.path.dirname(__file__) or "." # py3.8 is not abs. remove "." when dropping 3.8
|
|
|
|
from WebHostLib import register, app as raw_app
|
|
from waitress import serve
|
|
|
|
from WebHostLib.models import db
|
|
from WebHostLib.autolauncher import autohost, autogen
|
|
from WebHostLib.lttpsprites import update_sprites_lttp
|
|
from WebHostLib.options import create as create_options_files
|
|
|
|
settings.no_gui = True
|
|
configpath = os.path.abspath("config.yaml")
|
|
if not os.path.exists(configpath): # fall back to config.yaml in home
|
|
configpath = os.path.abspath(Utils.user_path('config.yaml'))
|
|
|
|
|
|
def get_app():
|
|
register()
|
|
app = raw_app
|
|
if os.path.exists(configpath) and not app.config["TESTING"]:
|
|
import yaml
|
|
app.config.from_file(configpath, yaml.safe_load)
|
|
logging.info(f"Updated config from {configpath}")
|
|
if not app.config["HOST_ADDRESS"]:
|
|
logging.info("Getting public IP, as HOST_ADDRESS is empty.")
|
|
app.config["HOST_ADDRESS"] = Utils.get_public_ipv4()
|
|
logging.info(f"HOST_ADDRESS was set to {app.config['HOST_ADDRESS']}")
|
|
|
|
db.bind(**app.config["PONY"])
|
|
db.generate_mapping(create_tables=True)
|
|
return app
|
|
|
|
|
|
def create_ordered_tutorials_file() -> typing.List[typing.Dict[str, typing.Any]]:
|
|
import json
|
|
import shutil
|
|
import zipfile
|
|
|
|
zfile: zipfile.ZipInfo
|
|
|
|
from worlds.AutoWorld import AutoWorldRegister
|
|
worlds = {}
|
|
data = []
|
|
for game, world in AutoWorldRegister.world_types.items():
|
|
if hasattr(world.web, 'tutorials') and (not world.hidden or game == 'Archipelago'):
|
|
worlds[game] = world
|
|
|
|
base_target_path = Utils.local_path("WebHostLib", "static", "generated", "docs")
|
|
for game, world in worlds.items():
|
|
# copy files from world's docs folder to the generated folder
|
|
target_path = os.path.join(base_target_path, game)
|
|
os.makedirs(target_path, exist_ok=True)
|
|
|
|
if world.zip_path:
|
|
zipfile_path = world.zip_path
|
|
|
|
assert os.path.isfile(zipfile_path), f"{zipfile_path} is not a valid file(path)."
|
|
assert zipfile.is_zipfile(zipfile_path), f"{zipfile_path} is not a valid zipfile."
|
|
|
|
with zipfile.ZipFile(zipfile_path) as zf:
|
|
for zfile in zf.infolist():
|
|
if not zfile.is_dir() and "/docs/" in zfile.filename:
|
|
zfile.filename = os.path.basename(zfile.filename)
|
|
zf.extract(zfile, target_path)
|
|
else:
|
|
source_path = Utils.local_path(os.path.dirname(world.__file__), "docs")
|
|
files = os.listdir(source_path)
|
|
for file in files:
|
|
shutil.copyfile(Utils.local_path(source_path, file), Utils.local_path(target_path, file))
|
|
|
|
# build a json tutorial dict per game
|
|
game_data = {'gameTitle': game, 'tutorials': []}
|
|
for tutorial in world.web.tutorials:
|
|
# build dict for the json file
|
|
current_tutorial = {
|
|
'name': tutorial.tutorial_name,
|
|
'description': tutorial.description,
|
|
'files': [{
|
|
'language': tutorial.language,
|
|
'filename': game + '/' + tutorial.file_name,
|
|
'link': f'{game}/{tutorial.link}',
|
|
'authors': tutorial.authors
|
|
}]
|
|
}
|
|
|
|
# check if the name of the current guide exists already
|
|
for guide in game_data['tutorials']:
|
|
if guide and tutorial.tutorial_name == guide['name']:
|
|
guide['files'].append(current_tutorial['files'][0])
|
|
break
|
|
else:
|
|
game_data['tutorials'].append(current_tutorial)
|
|
|
|
data.append(game_data)
|
|
with open(Utils.local_path("WebHostLib", "static", "generated", "tutorials.json"), 'w', encoding='utf-8-sig') as json_target:
|
|
generic_data = {}
|
|
for games in data:
|
|
if 'Archipelago' in games['gameTitle']:
|
|
generic_data = data.pop(data.index(games))
|
|
sorted_data = [generic_data] + Utils.title_sorted(data, key=lambda entry: entry["gameTitle"])
|
|
json.dump(sorted_data, json_target, indent=2, ensure_ascii=False)
|
|
return sorted_data
|
|
|
|
|
|
if __name__ == "__main__":
|
|
multiprocessing.freeze_support()
|
|
multiprocessing.set_start_method('spawn')
|
|
logging.basicConfig(format='[%(asctime)s] %(message)s', level=logging.INFO)
|
|
try:
|
|
update_sprites_lttp()
|
|
except Exception as e:
|
|
logging.exception(e)
|
|
logging.warning("Could not update LttP sprites.")
|
|
app = get_app()
|
|
create_options_files()
|
|
create_ordered_tutorials_file()
|
|
if app.config["SELFLAUNCH"]:
|
|
autohost(app.config)
|
|
if app.config["SELFGEN"]:
|
|
autogen(app.config)
|
|
if app.config["SELFHOST"]: # using WSGI, you just want to run get_app()
|
|
if app.config["DEBUG"]:
|
|
app.run(debug=True, port=app.config["PORT"])
|
|
else:
|
|
serve(app, port=app.config["PORT"], threads=app.config["WAITRESS_THREADS"])
|