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