| 
									
										
										
										
											2020-07-27 04:05:42 +02:00
										 |  |  | import zipfile | 
					
						
							| 
									
										
										
										
											2023-10-22 02:02:30 +02:00
										 |  |  | import base64 | 
					
						
							|  |  |  | from typing import Union, Dict, Set, Tuple | 
					
						
							| 
									
										
										
										
											2020-07-27 04:05:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-20 01:01:42 +02:00
										 |  |  | from flask import request, flash, redirect, url_for, render_template | 
					
						
							|  |  |  | from markupsafe import Markup | 
					
						
							| 
									
										
										
										
											2020-07-27 04:05:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | from WebHostLib import app | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | banned_zip_contents = (".sfc",) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def allowed_file(filename): | 
					
						
							|  |  |  |     return filename.endswith(('.txt', ".yaml", ".zip")) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-02 22:11:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-17 17:25:59 +01:00
										 |  |  | from Generate import roll_settings, PlandoOptions | 
					
						
							| 
									
										
										
										
											2022-04-12 10:57:29 +02:00
										 |  |  | from Utils import parse_yamls | 
					
						
							| 
									
										
										
										
											2020-07-27 04:05:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-02 22:11:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 15:17:47 +02:00
										 |  |  | @app.route('/check', methods=['GET', 'POST']) | 
					
						
							|  |  |  | def check(): | 
					
						
							| 
									
										
										
										
											2020-07-27 04:05:42 +02:00
										 |  |  |     if request.method == 'POST': | 
					
						
							|  |  |  |         # check if the post request has the file part | 
					
						
							|  |  |  |         if 'file' not in request.files: | 
					
						
							|  |  |  |             flash('No file part') | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2023-09-11 13:57:14 -07:00
										 |  |  |             files = request.files.getlist('file') | 
					
						
							|  |  |  |             options = get_yaml_data(files) | 
					
						
							| 
									
										
										
										
											2022-12-06 00:40:51 +01:00
										 |  |  |             if isinstance(options, str): | 
					
						
							| 
									
										
										
										
											2020-08-02 22:11:52 +02:00
										 |  |  |                 flash(options) | 
					
						
							| 
									
										
										
										
											2020-07-27 04:05:42 +02:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2020-10-29 01:43:23 +01:00
										 |  |  |                 results, _ = roll_options(options) | 
					
						
							| 
									
										
										
										
											2023-10-22 02:02:30 +02:00
										 |  |  |                 if len(options) > 1: | 
					
						
							|  |  |  |                     # offer combined file back | 
					
						
							|  |  |  |                     combined_yaml = "---\n".join(f"# original filename: {file_name}\n{file_content.decode('utf-8-sig')}" | 
					
						
							|  |  |  |                                                  for file_name, file_content in options.items()) | 
					
						
							|  |  |  |                     combined_yaml = base64.b64encode(combined_yaml.encode("utf-8-sig")).decode() | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     combined_yaml = "" | 
					
						
							|  |  |  |                 return render_template("checkResult.html", | 
					
						
							|  |  |  |                                        results=results, combined_yaml=combined_yaml) | 
					
						
							| 
									
										
										
										
											2020-07-27 04:05:42 +02:00
										 |  |  |     return render_template("check.html") | 
					
						
							| 
									
										
										
										
											2020-08-02 22:11:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 15:17:47 +02:00
										 |  |  | @app.route('/mysterycheck') | 
					
						
							|  |  |  | def mysterycheck(): | 
					
						
							|  |  |  |     return redirect(url_for("check"), 301) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 13:57:14 -07:00
										 |  |  | def get_yaml_data(files) -> Union[Dict[str, str], str, Markup]: | 
					
						
							| 
									
										
										
										
											2020-08-02 22:11:52 +02:00
										 |  |  |     options = {} | 
					
						
							| 
									
										
										
										
											2023-10-22 02:02:30 +02:00
										 |  |  |     for uploaded_file in files: | 
					
						
							| 
									
										
										
										
											2023-09-11 13:57:14 -07:00
										 |  |  |         # if user does not select file, browser also | 
					
						
							|  |  |  |         # submit an empty part without filename | 
					
						
							| 
									
										
										
										
											2023-10-22 02:02:30 +02:00
										 |  |  |         if uploaded_file.filename == '': | 
					
						
							| 
									
										
										
										
											2023-09-11 13:57:14 -07:00
										 |  |  |             return 'No selected file' | 
					
						
							| 
									
										
										
										
											2023-10-22 02:02:30 +02:00
										 |  |  |         elif uploaded_file.filename in options: | 
					
						
							|  |  |  |             return f'Conflicting files named {uploaded_file.filename} submitted' | 
					
						
							|  |  |  |         elif uploaded_file and allowed_file(uploaded_file.filename): | 
					
						
							|  |  |  |             if uploaded_file.filename.endswith(".zip"): | 
					
						
							| 
									
										
										
										
											2023-09-11 13:57:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-22 02:02:30 +02:00
										 |  |  |                 with zipfile.ZipFile(uploaded_file, 'r') as zfile: | 
					
						
							| 
									
										
										
										
											2023-09-11 13:57:14 -07:00
										 |  |  |                     infolist = zfile.infolist() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if any(file.filename.endswith(".archipelago") for file in infolist): | 
					
						
							|  |  |  |                         return Markup("Error: Your .zip file contains an .archipelago file. " | 
					
						
							| 
									
										
										
										
											2023-10-22 02:02:30 +02:00
										 |  |  |                                       'Did you mean to <a href="/uploads">host a game</a>?') | 
					
						
							| 
									
										
										
										
											2023-09-11 13:57:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     for file in infolist: | 
					
						
							|  |  |  |                         if file.filename.endswith(banned_zip_contents): | 
					
						
							| 
									
										
										
										
											2023-10-22 02:02:30 +02:00
										 |  |  |                             return ("Uploaded data contained a rom file, " | 
					
						
							|  |  |  |                                     "which is likely to contain copyrighted material. " | 
					
						
							|  |  |  |                                     "Your file was deleted.") | 
					
						
							| 
									
										
										
										
											2023-09-11 13:57:14 -07:00
										 |  |  |                         elif file.filename.endswith((".yaml", ".json", ".yml", ".txt")): | 
					
						
							|  |  |  |                             options[file.filename] = zfile.open(file, "r").read() | 
					
						
							|  |  |  |             else: | 
					
						
							| 
									
										
										
										
											2023-10-22 02:02:30 +02:00
										 |  |  |                 options[uploaded_file.filename] = uploaded_file.read() | 
					
						
							| 
									
										
										
										
											2020-08-02 22:11:52 +02:00
										 |  |  |     if not options: | 
					
						
							|  |  |  |         return "Did not find a .yaml file to process." | 
					
						
							|  |  |  |     return options | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-22 17:20:24 +02:00
										 |  |  | def roll_options(options: Dict[str, Union[dict, str]], | 
					
						
							|  |  |  |                  plando_options: Set[str] = frozenset({"bosses", "items", "connections", "texts"})) -> \ | 
					
						
							|  |  |  |         Tuple[Dict[str, Union[str, bool]], Dict[str, dict]]: | 
					
						
							| 
									
										
										
										
											2023-01-17 17:25:59 +01:00
										 |  |  |     plando_options = PlandoOptions.from_set(set(plando_options)) | 
					
						
							| 
									
										
										
										
											2020-08-02 22:11:52 +02:00
										 |  |  |     results = {} | 
					
						
							|  |  |  |     rolled_results = {} | 
					
						
							|  |  |  |     for filename, text in options.items(): | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2020-10-29 01:43:23 +01:00
										 |  |  |             if type(text) is dict: | 
					
						
							| 
									
										
										
										
											2022-04-12 10:57:29 +02:00
										 |  |  |                 yaml_datas = (text, ) | 
					
						
							| 
									
										
										
										
											2020-10-29 01:43:23 +01:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2022-04-12 10:57:29 +02:00
										 |  |  |                 yaml_datas = tuple(parse_yamls(text)) | 
					
						
							| 
									
										
										
										
											2020-08-02 22:11:52 +02:00
										 |  |  |         except Exception as e: | 
					
						
							|  |  |  |             results[filename] = f"Failed to parse YAML data in {filename}: {e}" | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2022-04-12 10:57:29 +02:00
										 |  |  |                 if len(yaml_datas) == 1: | 
					
						
							|  |  |  |                     rolled_results[filename] = roll_settings(yaml_datas[0], | 
					
						
							| 
									
										
										
										
											2022-05-22 17:20:24 +02:00
										 |  |  |                                                              plando_options=plando_options) | 
					
						
							| 
									
										
										
										
											2022-04-12 10:57:29 +02:00
										 |  |  |                 else: | 
					
						
							|  |  |  |                     for i, yaml_data in enumerate(yaml_datas): | 
					
						
							|  |  |  |                         rolled_results[f"{filename}/{i + 1}"] = roll_settings(yaml_data, | 
					
						
							| 
									
										
										
										
											2022-05-22 17:20:24 +02:00
										 |  |  |                                                                               plando_options=plando_options) | 
					
						
							| 
									
										
										
										
											2020-08-02 22:11:52 +02:00
										 |  |  |             except Exception as e: | 
					
						
							| 
									
										
										
										
											2023-06-23 10:17:35 +02:00
										 |  |  |                 results[filename] = f"Failed to generate options in {filename}: {e}" | 
					
						
							| 
									
										
										
										
											2020-08-02 22:11:52 +02:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 results[filename] = True | 
					
						
							|  |  |  |     return results, rolled_results |