next
This commit is contained in:
parent
ac07eab441
commit
06b86d706e
14
app.py
14
app.py
|
@ -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()
|
|
@ -1,7 +1,15 @@
|
|||
click==7.1.2
|
||||
Flask==1.1.2
|
||||
Flask-SocketIO==4.3.1
|
||||
Flask-WTF==0.14.3
|
||||
gunicorn==20.0.4
|
||||
itsdangerous==1.1.0
|
||||
Jinja2==2.11.2
|
||||
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
|
||||
WTForms==2.3.3
|
||||
|
|
94
src/app.py
Normal file
94
src/app.py
Normal 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
8
src/config.py
Normal 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
10
src/host.py
Normal 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
6
src/join.py
Normal 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
34
src/sec.py
Normal 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))
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
BIN
src/static/favicon.ico
Normal file
BIN
src/static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 318 B |
7
src/static/game.js
Normal file
7
src/static/game.js
Normal 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)
|
|
@ -20,7 +20,13 @@ body {
|
|||
font-size: 3.3rem;
|
||||
}
|
||||
|
||||
.button {
|
||||
.subttl {
|
||||
text-align: center;
|
||||
font-family: 'Abberancy-Regular';
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.center {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
@ -63,6 +69,30 @@ body {
|
|||
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-family: 'Abberancy-Regular';
|
||||
src: url('Abberancy-Regular.svg#Abberancy-Regular') format('svg'),
|
9
src/templates/404.html
Normal file
9
src/templates/404.html
Normal 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
20
src/templates/base.html
Normal 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
8
src/templates/games.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"hostcode": "",
|
||||
"tossup": 10,
|
||||
"bonus": 20,
|
||||
"power": 15,
|
||||
"negs": 5,
|
||||
"teams": false
|
||||
}
|
47
src/templates/host.html
Normal file
47
src/templates/host.html
Normal 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
14
src/templates/index.html
Normal 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 %}
|
7
src/templates/inprogress.html
Normal file
7
src/templates/inprogress.html
Normal 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
47
src/templates/join.html
Normal 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
9
src/templates/play.html
Normal 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 %}
|
|
@ -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>
|
|
@ -1,9 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user