diff --git a/client.py b/client.py index c19cfd7..427c646 100644 --- a/client.py +++ b/client.py @@ -1,7 +1,9 @@ import pyperclip import socketio import os +import sys import subprocess +import zc.lockfile # standard Python # to put in a conf file @@ -23,6 +25,14 @@ ip = f"http://{ip}:{port}/" print(ip) sio = socketio.Client() sio.connect(ip) + +try: + print("[Debug] Trying to lockfile") + zc.lockfile.LockFile('/tmp/notifysync.lock') +except: + print("[Debug] Failed to lock file, another instance running, exiting") + sys.exit() + print("[Debug] Connected to Server .w.") def sendSystemNotification(title:str,content:str): diff --git a/serveur.py b/serveur.py index 322c6e7..279fec2 100644 --- a/serveur.py +++ b/serveur.py @@ -1,38 +1,185 @@ #!/bin/python -from flask import Flask, request, render_template, json, jsonify import flask_socketio +import sqlite3 +import secrets +import time +from flask import Flask, request, render_template, json, jsonify # base socket app = Flask(__name__) socketio = flask_socketio.SocketIO(app) +############################################################################### -@app.route("/notify", methods=['POST']) -def notify(): - """ - Le but de cet app se resume a cette fonction, elle recoit une requette http et renvoie via le websocket - le contenu de la requette a tout les client. - """ - data = {} - data["ip"] = request.remote_addr - print(request.remote_addr) - data['title'] = request.form['title'] - data['content'] = request.form['content'] - print(f"""[Debug] Sending to all clients notification event""") - socketio.emit("notify", data, broadcast=True) - return "true" , 200 -@app.route("/clip", methods=['POST']) -def clip(): +def first_run(): """ - pareil qu'en haut mais pour le clipboard .w. + create databases """ - data = {} - data["ip"] = request.remote_addr - data['content'] = request.form['content'] - print(f"""[Debug] Sending to all clients clipboard event""") - socketio.emit("clip", data, broadcast=True) - return "true" , 200 + con = sqlite3.connect("database.db") + cur = con.cursor() + cur.execute("CREATE TABLE USERS(\ + username,\ + password,\ + token)") + + cur.execute("CREATE TABLE NOTIFICATION(\ + id,\ + date,\ + machine,\ + token,\ + title,\ + content)") + + cur.execute("CREATE TABLE CLIPBOARD(\ + id,\ + date,\ + machine,\ + token,\ + content)") + + con.commit() + con.close() + +############################################################################### + +@app.route("/user", methods=['POST']) +def auth(): + """ + Authentifie un user, simple, basique + "username" + "password" + """ + user = (request.values.get("username"), request.values.get("password")) + con = sqlite3.connect("database.db") + cur = con.cursor() + db_user = cur.execute("SELECT token FROM USERS WHERE USERNAME=? AND \ + PASSWORD=?", user).fetchone() + con.close() + if db_user is None: + return {"status": "This user does not exist or the password is \ + incorrect"}, 404 + else: + return {"status": "ok", "token": db_user[0]} + + +@app.route("/user", methods=['PUT']) +def register(): + """ + Authentifie un user, simple, basique + "username" + "password" + """ + con = sqlite3.connect("database.db") + cur = con.cursor() + username = request.values.get("username") + user = (username,) + if cur.execute("SELECT username FROM USERS WHERE username=?", user)\ + .fetchone() is not None: + con.close() + return {"status": "Error, username already taken"}, 500 + user = (request.values.get("username"), request.values.get("password"), + secrets.token_urlsafe(64)) + try: + cur.execute("INSERT INTO USERS VALUES (?,?,?)", user) + con.commit() + con.close() + return {"status": "ok"} + except: + con.close() + return {"status": "Error, most likely username already taken"}, 500 + +############################################################################### + + +@app.route("/notification", methods=['PUT']) +def add_notification(): + """ + Le but de cet app se resume a cette fonction, elle recoit une requete + http et renvoie via le websocket le contenu de la requette a tout les + client. + """ + token = request.values.get("token") + title = request.values.get('title') + content = request.values.get('content') + device_name = request.values.get('deviceName') + date = time.time() + con = sqlite3.connect("database.db") + cur = con.cursor() + if cur.execute("SELECT username FROM USERS WHERE token=?", (token,))\ + .fetchone() is None: + return {"status": "Error, no user"}, 500 + try: + notification = (date, device_name, token, title, content) + cur.execute("INSERT INTO notification VALUES (0,?,?,?,?,?)", + notification) + con.commit() + con.close() + socketio.emit("update", broadcast=True) + return {"status": "ok"}, 200 + except: + return {"status": "error"}, 500 + + +@app.route("/notification", methods=['GET']) +def get_notifications(): + """ + Le but de cet app se resume a cette fonction, elle recoit une requete + http et renvoie via le websocket le contenu de la requette a tout les + client. + """ + token = request.values.get("token") + con = sqlite3.connect("database.db") + cur = con.cursor() + notifications = cur.execute("SELECT title,content FROM NOTIFICATION WHERE \ + token=?", (token, )).fetchall() + return {"status": "ok", "notifications": notifications}, 200 + +############################################################################### + + +@app.route("/clipboard", methods=['PUT']) +def add_clipboard(): + """ + Le but de cet app se resume a cette fonction, elle recoit une requete http + et renvoie via le websocket le contenu de la requette a tout les clients. + """ + token = request.values.get("token") + content = request.values.get('content') + device_name = request.values.get('deviceName') + date = time.time() + con = sqlite3.connect("database.db") + cur = con.cursor() + if cur.execute("SELECT username FROM USERS WHERE token=?", (token,))\ + .fetchone() is None: + return {"status": "Error, no user"}, 500 + try: + clipboard = (date, device_name, token, content) + cur.execute("INSERT INTO CLIPBOARD VALUES (0,?,?,?,?)", clipboard) + con.commit() + con.close() + socketio.emit("update", broadcast=True) + return {"status": "ok"}, 200 + except: + return {"status": "error"}, 500 + + +@app.route("/clipboard", methods=['GET']) +def get_clipboard(): + """ + Le but de cet app se resume a cette fonction, elle recoit une requete + http et renvoie via le websocket le contenu de la requette a tout les + client. + """ + token = request.values.get("token") + con = sqlite3.connect("database.db") + cur = con.cursor() + clipboard = cur.execute("SELECT content FROM CLIPBOARD WHERE \ + token=?", (token, )).fetchall() + return {"status": "ok", "notifications": clipboard}, 200 + if __name__ == '__main__': - socketio.run(app, host="0.0.0.0", port = 9564) + if True: + first_run() + socketio.run(app, host="0.0.0.0", port=9564)