commit b8664c1af20c52765f671fcf27b8da78975b5643 Author: guimoz Date: Thu Jan 26 23:32:27 2017 +0100 Import depuis le home de lhark diff --git a/README b/README new file mode 100644 index 0000000..e2d5581 --- /dev/null +++ b/README @@ -0,0 +1,2 @@ +Le serveur a besoin des droits en écriture sur la base SQLite3 et le répertoire +la contenant. diff --git a/assholes b/assholes new file mode 100644 index 0000000..4c41dba --- /dev/null +++ b/assholes @@ -0,0 +1,2 @@ +Luc Absil +Louis-Guillaume Dubois diff --git a/immunity b/immunity new file mode 100644 index 0000000..dfe4b59 --- /dev/null +++ b/immunity @@ -0,0 +1,6 @@ +Goulven Kermarec +Lazare Olivry +Brieuc Lacroix +Cyriaque Millot +Juliette Tibayrenc +Siqi Liu diff --git a/players.db b/players.db new file mode 100644 index 0000000..54df649 Binary files /dev/null and b/players.db differ diff --git a/players.db.bak b/players.db.bak new file mode 100644 index 0000000..d37b198 Binary files /dev/null and b/players.db.bak differ diff --git a/roulette.py b/roulette.py new file mode 100644 index 0000000..3a49173 --- /dev/null +++ b/roulette.py @@ -0,0 +1,417 @@ +# -*- coding: utf8 -* + +from flask import Flask, request, session, g, redirect, url_for, \ + abort, render_template, flash + +from functools import wraps +from contextlib import closing +import sqlite3 +import MySQLdb as mdb +from time import time, localtime, strftime +import locale +import random + +# configuration +DEBUG = True +SECRET_KEY = "\xf3'\xd2\xf7\xa4[.h\x8e\x11|\xda\x00\x9fyS\xfe\xb3(!\x91'6\x16" +USERNAME = 'admin' +PASSWORD = 'pipo' + +SQLITE_FILENAME = '/var/www/roulette/players.db' +SQLITE_SCHEMA = 'schema.sql' + +MYSQL_HOST = 'mysql.rez' +MYSQL_USER = 'rezo_admin_ro' +MYSQL_PASSWORD = 'rezopaspipo' +MYSQL_DB = 'rezo_admin' + +BAN_DURATION = 30. * 60. + +IMMUNITY_FILE = '/var/www/roulette/immunity' +ASSHOLES_FILE = '/var/www/roulette/assholes' + +IMMUNITY = [ + 'Lazare Olivry', + 'Brieuc Lacroix', + 'Elliot Butty', + 'Jean-Christophe Carli', + 'Juliette Tibayrenc', + 'Elise Laurent', + 'Goulven Kermarec', + 'Siqi Liu', + ] + +ASSHOLES = [] + +app = Flask(__name__) +app.config.from_object(__name__) +app.secret_key = SECRET_KEY + +random.seed(time()) + +locale.setlocale(locale.LC_ALL, 'fr_FR.utf8') + +# Utilisation de la base SQLite +def connect_sqlite(): + return sqlite3.connect(SQLITE_FILENAME) + +def init_db(): + # Initialisation de la base SQLite + with closing(connect_sqlite()) as con_sqlite: + with app.open_resource('schema.sql') as f: + con_sqlite.cursor().executescript(f.read()) + con_sqlite.commit() + + # Connexion à la base SQLite locale + con_sqlite = connect_sqlite() + cur_sqlite = con_sqlite.cursor() + + # Connexion à la base MySQL sur babel + con_mysql = mdb.connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DB, \ + charset='utf8', use_unicode=True) + cur_mysql = con_mysql.cursor(mdb.cursors.DictCursor) + + # Remplissage de la table players à partir de la table utilisateurs + cur_mysql.execute("""select id,prenom,nom from utilisateurs + where etat='STATE_ACTIVE' and ecole_id=1 and id<>1 + and typeUtilisateur='membre'""") + rows = cur_mysql.fetchall() + for row in rows: + if row['prenom'] + ' ' + row['nom'] in IMMUNITY: + print(row) + cur_sqlite.execute("""insert into players values (?,?,?,?)""", \ + ((row["id"]), row["prenom"], row["nom"], 0)) + + # Remplissage de la table ip à partir de la table equipements + cur_mysql.execute("""select equipements.id,utilisateurs.id,equipements.ip + from utilisateurs + inner join equipements on utilisateurs.id=equipements.utilisateur_id + where utilisateurs.ecole_id=1 and utilisateurs.id<>1 + and utilisateurs.etat='STATE_ACTIVE' and equipements.etat='STATE_ACTIVE' + and utilisateurs.typeUtilisateur='membre'""") + rows = cur_mysql.fetchall() + for row in rows: + print(row) + cur_sqlite.execute("""insert into machines values (?,?,?)""", \ + (row["id"], row["utilisateurs.id"], row["ip"])) + + con_sqlite.commit() + cur_sqlite.close() + cur_mysql.close() + +def duration_format(seconds): + hours = seconds / 3600 + seconds -= 3600*hours + minutes = seconds / 60 + seconds -= 60*minutes + s_str = seconds <= 1 and 'seconde' or 'secondes' + m_str = minutes <= 1 and 'minute' or 'minutes' + h_str = hours <= 1 and 'heure' or 'heures' + if hours == 0: + if minutes == 0: + return '%01d %s' % (seconds, s_str) + return '%01d %s et %01d %s' % (minutes, m_str, seconds, s_str) + return '%01d %s, %01d %s et %01d %s' % (hours, h_str, minutes, m_str, seconds, s_str) + +def get_ip(): + return request.remote_addr + +def get_player(player_id): + con = connect_sqlite() + cur = con.cursor() + + cur.execute("""select id,firstname,name,ban_end from players + where id=(?)""", [player_id]) + + row = cur.fetchone() + con.close() + + return {'id': row[0], 'firstname': row[1], 'name': row[2], 'ban_end': row[3]} + +def get_player_from_ip(ip): + con = connect_sqlite() + cur = con.cursor() + + cur.execute("""select players.id,players.firstname,players.name, + machines.id,machines.ip,players.ban_end + from players + inner join machines on players.id=machines.player_id + where machines.ip=(?)""", [ip]) + + row = cur.fetchone() + con.close() + + user = None + if row is not None: + user = {'id': row[0], 'firstname': row[1], 'name': row[2], \ + 'machine_id': row[3], 'ip': row[4], 'ban_end': row[5]} + + return user + +def get_player_from_full_name(firstname, name): + con = connect_sqlite() + cur = con.cursor() + + cur.execute("""select players.id,players.firstname,players.name, + machines.id,machines.ip,players.ban_end + from players + inner join machines on players.id=machines.player_id + where players.firstname=(?) and players.name=(?)""", [firstname, name]) + + row = cur.fetchone() + con.close() + + user = None + if row is not None: + user = {'id': row[0], 'firstname': row[1], 'name': row[2], \ + 'machine_id': row[3], 'ip': row[4], 'ban_end': row[5]} + + return user + +def is_banned(user_id): + con = connect_sqlite() + cur = con.cursor() + + cur.execute("""select ban_end from players where id=(?)""", [user_id]) + + ban_end = cur.fetchone()[0] + con.close() + + return time() < ban_end + +def playable_required(f): + @wraps(f) + def decorated_function(*args, **kwargs): + user = get_player_from_ip(get_ip()) + + # Attention : un utilisateur inscrit ne peut pas être forcé à être + # désinscrit s'il n'enlève pas son cookie de session. On évite la + # réexécution de la requête. + if 'subscribed' not in session or not session['subscribed']: + session['subscribed'] = user is not None + if not session['subscribed']: + return render_template('not_subscribed.html') + + # Un utilisateur banni ne peut pas jouer + if user and is_banned(user['id']): + return banned() + + return f(*args, **kwargs) + return decorated_function + +def get_players_not_banned(): + con = connect_sqlite() + cur = con.cursor() + + cur.execute("""select id,firstname,name from players + where (?) > ban_end """, [time()]) + + rows = cur.fetchall() + con.close() + + return [{'id': row[0], 'firstname': row[1], 'name': row[2]} for row in rows] + +def cheat(player_id, target_id): + success = random.choice([True, False]) + try: + ok = [line.strip().partition(' ') for line in IMMUNITY] + ok = [get_player_from_full_name(names[0], names[2])['id'] for names in ok] + + ko = [line.strip().partition(' ') for line in ASSHOLES] + ko = [get_player_from_full_name(names[0], names[2])['id'] for names in ko] + + if target_id in ko: + success = True + elif player_id in ko: + success = False + elif target_id in ok: + success = False + + except TypeError: + pass + + return success + + +def ban(player_id, target_id, success): + player = get_player(player_id) + target = get_player(target_id) + + banned_player = success and target or player + + con = connect_sqlite() + cur = con.cursor() + + cur.execute("""select id,ban_end from players + where id=(?)""", [banned_player['id']]) + + ban_end = cur.fetchone()[0] + ban_end = time() + BAN_DURATION + + cur.execute("""update players set ban_end=(?) + where id=(?)""", [ban_end, banned_player['id']]) + + cur.execute("""insert into bans (player_id,target_id,success,time) + values (?,?,?,?)""", [player['id'], target['id'], \ + success and 1 or 0, time()]) + + con.commit() + con.close() + +def unban(player_id): + con = connect_sqlite() + cur = con.cursor() + + cur.execute("""update players set ban_end=(?) + where id=(?)""", [time() - BAN_DURATION, player_id]) + + con.commit() + con.close() + +def get_bans(player_id): + con = connect_sqlite() + cur = con.cursor() + + # Bannissements concernant le joueur : + cur.execute("""select player_id,target_id,success,time from bans + where target_id=(?) + or player_id=(?)""", [player_id, player_id]) + + rows = cur.fetchall() + con.close() + + return [{'player_id': row[0], 'target_id': row[1], \ + 'success': row[2], 'time': row[3]} for row in rows] + +def banned(): + player = get_player_from_ip(get_ip()) + last_ban = sorted(get_bans(player['id']), key=lambda p: p['time'], \ + reverse=False)[-1] + + if last_ban['target_id'] == player['id'] and last_ban['success'] == 1: + source = get_player(last_ban['player_id']) + explanation = u'Tu t\'es fait bannir par %s %s.' \ + % (source['firstname'], source['name']) + else: + explanation = u'Tu t\'es banni toi-même, pas de chance...' + + timeleft = duration_format(int(player['ban_end'] - time())) + + return render_template('banned.html', \ + explanation=explanation, timeleft=timeleft) + + +@app.route('/banned_ip') +def banned_ip(): + # Liste des ip pour récupération par babel et plop + if get_ip() not in ['10.7.0.39', '10.7.0.254' ,'10.13.0.1', '10.69.8.5' ,'10.69.2.219']: + abort(403) + + con = connect_sqlite() + cur = con.cursor() + + cur.execute("""select machines.ip from players + inner join machines on players.id=machines.player_id + where players.ban_end>(?)""", [time()]) + + rows = cur.fetchall() + con.close() + + return '\n'.join([row[0] for row in rows]) + +@app.route('/') +@playable_required +def home(): + ip = get_ip() + player = get_player_from_ip(ip) + + #if ip not in ['10.69.8.5', '10.69.8.202']: + # abort(403) + + if session.get('logged_in'): + pass + + bans = sorted(get_bans(player['id']), \ + key=lambda ban: ban['time'], \ + reverse=True) + + bans_hist = [] + for ban in bans: + date = strftime('%Hh%M (%A)', localtime(ban['time'])) + source = get_player(ban['player_id']) + target = get_player(ban['target_id']) + + if target['id'] == player['id']: + if ban['success']: + entry = ('ban', u'%s : %s %s a réussi à t\'avoir.' \ + % (date, source['firstname'], source['name'])) + else: + entry = ('warn', u'%s : %s %s a essayé de te bannir, en vain.' \ + % (date, source['firstname'], source['name'])) + else: + if ban['success']: + entry = ('ok', u'%s : Tu as banni %s %s avec succès.' \ + % (date, target['firstname'], target['name'])) + else: + entry = ('ban', u'%s : Tu as échoué en voulant bannir %s %s.' \ + % (date, target['firstname'], target['name'])) + + bans_hist.append(entry) + + return render_template('home.html', bans_hist=bans_hist) + +@app.route('/jouer', methods=['GET', 'POST']) +@playable_required +def play(): + ip = get_ip() + player = get_player_from_ip(ip) + + # Traitement de la requête de bannissement + if request.method == 'POST': + target_id = request.form['target_id'] + if target_id != 'none': + if is_banned(target_id): + flash(u'Utilisateur déjà banni, il faut en choisir un autre.') + else: + success = cheat(player['id'], target_id) + if success: + target = get_player(target_id) + ban(player['id'], target_id, True) + flash(u'Trop cool, %s a été tranché pour un bon moment.' \ + % target['firstname']) + else: + ban(player['id'], target_id, False) + return banned() + + # Liste des joueurs non bannis, triée dans l'ordre croissant ou décroissant + players = sorted(get_players_not_banned(), \ + key=lambda player: player['firstname'], \ + reverse = random.choice([True, False])) + + # sans le joueur actuel + players = filter(lambda p: p['id'] != player['id'], players) + + return render_template('play.html', players=players) + +@app.route('/login', methods=['GET', 'POST']) +def login(): + error = None + if request.method == 'POST': + if request.form['username'] != app.config['USERNAME']: + error = 'Invalid username' + elif request.form['password'] != app.config['PASSWORD']: + error = 'Invalid password' + else: + session['logged_in'] = True + flash('You were logged in') + return redirect(url_for('home')) + return render_template('login.html', error=error) + +@app.route('/logout') +def logout(): + session.pop('logged_in', None) + flash('You were logged out') + return redirect(url_for('home')) + +if __name__ == '__main__': + app.run() diff --git a/roulette.wsgi b/roulette.wsgi new file mode 100644 index 0000000..608dad4 --- /dev/null +++ b/roulette.wsgi @@ -0,0 +1,4 @@ +import sys +sys.path.insert(0, '/var/www/roulette') + +from roulette import app as application diff --git a/schema.sql b/schema.sql new file mode 100644 index 0000000..f1f2bda --- /dev/null +++ b/schema.sql @@ -0,0 +1,23 @@ +drop table if exists players; +create table players ( + id integer primary key autoincrement, + firstname text not null, + name text not null, + ban_end float not null +); + +drop table if exists machines; +create table machines ( + id integer primary key autoincrement, + player_id integer not null, + ip text not null +); + +drop table if exists bans; +create table bans ( + id integer primary key autoincrement, + player_id integer not null, + target_id integer not null, + success integer not null, + time float not null +); diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..2b7f7c0 Binary files /dev/null and b/static/favicon.ico differ diff --git a/static/img/asocial_metzwork_v1.png b/static/img/asocial_metzwork_v1.png new file mode 100644 index 0000000..1f643cb Binary files /dev/null and b/static/img/asocial_metzwork_v1.png differ diff --git a/static/img/corner_bottomleft.png b/static/img/corner_bottomleft.png new file mode 100644 index 0000000..fd03428 Binary files /dev/null and b/static/img/corner_bottomleft.png differ diff --git a/static/img/corner_bottomright.png b/static/img/corner_bottomright.png new file mode 100644 index 0000000..1cde1b7 Binary files /dev/null and b/static/img/corner_bottomright.png differ diff --git a/static/img/corner_topleft.png b/static/img/corner_topleft.png new file mode 100644 index 0000000..9d16b63 Binary files /dev/null and b/static/img/corner_topleft.png differ diff --git a/static/img/corner_topright.png b/static/img/corner_topright.png new file mode 100644 index 0000000..2fccb2e Binary files /dev/null and b/static/img/corner_topright.png differ diff --git a/static/img/k6lqsh.png b/static/img/k6lqsh.png new file mode 100644 index 0000000..66d0468 Binary files /dev/null and b/static/img/k6lqsh.png differ diff --git a/static/img_red/asocial_metzwork_v1.png b/static/img_red/asocial_metzwork_v1.png new file mode 100644 index 0000000..1f643cb Binary files /dev/null and b/static/img_red/asocial_metzwork_v1.png differ diff --git a/static/img_red/corner_bottomleft.png b/static/img_red/corner_bottomleft.png new file mode 100644 index 0000000..02c9b30 Binary files /dev/null and b/static/img_red/corner_bottomleft.png differ diff --git a/static/img_red/corner_bottomright.png b/static/img_red/corner_bottomright.png new file mode 100644 index 0000000..7205d0f Binary files /dev/null and b/static/img_red/corner_bottomright.png differ diff --git a/static/img_red/corner_topleft.png b/static/img_red/corner_topleft.png new file mode 100644 index 0000000..6004abd Binary files /dev/null and b/static/img_red/corner_topleft.png differ diff --git a/static/img_red/corner_topright.png b/static/img_red/corner_topright.png new file mode 100644 index 0000000..402e0cf Binary files /dev/null and b/static/img_red/corner_topright.png differ diff --git a/static/img_red/k6lqsh.png b/static/img_red/k6lqsh.png new file mode 100644 index 0000000..51d8119 Binary files /dev/null and b/static/img_red/k6lqsh.png differ diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..b4055af --- /dev/null +++ b/static/style.css @@ -0,0 +1,188 @@ +body { + background: #3b5998; + color: white; + text-align: center; + font-family: helvetica, sans; +} + +a { + text-decoration: none; + color: grey; +} + +#body_bis { + margin-left: auto; + margin-right: auto; + width: 90%; + max-width: 1300px; + min-width: 550px; +} + +#banner { + height: 101px; + background: center center url('img/asocial_metzwork_v1.png') no-repeat; + padding: 10px 10px; +} + +#content_container { + margin-left: 200px; + margin-right: 200px; + position: relative; + background: white; + color: black; + padding-left: 12px; + padding-right: 12px; + padding-top: 10px; + padding-bottom: 10px; +} + +#content_container div.corner { + height: 70px; + width: 70px; + background-repeat: no-repeat; + position: absolute; +} + +#content_topleft { + top: 0px; + left: 0px; + background-image: url('img/corner_topleft.png'); + background-color: #3b5998; + z-index: 1; +} + +#content_topright { + top: 0px; + right: 0px; + background-image: url('img/corner_topright.png'); + background-color: #3b5998; + z-index: 2; +} + +#content_bottomleft { + bottom: 0px; + left: 0px; + background-image: url('img/corner_bottomleft.png'); + background-color: #3b5998; + z-index: 3; +} + +#content_bottomright { + bottom: 0px; + right: 0px; + background-image: url('img/corner_bottomright.png'); + background-color: #3b5998; + z-index: 4; +} + +#content { + position: relative; + z-index: 5; + text-align: left; +} + + +/* Contenu */ + +#content h1 { + margin-top: 5px; + padding-left: 50px; + font-size: 130%; +} + +#content h2, #content p { + margin-left: 20px; + margin-right: 20px; +} + +#content h2 { + margin-top:0px; + font-size: 100%; + margin-bottom: 5px; + padding-bottom: 0px; +} + +#content p { + text-indent: 2em; + margin-top: 0px; + font-size: 90%; +} + +#content ul#history { + padding-left: 60px; +} + +#content li.events { + font-size: 180%; +} + +#content li .normal { + color: black; + font-size: 80%; +} + +#content li.ban { + color: red; +} + +#content li.warn { + color: orange; +} + +#content li.ok { + color: #1D1; +} + +#content_container #footer { + margin-top: 4em; + font-size: 70%; +} + +p#play { + text-align: center; + font-size: 1.5em; + font-weight: bold; + margin-top: 1.6em; + margin-bottom: 2em; +} + +p#play a { + font-weight: bold; + color: white; + background: #2E2; + padding: .5em 2em; + border: 1px solid #191; + border-radius: 10px; +} + +p#play a:hover { + background: #191; +} + +form#select { + width: 500px; + margin: 1em auto; + background: #FA0; + border-radius: 1em; + border: 1px solid #C70; + padding: 1em 0em; + text-align: center; +} + +ul.flashes { + font-size: 80%; + font-weight: bold; + color: #222; + list-style-type: none; + padding: 0; + width: 90%; + margin: .5em auto; +} + +ul.flashes li { + background: #2E2; + border: 1px solid #191; + border-radius: .6em; + margin-bottom: 1em; + padding: .4em .7em; +} diff --git a/static/style_red.css b/static/style_red.css new file mode 100644 index 0000000..861fab9 --- /dev/null +++ b/static/style_red.css @@ -0,0 +1,188 @@ +body { + background: #3b5998; + color: red; + text-align: center; + font-family: helvetica, sans; +} + +a { + text-decoration: none; + color: grey; +} + +#body_bis { + margin-left: auto; + margin-right: auto; + width: 90%; + max-width: 1300px; + min-width: 550px; +} + +#banner { + height: 101px; + background: center center url('img_red/asocial_metzwork_v1.png') no-repeat; + padding: 10px 10px; +} + +#content_container { + margin-left: 200px; + margin-right: 200px; + position: relative; + background: red; + color: white; + padding-left: 12px; + padding-right: 12px; + padding-top: 10px; + padding-bottom: 10px; +} + +#content_container div.corner { + height: 70px; + width: 70px; + background-repeat: no-repeat; + position: absolute; +} + +#content_topleft { + top: 0px; + left: 0px; + background-image: url('img_red/corner_topleft.png'); + background-color: #3b5998; + z-index: 1; +} + +#content_topright { + top: 0px; + right: 0px; + background-image: url('img_red/corner_topright.png'); + background-color: #3b5998; + z-index: 2; +} + +#content_bottomleft { + bottom: 0px; + left: 0px; + background-image: url('img_red/corner_bottomleft.png'); + background-color: #3b5998; + z-index: 3; +} + +#content_bottomright { + bottom: 0px; + right: 0px; + background-image: url('img_red/corner_bottomright.png'); + background-color: #3b5998; + z-index: 4; +} + +#content { + position: relative; + z-index: 5; + text-align: left; +} + + +/* Contenu */ + +#content h1 { + margin-top: 5px; + padding-left: 50px; + font-size: 130%; +} + +#content h2, #content p { + margin-left: 20px; + margin-right: 20px; +} + +#content h2 { + margin-top:0px; + font-size: 100%; + margin-bottom: 5px; + padding-bottom: 0px; +} + +#content p { + text-indent: 2em; + margin-top: 0px; + font-size: 90%; +} + +#content ul#history { + padding-left: 60px; +} + +#content li.events { + font-size: 180%; +} + +#content li .normal { + color: black; + font-size: 80%; +} + +#content li.ban { + color: red; +} + +#content li.warn { + color: orange; +} + +#content li.ok { + color: #1D1; +} + +#content_container #footer { + margin-top: 4em; + font-size: 70%; +} + +p#play { + text-align: center; + font-size: 1.5em; + font-weight: bold; + margin-top: 1.6em; + margin-bottom: 2em; +} + +p#play a { + font-weight: bold; + color: white; + background: #2E2; + padding: .5em 2em; + border: 1px solid #191; + border-radius: 10px; +} + +p#play a:hover { + background: #191; +} + +form#select { + width: 500px; + margin: 1em auto; + background: #FA0; + border-radius: 1em; + border: 1px solid #C70; + padding: 1em 0em; + text-align: center; +} + +ul.flashes { + font-size: 80%; + font-weight: bold; + color: #222; + list-style-type: none; + padding: 0; + width: 90%; + margin: .5em auto; +} + +ul.flashes li { + background: #2E2; + border: 1px solid #191; + border-radius: .6em; + margin-bottom: 1em; + padding: .4em .7em; +} diff --git a/templates/banned.html b/templates/banned.html new file mode 100644 index 0000000..056af62 --- /dev/null +++ b/templates/banned.html @@ -0,0 +1,16 @@ +{% extends "layout_banned.html" %} +{% block content %} +

Tu es tranché

+

+ {{ explanation }} +

+

+ Rétablissement de la connexion externe dans approximativement : +

+

+ {{ timeleft }}. +

+

+ (redémarrer le navigateur peut être nécessaire une fois ce délai écoulé) +

+{% endblock %} diff --git a/templates/home.html b/templates/home.html new file mode 100644 index 0000000..01da8a4 --- /dev/null +++ b/templates/home.html @@ -0,0 +1,27 @@ +{% extends "layout.html" %} +{% block content %} +

24 heures

+

Toi aussi, joue au rézoman !

+

+ Jusqu'à samedi 11h, tu peux essayer de trancher tes + camarades pour 30 min. +

+

+ Jouer +

+

Historique personnel

+ +{% if bans_hist != [] %} + +{% else %} +

+ Rien pour l'instant +

+{% endif %} +{% endblock %} diff --git a/templates/home.html~ b/templates/home.html~ new file mode 100644 index 0000000..0708e74 --- /dev/null +++ b/templates/home.html~ @@ -0,0 +1,27 @@ +{% extends "layout.html" %} +{% block content %} +

24 heures

+

Toi aussi, joue au rézoman !

+

+ Jusqu'à mercredi 9h, tu peux essayer de trancher tes + camarades pour 30 min. +

+

+ Jouer +

+

Historique personnel

+ +{% if bans_hist != [] %} + +{% else %} +

+ Rien pour l'instant +

+{% endif %} +{% endblock %} diff --git a/templates/layout.html b/templates/layout.html new file mode 100644 index 0000000..de1c7f1 --- /dev/null +++ b/templates/layout.html @@ -0,0 +1,43 @@ + + + + asocial metzwork - 24h + + + + + + +
+ + +
+
+
+
+
+
+ {% with messages = get_flashed_messages() %} + {% if messages %} +
    + {% for message in messages %} +
  • {{ message }}
  • + {% endfor %} +
+ {% endif %} + {% endwith %} + {% block content %}{% endblock %} +
+
+
+
+
+ +
+
+ + diff --git a/templates/layout_banned.html b/templates/layout_banned.html new file mode 100644 index 0000000..135c35d --- /dev/null +++ b/templates/layout_banned.html @@ -0,0 +1,44 @@ + + + + asocial metzwork - 24h + + + + + + + +
+ + +
+
+
+
+
+
+ {% with messages = get_flashed_messages() %} + {% if messages %} +
    + {% for message in messages %} +
  • {{ message }}
  • + {% endfor %} +
+ {% endif %} + {% endwith %} + {% block content %}{% endblock %} +
+
+
+
+
+ +
+
+ + diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..d3b0844 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,15 @@ +{% extends "layout.html" %} +{% block content %} +

Login

+{% if error %}

Error: {{ error }}{% endif %} +

+ +
+
Identifiant : +
+
Mot de passe : +
+
+
+
+{% endblock %} diff --git a/templates/not_subscribed.html b/templates/not_subscribed.html new file mode 100644 index 0000000..1c28c77 --- /dev/null +++ b/templates/not_subscribed.html @@ -0,0 +1,9 @@ +{% extends "layout.html" %} +{% block content %} +

Vous n'êtes pas inscrit

+

+ Si vous désirez participer malgré les risques que le jeu comporte, veuillez + envoyer un email à goulven.kermarec@supelec.fr . + (Vous ne pouvez pas jouer depuis Supélec) +

+{% endblock %} diff --git a/templates/not_subscribed.html~ b/templates/not_subscribed.html~ new file mode 100644 index 0000000..6c45143 --- /dev/null +++ b/templates/not_subscribed.html~ @@ -0,0 +1,9 @@ +{% extends "layout.html" %} +{% block content %} +

Vous n'êtes pas inscrits

+

+ Si vous désirez participer malgré les risques que le jeu comporte, veuillez + envoyer un email à goulven.kermarec@supelec.fr . + (Vous ne pouvez pas jouer depuis Supélec) +

+{% endblock %} diff --git a/templates/play.html b/templates/play.html new file mode 100644 index 0000000..46c40f3 --- /dev/null +++ b/templates/play.html @@ -0,0 +1,23 @@ +{% extends "layout.html" %} +{% block content %} +

24 heures

+

Trancher un joueur

+

+ Ta cible sera notifiée quelle que soit l'issue de ta tentative. Question + chance, c'est 50-50. +

+
+ + +
+

+« retour à l'accueil +

+{% endblock %}