Split API / Webpage

We use react as a webpage, so it can be served either on OBS or on the
server.
This commit is contained in:
2023-09-18 00:52:42 +02:00
parent 6733a857ac
commit 7d18b5dc2e
29 changed files with 412 additions and 3 deletions

55
api/classes.py Normal file
View File

@@ -0,0 +1,55 @@
from sqlite3 import Connection
import json
from flask.json.provider import DefaultJSONProvider
class CustomJSONProvider(DefaultJSONProvider):
@staticmethod
def default(obj) -> dict :
if isinstance(obj,Payment):
return obj.to_json()
return DefaultJSONProvider.default(obj)
class Payment(json.JSONEncoder):
id : int
amount: float
name : str
message : str
def __init__(self,id,amount,message,name) -> None:
self.id = id
self.amount = amount
self.name = name
self.message = message
def save(self, conn : Connection):
try:
conn.cursor()
conn.execute("insert into orders values (:id,:amount,:message,:name)",
{
"id" : self.id,
"amount" : self.amount,
"message" : self.message,
"name" : self.name
})
conn.commit()
except:
print("Can't save?")
return
def __repr__(self) -> str:
return '{} - {}€- {}'.format(self.name,self.amount/100,self.message)
def to_json(self) -> dict:
return {
"name":self.name,
"amount": self.amount/100,
"message": self.message
}
class Client:
def __init__(self,sock) -> None:
self.sock = sock
def send_event(self, data):
print(self.sock)
self.sock.send(data)

6
api/db.sql Normal file
View File

@@ -0,0 +1,6 @@
CREATE TABLE orders (
id INTEGER NOT NULL UNIQUE,
amount REAL NOT NULL,
message TEXT,
name TEXT
);

5
api/pyvenv.cfg Normal file
View File

@@ -0,0 +1,5 @@
home = /usr/lib/python-exec/python3.11
include-system-site-packages = false
version = 3.11.4
executable = /usr/bin/python3.11
command = /usr/lib/python-exec/python3.11/python -m venv /stuffs/src/helloasso/api

11
api/requirements.txt Normal file
View File

@@ -0,0 +1,11 @@
blinker==1.6.2
click==8.1.7
Flask==2.3.3
flask-sock==0.6.0
h11==0.14.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
simple-websocket==0.10.1
Werkzeug==2.3.7
wsproto==1.2.0

94
api/serv.py Executable file
View File

@@ -0,0 +1,94 @@
#!/bin/env python3
import os
import sqlite3
from flask import Flask, make_response, render_template,request,g,jsonify
from flask_sock import Sock
from classes import Payment, Client, CustomJSONProvider
clients_list = []
payments_list : list[Payment] = []
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
DATABASE=os.path.join(app.instance_path,'db.sqlite')
)
app.json = CustomJSONProvider(app)
sock = Sock(app)
def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g.db = sqlite3.connect('db.sqlite')
return db
@app.teardown_appcontext
def close(exception):
db = getattr(g, 'db', None)
if db is not None:
db.close()
def notify_client_payment(msg):
for c in clients_list:
try:
c.send_event(app.json.dumps(msg))
except:
clients_list.remove(c)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/show')
def show():
db = get_db()
cur = db.cursor()
cur.execute('select * from orders;')
info = cur.fetchall();
val = ""
for i in info:
val += '{} {} <br/>'.format(i[0],i[1])
return make_response(val, 200)
@app.route('/test')
def test():
p = Payment(1,5000,'TEST DE MESSAGE BIEN LONG SKLDJQLKDJQLKSJDQLSKJDQLKJD','Nom donation')
notify_client_payment(p)
return jsonify(p), 200
@app.route('/last')
def last():
print(len(clients_list))
if(len(payments_list) > 0):
p = payments_list[0]
notify_client_payment(p)
return make_response('last',200)
@sock.route('/notify')
def notify(sock):
clients_list.append(Client(sock))
while True:
data = sock.receive()
sock.send(data)
@app.route('/notifications',methods=['POST'])
def notifications():
if request.json is not None:
print(request.json)
if request.json['eventType'] == 'Order':
p = Payment(request.json['data']['id'],
request.json['data']['amount']['total'],
request.json['data']['items'][0]['customFields'][0]['answer'],
request.json['data']['payer']['firstName'])
p.save(get_db());
payments_list.append(p)
notify_client_payment(p)
return make_response('OK',200)
return make_response('Not Handled',400)

48
api/templates/index.html Normal file
View File

@@ -0,0 +1,48 @@
<html>
<head>
<title>Hello Asso</title>
<style>
.notif {
margin: 10px;
padding: 5px;
border-radius: 5px;
border: 2px solid #1100ff;
}
</style>
</head>
<body>
<div id="msg"></div>
<script>
function addNode(msg){
let notifs = document.getElementsByClassName("notif");
if(notifs.length > 5)
{
notifs.slice(0,notifs.length-5).forEach(e => e.remove());
}
console.log(msg);
let ndiv = document.createElement('div');
ndiv.className='notif';
let data = document.createTextNode(msg);
ndiv.appendChild(data);
message = document.getElementById('msg');
document.body.insertBefore(ndiv,message);
}
const websocket = new WebSocket('ws://'+ location.host + '/notify');
websocket.addEventListener('message', ev => {
addNode(ev.data);
});
websocket.addEventListener('error', ev => {
let div = document.createTextNode(ev);
document.body.append(div);
});
websocket.addEventListener('close', ev => {
let div = document.createTextNode(ev);
document.body.append(div);
});
</script>
</body>
</html>