summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraltaf-creator <dev@altafcreator.com>2025-12-29 20:25:08 +0800
committeraltaf-creator <dev@altafcreator.com>2025-12-29 20:25:08 +0800
commit9080a0c516378dbb94c5178fbc26a8131a530263 (patch)
tree5f3aff1737d00ab01852daea742f1c5dfe982b1d
parent37b76b0f4c8e65b35bbbc617bcbff7a5d637ac3e (diff)
new notif everything
-rw-r--r--.gitignore2
-rw-r--r--backend/main.py12
-rw-r--r--backend/notif.py59
-rw-r--r--frontend/main.js46
-rw-r--r--frontend/permissionrequest.js16
5 files changed, 120 insertions, 15 deletions
diff --git a/.gitignore b/.gitignore
index b696bcc..d9fb045 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
db.db
.env
config.yaml
+private_key.pem
+public_key.pem
diff --git a/backend/main.py b/backend/main.py
index d77fdd1..fec436b 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -17,6 +17,7 @@ from enum import Enum, IntEnum
from dotenv import load_dotenv
from os import getenv
import yaml
+import notif # import notif.py
# ## API, db, and scheduler initialisation
app = fastapi.FastAPI(title="Victoria Hall LaundryWeb", description="LaundryWeb Backend API", version="0.1")
@@ -443,3 +444,14 @@ def uri_to_information(data: InformationRequestData, response: fastapi.Response,
return "NO INFORMATION PROVIDED. NO AUTH COOKIE."
return {"block": info[0], "machine": info[1]}
+
+
+# #### NOTIFICATION API END POINTS ####
+
+
+# --- subscribe
+@app.post("/notif_subscribe")
+def notif_subscribe(data: notif.PushSubscriptionData, response: fastapi.Response):
+ endpoint = notif.subscribe(data)
+ response.set_cookie("subscription_endpoint", endpoint)
+ response.status_code = fastapi.status.HTTP_200_OK
diff --git a/backend/notif.py b/backend/notif.py
new file mode 100644
index 0000000..59bb3c3
--- /dev/null
+++ b/backend/notif.py
@@ -0,0 +1,59 @@
+from pydantic import BaseModel
+import sqlite3
+from pywebpush import webpush
+
+
+class PushSubscriptionData(BaseModel):
+ endpoint: str
+ expirationTime: float
+ keys: object
+
+
+conn = sqlite3.connect("db.db", check_same_thread=False)
+cursor = conn.cursor()
+
+f = open("private_key.pem", "r")
+PRIVATE_VAPID_KEY = f.read()
+f.close()
+
+cursor.execute("""
+CREATE TABLE IF NOT EXISTS subscriptions (
+ endpoint TEXT PRIMARY KEY,
+ expiration_time REAL NOT NULL,
+ keys_p256dh TEXT NOT NULL,
+ keys_auth TEXT NOT NULL
+);""")
+
+
+# --- subscribe
+def subscribe(data: PushSubscriptionData):
+ cursor.execute("""
+ INSERT INTO subscriptions (endpoint, expiration_time, keys_p256dh, keys_auth)
+ VALUES (?, ?, ?, ?)""", (data.endpoint, data.expirationTime, data.keys["p256dh"], data.keys["auth"]))
+ conn.commit()
+ return data.endpoint
+
+
+# --- send notification
+def send_notification(endpoint: str):
+ cursor.execute("SELECT * FROM subscriptions WHERE endpoint = ?", (endpoint,))
+ row = cursor.fetchall()[0]
+ subscription_info = {
+ "endpoint": endpoint,
+ "keys": {
+ "p256dh": row[2],
+ "auth": row[3],
+ },
+ }
+
+ try:
+ webpush(
+ subscription_info=subscription_info,
+ data="Hello, world!",
+ vapid_private_key=PRIVATE_VAPID_KEY,
+ vapid_claims={
+ "sub": "mailto:dev@altafcreator.com",
+ },
+ )
+ except Exception as exception:
+ print(exception)
diff --git a/frontend/main.js b/frontend/main.js
index 1434979..b8803c0 100644
--- a/frontend/main.js
+++ b/frontend/main.js
@@ -7,6 +7,52 @@ const data = {
const API_URL = "https://backend.laundryweb.altafcreator.com"
+const PUBLIC_VAPID_KEY = "BCvVfKfWBtHKtzdakJfhYy604yTn0_FgZxy2sNtxcQm6YyC3qdzBBuCJLbVcG6pmbz_CZLa0I44Z-b5UVBbegGw"
+
+// --- REGISTER SERVICE WORKERS
+if ('serviceWorker' in navigator) {
+ navigator.serviceWorker.register('/sw.js', {
+ scope: '/',
+ });
+}
+
+// --- subscribe
+async function subscribe() {
+ if (!('serviceWorker' in navigator)) return;
+
+ const registration = await navigator.serviceWorker.ready;
+
+ const subscription = await registration.pushManager.subscribe({
+ userVisibleOnly: true,
+ applicationServerKey: urlBase64ToUint8Array(PUBLIC_VAPID_KEY),
+ });
+ console.log(subscription);
+
+ await fetch(`${API_URL}/notif_subscribe`, {
+ method: 'POST',
+ body: JSON.stringify(subscription),
+ headers: {
+ "Content-Type": "application/json",
+ },
+ })
+}
+
+/// copied from somewhere
+const urlBase64ToUint8Array = (base64String) => {
+ const padding = '='.repeat((4 - base64String.length % 4) % 4);
+ const base64 = (base64String + padding)
+ .replace(/\-/g, '+')
+ .replace(/_/g, '/');
+
+ const rawData = window.atob(base64);
+ const outputArray = new Uint8Array(rawData.length);
+
+ for (let i = 0; i < rawData.length; ++i) {
+ outputArray[i] = rawData.charCodeAt(i);
+ }
+ return outputArray;
+};
+
// --- check machine status
// returns a 2d array representing machines
// []: root array
diff --git a/frontend/permissionrequest.js b/frontend/permissionrequest.js
index 2303347..0c8d4d9 100644
--- a/frontend/permissionrequest.js
+++ b/frontend/permissionrequest.js
@@ -19,19 +19,5 @@ console.log("notbtn")
notbtn.addEventListener("click", () => requestPermission())
async function requestPermission() {
- try {
-
- console.log("Requesting permission...");
- const onesignal_result = await OneSignal.Notifications.requestPermission();
- alert("succ", onesignal_result.toString(), OneSignal.toString());
- console.log(onesignal_result);
- if (onesignal_result) {
- notif.remove();
- startbtn.disabled = false;
- data.onesignal_subscription_id = OneSignal.User.PushSubscription["id"];
- }
- }
- catch (e) {
- alert("err:", e, e.toString());
- }
+ subscribe()
}