This commit is contained in:
EvilMuffinHa 2020-10-12 20:03:26 -04:00
parent ac07eab441
commit 06b86d706e
23 changed files with 359 additions and 46 deletions

14
app.py
View File

@ -1,14 +0,0 @@
from flask import *
from random import randint as rint
app = Flask(__name__)
@app.route('/')
def home():
version = rint(0, 300000000)
return render_template('index.html', version=str(version))
if __name__ == "__main__":
app.run()

View File

@ -1,7 +1,15 @@
click==7.1.2 click==7.1.2
Flask==1.1.2 Flask==1.1.2
Flask-SocketIO==4.3.1
Flask-WTF==0.14.3
gunicorn==20.0.4 gunicorn==20.0.4
itsdangerous==1.1.0 itsdangerous==1.1.0
Jinja2==2.11.2 Jinja2==2.11.2
MarkupSafe==1.1.1 MarkupSafe==1.1.1
pycryptodome==3.9.8
python-dotenv==0.14.0
python-engineio==3.13.2
python-socketio==4.6.0
six==1.15.0
Werkzeug==1.0.1 Werkzeug==1.0.1
WTForms==2.3.3

94
src/app.py Normal file
View File

@ -0,0 +1,94 @@
from flask import *
from random import randint as rint
from src.config import Config
from src.host import HostForm
from src.sec import gencode, dohash
from logging.config import dictConfig
import logging
from flask_socketio import SocketIO
import json
dictConfig({
'version': 1,
'formatters': {'default': {
'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',
}},
'handlers': {'wsgi': {
'class': 'logging.StreamHandler',
'stream': 'ext://flask.logging.wsgi_errors_stream',
'formatter': 'default'
}},
'root': {
'level': 'INFO',
'handlers': ['wsgi']
}
})
app = Flask(__name__)
app.logger.info("Flask app loaded at " + __name__)
app.config.from_object(Config)
app.logger.setLevel(logging.DEBUG)
version = rint(0, 300000000)
games = {}
@app.route('/')
def home():
return render_template('index.html', version=str(version))
@app.route("/host", methods=["GET", "POST"])
def host():
form = HostForm()
if form.validate_on_submit():
hostcode = gencode(64)
hash = dohash(hostcode)
resp = redirect(url_for("play", hash=hash))
resp.set_cookie("_gid", str(hostcode), httponly=True, secure=True)
with open("src/templates/games.json", "r") as f:
tmp = json.load(f)
games[hash] = tmp
games[hash]["hostcode"] = hostcode
games[hash]["tossup"] = form.tossup.data
games[hash]["bonus"] = form.bonus.data
games[hash]["power"] = form.power.data
games[hash]["negs"] = form.negs.data
games[hash]["teams"] = form.teams.data
app.logger.debug("Game host at %s", hostcode)
app.logger.info("Game created at %s", hash)
return resp
default = [10, 20, 15, 5]
return render_template('host.html', title="Host Game", version=str(version), form=form, default=default)
@app.route("/play/<hash>")
def play(hash):
if hash in games.keys():
return render_template('play.html', version=str(version))
else:
abort(404)
@app.route("/join")
def join():
return "In progress!"
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
socketio = SocketIO(app)
@socketio.on('json')
def handle_json(json):
print('received message: ' + str(json))
if __name__ == "__main__":
socketio.run(app)
# app.run(host="127.0.0.1", port=25565)

8
src/config.py Normal file
View File

@ -0,0 +1,8 @@
from dotenv import load_dotenv
import os
load_dotenv()
class Config(object):
SECRET_KEY = os.getenv('SECRET_KEY') or "debug-secret-key-for-testing-only"

10
src/host.py Normal file
View File

@ -0,0 +1,10 @@
from flask_wtf import FlaskForm
from wtforms import IntegerField, SubmitField, BooleanField
from wtforms.validators import DataRequired
class HostForm(FlaskForm):
tossup = IntegerField('Tossup Points', validators=[DataRequired()])
bonus = IntegerField('Bonus Points', validators=[DataRequired()])
power = IntegerField('Power Points', validators=[DataRequired()])
negs = IntegerField('Neg Points [Positive]', validators=[DataRequired()])
teams = BooleanField('Teams? ')
create = SubmitField('Create Room')

6
src/join.py Normal file
View File

@ -0,0 +1,6 @@
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, BooleanField
from wtforms.validators import DataRequired
class JoinForm(FlaskForm):
roomcode = StringField('Room Code', validators=[DataRequired()])
create = SubmitField('Join Room')

34
src/sec.py Normal file
View File

@ -0,0 +1,34 @@
from Crypto.Hash import SHA256, SHA3_256, SHAKE128
import secrets
from string import ascii_letters, digits
from binascii import hexlify
def gencode(n):
return ''.join([secrets.choice(ascii_letters + digits) for i in range(n)])
def sha256(val):
h = SHA256.new()
h.update(bytes(str(val).encode('utf-8')))
return h.digest()
def sha3256(val):
ho = SHA3_256.new()
ho.update(bytes(str(val).encode('utf-8')))
return ho.digest()
def hexdigest(val):
return hexlify(val).decode('utf-8')
def shake(val, n):
xh = SHAKE128.new()
xh.update(val)
return xh.read(n)
def dohash(val):
return hexdigest(shake(sha3256(sha256(val)), 7))

View File

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

BIN
src/static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

7
src/static/game.js Normal file
View File

@ -0,0 +1,7 @@
var socket = io();
test = function() {
console.log("h");
socket.emit('json', {data: 'I\'m connected!'});
}
// div id = game (that's where the game goes)

View File

@ -20,7 +20,13 @@ body {
font-size: 3.3rem; font-size: 3.3rem;
} }
.button { .subttl {
text-align: center;
font-family: 'Abberancy-Regular';
font-size: 2rem;
}
.center {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
@ -63,6 +69,30 @@ body {
color: white; color: white;
} }
.back {
background: -webkit-gradient(to right,#a2ccb6 0%,#fceeb5 50%,#ee786e 100%);
background: linear-gradient(to right,#a2ccb6 0%,#fceeb5 50%,#ee786e 100%);
border-top: 12px;
padding-right: 12px;
padding-left: 12px;
padding-bottom: 6px;
padding-top: 6px;
border-radius: 3.75rem;
border-style: none;
box-shadow: 0 .5rem 1rem rgba(0,0,0,.15);
width: 15rem;
letter-spacing: 0.13rem;
background-size: 300%;
text-decoration: none;
color: white;
font: 0.5em Raleway, sans-serif;
}
.top {
margin-top: 17px;
margin-left: 5px;
}
@font-face { @font-face {
font-family: 'Abberancy-Regular'; font-family: 'Abberancy-Regular';
src: url('Abberancy-Regular.svg#Abberancy-Regular') format('svg'), src: url('Abberancy-Regular.svg#Abberancy-Regular') format('svg'),

9
src/templates/404.html Normal file
View File

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% block content %}
<div class="title">
<h1> 404 Error </h1>
</div>
<div class="title">
<h6>Page not found</h6>
</div>
{% endblock %}

20
src/templates/base.html Normal file
View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
{% if title %}
<head>
<meta charset="UTF-8">
<link rel="shortcut icon" type="image/x-icon" href="/static/favicon.ico" />
<link rel="stylesheet" href="/static/index.css?version={{ version }}">
<title>{{ title }} - Buzzer! </title>
</head>
{% else %}
<head>
<title> Buzzer! </title>
<link rel="shortcut icon" type="image/x-icon" href="/static/favicon.ico" />
<link rel="stylesheet" href="/static/index.css?version={{ version }}">
</head>
{% endif %}
<body class="wrap">
{% block content %}{% endblock %}
</body>
</html>

8
src/templates/games.json Normal file
View File

@ -0,0 +1,8 @@
{
"hostcode": "",
"tossup": 10,
"bonus": 20,
"power": 15,
"negs": 5,
"teams": false
}

47
src/templates/host.html Normal file
View File

@ -0,0 +1,47 @@
{% extends "base.html" %}
{% block content %}
<div class="button top">
<a href="{{ url_for('home') }}">Back</a>
</div>
<div class="subttl">
<h1> Host Game </h1>
</div>
<form action="" method="post" novalidate>
{{ form.csrf_token }}
{{ form.hidden_tag() }}
<p>
{{ form.tossup.label }}<br>
{{ form.tossup(size=32, value=default[0]) }}<br>
{% for error in form.tossup.errors %}
<span style="color: red;">[{{ error }}]</span><br>
{% endfor %}
<br>
{{ form.bonus.label }}<br>
{{ form.bonus(size=32, value=default[1]) }}<br>
{% for error in form.bonus.errors %}
<span style="color: red;">[{{ error }}]</span><br>
{% endfor %}
<br>
{{ form.power.label }}<br>
{{ form.power(size=32, value=default[2]) }}<br>
{% for error in form.power.errors %}
<span style="color: red;">[{{ error }}]</span><br>
{% endfor %}
<br>
{{ form.negs.label }}<br>
{{ form.negs(size=32, value=default[3]) }}<br>
{% for error in form.negs.errors %}
<span style="color: red;">[{{ error }}]</span><br>
{% endfor %}
<br>
{{ form.teams() }} {{ form.teams.label }}<br>
{% for error in form.negs.errors %}
<span style="color: red;">[{{ error }}]</span><br>
{% endfor %}
<br>
{{ form.create() }}
<br>
</p>
</form>
{% endblock %}

14
src/templates/index.html Normal file
View File

@ -0,0 +1,14 @@
{% extends "base.html" %}
{% block content %}
<div class="title">
<h1> Buzzer! </h1>
</div>
<div class="button">
<center>
<a href="{{ url_for('host') }}">Host Game</a>
<br><br><br>
<a href="{{ url_for('join') }}">Join Game</a>
</center>
</div>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "base.html" %}
{% block content %}
<div class="title">
<h1> In Progress! </h1>
</div>
{% endblock %}

47
src/templates/join.html Normal file
View File

@ -0,0 +1,47 @@
{% extends "base.html" %}
{% block content %}
<div class="button top">
<a href="{{ url_for('home') }}">Back</a>
</div>
<div class="subttl">
<h1> Host Game </h1>
</div>
<form action="" method="post" novalidate>
{{ form.csrf_token }}
{{ form.hidden_tag() }}
<p>
{{ form.tossup.label }}<br>
{{ form.tossup(size=32, value=default[0]) }}<br>
{% for error in form.tossup.errors %}
<span style="color: red;">[{{ error }}]</span><br>
{% endfor %}
<br>
{{ form.bonus.label }}<br>
{{ form.bonus(size=32, value=default[1]) }}<br>
{% for error in form.bonus.errors %}
<span style="color: red;">[{{ error }}]</span><br>
{% endfor %}
<br>
{{ form.power.label }}<br>
{{ form.power(size=32, value=default[2]) }}<br>
{% for error in form.power.errors %}
<span style="color: red;">[{{ error }}]</span><br>
{% endfor %}
<br>
{{ form.negs.label }}<br>
{{ form.negs(size=32, value=default[3]) }}<br>
{% for error in form.negs.errors %}
<span style="color: red;">[{{ error }}]</span><br>
{% endfor %}
<br>
{{ form.teams() }} {{ form.teams.label }}<br>
{% for error in form.negs.errors %}
<span style="color: red;">[{{ error }}]</span><br>
{% endfor %}
<br>
{{ form.create() }}
<br>
</p>
</form>
{% endblock %}

9
src/templates/play.html Normal file
View File

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% block content %}
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js" integrity="sha256-yr4fRk/GU1ehYJPAs8P4JlTgu0Hdsp4ZKrx8bDEDC3I=" crossorigin="anonymous"></script>
<script src="/static/game.js" type="text/javascript" charset="utf-8"></script>
<div id="game">
</div>
{% endblock %}

View File

@ -1,22 +0,0 @@
<html>
<link rel="stylesheet" href="static/index.css?version={{ version }}">
{% if title %}
<head>
<title>{{ title }} - Buzzer! </title>
</head>
{% else %}
<head><title> Buzzer! </title></head>
{% endif %}
<body class="wrap">
<div class="title">
<h1> Buzzer! </h1>
</div>
<div class="button">
<center>
<a href="#">Host Game</a>
<br><br><br>
<a href="#">Join Game</a>
</center>
</div>
</body>
</html>

View File

@ -1,9 +0,0 @@
<html>
<head>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>