1
0
Fork 0
forked from bton/matekasse

Compare commits

..

83 commits

Author SHA1 Message Date
d306e0a7a1 Merge pull request 'trans' (#42) from origin/transaction_between_user into master
Reviewed-on: bton/matekasse#42
2024-11-13 19:53:05 +00:00
baf7277247 added the trans to the fare 2024-11-13 20:10:32 +01:00
ac400f9db7 Merge pull request 'origin/transaction_between_user' (#41) from origin/transaction_between_user into master
Reviewed-on: anton/matekasse#41
2024-10-04 19:48:17 +00:00
f6e8383a57 added min and max to change 2024-09-18 22:56:03 +02:00
2357d37228 changed smth? 2024-09-18 22:32:25 +02:00
379f8b1fd3 changed a float error 2024-09-18 22:29:02 +02:00
3c87a971ea added a function to transfare money between two user 2024-09-18 22:25:50 +02:00
e5bdad65df Merge pull request 'KA CHING!' (#39) from nmeum/matekasse:ka-ching into master
Reviewed-on: anton/matekasse#39
2024-09-11 17:00:50 +00:00
Sören Tempel
71ddc32f49 KA CHING! 2024-09-09 10:12:24 +02:00
cfafd0e148 typo 2024-06-05 22:02:16 +02:00
b8f54c497e added filter fpr length in list and transactionlist 2024-06-05 21:57:30 +02:00
a6dd6310b7 transaction list as template 2024-06-05 21:26:17 +02:00
efff31aa27 transaction list as template 2024-06-05 21:26:00 +02:00
a31337f0f2 max and min value in user 2024-06-02 12:52:09 +02:00
14624a4f6e limit ui 2024-06-01 22:04:26 +02:00
79a31ab6d5 Added max and min value for the change input (in the html code) 2024-05-25 10:54:05 +02:00
9c7f2cd0cb fixed somthing I hope 2024-03-29 19:57:11 +01:00
03654ac4cf fixed 2024-03-20 20:02:11 +01:00
ed8bd817b7 fixed 2024-03-20 20:01:37 +01:00
404e292450 fixed 2024-03-20 20:01:00 +01:00
fbe6b45050 fixed 2024-03-20 19:58:02 +01:00
cdbcbea91a deleted non used file 2024-03-20 19:53:16 +01:00
be77d21577 Merge branch 'master' of ssh://hannover.ccc.de:3071/anton/matekasse 2024-03-20 00:19:46 +01:00
960f79f8e5 removed matekasse.server.c3h 2024-03-19 23:59:40 +01:00
8387b6ccba removet matekasse.server.c3h 2024-03-19 23:54:51 +01:00
dd9e3463c9 Transaction log without time 2024-03-19 23:52:49 +01:00
e76e5beae7 there where still some safe 2024-03-13 21:49:23 +01:00
6b70c563b5 - 2024-03-13 21:31:51 +01:00
5ab0b3db7d - 2024-03-13 21:22:57 +01:00
069efb54f2 ( 2024-03-13 21:20:45 +01:00
22d441a1c0 escape kram wieder rückgängig machen 2024-03-13 21:10:34 +01:00
437a7e596c log statements 2024-03-13 20:50:34 +01:00
657c500f24 Ahhhhhhhhhhhhhhhh 2024-03-13 19:29:15 +01:00
f6c06771dd Ahhhhhhhhhhh 2024-03-13 19:27:45 +01:00
6f0edf0feb Ahhhh 2024-03-13 19:26:21 +01:00
ce8acc10b1 fixed stuff 2024-03-06 21:54:57 +01:00
5e9e584f04 added escape 2024-03-06 21:45:02 +01:00
f4a1cb8369 added escape 2024-03-06 21:44:02 +01:00
f8dc320735 added escape 2024-03-06 21:41:49 +01:00
04fd8a20c2 added escape 2024-03-06 21:38:53 +01:00
ff0c91e3e8 added escape 2024-03-06 21:35:34 +01:00
3127e2de1f added escape 2024-03-06 21:31:00 +01:00
c86b91a246 removed escape 2024-03-06 21:27:12 +01:00
f4181ade07 Was Commite ich hier? 2024-03-06 20:43:48 +01:00
f691e7534d AHHH escape 2024-03-06 20:41:45 +01:00
364dfb69b6 Merge pull request 'add css / wolkenflattern wegwerfen' (#34) from 33_schoeeeener into master
Reviewed-on: https://hannover.ccc.de/gitlab/anton/matekasse/pulls/34
2024-03-06 18:17:45 +00:00
64ce118f80 add static socket.io.js 2024-03-06 19:03:13 +01:00
389c14358e add css / wolkenflattern wegwerfen 2024-03-06 19:03:06 +01:00
ce009a278b new db system 2024-03-01 21:59:30 +01:00
7f1f908961 ahh 2024-02-25 17:54:51 +01:00
dc71f8dcf4 ahh 2024-02-25 17:53:25 +01:00
0147e61c6b Es muss im Stable getestet werden 2024-02-25 17:36:36 +01:00
ac907638e6 log und so 2024-02-25 17:24:44 +01:00
5cb4dcc533 float errors fixed 2024-02-24 00:14:43 +01:00
64e0c340c3 removed print 2024-02-23 23:57:54 +01:00
a8fec178e6 fixed number errors 2024-02-23 23:57:31 +01:00
389e6ffcee AHHHHH 2024-02-23 22:49:25 +01:00
1a51402170 float to int 2024-02-23 22:47:12 +01:00
701d9c2f1e main wurde gesäubert 2024-02-22 00:19:59 +01:00
ccb4d64cde Updated README 2024-02-22 00:04:59 +01:00
34eb392ce0 doch nicht 2024-02-21 23:36:32 +01:00
109f7eb4c2 removed lines from main.py 2024-02-21 23:33:32 +01:00
42b8a774ea Merge pull request 'könnte so klappen' (#32) from 31_templates_vereinfachen into master
Reviewed-on: https://hannover.ccc.de/gitlab/anton/matekasse/pulls/32
2024-02-21 22:30:36 +00:00
1f227df358 hupsala noch was vergessen 2024-02-21 22:13:24 +01:00
19fbecda56 könnte so klappen 2024-02-21 22:02:07 +01:00
727617e2be main 2024-02-21 18:54:55 +01:00
75081d5020 , and . 2024-02-20 18:11:23 +01:00
ef43f79ff4 typo 2024-02-20 18:05:43 +01:00
8d25e0b645 main.py wird doch gebraucht 2024-02-20 18:05:14 +01:00
d55b7c5aea balance get api 2024-02-20 17:33:56 +01:00
55124040ae fixed the README 2024-02-17 02:16:49 +01:00
66babf1b2c delted stuff 2024-02-17 02:14:08 +01:00
5179ec792c jinja 2024-02-17 02:12:27 +01:00
2432eed1ae Doc repariert 2024-02-16 23:11:12 +01:00
fd5fd4d78c -1.5€ Button und preis var 2024-02-16 22:51:32 +01:00
64580f02cb New error 2024-02-16 21:19:11 +01:00
56aa79378b Doc Input Error 2024-02-16 19:54:32 +01:00
e9acd07fb4 test 2024-02-14 20:52:50 +01:00
e11512f458 1 ct 2023-12-20 19:47:38 +01:00
f927a70f60 removed get method from /api/change 2023-12-02 18:14:34 +01:00
3832282101 change balance next to balance 2023-12-02 17:27:36 +01:00
d9aff6a56a Documentation api to post 2023-12-01 23:23:11 +01:00
fda3f58cca Merge pull request 'Update Website/templates/documentation.html' (#22) from j3d1/matekasse:j3d1-patch-1 into master
Reviewed-on: https://hannover.ccc.de/gitlab/anton/matekasse/pulls/22
2023-12-01 16:38:39 +00:00
26 changed files with 6585 additions and 283 deletions

2
.gitignore vendored
View file

@ -1,5 +1,4 @@
*.db *.db
socket.io.js
__pycache__/ __pycache__/
logs/* logs/*
venv/* venv/*
@ -11,3 +10,4 @@ flask_session/
/test/flask_session/ /test/flask_session/
/Website/__pycache__/ /Website/__pycache__/
/Website/.pytest_cache/ /Website/.pytest_cache/
/.idea

4
README
View file

@ -5,8 +5,6 @@ How to get started:
source venv/bin/activate source venv/bin/activate
install requiremens: install requiremens:
pip install -r requirements.txt pip install -r requirements.txt
create the log folder:
mkdir logs
start the program: start the program:
python main.py venv/bin/gunicorn -b "127.0.0.1:5000" -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 main:app
You can now accses the Website on http://127.0.0.1:5000 You can now accses the Website on http://127.0.0.1:5000

View file

@ -1,27 +1,21 @@
import queue, time, uuid, json, logging, datetime, os import queue, time, uuid, json, logging, datetime, os
from flask import Flask, render_template, request, make_response, session, send_file, g from flask import Flask, render_template, render_template_string, request, make_response, session, send_file, g
from flask_socketio import SocketIO, join_room, leave_room from flask_socketio import SocketIO, join_room, leave_room
from flask_session import Session from flask_session import Session
from markupsafe import escape from Website.db import get_db
from .db import get_db import Website.db as db_handler
from datetime import datetime from datetime import datetime
finished = None finished = None
preis = -150 #Ein Getraenk
#flask_config #flask_config
DATABASE = './Website/mate.db' DATABASE = './Website/mate.db'
#def create_logs(app): def limit_length(text, length=50):
# now = datetime.datetime.now().strftime('%d-%m-%Y-%H-%M-%S') if type(text) != str:
# 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) text = str(text)
# app.logger = logging.getLogger('db') if len(text) > length:
# return f"{text[:(length -3)]}..."
# app.logger.info("Website is starting") return text
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()
def create_app(test_config=None): def create_app(test_config=None):
app = Flask(__name__) app = Flask(__name__)
@ -30,15 +24,15 @@ def create_app(test_config=None):
app.config['SESSION_TYPE'] = 'filesystem' app.config['SESSION_TYPE'] = 'filesystem'
app.config['SECRET_KEY'] = key app.config['SECRET_KEY'] = key
app.config['DATABASE'] = DATABASE app.config['DATABASE'] = DATABASE
app.jinja_env.filters['limit_length'] = limit_length
else: else:
app.config.from_mapping(test_config) app.config.from_mapping(test_config)
try: try:
os.makedirs(app.instance_path) os.makedirs(app.instance_path)
except OSError: except OSError:
pass pass
#with app.app_context():
# create_logs(app)
Session(app) Session(app)
socketio = SocketIO(app) socketio = SocketIO(app)
@ -48,32 +42,32 @@ def create_app(test_config=None):
# db = getattr(g, '_database', None) # db = getattr(g, '_database', None)
# if db is not None: # if db is not None:
# db.close() # db.close()
# app.logger.info("Website exited") # appt.logger.info("Website exited")
#var #var
user_queue = queue.Queue() user_queue = queue.Queue()
#website #website
@app.route('/favicon.ico') @app.route('/favicon.ico')
@app.route('/ccc_logo.png')
def favicon(): def favicon():
return send_file("../static/Logo_CCC.svg.png") return send_file("../static/Logo_CCC.svg.png")
#@app.route('/socket.io.js') @app.route('/socket.io.js')
#def socketiojs(): def socketiojs():
# return url_for('static', filename='socket.io.js') return send_file('../static/socket.io.js')
@app.route('/ka-ching.wav')
def kaching():
return send_file('../static/ka-ching.wav')
@app.route('/new.css')
def newcss():
return send_file('../static/new.min.css')
@app.route("/") @app.route("/")
def index(): def index():
return """ return render_template("index.html")
<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") @app.route("/list")
def list(): def list():
@ -81,35 +75,57 @@ def create_app(test_config=None):
c = db.cursor() c = db.cursor()
c.execute("SELECT * FROM users") c.execute("SELECT * FROM users")
users = c.fetchall() users = c.fetchall()
text = "" return render_template("list.html", users=users, preis=(preis/100), min_value=-50000)
for i in users:
text = text + f'<p><a href="list/user?id={i[0]}">{escape(i[1])}</a>: {i[2]/100}€ <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") @app.route("/transactionlist")
def transactionlist(): def transactionlist():
db = get_db() db = get_db()
c = db.cursor() c = db.cursor()
text = "" action_list = []
c.execute("SELECT * FROM transaction_log ORDER BY ROWID DESC LIMIT 100") c.execute("SELECT * FROM transaction_log ORDER BY ROWID DESC LIMIT 1000")
transactionlist = c.fetchall() transactionlist = c.fetchall()
for i in transactionlist: for i in transactionlist:
text = text + f"<p>{i[0]} userid: {i[1]} {i[2]} {i[3]} to {i[4]}</p>" action = {
return text "statement":i[0],
"user_id":i[1],
"before":i[2],
"after":i[3],
"change":i[4]
}
if action["statement"] == "balance":
action["reverse_statement"] = "balance"
action["reverse_user_id"] = action["user_id"]
action["reverse_before"] = None
action["reverse_after"] = None
action["reverse_change"] = action["change"] *(-1)
elif action["statement"] == "add_user":
action["reverse_statement"] = "remove_user"
action["reverse_user_id"] = action["user_id"]
action["reverse_before"] = action["after"]
action["reverse_after"] = None
action["reverse_change"] = None
elif action["statement"] == "remove_user":
action["reverse_statement"] = "add_user"
action["reverse_user_id"] = action["user_id"]
action["reverse_before"] = None
action["reverse_after"] = action["before"]
action["reverse_change"] = None
elif action["statement"] == "add_tag":
action["reverse_statement"] = "remove_tag"
action["reverse_user_id"] = action["user_id"]
action["reverse_before"] = action["after"]
action["reverse_after"] = None
action["reverse_change"] = None
elif action["statement"] == "remove_tag":
action["reverse_statement"] = "add_tag"
action["reverse_user_id"] = action["user_id"]
action["reverse_before"] = None
action["reverse_after"] = action["before"]
action["reverse_change"] = None
else:
raise Exception(statement)
action_list.append(action)
return render_template("transactionlist.html", action_list=action_list)
@app.route("/list/user", methods=['GET']) @app.route("/list/user", methods=['GET'])
def user_info(): def user_info():
@ -117,41 +133,18 @@ def create_app(test_config=None):
c = db.cursor() c = db.cursor()
id = request.args.get("id") id = request.args.get("id")
c.execute(f"SELECT * FROM users WHERE id=?", [id]) c.execute(f"SELECT * FROM users WHERE id=?", [id])
user_list = c.fetchall() user = c.fetchone()
if user_list != []: if user != None :
user = user_list[0]
c.execute(f"SELECT * FROM tags WHERE userid={user[0]}") c.execute(f"SELECT * FROM tags WHERE userid={user[0]}")
tags = c.fetchall() tags = c.fetchall()
text = "" return render_template("user.html", user=user, tags=tags, min_value=-50000)
for tag in tags:
text = text + f'<p><form action="/removetag" method="post"><label for="removetag">{tag[0]} </label><input name="id" type="hidden" value="{user[0]}"><input name="tagid" type="hidden" value="{tag[0]}"><button id="removetag" type="submit">Remove Tag</button></form> </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])} : {escape(user[2]/100)} <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: else:
return render_template("error.html", error_code="043") return render_template("error.html", error_code="043")
@app.route("/adduser", methods=['POST']) @app.route("/adduser", methods=['POST'])
def new_user(): def new_user():
return render_template("adduser.html") return render_template("adduser.html")
@app.route("/removeuser", methods=['POST']) @app.route("/removeuser", methods=['POST'])
def remove_user(): def remove_user():
@ -159,16 +152,12 @@ def create_app(test_config=None):
c = db.cursor() c = db.cursor()
user_id = request.form["id"] user_id = request.form["id"]
c.execute(f"SELECT * FROM users WHERE id=?", [user_id]) c.execute(f"SELECT * FROM users WHERE id=?", [user_id])
users = c.fetchall() user = c.fetchone()
if users != []: if user != None:
user_name = users[0][1] user_name = user[1]
c.execute(f"DELETE FROM tags WHERE userid=?", [user_id]) db_handler.remove_user(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") 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>' return render_template("removeuser.html", user_name=user_name)
else: else:
return render_template("error.html", error_code="043") return render_template("error.html", error_code="043")
@ -181,20 +170,11 @@ def create_app(test_config=None):
return render_template("error.html", error_code="418") return render_template("error.html", error_code="418")
c.execute("SELECT * FROM users WHERE username=?", [username]) c.execute("SELECT * FROM users WHERE username=?", [username])
if c.fetchall() == []: if c.fetchall() == []:
c.execute("INSERT or IGNORE INTO users (username, balance) VALUES (?, 0)", [username]) db_handler.add_user(username)
db.commit()
socketio.emit("update", "update") socketio.emit("update", "update")
c.execute(f"SELECT * FROM users WHERE username=?", [username]) c.execute(f"SELECT * FROM users WHERE username=?", [username])
user = c.fetchone() user = c.fetchone()
log(type="adduser", userid=user[0], after=user[1]) return render_template("redirect.html")
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: else:
return render_template("error.html", error_code="757") return render_template("error.html", error_code="757")
@ -205,27 +185,16 @@ def create_app(test_config=None):
c = db.cursor() c = db.cursor()
try: try:
user_id = request.form["id"] user_id = request.form["id"]
change = float(request.form["change"]) change = int(float(request.form["change"]) * float(100))
print(change)
except: except:
return render_template("error.html", error_code="095") return render_template("error.html", error_code="095")
c.execute(f"SELECT * FROM users WHERE id=?", [user_id]) c.execute(f"SELECT * FROM users WHERE id=?", [user_id])
users = c.fetchall() users = c.fetchall()
if users != []: if users != []:
balance_old = users[0][2] balance_old = users[0][2]
c.execute(f"UPDATE users SET balance = balance + {change*100} WHERE id={user_id}") db_handler.change_balance(user_id, change)
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") socketio.emit("update", "update")
return """<html> return render_template("redirect.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: else:
return render_template("error.html", error_code="043") return render_template("error.html", error_code="043")
@ -285,17 +254,9 @@ def create_app(test_config=None):
c = db.cursor() c = db.cursor()
c.execute(f"SELECT * FROM tags WHERE (tagid = ? AND userid = ?)", [tag_id, user_id]) c.execute(f"SELECT * FROM tags WHERE (tagid = ? AND userid = ?)", [tag_id, user_id])
if c.fetchall != []: if c.fetchall != []:
c.execute(f"DELETE FROM tags WHERE (tagid = ? AND userid = ?)", [tag_id, user_id]) db_handler.remove_tag(tag_id)
db.commit()
message = f"Removed {tag_id} from user {user_id}" message = f"Removed {tag_id} from user {user_id}"
log(type="removetag", userid=user_id, before=tag_id) return render_template("redirect.html")
return f"""
<html>
<script>
window.location="/"
</script>
</html>
"""
else: else:
return render_template("error.html", error_code="054") return render_template("error.html", error_code="054")
@ -326,44 +287,75 @@ def create_app(test_config=None):
socketio.emit("error", "418", to=session[id]) socketio.emit("error", "418", to=session[id])
leave_room(session[id]) leave_room(session[id])
#api @app.route("/transfare")
@app.route("/api/change", methods=['GET', 'POST']) def transfare():
def api_change():
db = get_db() db = get_db()
c = db.cursor() c = db.cursor()
try: c.execute("SELECT * FROM users")
userid = request.form["id"]
except:
userid = request.args.get("id")
c.execute("SELECT * FROM users WHERE id=?", [userid])
user_list = c.fetchall() user_list = c.fetchall()
if user_list != []: return render_template("transfare.html", user_list=user_list)
user = user_list[0]
try: @app.route("/api/transfare", methods=['POST'])
change = int(request.args.get("change")) def api_transfare():
except: db = get_db()
change = -1.5 c = db.cursor()
c.execute(f"UPDATE users SET balance = balance + {change*100} WHERE id={user[0]}") transfare_from = request.form["transfarefrom"]
db.commit() transfare_to = request.form["transfareto"]
c.execute(f"SELECT * FROM users WHERE id = {userid}") change = int(float(request.form["change"]) * float(100))
user_new = c.fetchone() c.execute("SELECT * FROM users WHERE id=?", [transfare_from])
log(type="balance", userid=user[0], before=user[2], after=user_new[2]) if c.fetchall() == []:
socketio.emit("update", "update") return render_template("error.html", error_code="043")
return make_response(json.dumps({"mode":"balance", "username":user[1], "balance":user_new[2]})) c.execute("SELECT * FROM users WHERE id=?", [transfare_to])
else: if c.fetchall() == []:
return make_response(json.dumps({"mode":"error","error":"043"})) return render_template("error.html", error_code="043")
db_handler.change_balance(transfare_from, -change)
db_handler.change_balance(transfare_to, change)
return render_template("redirect.html")
@app.route("/api/balance", methods=['POST', 'GET'])
def api_change():
if request.method == 'POST':
db = get_db()
c = db.cursor()
userid = request.form["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 = preis
db_handler.change_balance(userid, change)
socketio.emit("update", "update")
c.execute("SELECT * FROM users WHERE id=?",[userid])
return make_response(json.dumps({"mode":"balance", "username":user[1], "balance":c.fetchone()[2]}))
else:
return make_response(json.dumps({"mode":"error","error":"043"}))
elif request.method == 'GET':
db = get_db()
c = db.cursor()
userid = request.args.get("id")
c.execute("SELECT * FROM users WHERE id=?", [userid])
user = c.fetchone()
if user != None:
return make_response(json.dumps({"mode":"balance", "username":user[1], "balance":user[2]}))
else:
return make_response(json.dumps({"mode":"error", "error":"043"}))
@app.route("/api/tag_id", methods=['GET', 'POST'])
@app.route("/api/tag_id", methods=['POST'])
def get_id(): def get_id():
db = get_db()
c = db.cursor()
global finished global finished
global message global message
db = get_db()
c = db.cursor()
try: try:
tag_id = request.form["id"] tag_id = request.form["id"]
except: except:
tag_id = request.args.get("id") return make_response(json.dumps({"mode":"error", "error":"638"}))
c.execute(f"SELECT * FROM tags WHERE tagid=?", [tag_id]) c.execute(f"SELECT * FROM tags WHERE tagid=?", [tag_id])
tag_list = c.fetchall() tag_list = c.fetchall()
@ -383,20 +375,16 @@ def create_app(test_config=None):
finished = queue_item finished = queue_item
return make_response(json.dumps({"mode":"error","error":"170"})) return make_response(json.dumps({"mode":"error","error":"170"}))
else: else:
c.execute(f"INSERT OR IGNORE INTO tags (tagid, userid) VALUES ({tag_id}, ?)", [user_id]) db_handler.add_tag(user_id, tag_id)
db.commit()
message = f"Added {tag_id} to {username}" message = f"Added {tag_id} to {username}"
log(type="addtag", userid=user_id ,after=tag_id)
finished = queue_item finished = queue_item
return make_response(json.dumps({"mode":"message","username":"{}".format(username),"message":"A tag was added"})) return make_response(json.dumps({"mode":"message","username":"{}".format(username),"message":"A tag was added"}))
elif state == "remove": elif state == "remove":
c.execute(f"SELECT * FROM tags WHERE (tagid = {tag_id} AND userid = ?)", [user_id]) c.execute(f"SELECT * FROM tags WHERE (tagid = {tag_id} AND userid = ?)", [user_id])
tags = c.fetchall() tags = c.fetchall()
if tags != []: if tags != []:
c.execute(f"DELETE FROM tags WHERE (tagid = {tag_id} AND userid = ?)", [user_id])
db.commit() db.commit()
message = f"Removed {tag_id} from {username}" message = f"Removed {tag_id} from {username}"
log(type="removetag", userid=user_id, before=tag_id)
finished = queue_item finished = queue_item
return make_response(json.dumps({"mode":"message","username":"{}".format(username),"message":"A tag was removed"})) return make_response(json.dumps({"mode":"message","username":"{}".format(username),"message":"A tag was removed"}))
else: else:
@ -414,11 +402,9 @@ def create_app(test_config=None):
if user_list != []: if user_list != []:
balance_old = user_list[0][2] balance_old = user_list[0][2]
if user_queue.qsize() == 0: if user_queue.qsize() == 0:
c.execute(f"UPDATE users SET balance = balance - 150 WHERE id={tag[1]}") db_handler.change_balance(tag[1], preis)
db.commit()
c.execute(f"SELECT * FROM users WHERE id={tag[1]}") c.execute(f"SELECT * FROM users WHERE id={tag[1]}")
user = c.fetchone() user = c.fetchone()
log(type="balance", userid=user[0], before=balance_old, after=user[2])
socketio.emit("update", "update") socketio.emit("update", "update")
return make_response(json.dumps({"mode":"balance", "username":user[1], "balance":user[2]/100})) return make_response(json.dumps({"mode":"balance", "username":user[1], "balance":user[2]/100}))
else: else:
@ -426,9 +412,35 @@ def create_app(test_config=None):
socketio.emit("update", "update") socketio.emit("update", "update")
return make_response(json.dumps({"mode":"error","error":"054"})) return make_response(json.dumps({"mode":"error","error":"054"}))
@app.route("/api/change", methods=['POST'])
def reroll():
statement = request.form["statement"]
user_id = request.form["user_id"]
before = request.form["before"]
after = request.form["after"]
change = request.form["change"]
if statement == "add_user":
db_handler.add_user(after)
elif statement == "remove_user":
db_handler.remove_user(user_id)
elif statement == "add_tag":
db_handler.add_tag(user_id, after)
elif statement == "remove_tag":
db_handler.remove_tag(befor)
elif statement == "balance":
db_handler.change_balance(user_id, change)
else:
return make_response(json.dumps({"mode":"error", "error":"418"})) #Error code
socketio.emit("update", "update")
return render_template("index.html")
#Documentation #Documentation
@app.route("/documentation") @app.route("/documentation")
def documentation(): def documentation():
return render_template("documentation.html") return render_template("documentation.html")
return {"app":app,"socketio":socketio} return {"app":app,"socketio":socketio}

View file

@ -1,9 +1,58 @@
from re import M from re import M
from markupsafe import escape
import sqlite3 import sqlite3
from datetime import datetime
import click import click
from flask import current_app, g from flask import current_app, g
def log(statement, user_id=None, before=None, after=None, change=None):
db = get_db()
c = db.cursor()
c.execute("INSERT INTO transaction_log (type, user_id, before, after, change) VALUES (?, ?, ?, ?, ?)", [ statement, user_id, before, after, change])
db.commit()
def add_user(after):
db = get_db()
c = db.cursor()
c.execute("INSERT or IGNORE INTO users (username, balance) VALUES (?, 0)", [after])
user_id = c.lastrowid
log("add_user", user_id=user_id, after=after)
db.commit()
def remove_user(user_id):
db = get_db()
c = db.cursor()
c.execute("SELECT * FROM users WHERE id = ?", [user_id])
user_name = c.fetchone()[1]
c.execute("SELECT * FROM tags WHERE userid = ?", [user_id])
for tag in c.fetchall():
remove_tag(tag[0])
c.execute("DELETE FROM users WHERE id = ?", [user_id])
log("remove_user", user_id=user_id, before=user_name)
db.commit()
def add_tag(user_id, tag_id):
db = get_db()
c = db.cursor()
c.execute("INSERT OR IGNORE INTO tags (tagid, userid) VALUES (?, ?)", [tag_id, user_id])
db.commit()
log("add_tag", after=tag_id, user_id=user_id)
def remove_tag(tag_id):
db = get_db()
c = db.cursor()
c.execute("SELECT * FROM tags WHERE tagid = ?", [tag_id])
user_id = c.fetchone()[1]
c.execute("DELETE FROM tags WHERE tagid = ?", [tag_id])
log("remove_tag", before=tag_id, user_id=user_id)
db.commit()
def change_balance(user_id, change):
db = get_db()
c = db.cursor()
c.execute("UPDATE users SET balance = balance + ? WHERE id=?", [change, user_id])
log("balance", user_id=user_id, change=change)
db.commit()
def get_db(): def get_db():
if 'db' not in g: if 'db' not in g:

View file

@ -1,14 +0,0 @@
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS "users" (
"id" INTEGER NOT NULL,
"username" TEXT NOT NULL,
"balance" INTEGER NOT NULL,
PRIMARY KEY("id")
);
CREATE TABLE IF NOT EXISTS "tags" (
"tagid" INEGER NOT NULL,
"userid" INTEGER,
FOREIGN KEY("userid") REFERENCES "users"("id"),
PRIMARY KEY("tagid")
);
COMMIT;

View file

@ -12,10 +12,10 @@ CREATE TABLE IF NOT EXISTS "tags" (
PRIMARY KEY("tagid") PRIMARY KEY("tagid")
); );
CREATE TABLE IF NOT EXISTS "transaction_log" ( CREATE TABLE IF NOT EXISTS "transaction_log" (
"timestamp" INTEGER NOT NULL,
"userid" INTEGER NOT NULL,
"type" TEXT NOT NULL, "type" TEXT NOT NULL,
"user_id" INTEGER,
"before" TEXT, "before" TEXT,
"after" TEXT "after" TEXT,
"change" INTEGER
); );
COMMIT; COMMIT;

View file

@ -1,26 +1,25 @@
<!DOCTYPE html> {% extends "base.html" %}
<html lang="en"> {% block customscript %}
<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">
<script type="text/javascript" charset="utf-8"> var socket = io();
var socket = io(); var user = {{ user }}
var user = {{ user }} socket.on('connect', function() {
socket.on('connect', function() { socket.emit('addtag', {data: user});
socket.emit('addtag', {data: user}); });
}); socket.on("busy", function(){
socket.on("busy", function(){ document.write('<p>the nfc reader is busy at the moment. Pleas Wait ...</p>')
document.write('<p>the nfc reader is busy at the moment. Pleas Wait ...</p>') socket.emit('addtag', {data: user})
socket.emit('addtag', {data: user}) });
}); socket.on("wait", function(){
socket.on("wait", function(){ document.write('<p>Pleas hold your tag on to the nfc reader</p>')
document.write('<p>Pleas hold your tag on to the nfc reader</p>') });
}); socket.on("error", function(data) {
socket.on("error", function(data) { alert(data)
alert(data) window.location="http://matekasse.server.c3h/"
window.location="http://matekasse.server.c3h/" });
}); socket.on("finished", function(data){
socket.on("finished", function(data){ alert(data)
alert(data) window.location="http://matekasse.server.c3h/"
window.location="http://matekasse.server.c3h/" });
}); </script>
</script> {% endblock %}
</html>

View file

@ -1,8 +1,10 @@
<!DOCTYPE html> {% extends "base.html" %}
<html lang="en"> {% block title %}
<title>add user</title> add user
<p><a href="/list">user and tag list</a> | <a href="/documentation">Documentation</a></p> {% endblock %}
<p> {% block content %}
<form action="/adduser/user" method="post"><input name="username" type="search" placeholder="Username"><button>Add user</button></form> <form action="/adduser/user" method="post"><input name="username" type="search" placeholder="Username">
</p> <button>Add user</button>
</html> </form>
</p>
{% endblock %}

View file

@ -1,17 +1,29 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<title> <title>{% block title %}{% endblock %}</title>
{% block title %} {% endblock %} - FlaskApp <script src="/socket.io.js"
</title> integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA=="
</head> crossorigin="anonymous"
<body> ></script>
<nav> <link rel="stylesheet" href="/new.css">
<p><a href="/list">user and tag list</a> | <a href="/documentation">Documentation</a></p>
</nav> <link rel="prefetch" href="/ka-ching.wav" />
<hr> <link rel="shortcut icon" type="Logo/png" href="/ccc_logo.png"/>
<div class="conntent"> {% block customscript %}{% endblock %}
{% block content %} {% endblock %} </head>
</div> <body>
</body> <nav>
<p><a href="/">index page</a>
| <a href="/list">user and tag list</a>
| <a href="/documentation">Documentation</a>
| <a href="/transactionlist">transactionlist</a>
| <a href="/transfare">transfare<font face="emoji">🎺⚧</font></a>
</p>
</nav>
<hr>
<div class="conntent">
{% block content %} {% endblock %}
</div>
</body>
</html> </html>

View file

@ -1,6 +1,5 @@
<!DOCTYPE html> {% extends "base.html" %}
<html lang="en"> {% block customscript %}
<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"> <script type="text/javascript" charset="utf-8">
var socket = io(); var socket = io();
var change = {{change}} var change = {{change}}
@ -16,11 +15,11 @@
}); });
socket.on("error", function(data) { socket.on("error", function(data) {
alert(data) alert(data)
window.location="http://matekasse.server.c3h/" window.location="/list"
}); });
socket.on("finished", function(data){ socket.on("finished", function(data){
alert(data) alert(data)
window.location="http://matekasse.server.c3h/" window.location="/list"
}); });
</script> </script>
</html> {% endblock %}

View file

@ -0,0 +1,16 @@
{% extends "base.html" %}
{% block customscript %}
<script type="text/javascript" charset="utf-8">
if (confirm("{message}") == true) {
fetch("{{destination}}", {
method: "POST",
body: JSON.stringify({data}),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
})
} else {
window.location = "/list"
}
</script>
{% endblock %}

View file

@ -1,32 +1,30 @@
<html> {% extends "base.html" %}
{% block title %}
<head> Documentation
<title>Documentation</title> {% endblock %}
<link rel="stylesheet" type="text/css" href="documentation.css"> {% block customscript %}
<link rel="shortcut icon" type="Logo/png" href="ccc_logo.png"/> <link rel="stylesheet" type="text/css" href="documentation.css">
</head> {% endblock %}
{% block content %}
<body>
<div id="Infos">
<p> <a href="/">index page</a> | <a href="/list">user and tag list</a></p>
<p><a href="https://hannover.ccc.de/gitlab/anton/matekasse">https://hannover.ccc.de/gitlab/anton/matekasse</a></p>
</div>
<h1 class="header"> <u>Documentation</u> </h1> <h1 class="header"> <u>Documentation</u> </h1>
<p>&nbsp;</p> <p>&nbsp;</p>
<div id="text"> <div id="text">
<h2>API:</h2> <h2>API:</h2>
<p>http://matekasse.server.c3h/api/tag_id?={tag_id}</p> <p>http://matekasse.server.c3h/api/tag_id</p>
<p>Post method {"id":tag_id}</p>
<p>Response: <p>Response:
{"mode":"error" "error":"{error}"} or {"mode":"error" "error":"{error}"} or
{"mode":"message","username":"{username}","message":"{message}"} or {"mode":"message","username":"{username}","message":"{message}"} or
{"mode":"balance", "username":"{username}", "balance":"{balance}"} {"mode":"balance", "username":"{username}", "balance":"{balance}"}
</p> </p>
<br></br> <br></br>
<p>http://matekasse.server.c3h/api/change?id={user_id}&?change={change}</p> <p>http://matekasse.server.c3h/api/balance</p>
<p>Post method {"id":user_id, "change":change}</p>
<p> <p>
If change = None or NaN the change will be -1 If change = None or NaN the change will be -1
</p> </p>
<p>Get method ?id=user_id</p>
<p> <p>
Response: Response:
{"mode":"error" "error":"{error}"} or {"mode":"error" "error":"{error}"} or
@ -40,8 +38,7 @@
<p>043: User does not exists</p> <p>043: User does not exists</p>
<p>352: Timeout</p> <p>352: Timeout</p>
<p>095: Input is not a Number</p> <p>095: Input is not a Number</p>
<p>638: Wrong Input</p>
<P>418: I'm a teapot</P> <P>418: I'm a teapot</P>
</div> </div>
</body> {% endblock %}
</html>

View file

@ -1,8 +1,8 @@
<!DOCTYPE html> {% extends "base.html" %}
<html lang="en"> {% block title %}Error{% endblock %}
<title>Error</title> {% block customscript %}
<p><a href="/list">user and tag list</a> | <a href="/documentation">Documentation</a></p> <p><a href="/list">user and tag list</a> | <a href="/documentation">Documentation</a></p>
<p> <p>
Error: {{error_code}} Error: {{error_code}}
</p> </p>
</html> {% endblock %}

View file

@ -0,0 +1,12 @@
{% extends "base.html" %}
{% block customscript %}
<script type="text/javascript" charset="utf-8">
window.location="/list"
</script>
{% endblock %}
{% block content %}
<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>
{% endblock %}

View file

@ -0,0 +1,51 @@
{% extends "base.html" %}
{% block title %}
Strichliste
{% endblock %}
{% block customscript %}
<script type="text/javascript" charset="utf-8">
function play() {
return new Promise((resolve, reject) => {
var audio = new Audio('/ka-ching.wav');
audio.play();
audio.addEventListener("ended", function(){
resolve()
});
});
}
async function ka_ching(element) {
await play();
element.parentElement.submit();
}
var socket = io();
socket.on("update", function () {
window.location = "http://matekasse.server.c3h/list"
});
</script>
{% endblock %}
{% block content %}
<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>
{% for user in users %}
<form action="/change" method="post" style="display: inline;">
<p style="display: inline;">
<a href="list/user?id={{user[0]}}">{{user[1]|limit_length}}</a>: {{user[2]/100}}€
</p>
<input name="id" type="hidden" value="{{user[0]}}">
<input name="change" type="number" lang="nb" step="0.01" max={{50000-user[2]/100}} min={{min_value-user[2]/100}} placeholder="add to balance">
</form>
<form action="/change" method="post" style="display: inline">
<input name="id" type="hidden" value="{{user[0]}}">
<input name="change" value={{preis}} type="hidden">
<button onclick="ka_ching(this)" type="button">{{preis}}€</button>
</form>
<br style="line-height: 50%;"></br>
{% endfor %}
{% endblock %}

View file

@ -0,0 +1,12 @@
{% extends "base.html" %}
{% block title %}
{% endblock %}
{% block content %}
<p>redirekting</p>
<a href="/list">destination</a>
{% endblock %}
{% block customscript %}
<script type="text/javascript" charset="utf-8">
window.location = "/list";
</script>
{% endblock %}

View file

@ -1,7 +1,6 @@
<!DOCTYPE html> {% extends "base.html" %}
<html lang="en"> {% block customscript %}
<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">
<script type="text/javascript" charset="utf-8">
var socket = io(); var socket = io();
var user = {{ user }} var user = {{ user }}
socket.on('connect', function() { socket.on('connect', function() {
@ -23,4 +22,4 @@
window.location="http://matekasse.server.c3h/" window.location="http://matekasse.server.c3h/"
}); });
</script> </script>
</html> {% endblock %}

View file

@ -0,0 +1,10 @@
{% extends "base.html" %}
{% block title %}
remove user
{% endblock %}
{% block content %}
<p>
<p>Deleted user {{user_name|safe}}</p>
<a href="/list">return to the tags and user list</a>
</p>
{% endblock %}

View file

@ -0,0 +1,17 @@
{% extends "base.html" %}
{% block title %}
Transactionlist
{% endblock %}
{% block content %}
{% for action in action_list%}
<form action="/api/change" method="post">
<p style="display: inline;">{{action["statement"]}} userid:{{action["user_id"]}} {{action["before"]|limit_length}} {{action["after"]|limit_length}} {{action["change"]}}</p>
<input type="hidden" name="statement" value={{action["reverse_statement"]}}>
<input type="hidden" name="user_id" value={{action["reverse_user_id"]}}>
<input type="hidden" name="before" value={{action["reverse_before"]}}>
<input type="hidden" name="after" value={{action["reverse_after"]}}>
<input type="hidden" name="change" value={{action["reverse_change"]}}>
<button type="submit">rollback</button></form><br></br>
{% endfor %}
{% endblock %}

View file

@ -0,0 +1,34 @@
{% extends "base.html" %}
{% block title %}
transfare
{% endblock %}
{% block content %}
<form action="/api/transfare" method="post">
<p>
<select name="transfarefrom">
<option value="">Select the user to transfare from</option>
{% for user in user_list %}
<option value={{user[0]}}>{{user[1]}}</option>
{% endfor %}
</select>
</p>
<p>
<select name="transfareto">
<option value="">Select the user to transfare to</option>
{% for user in user_list %}
<option value={{user[0]}}>{{user[1]}}</option>
{% endfor %}
</select>
</p>
<p>
<input name="change" type="number" lang="nb" step="0.01" max=1000 min=-1000 placeholder="money to transfare">
</p>
<p>
<button type="submit">transfare money</button>
</p>
</form>
{% endblock %}

View file

@ -0,0 +1,45 @@
{% extends "base.html" %}
{% block customscript %}
<script type="text/javascript" charset="utf-8">
var socket = io();
socket.on("update", function () {
window.location = "/list/user?id={{user[0]}}"
});
</script>
{% endblock %}
{% block title %}
{{user[1]}}
{% endblock %}
{% block content %}
<p> {{user[1]}} : {{user[2]/100}}€ <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" lang="nb" step="0.01" max={{50000-user[2]/100}} min={{min_value-user[2]/100}} placeholder="add to balance">
</form>
</p>
<br></br>
<p>Tags:</p>
{% for tag in tags %}
<p>
<form action="/removetag" method="post">
<label for="removetag">{{tag[0]}} </label>
<input name="id" type="hidden" value="{{user[0]}}">
<input name="tagid" type="hidden" value="{{tag[0]}}">
<button id="removetag" type="submit">Remove Tag</button>
</form>
</p>
{% endfor %}
<br></br>
<form action="/removeuser" method="post"><input name="id" type="hidden" value="{{user[0]}}">
<button type="submit">Remove User</button>
</form>
{% endblock %}

View file

@ -10,8 +10,6 @@ def exit_handler():
sys.exit("Program sucsesfully exited") sys.exit("Program sucsesfully exited")
def main(): def main():
app_data = create_app()
app = app_data["app"]
socketio = app_data["socketio"] socketio = app_data["socketio"]
atexit.register(exit_handler) atexit.register(exit_handler)
socketio.run(app, host='0.0.0.0', port=5000) socketio.run(app, host='0.0.0.0', port=5000)

BIN
static/ka-ching.wav Normal file

Binary file not shown.

8
static/new.min.css vendored Normal file
View file

@ -0,0 +1,8 @@
/**
* Minified by jsDelivr using clean-css v4.2.1.
* Original file: /npm/@exampledev/new.css@1.1.2/new.css
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
:root{--nc-font-sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--nc-font-mono:Consolas,monaco,'Ubuntu Mono','Liberation Mono','Courier New',Courier,monospace;--nc-tx-1:#000000;--nc-tx-2:#1A1A1A;--nc-bg-1:#FFFFFF;--nc-bg-2:#F6F8FA;--nc-bg-3:#E5E7EB;--nc-lk-1:#0070F3;--nc-lk-2:#0366D6;--nc-lk-tx:#FFFFFF;--nc-ac-1:#79FFE1;--nc-ac-tx:#0C4047}@media (prefers-color-scheme:dark){:root{--nc-tx-1:#ffffff;--nc-tx-2:#eeeeee;--nc-bg-1:#000000;--nc-bg-2:#111111;--nc-bg-3:#222222;--nc-lk-1:#3291FF;--nc-lk-2:#0070F3;--nc-lk-tx:#FFFFFF;--nc-ac-1:#7928CA;--nc-ac-tx:#FFFFFF}}*{margin:0;padding:0}address,area,article,aside,audio,blockquote,datalist,details,dl,fieldset,figure,form,iframe,img,input,meter,nav,ol,optgroup,option,output,p,pre,progress,ruby,section,table,textarea,ul,video{margin-bottom:1rem}button,html,input,select{font-family:var(--nc-font-sans)}body{margin:0 auto;max-width:750px;padding:2rem;border-radius:6px;overflow-x:hidden;word-break:break-word;overflow-wrap:break-word;background:var(--nc-bg-1);color:var(--nc-tx-2);font-size:1.03rem;line-height:1.5}::selection{background:var(--nc-ac-1);color:var(--nc-ac-tx)}h1,h2,h3,h4,h5,h6{line-height:1;color:var(--nc-tx-1);padding-top:.875rem}h1,h2,h3{color:var(--nc-tx-1);padding-bottom:2px;margin-bottom:8px;border-bottom:1px solid var(--nc-bg-2)}h4,h5,h6{margin-bottom:.3rem}h1{font-size:2.25rem}h2{font-size:1.85rem}h3{font-size:1.55rem}h4{font-size:1.25rem}h5{font-size:1rem}h6{font-size:.875rem}a{color:var(--nc-lk-1)}a:hover{color:var(--nc-lk-2)}abbr:hover{cursor:help}blockquote{padding:1.5rem;background:var(--nc-bg-2);border-left:5px solid var(--nc-bg-3)}abbr{cursor:help}blockquote :last-child{padding-bottom:0;margin-bottom:0}header{background:var(--nc-bg-2);border-bottom:1px solid var(--nc-bg-3);padding:2rem 1.5rem;margin:-2rem calc(0px - (50vw - 50%)) 2rem;padding-left:calc(50vw - 50%);padding-right:calc(50vw - 50%)}header h1,header h2,header h3{padding-bottom:0;border-bottom:0}header>:first-child{margin-top:0;padding-top:0}header>:last-child{margin-bottom:0}a button,button,input[type=button],input[type=reset],input[type=submit]{font-size:1rem;display:inline-block;padding:6px 12px;text-align:center;text-decoration:none;white-space:nowrap;background:var(--nc-lk-1);color:var(--nc-lk-tx);border:0;border-radius:4px;box-sizing:border-box;cursor:pointer;color:var(--nc-lk-tx)}a button[disabled],button[disabled],input[type=button][disabled],input[type=reset][disabled],input[type=submit][disabled]{cursor:default;opacity:.5;cursor:not-allowed}.button:focus,.button:hover,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover{background:var(--nc-lk-2)}code,kbd,pre,samp{font-family:var(--nc-font-mono)}code,kbd,pre,samp{background:var(--nc-bg-2);border:1px solid var(--nc-bg-3);border-radius:4px;padding:3px 6px;font-size:.9rem}kbd{border-bottom:3px solid var(--nc-bg-3)}pre{padding:1rem 1.4rem;max-width:100%;overflow:auto}pre code{background:inherit;font-size:inherit;color:inherit;border:0;padding:0;margin:0}code pre{display:inline;background:inherit;font-size:inherit;color:inherit;border:0;padding:0;margin:0}details{padding:.6rem 1rem;background:var(--nc-bg-2);border:1px solid var(--nc-bg-3);border-radius:4px}summary{cursor:pointer;font-weight:700}details[open]{padding-bottom:.75rem}details[open] summary{margin-bottom:6px}details[open]>:last-child{margin-bottom:0}dt{font-weight:700}dd::before{content:'→ '}hr{border:0;border-bottom:1px solid var(--nc-bg-3);margin:1rem auto}fieldset{margin-top:1rem;padding:2rem;border:1px solid var(--nc-bg-3);border-radius:4px}legend{padding:auto .5rem}table{border-collapse:collapse;width:100%}td,th{border:1px solid var(--nc-bg-3);text-align:left;padding:.5rem}th{background:var(--nc-bg-2)}tr:nth-child(even){background:var(--nc-bg-2)}table caption{font-weight:700;margin-bottom:.5rem}textarea{max-width:100%}ol,ul{padding-left:2rem}li{margin-top:.4rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}mark{padding:3px 6px;background:var(--nc-ac-1);color:var(--nc-ac-tx)}input,select,textarea{padding:6px 12px;margin-bottom:.5rem;background:var(--nc-bg-2);color:var(--nc-tx-2);border:1px solid var(--nc-bg-3);border-radius:4px;box-shadow:none;box-sizing:border-box}img{max-width:100%}
/*# sourceMappingURL=/sm/4a51164882967d28a74fabce02685c18fa45a529b77514edc75d708f04dd08b9.map */

6046
static/socket.io.js Normal file

File diff suppressed because it is too large Load diff

View file

@ -23,14 +23,14 @@ def test_index(client):
#/adduser #/adduser
def test_adduser(client): def test_adduser(client):
response = client.get('/adduser/user') response = client.post('/adduser/user', data={})
assert "418" in response.data.decode('utf-8') assert "418" in response.data.decode('utf-8')
def test_adduser_new(app, client): def test_adduser_new(app, client):
with app.app_context(): with app.app_context():
db = get_db() db = get_db()
assert db is get_db() assert db is get_db()
response = client.get('/adduser/user?username=test') response = client.post('/adduser/user', data={user_name:"test"})
c = db.cursor() c = db.cursor()
c.execute("SELECT * FROM users WHERE username = ?", ["test"]) c.execute("SELECT * FROM users WHERE username = ?", ["test"])
data = c.fetchone() data = c.fetchone()
@ -40,7 +40,7 @@ def test_adduser_new(app, client):
assert data[2] == 0 assert data[2] == 0
def test_adduser_allreadyexists(client): def test_adduser_allreadyexists(client):
response = client.get('/adduser/user?username=test') response = client.post('/adduser/user', data={username:"test"})
assert "Error: 757" in response.data.decode('utf-8') assert "Error: 757" in response.data.decode('utf-8')
#/addtag #/addtag
@ -49,7 +49,7 @@ def test_addtag(client):
assert response.data.decode('utf-8') == "Error: 095" assert response.data.decode('utf-8') == "Error: 095"
def test_addtag_userid_nan(client): def test_addtag_userid_nan(client):
response = client.get('/addtag?id=test') response = client.post('/addtag', data={id:1})
assert response.data.decode('utf-8') == "Error: 095" assert response.data.decode('utf-8') == "Error: 095"
def test_add_tag_direktli(app): def test_add_tag_direktli(app):