# HG changeset patch # User Simon Cross # Date 1381092465 -7200 # Node ID 1306f7d8ed358c4d1cd49ee51d2d0c22a7a6f303 # Parent 486c7ae141ea6af25c972a3648c5a3307731c95b Add support for serving zip file containing all levels. diff -r 486c7ae141ea -r 1306f7d8ed35 mamba/forest.py --- a/mamba/forest.py Sun Oct 06 22:46:41 2013 +0200 +++ b/mamba/forest.py Sun Oct 06 22:47:45 2013 +0200 @@ -11,54 +11,88 @@ import sys import socket import json +import StringIO +import zipfile app = Flask(__name__) -def path(ctype): - main = app.config.forest.main - if ctype == "curated": - return os.path.join(main.level_folder, 'curated') - elif ctype == "uncurated": - return os.path.join(main.level_folder, 'uncurated') - abort(404, "Not found") +class LevelSet(object): + def __init__(self, ctype): + self.ctype = ctype + self.folder = self._path(ctype) + + @classmethod + def _path(cls, ctype): + main = app.config.forest.main + if ctype == "curated": + return os.path.join(main.level_folder, 'curated') + elif ctype == "uncurated": + return os.path.join(main.level_folder, 'uncurated') + abort(404, "Not found") + + def _level_path(self, levelname): + filename = "%s.txt" % secure_filename(levelname) + return os.path.join(self.folder, filename) + + def list_levels(self): + endl = len(".txt") + files = [x[:-endl] for x in os.listdir(self.folder) + if not x.startswith('.') and x.endswith('.txt')] + return files + def read_level(self, levelname): + level_path = self._level_path(levelname) + if not os.path.isfile(level_path): + abort(404, "Level not found. Hsss.") + with open(level_path) as level: + return level.read() -def list_levels(folder): - endl = len(".txt") - files = [x[:-endl] for x in os.listdir(folder) - if not x.startswith('.') and x.endswith('.txt')] - return "\n".join(files) + def write_level(self, levelname, leveldata): + level_path = self._level_path(levelname) + if os.path.exists(level_path): + abort(409, "Mamba already resident.") + with open(level_path, 'w') as level: + level.write(leveldata) + + def zip_levels(self): + levels_raw = StringIO.StringIO() + levels_zip = zipfile.ZipFile( + levels_raw, "w", compression=zipfile.ZIP_DEFLATED) + for levelname in self.list_levels(): + levels_zip.writestr( + "%s.txt" % levelname, self.read_level(levelname)) + levels_zip.close() + return levels_raw.getvalue() @app.route("//index") def index(ctype): - ctype = path(ctype) - return list_levels(ctype) + ls = LevelSet(ctype) + levels = ls.list_levels() + return "\n".join(levels) @app.route("//level/") def level(ctype, levelname): - ctype = path(ctype) - levelname = "%s.txt" % secure_filename(levelname) - levelpath = os.path.join(ctype, levelname) - if not os.path.isfile(levelpath): - abort(404, "Level not found. Hsss.") - with open(levelpath) as level: - return level.read() + ls = LevelSet(ctype) + return ls.read_level(levelname) + + +@app.route("//levels.zip") +def levels_zip(ctype): + ls = LevelSet(ctype) + return ls.zip_levels() @app.route("/save/", methods=['GET', 'POST']) def save(levelname): ts = datetime.now().strftime("%Y%m%d.%H%M%S") - levelname = "%s.%s.txt" % (secure_filename(levelname), ts) - levelpath = os.path.join(path("uncurated"), levelname) + levelname = "%s.%s" % (levelname, ts) + ls = LevelSet("uncurated") if request.method == 'POST': - if os.path.exists(levelpath): - abort(409, "Mamba already resident.") leveldata = request.form['data'].encode('ascii') - with open(levelpath, 'w') as level: - level.write(leveldata) + ls.write_level(levelname, leveldata) inform_cia(levelname, "New level uploaded.", branch="uncurated") inform_irker(levelname, "New level uploaded.", branch="uncurated") return "Ssss." @@ -117,7 +151,7 @@ 'author': 'unknown', 'file': filename, 'log': log, - } + } srv = xmlrpclib.Server(cia.url) srv.hub.deliver(msg)