2020-06-26 17:29:33 +00:00
|
|
|
import zipfile
|
2021-05-14 13:25:57 +00:00
|
|
|
import lzma
|
2021-05-15 23:16:51 +00:00
|
|
|
import json
|
|
|
|
import base64
|
2021-04-04 01:18:19 +00:00
|
|
|
import MultiServer
|
2020-06-26 17:29:33 +00:00
|
|
|
|
|
|
|
from flask import request, flash, redirect, url_for, session, render_template
|
2021-05-14 13:25:57 +00:00
|
|
|
from pony.orm import flush, select
|
2020-06-26 17:29:33 +00:00
|
|
|
|
2021-05-14 13:25:57 +00:00
|
|
|
from WebHostLib import app, Seed, Room, Slot
|
|
|
|
from Utils import parse_yaml
|
2020-06-26 17:29:33 +00:00
|
|
|
|
2020-10-19 06:26:31 +00:00
|
|
|
accepted_zip_contents = {"patches": ".apbp",
|
2020-06-26 17:29:33 +00:00
|
|
|
"spoiler": ".txt",
|
2021-01-03 13:32:32 +00:00
|
|
|
"multidata": ".archipelago"}
|
2020-06-26 17:29:33 +00:00
|
|
|
|
|
|
|
banned_zip_contents = (".sfc",)
|
|
|
|
|
|
|
|
|
2020-07-04 21:50:18 +00:00
|
|
|
@app.route('/uploads', methods=['GET', 'POST'])
|
|
|
|
def uploads():
|
2020-06-26 17:29:33 +00: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:
|
|
|
|
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"):
|
2021-05-14 13:25:57 +00:00
|
|
|
slots = set()
|
2020-06-26 17:29:33 +00:00
|
|
|
spoiler = ""
|
|
|
|
multidata = None
|
|
|
|
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."
|
2020-10-19 06:26:31 +00:00
|
|
|
elif file.filename.endswith(".apbp"):
|
2021-05-14 13:25:57 +00:00
|
|
|
data = zfile.open(file, "r").read()
|
|
|
|
yaml_data = parse_yaml(lzma.decompress(data).decode("utf-8-sig"))
|
|
|
|
if yaml_data["version"] < 2:
|
|
|
|
return "Old format cannot be uploaded (outdated .apbp)", 500
|
|
|
|
metadata = yaml_data["meta"]
|
|
|
|
slots.add(Slot(data=data, player_name=metadata["player_name"],
|
|
|
|
player_id=metadata["player_id"],
|
|
|
|
game="A Link to the Past"))
|
2021-05-15 23:16:51 +00:00
|
|
|
|
|
|
|
elif file.filename.endswith(".apmc"):
|
|
|
|
data = zfile.open(file, "r").read()
|
|
|
|
metadata = json.loads(base64.b64decode(data).decode("utf-8"))
|
|
|
|
slots.add(Slot(data=data, player_name=metadata["player_name"],
|
|
|
|
player_id=metadata["player_id"],
|
|
|
|
game="Minecraft"))
|
|
|
|
|
2021-05-16 20:59:45 +00:00
|
|
|
elif file.filename.endswith(".zip"):
|
2021-08-21 04:55:08 +00:00
|
|
|
# Factorio mods needs a specific name or they do not function
|
2021-05-16 20:59:45 +00:00
|
|
|
_, seed_name, slot_id, slot_name = file.filename.rsplit("_", 1)[0].split("-")
|
|
|
|
slots.add(Slot(data=zfile.open(file, "r").read(), player_name=slot_name,
|
|
|
|
player_id=int(slot_id[1:]), game="Factorio"))
|
|
|
|
|
2020-06-26 17:29:33 +00:00
|
|
|
elif file.filename.endswith(".txt"):
|
2020-08-30 14:46:25 +00:00
|
|
|
spoiler = zfile.open(file, "r").read().decode("utf-8-sig")
|
2021-01-03 13:32:32 +00:00
|
|
|
elif file.filename.endswith(".archipelago"):
|
2020-06-26 17:29:33 +00:00
|
|
|
try:
|
2021-04-04 01:18:19 +00:00
|
|
|
multidata = zfile.open(file).read()
|
|
|
|
MultiServer.Context._decompress(multidata)
|
2020-06-26 17:29:33 +00:00
|
|
|
except:
|
|
|
|
flash("Could not load multidata. File may be corrupted or incompatible.")
|
2021-04-04 01:18:19 +00:00
|
|
|
else:
|
|
|
|
multidata = zfile.open(file).read()
|
2020-06-26 17:29:33 +00:00
|
|
|
if multidata:
|
2021-05-14 13:25:57 +00:00
|
|
|
flush() # commit slots
|
|
|
|
seed = Seed(multidata=multidata, spoiler=spoiler, slots=slots, owner=session["_id"])
|
|
|
|
flush() # create seed
|
|
|
|
for slot in slots:
|
|
|
|
slot.seed = seed
|
2020-06-26 17:29:33 +00:00
|
|
|
|
2020-12-01 02:15:47 +00:00
|
|
|
return redirect(url_for("viewSeed", seed=seed.id))
|
2020-06-26 17:29:33 +00:00
|
|
|
else:
|
|
|
|
flash("No multidata was found in the zip file, which is required.")
|
|
|
|
else:
|
|
|
|
try:
|
2021-04-04 01:18:19 +00:00
|
|
|
multidata = file.read()
|
|
|
|
MultiServer.Context._decompress(multidata)
|
2020-06-26 17:29:33 +00:00
|
|
|
except:
|
|
|
|
flash("Could not load multidata. File may be corrupted or incompatible.")
|
2021-04-04 01:18:19 +00:00
|
|
|
raise
|
2020-06-26 17:29:33 +00:00
|
|
|
else:
|
2020-06-27 11:52:03 +00:00
|
|
|
seed = Seed(multidata=multidata, owner=session["_id"])
|
2021-05-14 13:25:57 +00:00
|
|
|
flush() # place into DB and generate ids
|
2020-12-01 02:15:47 +00:00
|
|
|
return redirect(url_for("viewSeed", seed=seed.id))
|
2020-06-26 17:29:33 +00:00
|
|
|
else:
|
|
|
|
flash("Not recognized file format. Awaiting a .multidata file.")
|
2020-12-04 23:22:12 +00:00
|
|
|
return render_template("hostGame.html")
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/user-content', methods=['GET'])
|
|
|
|
def user_content():
|
2020-06-26 17:29:33 +00:00
|
|
|
rooms = select(room for room in Room if room.owner == session["_id"])
|
2020-12-04 22:25:49 +00:00
|
|
|
seeds = select(seed for seed in Seed if seed.owner == session["_id"])
|
2020-12-04 23:22:12 +00:00
|
|
|
return render_template("userContent.html", rooms=rooms, seeds=seeds)
|
2020-07-27 02:05:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
def allowed_file(filename):
|
2021-01-03 13:32:32 +00:00
|
|
|
return filename.endswith(('.archipelago', ".zip"))
|