1
0
forked from sent/waves

UPDATEEEE

This commit is contained in:
𓍼 2025-06-07 16:54:12 -05:00
parent c2a6cb8639
commit 265de4f542
16 changed files with 1883 additions and 1410 deletions

View File

@ -140,7 +140,7 @@ if (cluster.isPrimary) {
app.get("/", sendHtml("$.html"));
app.get("/g", sendHtml("!.html"));
app.get("/a", sendHtml("!!.html"));
app.get("/s", sendHtml("!!.html"));
app.get("/resent", (_req, res) => res.sendFile(path.join(publicPath, "resent", "index.html")));
app.get("/api/info", (_req, res) => {

View File

@ -3,76 +3,80 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta property="og:title" content="Waves. - Apps"/>
<meta property="og:description" content="A sleek and minimalist web proxy."/>
<meta property="og:image" content="/assets/images/icons/favicon.ico"/>
<meta name="theme-color" content="#ffffff"/>
<meta name="msapplication-TileColor" content="#ffffff"/>
<meta property="og:title" content="Waves." />
<meta property="og:description" content="A sleek and minimalist web proxy." />
<meta property="og:image" content="/assets/images/icons/favicon.ico" />
<meta name="theme-color" content="#ffffff" />
<meta name="msapplication-TileColor" content="#ffffff" />
<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="stylesheet" href="/assets/css/settings.css">
<link rel="stylesheet" href="/assets/css/toast.css">
<link rel="stylesheet" href="/assets/css/a.css">
<link rel="stylesheet" href="/assets/css/nprogress.css">
<link href="https://cdn.jsdelivr.net/gh/aquawolf04/font-awesome-pro@5cd1511/css/all.css" 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>
<!-- Cool little title animation :D-->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="icon" type="image/x-icon" href="/assets/images/icons/favicon.ico" />
<link rel="stylesheet" href="/assets/css/$.css" />
<link rel="preload" href="/assets/css/settings.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<link rel="preload" href="/assets/css/toast.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<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>
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.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
window.addEventListener('load', function () {
NProgress.done();
});
});
gtag("js", new Date());
gtag("config", "G-WGJ2192JZY");
</script>
</head>
<body>
<script src="/baremux/index.js"></script>
<script src="/assets/js/nprogress.js?v=0.2.0"></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/cute1.js" 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/settings.js?v=2.8.7" defer></script>
<script src="/assets/js/greetings.js?v=2.8.5" defer></script>
<script src="/assets/js/shortcuts.js?v=2.8.4" defer></script>
<script src="/assets/js/$.js?v=2.8.4" defer></script>
<script src="/assets/js/a.js?v=2.8.4" defer></script>
<script src="/assets/js/register.js?v=2.8.9" defer></script>
<script src="/assets/js/settings.js?v=2.8.9" defer></script>
<script src="/assets/js/greetings.js?v=2.8.9" defer></script>
<script src="/assets/js/shortcuts.js?v=2.8.9" defer></script>
<script src="/assets/js/$.js?v=2.8.9" 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="absolute inset-0 overflow-hidden">
<div class="god-rays absolute -inset-[10px] opacity-50"></div>
</div>
</div>
<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>
<a href="/" id="home">Home</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="ai">AI</a>
<a href="#" id="settings-icon">
<i class="settings-icon fa-regular fa-gear"></i>
</a>
</div>
<div id="settings-menu" class="settings-menu"></div>
<div class="navbar">
<ul class="nav-buttons">
<li><a id="backIcon" href="#"><i class="fa-regular fa-arrow-left"></i></a></li>
@ -82,41 +86,70 @@
<li>
<div class="small-searchbar" style="position: relative;">
<i id="lockIcon" class="fa-solid fa-lock"></i>
<input class="waves" type="text" id="searchInputt"
placeholder="Search for a query or enter a URL..." autocomplete="off"
style="padding-left: 40px;">
<span class="shortcut-indicator-2">Ctrl + S</span>
<input class="waves" type="text" id="searchInputt" placeholder="Search for a query or enter a URL..." autocomplete="off" style="padding-left: 40px;" />
</div>
</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="/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>
</ul>
</div>
<div class="content apps-page">
<h1>Apps</h1>
<div class="apps-search-bar">
<input type="text" id="appSearchInput" placeholder="Search apps..." autocomplete="off" />
<div class="content shortcuts-page">
<h1>Shortcuts</h1>
<div class="shortcuts-search-bar">
<input type="text" id="shortcutSearchInput" placeholder="Search shortcuts..." autocomplete="off" />
<span class="shortcut-indicator-4">Ctrl + S</span>
</div>
<div class="apps-grid">
</div>
<div class="shortcuts-grid"></div>
</div>
<div id="erudaLoadingScreen" style="display: none;">Eruda is loading...</div>
<div id="overlay" class="overlay"></div>
<div id="namePrompt" class="popup">
<div class="input-container">
<label for="userName">Please enter a name so we know what to call you:</label>
<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>
<button id="doneButton" onclick="submitName()" disabled>
<i class="fas fa-check"></i> Done
</button>
<button id="doneButton" onclick="submitName()" disabled><i class="fa-regular fa-check"></i> Done</button>
</div>
</div>
<div id="erudaLoadingScreen" style="display: none;">Eruda is loading...</div>
<iframe id="cool-iframe" class="iframe"></iframe>
<script type='text/javascript' src='//pl26200346.effectiveratecpm.com/08/db/84/08db842da9b43ad3d13c14634f9fd1c8.js'></script>
<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>
</body>
</html>

View File

@ -3,76 +3,80 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta property="og:title" content="Waves. - Games"/>
<meta property="og:description" content="A sleek and minimalist web proxy."/>
<meta property="og:image" content="/assets/images/icons/favicon.ico"/>
<meta name="theme-color" content="#ffffff"/>
<meta name="msapplication-TileColor" content="#ffffff"/>
<meta property="og:title" content="Waves." />
<meta property="og:description" content="A sleek and minimalist web proxy." />
<meta property="og:image" content="/assets/images/icons/favicon.ico" />
<meta name="theme-color" content="#ffffff" />
<meta name="msapplication-TileColor" content="#ffffff" />
<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="stylesheet" href="/assets/css/settings.css">
<link rel="stylesheet" href="/assets/css/toast.css">
<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" />
<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>
<script type='text/javascript' src='//pl26200262.effectiveratecpm.com/f0/e8/15/f0e81559842363ebf19aa99900ff2d02.js'></script>
<!-- Cool little title animation :D-->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="icon" type="image/x-icon" href="/assets/images/icons/favicon.ico" />
<link rel="stylesheet" href="/assets/css/$.css" />
<link rel="preload" href="/assets/css/settings.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<link rel="preload" href="/assets/css/toast.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<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>
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.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
window.addEventListener('load', function () {
NProgress.done();
});
});
gtag("js", new Date());
gtag("config", "G-WGJ2192JZY");
</script>
</head>
<body>
<script src="/baremux/index.js"></script>
<script src="/assets/js/nprogress.js?v=0.2.0"></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/cute1.js" 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/settings.js?v=2.8.7" defer></script>
<script src="/assets/js/greetings.js?v=2.8.5" defer></script>
<script src="/assets/js/shortcuts.js?v=2.8.4" defer></script>
<script src="/assets/js/$.js?v=2.8.4" defer></script>
<script src="/assets/js/g.js?v=2.8.4" defer></script>
<script src="/assets/js/register.js?v=2.8.9" defer></script>
<script src="/assets/js/settings.js?v=2.8.9" defer></script>
<script src="/assets/js/greetings.js?v=2.8.9" defer></script>
<script src="/assets/js/shortcuts.js?v=2.8.9" defer></script>
<script src="/assets/js/$.js?v=2.8.9" 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="absolute inset-0 overflow-hidden">
<div class="god-rays absolute -inset-[10px] opacity-50"></div>
</div>
</div>
<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>
<a href="/" id="home">Home</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="ai">AI</a>
<a href="#" id="settings-icon">
<i class="settings-icon fa-regular fa-gear"></i>
</a>
</div>
<div id="settings-menu" class="settings-menu"></div>
<div class="navbar">
<ul class="nav-buttons">
<li><a id="backIcon" href="#"><i class="fa-regular fa-arrow-left"></i></a></li>
@ -82,41 +86,70 @@
<li>
<div class="small-searchbar" style="position: relative;">
<i id="lockIcon" class="fa-solid fa-lock"></i>
<input class="waves" type="text" id="searchInputt"
placeholder="Search for a query or enter a URL..." autocomplete="off"
style="padding-left: 40px;">
<span class="shortcut-indicator-2">Ctrl + S</span>
<input class="waves" type="text" id="searchInputt" placeholder="Search for a query or enter a URL..." autocomplete="off" style="padding-left: 40px;" />
</div>
</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="/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>
</ul>
</div>
<div class="content games-page">
<h1>Games</h1>
<div class="games-search-bar">
<input type="text" id="gameSearchInput" placeholder="Search games..." autocomplete="off" />
<span class="shortcut-indicator-3">Ctrl + S</span>
</div>
<div class="games-grid">
</div>
<div class="games-grid"></div>
</div>
<div id="erudaLoadingScreen" style="display: none;">Eruda is loading...</div>
<div id="overlay" class="overlay"></div>
<div id="namePrompt" class="popup">
<div class="input-container">
<label for="userName">Please enter a name so we know what to call you:</label>
<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>
<button id="doneButton" onclick="submitName()" disabled>
<i class="fas fa-check"></i> Done
</button>
<button id="doneButton" onclick="submitName()" disabled><i class="fa-regular fa-check"></i> Done</button>
</div>
</div>
<div id="erudaLoadingScreen" style="display: none;">Eruda is loading...</div>
<iframe id="cool-iframe" class="iframe"></iframe>
<script type='text/javascript' src='//pl26200346.effectiveratecpm.com/08/db/84/08db842da9b43ad3d13c14634f9fd1c8.js'></script>
<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>
</body>
</html>

View File

@ -1,78 +1,78 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta property="og:title" content="Waves."/>
<meta property="og:description" content="A sleek and minimalist web proxy."/>
<meta property="og:image" content="/assets/images/icons/favicon.ico"/>
<meta name="theme-color" content="#ffffff"/>
<meta name="msapplication-TileColor" content="#ffffff"/>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta property="og:title" content="Waves." />
<meta property="og:description" content="A sleek and minimalist web proxy." />
<meta property="og:image" content="/assets/images/icons/favicon.ico" />
<meta name="theme-color" content="#ffffff" />
<meta name="msapplication-TileColor" content="#ffffff" />
<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="stylesheet" href="/assets/css/settings.css">
<link rel="stylesheet" href="/assets/css/toast.css">
<link rel="stylesheet" href="/assets/css/nprogress.css">
<link href="https://cdn.jsdelivr.net/gh/aquawolf04/font-awesome-pro@5cd1511/css/all.css" 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>
<!-- Cool little title animation :D-->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="icon" type="image/x-icon" href="/assets/images/icons/favicon.ico" />
<link rel="stylesheet" href="/assets/css/$.css" />
<link rel="preload" href="/assets/css/settings.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<link rel="preload" href="/assets/css/toast.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<link rel="preload" href="/assets/css/nprogress.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" />
</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>
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.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
window.addEventListener('load', function () {
NProgress.done();
});
});
gtag("js", new Date());
gtag("config", "G-WGJ2192JZY");
</script>
</head>
<body>
<script src="/baremux/index.js"></script>
<script src="/assets/js/nprogress.js?v=0.2.0"></script>
<script src="/assets/js/nprogress.js?v=0.2.0" defer></script>
<script src="/wah/uv.bundle.js" defer></script>
<script src="/wah/cute1.js" defer></script>
<script src="/assets/js/eruda.js?v=2.8.4" defer></script>
<script src="/assets/js/register.js?v=2.8.4" defer></script>
<script src="/assets/js/settings.js?v=2.8.8" defer></script>
<script src="/assets/js/ping.js?v=2.8.4" defer></script>
<script src="/assets/js/greetings.js?v=2.8.4" defer></script>
<script src="/assets/js/shortcuts.js?v=2.8.4" defer></script>
<script src="/assets/js/$.js?v=2.8.4" defer></script>
<script src="/assets/js/register.js?v=2.8.9" defer></script>
<script src="/assets/js/settings.js?v=2.8.9" defer></script>
<script src="/assets/js/ping.js?v=2.8.9" defer></script>
<script src="/assets/js/greetings.js?v=2.8.9" defer></script>
<script src="/assets/js/shortcuts.js?v=2.8.9" defer></script>
<script src="/assets/js/$.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="absolute inset-0 overflow-hidden">
<div class="god-rays absolute -inset-[10px] opacity-50"></div>
</div>
</div>
<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>
<a href="/" id="home" style="color: #ffffff;">Home</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="ai">AI</a>
<a href="#" id="settings-icon">
<i class="settings-icon fa-regular fa-gear"></i>
</a>
<a href="#" id="settings-icon"><i class="settings-icon fa-regular fa-gear"></i></a>
</div>
<div class="glow-blob"></div>
<div id="settings-menu" class="settings-menu"></div>
<div class="navbar">
<ul class="nav-buttons">
<li><a id="backIcon" href="#"><i class="fa-regular fa-arrow-left"></i></a></li>
@ -82,56 +82,91 @@
<li>
<div class="small-searchbar" style="position: relative;">
<i id="lockIcon" class="fa-solid fa-lock"></i>
<input class="waves" type="text" id="searchInputt" placeholder="Search for a query or enter a URL..." autocomplete="off" style="padding-left: 40px;">
<input class="waves" type="text" id="searchInputt" placeholder="Search for a query or enter a URL..." autocomplete="off" style="padding-left: 40px;" />
<span class="shortcut-indicator-2">Ctrl + S</span>
</div>
</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="/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>
</ul>
</div>
<div class="search-container">
<div class="search-title">Waves.</div>
<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>
</div>
</div>
<div id="erudaLoadingScreen" style="display: none;">Eruda is loading...</div>
<div id="overlay" class="overlay"></div>
<div id="namePrompt" class="popup">
<div class="input-container">
<label for="userName">Please enter a name so we know what to call you:</label>
<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>
<button id="doneButton" onclick="submitName()" disabled>
<i class="fa-regular fa-check"></i> Done
</button>
<button id="doneButton" onclick="submitName()" disabled><i class="fa-regular fa-check"></i> Done</button>
</div>
</div>
<div id="pingDisplay"><i class="fa-regular fa-wifi"></i> Ping: Connecting...</div>
<div id="greeting"></div>
<iframe id="cool-iframe" class="iframe"></iframe>
<div id="lastest-commit">Loading latest commit</div>
<div id="copyright">
<i class="fa-regular fa-copyright"></i> 2025
<a class="hover-link" href="https://discord.gg/ire" target="_blank" rel="noopener noreferrer">
<span class="copyrightname">Waves Services</span>
</a>. All Rights Reserved.
<a class="hover-link" href="https://discord.gg/ire" target="_blank" rel="noopener noreferrer"><span class="copyrightname">Waves Services</span></a>.
All Rights Reserved.
</div>
<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 type="text/javascript" src="//pl26200346.effectiveratecpm.com/08/db/84/08db842da9b43ad3d13c14634f9fd1c8.js"></script>
<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>
</body>
</html>

View File

@ -63,7 +63,7 @@ body {
.home-navbar {
transform: translateX(-50%);
width: 670px;
width: 690px;
top: 1%;
margin-bottom: -10px;
margin-left: 50%;
@ -86,7 +86,7 @@ body {
}
.home-navbar .favicon {
width: 24px;
width: 28px;
height: 24px;
margin-right: -10px;
vertical-align: middle;
@ -105,7 +105,7 @@ body {
.home-navbar a:hover {
color: #bbbbbb;
font-size: 16px;
font-size: 18px;
}
.home-navbar a:active {
@ -223,6 +223,26 @@ body {
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 {
position: absolute;
top: 50%;
@ -236,12 +256,20 @@ body {
border-radius: 7px;
cursor: pointer;
transition: all 0.3s ease;
animation: fadeUp 0.3s ease;
}
.shortcut-indicator-2:hover {
background-color: #ffffff;
}
.arrow-mode {
display: inline-block;
margin-left: 17px;
transition: all 0.3s ease;
animation: fadeIn 0.3s ease;
}
#lockIcon {
position: absolute;
left: 25px;
@ -320,25 +348,6 @@ body {
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 {
position: fixed;
top: 50%;
@ -451,7 +460,7 @@ body {
display: none;
opacity: 0;
transition: opacity 0.3s ease-in-out;
animation: fadeInOverlay 0.3s ease-in-out forwards;
animation: fadeIn 0.3s ease-in-out forwards;
}
#namePrompt {
@ -578,7 +587,7 @@ body {
}
#namePrompt.fade-out {
animation: fadeOutPrompt 0.3s ease-in-out forwards;
animation: fadeOut 0.3s ease-in-out forwards;
}
#lastest-commit {
@ -650,6 +659,14 @@ body {
font-size: 14px;
}
.fadeIn {
animation: fadeIn 0.3s ease-in-out forwards;
}
.fadeOut {
animation: fadeOut 0.3s ease-in-out forwards;
}
@keyframes fadeSlideIn {
to {
opacity: 1;
@ -657,26 +674,6 @@ body {
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeInOverlay {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fadeInPrompt {
0% {
opacity: 0;
@ -689,7 +686,17 @@ body {
}
}
@keyframes fadeOutPrompt {
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeOut {
0% {
opacity: 1;
}
@ -709,47 +716,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 {
0% {
transform: rotate(0deg);

View File

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

View File

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

View File

@ -146,7 +146,7 @@ document.addEventListener('DOMContentLoaded', () => {
const randomSubject = subjects[Math.floor(Math.random() * subjects.length)];
try {
history.replaceState({}, '', `/learning?subject=${randomSubject}`);
} catch(e) {}
} catch (e) {}
}
function setupIframeNavigationListeners() {
@ -203,14 +203,14 @@ document.addEventListener('DOMContentLoaded', () => {
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 ) {
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];
const previousUrl = historyStack[currentIndex - 1];
currentIndex--;
iframe.src = previousUrl;
return;
@ -221,8 +221,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (navbarToggle && navbarToggle.checked && navBar) {
navBar.style.display = 'block';
}
} catch (error) {
} finally {
} catch (error) {} finally {
updateNavButtons();
updateDecodedSearchInput();
}
@ -358,14 +357,17 @@ document.addEventListener('DOMContentLoaded', () => {
finalUrlToLoad = searchURL;
} else if (searchURL.startsWith('/assets/g/')) {
finalUrlToLoad = new URL(searchURL, window.location.origin).href;
}
else {
} 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); }
} else {
finalUrlToLoad = await getUrl(searchURL);
}
} catch (e) {
finalUrlToLoad = await getUrl(searchURL);
}
}
if (searchInput2) searchInput2.value = decodeUrl(finalUrlToLoad);
@ -392,27 +394,47 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
if (movies) movies.addEventListener('click', e => { e.preventDefault(); APP.handleSearch('https://movies.usewaves.site/'); });
if (ai) ai.addEventListener('click', e => { e.preventDefault(); APP.handleSearch('https://ai.usewaves.site/'); });
if (movies) movies.addEventListener('click', e => {
e.preventDefault();
APP.handleSearch('https://movies.usewaves.site/');
});
if (ai) ai.addEventListener('click', e => {
e.preventDefault();
APP.handleSearch('https://ai.usewaves.site/');
});
function showToast(message, type = 'success', iconType = 'check') {
const toast = document.createElement('div');
toast.className = `toast show ${type}`;
const icons = { 'check': 'fa-regular fa-check-circle', 'times-circle': 'fa-regular fa-times-circle', 'info': 'fa-regular fa-info-circle', 'warning': 'fa-regular fa-exclamation-triangle', 'heart': 'fa-solid fa-heart' };
const icons = {
'check': 'fa-regular fa-check-circle',
'times-circle': 'fa-regular fa-times-circle',
'info': 'fa-regular fa-info-circle',
'warning': 'fa-regular fa-exclamation-triangle',
'heart': 'fa-solid fa-heart'
};
toast.innerHTML = `<i class="${icons[iconType] || icons.heart}" style="margin-right: 8px;"></i>${message}`;
const progressBar = document.createElement('div'); progressBar.className = 'progress-bar'; toast.appendChild(progressBar);
const closeBtn = document.createElement('button'); closeBtn.className = 'toast-close';
const progressBar = document.createElement('div');
progressBar.className = 'progress-bar';
toast.appendChild(progressBar);
const closeBtn = document.createElement('button');
closeBtn.className = 'toast-close';
closeBtn.innerHTML = '<i class="fa-solid fa-xmark" style="margin-left: 8px; font-size: 0.8em;"></i>';
closeBtn.onclick = () => { toast.classList.add('hide'); setTimeout(() => toast.remove(), 500); };
closeBtn.onclick = () => {
toast.classList.add('hide');
setTimeout(() => toast.remove(), 500);
};
toast.appendChild(closeBtn);
document.body.appendChild(toast);
setTimeout(() => { toast.classList.add('hide'); setTimeout(() => toast.remove(), 500); }, 3000);
setTimeout(() => {
toast.classList.add('hide');
setTimeout(() => toast.remove(), 500);
}, 3000);
}
if (navbarToggle && navBar && iframe) {
const savedNavbarState = localStorage.getItem('navbarToggled');
const defaultChecked = iframe.style.display !== 'block' ? true : (savedNavbarState === null ? false : savedNavbarState === 'true');
navbarToggle.checked = defaultChecked;
navbarToggle.checked = savedNavbarState !== 'false';
const updateNavbarDisplayBasedOnToggle = () => {
if (iframe.style.display === 'block') {
@ -446,7 +468,7 @@ document.addEventListener('DOMContentLoaded', () => {
iframe.style.display = 'block';
}
if(window.APP.updateNavbarDisplay) window.APP.updateNavbarDisplay();
if (window.APP.updateNavbarDisplay) window.APP.updateNavbarDisplay();
updateNavButtons();
updateDecodedSearchInput();
});
@ -456,44 +478,17 @@ document.addEventListener('DOMContentLoaded', () => {
});
(async () => {
const commitElement = document.getElementById('lastest-commit');
try {
const res = await fetch('/api/latest-commit');
console.log('Fetching latest commit from API:', res);
if (!res.ok) {
const remaining = res.headers.get('X-RateLimit-Remaining');
const reset = res.headers.get('X-RateLimit-Reset');
console.warn(`Status: ${res.status}`);
if (remaining !== null) {
console.warn(`Rate limit remaining: ${remaining}`);
if (Number(remaining) === 0) {
const resetDate = reset ? new Date(Number(reset) * 1000) : 'unknown';
throw new Error(`Rate limit exceeded. Try again at ${resetDate}`);
}
}
if (res.status === 403) {
throw new Error('403 Forbidden — possibly rate limited or blocked.');
}
throw new Error(`HTTP error! status: ${res.status}`);
}
const { updates } = await res.json();
const {
updates
} = await res.json();
const u = updates[0];
const commitUrl = `https://github.com/xojw/waves/commit/${u.sha}`;
commitElement.innerHTML = `
<a href="${commitUrl}" class="hover-link" target="_blank" rel="noopener noreferrer">
<i class="fa-solid fa-code-commit"></i> ${u.sha}
</a>`;
} catch (err) {
console.error('Failed to fetch latest commit:', err.message || err);
commitElement.textContent = 'Failed to load latest commit';
document.getElementById('lastest-commit').innerHTML =
`<a href="${commitUrl}" class="hover-link" target="_blank" rel="noopener noreferrer"><i class="fa-solid fa-code-commit"></i> ${u.sha}</a>`;
} catch {
document.getElementById('lastest-commit').textContent =
'Failed to load lastest commit';
}
})();

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

@ -38,8 +38,8 @@ function getWelcomeMessage(name) {
const path = window.location.pathname;
if (path === '/g') {
return `Have fun playing games, ${name}!`;
} else if (path === '/a') {
return `Enjoy our collection of apps, ${name}!`;
} else if (path === '/s') {
return `Enjoy our collection of, ${name}!`;
} else {
return `Welcome back, ${name}!`;
}
@ -47,7 +47,7 @@ function getWelcomeMessage(name) {
function getIconType(path) {
if (path === '/g') return 'game';
if (path === '/a') return 'apps';
if (path === '/s') return 'shortcuts';
return 'wave';
}
@ -65,7 +65,7 @@ timeGreetings.push(
{ 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: ' !' }
{ text: 'Your day starts here', icon: '<i class="fa-regular fa-star"></i>', suffix: '!' }
);
timeGreetings.push(

View File

@ -1,89 +1,80 @@
document.addEventListener('DOMContentLoaded', function() {
;(function(){
const origLog = console.log.bind(console);
document.addEventListener("DOMContentLoaded", () => {
origLog(
"%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%;"
);
});
const defaultWispUrl = `${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.host}/w/`;
let currentWispUrl = localStorage.getItem('customWispUrl') || defaultWispUrl;
const labelStyle = "background: white; color: black; font-weight: bold; padding: 2px 4px; border-radius: 2px";
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[method] = (...args) => {
const text = args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ');
orig(`%cWaves:%c ${text}`, labelStyle, messageStyle);
};
});
document.addEventListener("DOMContentLoaded", function(){
const defaultWispUrl = `${window.location.protocol==="https:"?"wss":"ws"}://${window.location.host}/w/`;
let currentWispUrl = localStorage.getItem("customWispUrl") || defaultWispUrl;
const wispUrl = currentWispUrl;
const connection = new BareMux.BareMuxConnection("/baremux/worker.js");
async function registerSW() {
registerSW();
async function registerSW(){
try {
if (!navigator.serviceWorker) {
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;
}
if (!navigator.serviceWorker) return console.error("Service Workers are not supported by this browser.");
await ensureWebSocketConnection(wispUrl);
console.log("%c[+]%c Registering Service Worker...", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
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;");
const savedTransport = localStorage.getItem('transport') || "epoxy";
console.log("Registering Service Worker...");
await navigator.serviceWorker.register("/wah/sw.js", { scope: "/wah/a/" });
console.log("Service Worker registered successfully.");
const savedTransport = localStorage.getItem("transport") || "epoxy";
switchTransport(savedTransport);
updateTransportUI(savedTransport);
console.log(`%c[#]%c Using ${capitalizeTransport(savedTransport)} transport.`, "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
} catch (error) {
logError(error, 'An error occurred during Service Worker registration or WebSocket connection');
console.log(`Using ${capitalizeTransport(savedTransport)} transport.`);
} catch (e) {
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) => {
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);
ws.onopen = () => {
console.log("%c[*]%c WebSocket connection established.", "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
resolve(ws);
};
ws.onerror = (error) => {
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;");
}
ws.onopen = () => { console.log("WebSocket connection established."); resolve(ws); };
ws.onerror = e => { console.error(`Failed to establish WebSocket connection: ${e.message||e}`); reject(e); };
ws.onclose = ev => {
if (ev.code !== 1000) console.warn(`WebSocket connection closed. Reason: ${ev.reason||"No reason provided"}`);
else console.warn("WebSocket connection closed normally.");
};
});
}
function logError(error, message) {
console.error(`%c[!]%c ${message}: ${error.message || error}`, "background-color: black; color: white; font-weight: bold;", "background-color: black; color: white;");
function switchTransport(t){
const m = { epoxy: "/epoxy/index.mjs", libcurl: "/libcurl/index.mjs" }[t];
if (m) connection.setTransport(m, [{ wisp: wispUrl }]);
}
function switchTransport(transport) {
const transportMap = {
"epoxy": "/epoxy/index.mjs",
"libcurl": "/libcurl/index.mjs"
};
const transportFile = transportMap[transport];
if (transportFile) {
connection.setTransport(transportFile, [{ wisp: wispUrl }]);
}
function updateTransportUI(t){
document.querySelector(".transport-selected").textContent = capitalizeTransport(t);
}
async function changeTransport(newTransport) {
try {
localStorage.setItem('transport', newTransport);
switchTransport(newTransport);
updateTransportUI(newTransport);
} catch (error) {
logError(error, 'An error occurred while storing transport preference');
}
function capitalizeTransport(t){
return t.charAt(0).toUpperCase() + t.slice(1).toLowerCase();
}
function updateTransportUI(transport) {
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) {
document.addEventListener("wispUrlChanged", function(e){
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

@ -1,4 +1,4 @@
document.addEventListener('DOMContentLoaded', function () {
document.addEventListener('DOMContentLoaded', function() {
const settingsMenu = document.getElementById('settings-menu');
settingsMenu.innerHTML = `
<h2>Settings</h2>
@ -105,6 +105,8 @@ document.addEventListener('DOMContentLoaded', function () {
wispInput.value = currentWispUrl;
let isToggling = false;
navbarToggle.checked = localStorage.getItem('navbarToggled') !== 'false';
function isValidUrl(url) {
try {
const p = new URL(url);
@ -144,6 +146,7 @@ document.addEventListener('DOMContentLoaded', function () {
`;
window.location.replace("https://bisd.schoology.com/home");
}
document.getElementById("aboutblank-toggle").addEventListener("change", function() {
localStorage.setItem("aboutBlankChecked", JSON.stringify(this.checked));
if (this.checked) {
@ -153,6 +156,7 @@ document.addEventListener('DOMContentLoaded', function () {
}
runScriptIfChecked();
});
window.addEventListener("load", function() {
const aboutBlankChecked = JSON.parse(localStorage.getItem("aboutBlankChecked")) || false;
document.getElementById("aboutblank-toggle").checked = aboutBlankChecked;
@ -163,16 +167,22 @@ document.addEventListener('DOMContentLoaded', function () {
if (isValidUrl(url)) {
currentWispUrl = url;
localStorage.setItem('customWispUrl', url);
document.dispatchEvent(new CustomEvent('wispUrlChanged', { detail: currentWispUrl }));
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 }));
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');
@ -222,7 +232,9 @@ document.addEventListener('DOMContentLoaded', function () {
if (infoContent.classList.contains('active')) {
updateServerInfo();
} else {
infoTab.addEventListener('click', startMonitoring, { once: true });
infoTab.addEventListener('click', startMonitoring, {
once: true
});
}
}
@ -289,14 +301,16 @@ document.addEventListener('DOMContentLoaded', function () {
});
Array.from(transportOptions.getElementsByTagName('div')).forEach(option => {
option.addEventListener('click', function (e) {
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() }));
document.dispatchEvent(new CustomEvent('newTransport', {
detail: val.toLowerCase()
}));
showToast('success', `Transport changed to ${val}`);
});
});
@ -315,7 +329,7 @@ document.addEventListener('DOMContentLoaded', function () {
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 () {
btn.addEventListener('click', function() {
const icon = this.querySelector('i');
if (!icon.classList.contains('fa-bounce')) {
icon.classList.add('fa-bounce');
@ -324,8 +338,12 @@ document.addEventListener('DOMContentLoaded', function () {
});
});
navbarToggle.addEventListener('change', function () {
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 () {
document.addEventListener('DOMContentLoaded', function () {
function getSearchInputs() {
(function(){
document.addEventListener('DOMContentLoaded', function(){
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 [
document.getElementById('searchInput'),
document.getElementById('searchInputt'),
document.getElementById('gameSearchInput'),
document.getElementById('appSearchInput')
document.getElementById('shortcutSearchInput')
].filter(Boolean);
}
function isVisible(el) {
function isVisible(el){
return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
}
function focusFirstVisibleInput() {
function focusFirstVisibleInput(){
const inputs = getSearchInputs();
for (const input of inputs) {
if (isVisible(input)) {
input.focus();
return;
for (let inp of inputs) {
if (isVisible(inp)) {
inp.focus();
return inp;
}
}
if (inputs.length) {
if (inputs[0]) {
inputs[0].focus();
return inputs[0];
}
return null;
}
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') {
const inputs = getSearchInputs();
const active = document.activeElement;
if (inputs.includes(active)) {
active.blur();
e.preventDefault();
let arrowMode = false;
function updateIndicatorState(){
const hasText = getSearchInputs().some(i => i.value.trim() !== '');
if (hasText === arrowMode) return;
arrowMode = hasText;
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;
}
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') {
e.preventDefault();
focusFirstVisibleInput();
}
});
document.querySelectorAll(
'.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4'
).forEach(function (el) {
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')
) {
document.body.addEventListener('click', e => {
const ind = e.target.closest('.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4');
if (!ind) return;
e.preventDefault();
if (ind.classList.contains('arrow-mode')) {
handleIndicatorAction();
} else {
focusFirstVisibleInput();
}
});
const coolIframe = document.getElementById('cool-iframe');
if (coolIframe) {
coolIframe.addEventListener('load', function () {
if (coolIframe){
coolIframe.addEventListener('load', () => {
const doc = coolIframe.contentWindow.document;
doc.addEventListener('keydown', function (e) {
if (e.key === 'Escape') {
if (doc.activeElement && doc.activeElement.blur) {
doc.activeElement.blur();
e.preventDefault();
return;
doc.addEventListener('keydown', innerE => {
if (innerE.key === 'Escape') {
if (doc.activeElement.blur) doc.activeElement.blur();
innerE.preventDefault();
}
}
if (e.ctrlKey && e.key.toLowerCase() === 's') {
e.preventDefault();
document.dispatchEvent(new KeyboardEvent('keydown', {
key: 's',
ctrlKey: true
}));
if (innerE.ctrlKey && innerE.key.toLowerCase() === 's') {
innerE.preventDefault();
document.dispatchEvent(new KeyboardEvent('keydown', { key: 's', ctrlKey: true, bubbles: true }));
}
});
doc.querySelectorAll(
'.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4'
).forEach(function (iframeEl) {
iframeEl.addEventListener('click', function (e) {
e.preventDefault();
window.parent.postMessage({
type: 'iframe-focus-search'
}, '*');
doc.querySelectorAll('.shortcut-indicator, .shortcut-indicator-2, .shortcut-indicator-3, .shortcut-indicator-4')
.forEach(el => {
el.addEventListener('click', ev => {
ev.preventDefault();
window.parent.postMessage({ type: 'iframe-focus-search' }, '*');
});
});
});
}
window.addEventListener('message', function (event) {
const msg = event.data;
if (msg.type === 'iframe-focus-search') {
focusFirstVisibleInput();
window.addEventListener('message', msgEvt => {
if (msgEvt.data?.type === 'iframe-focus-search'){
const inp = focusFirstVisibleInput();
if (inp && inp.value.trim()) triggerSubmit(inp);
}
});
});
})();

View File

@ -1,6 +1,8 @@
"use strict";
(() => {
const Ultraviolet = self.Ultraviolet;
const REMOVE_HEADERS = [
"cross-origin-embedder-policy",
"cross-origin-opener-policy",
@ -19,7 +21,162 @@
"x-powered-by",
"x-xss-protection"
];
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 {
constructor(config = __uv$config) {
super();
@ -30,9 +187,11 @@
this.syncInterval = 300000;
this.lastSync = Date.now();
}
route({ request }) {
return request.url.startsWith(location.origin + this.config.prefix);
}
async fetch({ request }) {
if (request.method.toUpperCase() === "OPTIONS") {
return new Response(null, {
@ -44,41 +203,64 @@
}
});
}
let requestUrl = "";
try {
if (!request.url.startsWith(location.origin + this.config.prefix))
if (!request.url.startsWith(location.origin + this.config.prefix)) {
return await fetch(request);
}
const uv = new Ultraviolet(this.config);
if (typeof this.config.construct === "function")
if (typeof this.config.construct === "function") {
uv.construct(uv, "service");
}
const blobPromise = NO_BODY_METHODS.includes(request.method.toUpperCase())
? Promise.resolve(null)
: request.blob();
const cookieDBPromise = uv.cookie.db();
const [body, cookieDB] = await Promise.all([blobPromise, cookieDBPromise]);
uv.meta.origin = location.origin;
uv.meta.base = uv.meta.url = new URL(uv.sourceUrl(request.url));
const reqWrapper = new UVRequestWrapper(request, uv, body);
if (uv.meta.url.protocol === "blob:") {
reqWrapper.blob = true;
reqWrapper.base = reqWrapper.url = new URL(reqWrapper.url.pathname);
}
if (request.referrer && request.referrer.startsWith(location.origin)) {
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;
}
delete reqWrapper.headers.referer;
}
const cookies = (await uv.cookie.getCookies(cookieDB)) || [];
const cookieString = uv.cookie.serialize(cookies, uv.meta, false);
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);
this.emit("request", reqEvent);
if (reqEvent.intercepted) return reqEvent.returnValue;
if (reqEvent.intercepted) {
return reqEvent.returnValue;
}
requestUrl = reqWrapper.blob
? "blob:" + location.origin + reqWrapper.url.pathname
: reqWrapper.url;
const options = {
headers: reqWrapper.headers,
method: reqWrapper.method,
@ -88,14 +270,17 @@
cache: reqWrapper.cache,
redirect: reqWrapper.redirect
};
if (request.method.toUpperCase() === "GET") {
const cache = await caches.open("uv-cache");
const cachedResponse = await cache.match(requestUrl);
if (cachedResponse) {
await this.recordAnalytics("cacheHit", requestUrl);
return cachedResponse.clone();
}
}
let responseRaw;
for (let i = 0; i < 2; i++) {
try {
@ -105,34 +290,62 @@
if (i === 1) throw e;
}
}
const respWrapper = new UVResponseWrapper(reqWrapper, responseRaw);
const respEvent = new InterceptionEvent(respWrapper, null, null);
this.emit("beforemod", respEvent);
if (respEvent.intercepted) return respEvent.returnValue;
if (respEvent.intercepted) {
return respEvent.returnValue;
}
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);
}
if (["document", "iframe"].includes(request.destination)) {
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)) {
const headIdx = text.search(/<head>/i);
const bodyIdx = text.search(/<body>/i);
const currentUrl = new URL(requestUrl);
for (const rule of this.config.inject) {
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);
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.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);
if (progress)
text = text.replace(/<\/body>/i, `<script>window.userProgress=${JSON.stringify(progress)}</script></body>`);
if (progress) {
text = text.replace(
/<\/body>/i,
`<script>window.userProgress=${JSON.stringify(progress)}</script></body>`
);
}
respWrapper.body = uv.rewriteHtml(text, {
document: true,
injectHead: uv.createHtmlInject(
@ -145,79 +358,122 @@
)
});
}
if (respWrapper.headers["set-cookie"]) {
Promise.resolve(uv.cookie.setCookies(respWrapper.headers["set-cookie"], cookieDB, uv.meta))
.then(() => {
self.clients.matchAll().then(clients =>
clients.forEach(client =>
client.postMessage({ msg: "updateCookies", url: uv.meta.url.href })
)
);
Promise.resolve(
uv.cookie.setCookies(respWrapper.headers["set-cookie"], cookieDB, uv.meta)
).then(() => {
self.clients.matchAll().then(clients => {
clients.forEach(client => {
client.postMessage({
msg: "updateCookies",
url: uv.meta.url.href
});
});
});
});
delete respWrapper.headers["set-cookie"];
}
if (respWrapper.body) {
switch (request.destination) {
case "script":
respWrapper.body = uv.js.rewrite(await responseRaw.text());
break;
case "worker": {
const scriptsList = [uv.bundleScript, uv.clientScript, uv.configScript, uv.handlerScript]
.map(s => JSON.stringify(s))
.join(",");
const scriptsList = [
uv.bundleScript,
uv.clientScript,
uv.configScript,
uv.handlerScript
].map(s => JSON.stringify(s)).join(",");
respWrapper.body =
`if(!self.__uv){${uv.createJsInject(uv.cookie.serialize(cookies, uv.meta, true), request.referrer)}importScripts(${scriptsList});}` +
uv.js.rewrite(await responseRaw.text());
break;
}
case "style":
respWrapper.body = uv.rewriteCSS(await responseRaw.text());
break;
}
}
respWrapper.headers["Access-Control-Allow-Origin"] = "*";
respWrapper.headers["Access-Control-Allow-Methods"] = "GET, HEAD, POST, OPTIONS";
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";
if (crossOriginIsolated)
}
if (crossOriginIsolated) {
respWrapper.headers["Cross-Origin-Embedder-Policy"] = "require-corp";
}
this.emit("response", respEvent);
if (respEvent.intercepted) return respEvent.returnValue;
if (respEvent.intercepted) {
return respEvent.returnValue;
}
const finalResponse = new Response(respWrapper.body, {
headers: respWrapper.headers,
status: respWrapper.status,
statusText: respWrapper.statusText
});
if (request.method.toUpperCase() === "GET") {
const cache = await caches.open("uv-cache");
cache.put(requestUrl, finalResponse.clone());
}
await this.recordAnalytics("fetchSuccess", requestUrl);
this.periodicSync();
return finalResponse;
} catch (error) {
const errHeaders = { "content-type": "text/html", "Access-Control-Allow-Origin": "*" };
if (crossOriginIsolated)
}
catch (error) {
const errHeaders = {
"content-type": "text/html",
"Access-Control-Allow-Origin": "*"
};
if (crossOriginIsolated) {
errHeaders["Cross-Origin-Embedder-Policy"] = "require-corp";
}
await this.recordAnalytics("fetchError", request.url);
if (["document", "iframe"].includes(request.destination))
if (["document", "iframe"].includes(request.destination)) {
return T(error, requestUrl);
return new Response(undefined, { status: 500, headers: errHeaders });
}
return new Response(undefined, {
status: 500,
headers: errHeaders
});
}
}
async recordAnalytics(type, url) {
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 });
if (now - this.lastSync > this.syncInterval) {
try {
await sendAnalytics(this.analyticsData);
this.analyticsData = {};
this.lastSync = now;
} catch (e) {}
}
catch (e) {}
}
}
periodicSync() {
if (Date.now() - this.lastSync > this.syncInterval) {
sendAnalytics(this.analyticsData)
@ -228,36 +484,47 @@
.catch(() => {});
}
}
static get Ultraviolet() {
return Ultraviolet;
}
}
class UVResponseWrapper {
constructor(reqWrapper, rawResponse) {
this.request = reqWrapper;
this.raw = rawResponse;
this.ultraviolet = reqWrapper.ultraviolet;
this.headers = {};
for (const k in rawResponse.rawHeaders) {
this.headers[k.toLowerCase()] = rawResponse.rawHeaders[k];
}
this.status = rawResponse.status;
this.statusText = rawResponse.statusText;
this.body = rawResponse.body;
}
get url() {
return this.request.url;
}
get base() {
return this.request.base;
}
set base(v) {
this.request.base = v;
}
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 {
constructor(request, uv, body = null) {
this.ultraviolet = uv;
@ -271,54 +538,68 @@
this.mode = request.mode === "cors" ? request.mode : "same-origin";
this.blob = false;
}
get url() {
return this.ultraviolet.meta.url;
}
set url(v) {
this.ultraviolet.meta.url = v;
}
get base() {
return this.ultraviolet.meta.base;
}
set base(v) {
this.ultraviolet.meta.base = v;
}
}
class InterceptionEvent {
#intercepted = false;
#returnValue = null;
constructor(data = {}, target = null, that = null) {
this.data = data;
this.target = target;
this.that = that;
}
get intercepted() {
return this.#intercepted;
}
get returnValue() {
return this.#returnValue;
}
respondWith(v) {
this.#returnValue = v;
this.#intercepted = true;
}
}
async function getProgress(host) {
const cache = await caches.open("progress-cache");
const response = await cache.match("progress-" + host);
if (response) {
try {
return await response.json();
} catch (e) {
}
catch (e) {
return null;
}
}
return null;
}
async function saveProgress(host, data) {
const cache = await caches.open("progress-cache");
await cache.put("progress-" + host, new Response(JSON.stringify(data)));
}
async function sendAnalytics(data) {
try {
await fetch(location.origin + "/wah/a/analytics", {
@ -326,42 +607,154 @@
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
});
} catch (e) {}
}
catch (e) {}
}
self.addEventListener("message", e => {
if (e.data && e.data.type === "saveProgress" && e.data.host && e.data.data) {
saveProgress(e.data.host, e.data.data);
}
if (e.data && e.data.type === "syncAnalytics") {
sendAnalytics(e.data.analytics || {});
}
if (e.data && e.data.type === "clearProgress" && e.data.host) {
caches.open("progress-cache").then(cache => {
cache.delete("progress-" + e.data.host);
});
}
});
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")};`;
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>`;
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")};
`;
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) {
const h = { "content-type": "text/html", "Access-Control-Allow-Origin": "*" };
if (crossOriginIsolated)
const h = {
"content-type": "text/html",
"Access-Control-Allow-Origin": "*"
};
if (crossOriginIsolated) {
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.skipWaiting();
});
self.addEventListener("activate", e => {
e.waitUntil(
(async () => {
if (self.registration.navigationPreload)
if (self.registration.navigationPreload) {
await self.registration.navigationPreload.enable();
}
await self.clients.claim();
})()
);
});
self.UVServiceWorker = UVServiceWorker;
})();