diff --git a/Dockerfile b/Dockerfile index 4ea8e93..22fc6f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM node:19-bullseye +FROM node:20-bullseye ENV NODE_ENV=production WORKDIR /app COPY ["package.json", "package-lock.json*", "./"] diff --git a/index.js b/index.js index 7f842a7..a3e13e4 100644 --- a/index.js +++ b/index.js @@ -1,19 +1,21 @@ import express from 'express'; import http from 'node:http'; import path from 'node:path'; -import { epoxyPath } from "@mercuryworkshop/epoxy-transport"; -import { baremuxPath } from "@mercuryworkshop/bare-mux/node"; -import { createBareServer } from "@tomphttp/bare-server-node"; -import { uvPath } from "@titaniumnetwork-dev/ultraviolet"; -import { server as wisp } from "@mercuryworkshop/wisp-js/server"; -import request from '@cypress/request'; +import { fileURLToPath } from 'node:url'; +import { createRequire } from 'node:module'; +import { epoxyPath } from '@mercuryworkshop/epoxy-transport'; +import { baremuxPath } from '@mercuryworkshop/bare-mux/node'; +import { createBareServer } from '@tomphttp/bare-server-node'; +import { uvPath } from '@titaniumnetwork-dev/ultraviolet'; +import { server as wisp } from '@mercuryworkshop/wisp-js/server'; import chalk from 'chalk'; -import packageJson from './package.json' with { type: 'json' }; -const __dirname = path.resolve(); +const require = createRequire(import.meta.url); +const packageJson = require('./package.json'); +const __dirname = path.dirname(fileURLToPath(import.meta.url)); const server = http.createServer(); const bareServer = createBareServer('/seal/'); -const app = express(server); +const app = express(); const version = packageJson.version; const discord = 'https://discord.gg/unblocking'; @@ -21,9 +23,9 @@ const routes = [ { route: '/mastery', file: './static/loader.html' }, { route: '/apps', file: './static/apps.html' }, { route: '/gms', file: './static/gms.html' }, - { route: '/lessons', file: './static/agloader.html' }, + { route: '/lessons', file: './static/loader.html' }, { route: '/info', file: './static/info.html' }, - { route: '/mycourses', file: './static/loading.html' } + { route: '/mycourses', file: './static/loading.html' }, ]; app.use(express.json()); @@ -34,9 +36,9 @@ app.use( ); app.use(express.static(path.join(__dirname, 'static'))); -app.use("/uv/", express.static(uvPath)); -app.use("/epoxy/", express.static(epoxyPath)); -app.use("/baremux/", express.static(baremuxPath)); +app.use('/uv/', express.static(uvPath)); +app.use('/epoxy/', express.static(epoxyPath)); +app.use('/baremux/', express.static(baremuxPath)); routes.forEach(({ route, file }) => { app.get(route, (req, res) => { @@ -45,7 +47,15 @@ routes.forEach(({ route, file }) => { }); app.get('/student', (req, res) => { - res.redirect('/portal'); + res.redirect('/mastery'); +}); + +app.get('/login.html', (req, res) => { + res.sendFile(path.join(__dirname, './login.html')); +}); + +app.get('/google0f9bc6787d77dc96.html', (req, res) => { + res.sendFile(path.join(__dirname, './google0f9bc6787d77dc96.html')); }); // FIXED: Removed broken worker.js mirror route @@ -62,16 +72,16 @@ app.use((req, res) => { res.sendFile(path.join(__dirname, './static/404.html')); }); -server.on("request", (req, res) => { +server.on('request', (req, res) => { if (bareServer.shouldRoute(req)) { bareServer.routeRequest(req, res); } else app(req, res); }); -server.on("upgrade", (req, socket, head) => { +server.on('upgrade', (req, socket, head) => { if (bareServer.shouldRoute(req)) { bareServer.routeUpgrade(req, socket, head); - } else if (req.url.endsWith("/wisp/") || req.url.endsWith("/wisp")) { + } else if (req.url.endsWith('/wisp/') || req.url.endsWith('/wisp')) { wisp.routeRequest(req, socket, head); } else { socket.end(); @@ -86,7 +96,9 @@ server.on('listening', () => { console.log(chalk.green(' 🕒 Time: ') + chalk.bold(new Date().toLocaleTimeString())); console.log(chalk.cyan('-----------------------------------------------')); console.log(chalk.magenta('📦 Version: ') + chalk.bold(version)); - console.log(chalk.magenta('🔗 URL: ') + chalk.underline('http://localhost:' + server.address().port)); + console.log( + chalk.magenta('🔗 URL: ') + chalk.underline('http://localhost:' + server.address().port) + ); console.log(chalk.cyan('-----------------------------------------------')); console.log(chalk.blue('💬 Discord: ') + chalk.underline(discord)); console.log(chalk.cyan('-----------------------------------------------')); @@ -99,7 +111,7 @@ function shutdown(signal) { console.log(chalk.yellow(' 🕒 Time: ') + chalk.bold(new Date().toLocaleTimeString())); console.log(chalk.red('-----------------------------------------------')); console.log(chalk.blue(' Exiting immediately...')); - process.exit(1); + process.exit(0); } process.on('SIGTERM', () => shutdown('SIGTERM')); diff --git a/start.sh b/start.sh index 54883fe..3c9ceaf 100644 --- a/start.sh +++ b/start.sh @@ -10,7 +10,7 @@ print_bold_with_outline() { done echo -e "\e[1m\e[44m$border\e[0m" - echo -e "\e[1m\e[44m# $msg #\e[0m + echo -e "\e[1m\e[44m# $msg #\e[0m" echo -e "\e[1m\e[44m$border\e[0m" } diff --git a/static/assets/js/main.js b/static/assets/js/main.js index ecbfcab..e536909 100644 --- a/static/assets/js/main.js +++ b/static/assets/js/main.js @@ -1,19 +1,19 @@ // Preconnect to CDN -var preconnect = document.createElement("link"); -preconnect.rel = "preconnect"; -preconnect.href = "https://cdn.jsdelivr.net"; +var preconnect = document.createElement('link'); +preconnect.rel = 'preconnect'; +preconnect.href = 'https://cdn.jsdelivr.net'; document.head.appendChild(preconnect); // Preload Bootstrap icons CSS -var preload = document.createElement("link"); -preload.rel = "preload"; -preload.as = "style"; -preload.href = "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css"; +var preload = document.createElement('link'); +preload.rel = 'preload'; +preload.as = 'style'; +preload.href = 'https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css'; document.head.appendChild(preload); function loadScript(src, callback) { - var script = document.createElement("script"); - script.type = "text/javascript"; + var script = document.createElement('script'); + script.type = 'text/javascript'; script.src = src; script.defer = true; if (callback) script.onload = callback; @@ -21,33 +21,42 @@ function loadScript(src, callback) { } function loadCSS(href, callback) { - var link = document.createElement("link"); - link.rel = "stylesheet"; + var link = document.createElement('link'); + link.rel = 'stylesheet'; link.href = href; - var supportsOnLoad = "onload" in link; + var supportsOnLoad = 'onload' in link; if (supportsOnLoad) { link.onload = callback; } else { - setTimeout(function() { + setTimeout(function () { callback(); }, 1000); } document.head.appendChild(link); } -loadCSS('https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css', function() {}); +loadCSS( + 'https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css', + function () {} +); -if (window.location.pathname === "/index.html" || window.location.pathname === "/") { - const options = ["Right-Click to access more features", "Set a custom background in settings.", "Tab Cloaking is highly recommended", "About:Blank Cloak is highly recommended", "This site was originally created for fun and educational purposes."]; +if (window.location.pathname === '/index.html' || window.location.pathname === '/') { + const options = [ + 'Right-Click to access more features', + 'Set a custom background in settings.', + 'Tab Cloaking is highly recommended', + 'About:Blank Cloak is highly recommended', + 'This site was originally created for fun and educational purposes.', + ]; function getRandomOption() { const randomNumber = Math.floor(Math.random() * options.length); return options[randomNumber]; } - const placeholder = document.getElementById("placeholder"); - const bar = document.querySelector(".browse-input"); - const search = document.getElementById("search"); + const placeholder = document.getElementById('placeholder'); + const bar = document.querySelector('.browse-input'); + const search = document.getElementById('search'); function setRandomPlaceholder() { if (!placeholder) return; @@ -57,26 +66,24 @@ if (window.location.pathname === "/index.html" || window.location.pathname === " setRandomPlaceholder(); if (bar && search) { - bar.addEventListener("focus", () => { - search.style.marginLeft = "-367px"; + bar.addEventListener('focus', () => { + search.style.marginLeft = '-367px'; }); - bar.addEventListener("blur", () => { - search.style.marginLeft = "-150px"; + bar.addEventListener('blur', () => { + search.style.marginLeft = '-150px'; }); } } -window.addEventListener("load", function() { +window.addEventListener('load', function () { // Register service worker for asset caching - if ("serviceWorker" in navigator) { - navigator.serviceWorker.register("/sw.js"); + if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('/sw.js'); } - loadScript("/worker.js"); - - if (window.location.pathname === "/index.html" || window.location.pathname === "/") { - location.href = "/math.html"; + if (window.location.pathname === '/index.html' || window.location.pathname === '/') { + location.href = '/math.html'; } if (window.location.pathname === '/loading.html') { diff --git a/static/sw.js b/static/sw.js index f95e4be..9189c2f 100644 --- a/static/sw.js +++ b/static/sw.js @@ -1 +1,70 @@ -importScripts("/uv/uv.bundle.js"),importScripts("/uv/uv.config.js"),importScripts("/uv/uv.sw.js");const CACHE_NAME="arctic-v1.0",urlsToCache=["/static/","/static/index.html","/static/settings.html","/static/assets/css/app.css","/static/assets/css/menu.css","/static/assets/js/particles.js","/static/assets/js/themes.js","/static/assets/js/index.js","/static/assets/js/anym.js","/static/assets/js/main.js","/static/assets/img/salyte.jpg","/static/android-chrome-192x192.png","/static/android-chrome-512x512.png","/static/wk/wk2.js","/static/wk/wk3.js"],uv=new UVServiceWorker;self.addEventListener("install",event=>{event.waitUntil(caches.open(CACHE_NAME).then(cache=>cache.addAll(urlsToCache.map(url=>new Request(url,{cache:"reload"}))))),self.skipWaiting()}),self.addEventListener("activate",event=>(event.waitUntil(caches.keys().then(cacheNames=>Promise.all(cacheNames.map(cacheName=>{if(cacheName!==CACHE_NAME)return caches.delete(cacheName)})))),self.clients.claim()));async function handleRequest(event){if(uv.route(event))return await uv.fetch(event);const cachedResponse=await caches.match(event.request);if(cachedResponse)return cachedResponse;try{const response=await fetch(event.request);if(response&&response.status===200&&response.type==="basic"){const responseToCache=response.clone();caches.open(CACHE_NAME).then(cache=>{cache.put(event.request,responseToCache)})}return response}catch{return await fetch(event.request)}}self.addEventListener("fetch",event=>{event.respondWith(handleRequest(event))}) +importScripts('/uv/uv.bundle.js'); +importScripts('/uv/uv.config.js'); +importScripts('/uv/uv.sw.js'); + +const CACHE_NAME = 'arctic-v1.0'; +const urlsToCache = [ + '/', + '/index.html', + '/settings.html', + '/assets/css/app.css', + '/assets/css/menu.css', + '/assets/js/particles.js', + '/assets/js/themes.js', + '/assets/js/index.js', + '/assets/js/anym.js', + '/assets/js/main.js', + '/assets/img/salyte.jpg', + '/wk/wk2.js', + '/wk/wk3.js', +]; + +const uv = new UVServiceWorker(); + +self.addEventListener('install', (event) => { + event.waitUntil( + caches + .open(CACHE_NAME) + .then((cache) => + cache.addAll(urlsToCache.map((url) => new Request(url, { cache: 'reload' }))) + ) + ); + self.skipWaiting(); +}); + +self.addEventListener('activate', (event) => { + event.waitUntil( + caches + .keys() + .then((cacheNames) => + Promise.all( + cacheNames.map((cacheName) => + cacheName !== CACHE_NAME ? caches.delete(cacheName) : undefined + ) + ) + ) + ); + self.clients.claim(); +}); + +async function handleRequest(event) { + if (uv.route(event)) return await uv.fetch(event); + + const cachedResponse = await caches.match(event.request); + if (cachedResponse) return cachedResponse; + + try { + const response = await fetch(event.request); + if (response && response.status === 200 && response.type === 'basic') { + const responseToCache = response.clone(); + caches.open(CACHE_NAME).then((cache) => cache.put(event.request, responseToCache)); + } + return response; + } catch { + return Response.error(); + } +} + +self.addEventListener('fetch', (event) => { + event.respondWith(handleRequest(event)); +});