WebHost: Add a yaml checker
This commit is contained in:
		
							parent
							
								
									89cea382ea
								
							
						
					
					
						commit
						63cbdb9449
					
				| 
						 | 
					@ -15,11 +15,6 @@ UPLOAD_FOLDER = os.path.relpath('uploads')
 | 
				
			||||||
LOGS_FOLDER = os.path.relpath('logs')
 | 
					LOGS_FOLDER = os.path.relpath('logs')
 | 
				
			||||||
os.makedirs(LOGS_FOLDER, exist_ok=True)
 | 
					os.makedirs(LOGS_FOLDER, exist_ok=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
def allowed_file(filename):
 | 
					 | 
				
			||||||
    return filename.endswith(('multidata', ".zip"))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app = Flask(__name__)
 | 
					app = Flask(__name__)
 | 
				
			||||||
Pony(app)
 | 
					Pony(app)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,8 +30,11 @@ app.config['MAX_CONTENT_LENGTH'] = 4 * 1024 * 1024  # 4 megabyte limit
 | 
				
			||||||
# if you want persistent sessions on your server, make sure you make this a constant in your config.yaml
 | 
					# if you want persistent sessions on your server, make sure you make this a constant in your config.yaml
 | 
				
			||||||
app.config["SECRET_KEY"] = os.urandom(32)
 | 
					app.config["SECRET_KEY"] = os.urandom(32)
 | 
				
			||||||
app.config['SESSION_PERMANENT'] = True
 | 
					app.config['SESSION_PERMANENT'] = True
 | 
				
			||||||
app.config[
 | 
					
 | 
				
			||||||
    "WAITRESS_THREADS"] = 10  # waitress uses one thread for I/O, these are for processing of views that then get sent
 | 
					# waitress uses one thread for I/O, these are for processing of views that then get sent
 | 
				
			||||||
 | 
					# berserkermulti.world uses gunicorn + nginx; ignoring this option
 | 
				
			||||||
 | 
					app.config["WAITRESS_THREADS"] = 10
 | 
				
			||||||
 | 
					#a default that just works. berserkermulti.world runs on mariadb
 | 
				
			||||||
app.config["PONY"] = {
 | 
					app.config["PONY"] = {
 | 
				
			||||||
    'provider': 'sqlite',
 | 
					    'provider': 'sqlite',
 | 
				
			||||||
    'filename': os.path.abspath('db.db3'),
 | 
					    'filename': os.path.abspath('db.db3'),
 | 
				
			||||||
| 
						 | 
					@ -111,4 +109,4 @@ def host_room(room: UUID):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from WebHostLib.customserver import run_server_process
 | 
					from WebHostLib.customserver import run_server_process
 | 
				
			||||||
from . import tracker, upload, landing  # to trigger app routing picking up on it
 | 
					from . import tracker, upload, landing, check  # to trigger app routing picking up on it
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,66 @@
 | 
				
			||||||
 | 
					import zipfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from flask import request, flash, redirect, url_for, session, render_template
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from WebHostLib import app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					banned_zip_contents = (".sfc",)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def allowed_file(filename):
 | 
				
			||||||
 | 
					    return filename.endswith(('.txt', ".yaml", ".zip"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from Mystery import roll_settings
 | 
				
			||||||
 | 
					from Utils import parse_yaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@app.route('/mysterycheck', methods=['GET', 'POST'])
 | 
				
			||||||
 | 
					def mysterycheck():
 | 
				
			||||||
 | 
					    if request.method == 'POST':
 | 
				
			||||||
 | 
					        # check if the post request has the file part
 | 
				
			||||||
 | 
					        if 'file' not in request.files:
 | 
				
			||||||
 | 
					            flash('No file part')
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            options = {}
 | 
				
			||||||
 | 
					            file = request.files['file']
 | 
				
			||||||
 | 
					            # if user does not select file, browser also
 | 
				
			||||||
 | 
					            # submit an empty part without filename
 | 
				
			||||||
 | 
					            if file.filename == '':
 | 
				
			||||||
 | 
					                flash('No selected file')
 | 
				
			||||||
 | 
					            elif file and allowed_file(file.filename):
 | 
				
			||||||
 | 
					                if file.filename.endswith(".zip"):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    with zipfile.ZipFile(file, 'r') as zfile:
 | 
				
			||||||
 | 
					                        infolist = zfile.infolist()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        for file in infolist:
 | 
				
			||||||
 | 
					                            if file.filename.endswith(banned_zip_contents):
 | 
				
			||||||
 | 
					                                return "Uploaded data contained a rom file, which is likely to contain copyrighted material. Your file was deleted."
 | 
				
			||||||
 | 
					                            elif file.filename.endswith(".yaml"):
 | 
				
			||||||
 | 
					                                options[file.filename] = zfile.open(file, "r").read()
 | 
				
			||||||
 | 
					                            elif file.filename.endswith(".txt"):
 | 
				
			||||||
 | 
					                                options[file.filename] = zfile.open(file, "r").read()
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    options = {file.filename: file.read()}
 | 
				
			||||||
 | 
					                if not options:
 | 
				
			||||||
 | 
					                    flash("Did not find a .yaml file to process.")
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    results = {}
 | 
				
			||||||
 | 
					                    for filename, text in options.items():
 | 
				
			||||||
 | 
					                        try:
 | 
				
			||||||
 | 
					                            yaml_data = parse_yaml(text)
 | 
				
			||||||
 | 
					                        except Exception as e:
 | 
				
			||||||
 | 
					                            results[filename] = f"Failed to parse YAML data in {filename}: {e}"
 | 
				
			||||||
 | 
					                        else:
 | 
				
			||||||
 | 
					                            try:
 | 
				
			||||||
 | 
					                                roll_settings(yaml_data)
 | 
				
			||||||
 | 
					                            except Exception as e:
 | 
				
			||||||
 | 
					                                results[filename] = f"Failed to generate mystery in {filename}: {e}"
 | 
				
			||||||
 | 
					                            else:
 | 
				
			||||||
 | 
					                                results[filename] = "Looks fine"
 | 
				
			||||||
 | 
					                    return render_template("checkresult.html", results=results)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                flash("Not recognized file format. Awaiting a .yaml file.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return render_template("check.html")
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					{% extends 'layout.html' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block head %}
 | 
				
			||||||
 | 
					    {{ super() }}
 | 
				
			||||||
 | 
					    <title>Mystery Check Result</title>
 | 
				
			||||||
 | 
					    <link rel="stylesheet" type="text/css" href="{{ static_autoversion("uploads.css") }}" />
 | 
				
			||||||
 | 
					    <script type="application/ecmascript" src="{{ static_autoversion("uploads.js") }}"></script>
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block body %}
 | 
				
			||||||
 | 
					    <div id="uploads-wrapper">
 | 
				
			||||||
 | 
					        <div id="uploads" class="main-content">
 | 
				
			||||||
 | 
					            <h3>Upload Yaml</h3>
 | 
				
			||||||
 | 
					            <p>This page checks a .yaml file for you, to be used as options for a mystery multiworld. You can also upload a .zip with multiple YAMLs.</p>
 | 
				
			||||||
 | 
					            <div id="uploads-form-wrapper">
 | 
				
			||||||
 | 
					                <form id="upload-form" method="post" enctype="multipart/form-data">
 | 
				
			||||||
 | 
					                    <input id="file-input" type="file" name="file">
 | 
				
			||||||
 | 
					                </form>
 | 
				
			||||||
 | 
					                <button id="upload-button">Upload</button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					{% extends 'layout.html' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block head %}
 | 
				
			||||||
 | 
					    {{ super() }}
 | 
				
			||||||
 | 
					    <title>Upload Mystery YAML</title>
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block body %}
 | 
				
			||||||
 | 
					    {%   for filename, resulttext in results.items() %}
 | 
				
			||||||
 | 
					    <span>{{ filename }}: {{ resulttext }}</span><br>
 | 
				
			||||||
 | 
					    {% endfor %}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@ import logging
 | 
				
			||||||
from flask import request, flash, redirect, url_for, session, render_template
 | 
					from flask import request, flash, redirect, url_for, session, render_template
 | 
				
			||||||
from pony.orm import commit, select
 | 
					from pony.orm import commit, select
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from WebHostLib import app, allowed_file, Seed, Room, Patch
 | 
					from WebHostLib import app, Seed, Room, Patch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
accepted_zip_contents = {"patches": ".bmbp",
 | 
					accepted_zip_contents = {"patches": ".bmbp",
 | 
				
			||||||
                         "spoiler": ".txt",
 | 
					                         "spoiler": ".txt",
 | 
				
			||||||
| 
						 | 
					@ -71,3 +71,7 @@ def uploads():
 | 
				
			||||||
                flash("Not recognized file format. Awaiting a .multidata file.")
 | 
					                flash("Not recognized file format. Awaiting a .multidata file.")
 | 
				
			||||||
    rooms = select(room for room in Room if room.owner == session["_id"])
 | 
					    rooms = select(room for room in Room if room.owner == session["_id"])
 | 
				
			||||||
    return render_template("uploads.html", rooms=rooms)
 | 
					    return render_template("uploads.html", rooms=rooms)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def allowed_file(filename):
 | 
				
			||||||
 | 
					    return filename.endswith(('multidata', ".zip"))
 | 
				
			||||||
		Loading…
	
		Reference in New Issue