matekasse/Website/__init__.py
2023-11-25 00:14:51 +01:00

405 lines
No EOL
17 KiB
Python

import queue, time, uuid, json, logging, datetime, os
from flask import Flask, render_template, request, make_response, session, send_file, g
from flask_socketio import SocketIO, join_room, leave_room
from flask_session import Session
from markupsafe import escape
from .db import get_db
from datetime import datetime
#flask_config
DATABASE = './Website/mate.db'
#def create_logs(app):
# now = datetime.datetime.now().strftime('%d-%m-%Y-%H-%M-%S')
# logging.basicConfig(filename=f"logs/matekasse-{now}.log",filemode='w', format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ,encoding='utf-8', level=logging.INFO)
# app.logger = logging.getLogger('db')
#
# app.logger.info("Website is starting")
def log(type=None, userid=None, before=None, after=None):
db = get_db()
c = db.cursor()
c.execute("INSERT or IGNORE INTO transaction_log (timestamp, userid, type, before, after) VALUES (?, ?, ?, ?, ?)", [datetime.now(), userid, type, before, after])
db.commit()
db.close()
def create_app(test_config=None):
app = Flask(__name__)
key = str(uuid.uuid4().hex)
if test_config is None:
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SECRET_KEY'] = key
app.config['DATABASE'] = DATABASE
else:
app.config.from_mapping(test_config)
try:
os.makedirs(app.instance_path)
except OSError:
pass
#with app.app_context():
# create_logs(app)
Session(app)
socketio = SocketIO(app)
#@app.teardown_appcontext
#def close_connection(exception):
# db = getattr(g, '_database', None)
# if db is not None:
# db.close()
# app.logger.info("Website exited")
#var
user_queue = queue.Queue()
#website
@app.route('/favicon.ico')
def favicon():
return send_file("../static/Logo_CCC.svg.png")
#@app.route('/socket.io.js')
#def socketiojs():
# return url_for('static', filename='socket.io.js')
@app.route("/")
def index():
return """
<a href="/list">user and tag list</a>
<p>The creator of this website accepts no liability for any linguistic or technical errors!</p>
<br style="line-height: 500%;"></br>
<a href="/documentation">Doumentation</a><script src="/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous">
</script>
<script type="text/javascript" charset="utf-8">
window.location="/list"
</script>
"""
@app.route("/list")
def list():
db = get_db()
c = db.cursor()
c.execute("SELECT * FROM users")
users = c.fetchall()
text = ""
for i in users:
text = text + f'<p><a href="list/user?id={i[0]}">{escape(i[1])}</a>: {i[2]}€ <form action="/change" method="post"><input name="id" type="hidden" value="{i[0]}"> <input name="change" type="number" step="0.1" placeholder="add to balance"></form></p> <br style="line-height: 50%;"></br>'
return '''<!DOCTYPE html>
<html lang="en">
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
var socket = io();
socket.on("update", function(){
window.location="http://matekasse.server.c3h/list"
});
</script>
<title>Strichliste</title>
<p><a href="/list">user and tag list</a> | <a href="/documentation">Documentation</a></p>
<form action="/list/user" method="get"><input name="user" type="search" placeholder="Search for user"><button>Search</button></form>
<form action="/adduser" method="post"><button type="submit">Add User</button></form>
<br></br>
''' + text + '</html>'
@app.route("/transactionlist")
def transactionlist():
db = get_db()
c = db.cursor()
text = ""
c.execute("SELECT * FROM transaction_log ORDER BY ROWID DESC LIMIT 100")
transactionlist = c.fetchall()
for i in transactionlist:
text = text + f"<p>{i[0]} userid: {i[1]} {i[2]} {i[3]} to {i[4]}</p>"
return text
@app.route("/list/user", methods=['GET'])
def user_info():
db = get_db()
c = db.cursor()
id = request.args.get("id")
c.execute(f"SELECT * FROM users WHERE id=?", [id])
user_list = c.fetchall()
if user_list != []:
user = user_list[0]
c.execute(f"SELECT * FROM tags WHERE userid={user[0]}")
tags = c.fetchall()
text = ""
for tag in tags:
text = text + f"<p>{tag[0]}</p>"
return f"""<!DOCTYPE html>
<html lang="en">
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
var socket = io();
""" + 'socket.on("update", function(){ window.location="http://matekasse.server.c3h/list/user?id=' + id + '"});' + f"""
</script>
<title>{escape(user[1])}</title>
<p><a href="/list">user and tag list</a> | <a href="/documentation">Documentation</a></p>
<p> {escape(user[1])} : {user[2]}€ <p>
<form action="/addtag" method="post"><input name="id" type="hidden" value="{user[0]}"><button type="submit">Add Tag</button></form>
<form action="/removetag" method="post"><input name="id" type="hidden" value="{user[0]}"><button type="submit">Remove Tag</button></form>
</p><form action="/change" method="post"><input name="id" type="hidden" value="{user[0]}"> <input name="change" type="number" step="0.1" placeholder="change balance"></form>
</p>
<br></br>
<p>Tags:</p>
{text}
<br></br>
<form action="/removeuser" method="post"><input name="id" type="hidden" value="{user[0]}"><button type="submit">Remove User</button></form>
</html>
"""
else:
return render_template("error.html", error_code="043")
@app.route("/adduser", methods=['POST'])
def new_user():
return render_template("adduser.html")
@app.route("/removeuser", methods=['POST'])
def remove_user():
db = get_db()
c = db.cursor()
user_id = request.form["id"]
c.execute(f"SELECT * FROM users WHERE id=?", [user_id])
users = c.fetchall()
if users != []:
user_name = users[0][1]
c.execute(f"DELETE FROM tags WHERE userid=?", [user_id])
app.logger.info(f"Deleted all tags from user ?", [user_id])
c.execute(f"DELETE FROM users WHERE id=?", [user_id])
db.commit()
log(type="removeuser", userid=user_id, before=user_name)
socketio.emit("update", "update")
return f'<title>remove user</title><p><p><a href="/list">user and tag list</a> | <a href="/documentation">Documentation</a></p> <p>Deleted user {escape(user_name)}</p><a href="/list">return to the tags and user list</a></p>'
else:
return render_template("error.html", error_code="043")
@app.route("/adduser/user", methods=['POST'])
def adduser():
db = get_db()
c = db.cursor()
username = request.form["username"]
if username == None:
return render_template("error.html", error_code="418")
c.execute("SELECT * FROM users WHERE username=?", [username])
if c.fetchall() == []:
c.execute("INSERT or IGNORE INTO users (username, balance) VALUES (?, 0)", [username])
db.commit()
socketio.emit("update", "update")
c.execute(f"SELECT * FROM users WHERE username=?", [username])
user = c.fetchone()
log(type="adduser", userid=user[0], after=user[1])
return """<html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
window.location="/list";
</script>
<p>tag was sucsesfully added</p>
</html>
"""
else:
return render_template("error.html", error_code="757")
@app.route("/change", methods=['POST'])
def change():
db = get_db()
c = db.cursor()
try:
user_id = request.form["id"]
change = float(request.form["change"])
except:
return render_template("error.html", error_code="095")
c.execute(f"SELECT * FROM users WHERE id=?", [user_id])
users = c.fetchall()
if users != []:
balance_old = users[0][2]
c.execute(f"UPDATE users SET balance = balance + {change} WHERE id={user_id}")
db.commit()
c.execute(f"SELECT * FROM users WHERE id={user_id}")
user = c.fetchone()
log(type="balance", userid=user[0], before=balance_old, after=user[2])
socketio.emit("update", "update")
return """<html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
window.location="/list";
</script>
</html>
"""
else:
return render_template("error.html", error_code="043")
@app.route("/addtag", methods=['POST'])
def get_addtag_request():
try:
user_id = int(request.form["id"])
except: #except im Normalen Code!
return render_template("error.html", error_code="095")
session_id = uuid.uuid4()
session[id] = session_id
user_queue.put([user_id, "add", session_id])
return render_template("addtag.html", user=user_id)
@socketio.on('addtag')
def request_addtag(data):
global finished
global message
join_room(session[id])
if len(user_queue.queue) > 0:
user = user_queue.queue[0]
if user == [data["data"], "add", session[id]]:
socketio.emit("wait", "wait", to=session[id])
i = 0
while finished != [data["data"], "add", session[id]]:
time.sleep(1)
i += 1
if i > 20:
socketio.emit("error", "352", to=session[id])
notimportant = user_queue.get()
break
else:
finished = None
socketio.emit("finished", f"{message}", to=session[id])
else:
socketio.emit("busy", "busy", to=session[id])
else:
socketio.emit("error", "418", to=session[id])
leave_room(session[id])
@app.route("/removetag", methods=['POST'])
def get_removetag_request():
try:
user_id = int(request.form["id"])
except: #except im Normalen Code!
return render_template("error.html", error_code="043")
session_id = uuid.uuid4()
session[id] = session_id
user_queue.put([user_id, "remove", session_id])
return render_template("removetag.html", user=user_id)
@socketio.on('removetag')
def request_removetag(data):
global finished
global message
join_room(session[id])
if len(user_queue.queue) > 0:
queue_item = user_queue.queue[len(user_queue.queue) - 1]
user = queue_item[0]
if queue_item == [data["data"], "remove", session[id]]:
socketio.emit("wait", "wait", to=session[id])
i = 0
while finished != [data["data"], "remove", session[id]]:
time.sleep(1)
i += 1
if i > 20:
socketio.emit("error", "352", to=session[id])
notimportant = user_queue.get()
break
else:
finished = None
socketio.emit("finished", f"{message}", to=session[id])
else:
socketio.emit("busy", "busy", to=session[id])
else:
socketio.emit("error", "418", to=session[id])
leave_room(session[id])
#api
@app.route("/api/change", methods=['GET'])
def api_change():
db = get_db()
c = db.cursor()
userid = request.args.get("id")
c.execute("SELECT * FROM users WHERE id=?", [userid])
user_list = c.fetchall()
if user_list != []:
user = user_list[0]
try:
change = int(request.args.get("change"))
except:
change = -1
c.execute(f"UPDATE users SET balance = balance + {change} WHERE id={user[0]}")
db.commit()
c.execute(f"SELECT * FROM users WHERE id = {userid}")
user_new = c.fetchone()
log(type="balance", userid=user[0], before=user[2], after=user_new[2])
socketio.emit("update", "update")
return make_response(json.dumps({"mode":"balance", "username":user[1], "balance":user_new[2]}))
else:
return make_response(json.dumps({"mode":"error","error":"043"}))
@app.route("/api/tag_id", methods=['GET'])
def get_id():
global finished
global message
db = get_db()
c = db.cursor()
tag_id = request.args.get("id")
c.execute(f"SELECT * FROM tags WHERE tagid=?", [tag_id])
tag_list = c.fetchall()
if user_queue.qsize() > 0:
queue_item = user_queue.get()
user = queue_item[0]
state = queue_item[1]
c.execute(f"SELECT * FROM users WHERE id=?", [user])
user = c.fetchall()
user_id = user[0]
username = user[1]
if state == "add":
c.execute(f"SELECT * FROM tags WHERE tagid={tag_id}")
if c.fetchall() != []:
message = "Error: 170"
finished = queue_item
return make_response(json.dumps({"mode":"error","error":"170"}))
else:
c.execute(f"INSERT OR IGNORE INTO tags (tagid, userid) VALUES ({tag_id}, ?)", [user])
db.commit()
log(type="addtag", userid=user_id ,after=tag_id)
finished = queue_item
return make_response(json.dumps({"mode":"message","username":"{}".format(username),"message":"A tag was added"}))
elif state == "remove":
c.execute(f"SELECT * FROM tags WHERE (tagid = {tag_id} AND userid = ?)", [user])
tags = c.fetchall()
if tags != []:
c.execute(f"DELETE FROM tags WHERE (tagid = {tag_id} AND userid = ?)", [user])
db.commit()
log(type="removetag", userid=user_id, before=tag_id)
finished = queue_item
return make_response(json.dumps({"mode":"message","username":"{}".format(username),"message":"A tag was removed"}))
else:
message = "054"
finished = queue_item
return make_response(json.dumps({"mode":"error","error":"054"}))
finished = queue_item
socketio.emit("update", "update")
return make_response(json.dumps({"mode":"error","error":"418"}))
elif tag_list != []:
tag = tag_list[0]
c.execute(f"SELECT * FROM users WHERE id={tag[1]}")
user_list = c.fetchall()
if user_list != []:
balance_old = user_list[0][2]
if user_queue.qsize() == 0:
c.execute(f"UPDATE users SET balance = balance - 1.5 WHERE id={tag[1]}")
db.commit()
c.execute(f"SELECT * FROM users WHERE id={tag[1]}")
user = c.fetchone()
log(type="balance", userid=user[0], before=balance_old, after=user[2])
socketio.emit("update", "update")
return make_response(json.dumps({"mode":"balance", "username":user[1], "balance":user[2]}))
else:
return make_response(json.dumps({"mode":"error", "error":"043"}))
socketio.emit("update", "update")
return make_response(json.dumps({"mode":"error","error":"054"}))
#Documentation
@app.route("/documentation")
def documentation():
return render_template("documentation.html")
return {"app":app,"socketio":socketio}