From 240087205ff1eab44b2460497627676103d6682c Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Sun, 16 Oct 2016 20:32:00 -0600 Subject: [PATCH] Devel server now serves static puzzles, yay --- devel-server.py | 34 ++++++++++++------ puzzles.py | 87 +++++++++++++++++++++++++++++++++++++++++++++++ www/res/style.css | 4 ++- 3 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 puzzles.py diff --git a/devel-server.py b/devel-server.py index 9f5284e..410e109 100755 --- a/devel-server.py +++ b/devel-server.py @@ -5,6 +5,7 @@ import http.server import mistune import os import pathlib +import puzzles import socketserver HTTPStatus = http.server.HTTPStatus @@ -17,7 +18,7 @@ def page(title, body): -
+
{}
@@ -72,24 +73,37 @@ you are a fool. def serve_puzzles(self): body = [] - parts = self.path.split("/") + path = self.path.rstrip('/') + parts = path.split("/") if len(parts) < 3: # List all categories body.append("# Puzzle Categories") for i in glob.glob(os.path.join("puzzles", "*", "")): body.append("* [{}](/{})".format(i, i)) - elif len(parts) == 4: + elif len(parts) == 3: # List all point values in a category body.append("# Puzzles in category `{}`".format(parts[2])) - puzzles = [] - for i in glob.glob(os.path.join("puzzles", parts[2], "*", "")): - pparts = os.path.split(i[:-1]) - points = int(pparts[-1]) - puzzles.append(points) - for puzzle in sorted(puzzles): + puzz = [] + for i in glob.glob(os.path.join("puzzles", parts[2], "*.moth")): + base = os.path.basename(i) + root, _ = os.path.splitext(base) + points = int(root) + puzz.append(points) + for puzzle in sorted(puzz): body.append("* [puzzles/{cat}/{points}](/puzzles/{cat}/{points}/)".format(cat=parts[2], points=puzzle)) - elif len(parts) == 5: + elif len(parts) == 4: body.append("# {} puzzle {}".format(parts[2], parts[3])) + with open("puzzles/{}/{}.moth".format(parts[2], parts[3])) as f: + p = puzzles.Puzzle(f) + body.append("* Author: `{}`".format(p.fields.get("author"))) + body.append("* Summary: `{}`".format(p.fields.get("summary"))) + body.append('') + body.append("## Body") + body.append(p.body) + body.append("## Answers:") + for a in p.answers: + body.append("* `{}`".format(a)) + body.append("") else: body.append("# Not Implemented Yet") self.serve_md('\n'.join(body)) diff --git a/puzzles.py b/puzzles.py new file mode 100644 index 0000000..e2c79f5 --- /dev/null +++ b/puzzles.py @@ -0,0 +1,87 @@ +#!/usr/bin/python3 + +import hmac +import base64 +import argparse +import glob +import json +import os +import mistune +import random + +messageChars = b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + +def djb2hash(buf): + h = 5381 + for c in buf: + h = ((h * 33) + c) & 0xffffffff + return h + +class Puzzle: + def __init__(self, stream): + self.message = bytes(random.choice(messageChars) for i in range(20)) + self.fields = {} + self.answers = [] + self.hashes = [] + + body = [] + header = True + for line in stream: + if header: + line = line.strip() + if not line.strip(): + header = False + continue + key, val = line.split(':', 1) + key = key.lower() + val = val.strip() + self._add_field(key, val) + else: + body.append(line) + self.body = ''.join(body) + + def _add_field(self, key, val): + if key == 'answer': + h = djb2hash(val.encode('utf8')) + self.answers.append(val) + self.hashes.append(h) + else: + self.fields[key] = val + + def htmlify(self): + return mistune.markdown(self.body) + + def publish(self): + obj = { + 'author': self.fields['author'], + 'hashes': self.hashes, + 'body': self.htmlify(), + } + return obj + + def secrets(self): + obj = { + 'answers': self.answers, + 'summary': self.fields['summary'], + } + return obj + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Build a puzzle category') + parser.add_argument('puzzledir', nargs='+', help='Directory of puzzle source') + args = parser.parse_args() + + for puzzledir in args.puzzledir: + puzzles = {} + secrets = {} + for puzzlePath in glob.glob(os.path.join(puzzledir, "*.moth")): + filename = os.path.basename(puzzlePath) + points, ext = os.path.splitext(filename) + points = int(points) + puzzle = Puzzle(open(puzzlePath)) + puzzles[points] = puzzle + + for points in sorted(puzzles): + puzzle = puzzles[points] + print(puzzle.secrets()) + diff --git a/www/res/style.css b/www/res/style.css index 404d707..f6802c1 100644 --- a/www/res/style.css +++ b/www/res/style.css @@ -55,7 +55,9 @@ pre, tt { padding: 0.25em 0.5em; } -#body { +#preview { + background-image: url(preview.png); + background-size: contain; max-width: 40em; display: block; margin: 1% auto;