WebHost: Support multi-select during check/generate file upload (#2138)

* Support multi-select during check/generate file upload

This will allow the user to select multiple YAML files via Shift-Click
or Control-Click in their browser when generating a game via the site
instead of having to zip them locally first.

* Update generate.html: File -> File(s)

* Change check.html button text to "Upload File(s)" to match generate.html
This commit is contained in:
Remy Jette 2023-09-11 13:57:14 -07:00 committed by GitHub
parent 3d9837678c
commit 57c13ff273
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 28 deletions

View File

@ -24,8 +24,8 @@ def check():
if 'file' not in request.files: if 'file' not in request.files:
flash('No file part') flash('No file part')
else: else:
file = request.files['file'] files = request.files.getlist('file')
options = get_yaml_data(file) options = get_yaml_data(files)
if isinstance(options, str): if isinstance(options, str):
flash(options) flash(options)
else: else:
@ -39,30 +39,33 @@ def mysterycheck():
return redirect(url_for("check"), 301) return redirect(url_for("check"), 301)
def get_yaml_data(file) -> Union[Dict[str, str], str, Markup]: def get_yaml_data(files) -> Union[Dict[str, str], str, Markup]:
options = {} options = {}
# if user does not select file, browser also for file in files:
# submit an empty part without filename # if user does not select file, browser also
if file.filename == '': # submit an empty part without filename
return 'No selected file' if file.filename == '':
elif file and allowed_file(file.filename): return 'No selected file'
if file.filename.endswith(".zip"): elif file.filename in options:
return f'Conflicting files named {file.filename} submitted'
elif file and allowed_file(file.filename):
if file.filename.endswith(".zip"):
with zipfile.ZipFile(file, 'r') as zfile: with zipfile.ZipFile(file, 'r') as zfile:
infolist = zfile.infolist() infolist = zfile.infolist()
if any(file.filename.endswith(".archipelago") for file in infolist): if any(file.filename.endswith(".archipelago") for file in infolist):
return Markup("Error: Your .zip file contains an .archipelago file. " return Markup("Error: Your .zip file contains an .archipelago file. "
'Did you mean to <a href="/uploads">host a game</a>?') 'Did you mean to <a href="/uploads">host a game</a>?')
for file in infolist: for file in infolist:
if file.filename.endswith(banned_zip_contents): if file.filename.endswith(banned_zip_contents):
return "Uploaded data contained a rom file, which is likely to contain copyrighted material. " \ return "Uploaded data contained a rom file, which is likely to contain copyrighted material. " \
"Your file was deleted." "Your file was deleted."
elif file.filename.endswith((".yaml", ".json", ".yml", ".txt")): elif file.filename.endswith((".yaml", ".json", ".yml", ".txt")):
options[file.filename] = zfile.open(file, "r").read() options[file.filename] = zfile.open(file, "r").read()
else: else:
options = {file.filename: file.read()} options[file.filename] = file.read()
if not options: if not options:
return "Did not find a .yaml file to process." return "Did not find a .yaml file to process."
return options return options

View File

@ -64,8 +64,8 @@ def generate(race=False):
if 'file' not in request.files: if 'file' not in request.files:
flash('No file part') flash('No file part')
else: else:
file = request.files['file'] files = request.files.getlist('file')
options = get_yaml_data(file) options = get_yaml_data(files)
if isinstance(options, str): if isinstance(options, str):
flash(options) flash(options)
else: else:

View File

@ -17,9 +17,9 @@
</p> </p>
<div id="check-form-wrapper"> <div id="check-form-wrapper">
<form id="check-form" method="post" enctype="multipart/form-data"> <form id="check-form" method="post" enctype="multipart/form-data">
<input id="file-input" type="file" name="file"> <input id="file-input" type="file" name="file" multiple>
</form> </form>
<button id="check-button">Upload</button> <button id="check-button">Upload File(s)</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -203,10 +203,10 @@ Warning: playthrough can take a significant amount of time for larger multiworld
</div> </div>
</div> </div>
<div id="generate-form-button-row"> <div id="generate-form-button-row">
<input id="file-input" type="file" name="file"> <input id="file-input" type="file" name="file" multiple>
</div> </div>
</form> </form>
<button id="generate-game-button">Upload File</button> <button id="generate-game-button">Upload File(s)</button>
</div> </div>
</div> </div>
</div> </div>