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:
55
api/classes.py
Normal file
55
api/classes.py
Normal 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
6
api/db.sql
Normal 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
5
api/pyvenv.cfg
Normal 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
11
api/requirements.txt
Normal 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
94
api/serv.py
Executable 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
48
api/templates/index.html
Normal 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>
|
||||
Reference in New Issue
Block a user