stuff
This commit is contained in:
parent
396b81929a
commit
20d49560e9
117
index.mjs
117
index.mjs
|
@ -17,7 +17,6 @@ import wisp from "wisp-server-node";
|
||||||
|
|
||||||
const surgeConfigPath = path.resolve("surge.config.json");
|
const surgeConfigPath = path.resolve("surge.config.json");
|
||||||
const isSurgedRun = process.argv.includes("--surged");
|
const isSurgedRun = process.argv.includes("--surged");
|
||||||
let startTime = Date.now();
|
|
||||||
|
|
||||||
function applySurgeAndRestartIfNeeded() {
|
function applySurgeAndRestartIfNeeded() {
|
||||||
if (isSurgedRun) {
|
if (isSurgedRun) {
|
||||||
|
@ -48,20 +47,13 @@ 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) global.gc();
|
if (heapTotal > 0 && heapUsed / heapTotal > 0.8) global.gc();
|
||||||
}, 60000);
|
}, 120000);
|
||||||
}
|
}
|
||||||
|
|
||||||
import "./others/scaler.mjs";
|
import "./others/scaler.mjs";
|
||||||
import "./others/warmup.mjs";
|
import "./others/warmup.mjs";
|
||||||
|
|
||||||
const cache = new LRUCache({
|
|
||||||
maxSize: 1000,
|
|
||||||
ttl: 60_000,
|
|
||||||
allowStale: false,
|
|
||||||
sizeCalculation: (value, key) => Buffer.byteLength(value) + Buffer.byteLength(key)
|
|
||||||
});
|
|
||||||
|
|
||||||
const port = parseInt(process.env.PORT || "3000", 10);
|
const port = parseInt(process.env.PORT || "3000", 10);
|
||||||
|
|
||||||
function logInfo(msg) {
|
function logInfo(msg) {
|
||||||
|
@ -80,9 +72,7 @@ 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} workers`);
|
||||||
|
|
||||||
for (let i = 0; i < workers; i++) {
|
for (let i = 0; i < workers; i++) {
|
||||||
|
@ -108,18 +98,26 @@ if (cluster.isPrimary) {
|
||||||
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();
|
||||||
let latencySamples = [];
|
|
||||||
|
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");
|
||||||
|
@ -128,13 +126,12 @@ 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));
|
||||||
|
|
||||||
|
@ -144,75 +141,40 @@ if (cluster.isPrimary) {
|
||||||
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.get("/api/info", (_req, res) => {
|
app.get("/api/info", (_req, res) => {
|
||||||
try {
|
const validSamples = latencySamples.filter(s => s !== undefined);
|
||||||
const average = latencySamples.length
|
const average = validSamples.length ? validSamples.reduce((a, b) => a + b, 0) / validSamples.length : 0;
|
||||||
? latencySamples.reduce((a, b) => a + b, 0) / latencySamples.length
|
|
||||||
: 0;
|
|
||||||
let speed = "Medium";
|
|
||||||
if (average < 200) speed = "Fast";
|
|
||||||
else if (average > 500) speed = "Slow";
|
|
||||||
const cpus = os.cpus();
|
|
||||||
const totalMem = os.totalmem() / 1024 / 1024 / 1024;
|
|
||||||
res.json({
|
res.json({
|
||||||
speed,
|
speed: average < 200 ? "Fast" : average > 500 ? "Slow" : "Medium",
|
||||||
averageLatency: average.toFixed(2),
|
averageLatency: average.toFixed(2),
|
||||||
specs: `${cpus[0].model} + ${cpus.length} CPU Cores + ${totalMem.toFixed(1)}GB of RAM`,
|
|
||||||
startTime,
|
|
||||||
samples: latencySamples.length,
|
|
||||||
timestamp: Date.now()
|
timestamp: Date.now()
|
||||||
});
|
});
|
||||||
} catch {
|
|
||||||
res.status(500).json({ error: "Internal error" });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get("/api/latest-commit", async (_req, res) => {
|
|
||||||
try {
|
|
||||||
const ghRes = await fetch(
|
|
||||||
"https://api.github.com/repos/xojw/waves/commits?per_page=1",
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"User-Agent": "waves-app",
|
|
||||||
Accept: "application/vnd.github.v3+json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!ghRes.ok) return res.status(ghRes.status).json({ error: "GitHub API error" });
|
|
||||||
|
|
||||||
const commits = await ghRes.json();
|
|
||||||
const updates = commits.map(c => ({
|
|
||||||
sha: c.sha.slice(0, 7),
|
|
||||||
message: c.commit.message.split("\n")[0],
|
|
||||||
author: c.commit.author.name,
|
|
||||||
date: c.commit.author.date
|
|
||||||
}));
|
|
||||||
|
|
||||||
res.json({ repo: "xojw/waves", updates });
|
|
||||||
} catch {
|
|
||||||
res.status(500).json({ error: "Internal server error" });
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use((_req, res) => res.status(404).sendFile(path.join(publicPath, "404.html")));
|
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({
|
const pingWSS = new WebSocket.Server({
|
||||||
noServer: true,
|
noServer: true,
|
||||||
maxPayload: 4 * 1024 * 1024,
|
maxPayload: 16384,
|
||||||
perMessageDeflate: false
|
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;
|
||||||
|
|
||||||
|
const sendPing = () => {
|
||||||
if (ws.readyState === WebSocket.OPEN) {
|
if (ws.readyState === WebSocket.OPEN) {
|
||||||
ws.send(JSON.stringify({ type: "ping", timestamp: Date.now() }));
|
ws.send(JSON.stringify({ type: "ping", timestamp: Date.now() }));
|
||||||
}
|
}
|
||||||
}, 1000);
|
};
|
||||||
|
|
||||||
|
const pingInterval = setInterval(sendPing, 500);
|
||||||
|
sendPing();
|
||||||
|
|
||||||
ws.on("message", msg => {
|
ws.on("message", msg => {
|
||||||
try {
|
try {
|
||||||
|
@ -220,21 +182,19 @@ if (cluster.isPrimary) {
|
||||||
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();
|
||||||
latencySamples.push(d);
|
|
||||||
if (latencySamples.length > 100) latencySamples.shift();
|
latencySamples[sampleIndex % latencySamples.length] = d;
|
||||||
ws.send(JSON.stringify({ type: "latency", latency: d }));
|
sampleIndex = (sampleIndex + 1) % latencySamples.length;
|
||||||
}
|
|
||||||
} catch (e) {
|
ws.send(JSON.stringify({ type: "latency", latency: d }), { compress: false });
|
||||||
logError(`Ping error: ${e}`);
|
|
||||||
}
|
}
|
||||||
|
} catch {}
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.on("close", () => {
|
ws.on("close", () => {
|
||||||
clearInterval(interval);
|
clearInterval(pingInterval);
|
||||||
const avg = lat.length
|
const avg = lat.length ? (lat.reduce((a, b) => a + b) / lat.length).toFixed(2) : 0;
|
||||||
? (lat.reduce((a, b) => a + b) / lat.length).toFixed(2)
|
|
||||||
: 0;
|
|
||||||
logInfo(`WS ${remote} closed. Avg: ${avg}ms`);
|
logInfo(`WS ${remote} closed. Avg: ${avg}ms`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -247,12 +207,11 @@ if (cluster.isPrimary) {
|
||||||
} else if (req.url.startsWith("/w/")) {
|
} 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 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) => {
|
||||||
|
|
|
@ -114,10 +114,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="pingDisplay"><i class="fa-regular fa-wifi"></i> 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>
|
||||||
<div id="lastest-commit">Loading latest commit</div>
|
<div id="hi">Hii,</div>
|
||||||
|
|
||||||
<div id="copyright">
|
<div id="copyright">
|
||||||
<i class="fa-regular fa-copyright"></i> 2025
|
<i class="fa-regular fa-copyright"></i> 2025
|
||||||
|
|
|
@ -55,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;
|
||||||
|
@ -88,7 +88,7 @@ body {
|
||||||
.home-navbar .favicon {
|
.home-navbar .favicon {
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
margin-right: -10px;
|
margin-right: -9px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,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 {
|
||||||
|
@ -590,14 +590,14 @@ body {
|
||||||
animation: fadeOut 0.3s ease-in-out forwards;
|
animation: fadeOut 0.3s ease-in-out forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
#lastest-commit {
|
#hi {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
background-color: #08080894;
|
background-color: #08080894;
|
||||||
border: 1px solid #ffffff21;
|
border: 1px solid #ffffff21;
|
||||||
color: #cfcfcf;
|
color: #aaaaaa;
|
||||||
font-weight: 540;
|
font-weight: 540;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
@ -606,6 +606,10 @@ body {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#hi:hover {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
#copyright {
|
#copyright {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
|
|
|
@ -141,6 +141,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
updateDecodedSearchInput();
|
updateDecodedSearchInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateSubject() {
|
||||||
|
const subjects = ['math', 'science', 'history', 'art', 'programming', 'philosophy'];
|
||||||
|
const randomSubject = subjects[Math.floor(Math.random() * subjects.length)];
|
||||||
|
try {
|
||||||
|
history.replaceState({}, '', `/learning?subject=${randomSubject}`);
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
function setupIframeNavigationListeners() {
|
function setupIframeNavigationListeners() {
|
||||||
try {
|
try {
|
||||||
const iframeWindow = iframe.contentWindow;
|
const iframeWindow = iframe.contentWindow;
|
||||||
|
@ -209,6 +217,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setupIframeNavigationListeners();
|
setupIframeNavigationListeners();
|
||||||
|
generateSubject();
|
||||||
if (navbarToggle && navbarToggle.checked && navBar) {
|
if (navbarToggle && navbarToggle.checked && navBar) {
|
||||||
navBar.style.display = 'block';
|
navBar.style.display = 'block';
|
||||||
}
|
}
|
||||||
|
@ -467,19 +476,3 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
window.APP.decodeUrl = decodeUrl;
|
window.APP.decodeUrl = decodeUrl;
|
||||||
window.APP.normalizeUrl = normalizeUrl;
|
window.APP.normalizeUrl = normalizeUrl;
|
||||||
});
|
});
|
||||||
|
|
||||||
(async () => {
|
|
||||||
try {
|
|
||||||
const res = await fetch('/api/latest-commit');
|
|
||||||
const {
|
|
||||||
updates
|
|
||||||
} = await res.json();
|
|
||||||
const u = updates[0];
|
|
||||||
const commitUrl = `https://github.com/xojw/waves/commit/${u.sha}`;
|
|
||||||
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';
|
|
||||||
}
|
|
||||||
})();
|
|
|
@ -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,20 +13,27 @@ 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');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -52,8 +60,7 @@ function getIconType(path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const generalGreetings = [
|
const generalGreetings = [
|
||||||
{ text: 'Welcome aboard', icon: '<i class="fa-regular fa-rocket"></i>', suffix: '!' },
|
{ text: 'Have fun', icon: '<i class="fa-regular fa-party-horn"></i>', suffix: '!' },
|
||||||
{ text: 'Hii', icon: '<i class="fa-regular fa-hand-wave"></i>', suffix: '!!' },
|
|
||||||
{ text: 'Hope you enjoy Waves', icon: '<i class="fa-solid fa-heart"></i>', suffix: ' <3' },
|
{ 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: '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: '?' }
|
{ text: 'How you doing today', icon: '<i class="fa-regular fa-question"></i>', suffix: '?' }
|
||||||
|
@ -67,21 +74,18 @@ timeGreetings.push(
|
||||||
{ text: 'Enjoy your morning', icon: '<i class="fa-regular fa-mug-hot"></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(
|
timeGreetings.push(
|
||||||
{ text: 'Good afternoon', icon: '<i class="fa-regular fa-leaf"></i>', suffix: '!' },
|
{ 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: '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: '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: '.' }
|
{ text: 'Stay on track today', icon: '<i class="fa-regular fa-sun"></i>', suffix: '.' }
|
||||||
);
|
);
|
||||||
|
|
||||||
timeGreetings.push(
|
timeGreetings.push(
|
||||||
{ text: 'Good evening', icon: '<i class="fa-regular fa-cloud-moon"></i>', suffix: '!' },
|
{ 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: 'Time to unwind', icon: '<i class="fa-regular fa-fire"></i>', suffix: '.' },
|
||||||
{ text: 'Evening’s here—relax', icon: '<i class="fa-regular fa-star"></i>', suffix: '.' },
|
{ text: 'Evening’s here—relax', icon: '<i class="fa-regular fa-star"></i>', suffix: '.' },
|
||||||
{ text: 'Breathe and recharge', icon: '<i class="fa-regular fa-moon"></i>', suffix: '…' }
|
{ text: 'Breathe and recharge', icon: '<i class="fa-regular fa-moon"></i>', suffix: '…' }
|
||||||
);
|
);
|
||||||
|
|
||||||
timeGreetings.push(
|
timeGreetings.push(
|
||||||
{ text: 'Good night', icon: '<i class="fa-regular fa-bed"></i>', suffix: '!' },
|
{ 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: 'Rest well', icon: '<i class="fa-regular fa-blanket"></i>', suffix: '.' },
|
||||||
|
@ -93,6 +97,7 @@ function getGreeting() {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const hour = now.getHours();
|
const hour = now.getHours();
|
||||||
let pool = [];
|
let pool = [];
|
||||||
|
|
||||||
if (hour >= 5 && hour < 12) {
|
if (hour >= 5 && hour < 12) {
|
||||||
pool = timeGreetings.slice(0, 4);
|
pool = timeGreetings.slice(0, 4);
|
||||||
} else if (hour < 17) {
|
} else if (hour < 17) {
|
||||||
|
@ -102,28 +107,34 @@ function getGreeting() {
|
||||||
} else {
|
} else {
|
||||||
pool = timeGreetings.slice(12, 16);
|
pool = timeGreetings.slice(12, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.random() < 0.5) {
|
if (Math.random() < 0.5) {
|
||||||
pool = generalGreetings;
|
pool = generalGreetings;
|
||||||
}
|
}
|
||||||
const choice = pool[Math.floor(Math.random() * pool.length)];
|
|
||||||
return { text: choice.text, icon: choice.icon, suffix: choice.suffix };
|
return pool[Math.floor(Math.random() * pool.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateGreeting(name) {
|
function updateGreeting(name) {
|
||||||
const { text, icon, suffix } = getGreeting();
|
const { text, icon, suffix } = getGreeting();
|
||||||
const el = document.getElementById('greeting');
|
const el = document.getElementById('greeting');
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
if (text === 'Hope you enjoy Waves') {
|
|
||||||
el.innerHTML = `${icon} ${text}, ${name}${suffix}`;
|
el.innerHTML = `${icon} ${text}, ${name}${suffix}`;
|
||||||
} else {
|
|
||||||
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}!!`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function showToast(message, type = 'success', iconType = 'wave') {
|
function showToast(message, type = 'success', iconType = 'wave') {
|
||||||
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="fas fa-check-circle" style="margin-right: 8px;"></i>',
|
success: '<i class="fas fa-check-circle" style="margin-right: 8px;"></i>',
|
||||||
error: '<i class="fas fa-times-circle" style="margin-right: 8px;"></i>',
|
error: '<i class="fas fa-times-circle" style="margin-right: 8px;"></i>',
|
||||||
|
@ -133,10 +144,13 @@ function showToast(message, type = 'success', iconType = 'wave') {
|
||||||
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}`;
|
||||||
|
|
||||||
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="fas fa-xmark" style="margin-left: 8px; font-size: 0.8em;"></i>';
|
closeBtn.innerHTML = '<i class="fas fa-xmark" style="margin-left: 8px; font-size: 0.8em;"></i>';
|
||||||
|
@ -145,7 +159,9 @@ function showToast(message, type = 'success', iconType = 'wave') {
|
||||||
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);
|
||||||
|
|
|
@ -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-solid 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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user