Compare commits

...

48 Commits
master ... main

Author SHA1 Message Date
043d121847 Fix versions numbering 2025-06-07 22:51:14 -07:00
525064596f Version Bump 2025-06-07 22:47:28 -07:00
𓍼
7beb269867 version 2025-06-08 00:44:18 -05:00
𓍼
20d49560e9 stuff 2025-06-08 00:43:31 -05:00
𓍼
396b81929a forgot the dot 2025-06-07 22:13:23 -05:00
𓍼
b2ad89c28a remove subjects 2025-06-07 17:17:38 -05:00
𓍼
ee3092a590 Smaller 2025-06-07 16:56:39 -05:00
𓍼
265de4f542 UPDATEEEE 2025-06-07 16:54:12 -05:00
𓍼
c2a6cb8639 uh 2025-06-06 19:06:46 -05:00
𓍼
6fd71fa6fa ? 2025-06-06 19:02:40 -05:00
𓍼
994cb17641 hi 2025-06-06 19:01:51 -05:00
𓍼
c265e724c9 Fix latest commit 2025-06-06 12:52:49 -05:00
𓍼
dc72461a68 Fix latest commit 2025-06-06 12:44:31 -05:00
2b1a912478 Update others/scaler.mjs 2025-06-05 21:26:40 -07:00
78fbc42a0c Add others/scaler.mjs 2025-06-05 21:25:37 -07:00
65bc526a91 Delete others/scaler.mjs 2025-06-05 21:24:46 -07:00
bc878dfb64 Add others/scaler.mjs 2025-06-05 21:23:14 -07:00
a083758325 Delete others/scaler.mjs 2025-06-05 21:22:22 -07:00
b622f3cb9b Cool Thingy 2025-06-05 21:18:57 -07:00
ff50de3064 Update index.mjs 2025-06-05 21:12:54 -07:00
c13a708584 Update others/scaler.mjs 2025-06-05 21:12:21 -07:00
8845426001 60000 2025-06-05 21:10:10 -07:00
𓍼
89279a6735 Something 2025-06-05 22:52:01 -05:00
𓍼
526ec4f236 Merge branch 'main' of https://gitea.sentt.lol/sent/waves 2025-06-05 22:50:24 -05:00
𓍼
f78a14b79c Something 2025-06-05 22:49:17 -05:00
e50b65dde1 Update public/$.html 2025-06-01 19:53:00 -07:00
f0529b100e Update public/assets/js/register.js 2025-06-01 19:49:22 -07:00
4658e475ef idk 2025-06-01 19:40:51 -07:00
𓍼
7b3737d44c Rename the API 2025-05-25 17:41:29 -05:00
𓍼
91e44ce19a Remove ads on 1v1.LOL 2025-05-25 14:43:27 -05:00
𓍼
ac7cc48119 ok 2025-05-25 14:27:15 -05:00
𓍼
d9de280d3d Last update for today 2025-05-25 14:25:58 -05:00
𓍼
1fb3876cd4 Fixes 2025-05-25 14:24:32 -05:00
𓍼
c568949e74 cool 2025-05-25 12:48:11 -05:00
𓍼
6f84c2a9e5 okay 2025-05-25 12:34:36 -05:00
𓍼
97a6a4a94a Remove lat updated label and only keep latest commit id 2025-05-25 12:27:18 -05:00
𓍼
e1b5f73c31 Whoops 2025-05-25 09:50:37 -05:00
𓍼
87f8a54656 Wrong one 2025-05-25 09:49:18 -05:00
𓍼
84b0c084de only get latest update 2025-05-25 09:47:27 -05:00
𓍼
6a269bbaae Accidentaly remove the banned ad 2025-05-25 09:36:22 -05:00
𓍼
9f9a892798 wv 2025-05-25 09:33:51 -05:00
𓍼
ff7390d3ae Top 2025-05-25 09:32:20 -05:00
𓍼
7ae9abb1ad Remove a game (it wasn't supposed to be push) and update the verification script 2025-05-25 09:30:11 -05:00
𓍼
cd4c462e62 Small Update 🤍 2025-05-25 09:20:08 -05:00
𓍼
b5a927077a Back to DuckDuckGo 2025-05-22 11:48:45 -05:00
𓍼
5996c1a6e0 Brave? 2025-05-21 23:33:19 -05:00
𓍼
ffe52a61e7 Colors Change 2025-05-21 23:30:03 -05:00
4551ab18c1 Merge pull request 'Small Little Update' (#2) from master into main
Reviewed-on: https://gitea.sentt.lol/sent/waves/pulls/2
2025-05-21 21:24:35 -07:00
33 changed files with 2807 additions and 37096 deletions

View File

@ -4,7 +4,9 @@
The following versions of this project that are currently supported and unsupported: The following versions of this project that are currently supported and unsupported:
- **Version 2.3.5** Supported ✅ - **Version 2.8.9** Supported ✅
- **Version 2.8.7** Supported ✅
- **Version 2.8.5** Supported ✅
- **Version 2.3.1** Supported ✅ - **Version 2.3.1** Supported ✅
- **Version 2.3.0** Supported ✅ - **Version 2.3.0** Supported ✅
- **Version 2.2.0** Supported ✅ - **Version 2.2.0** Supported ✅
@ -17,4 +19,4 @@ The following versions of this project that are currently supported and unsuppor
## Support ## Support
If you are experiencing an issue with Waves unrelated to security, feel free to join our [Discord](https://discord.gg/dJvdkPRheV) server and open a ticket. If you are experiencing an issue with Waves unrelated to security, feel free to join our [Discord Server](https://discord.gg/dJvdkPRheV) and open a ticket.

173
index.mjs
View File

@ -2,8 +2,8 @@ import cluster from "cluster";
import os from "os"; import os from "os";
import net from "net"; import net from "net";
import fs from "fs"; import fs from "fs";
import { spawnSync } from "child_process";
import path from "path"; import path from "path";
import { spawnSync } from "child_process";
import express from "express"; import express from "express";
import { createServer } from "http"; import { createServer } from "http";
import compression from "compression"; import compression from "compression";
@ -23,28 +23,22 @@ function applySurgeAndRestartIfNeeded() {
try { try {
const config = JSON.parse(fs.readFileSync(surgeConfigPath, "utf-8")); const config = JSON.parse(fs.readFileSync(surgeConfigPath, "utf-8"));
process.env.UV_THREADPOOL_SIZE = String(config.uvThreadpoolSize); process.env.UV_THREADPOOL_SIZE = String(config.uvThreadpoolSize);
} catch { } catch {}
}
return; return;
} }
console.log('[~] Running Surge...');
const result = spawnSync("node", ["./others/surge.mjs"], { stdio: "inherit" }); const result = spawnSync("node", ["./others/surge.mjs"], { stdio: "inherit" });
if (result.error) { if (result.error) process.exit(1);
console.error('[!] Surger failed:', result.error);
process.exit(1);
}
const config = JSON.parse(fs.readFileSync(surgeConfigPath, "utf-8")); const config = JSON.parse(fs.readFileSync(surgeConfigPath, "utf-8"));
const nodeArgs = config.nodeFlags.concat([path.resolve("index.mjs"), "--surged"]); const nodeArgs = [...config.nodeFlags, path.resolve("index.mjs"), "--surged"];
const env = { const env = {
...process.env, ...process.env,
UV_THREADPOOL_SIZE: String(config.uvThreadpoolSize), UV_THREADPOOL_SIZE: String(config.uvThreadpoolSize),
ALREADY_SURGED: "true" ALREADY_SURGED: "true"
}; };
console.log(`[~] Relaunching with Node flags: ${config.nodeFlags.join(' ')}`); const relaunch = spawnSync(process.execPath, nodeArgs, { stdio: "inherit", env });
const relaunch = spawnSync(process.execPath, nodeArgs, { stdio: 'inherit', env });
process.exit(relaunch.status || 0); process.exit(relaunch.status || 0);
} }
@ -53,39 +47,40 @@ applySurgeAndRestartIfNeeded();
if (global.gc) { if (global.gc) {
setInterval(() => { setInterval(() => {
const { heapUsed, heapTotal } = process.memoryUsage(); const { heapUsed, heapTotal } = process.memoryUsage();
if (heapTotal > 0 && heapUsed / heapTotal > 0.7) { if (heapTotal > 0 && heapUsed / heapTotal > 0.8) global.gc();
global.gc(); }, 120000);
console.info('[~] Performed GC due to high heap usage');
}
}, 60_000);
} }
import './others/scaler.mjs'; import "./others/scaler.mjs";
import './others/warmup.mjs'; import "./others/warmup.mjs";
const cache = new LRUCache({
maxSize: 1000,
ttl: 4 * 24 * 60 * 60 * 1000,
allowStale: false,
});
const port = parseInt(process.env.PORT || "3000", 10); const port = parseInt(process.env.PORT || "3000", 10);
function logInfo(msg) { console.info(`[~] ${msg}`); } function logInfo(msg) {
function logSuccess(msg) { console.info(`[+] ${msg}`); } console.info(`[~] ${msg}`);
function logError(err) { console.error(`[!] ${err instanceof Error ? err.message : err}`); } }
function logSuccess(msg) {
console.info(`[+] ${msg}`);
}
function logError(err) {
console.error(`[!] ${err instanceof Error ? err.message : err}`);
}
process.on("uncaughtException", err => logError(`Unhandled Exception: ${err}`)); process.on("uncaughtException", err => logError(`Unhandled Exception: ${err}`));
process.on("unhandledRejection", reason => logError(`Unhandled Rejection: ${reason}`)); process.on("unhandledRejection", reason => logError(`Unhandled Rejection: ${reason}`));
if (cluster.isPrimary) { if (cluster.isPrimary) {
const cpus = os.cpus().length; const workers = Math.max(1, os.cpus().length - 1);
const workers = Math.max(1, cpus - 1); logInfo(`Master: forking ${workers} workers`);
logInfo(`Master: forking ${workers} of ${cpus} cores`);
for (let i = 0; i < workers; i++) cluster.fork();
cluster.on("exit", (worker, code, signal) => { for (let i = 0; i < workers; i++) {
logError(`Worker ${worker.process.pid} exited (code=${code}, signal=${signal}). Restarting...`); cluster.fork();
}
cluster.on("exit", worker => {
logError(`Worker ${worker.process.pid} exited. Restarting...`);
cluster.fork(); cluster.fork();
}); });
@ -98,23 +93,31 @@ if (cluster.isPrimary) {
}); });
server.on("error", err => logError(`Server error: ${err}`)); server.on("error", err => logError(`Server error: ${err}`));
server.listen(port, () => logSuccess(`Server listening on port ${port}`)); server.listen(port, () => logSuccess(`Server listening on ${port}`));
} else { } else {
const __dirname = process.cwd(); const __dirname = process.cwd();
const publicPath = path.join(__dirname, "public"); const publicPath = path.join(__dirname, "public");
const app = express(); const app = express();
const cache = new LRUCache({
max: 500,
ttl: 60_000,
allowStale: false
});
const latencySamples = new Array(200);
app.use(compression({ level: 4, memLevel: 4, threshold: 1024 })); app.use(compression({ level: 4, memLevel: 4, threshold: 1024 }));
app.use((req, res, next) => { app.use((req, res, next) => {
if (req.path.startsWith("/api/")) return next();
const key = req.originalUrl; const key = req.originalUrl;
const val = cache.get(key); const val = cache.get(key);
if (val) { if (val) {
res.setHeader("X-Cache", "HIT"); res.setHeader("X-Cache", "HIT");
return res.send(val); return res.send(val);
} }
res.sendResponse = res.send.bind(res); res.sendResponse = res.send;
res.send = body => { res.send = body => {
cache.set(key, body); cache.set(key, body);
res.setHeader("X-Cache", "MISS"); res.setHeader("X-Cache", "MISS");
@ -123,67 +126,97 @@ if (cluster.isPrimary) {
next(); next();
}); });
const staticOpts = { maxAge: "7d", immutable: true }; const staticOpts = { maxAge: "7d", immutable: true, etag: false };
app.use("/baremux/", express.static(baremuxPath, staticOpts)); app.use("/baremux/", express.static(baremuxPath, staticOpts));
app.use("/epoxy/", express.static(epoxyPath, staticOpts)); app.use("/epoxy/", express.static(epoxyPath, staticOpts));
app.use("/libcurl/", express.static(libcurlPath, staticOpts)); app.use("/libcurl/", express.static(libcurlPath, staticOpts));
app.use(express.static(publicPath, staticOpts)); app.use(express.static(publicPath, staticOpts));
app.use("/wah/", express.static(uvPath, staticOpts)); app.use("/wah/", express.static(uvPath, staticOpts));
app.use(express.json()); const sendHtml = file => (_req, res) => res.sendFile(path.join(publicPath, file));
const sendHtml = file => (req, res) => res.sendFile(path.join(publicPath, file)); app.get("/", sendHtml("$.html"));
app.get('/', sendHtml('$.html')); app.get("/g", sendHtml("!.html"));
app.get('/g', sendHtml('!.html')); app.get("/s", sendHtml("!!.html"));
app.get('/a', sendHtml('!!.html')); app.get("/resent", (_req, res) => res.sendFile(path.join(publicPath, "resent", "index.html")));
app.get('/resent', (req, res) => res.sendFile(path.join(publicPath, 'resent', 'index.html')));
app.use((req, res) => res.status(404).sendFile(path.join(publicPath, '404.html'))); app.get("/api/info", (_req, res) => {
const validSamples = latencySamples.filter(s => s !== undefined);
const average = validSamples.length ? validSamples.reduce((a, b) => a + b, 0) / validSamples.length : 0;
res.json({
speed: average < 200 ? "Fast" : average > 500 ? "Slow" : "Medium",
averageLatency: average.toFixed(2),
timestamp: Date.now()
});
});
app.use((_req, res) => res.status(404).sendFile(path.join(publicPath, "404.html")));
const server = createServer(app); const server = createServer(app);
server.keepAliveTimeout = 0; server.keepAliveTimeout = 5000;
server.headersTimeout = 0; server.headersTimeout = 10000;
const pingWSS = new WebSocket.Server({
noServer: true,
maxPayload: 16384,
perMessageDeflate: false
});
const pingWSS = new WebSocket.Server({ noServer: true, maxPayload: 4 * 1024 * 1024, perMessageDeflate: false });
pingWSS.on("connection", (ws, req) => { pingWSS.on("connection", (ws, req) => {
const remote = req.socket.remoteAddress || 'unknown'; const remote = req.socket.remoteAddress || "unknown";
let lat = []; const lat = [];
const interval = setInterval(() => { let sampleIndex = 0;
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'ping', timestamp: Date.now() }));
}, 1000); const sendPing = () => {
ws.on('message', msg => { if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: "ping", timestamp: Date.now() }));
}
};
const pingInterval = setInterval(sendPing, 500);
sendPing();
ws.on("message", msg => {
try { try {
const data = JSON.parse(msg); const data = JSON.parse(msg);
if (data.type === 'pong' && data.timestamp) { if (data.type === "pong" && data.timestamp) {
const d = Date.now() - data.timestamp; const d = Date.now() - data.timestamp;
lat.push(d); lat.push(d);
if (lat.length > 5) lat.shift(); if (lat.length > 10) lat.shift();
ws.send(JSON.stringify({ type: 'latency', latency: d }));
latencySamples[sampleIndex % latencySamples.length] = d;
sampleIndex = (sampleIndex + 1) % latencySamples.length;
ws.send(JSON.stringify({ type: "latency", latency: d }), { compress: false });
} }
} catch(e) { logError(`Ping error: ${e}`); } } catch {}
}); });
ws.on('close', () => {
clearInterval(interval); ws.on("close", () => {
const avg = lat.length ? (lat.reduce((a,b)=>a+b)/lat.length).toFixed(2) : 0; clearInterval(pingInterval);
logInfo(`WS ${remote} closed. Avg latency ${avg}ms`); const avg = lat.length ? (lat.reduce((a, b) => a + b) / lat.length).toFixed(2) : 0;
logInfo(`WS ${remote} closed. Avg: ${avg}ms`);
}); });
}); });
server.on('upgrade', (req, sock, head) => { server.on("upgrade", (req, sock, head) => {
if (req.url === '/w/ping') { if (req.url === "/w/ping") {
pingWSS.handleUpgrade(req, sock, head, ws => pingWSS.emit('connection', ws, req)); pingWSS.handleUpgrade(req, sock, head, ws =>
} else if (req.url.startsWith('/w/')) { pingWSS.emit("connection", ws, req)
);
} else if (req.url.startsWith("/w/")) {
wisp.routeRequest(req, sock, head); wisp.routeRequest(req, sock, head);
} else { } else {
sock.end(); sock.destroy();
} }
}); });
server.on('error', err => logError(`Worker server error: ${err}`)); server.on("error", err => logError(`Worker error: ${err}`));
server.listen(0, () => logSuccess(`Worker ${process.pid} ready`)); server.listen(0, () => logSuccess(`Worker ${process.pid} ready`));
process.on('message', (msg, conn) => { process.on("message", (msg, conn) => {
if (msg === 'sticky-session:connection' && conn) { if (msg === "sticky-session:connection" && conn) {
server.emit('connection', conn); server.emit("connection", conn);
conn.resume(); conn.resume();
} }
}); });

View File

@ -6,7 +6,7 @@ let cache = makeCache(maxKeys);
function makeCache(maxEntries) { function makeCache(maxEntries) {
return new LRUCache({ return new LRUCache({
maxSize: maxEntries, maxSize: maxEntries,
ttl: 4 * 24 * 60 * 60 * 1_000, ttl: 60_000,
allowStale: false, allowStale: false,
updateAgeOnGet: false, updateAgeOnGet: false,
updateAgeOnHas: false, updateAgeOnHas: false,

3340
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "waves", "name": "waves",
"version": "2.8.5", "version": "2.8.9",
"description": "A sleek and minimalist Web Proxy.", "description": "A sleek and minimalist Web Proxy.",
"type": "module", "type": "module",
"engines": { "engines": {
@ -21,16 +21,13 @@
"@mercuryworkshop/epoxy-transport": "latest", "@mercuryworkshop/epoxy-transport": "latest",
"@mercuryworkshop/libcurl-transport": "latest", "@mercuryworkshop/libcurl-transport": "latest",
"@titaniumnetwork-dev/ultraviolet": "latest", "@titaniumnetwork-dev/ultraviolet": "latest",
"axios": "^1.8.2", "axios": "latest",
"cache": "^3.0.0", "cache": "latest",
"compression": "latest", "compression": "latest",
"cors": "^2.8.5", "cors": "latest",
"express": "latest", "express": "latest",
"express-rate-limit": "^7.5.0", "express-rate-limit": "latest",
"fs": "^0.0.1-security", "lru-cache": "latest",
"node": "^23.9.0",
"lru-cache": "^11.1.0",
"node-fetch": "latest",
"wisp-server-node": "latest", "wisp-server-node": "latest",
"ws": "latest" "ws": "latest"
}, },

View File

@ -3,54 +3,80 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta property="og:title" content="Waves. - Apps"/> <meta property="og:title" content="Waves." />
<meta property="og:description" content="A sleek and minimalist web proxy."/> <meta property="og:description" content="A sleek and minimalist web proxy." />
<meta property="og:image" content="/assets/images/icons/favicon.ico"/> <meta property="og:image" content="/assets/images/icons/favicon.ico" />
<meta name="theme-color" content="#ffffff"/> <meta name="theme-color" content="#ffffff" />
<meta name="msapplication-TileColor" content="#ffffff"/> <meta name="msapplication-TileColor" content="#ffffff" />
<title>Waves.</title> <title>Waves.</title>
<link rel="icon" type="image/x-icon" href="/assets/images/icons/favicon.ico">
<link rel="stylesheet" href="/assets/css/$.css"> <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="stylesheet" href="/assets/css/settings.css">
<link rel="stylesheet" href="/assets/css/toast.css"> <link rel="icon" type="image/x-icon" href="/assets/images/icons/favicon.ico" />
<link rel="stylesheet" href="/assets/css/a.css">
<link href="https://cdn.jsdelivr.net/gh/aquawolf04/font-awesome-pro@5cd1511/css/all.css" rel="stylesheet"> <link rel="stylesheet" href="/assets/css/$.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script> <link rel="preload" href="/assets/css/settings.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<script async src="https://www.googletagmanager.com/gtag/js?id=G-WGJ2192JZY"></script><script>window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-WGJ2192JZY');</script> <link rel="preload" href="/assets/css/toast.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<script type='text/javascript' src='//pl26200262.effectiveratecpm.com/f0/e8/15/f0e81559842363ebf19aa99900ff2d02.js'></script> <link rel="preload" href="/assets/css/nprogress.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<link rel="preload" href="/assets/css/s.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<noscript>
<link rel="stylesheet" href="/assets/css/settings.css" />
<link rel="stylesheet" href="/assets/css/toast.css" />
<link rel="stylesheet" href="/assets/css/nprogress.css" />
<link rel="stylesheet" href="/assets/css/s.css" />
</noscript>
<link rel="preload" as="style" href="https://cdn.jsdelivr.net/gh/aquawolf04/font-awesome-pro@5cd1511/css/all.css" onload="this.onload=null;this.rel='stylesheet'" />
<noscript>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/aquawolf04/font-awesome-pro@5cd1511/css/all.css" />
</noscript>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-WGJ2192JZY"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "G-WGJ2192JZY");
</script>
</head> </head>
<body> <body>
<script src="/baremux/index.js"></script> <script src="/baremux/index.js" defer></script>
<script src="/assets/js/nprogress.js?v=0.2.0" defer></script>
<script src="/wah/uv.bundle.js" defer></script> <script src="/wah/uv.bundle.js" defer></script>
<script src="/wah/cute1.js" defer></script> <script src="/wah/cute1.js" defer></script>
<script src="/assets/js/navbar.js?v=2.8.4" defer></script>
<script src="/assets/js/load.js?v=2.8.4" defer></script>
<script src="/assets/js/eruda.js?v=2.8.4" defer></script> <script src="/assets/js/eruda.js?v=2.8.4" defer></script>
<script src="/assets/js/register.js?v=2.8.5" defer></script> <script src="/assets/js/register.js?v=2.8.9" defer></script>
<script src="/assets/js/settings.js?v=2.8.5" defer></script> <script src="/assets/js/settings.js?v=2.8.9" defer></script>
<script src="/assets/js/greetings.js?v=2.8.5" defer></script> <script src="/assets/js/greetings.js?v=2.8.9" defer></script>
<script src="/assets/js/shortcuts.js?v=2.8.4" defer></script> <script src="/assets/js/shortcuts.js?v=2.8.9" defer></script>
<script src="/assets/js/$.js?v=2.8.4" defer></script> <script src="/assets/js/$.js?v=2.8.9" defer></script>
<script src="/assets/js/a.js?v=2.8.4" defer></script> <script src="/assets/js/s.js?v=2.8.9" defer></script>
<script src="/assets/js/wv.js?v=1.4.1" defer></script>
<div class="relative flex flex-col h-[100vh] items-center justify-center bg-black transition-bg"> <div class="relative flex flex-col h-[100vh] items-center justify-center bg-black transition-bg">
<div class="absolute inset-0 overflow-hidden"> <div class="absolute inset-0 overflow-hidden">
<div class="god-rays absolute -inset-[10px] opacity-50"></div> <div class="god-rays absolute -inset-[10px] opacity-50"></div>
</div> </div>
</div> </div>
<div class="home-navbar"> <div class="home-navbar">
<img src="/assets/images/icons/favicon.ico" class="favicon"> <img src="/assets/images/icons/favicon.ico" class="favicon" alt="favicon" />
<span id="waves">Waves.</span> <span id="waves">Waves.</span>
<a href="/" id="home">Home</a> <a href="/" id="home">Home</a>
<a href="/g" id="games">Games</a> <a href="/g" id="games">Games</a>
<a href="/a" id="apps" style="color: #ffffff;">Apps</a> <a href="/s" id="shortcuts" style="color: #ffffff;">Shortcuts</a>
<a href="#" id="movies">Movies</a> <a href="#" id="movies">Movies</a>
<a href="#" id="ai">AI</a> <a href="#" id="ai">AI</a>
<a href="#" id="settings-icon"> <a href="#" id="settings-icon">
<i class="settings-icon fa-regular fa-gear"></i> <i class="settings-icon fa-regular fa-gear"></i>
</a> </a>
</div> </div>
<div id="settings-menu" class="settings-menu"></div> <div id="settings-menu" class="settings-menu"></div>
<div class="navbar"> <div class="navbar">
<ul class="nav-buttons"> <ul class="nav-buttons">
<li><a id="backIcon" href="#"><i class="fa-regular fa-arrow-left"></i></a></li> <li><a id="backIcon" href="#"><i class="fa-regular fa-arrow-left"></i></a></li>
@ -60,51 +86,70 @@
<li> <li>
<div class="small-searchbar" style="position: relative;"> <div class="small-searchbar" style="position: relative;">
<i id="lockIcon" class="fa-solid fa-lock"></i> <i id="lockIcon" class="fa-solid fa-lock"></i>
<input class="waves" type="text" id="searchInputt" <input class="waves" type="text" id="searchInputt" placeholder="Search for a query or enter a URL..." autocomplete="off" style="padding-left: 40px;" />
placeholder="Search for a query or enter a URL..." autocomplete="off"
style="padding-left: 40px;">
<span class="shortcut-indicator-2">Ctrl + S</span>
</div> </div>
</li> </li>
<li><a href="/"><i class="fa-regular fa-home"></i></a></li> <li><a href="/"><i class="fa-regular fa-home"></i></a></li>
<li><a href="/g"><i class="fa-regular fa-gamepad"></i></a></li> <li><a href="/g"><i class="fa-regular fa-gamepad"></i></a></li>
<li><a href="/a"><i class="fa-regular fa-grid-2"></i></a></li> <li><a href="/s"><i class="fa-regular fa-rocket"></i></a></li>
<li><a id="erudaIcon" href="#"><i class="fa-regular fa-code"></i></a></li> <li><a id="erudaIcon" href="#"><i class="fa-regular fa-code"></i></a></li>
</ul> </ul>
</div> </div>
<div class="content apps-page">
<h1>Apps</h1> <div class="content shortcuts-page">
<div class="apps-search-bar"> <h1>Shortcuts</h1>
<input type="text" id="appSearchInput" placeholder="Search apps..." autocomplete="off" /> <div class="shortcuts-search-bar">
<input type="text" id="shortcutSearchInput" placeholder="Search shortcuts..." autocomplete="off" />
<span class="shortcut-indicator-4">Ctrl + S</span> <span class="shortcut-indicator-4">Ctrl + S</span>
</div> </div>
<div class="apps-grid"> <div class="shortcuts-grid"></div>
</div>
</div> </div>
<div id="erudaLoadingScreen" style="display: none;">Eruda is loading...</div>
<div id="overlay" class="overlay"></div> <div id="overlay" class="overlay"></div>
<div id="namePrompt" class="popup"> <div id="namePrompt" class="popup">
<div class="input-container"> <div class="input-container">
<label for="userName">Please enter a name so we know what to call you:</label> <label for="userName">Please enter a name so we know what to call you:</label>
<div class="input-wrapper"> <div class="input-wrapper">
<input type="text" id="userName" placeholder="Your name" oninput="checkInput()" autocomplete="off" /> <input type="text" id="userName" placeholder="Your name" autocomplete="off" />
</div> </div>
<button id="doneButton" onclick="submitName()" disabled> <button id="doneButton" onclick="submitName()" disabled><i class="fa-regular fa-check"></i> Done</button>
<i class="fas fa-check"></i> Done
</button>
</div> </div>
</div> </div>
<div id="erudaLoadingScreen" style="display: none;">Eruda is loading...</div>
<iframe id="cool-iframe" class="iframe"></iframe> <iframe id="cool-iframe" class="iframe"></iframe>
<script type='text/javascript' src='//pl26200346.effectiveratecpm.com/08/db/84/08db842da9b43ad3d13c14634f9fd1c8.js'></script>
<script type="text/javascript"> <script defer>
atOptions = { document.addEventListener("DOMContentLoaded", function () {
'key' : '26bce7e7832b24b139944832990cf69d', NProgress.configure({ showSpinner: false });
'format' : 'iframe', NProgress.start();
'height' : 300,
'width' : 160, const titleElement = document.querySelector(".search-title");
'params' : {} if (titleElement) {
}; const text = titleElement.textContent.trim();
titleElement.textContent = "";
text.split("").forEach((letter, i) => {
const span = document.createElement("span");
span.textContent = letter;
span.style.animationDelay = `${i * 0.05}s`;
titleElement.appendChild(span);
});
}
window.addEventListener("load", function () {
NProgress.done();
});
});
</script>
<script>
requestIdleCallback(() => {
const ad = document.createElement("script");
ad.src = "//pl26200346.effectiveratecpm.com/08/db/84/08db842da9b43ad3d13c14634f9fd1c8.js";
ad.async = true;
document.body.appendChild(ad);
});
</script> </script>
<script type="text/javascript" src="//spaniardinformationbookworm.com/26bce7e7832b24b139944832990cf69d/invoke.js"></script>
</body> </body>
</html> </html>

View File

@ -3,54 +3,80 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta property="og:title" content="Waves. - Games"/> <meta property="og:title" content="Waves." />
<meta property="og:description" content="A sleek and minimalist web proxy."/> <meta property="og:description" content="A sleek and minimalist web proxy." />
<meta property="og:image" content="/assets/images/icons/favicon.ico"/> <meta property="og:image" content="/assets/images/icons/favicon.ico" />
<meta name="theme-color" content="#ffffff"/> <meta name="theme-color" content="#ffffff" />
<meta name="msapplication-TileColor" content="#ffffff"/> <meta name="msapplication-TileColor" content="#ffffff" />
<title>Waves.</title> <title>Waves.</title>
<link rel="icon" type="image/x-icon" href="/assets/images/icons/favicon.ico">
<link rel="stylesheet" href="/assets/css/$.css"> <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="stylesheet" href="/assets/css/settings.css">
<link rel="stylesheet" href="/assets/css/toast.css"> <link rel="icon" type="image/x-icon" href="/assets/images/icons/favicon.ico" />
<link rel="stylesheet" href="/assets/css/g.css">
<link href="https://cdn.jsdelivr.net/gh/aquawolf04/font-awesome-pro@5cd1511/css/all.css" rel="stylesheet" /> <link rel="stylesheet" href="/assets/css/$.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script> <link rel="preload" href="/assets/css/settings.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<script async src="https://www.googletagmanager.com/gtag/js?id=G-WGJ2192JZY"></script><script>window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-WGJ2192JZY');</script> <link rel="preload" href="/assets/css/toast.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<script type='text/javascript' src='//pl26200262.effectiveratecpm.com/f0/e8/15/f0e81559842363ebf19aa99900ff2d02.js'></script> <link rel="preload" href="/assets/css/nprogress.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<link rel="preload" href="/assets/css/g.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<noscript>
<link rel="stylesheet" href="/assets/css/settings.css" />
<link rel="stylesheet" href="/assets/css/toast.css" />
<link rel="stylesheet" href="/assets/css/nprogress.css" />
<link rel="stylesheet" href="/assets/css/g.css" />
</noscript>
<link rel="preload" as="style" href="https://cdn.jsdelivr.net/gh/aquawolf04/font-awesome-pro@5cd1511/css/all.css" onload="this.onload=null;this.rel='stylesheet'" />
<noscript>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/aquawolf04/font-awesome-pro@5cd1511/css/all.css" />
</noscript>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-WGJ2192JZY"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "G-WGJ2192JZY");
</script>
</head> </head>
<body> <body>
<script src="/baremux/index.js"></script> <script src="/baremux/index.js" defer></script>
<script src="/assets/js/nprogress.js?v=0.2.0" defer></script>
<script src="/wah/uv.bundle.js" defer></script> <script src="/wah/uv.bundle.js" defer></script>
<script src="/wah/cute1.js" defer></script> <script src="/wah/cute1.js" defer></script>
<script src="/assets/js/navbar.js?v=2.8.4" defer></script>
<script src="/assets/js/load.js?v=2.8.4" defer></script>
<script src="/assets/js/eruda.js?v=2.8.4" defer></script> <script src="/assets/js/eruda.js?v=2.8.4" defer></script>
<script src="/assets/js/register.js?v=2.8.5" defer></script> <script src="/assets/js/register.js?v=2.8.9" defer></script>
<script src="/assets/js/settings.js?v=2.8.5" defer></script> <script src="/assets/js/settings.js?v=2.8.9" defer></script>
<script src="/assets/js/greetings.js?v=2.8.5" defer></script> <script src="/assets/js/greetings.js?v=2.8.9" defer></script>
<script src="/assets/js/shortcuts.js?v=2.8.4" defer></script> <script src="/assets/js/shortcuts.js?v=2.8.9" defer></script>
<script src="/assets/js/$.js?v=2.8.4" defer></script> <script src="/assets/js/$.js?v=2.8.9" defer></script>
<script src="/assets/js/g.js?v=2.8.4" defer></script> <script src="/assets/js/g.js?v=2.8.9" defer></script>
<script src="/assets/js/wv.js?v=1.4.1" defer></script>
<div class="relative flex flex-col h-[100vh] items-center justify-center bg-black transition-bg"> <div class="relative flex flex-col h-[100vh] items-center justify-center bg-black transition-bg">
<div class="absolute inset-0 overflow-hidden"> <div class="absolute inset-0 overflow-hidden">
<div class="god-rays absolute -inset-[10px] opacity-50"></div> <div class="god-rays absolute -inset-[10px] opacity-50"></div>
</div> </div>
</div> </div>
<div class="home-navbar"> <div class="home-navbar">
<img src="/assets/images/icons/favicon.ico" class="favicon"> <img src="/assets/images/icons/favicon.ico" class="favicon" alt="favicon" />
<span id="waves">Waves.</span> <span id="waves">Waves.</span>
<a href="/" id="home">Home</a> <a href="/" id="home">Home</a>
<a href="/g" id="games" style="color: #ffffff;">Games</a> <a href="/g" id="games" style="color: #ffffff;">Games</a>
<a href="/a" id="apps">Apps</a> <a href="/s" id="apps">Shortcuts</a>
<a href="#" id="movies">Movies</a> <a href="#" id="movies">Movies</a>
<a href="#" id="ai">AI</a> <a href="#" id="ai">AI</a>
<a href="#" id="settings-icon"> <a href="#" id="settings-icon">
<i class="settings-icon fa-regular fa-gear"></i> <i class="settings-icon fa-regular fa-gear"></i>
</a> </a>
</div> </div>
<div id="settings-menu" class="settings-menu"></div> <div id="settings-menu" class="settings-menu"></div>
<div class="navbar"> <div class="navbar">
<ul class="nav-buttons"> <ul class="nav-buttons">
<li><a id="backIcon" href="#"><i class="fa-regular fa-arrow-left"></i></a></li> <li><a id="backIcon" href="#"><i class="fa-regular fa-arrow-left"></i></a></li>
@ -60,51 +86,70 @@
<li> <li>
<div class="small-searchbar" style="position: relative;"> <div class="small-searchbar" style="position: relative;">
<i id="lockIcon" class="fa-solid fa-lock"></i> <i id="lockIcon" class="fa-solid fa-lock"></i>
<input class="waves" type="text" id="searchInputt" <input class="waves" type="text" id="searchInputt" placeholder="Search for a query or enter a URL..." autocomplete="off" style="padding-left: 40px;" />
placeholder="Search for a query or enter a URL..." autocomplete="off"
style="padding-left: 40px;">
<span class="shortcut-indicator-2">Ctrl + S</span>
</div> </div>
</li> </li>
<li><a href="/"><i class="fa-regular fa-home"></i></a></li> <li><a href="/"><i class="fa-regular fa-home"></i></a></li>
<li><a href="/g"><i class="fa-regular fa-gamepad"></i></a></li> <li><a href="/g"><i class="fa-regular fa-gamepad"></i></a></li>
<li><a href="/a"><i class="fa-regular fa-grid-2"></i></a></li> <li><a href="/s"><i class="fa-regular fa-rocket"></i></a></li>
<li><a id="erudaIcon" href="#"><i class="fa-regular fa-code"></i></a></li> <li><a id="erudaIcon" href="#"><i class="fa-regular fa-code"></i></a></li>
</ul> </ul>
</div> </div>
<div class="content games-page"> <div class="content games-page">
<h1>Games</h1> <h1>Games</h1>
<div class="games-search-bar"> <div class="games-search-bar">
<input type="text" id="gameSearchInput" placeholder="Search games..." autocomplete="off" /> <input type="text" id="gameSearchInput" placeholder="Search games..." autocomplete="off" />
<span class="shortcut-indicator-3">Ctrl + S</span> <span class="shortcut-indicator-3">Ctrl + S</span>
</div> </div>
<div class="games-grid"> <div class="games-grid"></div>
</div>
</div> </div>
<div id="erudaLoadingScreen" style="display: none;">Eruda is loading...</div>
<div id="overlay" class="overlay"></div> <div id="overlay" class="overlay"></div>
<div id="namePrompt" class="popup"> <div id="namePrompt" class="popup">
<div class="input-container"> <div class="input-container">
<label for="userName">Please enter a name so we know what to call you:</label> <label for="userName">Please enter a name so we know what to call you:</label>
<div class="input-wrapper"> <div class="input-wrapper">
<input type="text" id="userName" placeholder="Your name" oninput="checkInput()" autocomplete="off" /> <input type="text" id="userName" placeholder="Your name" autocomplete="off" />
</div> </div>
<button id="doneButton" onclick="submitName()" disabled> <button id="doneButton" onclick="submitName()" disabled><i class="fa-regular fa-check"></i> Done</button>
<i class="fas fa-check"></i> Done
</button>
</div> </div>
</div> </div>
<div id="erudaLoadingScreen" style="display: none;">Eruda is loading...</div>
<iframe id="cool-iframe" class="iframe"></iframe> <iframe id="cool-iframe" class="iframe"></iframe>
<script type='text/javascript' src='//pl26200346.effectiveratecpm.com/08/db/84/08db842da9b43ad3d13c14634f9fd1c8.js'></script>
<script type="text/javascript"> <script defer>
atOptions = { document.addEventListener("DOMContentLoaded", function () {
'key' : '26bce7e7832b24b139944832990cf69d', NProgress.configure({ showSpinner: false });
'format' : 'iframe', NProgress.start();
'height' : 300,
'width' : 160, const titleElement = document.querySelector(".search-title");
'params' : {} if (titleElement) {
}; const text = titleElement.textContent.trim();
titleElement.textContent = "";
text.split("").forEach((letter, i) => {
const span = document.createElement("span");
span.textContent = letter;
span.style.animationDelay = `${i * 0.05}s`;
titleElement.appendChild(span);
});
}
window.addEventListener("load", function () {
NProgress.done();
});
});
</script>
<script>
requestIdleCallback(() => {
const ad = document.createElement("script");
ad.src = "//pl26200346.effectiveratecpm.com/08/db/84/08db842da9b43ad3d13c14634f9fd1c8.js";
ad.async = true;
document.body.appendChild(ad);
});
</script> </script>
<script type="text/javascript" src="//spaniardinformationbookworm.com/26bce7e7832b24b139944832990cf69d/invoke.js"></script>
</body> </body>
</html> </html>

View File

@ -1,60 +1,78 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta property="og:title" content="Waves."/> <meta property="og:title" content="Waves." />
<meta property="og:description" content="A sleek and minimalist web proxy."/> <meta property="og:description" content="A sleek and minimalist web proxy." />
<meta property="og:image" content="/assets/images/icons/favicon.ico"/> <meta property="og:image" content="/assets/images/icons/favicon.ico" />
<meta name="theme-color" content="#ffffff"/> <meta name="theme-color" content="#ffffff" />
<meta name="msapplication-TileColor" content="#ffffff"/> <meta name="msapplication-TileColor" content="#ffffff" />
<title>Waves.</title> <title>Waves.</title>
<link rel="icon" type="image/x-icon" href="/assets/images/icons/favicon.ico">
<link rel="stylesheet" href="/assets/css/$.css"> <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="stylesheet" href="/assets/css/settings.css">
<link rel="stylesheet" href="/assets/css/toast.css"> <link rel="icon" type="image/x-icon" href="/assets/images/icons/favicon.ico" />
<link href="https://cdn.jsdelivr.net/gh/aquawolf04/font-awesome-pro@5cd1511/css/all.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css"> <link rel="stylesheet" href="/assets/css/$.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-WGJ2192JZY"></script><script>window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-WGJ2192JZY');</script> <link rel="preload" href="/assets/css/settings.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<script type='text/javascript' src='//pl26200262.effectiveratecpm.com/f0/e8/15/f0e81559842363ebf19aa99900ff2d02.js'></script> <link rel="preload" href="/assets/css/toast.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<style> <link rel="preload" href="/assets/css/nprogress.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
body { <noscript>
overflow: hidden; <link rel="stylesheet" href="/assets/css/settings.css" />
<link rel="stylesheet" href="/assets/css/toast.css" />
<link rel="stylesheet" href="/assets/css/nprogress.css" />
</noscript>
<link rel="preload" as="style" href="https://cdn.jsdelivr.net/gh/aquawolf04/font-awesome-pro@5cd1511/css/all.css" onload="this.onload=null;this.rel='stylesheet'" />
<noscript>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/aquawolf04/font-awesome-pro@5cd1511/css/all.css" />
</noscript>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-WGJ2192JZY"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
} }
</style> gtag("js", new Date());
gtag("config", "G-WGJ2192JZY");
</script>
</head> </head>
<body> <body>
<script src="/baremux/index.js"></script> <script src="/baremux/index.js"></script>
<script src="/assets/js/nprogress.js?v=0.2.0" defer></script>
<script src="/wah/uv.bundle.js" defer></script> <script src="/wah/uv.bundle.js" defer></script>
<script src="/wah/cute1.js" defer></script> <script src="/wah/cute1.js" defer></script>
<script src="/assets/js/navbar.js?v=2.8.4" defer></script>
<script src="/assets/js/load.js?v=2.8.4" defer></script>
<script src="/assets/js/eruda.js?v=2.8.4" defer></script> <script src="/assets/js/eruda.js?v=2.8.4" defer></script>
<script src="/assets/js/register.js?v=2.8.5" defer></script> <script src="/assets/js/register.js?v=2.8.9" defer></script>
<script src="/assets/js/settings.js?v=2.8.5" defer></script> <script src="/assets/js/settings.js?v=2.8.9" defer></script>
<script src="/assets/js/ping.js?v=2.8.4" defer></script> <script src="/assets/js/ping.js?v=2.8.9" defer></script>
<script src="/assets/js/greetings.js?v=2.8.5" defer></script> <script src="/assets/js/greetings.js?v=2.8.9" defer></script>
<script src="/assets/js/shortcuts.js?v=2.8.4" defer></script> <script src="/assets/js/shortcuts.js?v=2.8.9" defer></script>
<script src="/assets/js/$.js?v=2.8.4" defer></script> <script src="/assets/js/$.js?v=2.8.9" defer></script>
<div class="relative flex flex-col h-[100vh] items-center justify-center bg-white transition-bg"> <script src="/assets/js/wv.js?v=1.4.1" defer></script>
<div class="relative flex flex-col h-[100vh] items-center justify-center bg-black transition-bg">
<div class="absolute inset-0 overflow-hidden"> <div class="absolute inset-0 overflow-hidden">
<div class="god-rays absolute -inset-[10px] opacity-50"></div> <div class="god-rays absolute -inset-[10px] opacity-50"></div>
</div> </div>
</div> </div>
<div class="home-navbar"> <div class="home-navbar">
<img src="/assets/images/icons/favicon.ico" class="favicon"> <img src="/assets/images/icons/favicon.ico" class="favicon" />
<span id="waves">Waves.</span> <span id="waves">Waves.</span>
<a href="/" id="home" style="color: #ffffff;">Home</a> <a href="/" id="home" style="color: #ffffff;">Home</a>
<a href="/g" id="games">Games</a> <a href="/g" id="games">Games</a>
<a href="/a" id="apps">Apps</a> <a href="/s" id="apps">Shortcuts</a>
<a href="#" id="movies">Movies</a> <a href="#" id="movies">Movies</a>
<a href="#" id="ai">AI</a> <a href="#" id="ai">AI</a>
<a href="#" id="settings-icon"> <a href="#" id="settings-icon"><i class="settings-icon fa-regular fa-gear"></i></a>
<i id="settings-icon" class="settings-icon fa-regular fa-gear"></i>
</a>
</div> </div>
<div id="settings-menu" class="settings-menu"></div> <div id="settings-menu" class="settings-menu"></div>
<div class="navbar"> <div class="navbar">
<ul class="nav-buttons"> <ul class="nav-buttons">
<li><a id="backIcon" href="#"><i class="fa-regular fa-arrow-left"></i></a></li> <li><a id="backIcon" href="#"><i class="fa-regular fa-arrow-left"></i></a></li>
@ -64,51 +82,91 @@
<li> <li>
<div class="small-searchbar" style="position: relative;"> <div class="small-searchbar" style="position: relative;">
<i id="lockIcon" class="fa-solid fa-lock"></i> <i id="lockIcon" class="fa-solid fa-lock"></i>
<input class="waves" type="text" id="searchInputt" <input class="waves" type="text" id="searchInputt" placeholder="Search for a query or enter a URL..." autocomplete="off" style="padding-left: 40px;" />
placeholder="Search for a query or enter a URL..." autocomplete="off"
style="padding-left: 40px;">
<span class="shortcut-indicator-2">Ctrl + S</span> <span class="shortcut-indicator-2">Ctrl + S</span>
</div> </div>
</li> </li>
<li><a href="/"><i class="fa-regular fa-home"></i></a></li> <li><a href="/"><i class="fa-regular fa-home"></i></a></li>
<li><a href="/g"><i class="fa-regular fa-gamepad"></i></a></li> <li><a href="/g"><i class="fa-regular fa-gamepad"></i></a></li>
<li><a href="/a"><i class="fa-regular fa-grid-2"></i></a></li> <li><a href="/s"><i class="fa-regular fa-rocket"></i></a></li>
<li><a id="erudaIcon" href="#"><i class="fa-regular fa-code"></i></a></li> <li><a id="erudaIcon" href="#"><i class="fa-regular fa-code"></i></a></li>
</ul> </ul>
</div> </div>
<div class="search-container"> <div class="search-container">
<div class="search-title">Waves.</div> <div class="search-title">Waves.</div>
<div class="search-bar"> <div class="search-bar">
<input class="waves" type="text" id="searchInput" placeholder="What's been on your mind lately?" autocomplete="off"> <input class="waves" type="text" id="searchInput" placeholder="What's been on your mind lately?" autocomplete="off" />
<span class="shortcut-indicator">Ctrl + S</span> <span class="shortcut-indicator">Ctrl + S</span>
</div> </div>
</div> </div>
<div id="erudaLoadingScreen" style="display: none;">Eruda is loading...</div> <div id="erudaLoadingScreen" style="display: none;">Eruda is loading...</div>
<div id="overlay" class="overlay"></div> <div id="overlay" class="overlay"></div>
<div id="namePrompt" class="popup"> <div id="namePrompt" class="popup">
<div class="input-container"> <div class="input-container">
<label for="userName">Please enter a name so we know what to call you:</label> <label for="userName">Please enter a name so we know what to call you:</label>
<div class="input-wrapper"> <div class="input-wrapper">
<input type="text" id="userName" placeholder="Your name" autocomplete="off"> <input type="text" id="userName" placeholder="Your name" autocomplete="off" />
</div> </div>
<button id="doneButton" onclick="submitName()" disabled> <button id="doneButton" onclick="submitName()" disabled><i class="fa-regular fa-check"></i> Done</button>
<i class="fa-regular fa-check"></i> Done
</button>
</div> </div>
</div> </div>
<div id="pingDisplay">Ping: Connecting...</div>
<div id="pingDisplay"><i class="fas fa-satellite-dish"></i> Ping: Connecting...</div>
<div id="greeting"></div> <div id="greeting"></div>
<iframe id="cool-iframe" class="iframe"></iframe> <iframe id="cool-iframe" class="iframe"></iframe>
<script type='text/javascript' src='//pl26200346.effectiveratecpm.com/08/db/84/08db842da9b43ad3d13c14634f9fd1c8.js'></script> <div id="hi">Hii,</div>
<script type="text/javascript">
atOptions = { <div id="copyright">
'key' : '26bce7e7832b24b139944832990cf69d', <i class="fa-regular fa-copyright"></i> 2025
'format' : 'iframe', <a class="hover-link" href="https://discord.gg/ire" target="_blank" rel="noopener noreferrer"><span class="copyrightname">Waves Services</span></a>.
'height' : 300, All Rights Reserved.
'width' : 160, </div>
'params' : {}
}; <div id="discord">
<a class="hover-link" href="https://discord.gg/ire" target="_blank" rel="noopener noreferrer">
<i class="fa-brands fa-discord"></i> Discord
</a>
</div>
<div id="github">
<a class="hover-link" href="https://github.com/xojw/waves" target="_blank" rel="noopener noreferrer">
<i class="fa-brands fa-github"></i> Github
</a>
</div>
<script defer>
document.addEventListener("DOMContentLoaded", function () {
NProgress.configure({ showSpinner: false });
NProgress.start();
const titleElement = document.querySelector(".search-title");
if (titleElement) {
const text = titleElement.textContent.trim();
titleElement.textContent = "";
text.split("").forEach((letter, i) => {
const span = document.createElement("span");
span.textContent = letter;
span.style.animationDelay = `${i * 0.05}s`;
titleElement.appendChild(span);
});
}
window.addEventListener("load", function () {
NProgress.done();
});
});
</script>
<script>
requestIdleCallback(() => {
const ad = document.createElement("script");
ad.src = "//pl26200346.effectiveratecpm.com/08/db/84/08db842da9b43ad3d13c14634f9fd1c8.js";
ad.async = true;
document.body.appendChild(ad);
});
</script> </script>
<script type="text/javascript" src="//spaniardinformationbookworm.com/26bce7e7832b24b139944832990cf69d/invoke.js"></script>
</body> </body>
</html> </html>

View File

@ -1 +0,0 @@
google.com, pub-7835554576835583, DIRECT, f08c47fec0942fa0

View File

@ -7,6 +7,7 @@ body {
color: #e0e0e0; color: #e0e0e0;
overflow-x: hidden; overflow-x: hidden;
transition: background-color 0.3s ease; transition: background-color 0.3s ease;
animation: fadeIn 0.3s ease;
scroll-behavior: smooth; scroll-behavior: smooth;
position: relative; position: relative;
z-index: 1; z-index: 1;
@ -54,7 +55,7 @@ body {
color: #ffffff; color: #ffffff;
display: inline-block; display: inline-block;
text-align: left; text-align: left;
margin: 1px 80px 0 10px; margin: 1px 75px 0 10px;
white-space: nowrap; white-space: nowrap;
cursor: default; cursor: default;
transition: all 0.3s ease; transition: all 0.3s ease;
@ -62,7 +63,7 @@ body {
.home-navbar { .home-navbar {
transform: translateX(-50%); transform: translateX(-50%);
width: 670px; width: 700px;
top: 1%; top: 1%;
margin-bottom: -10px; margin-bottom: -10px;
margin-left: 50%; margin-left: 50%;
@ -71,7 +72,6 @@ body {
height: 35px; height: 35px;
color: #818181; color: #818181;
padding: 10px; padding: 10px;
animation: fadeIn 2s ease;
text-align: center; text-align: center;
font-size: 18px; font-size: 18px;
font-weight: bold; font-weight: bold;
@ -86,14 +86,14 @@ body {
} }
.home-navbar .favicon { .home-navbar .favicon {
width: 24px; width: 28px;
height: 24px; height: 24px;
margin-right: -10px; margin-right: -9px;
vertical-align: middle; vertical-align: middle;
} }
.home-navbar a { .home-navbar a {
color: #afafaf; color: #7c7c7c;
text-decoration: none; text-decoration: none;
padding: 8px 16px; padding: 8px 16px;
font-size: 14px; font-size: 14px;
@ -104,7 +104,8 @@ body {
} }
.home-navbar a:hover { .home-navbar a:hover {
font-size: 16px; color: #bbbbbb;
font-size: 18px;
} }
.home-navbar a:active { .home-navbar a:active {
@ -113,8 +114,8 @@ body {
.home-navbar i { .home-navbar i {
color: #ffffff; color: #ffffff;
margin-right: -15px; margin-right: -19px;
margin-left: 115px; margin-left: 119px;
} }
.navbar { .navbar {
@ -222,6 +223,26 @@ body {
color: #818181; color: #818181;
} }
.shortcut-indicator {
position: absolute;
top: 50%;
left: 50%;
transform: translate(calc(-50% + 235px), -50%);
font-size: 12px;
font-weight: 500;
color: #000000;
background-color: #c4c4c4;
padding: 2px 6px;
border-radius: 7px;
cursor: pointer;
transition: all 0.3s ease;
animation: fadeIn 0.3s ease;
}
.shortcut-indicator:hover {
background-color: #ffffff;
}
.shortcut-indicator-2 { .shortcut-indicator-2 {
position: absolute; position: absolute;
top: 50%; top: 50%;
@ -235,12 +256,20 @@ body {
border-radius: 7px; border-radius: 7px;
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: all 0.3s ease;
animation: fadeUp 0.3s ease;
} }
.shortcut-indicator-2:hover { .shortcut-indicator-2:hover {
background-color: #ffffff; background-color: #ffffff;
} }
.arrow-mode {
display: inline-block;
margin-left: 17px;
transition: all 0.3s ease;
animation: fadeIn 0.3s ease;
}
#lockIcon { #lockIcon {
position: absolute; position: absolute;
left: 25px; left: 25px;
@ -255,7 +284,6 @@ body {
margin-top: 20%; margin-top: 20%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
animation: fadeIn 2s ease;
text-align: center; text-align: center;
width: 90%; width: 90%;
} }
@ -265,7 +293,7 @@ body {
font-weight: bolder; font-weight: bolder;
text-align: center; text-align: center;
display: inline-block; display: inline-block;
background: linear-gradient(-45deg, #4e4e4e, #ffffff); background: linear-gradient(-45deg, #8d8d8d, #ffffff);
-webkit-background-clip: text; -webkit-background-clip: text;
background-clip: text; background-clip: text;
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;
@ -274,16 +302,13 @@ body {
transition: all 0.3s ease; transition: all 0.3s ease;
} }
.search-title span { .search-title span {
display: inline-block; display: inline-block;
background: inherit;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
opacity: 0; opacity: 0;
transform: translateX(-50px); background: inherit;
animation: fadeInFromLeft 0.5s ease-in-out forwards; color: transparent;
transform: translateY(4rem);
animation: fadeSlideIn 0.6s forwards;
} }
.search-bar { .search-bar {
@ -323,25 +348,6 @@ body {
color: #ffffff69; color: #ffffff69;
} }
.shortcut-indicator {
position: absolute;
top: 50%;
left: 50%;
transform: translate(calc(-50% + 235px), -50%);
font-size: 12px;
font-weight: 500;
color: #000000;
background-color: #c4c4c4;
padding: 2px 6px;
border-radius: 7px;
cursor: pointer;
transition: all 0.3s ease;
}
.shortcut-indicator:hover {
background-color: #ffffff;
}
#erudaLoadingScreen { #erudaLoadingScreen {
position: fixed; position: fixed;
top: 50%; top: 50%;
@ -387,13 +393,13 @@ body {
} }
.hover-link { .hover-link {
color: #949494; color: #b3b3b3;
text-decoration: none; text-decoration: none;
transition: color 0.3s ease; transition: color 0.3s ease;
} }
.hover-link:hover { .hover-link:hover {
color: #dadada; color: #ffffff;
} }
#pingDisplay { #pingDisplay {
@ -401,10 +407,9 @@ body {
margin-top: -46px; margin-top: -46px;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
font-weight: bold; font-weight: 550;
color: #888888; color: #888888;
cursor: default; cursor: default;
animation: fadeIn 2s ease;
padding: 5px 10px; padding: 5px 10px;
transition: all 0.3s ease; transition: all 0.3s ease;
z-index: -1; z-index: -1;
@ -412,7 +417,7 @@ body {
} }
#pingDisplay:hover { #pingDisplay:hover {
color: #b6b6b6; color: #d3d3d3;
} }
.god-rays { .god-rays {
@ -426,7 +431,6 @@ body {
background-image: var(--stripes), var(--rays); background-image: var(--stripes), var(--rays);
background-size: 300%, 200%; background-size: 300%, 200%;
background-position: 50% 50%, 50% 50%; background-position: 50% 50%, 50% 50%;
animation: fadeIn 2s ease;
mask-image: radial-gradient(ellipse at 100% 0%, transparent 40%, transparent 70%); mask-image: radial-gradient(ellipse at 100% 0%, transparent 40%, transparent 70%);
-webkit-mask-image: radial-gradient(ellipse at 100% 0%, white 40%, transparent 70%); -webkit-mask-image: radial-gradient(ellipse at 100% 0%, white 40%, transparent 70%);
pointer-events: none; pointer-events: none;
@ -456,7 +460,7 @@ body {
display: none; display: none;
opacity: 0; opacity: 0;
transition: opacity 0.3s ease-in-out; transition: opacity 0.3s ease-in-out;
animation: fadeInOverlay 0.3s ease-in-out forwards; animation: fadeIn 0.3s ease-in-out forwards;
} }
#namePrompt { #namePrompt {
@ -572,7 +576,6 @@ body {
position: fixed; position: fixed;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
animation: fadeIn 2s ease;
opacity: 0; opacity: 0;
transition: all 0.3s ease; transition: all 0.3s ease;
cursor: default; cursor: default;
@ -580,42 +583,98 @@ body {
} }
#greeting:hover { #greeting:hover {
color: #b6b6b6; color: #d3d3d3;
} }
#namePrompt.fade-out { #namePrompt.fade-out {
animation: fadeOutPrompt 0.3s ease-in-out forwards; animation: fadeOut 0.3s ease-in-out forwards;
} }
@keyframes fadeInFromLeft { #hi {
0% { position: fixed;
opacity: 0; bottom: 10px;
transform: translateX(-50px); left: 10px;
} z-index: 9999;
background-color: #08080894;
100% { border: 1px solid #ffffff21;
opacity: 1; color: #aaaaaa;
transform: translateX(0); font-weight: 540;
} transition: all 0.3s ease;
cursor: default;
padding: 8px 12px;
border-radius: 15px;
font-size: 14px;
} }
@keyframes fadeIn { #hi:hover {
from { color: #ffffff;
opacity: 0; }
}
#copyright {
position: fixed;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
z-index: 9999;
background-color: #08080894;
border: 1px solid #ffffff21;
color: #858585;
font-weight: 540;
transition: all 0.3s ease;
cursor: default;
padding: 8px 12px;
border-radius: 15px;
font-size: 14px;
}
#copyright:hover {
color: #afafaf;
}
#discord {
position: fixed;
bottom: 10px;
right: 100px;
z-index: 9999;
background-color: #08080894;
border: 1px solid #ffffff21;
color: #858585;
font-weight: 540;
transition: all 0.3s ease;
cursor: default;
padding: 8px 12px;
border-radius: 15px;
font-size: 14px;
}
#github {
position: fixed;
bottom: 10px;
right: 10px;
z-index: 9999;
background-color: #08080894;
border: 1px solid #ffffff21;
color: #858585;
font-weight: 540;
transition: all 0.3s ease;
cursor: default;
padding: 8px 12px;
border-radius: 15px;
font-size: 14px;
}
.fadeIn {
animation: fadeIn 0.3s ease-in-out forwards;
}
.fadeOut {
animation: fadeOut 0.3s ease-in-out forwards;
}
@keyframes fadeSlideIn {
to { to {
opacity: 1; opacity: 1;
} transform: translateY(0);
}
@keyframes fadeInOverlay {
0% {
opacity: 0;
}
100% {
opacity: 1;
} }
} }
@ -631,7 +690,17 @@ body {
} }
} }
@keyframes fadeOutPrompt { @keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeOut {
0% { 0% {
opacity: 1; opacity: 1;
} }
@ -651,47 +720,6 @@ body {
} }
} }
@keyframes swing {
0%,
100% {
transform: rotate(3deg);
}
50% {
transform: rotate(-3deg);
}
}
@keyframes steamLarge {
0% {
stroke-dashoffset: 13;
opacity: 0.6;
}
100% {
stroke-dashoffset: 39;
opacity: 0;
}
}
@keyframes steamSmall {
10% {
stroke-dashoffset: 9;
opacity: 0.6;
}
80% {
stroke-dashoffset: 27;
opacity: 0;
}
100% {
stroke-dashoffset: 27;
opacity: 0;
}
}
@keyframes spin { @keyframes spin {
0% { 0% {
transform: rotate(0deg); transform: rotate(0deg);

View File

@ -5,7 +5,6 @@
} }
.games-page h1 { .games-page h1 {
animation: fadeIn 2s ease;
font-size: 2.5rem; font-size: 2.5rem;
margin-bottom: 20px; margin-bottom: 20px;
color: #fff; color: #fff;
@ -82,7 +81,6 @@
margin-top: 20px; margin-top: 20px;
margin-bottom: 20px; margin-bottom: 20px;
color: #a8a8a8; color: #a8a8a8;
animation: fadeIn 2s ease;
position: relative; position: relative;
} }

View File

@ -0,0 +1 @@
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translate(0,-4px);-ms-transform:rotate(3deg) translate(0,-4px);transform:rotate(3deg) translate(0,-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner 400ms linear infinite;animation:nprogress-spinner 400ms linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}

View File

@ -1,17 +1,16 @@
.apps-page { .shortcuts-page {
padding: 100px 20px 40px; padding: 100px 20px 40px;
text-align: center; text-align: center;
position: relative; position: relative;
} }
.apps-page h1 { .shortcuts-page h1 {
animation: fadeIn 2s ease;
font-size: 2.5rem; font-size: 2.5rem;
margin-bottom: 20px; margin-bottom: 20px;
color: #fff; color: #fff;
} }
.apps-grid { .shortcuts-grid {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
@ -22,14 +21,14 @@
margin: 0 auto; margin: 0 auto;
} }
.content.apps-page { .content.shortcuts-page {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
text-align: center; text-align: center;
} }
.app-card { .shortcut-card {
background-color: #08080894; background-color: #08080894;
border-radius: 25px; border-radius: 25px;
padding: 15px 20px; padding: 15px 20px;
@ -49,7 +48,7 @@
animation: fadeIn 2s ease; animation: fadeIn 2s ease;
} }
.app-card img { .shortcut-card img {
width: 100%; width: 100%;
height: 200px; height: 200px;
object-fit: cover; object-fit: cover;
@ -58,40 +57,39 @@
transition: all 0.3s ease; transition: all 0.3s ease;
} }
.app-card:hover img { .shortcut-card:hover img {
filter: brightness(1); filter: brightness(1);
} }
.app-card:hover { .shortcut-card:hover {
background-color: #333333; background-color: #333333;
} }
.app-card h2 { .shortcut-card h2 {
font-size: 1rem; font-size: 1rem;
margin: 10px 0; margin: 10px 0;
color: #fff; color: #fff;
} }
.app-card p { .shortcut-card p {
font-size: 1rem; font-size: 1rem;
color: #ccc; color: #ccc;
} }
.apps-search-bar { .shortcuts-search-bar {
text-align: center; text-align: center;
margin-top: 20px; margin-top: 20px;
margin-bottom: 20px; margin-bottom: 20px;
color: #a8a8a8; color: #a8a8a8;
animation: fadeIn 2s ease;
position: relative; position: relative;
} }
#appSearchInput { #shortcutSearchInput {
padding: 14px 30px; padding: 14px 30px;
border: 1px solid #ffffff1a; border: 1px solid #ffffff1a;
background-image: url('/assets/images/icons/search.png'); background-image: url('/assets/images/icons/search.png');
background-size: 35px 35px; background-size: 35px 35px;
background-position: 10px center; background-position: 5px center;
background-repeat: no-repeat; background-repeat: no-repeat;
padding-left: 45px; padding-left: 45px;
border-radius: 20px; border-radius: 20px;
@ -104,12 +102,12 @@
transition: all 0.3s ease; transition: all 0.3s ease;
} }
#appSearchInput:focus, #shortcutSearchInput:focus,
#appSearchInput:hover { #shortcutSearchInput:hover {
border: 1px solid #ffffff69; border: 1px solid #ffffff69;
} }
#appSearchInput::placeholder { #shortcutSearchInput::placeholder {
color: #a8a8a8; color: #a8a8a8;
} }

View File

@ -63,7 +63,7 @@
#close-settings:hover { #close-settings:hover {
transform: rotate(90deg); transform: rotate(90deg);
color: #d3d3d3; color: #ffffff;
} }
#close-settings i { #close-settings i {
@ -91,11 +91,12 @@
max-width: 300px; max-width: 300px;
margin-bottom: 15px; margin-bottom: 15px;
} }
.transport-selected { .transport-selected {
background-color: #141414; background-color: #141414;
border: 1px solid #ffffff1a;
color: #e0e0e0; color: #e0e0e0;
padding: 10px; padding: 10px;
border: 1px solid #4141411a;
border-radius: 15px; border-radius: 15px;
cursor: pointer; cursor: pointer;
display: flex; display: flex;
@ -136,8 +137,7 @@
opacity: 0; opacity: 0;
} }
.transport-options.transport-show, .transport-options.transport-show {
.server-options.transport-show {
max-height: 200px; max-height: 200px;
opacity: 1; opacity: 1;
} }
@ -159,7 +159,7 @@
margin-left: -80px; margin-left: -80px;
background-color: #141414; background-color: #141414;
color: #e0e0e0; color: #e0e0e0;
border: 1px solid #4141411a; border: 1px solid #ffffff1a;
border-radius: 15px; border-radius: 15px;
font-size: 15px; font-size: 15px;
outline: none; outline: none;

View File

@ -32,6 +32,10 @@
display: inline-block; display: inline-block;
} }
.toast i {
margin-right: 8px;
}
.toast.show { .toast.show {
animation: slideIn 0.3s forwards; animation: slideIn 0.3s forwards;
} }
@ -51,6 +55,21 @@
animation: progress 3s linear forwards; animation: progress 3s linear forwards;
} }
.toast .toast-close {
background: none;
border: none;
color: #888888;
font-size: 18px;
cursor: pointer;
padding: 0;
margin-left: 10px;
transition: 0.3s;
}
.toast-close:hover {
color: #ffffff;
}
@keyframes slideIn { @keyframes slideIn {
0% { 0% {
right: -300px; right: -300px;
@ -80,18 +99,3 @@
width: 0%; width: 0%;
} }
} }
.toast .toast-close {
background: none;
border: none;
color: #888888;
font-size: 18px;
cursor: pointer;
padding: 0;
margin-left: 10px;
transition: 0.3s;
}
.toast-close:hover {
color: #d3d3d3;
}

View File

@ -1,5 +1,5 @@
{ {
"apps": [ "shortcuts": [
{ {
"icon": "/assets/images/a/crazygames.jpg", "icon": "/assets/images/a/crazygames.jpg",
"title": "Crazy Games", "title": "Crazy Games",

View File

@ -13,7 +13,6 @@
<script> <script>
var gameLoaded = false; var gameLoaded = false;
window.addEventListener("beforeunload", function (e) { window.addEventListener("beforeunload", function (e) {
if (adsVisible || !gameLoaded || !lockedOccured) return null;
var confirmationMessage = "Are you sure you want to leave? "; var confirmationMessage = "Are you sure you want to leave? ";
(e || window.event).returnValue = confirmationMessage; //Gecko + IE (e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc. return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
@ -86,52 +85,10 @@
}, },
}); });
</script> </script>
<!-- MIDROLL/INTERSTITIAL VIDEO API -->
<script src="js/cpmstar.js"></script>
</head> </head>
<body> <body>
<div class="ads">
<div class="ad-smallscreen">
<div class="ad ad-rectangle-bottom"></div>
</div>
<div class="ad ad-rectangle-upper" id="adRectangleUpper">
<!-- 300X250B PLACEMENT TAG - PLACE INTO BODY (ZONE TAG REQUIRED) -->
<script>
(function (w, pid) {
var r = function (c, m) {
c = c.split("").reduce(function (a, b) {
return ((a << 5) - a + b.charCodeAt(0)) >>> m;
}, 0);
return (10 + ((c * 7) % 26)).toString(36) + c.toString(36);
},
y = r(w.location.href.split("#")[0], 1),
c = r(w.location.href.split("#")[0] + pid, 0);
w.document.write('<div style="width:300px;height:250px" class="' + c + '"></div>');
})(window, 83023);
</script>
</div>
<div class="ad-largescreen">
<div class="ad ad-leaderboard-bottom">
<!-- 300X600B PLACEMENT TAG - PLACE INTO BODY (ZONE TAG REQUIRED) -->
<script>
(function (w, pid) {
var r = function (c, m) {
c = c.split("").reduce(function (a, b) {
return ((a << 5) - a + b.charCodeAt(0)) >>> m;
}, 0);
return (10 + ((c * 7) % 26)).toString(36) + c.toString(36);
},
y = r(w.location.href.split("#")[0], 1),
c = r(w.location.href.split("#")[0] + pid, 0);
w.document.write('<div style="width:300px;height:600px" class="' + c + '"></div>');
})(window, 85420);
</script>
</div>
</div>
</div>
<!-- <div id="interAdsContainer" style="display: none;"></div> -->
<div id="gameContainer"></div> <div id="gameContainer"></div>
<div id="loader"> <div id="loader">
<img class="logo" src="logo.png" /> <img class="logo" src="logo.png" />
@ -222,55 +179,6 @@
var refreshNextTime = true; var refreshNextTime = true;
function showAds() {
document.getElementsByClassName("ad-rectangle-bottom")[0].style.display = "block";
document.getElementsByClassName("ad-leaderboard-bottom")[0].style.display = "block";
document.getElementById("adRectangleUpper").style.display = "block";
if (typeof counter === "undefined") {
startCounter();
resumeCounter();
} else {
resumeCounter();
refresh();
}
}
function hideAds() {
document.getElementsByClassName("ad-rectangle-bottom")[0].style.display = "none";
document.getElementsByClassName("ad-leaderboard-bottom")[0].style.display = "none";
document.getElementById("adRectangleUpper").style.display = "none";
pauseCounter();
}
// hide ads
hideAds();
function refresh() {
//console.log("time since ads refresh = " + timeSinceRefresh + " seconds");
//console.log("time ads visible = " + timeAdsVisible + " seconds");
if (timeSinceRefresh <= 30 || timeAdsVisible <= 2) {
//console.log("don't refresh");
return;
}
if (document.getElementById("adRectangleBottom") != null && window.getComputedStyle(document.getElementsByClassName("ad-smallscreen")[0]).display != "none") {
cpmstarAPI({ kind: "adcmd", module: "POOL 83023", command: "refresh" });
}
if (document.getElementById("adLeaderboardBottom") != null && window.getComputedStyle(document.getElementsByClassName("ad-largescreen")[0]).display != "none") {
cpmstarAPI({ kind: "adcmd", module: "POOL 85420", command: "refresh" });
}
cpmstarAPI({ kind: "adcmd", module: "POOL 83025", command: "refresh" });
timeSinceRefresh = 0;
timeAdsVisible = 0;
//console.log("refresh ads");
}
window.onfocus = function () { window.onfocus = function () {
//console.log("onfocus"); //console.log("onfocus");
resumeCounter(); resumeCounter();
@ -283,26 +191,16 @@
}; };
var timeSinceRefresh = 0; var timeSinceRefresh = 0;
var timeAdsVisible = 0;
var counter; var counter;
var adsVisible = false;
function startCounter() { function startCounter() {
timeSinceRefresh++; timeSinceRefresh++;
if (adsVisible) timeAdsVisible++;
counter = setTimeout(function () { counter = setTimeout(function () {
startCounter(); startCounter();
}, 1000); }, 1000);
} }
function resumeCounter() {
adsVisible = true;
}
function pauseCounter() {
adsVisible = false;
}
</script> </script>
<!-- Firebase App (the core Firebase SDK) is always required and must be listed first --> <!-- Firebase App (the core Firebase SDK) is always required and must be listed first -->
<script src="firebase/firebase-app.js"></script> <script src="firebase/firebase-app.js"></script>

View File

@ -1,293 +1,478 @@
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const historyStack = [] window.APP = {};
let currentIndex = -1
const refreshIcon = document.getElementById('refreshIcon') const iframe = document.getElementById('cool-iframe');
const fullscreenIcon = document.getElementById('fullscreenIcon') const erudaLoadingScreen = document.getElementById('erudaLoadingScreen');
const backIcon = document.getElementById('backIcon') const searchInput1 = document.getElementById('searchInput');
const forwardIcon = document.getElementById('forwardIcon') const movies = document.getElementById('movies');
const iframe = document.getElementById('cool-iframe') const ai = document.getElementById('ai');
const erudaLoadingScreen = document.getElementById('erudaLoadingScreen') const topBar = document.querySelector('.topbar');
if (!refreshIcon || !fullscreenIcon || !backIcon || !forwardIcon || !iframe) return const refreshIcon = document.getElementById('refreshIcon');
const originalTitle = document.title const fullscreenIcon = document.getElementById('fullscreenIcon');
let loadingHidden = false const backIcon = document.getElementById('backIcon');
function showLoadingScreen(withToast = true, showEruda = false) { const forwardIcon = document.getElementById('forwardIcon');
loadingHidden = false const searchInput2 = document.getElementById('searchInputt');
NProgress.start() const lockIcon = document.getElementById('lockIcon');
document.title = 'Loading... <3' const navbarToggle = document.getElementById('navbar-toggle');
const navBar = document.querySelector('.navbar');
const historyStack = [];
let currentIndex = -1;
const originalTitle = document.title;
let isLoading = false;
if (!iframe || !refreshIcon || !fullscreenIcon || !backIcon || !forwardIcon) {
return;
}
const animationStyle = document.createElement('style');
animationStyle.textContent = `
@keyframes slideLeft {0% { transform: translateX(0); } 50% { transform: translateX(-5px); } 100% { transform: translateX(0); }}
@keyframes slideRight {0% { transform: translateX(0); } 50% { transform: translateX(5px); } 100% { transform: translateX(0); }}
.button-animate-back { animation: slideLeft 0.3s ease-in-out; }
.button-animate-forward { animation: slideRight 0.3s ease-in-out; }
.spin { animation: spinAnimation 0.3s linear; }
@keyframes spinAnimation { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
`;
document.head.appendChild(animationStyle);
function showLoadingScreen(withToast = true) {
if (isLoading) return;
isLoading = true;
if (typeof NProgress !== 'undefined') NProgress.start();
if (withToast) { if (withToast) {
showToast( showToast(
'Consider joining our <a href="https://discord.gg/dJvdkPRheV" target="_blank" class="hover-link">Discord</a>&nbsp;<3', 'Consider joining our <a href="https://discord.gg/dJvdkPRheV" target="_blank" class="hover-link">Discord</a>&nbsp;<3',
'success', 'success',
'heart' 'heart'
) );
} }
} }
function hideLoadingScreen() { function hideLoadingScreen() {
if (loadingHidden) return if (!isLoading) return;
loadingHidden = true if (typeof NProgress !== 'undefined') NProgress.done();
NProgress.done() document.title = originalTitle;
document.title = originalTitle isLoading = false;
if (erudaLoadingScreen) erudaLoadingScreen.style.display = 'none';
} }
refreshIcon.addEventListener('click', () => {
refreshIcon.classList.add('spin')
if (iframe.tagName === 'IFRAME') {
const currentUrl = iframe.contentWindow.location.href
if (normalizeUrl(currentUrl) !== normalizeUrl(historyStack[currentIndex] || '')) {
addToHistory(currentUrl)
}
iframe.contentWindow.location.reload(true)
}
setTimeout(() => refreshIcon.classList.remove('spin'), 300)
})
fullscreenIcon.addEventListener('click', () => {
if (iframe.requestFullscreen) iframe.requestFullscreen()
else if (iframe.mozRequestFullScreen) iframe.mozRequestFullScreen()
else if (iframe.webkitRequestFullscreen) iframe.webkitRequestFullscreen()
else if (iframe.msRequestFullscreen) iframe.msRequestFullscreen()
})
backIcon.addEventListener('click', () => {
if (currentIndex > 0) {
currentIndex--
iframe.src = historyStack[currentIndex]
showLoadingScreen(false, false)
updateNavButtons()
updateDecodedSearchInput()
}
})
forwardIcon.addEventListener('click', () => {
if (currentIndex < historyStack.length - 1) {
currentIndex++
iframe.src = historyStack[currentIndex]
showLoadingScreen(false, false)
updateNavButtons()
updateDecodedSearchInput()
}
})
function normalizeUrl(urlStr) { function normalizeUrl(urlStr) {
if (!urlStr || urlStr === 'about:blank') return urlStr;
try { try {
const url = new URL(urlStr) const url = new URL(urlStr);
url.searchParams.delete('ia') url.searchParams.delete('ia');
return url.toString() return url.toString();
} catch { } catch {
return urlStr return urlStr;
} }
} }
function addToHistory(url) {
const normalized = normalizeUrl(url) function decodeUrl(encodedUrl) {
if (currentIndex >= 0 && normalizeUrl(historyStack[currentIndex]) === normalized) return if (!encodedUrl) return '';
if (currentIndex < historyStack.length - 1) historyStack.splice(currentIndex + 1) try {
historyStack.push(url) const prefix = (typeof __uv$config !== 'undefined' && __uv$config.prefix) ? __uv$config.prefix : '/wa/a/';
currentIndex++ const decodeFunction = (typeof __uv$config !== 'undefined' && __uv$config.decodeUrl) ? __uv$config.decodeUrl : decodeURIComponent;
updateNavButtons() const urlObject = new URL(encodedUrl, window.location.origin);
updateDecodedSearchInput() if (urlObject.pathname.startsWith(prefix)) {
const encodedPart = urlObject.pathname.slice(prefix.length);
return decodeFunction(encodedPart) + urlObject.search + urlObject.hash;
} }
} catch {}
try {
return decodeURIComponent(encodedUrl);
} catch {
return encodedUrl;
}
}
function updateNavButtons() { function updateNavButtons() {
backIcon.disabled = currentIndex <= 0 if (!backIcon || !forwardIcon) return;
forwardIcon.disabled = currentIndex >= historyStack.length - 1 const canGoBack = currentIndex > 0;
backIcon.classList.toggle('disabled', currentIndex <= 0) const canGoForward = currentIndex < historyStack.length - 1;
forwardIcon.classList.toggle('disabled', currentIndex >= historyStack.length - 1) backIcon.disabled = !canGoBack;
forwardIcon.disabled = !canGoForward;
backIcon.classList.toggle('disabled', !canGoBack);
forwardIcon.classList.toggle('disabled', !canGoForward);
} }
function updateDecodedSearchInput() { function updateDecodedSearchInput() {
const searchInput2 = document.getElementById('searchInputt') if (!searchInput2) return;
if (!searchInput2) return let currentUrl = '';
let url = ''
if (currentIndex >= 0 && historyStack[currentIndex]) { if (currentIndex >= 0 && historyStack[currentIndex]) {
url = historyStack[currentIndex] currentUrl = historyStack[currentIndex];
} else if (iframe.src) { } else if (iframe.src && iframe.src !== 'about:blank') {
url = iframe.src currentUrl = iframe.src;
} }
searchInput2.value = decodeUrl(url) const decoded = decodeUrl(currentUrl);
const lockIcon = document.getElementById('lockIcon') searchInput2.value = decoded;
if (lockIcon) { if (lockIcon) {
lockIcon.className = decodeUrl(url).startsWith('https://') ? const isSecure = decoded.startsWith('https://');
'fa-regular fa-lock' : lockIcon.className = isSecure ? 'fa-regular fa-lock' : 'fa-regular fa-lock-open';
'fa-regular fa-lock-open'
lockIcon.style.color = ''
} }
} }
iframe.addEventListener('load', () => {
function addToHistory(url, isReplacingCurrent = false) {
if (!url || url === 'about:blank') return;
const normalizedNewUrl = normalizeUrl(url);
const currentHistoryEntry = historyStack[currentIndex];
const normalizedCurrentHistoryEntry = currentIndex >= 0 ? normalizeUrl(currentHistoryEntry) : null;
if (isReplacingCurrent && currentIndex >= 0) {
if (normalizedCurrentHistoryEntry !== normalizedNewUrl || currentHistoryEntry !== url) {
historyStack[currentIndex] = url;
} else {
return;
}
} else {
if (normalizedCurrentHistoryEntry === normalizedNewUrl && currentHistoryEntry === url) {
return;
}
if (currentIndex < historyStack.length - 1) {
historyStack.splice(currentIndex + 1);
}
historyStack.push(url);
currentIndex++;
}
updateNavButtons();
updateDecodedSearchInput();
}
function generateSubject() {
const subjects = ['math', 'science', 'history', 'art', 'programming', 'philosophy'];
const randomSubject = subjects[Math.floor(Math.random() * subjects.length)];
try { try {
hideLoadingScreen() history.replaceState({}, '', `/learning?subject=${randomSubject}`);
} catch { } catch (e) {}
hideLoadingScreen()
} finally {
if (erudaLoadingScreen) erudaLoadingScreen.style.display = 'none'
} }
})
iframe.addEventListener('error', () => { function setupIframeNavigationListeners() {
hideLoadingScreen() try {
}) const iframeWindow = iframe.contentWindow;
if (!iframeWindow || iframeWindow === window || iframeWindow.location.href === 'about:blank') return;
const handleNav = (isReplace = false) => {
setTimeout(() => {
try {
const newUrlInIframe = iframeWindow.location.href;
if (newUrlInIframe === 'about:blank' && historyStack[currentIndex] === 'about:blank') return;
addToHistory(newUrlInIframe, isReplace);
} catch (e) {}
}, 0);
};
if (!iframeWindow.history.pushState.__isPatched) {
const originalPushState = iframeWindow.history.pushState;
iframeWindow.history.pushState = function(...args) {
originalPushState.apply(this, args);
handleNav(false);
};
iframeWindow.history.pushState.__isPatched = true;
}
if (!iframeWindow.history.replaceState.__isPatched) {
const originalReplaceState = iframeWindow.history.replaceState;
iframeWindow.history.replaceState = function(...args) {
originalReplaceState.apply(this, args);
handleNav(true);
};
iframeWindow.history.replaceState.__isPatched = true;
}
iframeWindow.removeEventListener('popstate', iframeWindow.__popstateHandler);
iframeWindow.__popstateHandler = () => handleNav(false);
iframeWindow.addEventListener('popstate', iframeWindow.__popstateHandler);
iframeWindow.removeEventListener('hashchange', iframeWindow.__hashchangeHandler);
iframeWindow.__hashchangeHandler = () => handleNav(false);
iframeWindow.addEventListener('hashchange', iframeWindow.__hashchangeHandler);
} catch (error) {}
}
iframe.addEventListener('loadstart', () => { iframe.addEventListener('loadstart', () => {
const navBar = document.querySelector('.navbar') showLoadingScreen(false);
const navbarToggle = document.getElementById('navbar-toggle') if (navbarToggle && navbarToggle.checked && navBar) {
if (navbarToggle && navbarToggle.checked && navBar) navBar.style.display = 'block' navBar.style.display = 'block';
showLoadingScreen(false, false)
})
const navBar = document.querySelector('.navbar')
const topBar = document.querySelector('.topbar')
const searchInput1 = document.getElementById('searchInput')
const searchInput2 = document.getElementById('searchInputt')
const movies = document.getElementById('movies')
const ai = document.getElementById('ai')
const navbarToggle = document.getElementById('navbar-toggle')
if (navbarToggle && navBar) {
const savedNavbarState = localStorage.getItem('navbarToggled')
navbarToggle.checked = savedNavbarState === null ? true : savedNavbarState === 'true'
navBar.style.display = iframe.style.display === 'block' && navbarToggle.checked ? 'block' : 'none'
navbarToggle.addEventListener('change', () => {
localStorage.setItem('navbarToggled', navbarToggle.checked)
navBar.style.display = iframe.style.display === 'block' && navbarToggle.checked ? 'block' : 'none'
})
} }
iframe.style.display = 'none' });
window.addEventListener('load', hideLoadingScreen)
;[searchInput1, searchInput2].forEach(input => { iframe.addEventListener('load', () => {
hideLoadingScreen();
try {
const newUrl = iframe.contentWindow ? iframe.contentWindow.location.href : iframe.src;
if (newUrl && newUrl !== 'about:blank') {
if (currentIndex === -1 || normalizeUrl(historyStack[currentIndex]) !== normalizeUrl(newUrl) || historyStack[currentIndex] !== newUrl) {
addToHistory(newUrl);
} else if (historyStack[currentIndex] !== newUrl) {
addToHistory(newUrl, true);
}
} else if (newUrl === 'about:blank' && historyStack.length > 0 && historyStack[currentIndex] !== 'about:blank') {
if (currentIndex > 0) {
const previousUrl = historyStack[currentIndex - 1];
currentIndex--;
iframe.src = previousUrl;
return;
}
}
setupIframeNavigationListeners();
generateSubject();
if (navbarToggle && navbarToggle.checked && navBar) {
navBar.style.display = 'block';
}
} catch (error) {} finally {
updateNavButtons();
updateDecodedSearchInput();
}
});
iframe.addEventListener('error', () => {
hideLoadingScreen();
showToast('Error: Could not load page content.', 'error', 'times-circle');
updateNavButtons();
updateDecodedSearchInput();
});
function toggleButtonAnimation(button, animationClass) {
if (button) {
button.classList.add(animationClass);
setTimeout(() => button.classList.remove(animationClass), 200);
}
}
backIcon.addEventListener('click', () => {
toggleButtonAnimation(backIcon, 'button-animate-back');
if (currentIndex > 0) {
currentIndex--;
showLoadingScreen(false);
iframe.src = historyStack[currentIndex];
updateNavButtons();
updateDecodedSearchInput();
}
});
forwardIcon.addEventListener('click', () => {
toggleButtonAnimation(forwardIcon, 'button-animate-forward');
if (currentIndex < historyStack.length - 1) {
currentIndex++;
showLoadingScreen(false);
iframe.src = historyStack[currentIndex];
updateNavButtons();
updateDecodedSearchInput();
}
});
refreshIcon.addEventListener('click', () => {
if (refreshIcon) refreshIcon.classList.add('spin');
if (iframe.contentWindow) {
showLoadingScreen(false);
const currentIframeUrl = iframe.contentWindow.location.href;
if (normalizeUrl(currentIframeUrl) !== normalizeUrl(historyStack[currentIndex] || '')) {
addToHistory(currentIframeUrl);
}
iframe.contentWindow.location.reload(true);
}
if (refreshIcon) setTimeout(() => refreshIcon.classList.remove('spin'), 300);
});
fullscreenIcon.addEventListener('click', () => {
if (iframe.requestFullscreen) iframe.requestFullscreen();
else if (iframe.mozRequestFullScreen) iframe.mozRequestFullScreen();
else if (iframe.webkitRequestFullscreen) iframe.webkitRequestFullscreen();
else if (iframe.msRequestFullscreen) iframe.msRequestFullscreen();
});
function generateSearchUrl(query) {
query = query.trim();
if (!query) return `https://duckduckgo.com/?q=&ia=web`;
if (/^[a-zA-Z]+:\/\//.test(query)) {
try {
new URL(query);
return query;
} catch (e) {}
}
if (/^(localhost|(\d{1,3}\.){3}\d{1,3})(:\d+)?(\/.*)?$/.test(query) || query.toLowerCase() === "localhost") {
if (!query.toLowerCase().startsWith("http:") && !query.toLowerCase().startsWith("https:")) {
return `http://${query}`;
}
return query;
}
try {
const urlWithHttps = new URL(`https://${query}`);
if (urlWithHttps.hostname &&
urlWithHttps.hostname.includes('.') &&
!urlWithHttps.hostname.endsWith('.') &&
urlWithHttps.hostname !== '.' &&
urlWithHttps.hostname.split('.').pop().length >= 2 &&
!/^\d+$/.test(urlWithHttps.hostname.split('.').pop())
) {
return urlWithHttps.toString();
}
} catch (e) {}
return `https://duckduckgo.com/?q=${encodeURIComponent(query)}&ia=web`;
}
async function getUrl(url) {
if (typeof __uv$config !== 'undefined' && __uv$config.encodeUrl) {
return Promise.resolve(__uv$config.prefix + __uv$config.encodeUrl(url));
}
return Promise.resolve(url);
}
function clearBackground() {
const preservedElements = [
navBar, iframe, document.querySelector('.loading-screen'),
erudaLoadingScreen, topBar
].filter(el => el != null);
Array.from(document.body.children).forEach(child => {
if (!preservedElements.includes(child) && child.tagName !== 'SCRIPT' && child.tagName !== 'STYLE' && !child.classList.contains('toast')) {
child.remove();
}
});
}
async function handleSearch(query) {
if (!query || !query.trim()) {
showToast('Please enter something in the Search Bar.', 'error', 'warning');
return;
}
clearBackground();
let searchURL = generateSearchUrl(query);
historyStack.length = 0;
currentIndex = -1;
updateNavButtons();
showLoadingScreen(true);
iframe.style.display = 'block';
if (topBar) topBar.style.display = 'flex';
if (navBar && navbarToggle && navbarToggle.checked) navBar.style.display = 'block';
let finalUrlToLoad;
if (searchURL.startsWith(window.location.origin + '/assets/g/')) {
finalUrlToLoad = searchURL;
} else if (searchURL.startsWith('/assets/g/')) {
finalUrlToLoad = new URL(searchURL, window.location.origin).href;
} else {
try {
const tempUrl = new URL(searchURL);
if (tempUrl.origin === window.location.origin && tempUrl.pathname.startsWith('/assets/g/')) {
finalUrlToLoad = tempUrl.href;
} else {
finalUrlToLoad = await getUrl(searchURL);
}
} catch (e) {
finalUrlToLoad = await getUrl(searchURL);
}
}
if (searchInput2) searchInput2.value = decodeUrl(finalUrlToLoad);
iframe.src = finalUrlToLoad;
}
window.APP.handleSearch = handleSearch;
[searchInput1, searchInput2].forEach(input => {
if (input) { if (input) {
input.addEventListener('keyup', e => { input.addEventListener('keyup', e => {
if (e.key === 'Enter') { if (e.key === 'Enter') {
const val = input.value.trim() const queryValue = input.value.trim();
if (val) handleSearch(val) if (queryValue) {
else showToast('Please enter something in the Search Bar.', 'error', 'warning') APP.handleSearch(queryValue);
if (input === searchInput1) searchInput1.value = '';
} else {
showToast('Please enter something in the Search Bar.', 'error', 'warning');
} }
})
} }
}) });
if (input === searchInput2) {
input.addEventListener('focus', updateDecodedSearchInput);
}
}
});
if (movies) movies.addEventListener('click', e => { if (movies) movies.addEventListener('click', e => {
e.preventDefault() e.preventDefault();
handleSearch('https://movies.usewaves.site/') APP.handleSearch('https://movies.usewaves.site/');
}) });
if (ai) ai.addEventListener('click', e => { if (ai) ai.addEventListener('click', e => {
e.preventDefault() e.preventDefault();
handleSearch('https://ai.usewaves.site/') APP.handleSearch('https://ai.usewaves.site/');
}) });
function clearBackground() {
const preserved = [
document.querySelector('.navbar'),
document.getElementById('cool-iframe'),
document.querySelector('.loading-screen'),
erudaLoadingScreen
]
Array.from(document.body.children).forEach(child => {
if (!preserved.includes(child)) child.remove()
})
}
async function handleSearch(query) {
if (!query || !query.trim()) {
showToast('Please enter something in the Search Bar.', 'error', 'warning')
return
}
clearBackground()
let searchURL
if (
query.startsWith('/assets/g/') ||
query.startsWith(window.location.origin + '/assets/g/')
) {
searchURL = query
} else {
searchURL = generateSearchUrl(query)
}
if (searchInput2) searchInput2.value = searchURL
historyStack.length = 0
currentIndex = -1
showLoadingScreen(true, false)
iframe.style.display = 'block'
if (topBar) topBar.style.display = 'none'
backIcon.disabled = forwardIcon.disabled = true
let finalUrl
try {
const u = new URL(searchURL, window.location.origin)
if (u.origin === window.location.origin && u.pathname.startsWith('/assets/g/')) {
finalUrl = u.href
} else {
finalUrl = await getUrl(searchURL)
}
} catch {
finalUrl = await getUrl(searchURL)
}
iframe.src = finalUrl
iframe.onload = () => {
hideLoadingScreen()
if (navbarToggle && navbarToggle.checked && navBar) navBar.style.display = 'block'
generateSubject()
updateDecodedSearchInput()
}
iframe.onerror = () => {
hideLoadingScreen()
}
}
window.handleSearch = handleSearch
function generateSearchUrl(query) {
try {
return new URL(query).toString()
} catch {
try {
const u = new URL(`https://${query}`)
if (u.hostname.includes('.')) return u.toString()
} catch {}
}
return `https://duckduckgo.com/?q=${encodeURIComponent(query)}&ia=web`
}
function showToast(message, type = 'success', iconType = 'check') { function showToast(message, type = 'success', iconType = 'check') {
const toast = document.createElement('div') const toast = document.createElement('div');
toast.className = `toast show ${type}` toast.className = `toast show ${type}`;
const icons = { const icons = {
success: '<i class="fa-regular fa-check-circle" style="margin-right: 8px;"></i>', 'check': 'fa-regular fa-check-circle',
error: '<i class="fa-regular fa-times-circle" style="margin-right: 8px;"></i>', 'times-circle': 'fa-regular fa-times-circle',
info: '<i class="fa-regular fa-info-circle" style="margin-right: 8px;"></i>', 'info': 'fa-regular fa-info-circle',
warning: '<i class="fa-regular fa-exclamation-triangle" style="margin-right: 8px;"></i>', 'warning': 'fa-regular fa-exclamation-triangle',
heart: '<i class="fa-regular fa-heart" style="margin-right: 8px;"></i>' 'heart': 'fa-solid fa-heart'
} };
const icon = icons[iconType] || icons.heart toast.innerHTML = `<i class="${icons[iconType] || icons.heart}" style="margin-right: 8px;"></i>${message}`;
toast.innerHTML = `${icon}${message} ` const progressBar = document.createElement('div');
const progressBar = document.createElement('div') progressBar.className = 'progress-bar';
progressBar.className = 'progress-bar' toast.appendChild(progressBar);
toast.appendChild(progressBar) const closeBtn = document.createElement('button');
const closeBtn = document.createElement('button') closeBtn.className = 'toast-close';
closeBtn.className = 'toast-close' closeBtn.innerHTML = '<i class="fa-solid fa-xmark" style="margin-left: 8px; font-size: 0.8em;"></i>';
closeBtn.innerHTML = '<i class="fa-solid fa-xmark" style="margin-left: 8px; font-size: 0.8em;"></i>' closeBtn.onclick = () => {
closeBtn.addEventListener('click', () => { toast.classList.add('hide');
toast.classList.add('hide') setTimeout(() => toast.remove(), 500);
setTimeout(() => toast.remove(), 500) };
}) toast.appendChild(closeBtn);
toast.appendChild(closeBtn) document.body.appendChild(toast);
document.body.appendChild(toast)
setTimeout(() => { setTimeout(() => {
toast.classList.add('hide') toast.classList.add('hide');
setTimeout(() => toast.remove(), 500) setTimeout(() => toast.remove(), 500);
}, 3000) }, 3000);
} }
function preloadResources(url) {
if (!url) return if (navbarToggle && navBar && iframe) {
try { const savedNavbarState = localStorage.getItem('navbarToggled');
const link = document.createElement('link') navbarToggle.checked = savedNavbarState !== 'false';
link.rel = 'preload'
link.href = url const updateNavbarDisplayBasedOnToggle = () => {
link.as = 'fetch' if (iframe.style.display === 'block') {
link.crossOrigin = 'anonymous' navBar.style.display = navbarToggle.checked ? 'block' : 'none';
document.head.appendChild(link) } else {
} catch {} navBar.style.display = 'none';
} }
function getUrl(url) { };
return Promise.resolve(__uv$config.prefix + __uv$config.encodeUrl(url)) updateNavbarDisplayBasedOnToggle();
navbarToggle.addEventListener('change', () => {
localStorage.setItem('navbarToggled', navbarToggle.checked.toString());
updateNavbarDisplayBasedOnToggle();
});
window.APP.updateNavbarDisplay = updateNavbarDisplayBasedOnToggle;
} }
function generateSubject() {
const subjects = ['math', 'science', 'history', 'art', 'programming', 'philosophy'] window.addEventListener('load', () => {
const random = subjects[Math.floor(Math.random() * subjects.length)] let iframeInitiallyHidden = true;
history.replaceState({}, '', '/learning?subject=' + random) if (iframe.src && iframe.src !== 'about:blank') {
iframeInitiallyHidden = false;
} }
function decodeUrl(enc) {
try { if (iframeInitiallyHidden) {
const o = new URL(enc, window.location.origin) hideLoadingScreen();
const p = (__uv$config && __uv$config.prefix) || '/wa/a/' if (topBar) topBar.style.display = 'flex';
if (o.pathname.startsWith(p)) { iframe.style.display = 'none';
const part = o.pathname.slice(p.length) } else {
return (__uv$config.decodeUrl ? __uv$config.decodeUrl(part) : decodeURIComponent(part)) if (topBar) topBar.style.display = 'flex';
iframe.style.display = 'block';
} }
} catch {}
return enc if (window.APP.updateNavbarDisplay) window.APP.updateNavbarDisplay();
} updateNavButtons();
window.decodeUrl = decodeUrl updateDecodedSearchInput();
window.addToHistory = addToHistory });
window.updateDecodedSearchInput = updateDecodedSearchInput
window.normalizeUrl = normalizeUrl window.APP.decodeUrl = decodeUrl;
}) window.APP.normalizeUrl = normalizeUrl;
});

View File

@ -1,45 +0,0 @@
document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.getElementById('appSearchInput');
const grid = document.querySelector('.apps-grid');
let appsData = [];
fetch('/assets/data/a.json')
.then(response => response.json())
.then(data => {
appsData = data.apps;
searchInput.placeholder = `Search through ${appsData.length} Apps…`;
displayApps(appsData);
searchInput.addEventListener('input', function() {
const query = searchInput.value.toLowerCase();
const filteredApps = appsData.filter(app => {
const title = app.title ? app.title.toLowerCase() : '';
const description = app.description ? app.description.toLowerCase() : '';
return title.includes(query) || description.includes(query);
});
displayApps(filteredApps);
});
})
.catch(err => console.error('Error loading apps data:', err));
function displayApps(apps) {
grid.innerHTML = '';
if (apps.length === 0) {
grid.innerHTML = '<p>Zero apps were found matching your search :(</p>';
}
apps.forEach(app => {
const card = document.createElement('div');
card.classList.add('app-card');
card.innerHTML = `
<img src="${app.icon}" alt="${app.title} Icon" />
<h2>${app.title}</h2>
`;
card.addEventListener('click', function() {
window.handleSearch(app.link);
});
grid.appendChild(card);
});
}
});

View File

@ -1,98 +1,69 @@
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.getElementById('gameSearchInput'); const searchInput = document.getElementById('gameSearchInput');
const grid = document.querySelector('.games-grid'); const grid = document.querySelector('.games-grid');
let gamesData = [];
let filteredData = [];
const BATCH_SIZE = 50;
let renderedCount = 0;
const sentinel = document.createElement('div'); const sentinel = document.createElement('div');
sentinel.className = 'sentinel'; let allGames = [];
grid.after(sentinel); let filteredGames = [];
let renderedCount = 0;
const BATCH_SIZE = 20;
const observer = new IntersectionObserver(entries => { const observer = new IntersectionObserver(entries => {
entries.forEach(entry => { if (entries[0].isIntersecting) loadNextBatch();
if (entry.isIntersecting) { }, { rootMargin: '500px' });
renderNextBatch();
}
});
}, { rootMargin: '200px', threshold: 0.1 });
function debounce(fn, wait = 200) {
let t;
return (...args) => {
clearTimeout(t);
t = setTimeout(() => fn.apply(this, args), wait);
};
}
fetch('/assets/data/g.json') fetch('/assets/data/g.json')
.then(r => r.json()) .then(res => res.json())
.then(data => { .then(data => {
gamesData = data; allGames = data;
filteredData = data; filteredGames = data;
searchInput.placeholder = `Search through ${data.length} Games…`; searchInput.placeholder = `Search through ${allGames.length} Games…`;
grid.parentNode.appendChild(sentinel);
observer.observe(sentinel); observer.observe(sentinel);
renderNextBatch(); resetAndRender();
searchInput.addEventListener('input', debounce(() => {
const q = searchInput.value.trim().toLowerCase();
filteredData = gamesData.filter(g =>
(g.name || '').toLowerCase().includes(q)
);
resetRendering();
}, 250));
}) })
.catch(console.error); .catch(err => console.error(err));
function resetRendering() { searchInput.addEventListener('input', function() {
const q = this.value.toLowerCase();
filteredGames = allGames.filter(game =>
(game.name || '').toLowerCase().includes(q)
);
resetAndRender();
});
function resetAndRender() {
grid.innerHTML = ''; grid.innerHTML = '';
renderedCount = 0; renderedCount = 0;
observer.observe(sentinel); if (filteredGames.length === 0) {
renderNextBatch(); grid.innerHTML = '<p>Zero games were found matching your search :(</p>';
}
function renderNextBatch() {
const batch = filteredData.slice(renderedCount, renderedCount + BATCH_SIZE);
if (!batch.length) {
observer.unobserve(sentinel); observer.unobserve(sentinel);
return; return;
} }
observer.observe(sentinel);
loadNextBatch();
}
const frag = document.createDocumentFragment(); function loadNextBatch() {
batch.forEach(game => { const nextCount = Math.min(renderedCount + BATCH_SIZE, filteredGames.length);
for (let i = renderedCount; i < nextCount; i++) {
const game = filteredGames[i];
const card = document.createElement('div'); const card = document.createElement('div');
card.className = 'game-card'; card.classList.add('game-card');
card.innerHTML = ` card.innerHTML = `
<img <img src="/assets/g/${game.directory}/${game.image}" alt="${game.name} Icon" />
loading="lazy"
src="/assets/g/${game.directory}/${game.image}"
alt="${game.name} Icon"
/>
<h2>${game.name}</h2> <h2>${game.name}</h2>
`; `;
card.addEventListener('click', () => { card.addEventListener('click', () => {
window.handleSearch(`/assets/g/${game.directory}`); const gameUrl = window.location.origin + `/assets/g/${game.directory}`;
APP.handleSearch(gameUrl);
}); });
frag.appendChild(card); grid.appendChild(card);
}); }
renderedCount = nextCount;
grid.appendChild(frag); if (renderedCount >= filteredGames.length) {
renderedCount += batch.length;
preloadNextImages(5);
if (renderedCount >= filteredData.length) {
observer.unobserve(sentinel); observer.unobserve(sentinel);
} else {
grid.parentNode.appendChild(sentinel);
} }
} }
function preloadNextImages(limit = 3) {
const next = filteredData.slice(renderedCount, renderedCount + limit);
next.forEach(({ directory, image }) => {
const img = new Image();
img.src = `/assets/g/${directory}/${image}`;
});
}
}); });

View File

@ -1,6 +1,7 @@
window.onload = function() { window.onload = function() {
const storedName = localStorage.getItem('userName'); const storedName = localStorage.getItem('userName');
const path = window.location.pathname; const path = window.location.pathname;
if (!storedName) { if (!storedName) {
document.getElementById('overlay').style.display = 'block'; document.getElementById('overlay').style.display = 'block';
document.getElementById('namePrompt').style.display = 'block'; document.getElementById('namePrompt').style.display = 'block';
@ -12,24 +13,29 @@ window.onload = function() {
}); });
return; return;
} }
const welcomeMsg = getWelcomeMessage(storedName); const welcomeMsg = getWelcomeMessage(storedName);
const iconType = getIconType(path); const iconType = getIconType(path);
showToast(welcomeMsg, 'success', iconType); showToast(welcomeMsg, 'success', iconType);
const greetingElement = document.getElementById('greeting'); const greetingElement = document.getElementById('greeting');
if (greetingElement) { if (greetingElement) {
updateGreeting(storedName); updateGreeting(storedName);
} }
updateHi(storedName);
}; };
function submitName() { function submitName() {
const name = document.getElementById('userName').value.trim(); const name = document.getElementById('userName').value.trim();
if (!name) return; if (!name) return;
localStorage.setItem('userName', name); localStorage.setItem('userName', name);
updateGreeting(name); updateGreeting(name);
updateHi(name);
document.getElementById('namePrompt').classList.add('fade-out'); document.getElementById('namePrompt').classList.add('fade-out');
showToast(`Hey, ${name}! Welcome to Waves!`, 'success', 'wave'); showToast(`Hey, ${name}! Welcome to Waves!`, 'success', 'wave');
const path = window.location.pathname;
setTimeout(() => { setTimeout(() => {
document.getElementById('namePrompt').style.display = 'none'; document.getElementById('namePrompt').style.display = 'none';
document.getElementById('overlay').style.display = 'none'; document.getElementById('overlay').style.display = 'none';
@ -40,8 +46,8 @@ function getWelcomeMessage(name) {
const path = window.location.pathname; const path = window.location.pathname;
if (path === '/g') { if (path === '/g') {
return `Have fun playing games, ${name}!`; return `Have fun playing games, ${name}!`;
} else if (path === '/a') { } else if (path === '/s') {
return `Enjoy our collection of apps, ${name}!`; return `Enjoy our collection of, ${name}!`;
} else { } else {
return `Welcome back, ${name}!`; return `Welcome back, ${name}!`;
} }
@ -49,21 +55,79 @@ function getWelcomeMessage(name) {
function getIconType(path) { function getIconType(path) {
if (path === '/g') return 'game'; if (path === '/g') return 'game';
if (path === '/a') return 'apps'; if (path === '/s') return 'shortcuts';
return 'wave'; return 'wave';
} }
function updateGreeting(name) { const generalGreetings = [
const { text, icon } = getGreeting(); { text: 'Have fun', icon: '<i class="fa-regular fa-party-horn"></i>', suffix: '!' },
{ text: 'Hope you enjoy Waves', icon: '<i class="fa-solid fa-heart"></i>', suffix: ' <3' },
{ text: 'Consider joining our Discord (discord.gg/ire)', icon: '<i class="fa-solid fa-smile"></i>', suffix: '!' },
{ text: 'How you doing today', icon: '<i class="fa-regular fa-question"></i>', suffix: '?' }
];
const el = document.getElementById('greeting'); const timeGreetings = [];
if (el) {
if (text === 'Hope you enjoy Waves') { timeGreetings.push(
el.innerHTML = `${icon} ${text}, ${name} <3`; { text: 'Good morning, sunshine', icon: '<i class="fa-regular fa-sun"></i>', suffix: ' :D' },
{ text: 'Heres to a bright morning', icon: '<i class="fa-regular fa-cloud-sun"></i>', suffix: '.' },
{ text: 'Enjoy your morning', icon: '<i class="fa-regular fa-mug-hot"></i>', suffix: '!' },
{ text: 'Your day starts here', icon: '<i class="fa-regular fa-star"></i>', suffix: '!' }
);
timeGreetings.push(
{ text: 'Good afternoon', icon: '<i class="fa-regular fa-leaf"></i>', suffix: '!' },
{ text: 'Hope your day is going well', icon: '<i class="fa-regular fa-coffee"></i>', suffix: '.' },
{ text: 'Keep up the pace', icon: '<i class="fa-regular fa-book"></i>', suffix: '!' },
{ text: 'Stay on track today', icon: '<i class="fa-regular fa-sun"></i>', suffix: '.' }
);
timeGreetings.push(
{ text: 'Good evening', icon: '<i class="fa-regular fa-cloud-moon"></i>', suffix: '!' },
{ text: 'Time to unwind', icon: '<i class="fa-regular fa-fire"></i>', suffix: '.' },
{ text: 'Evenings here—relax', icon: '<i class="fa-regular fa-star"></i>', suffix: '.' },
{ text: 'Breathe and recharge', icon: '<i class="fa-regular fa-moon"></i>', suffix: '…' }
);
timeGreetings.push(
{ text: 'Good night', icon: '<i class="fa-regular fa-bed"></i>', suffix: '!' },
{ text: 'Rest well', icon: '<i class="fa-regular fa-blanket"></i>', suffix: '.' },
{ text: 'Sweet dreams', icon: '<i class="fa-regular fa-star-and-crescent"></i>', suffix: '!' },
{ text: 'See you tomorrow', icon: '<i class="fa-regular fa-moon"></i>', suffix: '!' }
);
function getGreeting() {
const now = new Date();
const hour = now.getHours();
let pool = [];
if (hour >= 5 && hour < 12) {
pool = timeGreetings.slice(0, 4);
} else if (hour < 17) {
pool = timeGreetings.slice(4, 8);
} else if (hour < 21) {
pool = timeGreetings.slice(8, 12);
} else { } else {
el.innerHTML = `${icon} ${text}, ${name}!`; pool = timeGreetings.slice(12, 16);
} }
if (Math.random() < 0.5) {
pool = generalGreetings;
}
return pool[Math.floor(Math.random() * pool.length)];
}
function updateGreeting(name) {
const { text, icon, suffix } = getGreeting();
const el = document.getElementById('greeting');
if (!el) return;
el.innerHTML = `${icon} ${text}, ${name}${suffix}`;
el.style.opacity = 1; el.style.opacity = 1;
}
function updateHi(name) {
const hiEl = document.getElementById('hi');
if (hiEl) {
hiEl.textContent = `Hii, ${name}!!`;
} }
} }
@ -78,7 +142,7 @@ function showToast(message, type = 'success', iconType = 'wave') {
warning: '<i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i>', warning: '<i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i>',
wave: '<i class="fa-regular fa-hand-wave" style="margin-right: 8px;"></i>', wave: '<i class="fa-regular fa-hand-wave" style="margin-right: 8px;"></i>',
game: '<i class="fa-regular fa-gamepad" style="margin-right: 8px;"></i>', game: '<i class="fa-regular fa-gamepad" style="margin-right: 8px;"></i>',
apps: '<i class="fa-regular fa-th" style="margin-right: 8px;"></i>', apps: '<i class="fa-regular fa-th" style="margin-right: 8px;"></i>'
}; };
toast.innerHTML = `${icons[iconType] || icons.wave}${message}`; toast.innerHTML = `${icons[iconType] || icons.wave}${message}`;
@ -97,59 +161,9 @@ function showToast(message, type = 'success', iconType = 'wave') {
toast.appendChild(closeBtn); toast.appendChild(closeBtn);
document.body.appendChild(toast); document.body.appendChild(toast);
setTimeout(() => { setTimeout(() => {
toast.classList.add('hide'); toast.classList.add('hide');
setTimeout(() => toast.remove(), 500); setTimeout(() => toast.remove(), 500);
}, 3000); }, 3000);
} }
function getGreeting() {
const now = new Date();
const hour = now.getHours();
const timeGreetings = [];
const generalGreetings = [
{ text: 'Welcome aboard', icon: '<i class="fa-regular fa-rocket"></i>' },
{ text: 'Lets do something great', icon: '<i class="fa-regular fa-lightbulb"></i>' },
{ text: 'Hope you enjoy Waves', icon: '<i class="fa-regular fa-heart"></i>' },
{ text: 'Time to explore', icon: '<i class="fa-regular fa-compass"></i>' },
{ text: 'Lets roll', icon: '<i class="fa-regular fa-tire"></i>' },
{ text: 'Another great visit', icon: '<i class="fa-regular fa-thumbs-up"></i>' },
{ text: 'The adventure continues', icon: '<i class="fa-regular fa-map"></i>' }
];
if (hour >= 5 && hour < 12) {
timeGreetings.push(
{ text: 'Good morning, sunshine', icon: '<i class="fa-regular fa-sun"></i>' },
{ text: 'Heres to a bright morning', icon: '<i class="fa-regular fa-cloud-sun"></i>' },
{ text: 'Enjoy your morning', icon: '<i class="fa-regular fa-mug-hot"></i>' },
{ text: 'Your day starts here', icon: '<i class="fa-regular fa-star"></i>' }
);
} else if (hour < 17) {
timeGreetings.push(
{ text: 'Good afternoon', icon: '<i class="fa-regular fa-leaf"></i>' },
{ text: 'Hope your day is going well', icon: '<i class="fa-regular fa-coffee"></i>' },
{ text: 'Keep up the pace', icon: '<i class="fa-regular fa-book"></i>' },
{ text: 'Stay on track today', icon: '<i class="fa-regular fa-sun"></i>' }
);
} else if (hour < 21) {
timeGreetings.push(
{ text: 'Good evening', icon: '<i class="fa-regular fa-cloud-moon"></i>' },
{ text: 'Time to unwind', icon: '<i class="fa-regular fa-fire"></i>' },
{ text: 'Evenings here—relax', icon: '<i class="fa-regular fa-star"></i>' },
{ text: 'Breathe and recharge', icon: '<i class="fa-regular fa-moon"></i>' }
);
} else {
timeGreetings.push(
{ text: 'Good night', icon: '<i class="fa-regular fa-bed"></i>' },
{ text: 'Rest well', icon: '<i class="fa-regular fa-blanket"></i>' },
{ text: 'Sweet dreams', icon: '<i class="fa-regular fa-star-and-crescent"></i>' },
{ text: 'See you tomorrow', icon: '<i class="fa-regular fa-moon"></i>' }
);
}
const useGeneral = Math.random() < 0.5;
const pool = useGeneral ? generalGreetings : timeGreetings;
return pool[Math.floor(Math.random() * pool.length)];
}

View File

@ -1,21 +0,0 @@
document.addEventListener('DOMContentLoaded', function () {
NProgress.configure({ showSpinner: false });
NProgress.start();
});
window.addEventListener('load', function () {
NProgress.done();
});
const titleElement = document.querySelector('.search-title');
if (titleElement) {
const text = titleElement.textContent;
titleElement.innerHTML = '';
text.split('').forEach((letter, index) => {
const span = document.createElement('span');
span.textContent = letter;
span.style.animationDelay = `${index * 0.2}s`;
titleElement.appendChild(span);
});
}

View File

@ -1,183 +0,0 @@
const style = document.createElement('style');
style.textContent = `
@keyframes slideLeft {0% { transform: translateX(0); } 50% { transform: translateX(-5px); } 100% { transform: translateX(0); }}
@keyframes slideRight {0% { transform: translateX(0); } 50% { transform: translateX(5px); } 100% { transform: translateX(0); }}
.button-animate-back { animation: slideLeft 0.3s ease-in-out; }
.button-animate-forward { animation: slideRight 0.3s ease-in-out; }
`;
document.head.appendChild(style);
const historyStack = [];
let currentIndex = -1;
const elements = {
refreshIcon: document.getElementById('refreshIcon'),
fullscreenIcon: document.getElementById('fullscreenIcon'),
backIcon: document.getElementById('backIcon'),
forwardIcon: document.getElementById('forwardIcon'),
searchInput2: document.getElementById('searchInputt'),
iframe: document.getElementById('cool-iframe')
};
const originalTitle = document.title;
let loadingFallbackTimeout;
elements.refreshIcon.addEventListener('click', handleRefresh);
elements.fullscreenIcon.addEventListener('click', handleFullscreen);
elements.backIcon.addEventListener('click', handleBack);
elements.forwardIcon.addEventListener('click', handleForward);
function showLoadingScreen() {
if (typeof NProgress !== 'undefined') {
NProgress.start();
document.title = 'Loading... <3';
setTimeout(() => {
if (typeof NProgress !== 'undefined') NProgress.done();
}, 10000);
}
}
function hideLoadingScreen() {
if (typeof NProgress !== 'undefined') NProgress.done();
document.title = originalTitle;
}
function handleRefresh() {
elements.refreshIcon.classList.add('spin');
const iframe = elements.iframe;
const currentUrl = iframe.contentWindow.location.href;
if (normalizeUrl(currentUrl) !== normalizeUrl(historyStack[currentIndex] || '')) {
addToHistory(currentUrl);
}
iframe.contentWindow.location.reload(true);
setTimeout(() => elements.refreshIcon.classList.remove('spin'), 300);
}
function handleFullscreen() {
const iframe = elements.iframe;
if (iframe && iframe.tagName === 'IFRAME') iframe.requestFullscreen();
}
function handleBack() {
toggleButtonAnimation(elements.backIcon, 'button-animate-back');
if (currentIndex > 0) {
currentIndex--;
updateIframeSrc();
}
}
function handleForward() {
toggleButtonAnimation(elements.forwardIcon, 'button-animate-forward');
if (currentIndex < historyStack.length - 1) {
currentIndex++;
updateIframeSrc();
}
}
function toggleButtonAnimation(button, animationClass) {
button.classList.add(animationClass);
setTimeout(() => button.classList.remove(animationClass), 200);
}
function normalizeUrl(urlStr) {
try {
const url = new URL(urlStr);
url.searchParams.delete('ia');
return url.toString();
} catch (e) {
return urlStr;
}
}
function addToHistory(url) {
const normalized = normalizeUrl(url);
if (currentIndex >= 0 && normalizeUrl(historyStack[currentIndex]) === normalized) return;
if (currentIndex < historyStack.length - 1) historyStack.splice(currentIndex + 1);
historyStack.push(url);
currentIndex++;
updateNavButtons();
updateDecodedSearchInput();
}
function updateIframeSrc() {
showLoadingScreen();
elements.iframe.src = historyStack[currentIndex];
updateNavButtons();
updateDecodedSearchInput();
}
function updateNavButtons() {
const isAtStart = currentIndex <= 0;
const isAtEnd = currentIndex >= historyStack.length - 1;
elements.backIcon.disabled = isAtStart;
elements.forwardIcon.disabled = isAtEnd;
elements.backIcon.classList.toggle('disabled', isAtStart);
elements.forwardIcon.classList.toggle('disabled', isAtEnd);
}
function updateDecodedSearchInput() {
if (elements.searchInput2) {
const url = historyStack[currentIndex] || elements.iframe.src;
elements.searchInput2.value = decodeUrl(url);
}
}
function decodeUrl(url) {
try {
return decodeURIComponent(url);
} catch (e) {
return url;
}
}
window.addToHistory = addToHistory;
window.updateDecodedSearchInput = updateDecodedSearchInput;
window.normalizeUrl = normalizeUrl;
function detectIframeNavigation() {
try {
const iframeWindow = elements.iframe.contentWindow;
const pushState = iframeWindow.history.pushState;
const replaceState = iframeWindow.history.replaceState;
iframeWindow.history.pushState = function() {
pushState.apply(this, arguments);
handleIframeNavigation(iframeWindow.location.href);
};
iframeWindow.history.replaceState = function() {
replaceState.apply(this, arguments);
handleIframeNavigation(iframeWindow.location.href);
};
iframeWindow.addEventListener('popstate', () => handleIframeNavigation(iframeWindow.location.href));
iframeWindow.addEventListener('hashchange', () => handleIframeNavigation(iframeWindow.location.href));
} catch (error) {}
}
function handleIframeNavigation(rawUrl) {
let urlStr = rawUrl;
try {
urlStr = decodeUrl(rawUrl);
} catch {}
try {
const u = new URL(urlStr);
if (u.hostname.endsWith('duckduckgo.com')) {
if (typeof NProgress !== 'undefined') NProgress.done();
return;
}
} catch (e) {}
if (normalizeUrl(urlStr) !== normalizeUrl(historyStack[currentIndex] || '')) {
showLoadingScreen();
addToHistory(urlStr);
} else {
hideLoadingScreen();
}
}
elements.iframe.addEventListener('load', () => {
try {
detectIframeNavigation();
if (historyStack.length === 0) {
addToHistory(elements.iframe.contentWindow.location.href);
} else {
handleIframeNavigation(elements.iframe.contentWindow.location.href);
}
} catch (error) {}
hideLoadingScreen();
});

View File

@ -0,0 +1 @@
!function(n,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e():n.NProgress=e()}(this,function(){function n(n,e,t){return e>n?e:n>t?t:n}function e(n){return 100*(-1+n)}function t(n,t,r){var i;return i="translate3d"===c.positionUsing?{transform:"translate3d("+e(n)+"%,0,0)"}:"translate"===c.positionUsing?{transform:"translate("+e(n)+"%,0)"}:{"margin-left":e(n)+"%"},i.transition="all "+t+"ms "+r,i}function r(n,e){var t="string"==typeof n?n:o(n);return t.indexOf(" "+e+" ")>=0}function i(n,e){var t=o(n),i=t+e;r(t,e)||(n.className=i.substring(1))}function s(n,e){var t,i=o(n);r(n,e)&&(t=i.replace(" "+e+" "," "),n.className=t.substring(1,t.length-1))}function o(n){return(" "+(n.className||"")+" ").replace(/\s+/gi," ")}function a(n){n&&n.parentNode&&n.parentNode.removeChild(n)}var u={};u.version="0.2.0";var c=u.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};u.configure=function(n){var e,t;for(e in n)t=n[e],void 0!==t&&n.hasOwnProperty(e)&&(c[e]=t);return this},u.status=null,u.set=function(e){var r=u.isStarted();e=n(e,c.minimum,1),u.status=1===e?null:e;var i=u.render(!r),s=i.querySelector(c.barSelector),o=c.speed,a=c.easing;return i.offsetWidth,l(function(n){""===c.positionUsing&&(c.positionUsing=u.getPositioningCSS()),f(s,t(e,o,a)),1===e?(f(i,{transition:"none",opacity:1}),i.offsetWidth,setTimeout(function(){f(i,{transition:"all "+o+"ms linear",opacity:0}),setTimeout(function(){u.remove(),n()},o)},o)):setTimeout(n,o)}),this},u.isStarted=function(){return"number"==typeof u.status},u.start=function(){u.status||u.set(0);var n=function(){setTimeout(function(){u.status&&(u.trickle(),n())},c.trickleSpeed)};return c.trickle&&n(),this},u.done=function(n){return n||u.status?u.inc(.3+.5*Math.random()).set(1):this},u.inc=function(e){var t=u.status;return t?("number"!=typeof e&&(e=(1-t)*n(Math.random()*t,.1,.95)),t=n(t+e,0,.994),u.set(t)):u.start()},u.trickle=function(){return u.inc(Math.random()*c.trickleRate)},function(){var n=0,e=0;u.promise=function(t){return t&&"resolved"!==t.state()?(0===e&&u.start(),n++,e++,t.always(function(){e--,0===e?(n=0,u.done()):u.set((n-e)/n)}),this):this}}(),u.render=function(n){if(u.isRendered())return document.getElementById("nprogress");i(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=c.template;var r,s=t.querySelector(c.barSelector),o=n?"-100":e(u.status||0),l=document.querySelector(c.parent);return f(s,{transition:"all 0 linear",transform:"translate3d("+o+"%,0,0)"}),c.showSpinner||(r=t.querySelector(c.spinnerSelector),r&&a(r)),l!=document.body&&i(l,"nprogress-custom-parent"),l.appendChild(t),t},u.remove=function(){s(document.documentElement,"nprogress-busy"),s(document.querySelector(c.parent),"nprogress-custom-parent");var n=document.getElementById("nprogress");n&&a(n)},u.isRendered=function(){return!!document.getElementById("nprogress")},u.getPositioningCSS=function(){var n=document.body.style,e="WebkitTransform"in n?"Webkit":"MozTransform"in n?"Moz":"msTransform"in n?"ms":"OTransform"in n?"O":"";return e+"Perspective"in n?"translate3d":e+"Transform"in n?"translate":"margin"};var l=function(){function n(){var t=e.shift();t&&t(n)}var e=[];return function(t){e.push(t),1==e.length&&n()}}(),f=function(){function n(n){return n.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(n,e){return e.toUpperCase()})}function e(n){var e=document.body.style;if(n in e)return n;for(var t,r=i.length,s=n.charAt(0).toUpperCase()+n.slice(1);r--;)if(t=i[r]+s,t in e)return t;return n}function t(t){return t=n(t),s[t]||(s[t]=e(t))}function r(n,e,r){e=t(e),n.style[e]=r}var i=["Webkit","O","Moz","ms"],s={};return function(n,e){var t,i,s=arguments;if(2==s.length)for(t in e)i=e[t],void 0!==i&&e.hasOwnProperty(t)&&r(n,t,i);else r(n,s[1],s[2])}}();return u});

View File

@ -10,7 +10,7 @@
ws = new WebSocket(wsUrl); ws = new WebSocket(wsUrl);
ws.onopen = function() { ws.onopen = function() {
pingDisplay.innerHTML = '<i class="fas fa-wifi"></i> Ping: Waiting...'; pingDisplay.innerHTML = '<i class="fas fa-satellite-dish"></i> Ping: Waiting...';
}; };
ws.onmessage = function(event) { ws.onmessage = function(event) {
@ -23,7 +23,7 @@
})); }));
} }
if (data.type === "latency" && typeof data.latency === "number") { if (data.type === "latency" && typeof data.latency === "number") {
pingDisplay.innerHTML = '<i class="fa-regular fa-wifi"></i> Ping: ' + data.latency + ' ms'; pingDisplay.innerHTML = '<i class="fas fa-satellite-dish"></i> ' + 'Ping: ' + '~' + data.latency + 'ms';
} }
} catch (err) { } catch (err) {
console.error("Error parsing message:", err); console.error("Error parsing message:", err);
@ -31,11 +31,11 @@
}; };
ws.onerror = function() { ws.onerror = function() {
pingDisplay.innerHTML = '<i class="fa-regular fa-wifi"></i> Ping: Error'; pingDisplay.innerHTML = '<i class="fas fa-satellite-dish"></i> Ping: Error';
}; };
ws.onclose = function() { ws.onclose = function() {
pingDisplay.innerHTML = '<i class="fa-regular fa-wifi"></i> Ping: Disconnected'; pingDisplay.innerHTML = '<i class="fas fa-satellite-dish"></i> Ping: Disconnected';
setTimeout(createWebSocket, 1000); setTimeout(createWebSocket, 1000);
}; };
} }

View File

@ -1,124 +1,80 @@
document.addEventListener('DOMContentLoaded', function() { ;(function(){
const originalLog = console.log; const origLog = console.log.bind(console);
const originalWarn = console.warn; document.addEventListener("DOMContentLoaded", () => {
const originalError = console.error; origLog(
const scriptLogs = []; "%c\n" +
" ᶻ 𝗓 𐰁 .ᐟ\n" +
" |\\ _,,,---,,_\n" +
" /, `.-'`' -. ;-;;,_\n" +
" |,4- ) )-,_..;\\ ( `'-'\n" +
" '---''(_/--' `-`\\_)\n discord.gg/dJvdkPRheV",
"color: hotpink; font-size: 16px; display: block; white-space: pre; text-align: center; padding-left: 28%;"
);
});
function isScriptLog(args) { const labelStyle = "background: white; color: black; font-weight: bold; padding: 2px 4px; border-radius: 2px";
return args[0] && (args[0].includes('%c[+]%c') || args[0].includes('%c[*]%c') || args[0].includes('%c[#]%c') || args[0].includes('%c[-]%c') || args[0].includes('%c[!]%c')); const messageStyle = "background: black; color: white; padding: 2px 4px; border-radius: 2px";
} ["log","info","warn","error","debug"].forEach(method => {
const orig = console[method].bind(console);
console.log = function(...args) { console[method] = (...args) => {
if (isScriptLog(args)) { const text = args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ');
scriptLogs.push(args); orig(`%cWaves:%c ${text}`, labelStyle, messageStyle);
}
originalLog.apply(console, args);
}; };
});
console.warn = function(...args) { document.addEventListener("DOMContentLoaded", function(){
if (isScriptLog(args)) { const defaultWispUrl = `${window.location.protocol==="https:"?"wss":"ws"}://${window.location.host}/w/`;
scriptLogs.push(args); let currentWispUrl = localStorage.getItem("customWispUrl") || defaultWispUrl;
}
originalWarn.apply(console, args);
};
console.error = function(...args) {
if (isScriptLog(args)) {
scriptLogs.push(args);
}
originalError.apply(console, args);
};
setInterval(() => {
const currentLogs = [...scriptLogs];
console.clear();
currentLogs.forEach(log => originalLog.apply(console, log));
}, 400);
const defaultWispUrl = `${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.host}/w/`;
let currentWispUrl = localStorage.getItem('customWispUrl') || defaultWispUrl;
const wispUrl = currentWispUrl; const wispUrl = currentWispUrl;
const connection = new BareMux.BareMuxConnection("/baremux/worker.js"); const connection = new BareMux.BareMuxConnection("/baremux/worker.js");
async function registerSW() { registerSW();
async function registerSW(){
try { try {
if (!navigator.serviceWorker) { if (!navigator.serviceWorker) return console.error("Service Workers are not supported by this browser.");
console.log("%c[!]%c Service Workers are not supported by this browser.", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
return;
}
await ensureWebSocketConnection(wispUrl); await ensureWebSocketConnection(wispUrl);
console.log("%c[+]%c Registering Service Worker...", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;"); console.log("Registering Service Worker...");
await navigator.serviceWorker.register("/wah/sw.js", { scope: '/wah/a/' }); await navigator.serviceWorker.register("/wah/sw.js", { scope: "/wah/a/" });
console.log("%c[*]%c Service Worker registered successfully.", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;"); console.log("Service Worker registered successfully.");
const savedTransport = localStorage.getItem('transport') || "epoxy"; const savedTransport = localStorage.getItem("transport") || "epoxy";
switchTransport(savedTransport); switchTransport(savedTransport);
updateTransportUI(savedTransport); updateTransportUI(savedTransport);
console.log(`%c[#]%c Using ${capitalizeTransport(savedTransport)} transport.`, "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;"); console.log(`Using ${capitalizeTransport(savedTransport)} transport.`);
} catch (error) { } catch (e) {
logError(error, 'An error occurred during Service Worker registration or WebSocket connection'); console.error(`An error occurred during Service Worker registration or WebSocket connection: ${e.message||e}`);
} }
} }
async function ensureWebSocketConnection(url) { async function ensureWebSocketConnection(url){
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
console.log("%c[+]%c Establishing WebSocket connection...", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;"); console.log("Establishing WebSocket connection...");
const ws = new WebSocket(url); const ws = new WebSocket(url);
ws.onopen = () => { ws.onopen = () => { console.log("WebSocket connection established."); resolve(ws); };
console.log("%c[*]%c WebSocket connection established.", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;"); ws.onerror = e => { console.error(`Failed to establish WebSocket connection: ${e.message||e}`); reject(e); };
resolve(ws); ws.onclose = ev => {
}; if (ev.code !== 1000) console.warn(`WebSocket connection closed. Reason: ${ev.reason||"No reason provided"}`);
ws.onerror = (error) => { else console.warn("WebSocket connection closed normally.");
logError(error, 'Failed to establish WebSocket connection');
reject(error);
};
ws.onclose = (event) => {
if (event.code !== 1000) {
console.warn(`%c[-]%c WebSocket connection closed. Reason: ${event.reason || "No reason provided"}`, "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
} else {
console.warn("%c[-]%c WebSocket connection closed normally.", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
}
}; };
}); });
} }
function logError(error, message) { function switchTransport(t){
console.error(`%c[!]%c ${message}: ${error.message || error}`, "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;"); const m = { epoxy: "/epoxy/index.mjs", libcurl: "/libcurl/index.mjs" }[t];
if (m) connection.setTransport(m, [{ wisp: wispUrl }]);
} }
function switchTransport(transport) { function updateTransportUI(t){
const transportMap = { document.querySelector(".transport-selected").textContent = capitalizeTransport(t);
"epoxy": "/epoxy/index.mjs",
"libcurl": "/libcurl/index.mjs"
};
const transportFile = transportMap[transport];
if (transportFile) {
connection.setTransport(transportFile, [{ wisp: wispUrl }]);
}
} }
async function changeTransport(newTransport) { function capitalizeTransport(t){
try { return t.charAt(0).toUpperCase() + t.slice(1).toLowerCase();
localStorage.setItem('transport', newTransport);
switchTransport(newTransport);
updateTransportUI(newTransport);
} catch (error) {
logError(error, 'An error occurred while storing transport preference');
}
} }
function updateTransportUI(transport) { document.addEventListener("wispUrlChanged", function(e){
const transportSelected = document.querySelector(".transport-selected");
transportSelected.textContent = capitalizeTransport(transport);
}
function capitalizeTransport(transport) {
return transport.charAt(0).toUpperCase() + transport.slice(1).toLowerCase();
}
document.addEventListener('wispUrlChanged', function(e) {
currentWispUrl = e.detail; currentWispUrl = e.detail;
switchTransport(localStorage.getItem('transport') || "epoxy"); switchTransport(localStorage.getItem("transport") || "epoxy");
}); });
});
registerSW(); })();
});

45
public/assets/js/s.js Normal file
View File

@ -0,0 +1,45 @@
document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.getElementById('shortcutSearchInput');
const grid = document.querySelector('.shortcuts-grid');
let shortcutsData = [];
fetch('/assets/data/s.json')
.then(response => response.json())
.then(data => {
shortcutsData = data.shortcuts;
searchInput.placeholder = `Search through ${shortcutsData.length} Shortcuts...`;
displayShortcuts(shortcutsData);
searchInput.addEventListener('input', function() {
const query = searchInput.value.toLowerCase();
const filteredShortcuts = shortcutsData.filter(shortcut => {
const title = shortcut.title ? shortcut.title.toLowerCase() : '';
const description = shortcut.description ? shortcut.description.toLowerCase() : '';
return title.includes(query) || description.includes(query);
});
displayShortcuts(filteredShortcuts);
});
})
.catch(err => console.error('Error loading shortcuts data:', err));
function displayShortcuts(shortcuts) {
grid.innerHTML = '';
if (shortcuts.length === 0) {
grid.innerHTML = '<p>Zero shortcuts were found matching your search :(</p>';
}
shortcuts.forEach(shortcut => {
const card = document.createElement('div');
card.classList.add('shortcut-card');
card.innerHTML = `
<img src="${shortcut.icon}" alt="${shortcut.title} Icon" />
<h2>${shortcut.title}</h2>
`;
card.addEventListener('click', function() {
APP.handleSearch(shortcut.link);
});
grid.appendChild(card);
});
}
});

View File

@ -3,11 +3,20 @@ document.addEventListener('DOMContentLoaded', function() {
settingsMenu.innerHTML = ` settingsMenu.innerHTML = `
<h2>Settings</h2> <h2>Settings</h2>
<div class="settings-tabs"> <div class="settings-tabs">
<button class="tab-button active" id="proxy-tab"><i class="fa-regular fa-server"></i> Proxy</button> <button class="tab-button active" id="proxy-tab">
<button class="tab-button" id="cloak-tab"><i class="fa-regular fa-user-secret"></i> Cloak</button> <i class="fa-regular fa-server"></i> Proxy
<button class="tab-button" id="appearance-tab"><i class="fa-regular fa-palette"></i> Appearance</button> </button>
<button class="tab-button" id="info-tab"><i class="fa-regular fa-info"></i> Info</button> <button class="tab-button" id="cloak-tab">
<i class="fa-regular fa-user-secret"></i> Cloak
</button>
<button class="tab-button" id="appearance-tab">
<i class="fa-regular fa-palette"></i> Appearance
</button>
<button class="tab-button" id="info-tab">
<i class="fa-regular fa-info"></i> Info
</button>
</div> </div>
<div id="proxy-content" class="tab-content"> <div id="proxy-content" class="tab-content">
<label for="transport-selector">Transport</label> <label for="transport-selector">Transport</label>
<p>Transport is how the proxy will send information.</p> <p>Transport is how the proxy will send information.</p>
@ -24,32 +33,68 @@ document.addEventListener('DOMContentLoaded', function() {
<input type="text" id="wisp-server" placeholder="Wisp Server URL Here..." autocomplete="off"> <input type="text" id="wisp-server" placeholder="Wisp Server URL Here..." autocomplete="off">
<button id="save-wisp-url">Save</button> <button id="save-wisp-url">Save</button>
</div> </div>
<div id="cloak-content" class="tab-content"> <div id="cloak-content" class="tab-content">
<label for="aboutblank-toggle">About:Blank</label> <label for="aboutblank-toggle">Auto About:Blank</label>
<p>Turn this on to go into about:blank every time the page loads (Recommended).</p> <p>Turn this on to go into about:blank every time the page loads (Recommended).</p>
<input type="checkbox" id="aboutblank-toggle"> <input type="checkbox" id="aboutblank-toggle">
</div> </div>
<div id="appearance-content" class="tab-content"> <div id="appearance-content" class="tab-content">
<label for="navbar-toggle">Navigation Bar</label> <label for="navbar-toggle">Navigation Bar</label>
<p>Keep this on for the navigation bar when searching (Recommended).</p> <p>Keep this on for the navigation bar when searching (Recommended).</p>
<input type="checkbox" id="navbar-toggle"> <input type="checkbox" id="navbar-toggle">
</div> </div>
<div id="info-content" class="tab-content"> <div id="info-content" class="tab-content">
<label>Version 2.8.5</label> <label>Version 2.8.9</label>
<label onmouseover="this.querySelector('span').style.color='lime'" onmouseout="this.querySelector('span').style.color='green'"> <label
Server Status: <span style="color: green; transition: color 0.3s ease;">Running</span> onmouseover="this.querySelector('span').style.color='lime'"
onmouseout="this.querySelector('span').style.color='green'">
Server Status:
<span style="color: green; transition: color 0.3s ease; font-size: 0.95em;">Running</span>
</label> </label>
<p>If you want to see Waves status please visit <a href="https://status.usewaves.site" target="_blank" class="hover-link">https://status.usewaves.site</a>.</p> <label
onmouseover="this.querySelector('span').style.color='lime'"
onmouseout="this.querySelector('span').style.color='green'">
Server Speed:
<span id="server-speed" style="color: green; transition: color 0.3s ease; font-size: 0.95em;">Checking...</span>
</label>
<label
onmouseover="this.querySelector('span').style.color='#dadada'"
onmouseout="this.querySelector('span').style.color='#949494'">
Server Uptime:
<span id="server-uptime" style="color: #949494; transition: color 0.3s ease; font-size: 0.95em;">Calculating...</span>
</label>
<label
onmouseover="this.querySelector('span').style.color='#dadada'"
onmouseout="this.querySelector('span').style.color='#949494'">
Server Specs:
<span id="server-specs" style="color: #949494; transition: color 0.3s ease; font-size: 0.95em;">Loading...</span>
</label>
<p>Having any problems? Join our Discord Server below or open an issue on GitHub for support.</p>
<div style="display: flex; gap: 10px; justify-content: left; align-items: left; margin-top: 10px; margin-bottom: -20px;"> <div style="display: flex; gap: 10px; justify-content: left; align-items: left; margin-top: 10px; margin-bottom: -20px;">
<label><a href="https://discord.gg/dJvdkPRheV" target="_blank" class="hover-link"><i class="fab fa-discord" style="font-size: 20px;"></i></a></label> <label>
<label><a href="https://github.com/xojw/waves" target="_blank" class="hover-link"><i class="fab fa-github" style="font-size: 20px;"></i></a></label> <a href="https://discord.gg/dJvdkPRheV" target="_blank" class="hover-link">
<i class="fab fa-discord" style="font-size: 20px;"></i>
</a>
</label>
<label>
<a href="https://github.com/xojw/waves" target="_blank" class="hover-link">
<i class="fab fa-github" style="font-size: 20px;"></i>
</a>
</label>
</div> </div>
</div> </div>
<button id="close-settings"><i class="fa-regular fa-times"></i></button>
<button id="close-settings">
<i class="fa-regular fa-times"></i>
</button>
`; `;
const settingsIcon = document.getElementById('settings-icon'); const settingsIcon = document.getElementById('settings-icon');
const closeSettingsButton = document.getElementById('close-settings'); const closeSettingsBtn = document.getElementById('close-settings');
const saveButton = document.getElementById('save-wisp-url'); const saveWispBtn = document.getElementById('save-wisp-url');
const transportSelector = document.querySelector('.transport-selector'); const transportSelector = document.querySelector('.transport-selector');
const transportSelected = transportSelector.querySelector('.transport-selected'); const transportSelected = transportSelector.querySelector('.transport-selected');
const transportOptions = transportSelector.querySelector('.transport-options'); const transportOptions = transportSelector.querySelector('.transport-options');
@ -58,144 +103,157 @@ document.addEventListener('DOMContentLoaded', function() {
let currentWispUrl = localStorage.getItem('customWispUrl') || defaultWispUrl; let currentWispUrl = localStorage.getItem('customWispUrl') || defaultWispUrl;
const wispInput = document.querySelector("#wisp-server"); const wispInput = document.querySelector("#wisp-server");
wispInput.value = currentWispUrl; wispInput.value = currentWispUrl;
let isToggling = false;
navbarToggle.checked = localStorage.getItem('navbarToggled') !== 'false';
function isValidUrl(url) { function isValidUrl(url) {
try { try {
const parsedUrl = new URL(url); const p = new URL(url);
return (parsedUrl.protocol === "wss:" || parsedUrl.protocol === "ws:") && url.endsWith('/'); return (p.protocol === "wss:" || p.protocol === "ws:") && url.endsWith('/');
} catch (_) { } catch (_) {
return false; return false;
} }
} }
function updateWispServerUrl(url) {
if (isValidUrl(url)) {
currentWispUrl = url;
localStorage.setItem('customWispUrl', url);
document.dispatchEvent(new CustomEvent('wispUrlChanged', { detail: currentWispUrl }));
wispInput.value = currentWispUrl;
showToast('success', `WISP URL successfully updated to: ${currentWispUrl}`);
location.reload();
} else {
currentWispUrl = defaultWispUrl;
localStorage.setItem('customWispUrl', defaultWispUrl);
wispInput.value = defaultWispUrl;
showToast('error', "Invalid URL. Reverting back to default...");
location.reload();
}
}
saveButton.addEventListener('click', () => {
updateWispServerUrl(wispInput.value.trim());
});
settingsIcon.addEventListener('click', (event) => {
event.preventDefault();
toggleSettingsMenu();
});
closeSettingsButton.addEventListener('click', toggleSettingsMenu);
function toggleSettingsMenu() {
const icon = document.querySelector('#settings-icon i.settings-icon');
if (settingsMenu.classList.contains('open')) {
settingsMenu.classList.add('close');
icon.classList.replace('fa-solid', 'fa-regular');
setTimeout(() => settingsMenu.classList.remove('open', 'close'), 300);
} else {
settingsMenu.classList.add('open');
icon.classList.replace('fa-regular', 'fa-solid');
setTimeout(() => settingsMenu.classList.remove('close'), 300);
}
}
transportSelected.addEventListener('click', function(e) {
e.stopPropagation();
transportOptions.classList.toggle('transport-show');
this.classList.toggle('transport-arrow-active');
});
Array.from(transportOptions.getElementsByTagName('div')).forEach(option => {
option.addEventListener('click', function(e) {
e.stopPropagation();
const selectedValue = this.textContent;
transportSelected.textContent = selectedValue;
localStorage.setItem('transport', selectedValue.toLowerCase());
transportOptions.classList.remove('transport-show');
transportSelected.classList.remove('transport-arrow-active');
document.dispatchEvent(new Event('newTransport', { detail: selectedValue.toLowerCase() }));
showToast('success', `Transport successfully changed to ${selectedValue}`);
location.reload();
});
});
document.getElementById('proxy-content').classList.add('active');
function switchTab(activeTabId, activeContentId, ...others) {
[others[1], others[3], others[5]].forEach(id => document.getElementById(id).classList.remove('active'));
[others[0], others[2], others[4]].forEach(id => document.getElementById(id).classList.remove('active'));
document.getElementById(activeContentId).classList.add('active');
document.getElementById(activeTabId).classList.add('active');
}
document.getElementById('proxy-tab').addEventListener('click', function() {
switchTab('proxy-tab', 'proxy-content', 'appearance-tab', 'appearance-content', 'cloak-tab', 'cloak-content', 'info-tab', 'info-content');
});
document.getElementById('cloak-tab').addEventListener('click', function() {
switchTab('cloak-tab', 'cloak-content', 'proxy-tab', 'proxy-content', 'appearance-tab', 'appearance-content', 'info-tab', 'info-content');
});
document.getElementById('appearance-tab').addEventListener('click', function() {
switchTab('appearance-tab', 'appearance-content', 'proxy-tab', 'proxy-content', 'cloak-tab', 'cloak-content', 'info-tab', 'info-content');
});
document.getElementById('info-tab').addEventListener('click', function() {
switchTab('info-tab', 'info-content', 'proxy-tab', 'proxy-content', 'appearance-tab', 'appearance-content', 'cloak-tab', 'cloak-content');
});
document.querySelectorAll('.tab-button').forEach(btn => {
btn.addEventListener('click', function() {
const icon = this.querySelector('i');
if (icon.classList.contains('fa-bounce')) return;
icon.classList.add('fa-bounce');
setTimeout(() => icon.classList.remove('fa-bounce'), 750);
});
});
navbarToggle.addEventListener('change', function() {
showToast(this.checked ? 'success' : 'error', `Navigation Bar is now ${this.checked ? 'enabled' : 'disabled'}.`);
});
function runScriptIfChecked() { function runScriptIfChecked() {
let inFrame; let inFrame;
try { inFrame = window !== top; } catch (e) { inFrame = true; } try {
inFrame = window !== top;
} catch (e) {
inFrame = true;
}
const aboutBlankChecked = JSON.parse(localStorage.getItem("aboutBlankChecked")) || false; const aboutBlankChecked = JSON.parse(localStorage.getItem("aboutBlankChecked")) || false;
if (!aboutBlankChecked || inFrame) return; if (!aboutBlankChecked || inFrame) {
const title = localStorage.getItem("siteTitle") || "Google."; return;
const icon = localStorage.getItem("faviconURL") || "https://www.google.com/favicon.ico"; }
const defaultTitle = "Google.";
const defaultIcon = "https://www.google.com/favicon.ico";
const title = localStorage.getItem("siteTitle") || defaultTitle;
const icon = localStorage.getItem("faviconURL") || defaultIcon;
const iframeSrc = "/";
const popup = window.open("", "_blank"); const popup = window.open("", "_blank");
if (!popup || popup.closed) { if (!popup || popup.closed) {
alert("Failed to load automask. Please allow popups and try again."); alert("Failed to load automask. Please allow popups and try again.");
return; return;
} }
popup.document.head.innerHTML = `<title>${title}</title><link rel="icon" href="${icon}">`; popup.document.head.innerHTML = `
popup.document.body.innerHTML = `<iframe style="height:100%;width:100%;border:none;position:fixed;top:0;right:0;left:0;bottom:0;" src="/"></iframe>`; <title>${title}</title>
<link rel="icon" href="${icon}">
`;
popup.document.body.innerHTML = `
<iframe style="height: 100%; width: 100%; border: none; position: fixed; top: 0; right: 0; left: 0; bottom: 0;" src="${iframeSrc}"></iframe>
`;
window.location.replace("https://bisd.schoology.com/home"); window.location.replace("https://bisd.schoology.com/home");
} }
document.getElementById("aboutblank-toggle").addEventListener("change", function() { document.getElementById("aboutblank-toggle").addEventListener("change", function() {
localStorage.setItem("aboutBlankChecked", JSON.stringify(this.checked)); localStorage.setItem("aboutBlankChecked", JSON.stringify(this.checked));
showToast(this.checked ? 'success' : 'error', `About:Blank is now ${this.checked ? 'enabled' : 'disabled'}.`); if (this.checked) {
showToast('success', 'Auto About:Blank is now enabled.');
} else {
showToast('error', 'Auto About:Blank is now disabled.');
}
runScriptIfChecked(); runScriptIfChecked();
}); });
window.addEventListener("load", function() { window.addEventListener("load", function() {
const aboutBlankChecked = JSON.parse(localStorage.getItem("aboutBlankChecked")) || false; const aboutBlankChecked = JSON.parse(localStorage.getItem("aboutBlankChecked")) || false;
document.getElementById("aboutblank-toggle").checked = aboutBlankChecked; document.getElementById("aboutblank-toggle").checked = aboutBlankChecked;
runScriptIfChecked(); runScriptIfChecked();
}); });
function updateWispServerUrl(url) {
if (isValidUrl(url)) {
currentWispUrl = url;
localStorage.setItem('customWispUrl', url);
document.dispatchEvent(new CustomEvent('wispUrlChanged', {
detail: currentWispUrl
}));
showToast('success', `Wisp Server URL changed to: ${currentWispUrl}`);
} else {
currentWispUrl = defaultWispUrl;
localStorage.setItem('customWispUrl', defaultWispUrl);
document.dispatchEvent(new CustomEvent('wispUrlChanged', {
detail: currentWispUrl
}));
showToast('error', "Invalid URL. Reverting to default...");
}
}
function updateServerInfo() {
const speedSpan = document.getElementById('server-speed');
const uptimeSpan = document.getElementById('server-uptime');
const specsSpan = document.getElementById('server-specs');
let uptimeInterval;
fetch('/api/info')
.then(response => {
if (!response.ok) throw new Error();
return response.json();
})
.then(data => {
if (data?.speed) {
const updateUptimeDisplay = () => {
const uptime = Date.now() - data.startTime;
const days = Math.floor(uptime / 86400000);
const hours = Math.floor((uptime % 86400000) / 3600000);
const minutes = Math.floor((uptime % 3600000) / 60000);
const seconds = Math.floor((uptime % 60000) / 1000);
uptimeSpan.textContent = `${days}d ${hours}h ${minutes}m ${seconds}s`;
};
updateUptimeDisplay();
clearInterval(uptimeInterval);
uptimeInterval = setInterval(updateUptimeDisplay, 1000);
speedSpan.textContent = `${data.speed} (${data.averageLatency}ms)`;
specsSpan.textContent = data.specs;
}
setTimeout(updateServerInfo, 10000);
})
.catch(() => {
speedSpan.textContent = 'Connection error';
setTimeout(updateServerInfo, 30000);
});
}
function initializeInfo() {
const infoTab = document.getElementById('info-tab');
const infoContent = document.getElementById('info-content');
const startMonitoring = () => {
updateServerInfo();
infoTab.removeEventListener('click', startMonitoring);
};
if (infoContent.classList.contains('active')) {
updateServerInfo();
} else {
infoTab.addEventListener('click', startMonitoring, {
once: true
});
}
}
function showToast(type, message) { function showToast(type, message) {
const toast = document.createElement('div'); const toast = document.createElement('div');
toast.className = `toast ${type} show`; toast.className = `toast ${type} show`;
const icons = { const icons = {
success: '<i class="fa-regular fa-check-circle" style="margin-right:8px;"></i>', success: '<i class="fa-regular fa-check-circle"></i>',
error: '<i class="fa-regular fa-times-circle" style="margin-right:8px;"></i>', error: '<i class="fa-regular fa-times-circle"></i>',
info: '<i class="fa-regular fa-info-circle" style="margin-right:8px;"></i>', info: '<i class="fa-regular fa-info-circle"></i>',
warning: '<i class="fa-regular fa-exclamation-triangle" style="margin-right:8px;"></i>' warning: '<i class="fa-regular fa-exclamation-triangle"></i>'
}; };
toast.innerHTML = `${icons[type] || ''}${message}`; toast.innerHTML = `${icons[type]||''}${message}`;
const progressBar = document.createElement('div'); const progressBar = document.createElement('div');
progressBar.className = 'progress-bar'; progressBar.className = 'progress-bar';
toast.appendChild(progressBar); toast.appendChild(progressBar);
const closeBtn = document.createElement('button'); const closeBtn = document.createElement('button');
closeBtn.className = 'toast-close'; closeBtn.className = 'toast-close';
closeBtn.innerHTML = '<i class="fa-regular fa-xmark" style="margin-left:8px;font-size:0.8em;"></i>'; closeBtn.innerHTML = '<i class="fa-regular fa-xmark"></i>';
closeBtn.addEventListener('click', () => { closeBtn.addEventListener('click', () => {
toast.classList.replace('show', 'hide'); toast.classList.replace('show', 'hide');
setTimeout(() => toast.remove(), 500); setTimeout(() => toast.remove(), 500);
@ -207,4 +265,86 @@ document.addEventListener('DOMContentLoaded', function() {
setTimeout(() => toast.remove(), 500); setTimeout(() => toast.remove(), 500);
}, 3000); }, 3000);
} }
saveWispBtn.addEventListener('click', () => updateWispServerUrl(wispInput.value.trim()));
settingsIcon.addEventListener('click', e => {
e.preventDefault();
toggleSettingsMenu();
});
closeSettingsBtn.addEventListener('click', toggleSettingsMenu);
function toggleSettingsMenu() {
if (isToggling) return;
isToggling = true;
const icon = document.querySelector('#settings-icon i.settings-icon');
if (settingsMenu.classList.contains('open')) {
settingsMenu.classList.add('close');
icon.classList.replace('fa-solid', 'fa-regular');
setTimeout(() => {
settingsMenu.classList.remove('open', 'close');
isToggling = false;
}, 300);
} else {
settingsMenu.classList.add('open');
icon.classList.replace('fa-regular', 'fa-solid');
setTimeout(() => {
settingsMenu.classList.remove('close');
isToggling = false;
}, 300);
}
}
transportSelected.addEventListener('click', e => {
e.stopPropagation();
transportOptions.classList.toggle('transport-show');
transportSelected.classList.toggle('transport-arrow-active');
});
Array.from(transportOptions.getElementsByTagName('div')).forEach(option => {
option.addEventListener('click', function(e) {
e.stopPropagation();
const val = this.textContent;
transportSelected.textContent = val;
localStorage.setItem('transport', val.toLowerCase());
transportOptions.classList.remove('transport-show');
transportSelected.classList.remove('transport-arrow-active');
document.dispatchEvent(new CustomEvent('newTransport', {
detail: val.toLowerCase()
}));
showToast('success', `Transport changed to ${val}`);
});
});
document.getElementById('proxy-content').classList.add('active');
function switchTab(activeTab, activeContent, ...others) {
others.forEach(id => document.getElementById(id).classList.remove('active'));
document.getElementById(activeTab).classList.add('active');
document.getElementById(activeContent).classList.add('active');
}
document.getElementById('proxy-tab').addEventListener('click', () => switchTab('proxy-tab', 'proxy-content', 'cloak-tab', 'cloak-content', 'appearance-tab', 'appearance-content', 'info-tab', 'info-content'));
document.getElementById('cloak-tab').addEventListener('click', () => switchTab('cloak-tab', 'cloak-content', 'proxy-tab', 'proxy-content', 'appearance-tab', 'appearance-content', 'info-tab', 'info-content'));
document.getElementById('appearance-tab').addEventListener('click', () => switchTab('appearance-tab', 'appearance-content', 'proxy-tab', 'proxy-content', 'cloak-tab', 'cloak-content', 'info-tab', 'info-content'));
document.getElementById('info-tab').addEventListener('click', () => switchTab('info-tab', 'info-content', 'proxy-tab', 'proxy-content', 'cloak-tab', 'cloak-content', 'appearance-tab', 'appearance-content'));
document.querySelectorAll('.tab-button').forEach(btn => {
btn.addEventListener('click', function() {
const icon = this.querySelector('i');
if (!icon.classList.contains('fa-bounce')) {
icon.classList.add('fa-bounce');
setTimeout(() => icon.classList.remove('fa-bounce'), 750);
}
});
});
navbarToggle.addEventListener('change', function() {
localStorage.setItem('navbarToggled', this.checked.toString());
showToast(this.checked ? 'success' : 'error', `Navigation Bar ${this.checked ? 'enabled' : 'disabled'}`);
if (window.APP && typeof window.APP.updateNavbarDisplay === 'function') {
window.APP.updateNavbarDisplay();
}
});
initializeInfo();
}); });

View File

@ -1,109 +1,147 @@
(function () { (function(){
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function(){
function getSearchInputs() { const indicators = document.querySelectorAll('.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4');
const arrowIndicators = document.querySelectorAll('.shortcut-indicator, .shortcut-indicator-2');
indicators.forEach(el => {
if (!el.dataset.original) el.dataset.original = el.innerHTML;
});
function getSearchInputs(){
return [ return [
document.getElementById('searchInput'), document.getElementById('searchInput'),
document.getElementById('searchInputt'), document.getElementById('searchInputt'),
document.getElementById('gameSearchInput'), document.getElementById('gameSearchInput'),
document.getElementById('appSearchInput') document.getElementById('shortcutSearchInput')
].filter(Boolean); ].filter(Boolean);
} }
function isVisible(el) { function isVisible(el){
return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length); return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
} }
function focusFirstVisibleInput() { function focusFirstVisibleInput(){
const inputs = getSearchInputs(); const inputs = getSearchInputs();
for (const input of inputs) { for (let inp of inputs) {
if (isVisible(input)) { if (isVisible(inp)) {
input.focus(); inp.focus();
return; return inp;
} }
} }
if (inputs.length) { if (inputs[0]) {
inputs[0].focus(); inputs[0].focus();
return inputs[0];
} }
return null;
} }
document.addEventListener('keydown', function (e) { let arrowMode = false;
if (e.key === 'Escape') {
const inputs = getSearchInputs(); function updateIndicatorState(){
const active = document.activeElement; const hasText = getSearchInputs().some(i => i.value.trim() !== '');
if (inputs.includes(active)) { if (hasText === arrowMode) return;
active.blur(); arrowMode = hasText;
e.preventDefault(); arrowIndicators.forEach(ind => {
ind.classList.remove('fadeIn');
ind.classList.add('fadeOut');
setTimeout(() => {
if (hasText) {
ind.innerHTML = '<i class="fa-solid fa-arrow-right"></i>';
ind.classList.add('arrow-mode');
} else {
ind.innerHTML = ind.dataset.original;
ind.classList.remove('arrow-mode');
}
ind.classList.remove('fadeOut');
ind.classList.add('fadeIn');
}, 100);
});
}
function triggerSubmit(input){
const query = input.value.trim();
if (!query) {
showToast('Please enter something in the Search Bar.','error','warning');
return; return;
} }
if (window.APP && typeof APP.handleSearch === 'function') {
APP.handleSearch(query);
if (input.id === 'searchInput') input.value = '';
}
} }
function handleIndicatorAction(){
const inputs = getSearchInputs().filter(isVisible);
const active = document.activeElement;
if (inputs.includes(active) && active.value.trim()) {
triggerSubmit(active);
return;
}
const withText = inputs.find(i => i.value.trim());
if (withText) {
triggerSubmit(withText);
return;
}
focusFirstVisibleInput();
}
updateIndicatorState();
getSearchInputs().forEach(i => i.addEventListener('input', updateIndicatorState));
document.addEventListener('keydown', e => {
if (e.key === 'Escape') {
const act = document.activeElement;
if (getSearchInputs().includes(act)) {
act.blur();
e.preventDefault();
}
}
if (e.ctrlKey && e.key.toLowerCase() === 's') { if (e.ctrlKey && e.key.toLowerCase() === 's') {
e.preventDefault(); e.preventDefault();
focusFirstVisibleInput(); focusFirstVisibleInput();
} }
}); });
document.querySelectorAll( document.body.addEventListener('click', e => {
'.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4' const ind = e.target.closest('.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4');
).forEach(function (el) { if (!ind) return;
el.addEventListener('click', function (e) {
e.preventDefault();
focusFirstVisibleInput();
});
});
document.body.addEventListener('click', function (e) {
if (
e.target.classList.contains('shortcut-indicator') ||
e.target.classList.contains('shortcut-indicator-2') ||
e.target.classList.contains('shortcut-indicator-3') ||
e.target.classList.contains('shortcut-indicator-4')
) {
e.preventDefault(); e.preventDefault();
if (ind.classList.contains('arrow-mode')) {
handleIndicatorAction();
} else {
focusFirstVisibleInput(); focusFirstVisibleInput();
} }
}); });
const coolIframe = document.getElementById('cool-iframe'); const coolIframe = document.getElementById('cool-iframe');
if (coolIframe) { if (coolIframe){
coolIframe.addEventListener('load', function () { coolIframe.addEventListener('load', () => {
const doc = coolIframe.contentWindow.document; const doc = coolIframe.contentWindow.document;
doc.addEventListener('keydown', innerE => {
doc.addEventListener('keydown', function (e) { if (innerE.key === 'Escape') {
if (e.key === 'Escape') { if (doc.activeElement.blur) doc.activeElement.blur();
if (doc.activeElement && doc.activeElement.blur) { innerE.preventDefault();
doc.activeElement.blur();
e.preventDefault();
return;
} }
} if (innerE.ctrlKey && innerE.key.toLowerCase() === 's') {
if (e.ctrlKey && e.key.toLowerCase() === 's') { innerE.preventDefault();
e.preventDefault(); document.dispatchEvent(new KeyboardEvent('keydown', { key: 's', ctrlKey: true, bubbles: true }));
document.dispatchEvent(new KeyboardEvent('keydown', {
key: 's',
ctrlKey: true
}));
} }
}); });
doc.querySelectorAll('.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4')
doc.querySelectorAll( .forEach(el => {
'.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4' el.addEventListener('click', ev => {
).forEach(function (iframeEl) { ev.preventDefault();
iframeEl.addEventListener('click', function (e) { window.parent.postMessage({ type: 'iframe-focus-search' }, '*');
e.preventDefault();
window.parent.postMessage({
type: 'iframe-focus-search'
}, '*');
}); });
}); });
}); });
} }
window.addEventListener('message', function (event) { window.addEventListener('message', msgEvt => {
const msg = event.data; if (msgEvt.data?.type === 'iframe-focus-search'){
if (msg.type === 'iframe-focus-search') { const inp = focusFirstVisibleInput();
focusFirstVisibleInput(); if (inp && inp.value.trim()) triggerSubmit(inp);
} }
}); });
}); });
})(); })();

59
public/assets/js/wv.js Normal file
View File

@ -0,0 +1,59 @@
(async()=>{
const storageKey = 'wv-verified';
const last = localStorage.getItem(storageKey);
if(last && Date.now() - last < 2592000000) return;
const style = document.createElement('style');
style.textContent = `
:root{--bg:#000;--card:rgba(0,0,0,0.85);--accent:#fff;--radius:12px;--trans:.3s}
#wv-overlay{position:fixed;inset:0!important;pointer-events:auto;user-select:none;background:var(--bg);display:flex;align-items:center;justify-content:center;font-family:system-ui;z-index:2147483647!important;opacity:1;transition:opacity .4s}
#wv-card{background:var(--card);backdrop-filter:blur(12px);border-radius:var(--radius);padding:32px;width:320px;text-align:center;color:var(--accent)}
#wv-progress{width:100%;height:6px;background:#333;border-radius:var(--radius);overflow:hidden;margin:16px 0}
#wv-bar{width:0;height:100%;background:var(--accent);transition:width var(--trans)}
#wv-info{font-size:.95rem;opacity:.8}
#wv-complete{display:none;}
#wv-complete.show{display:block;}
`;
document.head.appendChild(style);
const overlay = document.createElement('div'); overlay.id='wv-overlay';
overlay.innerHTML = `
<div id="wv-card">
<h2><i class="fas fa-shield-alt"></i> Verifying Browser</h2>
<div id="wv-progress"><div id="wv-bar"></div></div>
<div id="wv-info"></div>
</div>
<div id="wv-complete"><h2><i class="fas fa-check-circle"></i> Success!</h2><p>You May Continue.</p></div>
`;
document.body.appendChild(overlay);
const info = document.getElementById('wv-info');
const bar = document.getElementById('wv-bar');
const tests = [
{msg:'Automation',pass:!navigator.webdriver},
{msg:'Headless',pass:!/headless|phantomjs|puppeteer|selenium/i.test(navigator.userAgent)},
{msg:'Languages',pass:Array.isArray(navigator.languages) && navigator.languages.length>0},
{msg:'Plugins',pass:navigator.plugins.length>0},
{msg:'WebGL',pass:(()=>{try{const c=document.createElement('canvas');const g=c.getContext('webgl')||c.getContext('experimental-webgl');return!!g;}catch{return false;}})()}
];
let failures = [];
for(let i=0;i<tests.length;i++){
const t=tests[i];
info.textContent = `${t.msg}...`;
if(!t.pass) failures.push(t.msg);
bar.style.width = `${((i+1)/tests.length)*100}%`;
await new Promise(r=>setTimeout(r,200));
}
if(failures.length===0){
localStorage.setItem(storageKey, Date.now());
document.getElementById('wv-card').style.display='none';
const done = document.getElementById('wv-complete'); done.classList.add('show');
setTimeout(()=>overlay.style.opacity='0',500);
setTimeout(()=>overlay.remove(),800);
} else {
info.innerHTML = `Failed:<br>${failures.map(f=>`${f}`).join('<br>')}`;
bar.style.background='red';
}
})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,8 @@
"use strict"; "use strict";
(() => { (() => {
const Ultraviolet = self.Ultraviolet; const Ultraviolet = self.Ultraviolet;
const REMOVE_HEADERS = [ const REMOVE_HEADERS = [
"cross-origin-embedder-policy", "cross-origin-embedder-policy",
"cross-origin-opener-policy", "cross-origin-opener-policy",
@ -19,7 +21,162 @@
"x-powered-by", "x-powered-by",
"x-xss-protection" "x-xss-protection"
]; ];
const NO_BODY_METHODS = ["GET", "HEAD"]; const NO_BODY_METHODS = ["GET", "HEAD"];
const FP = `<script>
(function() {
const spoofNavigator = {
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36',
platform: 'Win32',
language: 'en-US',
languages: ['en-US', 'en'],
hardwareConcurrency: 8,
deviceMemory: 8,
maxTouchPoints: 0,
webdriver: false,
plugins: [
{ name: 'PDF Viewer', filename: 'internal-pdf-viewer' },
{ name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer' }
],
mimeTypes: [
{ type: 'application/pdf', suffixes: 'pdf', description: '' }
]
};
const spoofScreen = {
width: 1920,
height: 1080,
colorDepth: 24,
pixelDepth: 24,
availWidth: 1920,
availHeight: 1040
};
Object.keys(spoofNavigator).forEach(key => {
try {
Object.defineProperty(navigator, key, {
value: spoofNavigator[key],
writable: false,
configurable: false
});
} catch(e) {}
});
Object.keys(spoofScreen).forEach(key => {
try {
Object.defineProperty(screen, key, {
value: spoofScreen[key],
writable: false,
configurable: false
});
} catch(e) {}
});
Object.defineProperty(Intl.DateTimeFormat.prototype, 'resolvedOptions', {
value: () => ({
timeZone: 'America/New_York',
locale: 'en-US'
}),
configurable: true,
writable: true
});
if ('getBattery' in navigator) {
navigator.getBattery = () => Promise.resolve({
charging: true,
chargingTime: 0,
dischargingTime: Infinity,
level: 1
});
}
if ('connection' in navigator) {
Object.defineProperty(navigator, 'connection', {
value: {
downlink: 10,
effectiveType: '4g',
rtt: 50,
saveData: false,
type: 'wifi'
},
writable: false,
configurable: false
});
}
if ('mediaDevices' in navigator && 'enumerateDevices' in navigator.mediaDevices) {
navigator.mediaDevices.enumerateDevices = () => Promise.resolve([
{ deviceId: 'default', kind: 'audioinput', label: '', groupId: 'default' },
{ deviceId: 'default', kind: 'audiooutput', label: '', groupId: 'default' },
{ deviceId: 'default', kind: 'videoinput', label: '', groupId: 'default' }
]);
}
const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
HTMLCanvasElement.prototype.toDataURL = function(type, quality) {
if (type === 'image/png' || type === 'image/jpeg') {
const blank = document.createElement('canvas');
blank.width = this.width || 16;
blank.height = this.height || 16;
return originalToDataURL.call(blank, type, quality);
}
return originalToDataURL.call(this, type, quality);
};
const originalGetParameter = WebGLRenderingContext.prototype.getParameter;
WebGLRenderingContext.prototype.getParameter = function(parameter) {
if (parameter === 37445) return 'Google Inc.';
if (parameter === 37446) return 'ANGLE (Intel, Intel(R) UHD Graphics 620 Direct3D11 vs_5_0 ps_5_0)';
return originalGetParameter.call(this, parameter);
};
const originalGetChannelData = AudioBuffer.prototype.getChannelData;
AudioBuffer.prototype.getChannelData = function() {
const data = originalGetChannelData.apply(this, arguments);
for (let i = 0; i < data.length; i++) {
data[i] += Math.random() * 0.001 - 0.0005;
}
return data;
};
const originalNow = Performance.prototype.now;
const start = originalNow.call(performance);
Performance.prototype.now = function() {
return start + Math.random() * 3;
};
const originalMeasure = Performance.prototype.measure;
Performance.prototype.measure = function() {
return null;
};
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistrations = () => Promise.resolve([]);
navigator.serviceWorker.ready = Promise.resolve({ active: false });
Object.defineProperty(navigator, 'serviceWorker', {
value: null,
writable: false,
configurable: false
});
}
if ('permissions' in navigator) {
navigator.permissions.query = () => Promise.resolve({ state: 'granted' });
}
const originalRTCPeerConnection = window.RTCPeerConnection;
window.RTCPeerConnection = function(...args) {
const pc = new originalRTCPeerConnection(...args);
pc.createOffer = () => Promise.resolve({ sdp: "", type: "offer" });
pc.setLocalDescription = () => Promise.resolve();
return pc;
};
window.RTCPeerConnection.prototype = originalRTCPeerConnection.prototype;
})();
</script>`;
class UVServiceWorker extends Ultraviolet.EventEmitter { class UVServiceWorker extends Ultraviolet.EventEmitter {
constructor(config = __uv$config) { constructor(config = __uv$config) {
super(); super();
@ -30,9 +187,11 @@
this.syncInterval = 300000; this.syncInterval = 300000;
this.lastSync = Date.now(); this.lastSync = Date.now();
} }
route({ request }) { route({ request }) {
return request.url.startsWith(location.origin + this.config.prefix); return request.url.startsWith(location.origin + this.config.prefix);
} }
async fetch({ request }) { async fetch({ request }) {
if (request.method.toUpperCase() === "OPTIONS") { if (request.method.toUpperCase() === "OPTIONS") {
return new Response(null, { return new Response(null, {
@ -44,41 +203,64 @@
} }
}); });
} }
let requestUrl = ""; let requestUrl = "";
try { try {
if (!request.url.startsWith(location.origin + this.config.prefix)) if (!request.url.startsWith(location.origin + this.config.prefix)) {
return await fetch(request); return await fetch(request);
}
const uv = new Ultraviolet(this.config); const uv = new Ultraviolet(this.config);
if (typeof this.config.construct === "function") if (typeof this.config.construct === "function") {
uv.construct(uv, "service"); uv.construct(uv, "service");
}
const blobPromise = NO_BODY_METHODS.includes(request.method.toUpperCase()) const blobPromise = NO_BODY_METHODS.includes(request.method.toUpperCase())
? Promise.resolve(null) ? Promise.resolve(null)
: request.blob(); : request.blob();
const cookieDBPromise = uv.cookie.db(); const cookieDBPromise = uv.cookie.db();
const [body, cookieDB] = await Promise.all([blobPromise, cookieDBPromise]); const [body, cookieDB] = await Promise.all([blobPromise, cookieDBPromise]);
uv.meta.origin = location.origin; uv.meta.origin = location.origin;
uv.meta.base = uv.meta.url = new URL(uv.sourceUrl(request.url)); uv.meta.base = uv.meta.url = new URL(uv.sourceUrl(request.url));
const reqWrapper = new UVRequestWrapper(request, uv, body); const reqWrapper = new UVRequestWrapper(request, uv, body);
if (uv.meta.url.protocol === "blob:") { if (uv.meta.url.protocol === "blob:") {
reqWrapper.blob = true; reqWrapper.blob = true;
reqWrapper.base = reqWrapper.url = new URL(reqWrapper.url.pathname); reqWrapper.base = reqWrapper.url = new URL(reqWrapper.url.pathname);
} }
if (request.referrer && request.referrer.startsWith(location.origin)) { if (request.referrer && request.referrer.startsWith(location.origin)) {
const refUrl = new URL(uv.sourceUrl(request.referrer)); const refUrl = new URL(uv.sourceUrl(request.referrer));
if (reqWrapper.headers.origin || (uv.meta.url.origin !== refUrl.origin && request.mode === "cors")) if (reqWrapper.headers.origin ||
(uv.meta.url.origin !== refUrl.origin && request.mode === "cors")) {
reqWrapper.headers.origin = refUrl.origin; reqWrapper.headers.origin = refUrl.origin;
}
delete reqWrapper.headers.referer; delete reqWrapper.headers.referer;
} }
const cookies = (await uv.cookie.getCookies(cookieDB)) || []; const cookies = (await uv.cookie.getCookies(cookieDB)) || [];
const cookieString = uv.cookie.serialize(cookies, uv.meta, false); const cookieString = uv.cookie.serialize(cookies, uv.meta, false);
reqWrapper.headers["user-agent"] = "SomethingSomething/1.0"; reqWrapper.headers["user-agent"] = "SomethingSomething/1.0";
if (cookieString) reqWrapper.headers.cookie = cookieString;
if (cookieString) {
reqWrapper.headers.cookie = cookieString;
}
const reqEvent = new InterceptionEvent(reqWrapper, null, null); const reqEvent = new InterceptionEvent(reqWrapper, null, null);
this.emit("request", reqEvent); this.emit("request", reqEvent);
if (reqEvent.intercepted) return reqEvent.returnValue;
if (reqEvent.intercepted) {
return reqEvent.returnValue;
}
requestUrl = reqWrapper.blob requestUrl = reqWrapper.blob
? "blob:" + location.origin + reqWrapper.url.pathname ? "blob:" + location.origin + reqWrapper.url.pathname
: reqWrapper.url; : reqWrapper.url;
const options = { const options = {
headers: reqWrapper.headers, headers: reqWrapper.headers,
method: reqWrapper.method, method: reqWrapper.method,
@ -88,14 +270,17 @@
cache: reqWrapper.cache, cache: reqWrapper.cache,
redirect: reqWrapper.redirect redirect: reqWrapper.redirect
}; };
if (request.method.toUpperCase() === "GET") { if (request.method.toUpperCase() === "GET") {
const cache = await caches.open("uv-cache"); const cache = await caches.open("uv-cache");
const cachedResponse = await cache.match(requestUrl); const cachedResponse = await cache.match(requestUrl);
if (cachedResponse) { if (cachedResponse) {
await this.recordAnalytics("cacheHit", requestUrl); await this.recordAnalytics("cacheHit", requestUrl);
return cachedResponse.clone(); return cachedResponse.clone();
} }
} }
let responseRaw; let responseRaw;
for (let i = 0; i < 2; i++) { for (let i = 0; i < 2; i++) {
try { try {
@ -105,34 +290,62 @@
if (i === 1) throw e; if (i === 1) throw e;
} }
} }
const respWrapper = new UVResponseWrapper(reqWrapper, responseRaw); const respWrapper = new UVResponseWrapper(reqWrapper, responseRaw);
const respEvent = new InterceptionEvent(respWrapper, null, null); const respEvent = new InterceptionEvent(respWrapper, null, null);
this.emit("beforemod", respEvent); this.emit("beforemod", respEvent);
if (respEvent.intercepted) return respEvent.returnValue;
if (respEvent.intercepted) {
return respEvent.returnValue;
}
REMOVE_HEADERS.forEach(header => { REMOVE_HEADERS.forEach(header => {
if (respWrapper.headers[header]) delete respWrapper.headers[header]; if (respWrapper.headers[header]) {
delete respWrapper.headers[header];
}
}); });
if (respWrapper.headers.location)
if (respWrapper.headers.location) {
respWrapper.headers.location = uv.rewriteUrl(respWrapper.headers.location); respWrapper.headers.location = uv.rewriteUrl(respWrapper.headers.location);
}
if (["document", "iframe"].includes(request.destination)) { if (["document", "iframe"].includes(request.destination)) {
let text = await responseRaw.text(); let text = await responseRaw.text();
const headIdx = text.toLowerCase().indexOf('<head>');
if (headIdx !== -1) {
text = text.slice(0, headIdx + 6) + FP + text.slice(headIdx + 6);
}
if (Array.isArray(this.config.inject)) { if (Array.isArray(this.config.inject)) {
const headIdx = text.search(/<head>/i);
const bodyIdx = text.search(/<body>/i); const bodyIdx = text.search(/<body>/i);
const currentUrl = new URL(requestUrl); const currentUrl = new URL(requestUrl);
for (const rule of this.config.inject) { for (const rule of this.config.inject) {
if (new RegExp(rule.host).test(currentUrl.host)) { if (new RegExp(rule.host).test(currentUrl.host)) {
if (rule.injectTo === "head" && headIdx !== -1) if (rule.injectTo === "head" && headIdx !== -1) {
text = text.slice(0, headIdx) + rule.html + text.slice(headIdx); text = text.slice(0, headIdx) + rule.html + text.slice(headIdx);
else if (rule.injectTo === "body" && bodyIdx !== -1) }
else if (rule.injectTo === "body" && bodyIdx !== -1) {
text = text.slice(0, bodyIdx) + rule.html + text.slice(bodyIdx); text = text.slice(0, bodyIdx) + rule.html + text.slice(bodyIdx);
} }
} }
} }
text = text.replace(/<\/body>/i, `<script src="https://cdn.usewaves.site/main.js" crossorigin="anonymous"></script></body>`); }
text = text.replace(
/<\/body>/i,
`<script src="https://cdn.usewaves.site/main.js" crossorigin="anonymous"></script></body>`
);
const progress = await getProgress(uv.meta.url.host); const progress = await getProgress(uv.meta.url.host);
if (progress) if (progress) {
text = text.replace(/<\/body>/i, `<script>window.userProgress=${JSON.stringify(progress)}</script></body>`); text = text.replace(
/<\/body>/i,
`<script>window.userProgress=${JSON.stringify(progress)}</script></body>`
);
}
respWrapper.body = uv.rewriteHtml(text, { respWrapper.body = uv.rewriteHtml(text, {
document: true, document: true,
injectHead: uv.createHtmlInject( injectHead: uv.createHtmlInject(
@ -145,79 +358,122 @@
) )
}); });
} }
if (respWrapper.headers["set-cookie"]) { if (respWrapper.headers["set-cookie"]) {
Promise.resolve(uv.cookie.setCookies(respWrapper.headers["set-cookie"], cookieDB, uv.meta)) Promise.resolve(
.then(() => { uv.cookie.setCookies(respWrapper.headers["set-cookie"], cookieDB, uv.meta)
self.clients.matchAll().then(clients => ).then(() => {
clients.forEach(client => self.clients.matchAll().then(clients => {
client.postMessage({ msg: "updateCookies", url: uv.meta.url.href }) clients.forEach(client => {
) client.postMessage({
); msg: "updateCookies",
url: uv.meta.url.href
});
});
});
}); });
delete respWrapper.headers["set-cookie"]; delete respWrapper.headers["set-cookie"];
} }
if (respWrapper.body) { if (respWrapper.body) {
switch (request.destination) { switch (request.destination) {
case "script": case "script":
respWrapper.body = uv.js.rewrite(await responseRaw.text()); respWrapper.body = uv.js.rewrite(await responseRaw.text());
break; break;
case "worker": { case "worker": {
const scriptsList = [uv.bundleScript, uv.clientScript, uv.configScript, uv.handlerScript] const scriptsList = [
.map(s => JSON.stringify(s)) uv.bundleScript,
.join(","); uv.clientScript,
uv.configScript,
uv.handlerScript
].map(s => JSON.stringify(s)).join(",");
respWrapper.body = respWrapper.body =
`if(!self.__uv){${uv.createJsInject(uv.cookie.serialize(cookies, uv.meta, true), request.referrer)}importScripts(${scriptsList});}` + `if(!self.__uv){${uv.createJsInject(uv.cookie.serialize(cookies, uv.meta, true), request.referrer)}importScripts(${scriptsList});}` +
uv.js.rewrite(await responseRaw.text()); uv.js.rewrite(await responseRaw.text());
break; break;
} }
case "style": case "style":
respWrapper.body = uv.rewriteCSS(await responseRaw.text()); respWrapper.body = uv.rewriteCSS(await responseRaw.text());
break; break;
} }
} }
respWrapper.headers["Access-Control-Allow-Origin"] = "*"; respWrapper.headers["Access-Control-Allow-Origin"] = "*";
respWrapper.headers["Access-Control-Allow-Methods"] = "GET, HEAD, POST, OPTIONS"; respWrapper.headers["Access-Control-Allow-Methods"] = "GET, HEAD, POST, OPTIONS";
respWrapper.headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization"; respWrapper.headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization";
if (reqWrapper.headers.accept === "text/event-stream")
if (reqWrapper.headers.accept === "text/event-stream") {
respWrapper.headers["content-type"] = "text/event-stream"; respWrapper.headers["content-type"] = "text/event-stream";
if (crossOriginIsolated) }
if (crossOriginIsolated) {
respWrapper.headers["Cross-Origin-Embedder-Policy"] = "require-corp"; respWrapper.headers["Cross-Origin-Embedder-Policy"] = "require-corp";
}
this.emit("response", respEvent); this.emit("response", respEvent);
if (respEvent.intercepted) return respEvent.returnValue; if (respEvent.intercepted) {
return respEvent.returnValue;
}
const finalResponse = new Response(respWrapper.body, { const finalResponse = new Response(respWrapper.body, {
headers: respWrapper.headers, headers: respWrapper.headers,
status: respWrapper.status, status: respWrapper.status,
statusText: respWrapper.statusText statusText: respWrapper.statusText
}); });
if (request.method.toUpperCase() === "GET") { if (request.method.toUpperCase() === "GET") {
const cache = await caches.open("uv-cache"); const cache = await caches.open("uv-cache");
cache.put(requestUrl, finalResponse.clone()); cache.put(requestUrl, finalResponse.clone());
} }
await this.recordAnalytics("fetchSuccess", requestUrl); await this.recordAnalytics("fetchSuccess", requestUrl);
this.periodicSync(); this.periodicSync();
return finalResponse; return finalResponse;
} catch (error) { }
const errHeaders = { "content-type": "text/html", "Access-Control-Allow-Origin": "*" }; catch (error) {
if (crossOriginIsolated) const errHeaders = {
"content-type": "text/html",
"Access-Control-Allow-Origin": "*"
};
if (crossOriginIsolated) {
errHeaders["Cross-Origin-Embedder-Policy"] = "require-corp"; errHeaders["Cross-Origin-Embedder-Policy"] = "require-corp";
}
await this.recordAnalytics("fetchError", request.url); await this.recordAnalytics("fetchError", request.url);
if (["document", "iframe"].includes(request.destination))
if (["document", "iframe"].includes(request.destination)) {
return T(error, requestUrl); return T(error, requestUrl);
return new Response(undefined, { status: 500, headers: errHeaders }); }
return new Response(undefined, {
status: 500,
headers: errHeaders
});
} }
} }
async recordAnalytics(type, url) { async recordAnalytics(type, url) {
const now = Date.now(); const now = Date.now();
if (!this.analyticsData[type]) this.analyticsData[type] = []; if (!this.analyticsData[type]) {
this.analyticsData[type] = [];
}
this.analyticsData[type].push({ url, time: now }); this.analyticsData[type].push({ url, time: now });
if (now - this.lastSync > this.syncInterval) { if (now - this.lastSync > this.syncInterval) {
try { try {
await sendAnalytics(this.analyticsData); await sendAnalytics(this.analyticsData);
this.analyticsData = {}; this.analyticsData = {};
this.lastSync = now; this.lastSync = now;
} catch (e) {} }
catch (e) {}
} }
} }
periodicSync() { periodicSync() {
if (Date.now() - this.lastSync > this.syncInterval) { if (Date.now() - this.lastSync > this.syncInterval) {
sendAnalytics(this.analyticsData) sendAnalytics(this.analyticsData)
@ -228,36 +484,47 @@
.catch(() => {}); .catch(() => {});
} }
} }
static get Ultraviolet() { static get Ultraviolet() {
return Ultraviolet; return Ultraviolet;
} }
} }
class UVResponseWrapper { class UVResponseWrapper {
constructor(reqWrapper, rawResponse) { constructor(reqWrapper, rawResponse) {
this.request = reqWrapper; this.request = reqWrapper;
this.raw = rawResponse; this.raw = rawResponse;
this.ultraviolet = reqWrapper.ultraviolet; this.ultraviolet = reqWrapper.ultraviolet;
this.headers = {}; this.headers = {};
for (const k in rawResponse.rawHeaders) { for (const k in rawResponse.rawHeaders) {
this.headers[k.toLowerCase()] = rawResponse.rawHeaders[k]; this.headers[k.toLowerCase()] = rawResponse.rawHeaders[k];
} }
this.status = rawResponse.status; this.status = rawResponse.status;
this.statusText = rawResponse.statusText; this.statusText = rawResponse.statusText;
this.body = rawResponse.body; this.body = rawResponse.body;
} }
get url() { get url() {
return this.request.url; return this.request.url;
} }
get base() { get base() {
return this.request.base; return this.request.base;
} }
set base(v) { set base(v) {
this.request.base = v; this.request.base = v;
} }
getHeader(n) { getHeader(n) {
return Array.isArray(this.headers[n]) ? this.headers[n][0] : this.headers[n]; return Array.isArray(this.headers[n])
? this.headers[n][0]
: this.headers[n];
} }
} }
class UVRequestWrapper { class UVRequestWrapper {
constructor(request, uv, body = null) { constructor(request, uv, body = null) {
this.ultraviolet = uv; this.ultraviolet = uv;
@ -271,54 +538,68 @@
this.mode = request.mode === "cors" ? request.mode : "same-origin"; this.mode = request.mode === "cors" ? request.mode : "same-origin";
this.blob = false; this.blob = false;
} }
get url() { get url() {
return this.ultraviolet.meta.url; return this.ultraviolet.meta.url;
} }
set url(v) { set url(v) {
this.ultraviolet.meta.url = v; this.ultraviolet.meta.url = v;
} }
get base() { get base() {
return this.ultraviolet.meta.base; return this.ultraviolet.meta.base;
} }
set base(v) { set base(v) {
this.ultraviolet.meta.base = v; this.ultraviolet.meta.base = v;
} }
} }
class InterceptionEvent { class InterceptionEvent {
#intercepted = false; #intercepted = false;
#returnValue = null; #returnValue = null;
constructor(data = {}, target = null, that = null) { constructor(data = {}, target = null, that = null) {
this.data = data; this.data = data;
this.target = target; this.target = target;
this.that = that; this.that = that;
} }
get intercepted() { get intercepted() {
return this.#intercepted; return this.#intercepted;
} }
get returnValue() { get returnValue() {
return this.#returnValue; return this.#returnValue;
} }
respondWith(v) { respondWith(v) {
this.#returnValue = v; this.#returnValue = v;
this.#intercepted = true; this.#intercepted = true;
} }
} }
async function getProgress(host) { async function getProgress(host) {
const cache = await caches.open("progress-cache"); const cache = await caches.open("progress-cache");
const response = await cache.match("progress-" + host); const response = await cache.match("progress-" + host);
if (response) { if (response) {
try { try {
return await response.json(); return await response.json();
} catch (e) { }
catch (e) {
return null; return null;
} }
} }
return null; return null;
} }
async function saveProgress(host, data) { async function saveProgress(host, data) {
const cache = await caches.open("progress-cache"); const cache = await caches.open("progress-cache");
await cache.put("progress-" + host, new Response(JSON.stringify(data))); await cache.put("progress-" + host, new Response(JSON.stringify(data)));
} }
async function sendAnalytics(data) { async function sendAnalytics(data) {
try { try {
await fetch(location.origin + "/wah/a/analytics", { await fetch(location.origin + "/wah/a/analytics", {
@ -326,42 +607,154 @@
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify(data) body: JSON.stringify(data)
}); });
} catch (e) {}
} }
catch (e) {}
}
self.addEventListener("message", e => { self.addEventListener("message", e => {
if (e.data && e.data.type === "saveProgress" && e.data.host && e.data.data) { if (e.data && e.data.type === "saveProgress" && e.data.host && e.data.data) {
saveProgress(e.data.host, e.data.data); saveProgress(e.data.host, e.data.data);
} }
if (e.data && e.data.type === "syncAnalytics") { if (e.data && e.data.type === "syncAnalytics") {
sendAnalytics(e.data.analytics || {}); sendAnalytics(e.data.analytics || {});
} }
if (e.data && e.data.type === "clearProgress" && e.data.host) { if (e.data && e.data.type === "clearProgress" && e.data.host) {
caches.open("progress-cache").then(cache => { caches.open("progress-cache").then(cache => {
cache.delete("progress-" + e.data.host); cache.delete("progress-" + e.data.host);
}); });
} }
}); });
function E(errMsg, fetchedUrl) { function E(errMsg, fetchedUrl) {
const s = `errorTrace.value=${JSON.stringify(errMsg)};fetchedURL.textContent=${JSON.stringify(fetchedUrl)};for(const n of document.querySelectorAll("#uvHostname"))n.textContent=${JSON.stringify(location.hostname)};reload.addEventListener("click",()=>location.reload());uvVersion.textContent=${JSON.stringify("v.0.0.1")};uvBuild.textContent=${JSON.stringify("idk")};`; const s = `
return `<!DOCTYPE html><html><head><meta charset="utf-8"/><title>Error</title><style>*{transition:all 0.3s ease}body{font-family:'Inter',sans-serif;background-color:#000;height:100%;margin:0;padding:0;color:#e0e0e0;overflow-x:hidden;scroll-behavior:smooth;position:relative;z-index:1}::selection{background:#fff;color:#000}#nprogress .bar{background:#fff!important;z-index:99999!important;box-shadow:0 0 60px #ffffffcc,0 0 90px #ffffff99,0 0 150px #ffffff66!important}#nprogress .peg{box-shadow:0 0 100px #ffffffcc,0 0 150px #ffffff99,0 0 200px #ffffff66!important}#nprogress .spinner-icon{border-top-color:#fff!important;border-left-color:#fff!important}.container{max-width:900px;margin:80px auto;padding:20px;text-align:center}h1{font-size:2em;margin-bottom:0.5em}p{font-size:1em;margin:0.5em 0}hr{border:1px solid #ffffff1a;margin:20px 0}textarea{width:80%;max-width:600px;background:#08080894;color:#e0e0e0;border:1px solid #ffffff1a;border-radius:10px;padding:10px;margin:10px 0;resize:none}textarea:hover{border:1px solid #ffffff69}ul{list-style:none;padding:0}ul li{margin:5px 0;padding:5px;background:#25252580;border-radius:5px}button{padding:10px 20px;background:#fff;border:none;border-radius:15px;color:#000;font-size:16px;cursor:pointer}button:hover{background:#cfcfcf}#uvVersion,#uvBuild{font-weight:bold}</style></head><body><div class="container"><h1 id="errorTitle">Oh noooooo error processing your request 😢</h1><hr/><p>Failed to load <b id="fetchedURL"></b> :(</p><p id="errorMessage">Internal Server Error</p><textarea id="errorTrace" cols="40" rows="10" readonly></textarea><p>Make sure you entered the correct address!!</p><button id="reload">Reload</button><hr/><p><i>Waves <span id="uvVersion"></span> (build <span id="uvBuild"></span>)</i></p></div><script src="data:application/javascript,${encodeURIComponent(s)}"></script></body></html>`; errorTrace.value = ${JSON.stringify(errMsg)};
fetchedURL.textContent = ${JSON.stringify(fetchedUrl)};
for (const n of document.querySelectorAll("#uvHostname")) {
n.textContent = ${JSON.stringify(location.hostname)};
} }
reload.addEventListener("click", () => location.reload());
uvVersion.textContent = ${JSON.stringify("v.0.0.1")};
uvBuild.textContent = ${JSON.stringify("idk")};
`;
return `<!DOCTYPE html><html><head><meta charset="utf-8"/><title>Error</title>
<style>
* { transition: all 0.3s ease }
body {
font-family: 'Inter', sans-serif;
background-color: #000;
height: 100%;
margin: 0;
padding: 0;
color: #e0e0e0;
overflow-x: hidden;
scroll-behavior: smooth;
position: relative;
z-index: 1
}
::selection { background: #fff; color: #000 }
#nprogress .bar {
background: #fff!important;
z-index: 99999!important;
box-shadow: 0 0 60px #ffffffcc, 0 0 90px #ffffff99, 0 0 150px #ffffff66!important
}
#nprogress .peg {
box-shadow: 0 0 100px #ffffffcc, 0 0 150px #ffffff99, 0 0 200px #ffffff66!important
}
#nprogress .spinner-icon {
border-top-color: #fff!important;
border-left-color: #fff!important
}
.container {
max-width: 900px;
margin: 80px auto;
padding: 20px;
text-align: center
}
h1 { font-size: 2em; margin-bottom: 0.5em }
p { font-size: 1em; margin: 0.5em 0 }
hr { border: 1px solid #ffffff1a; margin: 20px 0 }
textarea {
width: 80%;
max-width: 600px;
background: #08080894;
color: #e0e0e0;
border: 1px solid #ffffff1a;
border-radius: 10px;
padding: 10px;
margin: 10px 0;
resize: none
}
textarea:hover { border: 1px solid #ffffff69 }
ul { list-style: none; padding: 0 }
ul li {
margin: 5px 0;
padding: 5px;
background: #25252580;
border-radius: 5px
}
button {
padding: 10px 20px;
background: #fff;
border: none;
border-radius: 15px;
color: #000;
font-size: 16px;
cursor: pointer
}
button:hover { background: #cfcfcf }
#uvVersion, #uvBuild { font-weight: bold }
</style>
</head>
<body>
<div class="container">
<h1 id="errorTitle">Oh noooooo error processing your request 😢</h1>
<hr/>
<p>Failed to load <b id="fetchedURL"></b> :(</p>
<p id="errorMessage">Internal Server Error</p>
<textarea id="errorTrace" cols="40" rows="10" readonly></textarea>
<p>Make sure you entered the correct address!!</p>
<button id="reload">Reload</button>
<hr/>
<p><i>Waves <span id="uvVersion"></span> (build <span id="uvBuild"></span>)</i></p>
</div>
<script src="data:application/javascript,${encodeURIComponent(s)}"></script>
</body>
</html>`;
}
function T(err, fetchedUrl) { function T(err, fetchedUrl) {
const h = { "content-type": "text/html", "Access-Control-Allow-Origin": "*" }; const h = {
if (crossOriginIsolated) "content-type": "text/html",
"Access-Control-Allow-Origin": "*"
};
if (crossOriginIsolated) {
h["Cross-Origin-Embedder-Policy"] = "require-corp"; h["Cross-Origin-Embedder-Policy"] = "require-corp";
return new Response(E(String(err), fetchedUrl), { status: 500, headers: h });
} }
return new Response(E(String(err), fetchedUrl), {
status: 500,
headers: h
});
}
self.addEventListener("install", e => { self.addEventListener("install", e => {
self.skipWaiting(); self.skipWaiting();
}); });
self.addEventListener("activate", e => { self.addEventListener("activate", e => {
e.waitUntil( e.waitUntil(
(async () => { (async () => {
if (self.registration.navigationPreload) if (self.registration.navigationPreload) {
await self.registration.navigationPreload.enable(); await self.registration.navigationPreload.enable();
}
await self.clients.claim(); await self.clients.claim();
})() })()
); );
}); });
self.UVServiceWorker = UVServiceWorker; self.UVServiceWorker = UVServiceWorker;
})(); })();