You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
5.8 KiB

import random
import operator
import json
import datetime
from flask import Flask, Response, redirect, url_for, request, abort, render_template
from flask_login import LoginManager, UserMixin, login_required, login_user, logout_user, current_user
import sqlalchemy
from sqlalchemy.sql import select, text
from dateutil.parser import parse
app = Flask(__name__)
#config
app.config.update(
DEBUG = True,
SECRET_KEY = 'secret_xxx',
SESSION_TYPE = 'memcached'
)
db_engine = {}
db_metadata = {}
meals = {}
users = {}
class User(UserMixin):
def __init__(self, name):
self.name = name
self.id = name
self.user_id = -1
@staticmethod
def get(name):
if name not in users:
users[name] = User(name)
return users[name]
def connect(user, password, db, host='localhost', port=5432):
url = 'postgresql://{}:{}@{}:{}/{}'
url = url.format(user, password, host, port, db)
con = sqlalchemy.create_engine(url, client_encoding='utf8')
meta = sqlalchemy.MetaData(bind=con, reflect=True)
return con, meta
def getLeaderboard():
s = 'select u.username as name, u.score as score, max(m.meal_date) as last_meal from users as u left join meals as m on m.kuk = u.id group by u.id order by score, last_meal;'
r = db_engine.execute(text(s))
leaders=[]
for row in r:
leaders.append(dict(row))
r.close()
return leaders
def getUpcomingMeals():
# meals = []
# meals.append({'id':1, 'kuk':'davide', 'eaters':['marek','sven','wille'], 'flavor_text':'Pizza', 'date':'Tuesday 21st of November', 'selection_deadline':'23 hours 14 minutes', 'status':0})
# meals.append({'id':2, 'kuk':'marek', 'eaters':['davide','sven','david', 'wille'], 'flavor_text':'Grzybowa', 'date':'Friday 23rd of November', 'selection_deadline':'3 Days 23 hours', 'status':0})
# meals.append({'id':2, 'kuk':'marek', 'eaters':['davide','sven','david', 'wille'], 'flavor_text':'Grzybowa', 'date':'Friday 23rd of November', 'selection_deadline':'3 Days 23 hours', 'status':0})
# meals.append({'id':2, 'kuk':'marek', 'eaters':['davide','sven','david', 'wille'], 'flavor_text':'Grzybowa', 'date':'Sunday 25rd of November', 'selection_deadline':'3 Days 23 hours', 'status':0})
# meals.append({'id':2, 'kuk':'marek', 'eaters':['davide','sven','david', 'wille'], 'flavor_text':'Grzybowa', 'date':'Sunday 25rd of November', 'selection_deadline':'3 Days 23 hours', 'status':0})
# meals.append({'id':2, 'kuk':'marek', 'eaters':['davide','sven','david', 'wille'], 'flavor_text':'Grzybowa', 'date':'Monday 26rd of November', 'selection_deadline':'3 Days 23 hours', 'status':0})
query = 'select username as kuk, meal_date, array_agg as eaters, selection_deadline from (select kuk, meal_date, selection_deadline, array_agg(username) from meals join users on users.id = any(meals.eaters) where meals.status=0 group by meals.id order by meal_date) as foo join users on kuk=users.id;'
r = db_engine.execute(text(query))
meals = []
for row in r:
meals.append(dict(row))
seconds_to_deadline = (meals[-1]['selection_deadline'] - datetime.datetime.now()).total_seconds()
if seconds_to_deadline < 0:
meals[-1]['selection_deadline'] = 'Deadline passed'
elif seconds_to_deadline > 3600:
hours_td = round(seconds_to_deadline / 3600)
days_td = int(hours_td / 24)
hours_td = hours_td % 24
meals[-1]['selection_deadline'] = str(days_td) + ' days ' + str(hours_td) + ' hours'
else:
meals[-1]['selection_deadline'] = str(round(seconds_to_deadline / 60)) + ' minutes'
meals[-1]['meal_time'] = meals[-1]['meal_date'].strftime('%H:%M')
meals[-1]['meal_date'] = meals[-1]['meal_date'].strftime('%A %d %B')
meals[-1]['candidate'] = 'davide'
r.close()
return meals
# adding to meal
@app.route("/addme")
@login_required
def addme():
meal_id = request.args.get('meal')
query = 'select :user_id = any (eaters) from meals where id =:meal_id;'
r = db_engine.execute(text(query), user_id=current_user.user_id, meal_id = meal_id)
results = []
for row in r:
results.append(dict(row))
if 1==1:
return render_template('appresponse.html', message='Have a nice meal ' + meal_id + " mister " + str(current_user.name) )
else:
return render_template('appresponse.html', message='Only one meal per person!')
@app.route('/')
@login_required
def index():
return render_template('meal_list.html', leaderboard=getLeaderboard(), meals=getUpcomingMeals())
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
r = db_engine.execute(text('select id from users where username=:username and password=:password'), username=username, password=password)
result = []
for row in r:
result.append(dict(row))
r.close()
print(len(users))
if len(result) > 0:
u = User.get(username)
u.user_id = result[0]['id']
login_user(u)
return redirect(request.args.get("next"))
return abort(401)
else:
return Response('''
<form action="" method="post">
<p><input type=text name=username>
<p><input type=password name=password>
<p><input type=submit value=Login>
</form>
''')
with open('admin.json') as f:
postgres_credentials = json.load(f)
db_engine, db_metadata = connect(postgres_credentials['username'], postgres_credentials['password'], 'kuk_app')
meals = sqlalchemy.Table('meals', db_metadata)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "login"
# somewhere to logout
@app.route("/logout")
@login_required
def logout():
logout_user()
return Response('<p>Logged out</p>')
# handle login failed
@app.errorhandler(401)
def page_not_found(e):
return Response('<p>Login failed</p>')
# callback to reload the user object
@login_manager.user_loader
def load_user(userid):
return User.get(userid)
if __name__ == '__main__':
app.run('0.0.0.0')