diff --git a/assets/public/custom/pushMessages.js b/assets/public/custom/pushMessages.js index 90da39d8..15b4e346 100644 --- a/assets/public/custom/pushMessages.js +++ b/assets/public/custom/pushMessages.js @@ -1,18 +1,18 @@ function checkServiceWorkerSupport() { - if (!"serviceWorker" in navigator || !"PushManager" in window) + if (!("serviceWorker" in navigator) || !("PushManager" in window)) throw new Error("Your browser does not have Service Worker support") } async function unregisterPush() { checkServiceWorkerSupport(); - const registration = await navigator.serviceWorker.getRegistration(); - if (!registration) return; + const registrations = await navigator.serviceWorker.getRegistrations(); - const subscription = await reg.pushManager.getSubscription(); - if (!subscription) return; - - await subscription.unsubscribe(); + for (const reg of registrations) { + const sub = await reg.pushManager.getSubscription(); + if (sub) await sub.unsubscribe(); + await reg.unregister(); + } } async function registerPush(publicKey) { @@ -36,7 +36,7 @@ async function registerPush(publicKey) { method: "POST", headers: { "Content-Type": "application/json", - "Authorization": localStorage.token + "Authorization": getToken() }, body: JSON.stringify({ provider: "webpush", @@ -52,18 +52,18 @@ async function registerPush(publicKey) { } } -function urlBase64ToUint8Array(base64String) { - const padding = "=".repeat((4 - (base64String.length % 4)) % 4); - const base64 = (base64String + padding) - .replace(/\-/g, "+") - .replace(/_/g, "/"); +async function isPushRegistered() { + checkServiceWorkerSupport(); - const rawData = atob(base64); - const outputArray = new Uint8Array(rawData.length); - - for (let i = 0; i < rawData.length; i++) { - outputArray[i] = rawData.charCodeAt(i); + const registrations = await navigator.serviceWorker.getRegistrations(); + if (!registrations || registrations.length === 0) { + return false; } - return outputArray; + for (const reg of registrations) { + const sub = await reg.pushManager.getSubscription(); + if (sub) return true; + } + + return false; } \ No newline at end of file diff --git a/assets/public/custom/serviceWorker.js b/assets/public/custom/serviceWorker.js index 0a658c53..4aa3c175 100644 --- a/assets/public/custom/serviceWorker.js +++ b/assets/public/custom/serviceWorker.js @@ -2,6 +2,8 @@ self.addEventListener("push", (event) => { if (!event.data) return; const payload = event.data.json(); + if (payload.type !== "message") return; + const channel = payload.data?.channel || {}; const isInGuild = channel.type === "GUILD_TEXT" || channel.type === "GUILD_VOICE"; diff --git a/assets/public/custom/utils.js b/assets/public/custom/utils.js new file mode 100644 index 00000000..74004a16 --- /dev/null +++ b/assets/public/custom/utils.js @@ -0,0 +1,29 @@ +let authToken = null; + +function getToken() { + return authToken; +} + +function urlBase64ToUint8Array(base64String) { + const padding = "=".repeat((4 - (base64String.length % 4)) % 4); + const base64 = (base64String + padding) + .replace(/\-/g, "+") + .replace(/_/g, "/"); + + const rawData = atob(base64); + const outputArray = new Uint8Array(rawData.length); + + for (let i = 0; i < rawData.length; i++) { + outputArray[i] = rawData.charCodeAt(i); + } + + return outputArray; +} + +let proxied = window.XMLHttpRequest.prototype.setRequestHeader; +window.XMLHttpRequest.prototype.setRequestHeader = function() { + if (arguments[0] === "Authorization") { + authToken = arguments[1]; + } + return proxied.apply(this, [].slice.call(arguments)); +}; \ No newline at end of file diff --git a/assets/public/custom/web/main.js b/assets/public/custom/web/main.js index 058c861e..17e40fd5 100644 --- a/assets/public/custom/web/main.js +++ b/assets/public/custom/web/main.js @@ -16,20 +16,20 @@
`; - function addSwitches(container) { + async function addSwitches(container) { container.appendChild(createSwitch( "Push Notifications", "Sends you notifications even when you close the app", "push-notifications", - false, - async () => { + await isPushRegistered(), + async (checked) => { const publicKey = window.GLOBAL_ENV.VAPID_KEY; if (!publicKey) { alert("Server has not enabled push notifications") return false; } try { - await registerPush(publicKey); + checked ? await registerPush(publicKey) : await unregisterPush(); return true; } catch(err) { alert(err.message); diff --git a/assets/public/index.html b/assets/public/index.html index 9e989901..9f60e1e7 100644 --- a/assets/public/index.html +++ b/assets/public/index.html @@ -68,6 +68,7 @@ }; const customScripts = [ + "/assets/custom/utils.js", "/assets/custom/pushMessages.js", "/assets/custom/rtcPatcher.js", "/assets/custom/web/switch.js", diff --git a/src/api/routes/users/@me/devices.ts b/src/api/routes/users/@me/devices.ts index 3cf7172c..44f240fe 100644 --- a/src/api/routes/users/@me/devices.ts +++ b/src/api/routes/users/@me/devices.ts @@ -54,7 +54,7 @@ router.post( throw new HTTPError("Endpoint is not a valid url", 400); } - await webpush.sendNotification(subscription, JSON.stringify({ body: "Swoosh. Notifications are a go!" })).catch(async (err) => { + await webpush.sendNotification(subscription, JSON.stringify({ type: "test" })).catch(async (err) => { console.error("[WebPush] Failed to send test notification:", err.message); throw new HTTPError("Failed to send test notification", 400); }); diff --git a/src/util/interfaces/Notification.ts b/src/util/interfaces/Notification.ts index a7943af2..1219388b 100644 --- a/src/util/interfaces/Notification.ts +++ b/src/util/interfaces/Notification.ts @@ -1,4 +1,4 @@ export interface Notification { - type: "message"; - data: object; + type: "message" | "test"; + data?: object; } \ No newline at end of file