commit f1ee604638e495c8662c6bab70bc3040f9b1ceb4 Author: Michael Soukup Date: Sun May 9 18:23:32 2021 +0200 Write backend diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..11876fd --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +venv +surprise.txt diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b55c9d8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM xxx + +# Install flask and elm + +# Copy files + +# Compile elm + +# Run flask + diff --git a/README.md b/README.md new file mode 100644 index 0000000..cd5b4bf --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# Surprise countdown + +This is a web application for revealing a surprise at a given time. + + + diff --git a/backend/app.py b/backend/app.py new file mode 100644 index 0000000..23f3e3a --- /dev/null +++ b/backend/app.py @@ -0,0 +1,113 @@ +import os +import datetime +import base64 +import random +import string +from dateutil import parser as dt_parser +from toolz import compose +from toolz.curried import map, filter +from atomicwrites import atomic_write + +SURPRISE_TITLE = os.environ.get("SURPRISE_TITLE", "Surprise") +print("SURPRISE_TITLE =", SURPRISE_TITLE) + +SURPRISE_STORE_FILE = os.environ.get("SURPRISE_STORE_FILE", "surprise.txt") +print("SURPRISE_STORE_FILE =", SURPRISE_STORE_FILE) + +SURPRISE_SECRET = os.environ.get("SURPRISE_SECRET") +print("SURPRISE_SECRET =", SURPRISE_SECRET) +assert bool(SURPRISE_SECRET) + +SURPRISE_ASSET_DIR = os.environ.get("SURPRISE_ASSET_DIR", "../surprise-assets/gender-reveal") +print("SURPRISE_ASSET_DIR =", SURPRISE_ASSET_DIR) +assert os.path.isdir(SURPRISE_ASSET_DIR) + +SURPRISE_REVEAL_DATETIME = dt_parser.parse( + os.environ.get( + "SURPRISE_REVEAL_DATETIME", + (datetime.datetime.now() + datetime.timedelta(minutes=5)).isoformat() + ) +) +print("SURPRISE_REVEAL_DATETIME =", SURPRISE_REVEAL_DATETIME) + +def _get_surprise_assets(): + IMG_TYPES = ( + '.png', + '.jpeg', + '.jpg', + '.svg', + '.apng', + '.gif', + '.webp', + '.avif' + ) + _, _, files = next(os.walk(SURPRISE_ASSET_DIR)) + surprise_assets = compose( + dict, + map(lambda xy: (xy[0], os.path.join('/assets', ''.join(xy)))), + filter(lambda xy: xy[1] in IMG_TYPES), + map(lambda s: os.path.splitext(s)), + map(lambda s: s.lower().strip()) + )(files) + if '_null' not in surprise_assets: + surprise_assets['_null'] = os.path.join('/static', '_null.png') + if '_secret' not in surprise_assets: + surprise_assets['_secret'] = os.path.join('/static', '_secret.png') + return surprise_assets + +SURPRISE_ASSETS = _get_surprise_assets() +assert len(SURPRISE_ASSETS) >= 4 +print("SURPRISE_ASSETS =", SURPRISE_ASSETS) + + +from flask import ( + Flask, jsonify, send_from_directory, render_template, request, url_for, + redirect, flash +) +app = Flask(__name__) +app.config['SECRET_KEY'] = ''.join(random.choice(string.ascii_lowercase) for i in range(20)) + +@app.route('/') +def index(): + return render_template('index.html', title=SURPRISE_TITLE) + +@app.route('/assets/') +def assets(path): + return send_from_directory(SURPRISE_ASSET_DIR, path) + +@app.route('/get-surprise.json') +def get_surprise_json(): + diff = (SURPRISE_REVEAL_DATETIME - datetime.datetime.now()).total_seconds() + if os.path.isfile(SURPRISE_STORE_FILE): + if diff < 0: + with open(SURPRISE_STORE_FILE) as f: + surprise = f.read() + else: + surprise = '_secret' + else: + surprise = '_null' + return jsonify({ + 'diff_seconds': diff, + 'surprise': surprise, + 'asset': SURPRISE_ASSETS[surprise] + }) + +@app.route('/set-surprise') +def set_surprise(): + enum = [v for v in SURPRISE_ASSETS.keys() if v not in ('_null', '_secret')] + return render_template('set_surprise.html', title=SURPRISE_TITLE, enum=enum) + +@app.route('/post-surprise', methods=['POST']) +def post_surprise(): + if request.form.get('password') != SURPRISE_SECRET: + flash("Password is wrong") + return redirect(url_for('set_surprise')) + value = request.form.get('surprise') + if value not in SURPRISE_ASSETS.keys(): + flash("Invalid value '%s'" % value) + return redirect(url_for('set_surprise')) + with atomic_write(SURPRISE_STORE_FILE, overwrite=True) as f: + f.write(value) + flash("Value was successfully set to '%s'" % value) + return redirect(url_for('index')) + diff --git a/backend/requirements.pip b/backend/requirements.pip new file mode 100644 index 0000000..483c6f3 --- /dev/null +++ b/backend/requirements.pip @@ -0,0 +1,10 @@ +atomicwrites==1.4.0 +click==7.1.2 +Flask==1.1.2 +itsdangerous==1.1.0 +Jinja2==2.11.3 +MarkupSafe==1.1.1 +python-dateutil==2.8.1 +six==1.16.0 +toolz==0.11.1 +Werkzeug==1.0.1 diff --git a/backend/static/_null.png b/backend/static/_null.png new file mode 100644 index 0000000..e69de29 diff --git a/backend/static/_secret.png b/backend/static/_secret.png new file mode 100644 index 0000000..e69de29 diff --git a/backend/templates/index.html b/backend/templates/index.html new file mode 100644 index 0000000..4cb72de --- /dev/null +++ b/backend/templates/index.html @@ -0,0 +1,23 @@ + + + + + + {{ title }} + + + + {% with messages = get_flashed_messages() %} + {% if messages %} + + {% endif %} + {% endwith %} +

Hei

+

TODO

+ + + diff --git a/backend/templates/set_surprise.html b/backend/templates/set_surprise.html new file mode 100644 index 0000000..c650915 --- /dev/null +++ b/backend/templates/set_surprise.html @@ -0,0 +1,37 @@ + + + + + + {{ title }} + + + + {% with messages = get_flashed_messages() %} + {% if messages %} + + {% endif %} + {% endwith %} + + + + + diff --git a/surprise-assets/gender-reveal/_secret.png b/surprise-assets/gender-reveal/_secret.png new file mode 100644 index 0000000..e69de29 diff --git a/surprise-assets/gender-reveal/boy.png b/surprise-assets/gender-reveal/boy.png new file mode 100644 index 0000000..e69de29 diff --git a/surprise-assets/gender-reveal/girl.png b/surprise-assets/gender-reveal/girl.png new file mode 100644 index 0000000..e69de29