Merge pull request #14 from Skoolgq/1.2

2024 Update
This commit is contained in:
Russell
2023-12-31 22:38:32 -07:00
committed by GitHub
78 changed files with 5752 additions and 1687 deletions
+1
View File
@@ -1,2 +1,3 @@
**/node_modules
**.DS_Store
.gitpod.yml
-71
View File
@@ -1,71 +0,0 @@
import { createBareServer } from '@tomphttp/bare-server-node';
import express from 'express';
import mime from 'mime';
import cors from 'cors';
import url from 'node:url';
import fs from 'node:fs';
import path from 'node:path';
import http from 'node:http';
const app = express();
const server = http.createServer();
const bareServer = createBareServer('/bare/');
const port = process.env.PORT || process.argv[2] || 8080;
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
let navbar = fs.readFileSync(path.join(__dirname, './templates/navbar.html'), 'utf-8');
let meta = fs.readFileSync(path.join(__dirname, './templates/meta.html'), 'utf-8');
fs.readdirSync('./pages').forEach(file => {
let fileData = fs.readFileSync(path.join(__dirname, './pages/', file), 'utf-8');
fileData = fileData.replace('<body>', '<body> ' + navbar).replace('</head>', meta + '</head>');
app.get(`/${file.split('.')[0] === 'index' ? '' : file.split('.')[0]}`, (req, res) => res.status(200).send(fileData));
});
app.use(express.static(path.join(__dirname, '/static')));
app.get('/cdn/*', cors({
origin: false
}), async (req, res, next) => {
let reqTarget = `https://raw.githubusercontent.com/Skoolgq/Polaris-Assets/main/${req.path.replace('/cdn/', '')}`;
const asset = await fetch(reqTarget);
if (asset.status == 200) {
var data = Buffer.from(await asset.arrayBuffer());
const noRewrite = ['.unityweb'];
if (!noRewrite.includes(mime.getExtension(reqTarget))) res.writeHead(200, {
'content-type': mime.getType(reqTarget)
});
if (mime.getType(reqTarget) === 'text/html') data = data + '<script src=\'/assets/js/cdn_inject.js\' preload=\'true\'></script>';
res.end(data);
} else next();
});
let notFoundFile = fs.readFileSync(path.join(__dirname, './pages/404.html'), 'utf-8');
notFoundFile = notFoundFile.replace('<body>', '<body> ' + navbar).replace('</head>', meta + '</head>');
app.use((req, res, next) => res.status(404).send(notFoundFile));
server.on('request', (req, res) => {
if (bareServer.shouldRoute(req)) bareServer.routeRequest(req, res);
else app(req, res);
});
server.on('upgrade', (req, socket, head) => {
if (bareServer.shouldRoute(req)) bareServer.routeUpgrade(req, socket, head);
else socket.end();
});
server.on('listening', () => {
console.log(`Polaris started! http://localhost:${port}`);
});
server.listen({
port
});
export default app;
+1164 -7
View File
File diff suppressed because it is too large Load Diff
+10 -8
View File
@@ -1,23 +1,25 @@
{
"name": "polaris",
"version": "1.0.0",
"description": "The future of school gaming.",
"description": "The professional unblocked games site.",
"main": "index.js",
"type": "module",
"scripts": {
"dev": "nodemon index.js -e js,css,html,jpeg,png,json",
"start": "node index.js"
"start": "node server",
"prod": "node server prod",
"dev": "node server dev"
},
"author": "Polaris Developments",
"author": "Polaris Development Group",
"license": "GNU-3.0-or-later",
"dependencies": {
"@tomphttp/bare-server-node": "*",
"cors": "*",
"easyviolet": "github:Russell2259/Easyviolet",
"express": "*",
"mime": "*"
},
"devDependencies": {
"nodemon": "^3.0.1"
"html-minifier": "^4.0.0",
"javascript-obfuscator": "^4.1.0",
"jsdom": "^23.0.1",
"mime": "*",
"uuid": "^9.0.1"
}
}
+26 -21
View File
@@ -1,29 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="/assets/css/main.css">
<head>
<!--el:meta-->
<!--el:adtop-->
<!--el:analytics-->
<title>404 Error | Polaris</title>
</head>
<link rel="stylesheet" href="/assets/css/main.css">
<body>
<div class="content box">
<h1 style="font-size: 50px;">404</h1>
<p>Looks you found a page that does not exist! Try checking your url for spelling mistakes.<br><br>Or, you can report it in our <a href="//dsc.gg/skoolworld">discord server</a>.</p>
</div>
<title>404 Error | Polaris</title>
</head>
<script src="/assets/js/main.js" type="module"></script>
<script src='https://cdn.jsdelivr.net/npm/@widgetbot/crate@3' async defer>
new Crate({
server: '950407933408198717',
channel: '1172313771985870938'
})
</script>
</body>
<body>
<!--el:navbar-->
<!--el:sidebar-->
<div class="container centered">
<h1 style="font-size: 50px;">404</h1>
<p>
Looks you found a page that does not exist! Try checking your url for spelling mistakes.
<br>
<br>
Or, you can report it in our <a href="https://discord.gg/skool-community-950407933408198717" target="_blank" class="link">discord server</a>.
</p>
</div>
<script src="/assets/js/main.js" type="module"></script>
<!--el:{{mode === 'dev'}}:development-->
</body>
</html>
-211
View File
File diff suppressed because one or more lines are too long
-46
View File
@@ -1,46 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="/assets/css/main.css">
<script src="https://cdn.counter.dev/script.js" data-id="b0b2d4b2-daca-47e1-9287-b9e649b3dcd2" data-utcoffset="-5"></script>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9661054437111080"
crossorigin="anonymous"></script>
<title>Apps | Polaris</title>
</head>
<body>
<div class="content">
<h1>Apps</h1>
<br>
<div class="apps"></div>
</div>
<script type="text/javascript">
atOptions = {
'key' : 'ae1638b56336895e2ecf7d1adc3492a4',
'format' : 'iframe',
'height' : 50,
'width' : 320,
'params' : {}
};
document.write('<scr' + 'ipt type="text/javascript" src="//outrightsham.com/ae1638b56336895e2ecf7d1adc3492a4/invoke.js"></scr' + 'ipt>');
</script>
<script type="text/javascript">
atOptions = {
'key' : 'ae1638b56336895e2ecf7d1adc3492a4',
'format' : 'iframe',
'height' : 50,
'width' : 320,
'params' : {}
};
document.write('<scr' + 'ipt type="text/javascript" src="//outrightsham.com/ae1638b56336895e2ecf7d1adc3492a4/invoke.js"></scr' + 'ipt>');
</script>
<script src="/assets/js/main.js" type="module"></script>
<span data-ccpa-link="1"></span>
</body>
</html>
-46
View File
@@ -1,46 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="/assets/css/main.css">
<script src="https://cdn.counter.dev/script.js" data-id="b0b2d4b2-daca-47e1-9287-b9e649b3dcd2" data-utcoffset="-5"></script>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9661054437111080"
crossorigin="anonymous"></script>
<title>Cheats | Polaris</title>
</head>
<body>
<div class="content">
<h1>Cheats</h1>
<br>
<div class="games"></div>
</div>
<script type="text/javascript">
atOptions = {
'key' : 'ae1638b56336895e2ecf7d1adc3492a4',
'format' : 'iframe',
'height' : 50,
'width' : 320,
'params' : {}
};
document.write('<scr' + 'ipt type="text/javascript" src="//outrightsham.com/ae1638b56336895e2ecf7d1adc3492a4/invoke.js"></scr' + 'ipt>');
</script>
<script type="text/javascript">
atOptions = {
'key' : 'ae1638b56336895e2ecf7d1adc3492a4',
'format' : 'iframe',
'height' : 50,
'width' : 320,
'params' : {}
};
document.write('<scr' + 'ipt type="text/javascript" src="//outrightsham.com/ae1638b56336895e2ecf7d1adc3492a4/invoke.js"></scr' + 'ipt>');
</script>
<script src="/assets/js/main.js" type="module"></script>
<span data-ccpa-link="1"></span>
</body>
</html>
-57
View File
@@ -1,57 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="/assets/css/main.css">
<script src="https://cdn.counter.dev/script.js" data-id="b0b2d4b2-daca-47e1-9287-b9e649b3dcd2" data-utcoffset="-5"></script>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9661054437111080"
crossorigin="anonymous"></script>
<title>Games | Polaris</title>
</head>
<body>
<div class="content">
<h1 style="font-size: 6vh;">Games</h1>
<h1 style="font-size: 4vh;" class="gamesectionheader">Popular</h1>
<div class="popular-games">
</div>
<h1 style="font-size: 4vh;" class="gamesectionheader">All Games</h1>
<input type="text" id="searchInput" class="settings-input" placeholder="Search Games...">
<br>
<br>
<script type="text/javascript">
atOptions = {
'key' : 'ae1638b56336895e2ecf7d1adc3492a4',
'format' : 'iframe',
'height' : 50,
'width' : 320,
'params' : {}
};
document.write('<scr' + 'ipt type="text/javascript" src="//outrightsham.com/ae1638b56336895e2ecf7d1adc3492a4/invoke.js"></scr' + 'ipt>');
</script>
<script type="text/javascript">
atOptions = {
'key' : 'ae1638b56336895e2ecf7d1adc3492a4',
'format' : 'iframe',
'height' : 50,
'width' : 320,
'params' : {}
};
document.write('<scr' + 'ipt type="text/javascript" src="//outrightsham.com/ae1638b56336895e2ecf7d1adc3492a4/invoke.js"></scr' + 'ipt>');
</script>
<div style="padding-bottom: 2vh;">
</div>
<br>
<div class="games">
</div>
<div style="margin-top: 5vh;">
</div>
<script src="/assets/js/main.js" type="module"></script>
<span data-ccpa-link="1"></span>
</body>
</html>
-50
View File
@@ -1,50 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="/assets/css/main.css">
<meta name="6f9c120da628a61af2a67d51a1785baa69240b33" content="6f9c120da628a61af2a67d51a1785baa69240b33" />
<script src="https://cdn.counter.dev/script.js" data-id="b0b2d4b2-daca-47e1-9287-b9e649b3dcd2" data-utcoffset="-5"></script>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9661054437111080" crossorigin="anonymous"></script>
<meta name="description" content="Start Learning Math and other subjects today." />
<meta name="keywords" content="proxy, skool, games, unblock, half life, school, cheat, hack, no ads, ad-free, ad free, web proxy, ultraviolet, service workers, unblock websites, unblock chromebook, free web proxy, proxy list, proxy sites, un block chromebook, online proxy, proxy server, proxysite, proxy youtube, bypass securly, bypass iboss, bypass lightspeed filter, holy unblocker, chromebooks, titanium network, unblock youtube, youtube proxy, unblocked youtube, youtube unblocked, discord unblocked, blooket hacks, Games, Unblocking, Fun, Entertaining, Addictive, Challenging, Strategy, Puzzle, Multiplayer, Casual, Arcade, Action, Adventure, RPG, Sports, Racing, Shooter, Fighting, Platformer, Simulation, Open-World, Horror, Fantasy, Science Fiction, Casual Games, Skill Games, Board Games, Word Games, Card Games, Escape Games, Hidden Object, Match-3, Physics-Based, Time Management, Tycoon, Life Simulator, City Builder, Party Games, Music Games, Dance Games, Educational Games, Kids Games, Browser Games, Online Games, Mobile Games, PC Games, Console Games, Virtual Reality, Augmented Reality, Cross-Platform, Free-to-Play, Paid Games, In-App Purchases, Microtransactions, Free Games, Online Multiplayer, Local, Multiplayer, Co-op, Competitive, Fast-Paced, Relaxing, unbloc, notbroken, gameing, gameapps, noads, no ads, addfree, gamez, schoool, shcool unblocked, sjchool, schoolworld, shcool, no ad, free gam, free gamez, edpuzzle, edpuzzle hack, shcool wifi bypass, online game, shellshocker, front-end web developer, unblocked, games, google sites, unblocked games mom, ublocked, roblox, roblox games, roblox unblocked, roblox free, roblox free online, roblox working, roblox chromebook, chromebook roblox working, unblocker, unblocked, school, learn, blooket, blooket hack, blooket cheat, chatgpt unblocked, chatgpt, chatgpt free, chatgpt no signup, school chatgpt, free games, free movies, movies online, osu, osu unblocked, minecraft, free minecraft, eaglecrafter, minecraft 1.5, discord, discord unblocked, youtube, youtube unblocked, netflix, netflix online, tiktok, tiktok unblocked, edpuzzle, edpuzzle cheat, edpuzzle hack, autoclicker, bookmark, bookmarklet" />
<title>Home | Polaris</title>
</head>
<body>
<!--<h1 class="welcome" id="welcome">Please don't type <span class="blue">smurf</span>!</h1>-->
<div style="margin-top: 10vh; display: flex; justify-content: space-between;">
<div class="featuredcontainer">
<div class="featuredtopbar">
<b style="font-size: 5vh;">Featured Game</b>
</div>
<div>
<img class="featuredimg" data-link="true" />
</div>
</div>
<div class="mainpage-text">
<h1>Polaris</h1>
<p>By Skool</p>
<a href="https://discord.gg/skool-community-950407933408198717">
<button>Join our Discord Server</button>
</a>
<br>
<hr>
<h2>Changelog</h2>
<div id="changelog"></div>
</div>
</div>
<br><br>
<script src="/assets/js/main.js" type="module"></script>
<div style="position: relative; bottom: 0vh; text-align:center;">
</div>
</body>
</html>
-52
View File
@@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="/assets/css/main.css">
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9661054437111080"
crossorigin="anonymous"></script>
<title>Search | Polaris</title>
</head>
<body>
<div class="content">
<div class="proxycontainer">
<h1 class="proxytitle">Proxy</h1>
<text class="proxyDescription">You can search anything.</text>
<form id="wpf">
<input class="proxyinput" type="text" id="query" placeholder="URL or Search Query" />
</form>
</div>
<div style="bottom: 0; margin-top: 5vh;">
</script>
</div>
</div>
<script type="text/javascript">
atOptions = {
'key' : 'ae1638b56336895e2ecf7d1adc3492a4',
'format' : 'iframe',
'height' : 50,
'width' : 320,
'params' : {}
};
document.write('<scr' + 'ipt type="text/javascript" src="//outrightsham.com/ae1638b56336895e2ecf7d1adc3492a4/invoke.js"></scr' + 'ipt>');
</script>
<script type="text/javascript">
atOptions = {
'key' : 'ae1638b56336895e2ecf7d1adc3492a4',
'format' : 'iframe',
'height' : 50,
'width' : 320,
'params' : {}
};
document.write('<scr' + 'ipt type="text/javascript" src="//outrightsham.com/ae1638b56336895e2ecf7d1adc3492a4/invoke.js"></scr' + 'ipt>');
</script>
<script src="/assets/js/main.js" type="module"></script>
<span data-ccpa-link="1"></span>
</body>
</html>
+48
View File
@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!--el:meta-->
<!--el:adtop-->
<!--el:analytics-->
<link rel="stylesheet" href="/assets/css/main.css">
<title>404 Error | Polaris</title>
</head>
<body>
<div class="container centered">
<h1 style="font-size: 50px;">Loading</h1>
<p>
Loading the proxy...
</p>
</div>
<script src="/uv/uv.bundle.js"></script>
<script src="/uv/uv.config.js"></script>
<script type="module">
import { loadProxyWorker } from '/assets/js/utils.js';
try { document.body.dataset.theme = JSON.parse(localStorage.getItem('settings')).theme || 'system-default'; }
catch {
document.body.dataset.theme = 'system-default';
sessionStorage.setItem('settings', JSON.stringify({
theme: 'system-default'
}));
}
loadProxyWorker('uv')
.then(e => location.reload())
.catch(e => {
document.querySelector('h1').textContent = 'Error';
document.querySelector('p').textContent = 'Failed to load proxy';
});
</script>
<!--el:{{mode === 'dev'}}:development-->
</body>
</html>
-32
View File
@@ -1,32 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="/assets/css/main.css">
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9661054437111080"
crossorigin="anonymous"></script>
<title>View | Polaris</title>
</head>
<body>
<div>
<div style="overflow: hidden; z-index: 1000000;">
<iframe class="frame" overflow: auto; frameborder="no" sandbox="allow-scripts allow-forms allow-pointer-lock allow-same-origin"></iframe>
</div>
<div class="gamebar">
<img src="https://via.placeholder.com/20x20?text=img" id="gameicon" />
<p id="gametitle">Loading...</p>
<i class="fa-solid fa-expand" id="fullscreen"></i>
</div>
</div>
<br>
<a href="https://discord.gg/skool-community-950407933408198717"><button>Join our Discord Server</button></a>
<script src="/assets/js/main.js" type="module"></script>
<span data-ccpa-link="1"></span>
</body>
</html>
+14
View File
@@ -0,0 +1,14 @@
import configTemplate from './polaris.config.template.js';
/**
* @type {configTemplate}
*/
export default {
port: 8080,
mode: 'prod',
//Messes up uv
minify: false,
//Beta
assetScrambling: false,
allowDangerousTemplateInsert: true
};
+22
View File
@@ -0,0 +1,22 @@
export default {
/**
* @type {'auto' | number}
*/
port: 8080,
/**
* @type {'prod' | 'dev'}
*/
mode: 'prod',
/**
* @type {boolean}
*/
minify: true,
/**
* @type {boolean}
*/
assetScrambling: true,
/**
* @type {boolean}
*/
allowDangerousTemplateInsert: false
};
+1 -1
View File
@@ -5,7 +5,7 @@ services:
plan: free
runtime: node
buildCommand: npm i
startCommand: node index.js
startCommand: npm start
envVars:
- key: NODE_VERSION
value: 20.0.0
+118
View File
@@ -0,0 +1,118 @@
import { createBareServer } from '@tomphttp/bare-server-node';
import express from 'express';
import mime from 'mime';
import cors from 'cors';
import { pathToFile, TokenManager, rewriter } from './utils.js';
import config from '../polaris.config.js';
import path from 'node:path';
import http from 'node:http';
import url from 'node:url';
import fs from 'node:fs';
const app = express();
const server = http.createServer();
const bareServer = createBareServer('/bare/');
const mode = (process.argv[2] === 'prod' || process.argv[2] === 'dev' ? process.argv[2] : (process.argv[3] === 'prod' || process.argv[3] === 'dev' ? process.argv[3] : (config.mode === 'prod' || config.mode === 'dev' ? config.mode : 'prod')));
const port = (process.argv[2] !== 'prod' && process.argv[2] !== 'dev' && Boolean(Number(process.argv[2]))) ? process.argv[2] : (Boolean(Number(process.argv[3])) ? process.argv[3] : (Boolean(Number(config.port)) ? config.port : (mode === 'prod' ? 80 : 8080)));
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
const swPaths = [
'/uv/sw.js',
'/assets/js/offline.js'
];
app.get('/cdn/*', cors({
origin: false
}), async (req, res, next) => {
let reqTarget = `https://raw.githubusercontent.com/Skoolgq/Polaris-Assets/main/${req.path.replace('/cdn/', '')}`;
const asset = await fetch(reqTarget);
if (asset.status == 200) {
var data = Buffer.from(await asset.arrayBuffer());
const noRewrite = ['.unityweb'];
if (!noRewrite.includes(mime.getExtension(reqTarget))) res.writeHead(200, {
'content-type': mime.getType(reqTarget)
});
if (mime.getType(reqTarget) === 'text/html') data = data + '<script src=\'/assets/js/cdn_inject.js\' preload=\'true\'></script>';
res.end(data);
} else next();
});
app.get('*', (req, res, next) => {
if (swPaths.includes(req.path)) res.setHeader('Service-Worker-Allowed', '/');
next();
});
app.get('/asset', (req, res, next) => {
if (req.query.asset) {
const {
exists,
path: filePath
} = pathToFile(req.query.asset, path.join(__dirname, '../static/assets'));
if (exists) {
if (filePath.startsWith(path.join(__dirname, '../static/assets'))) res.setHeader('content-type', mime.getType(filePath)).end(fs.readFileSync(filePath));
else next();
} else next();
} else next();
});
app.get('/asset/:token', async (req, res, next) => {
if (req.params.token && !req.query.asset) {
if (TokenManager.exists(req.params.token)) {
const token = TokenManager.get(req.params.token);
if (TokenManager.get(req.params.token).type === 'asset') {
TokenManager.delete(req.params.token);
res.setHeader('content-type', token.data.type);
res.end(await rewriter.auto(fs.readFileSync(token.data.asset), token.data.type, token.data.asset.replace(path.join(__dirname, '../static'), '')));
} else next();
} else next();
}
});
app.get('/uv/service/*', async (req, res) => res.end(await rewriter.html(fs.readFileSync(path.join(__dirname, '../pages/uv_404.html')))));
app.use(async (req, res, next) => {
if (req.path === '/index') res.redirect('/');
else {
const {
exists,
path: filePath
} = pathToFile(req.path, path.join(__dirname, '../static'));
if (exists) {
if (req.path.endsWith('.html')) res.redirect(req.path.slice(0, -5));
else {
res.setHeader('content-type', mime.getType(filePath));
if (mime.getType(filePath) === 'text/html') res.end(await rewriter.html(fs.readFileSync(filePath), req.path));
else if (mime.getType(filePath) === 'text/javascript') res.end(await rewriter.javascript(fs.readFileSync(filePath), req.path));
else if (mime.getType(filePath) === 'text/css') res.end(await rewriter.css(fs.readFileSync(filePath), req.path));
else res.sendFile(filePath);
}
} else {
res.setHeader('content-type', 'text/html');
res.status(404).end(await rewriter.html(fs.readFileSync(path.join(__dirname, '../pages/404.html'))));
}
}
});
server.on('request', (req, res) => {
if (bareServer.shouldRoute(req)) bareServer.routeRequest(req, res);
else app(req, res);
});
server.on('upgrade', (req, socket, head) => {
if (bareServer.shouldRoute(req)) bareServer.routeUpgrade(req, socket, head);
else socket.end();
});
server.listen(port, () => console.log(`Polaris running\n\nPort: ${server.address().port}\nMode: ${mode}\nNode.js: ${process.version}`));
+34
View File
@@ -0,0 +1,34 @@
import * as rewriter from './utils/rewriter.js';
import TokenManager from './utils/token.js';
import path from 'node:path';
import fs from 'node:fs';
/**
* @param {string} url
* @param {string} folderPath
* @returns {{ exists: boolean, path: string }}
*/
const pathToFile = (url = '', folderPath) => {
if (url.endsWith('/')) url = url + 'index.html';
else if (url.split(/[#?]/)[0].split('.').pop().trim() === url) {
if (!fs.existsSync(path.join(folderPath, url))) url = url + '.html';
}
return {
exists: fs.existsSync(path.join(folderPath, url)),
path: path.join(folderPath, url)
};
};
export default {
pathToFile,
TokenManager,
rewriter
};
export {
pathToFile,
TokenManager,
rewriter
};
+225
View File
@@ -0,0 +1,225 @@
import JavaScriptObfuscator from 'javascript-obfuscator';
import { minify as minifyHTML } from 'html-minifier';
import { JSDOM } from 'jsdom';
import mime from 'mime';
import { TokenManager } from '../utils.js';
import config from '../../polaris.config.js';
import path from 'node:path';
import url from 'node:url';
import fs from 'node:fs';
const mode = (process.argv[2] === 'prod' || process.argv[2] === 'dev' ? process.argv[2] : (process.argv[3] === 'prod' || process.argv[3] === 'dev' ? process.argv[3] : (config.mode === 'prod' || config.mode === 'dev' ? config.mode : 'prod')));
const __dirname = url.fileURLToPath(new URL('../', import.meta.url));
const templateParser = (data) => {
return new Promise(async (resolve, reject) => {
resolve(String(data).split('<!--el:')
.map(data => {
if (data.split('\n')[0].trim().endsWith('-->')) return data.split('\n')[0].trim().replace('-->', '');
else return undefined;
})
.map(data => {
if (data) {
if (data.startsWith('{{') && data.split(':')[data.split(':').length - 2].endsWith('}}')) {
if (config.allowDangerousTemplateInsert) {
if (Boolean(eval(String(data.split(':')[data.split(':').length - 2]).slice(2, -2)))) return data;
else return undefined;
} else return undefined;
} else return data;
} else return undefined;
})
.filter(data => fs.existsSync(path.join(__dirname, '../templates', (data ? (data.startsWith('{{') && data.split(':')[data.split(':').length - 2].endsWith('}}') ? data.split(':')[data.split(':').length - 1] : data) : undefined) + '.html')))
.map(data => {
return {
name: data,
file: fs.readFileSync(path.join(__dirname, '../templates', (data ? (data.startsWith('{{') && data.split(':')[data.split(':').length - 2].endsWith('}}') ? data.split(':')[data.split(':').length - 1] : data) : undefined) + '.html').toString())
};
}));
});
};
const html = (data) => {
return new Promise(async (resolve, reject) => {
var htmlData = String(data);
const templates = await templateParser(data);
for (let i = 0; i < templates.length; i++) htmlData = htmlData.replace(`<!--el:${templates[i].name}-->`, templates[i].file)
const dom = new JSDOM(htmlData);
if (config.assetScrambling) {
for (let i = 0; i < dom.window.document.documentElement.querySelectorAll('script').length; i++) {
const script = dom.window.document.documentElement.querySelectorAll('script')[i];
if (script.src.startsWith('/') && !script.src.startsWith('//') && fs.existsSync(path.join(__dirname, '../static', script.src))) script.setAttribute('src', `/asset/${TokenManager.generate('asset', 20000, {
asset: path.join(__dirname, '../static', script.src),
type: 'application/javascript'
}).token}`);
}
for (let i = 0; i < dom.window.document.documentElement.querySelectorAll('link[rel="stylesheet"]').length; i++) {
const css = dom.window.document.documentElement.querySelectorAll('link[rel="stylesheet"]')[i];
if (css.href.startsWith('/') && !css.href.startsWith('//') && fs.existsSync(path.join(__dirname, '../static', css.href))) css.setAttribute('href', `/asset/${TokenManager.generate('asset', 20000, {
asset: path.join(__dirname, '../static', css.href),
type: 'text/css'
}).token}`);
}
for (let i = 0; i < dom.window.document.documentElement.querySelectorAll('img').length; i++) {
const img = dom.window.document.documentElement.querySelectorAll('img')[i];
if (img.src.startsWith('/') && !img.src.startsWith('//') && fs.existsSync(path.join(__dirname, '../static', img.src))) img.setAttribute('src', `/asset/${TokenManager.generate('asset', 20000, {
asset: path.join(__dirname, '../static', img.src),
type: mime.getType(path.join(__dirname, '../static', img.src))
}).token}`);
}
}
for (let i = 0; i < dom.window.document.documentElement.querySelectorAll('a').length; i++) {
const link = dom.window.document.documentElement.querySelectorAll('a')[i];
if (URL.canParse(link.href)) {
if (new URL(link.href).protocol === 'https:') link.href = `/view?load=${Buffer.from(JSON.stringify({
target: link.href,
redirect: true,
trusted: true
})).toString('base64')}`;
else if (new URL(link.href).protocol === 'http:') link.href = `/view?load=${Buffer.from(JSON.stringify({
target: link.href,
redirect: true
})).toString('base64')}`;
}
}
if (config.minify) resolve(minifyHTML(dom.serialize(), {
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
removeScriptTypeAttributes: true,
useShortDoctype: true,
collapseWhitespace: true,
removeComments: true
}))
else resolve(dom.serialize());
});
};
const javascript = (data, filePath) => {
return new Promise((resolve, reject) => {
filePath = filePath.replaceAll('\\', '/');
const imports = String(data).split('import ')
.map(data => data.split('from ')[1])
.filter(data => Boolean(data))
.map(data => data.split('\n')[0]
.replaceAll('\'', '')
.replaceAll('`', '')
.replaceAll('"', '')
.replaceAll(';', ''))
.map(data => {
if (data.startsWith('./')) return {
originalFile: data.replaceAll('\r', ''),
newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data).replaceAll('\r', '')
};
else if (data.startsWith('../')) return {
originalFile: data.replaceAll('\r', ''),
newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data).replaceAll('\r', '')
};
else return {
originalFile: data.replaceAll('\r', ''),
newFile: data.replaceAll('\r', '')
};
})
.filter(data => fs.existsSync(path.join(__dirname, '../static', data.newFile)));
let javascript = String(data);
if (config.assetScrambling) for (let i = 0; i < imports.length; i++) javascript = javascript.replace(imports[i].originalFile, '/asset/' + TokenManager.generate('asset', 20000, {
asset: path.join(__dirname, '../static', imports[i].newFile),
type: 'text/javascript'
}).token);
if (config.minify) resolve(JavaScriptObfuscator.obfuscate(javascript, {
compact: true,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
numbersToExpressions: true,
simplify: true,
stringArrayShuffle: true,
splitStrings: true,
stringArrayThreshold: 1
}).getObfuscatedCode());
else resolve(javascript);
});
};
const css = (data, filePath) => {
return new Promise((resolve, reject) => {
filePath = filePath.replaceAll('\\', '/');
const imports = String(data).split('url(')
.map(data => {
if (data.split('\n')[0].split(' ')[0].replace(';', '').trim().endsWith(')')) return data.split('\n')[0]
.split(' ')[0]
.trim()
.replace(';', '')
.replace(')', '')
.replaceAll('\'', '')
.replaceAll('`', '')
.replaceAll('"', '');
else return null;
})
.filter(data => {
if (data) try {
new URL(data);
return false;
} catch (e) {
return true;
} else return false;
})
.map(data => {
if (data.startsWith('./')) return {
originalFile: data,
newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data)
};
else if (data.startsWith('../')) return {
originalFile: data,
newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data)
};
else return {
originalFile: data,
newFile: data
};
})
.filter(data => fs.existsSync(path.join(__dirname, '../static', data.newFile)));
let css = String(data);
if (config.assetScrambling) for (let i = 0; i < imports.length; i++) css = css.replace(imports[i].originalFile, '/asset/' + TokenManager.generate('asset', 20000, {
asset: path.join(__dirname, '../static', imports[i].newFile),
type: mime.getType(path.join(__dirname, '../static', imports[i].newFile))
}).token);
if (config.minify) resolve(css.replace(/(\r\n|\n|\r)/gm, '').replaceAll(' ', ' '));
else resolve(css);
});
};
const auto = async (data, type, filePath) => {
if (type === 'text/html') return await html(data);
else if (type === 'text/javascript' || type === 'application/javascript') return await javascript(data, filePath);
else if (type === 'text/css') return await css(data, filePath);
else return data;
};
export {
auto,
html,
javascript,
css
};
+79
View File
@@ -0,0 +1,79 @@
import { v4 as uuid } from 'uuid';
class TokenManager {
constructor() {
this.tokens = {};
setInterval(() => {
const currentDate = Date.now();
Object.keys(this.tokens).forEach(key => {
const token = this.tokens[key];
if (currentDate > token.expires) delete this.tokens[key];
});
}, 100);
}
/**
* Generate a token
* @param {string} type The type of token you are generating
* @param {number} expires How long it will take for the token to expire in miliseconds
* @param {object | string} data The data to be stored with the token
* @returns {{token: number, expires: number}} The token data
*/
generate = (type, expires, data) => {
const token = uuid();
this.tokens[token] = {
token: token,
type: type,
expires: Date.now() + expires,
data: data
}
return {
token: token,
expires: Date.now() + expires
}
}
/**
* Check if a token exists
* @param {string} token The token
* @returns {boolean}
*/
exists = (token) => {
return this.tokens[token] ? true : false;
}
/**
* Get all tokens in a category
* @param {string} type The token category
* @returns {Array.<{token: stromg, type: string, expires: number, data: object | string}>} The list of tokens
*/
getAll = (type) => {
const tokens = [];
Object.keys(this.tokens).forEach(key => {
const token = this.tokens[key];
if (token.type == type) tokens.push(token);
});
return tokens;
}
/**
* Get token information from a token
* @param {string} token The token
* @returns {{token: stromg, type: string, expires: number, data: object | string}} Token data
*/
get = (token) => {
return this.tokens[token];
}
delete = (token) => delete this.tokens[token];
}
export default new TokenManager();
+31
View File
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!--el:meta-->
<!--el:adtop-->
<!--el:analytics-->
<link rel="stylesheet" href="/assets/css/main.css">
<title>Apps | Polaris</title>
</head>
<body>
<!--el:navbar-->
<!--el:sidebar-->
<div class="content centered">
<h1>Apps</h1>
<br>
<div class="apps"></div>
</div>
<!--el:ad_horizontal-->
<!--el:ad_horizontal-->
<script src="/assets/js/main.js" type="module"></script>
<!--el:{{mode === 'dev'}}:development-->
</body>
</html>
+11 -6
View File
@@ -2,26 +2,31 @@
{
"name": "Discord",
"image": "/assets/img/discord.png",
"source": "/service/hvtrs8%2F-dksaopd%2Ccmm-lmgkn"
"target": "https://discord.com/app",
"proxy": true
},
{
"name": "Emulator",
"image": "https://cdn-icons-png.flaticon.com/512/9889/9889883.png",
"source": "/service/hvtrs8%2F-dgmm.gmwlctmrhs%2Copg-"
"image": "https://emulatorjs.org/media/logo-light.png",
"target": "https://demo.emulatorjs.org/",
"proxy": true
},
{
"name": "Tiktok",
"image": "/assets/img/tiktok.png",
"source": "/service/hvtrs8%2F-wuw%2Ctkkvoi.aoo%2Fgn-"
"target": "https://www.tiktok.com/en/",
"proxy": true
},
{
"name": "Twitch",
"image": "/assets/img/twitch.png",
"source": "/service/hvtrs8%2F-wuw%2Ctuivcj.vv-"
"target": "https://www.twitch.tv/",
"proxy": true
},
{
"name": "Youtube",
"image": "/assets/img/youtube.png",
"source": "/service/hvtrs8%2F-wuw%2Cymuvu%60e%2Ccmm-"
"target": "https://youtube.com",
"proxy": true
}
]
+4
View File
@@ -1,4 +1,8 @@
[
{
"date": "1/1/2024",
"simpleDescription": "2024 Update!!!"
},
{
"date": "11/23/2023",
"simpleDescription": "Minor UI Changes"
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -1,4 +1,4 @@
/*Font template:*/
/*Font template:
@font-face {
font-family: 'fontname';
@@ -6,7 +6,7 @@
url('/assets/fonts/fontname.woff') format('woff');
font-weight: normal;
font-style: normal;
}
}*/
/*Lato*/
+89
View File
@@ -0,0 +1,89 @@
footer {
position: relative;
text-align: left;
background-image: url('/assets/img/background.jpeg');
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
user-select: none;
padding: 4% 5% 2% 5%;
color: #fff;
margin-top: 50px;
text-shadow: 0px 0px 20px rgba(0, 0, 0, 0.616);
}
footer p {
text-shadow: 0px 0px 20px rgba(0, 0, 0, 0.616);
}
footer h1 {
font-family: 'Lato-Black';
color: #fff;
margin: 0px;
margin-bottom: 10px;
}
footer::before {
display: block;
content: '';
height: 270px;
position: fixed;
bottom: 0;
left: 0;
width: 100vw;
z-index: -1;
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(0, 0, 0, 0.8) 100%);
}
footer .socials {
margin-bottom: 20px;
}
footer .socials i {
margin: 10px;
margin-left: 5px;
margin-right: 5px;
font-size: 20px;
cursor: pointer;
}
footer .socials a {
color: #fff;
}
footer .socials a:hover {
color: #fff;
}
footer .socials a::before {
display: none;
}
footer .socials i:is(:first-child) {
margin-left: 0px;
}
footer .right {
position: absolute;
right: 5%;
text-align: right;
}
footer .right a {
display: block;
margin-top: 20px;
}
footer .title:not(:last-child) {
display: flex;
margin: 0px;
}
footer .title img {
width: 40px;
height: 40px;
margin-left: 10px;
filter: drop-shadow(0px 0px 20px rgba(0, 0, 0, 0.616));
border-radius: 1vh;
}
+197 -186
View File
@@ -1,22 +1,28 @@
@import url('https://site-assets.fontawesome.com/releases/v6.2.0/css/all.css');
@import url('/assets/css/fonts.css');
@import url('/assets/css/themes.css');
@import url('/assets/css/nav.css');
@import url('/assets/css/sidebar.css');
@import url('/assets/css/dropdown.css');
@import url('https://site-assets.fontawesome.com/releases/v6.5.1/css/all.css');
@import url('./fonts.css');
@import url('./themes.css');
@import url('./nav.css');
@import url('./sidebar.css');
@import url('./dropdown.css');
@import url('./footer.css');
* {
font-family: 'Lato';
user-select: none;
scroll-behavior: smooth;
transition: 0.5s;
}
html,
body {
margin: 0vh;
margin: 0px;
background: var(--background-color);
background-attachment: fixed;
color: var(--text);
padding-top: 20vh;
background-repeat: no-repeat;
}
.centered {
text-align: center;
}
@@ -62,10 +68,27 @@ body::-webkit-scrollbar-corner {
background: transparent;
}
.row {
margin-top: 10vh;
display: flex;
justify-content: space-between;
}
.row.mainpage {
position: absolute;
margin-top: 0px;
top: calc(calc(9vh + 2.5em) + 100px);
bottom: 50px;
}
.hidden {
display: none;
}
#searchInput {
margin-bottom: 20px;
}
i {
margin: 1vh;
}
@@ -75,13 +98,13 @@ a {
text-decoration: none;
}
h1 {
text-align: center;
font-size: 8vh;
a.link {
color: #2d81ff;
}
p {
font-size: 4vh;
h1.title {
text-align: center;
font-size: 8vh;
}
hr {
@@ -90,49 +113,10 @@ hr {
background-image: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0));
}
.welcome {
padding-bottom: 0px;
}
.small {
font-size: 3vh;
}
.settings-input {
text-align: center;
box-shadow: 0.5vh 0.5vh 1vh 0vh var(--shadow-color);
border: none;
border-radius: 2vh;
cursor: pointer;
background: var(--sidebar-bg);
width: 25vh;
height: 4vh;
color: var(--text);
transition: 0.4s;
margin: auto;
margin-top: 2vh;
}
.proxycontainer {
background-color: var(--background-color);
box-shadow: 0.5vh 0.5vh 1vh 0vh var(--shadow-color);
width: 60vw;
height: 30vh;
margin: auto;
margin-top: 10vh;
padding-top: 1vh;
padding-bottom: 2vh;
padding-left: 1.5vh;
padding-right: 1.5vh;
border-radius: 2vh;
color: var(--text);
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.proxytitle {
margin-bottom: 1vh;
font-size: 5.5vh;
@@ -155,7 +139,7 @@ hr {
width: 55vw;
height: 6vh;
color: var(--text);
transition: 0.4s;
transition: 0.5s;
margin: auto;
margin-top: 2vh;
}
@@ -163,54 +147,39 @@ hr {
button {
text-align: center;
border: none;
border-radius: 1vh;
border-radius: 1.5vh;
cursor: pointer;
background-color: var(--button-bg);
color: var(--text);
transition: 0.5s;
font-size: 20px;
font-family: 'Lato';
padding: 5px;
padding-left: 10px;
padding-right: 10px;
}
input {
text-align: center;
box-shadow: 0.5vh 0.5vh 1vh 0vh var(--shadow-color);
border: none;
border-radius: 100px;
cursor: pointer;
background: var(--sidebar-bg);
width: 25vh;
height: 4vh;
color: var(--text);
transition: 0.4s;
font-size: 2.5vh;
font-family: 'Lato';
transition: 0.5s;
margin: auto;
margin-top: 2vh;
}
.mainpageimage-button {
background-color: transparent;
border: none;
padding: 0;
cursor: pointer;
justify-content: center;
width: 45vh;
margin-top: 10vh;
transition: all 0.4s ease;
}
.mainpageimage-button:hover {
transform: scale(1.025);
opacity: 1;
}
.mainpage-text {
box-shadow: 0.5vh 0.5vh 1vh 0vh var(--shadow-color);
background-color: var(--background-color);
margin-right: 15vh;
width: 75vh;
height: 52vh;
input::placeholder {
color: var(--text);
text-align: center;
border-radius: 2vh;
opacity: 0.9;
padding: 2vh;
line-height: 2vh;
}
.mainpage-text>h1 {
padding: 2vh;
margin: 0px;
}
.mainpage-text>p {
padding: 3vh;
margin: 0px;
input:not(:read-only) {
outline: none;
}
.blue {
@@ -219,28 +188,6 @@ button {
text-shadow: 0vh 0vh 1.5vh rgb(45, 129, 255);
}
.chromebook-btn-div {
box-shadow: 0.5vh 0.5vh 1vh 0vh var(--shadow-color);
background-color: var(--background-color);
width: 30vh;
height: 4.3vh;
color: var(--text);
text-align: center;
border-radius: 2vh;
justify-content: center;
padding: 0.5vh;
margin: 0 auto;
margin-top: 3vh;
position: relative;
opacity: 0.9;
padding: 2vh;
line-height: 2vh;
}
.settings-button {
box-shadow: 0.5vh 0.5vh 1vh 0vh var(--shadow-color);
}
select {
text-align: center;
box-shadow: 0.5vh 0.5vh 1vh 0vh var(--shadow-color);
@@ -251,7 +198,7 @@ select {
min-width: 7vh;
height: 4vh;
color: var(--text);
transition: 0.4s;
transition: 0.5s;
margin-left: 1vh;
margin-right: 1vh;
padding-left: 2vh;
@@ -396,6 +343,64 @@ input:checked+.slider:before {
z-index: 10;
}
.cheats {
width: 100%;
display: flex;
justify-content: center;
flex-wrap: wrap;
padding-bottom: 3vh;
}
.cheat {
min-width: 20vh;
min-height: 20vh;
display: block;
border: none;
cursor: pointer;
transition: .4s;
overflow: hidden;
position: relative;
box-shadow: 0vh 0.75vh 1.5vh 0vh black;
margin: 1vh;
text-align: left;
border-radius: 1.5vh;
}
.cheat:hover {
filter: brightness(95%);
transform: translateY(-0.2vh);
border-color: #ffffff;
}
.cheat>img {
width: 100%;
height: 100%;
object-fit: cover;
position: absolute;
left: 0;
top: 0;
object-position: center;
}
.cheat:after {
content: '';
top: 0;
left: 0;
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.6) 100%);
}
.cheat>h3 {
position: absolute;
bottom: -0.5vh;
left: 2vh;
color: #fff;
font-size: 1.8vh;
z-index: 10;
}
.apps {
width: 100%;
display: flex;
@@ -482,8 +487,6 @@ input:checked+.slider:before {
background: var(--solid);
}
;
.notifications>.notification.error {
background: rgba(171, 61, 222, 0.801);
color: #fff;
@@ -493,9 +496,9 @@ input:checked+.slider:before {
}
.box {
background: var(--sidebar-bg);
background: var(--background-color);
padding: 5vh;
border-radius: 1vh;
border-radius: 2vh;
position: absolute;
top: 50%;
left: 50%;
@@ -525,87 +528,95 @@ input:checked+.slider:before {
margin-top: 5vh;
}
.frame {
margin: auto;
display: block;
border-top: 3vh solid;
border-left: 3vh solid;
border-right: 3vh solid;
border-radius: 4vh 4vh 0vh 0vh;
background: #fff;
height: 70vh;
width: 75vw;
outline: none;
border-color: rgba(0, 0, 0);
}
.gamebar img {
width: 3.5vh;
height: 3.5vh;
margin: 1vh;
border-radius: 0.5vh;
}
.gamebar p {
font-weight: 900;
font-size: 2vh;
margin: auto 0;
}
.gamebar i {
font-size: 3vh;
margin: auto 0;
margin-left: auto;
cursor: pointer;
}
.gamebar {
width: 75vw;
margin: 0 auto;
border-left: 3vh solid black;
border-right: 3vh solid black;
display: flex;
border-radius: 0vh 0vh 4vh 4vh;
color: #ffffff;
border-color: rgba(0, 0, 0);
background: rgba(0, 0, 0);
}
.featuredcontainer {
.container {
background-color: var(--background-color);
box-shadow: 0.5vh 0.5vh 1vh 0vh var(--shadow-color);
width: 80vh;
height: 52vh;
box-shadow: 0vh 0.75vh 1.5vh 0vh var(--shadow-color);
margin-left: 15vh;
padding-top: 2vh;
padding-bottom: 2vh;
padding-left: 2vh;
padding-right: 2vh;
padding: 2vw;
border-radius: 2vh;
color: var(--text);
min-width: 40vw;
overflow: hidden;
margin-left: 50px;
margin-right: 25px;
text-align: center;
}
.featuredimg {
width: calc(100% - 2vh);
.container.centered {
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.container.left {
margin-right: 25px;
}
.container.right {
margin-right: 50px;
margin-left: 25px;
}
h1.nomargin {
margin: 0px;
}
img.featured {
width: 100%;
height: 100%;
object-fit: cover;
overflow: hidden;
display: inline;
margin-top: 2vh;
height: auto;
cursor: pointer;
border: solid;
border-width: 0.5vh;
border-radius: 2vh;
border-color: rgba(0, 0, 0, 0);
transition: border 0.4s linear;
transition: border 0.5s linear;
}
.featuredimg:hover {
img.featured:hover {
border-color: rgba(255, 255, 255, 1);
transition: border 0.4s linear;
transition: border 0.5s linear;
}
.featuredtopbar {
padding-bottom: 2vh;
.content {
margin-left: 100px;
margin-right: 100px;
}
/*
.gamesectionheader{
text-align: left;
left: 10vh;
}*/
@keyframes beat {
0%,
50%,
100% {
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%) scale(1.25, 1.25) rotate(-5deg);
transform: translate(-50%, -50%) scale(1.25, 1.25) rotate(-5deg);
}
30%,
80% {
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%) scale(1, 1) rotate(5deg);
transform: translate(-50%, -50%) scale(1, 1) rotate(5deg);
}
}
@keyframes shake {
0% { transform: translate(1px, 1px) rotate(0deg); }
10% { transform: translate(-1px, -2px) rotate(-1deg); }
20% { transform: translate(-3px, 0px) rotate(1deg); }
30% { transform: translate(3px, 2px) rotate(0deg); }
40% { transform: translate(1px, -1px) rotate(1deg); }
50% { transform: translate(-1px, 2px) rotate(-1deg); }
60% { transform: translate(-3px, 1px) rotate(0deg); }
70% { transform: translate(3px, 1px) rotate(-1deg); }
80% { transform: translate(-1px, -1px) rotate(1deg); }
90% { transform: translate(1px, 2px) rotate(0deg); }
100% { transform: translate(1px, -2px) rotate(-1deg); }
}
+49 -15
View File
@@ -1,8 +1,35 @@
@media (max-width:960px) {
.navbar>.right {
display: none;
}
}
.navbar {
position: sticky;
box-shadow: 0vh 0.75vh 1.5vh 0vh var(--shadow-color);
position: fixed;
width: calc(calc(100% - 100px) - calc(1.5em * 2));
background-color: var(--background-color);
top: 0;
margin-left: 50px;
margin-right: 50px;
margin-top: 50px;
color: rgb(255, 255, 255);
z-index: 100;
display: flex;
justify-content: space-between;
margin: 1.5vh;
border-radius: 2vh;
padding: 1.5em;
padding-bottom: 1em;
text-align: center;
backdrop-filter: blur(7.1px);
-webkit-backdrop-filter: blur(7.1px);
}
.navbar.scrolling {
background-color: var(--background-darker);
}
.navbar>.title {
margin: 1vh;
}
.navbar>.title>img {
@@ -13,35 +40,42 @@
.navbar>.title>span {
font-family: 'Lato-Black';
font-size: 3vh;
margin-left: 1.3vh;
position: relative;
top: -2.8vh;
left: 11vh;
position: absolute;
text-align: left;
}
.navbar>.title>span>span {
display: block;
display: flex;
position: relative;
font-size: 1.2vh;
margin-left: 3vh;
width: auto;
}
.navbar>.end {
display: flex;
justify-content: space-between;
.navbar>.right {
position: absolute;
right: 0;
margin: 2vh;
margin-top: 2.5vh;
margin-right: 3vh;
}
.navbar>.end>a {
.navbar>.right>a {
border-style: solid;
border-width: 0.5vh;
margin: 0.3rem;
padding: 0.8rem;
cursor: pointer;
font-size: 2.7vh;
border-radius: 2vh;
border-color: rgba( 0, 0, 0, 0);
border-radius: 1.5vh;
border-color: rgba(0, 0, 0, 0);
transition: border-color 0.4s linear;
}
.navbar>.end>a:hover {
.navbar>.right>a:hover {
border-color: rgba(255, 255, 255, 1);
}
.navbar>.right>a.active {
border-color: rgba(255, 255, 255, 1);
}
+9 -6
View File
@@ -1,10 +1,11 @@
.sidebar {
position: fixed;
top: 15vh;
margin-top: calc(calc(9vh + 2.5em) + 100px);
bottom: 50px;
top: 0;
right: -60vh;
width: 50vh;
height: 75vh;
background: var(--sidebar-bg);
background-color: var(--background-darker);
border-radius: 2vh;
box-shadow: 0vh 0.75vh 1.5vh 0vh var(--shadow-color);
text-align: center;
@@ -12,10 +13,12 @@
overflow-y: auto;
padding: 1vh;
transition: all 0.5s ease;
backdrop-filter: blur(7.1px);
-webkit-backdrop-filter: blur(7.1px);
}
.sidebar.active {
right: 5vh;
right: 50px;
transition: all 0.5s ease;
}
@@ -32,6 +35,7 @@
top: 87vh;
opacity: 0;
z-index: 9999999999999999999;
display: none;
}
.sidebar>.scroll.active {
@@ -79,5 +83,4 @@
.settings-button {
min-width: 7vh;
margin: 0.5vh;
}
}
+34 -46
View File
@@ -1,35 +1,22 @@
body[data-theme='halloween'] {
--background-color: #233147;
--text: #fff;
--sidebar-bg: #161f2eef;
--button-bg: #1c1c1c69;
--shadow-color: #4242424b;
--switch-color: #42424259;
--switch-active: #2196F3;
--scrollbar-color: #ffffff59;
--solid: #1b2735;
--hover: #757575;
background: radial-gradient(circle, rgba(58, 61, 96, 1) 0%, rgba(45, 40, 51, 1) 100%);
background-repeat: no-repeat;
}
body[data-theme='dark'] {
--background-color: #233147;
--background-color: rgba(0, 0, 0, 0.8);
--background-darker: rgba(0, 0, 0, 0.9);
--text: #fff;
--sidebar-bg: #161f2eef;
--button-bg: #1c1c1c69;
--shadow-color: #4242424b;
--shadow-color: #000;
--switch-color: #42424259;
--switch-active: #2196F3;
--scrollbar-color: #ffffff59;
--solid: #1b2735;
--hover: #757575;
background: radial-gradient(circle, rgba(58, 61, 96, 1) 0%, rgba(45, 40, 51, 1) 100%);
background: radial-gradient(at center bottom, rgb(27, 39, 53) 0%, rgb(9, 10, 15) 100%);;
background-repeat: no-repeat;
}
body[data-theme='light'] {
--background-color: #fff;
--background-darker: var(--background-color);
--text: #000;
--hover: #757575;
--sidebar-bg: #ffffffee;
@@ -46,18 +33,19 @@ body[data-theme='light'] {
}
body[data-theme='flamingo'] {
--background-color: #e75166;
--background-color: rgba(0, 0, 0, 0.8);
--background-darker: rgba(0, 0, 0, 0.9);
--text: #fff;
--sidebar-bg: #e75166ee;
--button-bg: #00000059;
--shadow-color: #F949724b;
--shadow-color: #000;
--switch-color: #959595;
--switch-active: #FB5E4C;
--scrollbar-color: #ffffff59;
--scrollbar-color: rgba(0, 0, 0, 0.8);
--solid: #FB5E4C;
--hover: #ed58b4;
background: linear-gradient(122deg, rgba(255, 41, 191, 1) 0%, rgba(215, 67, 46, 1) 85%);
animation: flamingo-gradient 12s ease infinite;
background: linear-gradient(304deg, rgb(255, 136, 0), rgb(245, 7, 226)) 0% 0% / 120% 120%;
animation: 12s ease 0s infinite normal none running flamingo-gradient;
@keyframes flamingo-gradient {
0% {
@@ -75,18 +63,19 @@ body[data-theme='flamingo'] {
}
body[data-theme='frost'] {
--background-color: #293a6bee;
--background-color: rgba(0, 0, 0, 0.8);
--background-darker: rgba(0, 0, 0, 0.9);
--text: #fff;
--sidebar-bg: #293a6bee;
--button-bg: #42424259;
--shadow-color: #0561814b;
--shadow-color: #000;
--switch-color: #42424259;
--switch-active: #056181;
--scrollbar-color: #ffffff59;
--solid: #056181;
--hover: #6491fa;
background: linear-gradient(90deg, #6491fa 0%, rgba(49, 49, 129) 84%);
animation: frost-gradient 12s ease infinite;
background: linear-gradient(304deg, rgb(0, 0, 0), rgb(8, 193, 255)) 0% 0% / 120% 120%;
animation: 12s ease 0s infinite normal none running frost-gradient;
@keyframes frost-gradient {
0% {
@@ -104,11 +93,12 @@ body[data-theme='frost'] {
}
body[data-theme='crimson'] {
--background-color: #a74c4cee;
--background-color: rgba(0, 0, 0, 0.8);
--background-darker: rgba(0, 0, 0, 0.9);
--text: #fff;
--sidebar-bg: #a74c4cee;
--button-bg: #00000059;
--shadow-color: #940C284b;
--shadow-color: #000;
--switch-color: #42424259;
--switch-active: #B90F32;
--scrollbar-color: #ffffff59;
@@ -133,7 +123,8 @@ body[data-theme='crimson'] {
}
body[data-theme='inferno'] {
--background-color: #871a13;
--background-color: rgba(0, 0, 0, 0.8);
--background-darker: rgba(0, 0, 0, 0.9);
--text: #fff;
--sidebar-bg: #871a13;
--button-bg: #00000059;
@@ -162,17 +153,18 @@ body[data-theme='inferno'] {
}
body[data-theme='indigo'] {
--background-color: #9247fc;
--background-color: rgba(0, 0, 0, 0.8);
--background-darker: rgba(0, 0, 0, 0.9);
--text: #fff;
--sidebar-bg: #9247fc;
--button-bg: #9449fc;
--shadow-color: #4e1f8f;
--button-bg: #482579;
--shadow-color: #2A1B55;
--switch-color: #9759e3;
--switch-active: #bf97f0;
--scrollbar-color: #ffffff59;
--solid: #9b6aeb;
--hover: #b07df0;
background: linear-gradient(90deg, rgba(98, 3, 252, 1) 0%, rgba(155, 106, 235, 1) 85%);
background: linear-gradient(90deg, #51305e 0%, #0f084e 85%);
animation: indigo-gradient 12s ease infinite;
@keyframes indigo-gradient {
@@ -192,6 +184,7 @@ body[data-theme='indigo'] {
body[data-theme='violet'] {
--background-color: #000000;
--background-darker: rgba(0, 0, 0, 0.9);
--text: #fff;
--sidebar-bg: #000000;
--button-bg: #000000;
@@ -219,16 +212,10 @@ body[data-theme='violet'] {
}
}
@media screen and (prefers-color-scheme: light) {
body[data-theme='system default'] {
body[data-theme='system-default'] {
--background-color: #fff;
--background-darker: var(--background-color)
--text: #000;
--sidebar-bg: #ffffffee;
--button-bg: #ffffff59;
@@ -244,18 +231,19 @@ body[data-theme='violet'] {
}
@media screen and (prefers-color-scheme: dark) {
body[data-theme='system default'] {
--background-color: #233147;
body[data-theme='system-default'] {
--background-color: rgba(0, 0, 0, 0.8);
--background-darker: rgba(0, 0, 0, 0.9);
--text: #fff;
--sidebar-bg: #161f2eef;
--button-bg: #42424259;
--shadow-color: #4242424b;
--shadow-color: #000;
--switch-color: #42424259;
--switch-active: #2196F3;
--scrollbar-color: #ffffff59;
--solid: #1b2735;
--hover: #757575;
background: radial-gradient(circle, rgba(58, 61, 96, 1) 0%, rgba(45, 40, 51, 1) 100%);
background: radial-gradient(at center bottom, rgb(27, 39, 53) 0%, rgb(9, 10, 15) 100%);;
background-repeat: no-repeat;
}
}
+87
View File
@@ -0,0 +1,87 @@
@import url('/assets/css/themes.css');
.gamebar {
background: var(--background-darker);
z-index: 9;
position: fixed;
bottom: 0;
left: 0;
right: 0;
margin: 40px;
margin-left: 20vw;
margin-right: 20vw;
border-radius: 2vh;
padding: 10px;
display: flex;
box-shadow: 0vh 0.75vh 1.5vh 0vh var(--shadow-color);
backdrop-filter: blur(7.1px);
-webkit-backdrop-filter: blur(7.1px);
}
.gamebar.collapsed {
margin-bottom: calc(-6vh + calc(-40px / 2));
padding-top: 20px;
}
.gamebar .logo {
width: 6vh;
border-radius: 1.5vh;
display: inline-flex;
}
.gamebar .title {
position: absolute;
text-align: center;
font-size: 40px;
width: calc(100% - 20px);
margin-top: calc(calc(calc(6vh - 10px) - 40px) / 2);
}
.gamebar .right {
position: absolute;
margin-top: calc(calc(calc(6vh - 10px) - 40px) / 2);
right: 10px;
}
.gamebar .item {
background: var(--shadow-color);
cursor: pointer;
box-shadow: 0vh 0.75vh 1.5vh 0vh var(--shadow-color);
font-size: 35px;
border-radius: 1vh;
padding: 5px;
}
.gamebar .item:not(:last-of-type) {
margin-right: 10px;
}
.hitbox {
display: none;
position: fixed;
bottom: 0;
left: 0;
right: 0;
margin-left: 20vw;
margin-right: 20vw;
border-top-right-radius: 2vh;
border-top-left-radius: 2vh;
height: calc(6vh + 40px);
}
.hitbox.active {
display: block;
}
iframe {
position: absolute;
width: calc(100vw - 50px);
height: calc(100vh - 50px);
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
border-radius: 2.5vh;
box-shadow: 0vh 0.75vh 1.5vh 0vh var(--shadow-color);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 KiB

After

Width:  |  Height:  |  Size: 1.6 MiB

+13 -52
View File
@@ -1,13 +1,6 @@
import { loadProxyWorker } from './utils.js';
import PolarisError from './error.js';
import { workerLoaded, loadWorker } from './wpm.js';
const tiltEffectSettings = {
max: 8, // max tilt rotation (degrees (deg))
perspective: 1000, // transform perspective, the lower the more extreme the tilt gets (pixels (px))
scale: 1.05, // transform scale - 2 = 200%, 1.5 = 150%, etc..
speed: 800, // speed (transition-duration) of the enter/exit transition (milliseconds (ms))
easing: 'cubic-bezier(.03,.98,.52,.99)' // easing (transition-timing-function) of the enter/exit transition
};
import effects from './effects.js';
const load = () => {
fetch('/assets/JSON/apps.json').then(res => res.json()).then(apps => {
@@ -17,59 +10,27 @@ const load = () => {
el.innerHTML = `<img src='${app.image}'><h3>${app.name}</h3>`;
document.querySelector('.apps').appendChild(el);
effects.hoverTilt({
max: 8,
perspective: 1000,
scale: 1.05,
speed: 800,
easing: 'cubic-bezier(.03,.98,.52,.99)'
}, el);
el.addEventListener('click', async () => {
if (!workerLoaded) await loadWorker();
await loadProxyWorker('uv');
localStorage.setItem('frameData', JSON.stringify({
type: 'app',
app
}));
location.href = '/view';
});
el.addEventListener('mouseenter', appMouseEnter);
el.addEventListener('mousemove', appMouseMove);
el.addEventListener('mouseleave', appMouseLeave);
});
}).catch(e => new PolarisError('Failed to load Apps'));
};
function appMouseEnter(event) {
setTransition(event);
}
function appMouseMove(event) {
const app = event.currentTarget;
const appWidth = app.offsetWidth;
const appHeight = app.offsetHeight;
const centerX = app.offsetLeft + appWidth / 2;
const centerY = app.offsetTop + appHeight / 2;
const mouseX = event.clientX - centerX;
const mouseY = event.clientY - centerY;
const rotateXUncapped = (+1) * tiltEffectSettings.max * mouseY / (appHeight / 2);
const rotateYUncapped = (-1) * tiltEffectSettings.max * mouseX / (appWidth / 2);
const rotateX = rotateXUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max :
(rotateXUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateXUncapped);
const rotateY = rotateYUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max :
(rotateYUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateYUncapped);
app.style.transform = `perspective(${tiltEffectSettings.perspective}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)
scale3d(${tiltEffectSettings.scale}, ${tiltEffectSettings.scale}, ${tiltEffectSettings.scale})`;
}
function appMouseLeave(event) {
event.currentTarget.style.transform = `perspective(${tiltEffectSettings.perspective}px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1)`;
setTransition(event);
}
function setTransition(event) {
const app = event.currentTarget;
clearTimeout(app.transitionTimeoutId);
app.style.transition = `transform ${tiltEffectSettings.speed}ms ${tiltEffectSettings.easing}`;
app.transitionTimeoutId = setTimeout(() => {
app.style.transition = '';
}, tiltEffectSettings.speed);
}
export default {
load
};
};
+22 -64
View File
@@ -1,72 +1,30 @@
import PolarisError from './error.js';
import effects from './effects.js';
const tiltEffectSettings = {
max: 8,
perspective: 1000,
scale: 1.05,
speed: 800,
easing: 'cubic-bezier(.03,.98,.52,.99)'
};
const load = () => fetch('/assets/JSON/cheats.json')
.then(res => res.json())
.then(cheats => cheats.forEach(cheat => {
const el = document.createElement('div');
el.classList = 'game';
el.innerHTML = `<img src='${cheat.image}'><h3>${cheat.name}</h3>`;
document.querySelector('.cheats').appendChild(el);
const load = () => {
fetch('/assets/JSON/cheats.json').then(res => res.json()).then(cheats => {
cheats.forEach(cheat => {
const el = document.createElement('div');
el.classList = 'game';
el.innerHTML = `<img src='${cheat.image}'><h3>${cheat.name}</h3>`;
document.querySelector('.games').appendChild(el);
effects.hoverTilt({
max: 8,
perspective: 1000,
scale: 1.05,
speed: 800,
easing: 'cubic-bezier(.03,.98,.52,.99)'
}, el);
el.addEventListener('click', () => {
localStorage.setItem('frameData', JSON.stringify({
type: 'cheat',
cheat
}));
location.href = '/view';
});
el.addEventListener('mouseenter', gameMouseEnter);
el.addEventListener('mousemove', gameMouseMove);
el.addEventListener('mouseleave', gameMouseLeave);
el.addEventListener('click', () => {
localStorage.setItem('frameData', JSON.stringify({
type: 'cheat',
cheat
}));
location.href = '/view';
});
}).catch(e => new PolarisError('Failed to load cheats.'));
};
function gameMouseEnter(event) {
setTransition(event);
}
function gameMouseMove(event) {
const game = event.currentTarget;
const gameWidth = game.offsetWidth;
const gameHeight = game.offsetHeight;
const centerX = game.offsetLeft + gameWidth / 2;
const centerY = game.offsetTop + gameHeight / 2;
const mouseX = event.clientX - centerX;
const mouseY = event.clientY - centerY;
const rotateXUncapped = (+1) * tiltEffectSettings.max * mouseY / (gameHeight / 2);
const rotateYUncapped = (-1) * tiltEffectSettings.max * mouseX / (gameWidth / 2);
const rotateX = rotateXUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max :
(rotateXUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateXUncapped);
const rotateY = rotateYUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max :
(rotateYUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateYUncapped);
game.style.transform = `perspective(${tiltEffectSettings.perspective}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)
scale3d(${tiltEffectSettings.scale}, ${tiltEffectSettings.scale}, ${tiltEffectSettings.scale})`;
}
function gameMouseLeave(event) {
event.currentTarget.style.transform = `perspective(${tiltEffectSettings.perspective}px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1)`;
setTransition(event);
}
function setTransition(event) {
const game = event.currentTarget;
clearTimeout(game.transitionTimeoutId);
game.style.transition = `transform ${tiltEffectSettings.speed}ms ${tiltEffectSettings.easing}`;
game.transitionTimeoutId = setTimeout(() => {
game.style.transition = '';
}, tiltEffectSettings.speed);
}
})).catch(e => new PolarisError('Failed to load cheats.'));
export default {
load
+359
View File
@@ -0,0 +1,359 @@
/**
* @typedef binding
* @type {object}
* @property {() => {}} binding.remove
*/
/**
* @typedef easterEgg
* @type {object}
* @property {'keybind' | 'click'} easterEgg.type
* @property {string} easterEgg.phrase
* @property {number} easterEgg.clickCount
* @property {object} easterEgg.element
* @property {object} easterEgg.variables
* @property {(binding: binding, variables: ) => Promise} easterEgg.run
* @property {() => {}} easterEgg.preload
*/
const utils = {
easterEggActive: false,
/**
* @param {string} string
* @param {easterEgg['run']} script
*/
createKeybind: (string, script) => {
let keybindString = '';
const listener = window.addEventListener('keydown', async (e) => {
const chars = string.split('');
if (chars.includes(e.key)) {
if (e.key === string.charAt(string.length)) keybindString = string.charAt(string.length);
else keybindString += e.key;
if (keybindString === string && !utils.easterEggActive) {
utils.easterEggActive = true;
try {
await script({
remove: () => window.removeEventListener('keydown', listener, true)
});
utils.easterEggActive = false;
} catch (e) {
utils.easterEggActive = false;
}
keybindString = '';
}
} else keybindString = '';
});
return {
remove: () => window.removeEventListener(listener)
};
}
};
/**
* @type {Array.<easterEgg>}
*/
const easterEggs = [];
easterEggs.push({
type: 'keybind',
phrase: 'smurf',
run: () => {
return new Promise((resolve, reject) => {
const audio = new Audio('/assets/misc/smurf.mp3');
audio.play();
audio.onplay = () => {
const imageElement = document.createElement('img');
imageElement.src = '/assets/img/smurf.jpg';
imageElement.style = `position: fixed;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
z-index: 2147483647;
transition: 0.5s;`;
document.body.appendChild(imageElement);
const overlay = document.createElement('div');
overlay.style = `position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: black;
z-index: 2147483646;`;
document.body.appendChild(overlay);
var flashInterval;
setTimeout(() => {
for (let i = 0; i < 360 * 3; i++) setTimeout(() => imageElement.style.filter = `hue-rotate(${i > 360 ? i - 360 * Math.trunc(i / 360) : i}deg)`, 20 * i);
imageElement.style.animation = '1.06s ease 0s infinite beat';
overlay.style.background = 'white';
flashInterval = setInterval(() => overlay.style.background = overlay.style.background === 'black' ? 'white' : 'black', 460);
}, 7330);
audio.onended = () => {
imageElement.remove();
overlay.remove();
resolve();
}
}
});
}
});
easterEggs.push({
type: 'keybind',
phrase: 'ham',
run: () => {
return new Promise((resolve, reject) => {
const audio = new Audio('/assets/misc/ringtone.mp3');
audio.loop = true;
audio.play();
audio.onplay = () => {
const overlay = document.createElement('div');
overlay.style = `position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: #000;
z-index: 2147483645;`;
document.body.appendChild(overlay);
const menu = document.createElement('div');
menu.style = `position: fixed;
z-index: 2147483646;
top: 0;
bottom: 0;
left: 50%;
-ms-transform: translate(-50%);
transform: translate(-50%);
width: 35%;
background: rgba(255, 255, 255, 0.1);`;
document.body.appendChild(menu);
const caller = document.createElement('div');
caller.innerHTML = `<img src="/assets/img/hamster.jpg" style="position: fixed;
width: 37vh;
height: 37vh;
object-fit: cover;
border-radius: 100%;
top: 10%;
left: 50%;
-ms-transform: translate(-50%);
transform: translate(-50%);"/>
<span style="position: fixed;
display: block;
top: calc(37vh + 15%);
font-size: 5.5vh;
left: 50%;
-ms-transform: translate(-50%);
transform: translate(-50%);">Hamter</span>`;
menu.appendChild(caller);
const call = document.createElement('div');
call.innerHTML = `<img src="/assets/img/hamster.gif" style="position: fixed;
top: 50%;
left: 50%;
height: 100%;
object-fit: cover;
width: 100%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);" />`;
const buttons = document.createElement('div');
buttons.style = `position: fixed;
z-index: 2147483647;
bottom: 10%;
left: 50%;
-ms-transform: translate(-50%);
transform: translate(-50%);
width: auto;
height: auto;
display: flex;`;
menu.appendChild(buttons);
const answer = document.createElement('span');
answer.style = `width: 5vw;
height: 5vw;
display: block;
background: green;
display: flex;
border-radius: 100%;
cursor: pointer;
margin-right: 6vh;`;
answer.innerHTML = `<i class="fa-solid fa-phone" style="font-size: 3vh;
margin: auto;
position: relative;"></i>`;
buttons.appendChild(answer);
const hangUp = document.createElement('span');
hangUp.style = `width: 5vw;
height: 5vw;
display: block;
background: red;
display: flex;
border-radius: 100%;
cursor: pointer;`;
hangUp.innerHTML = `<i class="fa-solid fa-phone-hangup" style="font-size: 3vh;
margin: auto;
position: relative;"></i>`;
buttons.appendChild(hangUp);
answer.addEventListener('click', () => {
answer.remove();
audio.pause();
audio.remove();
caller.remove();
menu.appendChild(call);
});
hangUp.addEventListener('click', () => {
resolve();
audio.pause();
audio.remove();
menu.remove();
overlay.remove();
});
}
});
}
});
easterEggs.push({
type: 'keybind',
phrase: 'polaris',
run: () => {
return new Promise((resolve, reject) => {
document.querySelector('.navbar img').style.animation = 'shake 0.5s';
setTimeout(() => {
document.querySelector('.navbar img').style.animation = '';
resolve();
}, 500);
});
}
});
easterEggs.push({
type: 'keybind',
phrase: 'bruh',
run: () => {
return new Promise((resolve, reject) => {
const audio = new Audio('/assets/misc/bruh.mp3');
audio.play();
const trollFace = document.createElement('img');
trollFace.src = '/assets/img/trollface.png';
trollFace.style = `position: fixed;
z-index: 2147483647;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
height: 0px;`;
var sizeInterval;
audio.onplay = () => {
document.body.appendChild(trollFace);
var counter = 1;
sizeInterval = setInterval(() => {
trollFace.style.height = `${(100 - counter) * counter}px`;
counter += 1;
}, 10);
};
audio.onended = () => {
clearInterval(sizeInterval);
trollFace.remove();
resolve();
};
});
}
});
easterEggs.push({
type: 'keybind',
phrase: 'rick',
run: () => {
return new Promise((resolve, reject) => {
const navbarTitle = document.querySelector('.title');
const title = navbarTitle.querySelector('span');
title.innerHTML = 'Rick <span style="">(spam click the logo)</span>';
const logo = navbarTitle.querySelector('img');
logo.src = '/assets/img/rick.png';
var audioPlaying = false;
var clickTime = 0;
var clicks = 0;
const rick = document.createElement('img');
rick.src = '/assets/img/rick.png';
rick.style = `position: fixed;
bottom: -60px;
right: -60px;
height: 500px;
display: block;
z-index: -99;
transform: rotate(-30deg);`;
document.body.appendChild(rick);
const rickClick = navbarTitle.addEventListener('click', (e) => {
e.preventDefault();
if ((Date.now() - clickTime) < 500) clicks += 1;
else clicks = 0;
if (clicks > 2 && !audioPlaying) {
clicks = 0;
clickTime = 0;
const audio = new Audio('/assets/misc/rickroll.mp3');
audio.play();
audio.onplay = () => {
audioPlaying = true;
};
audio.onended = () => {
audioPlaying = false;
title.innerHTML = 'Polaris <span>by Skool</span>';
logo.src = '/assets/img/logo.png';
navbarTitle.removeEventListener('click', rickClick);
rick.remove();
audio.remove();
resolve();
};
} else clickTime = Date.now();
});
});
}
});
export default () => easterEggs.forEach(easterEgg => {
if (easterEgg.type === 'keybind') {
utils.createKeybind(easterEgg.phrase, easterEgg.run);
try {
easterEgg.preload();
} catch (e) { }
}
});
+79
View File
@@ -0,0 +1,79 @@
/**
* Creates a tilt effect based on the mouse position when it is hovered over
* @param {{ max: number, perspective: number, scale: number, speed: number, easing: 'cubic-bezier(.03,.98,.52,.99)' }} settings
* @param {HTMLDivElement} element
*/
const hoverTilt = (settings, element) => {
const defaultsettings = {
max: 8,
perspective: 1000,
scale: 1.05,
speed: 800,
easing: 'cubic-bezier(.03,.98,.52,.99)'
};
settings = {
...defaultsettings,
...settings
};
const setTransition = (e) => {
const element = e.currentTarget;
clearTimeout(element.transitionTimeoutId);
element.style.transition = `transform ${settings.speed}ms ${settings.easing}`;
element.transitionTimeoutId = setTimeout(() => element.style.transition = '', settings.speed);
};
const listeners = [];
var stopped = false;
const eventHandlers = {
mouseEnter: (e) => {
if (!stopped) setTransition(e)
},
mouseMove: (e) => {
if (!stopped) {
const element = e.currentTarget;
const gameWidth = element.offsetWidth;
const gameHeight = element.offsetHeight;
const centerX = element.offsetLeft + gameWidth / 2;
const centerY = element.offsetTop + gameHeight / 2;
const mouseX = e.clientX - centerX;
const mouseY = e.clientY - centerY;
const rotateXUncapped = (+1) * settings.max * mouseY / (gameHeight / 2);
const rotateYUncapped = (-1) * settings.max * mouseX / (gameWidth / 2);
const rotateX = rotateXUncapped < -settings.max ? -settings.max : (rotateXUncapped > settings.max ? settings.max : rotateXUncapped);
const rotateY = rotateYUncapped < -settings.max ? -settings.max : (rotateYUncapped > settings.max ? settings.max : rotateYUncapped);
element.style.transform = `perspective(${settings.perspective}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(${settings.scale}, ${settings.scale}, ${settings.scale})`;
}
},
mouseLeave: (e) => {
if (!stopped) {
e.currentTarget.style.transform = `perspective(${settings.perspective}px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1)`;
setTransition(e);
}
}
};
if (element) {
listeners.push(element.addEventListener('mouseenter', eventHandlers.mouseEnter));
listeners.push(element.addEventListener('mousemove', eventHandlers.mouseMove));
listeners.push(element.addEventListener('mouseleave', eventHandlers.mouseLeave));
}
return {
events: eventHandlers,
remove: () => {
stopped = true;
listeners.forEach(listener => listener.remove());
}
};
};
export default { hoverTilt };
export { hoverTilt };
-46
View File
@@ -1,46 +0,0 @@
const load = () => {
let frameData = JSON.parse(localStorage.getItem('frameData'));
if (!frameData) location.href = '/';
const iframe = document.querySelector('.frame');
if (frameData.type === 'game') {
if (frameData.game) {
iframe.src = frameData.game.source;
document.querySelector('#gameicon').src = frameData.game.image;
document.querySelector('#gametitle').textContent = frameData.game.name;
} else document.querySelector('#gametitle').textContent = 'Failed to load game.';
} else if (frameData.type === 'app') {
if (frameData.app) {
iframe.src = frameData.app.source;
document.querySelector('#gameicon').src = frameData.app.image;
document.querySelector('#gametitle').textContent = frameData.app.name;
} else document.querySelector('#gametitle').textContent = 'Failed to load app.';
} else if (frameData.type === 'cheat') {
if (frameData.cheat) {
iframe.src = frameData.cheat.source;
document.querySelector('#gameicon').src = frameData.cheat.image;
document.querySelector('#gametitle').textContent = frameData.cheat.name;
} else document.querySelector('#gametitle').textContent = 'Failed to load cheat.';
}
else if (frameData.type === 'proxy') {
if (frameData.source) {
iframe.src = frameData.source;
document.querySelector('#gameicon').src = "https://cdn3.iconfinder.com/data/icons/feather-5/24/search-512.png";
document.querySelector('#gametitle').textContent = "Proxy";
} else document.querySelector('#gametitle').textContent = 'Failed to load proxy.';
} else location.href = '/';
document.querySelector('#fullscreen').addEventListener('click', () => {
const iframe = document.querySelector('.frame');
iframe.style.borderRadius = '0px';
if (iframe.requestFullscreen) iframe.requestFullscreen();
else if (iframe.webkitRequestFullscreen) iframe.webkitRequestFullscreen();
else if (iframe.mozRequestFullScreen) iframe.mozRequestFullScreen();
else if (iframe.msRequestFullscreen) iframe.msRequestFullscreen();
});
};
export default { load };
+81 -139
View File
@@ -1,149 +1,91 @@
import { createViewPage } from './utils.js';
import PolarisError from './error.js';
import { workerLoaded, loadWorker } from './wpm.js';
const tiltEffectSettings = {
max: 8, // max tilt rotation (degrees (deg))
perspective: 1000, // transform perspective, the lower the more extreme the tilt gets (pixels (px))
scale: 1.05, // transform scale - 2 = 200%, 1.5 = 150%, etc..
speed: 800, // speed (transition-duration) of the enter/exit transition (milliseconds (ms))
easing: 'cubic-bezier(.03,.98,.52,.99)' // easing (transition-timing-function) of the enter/exit transition
};
let games = []; // store all games
let filteredGames = []; // store filtered games
import effects from './effects.js';
const load = () => {
fetch('/assets/JSON/games.json').then(res => res.json()).then(data => {
games = data;
filteredGames = games; // initialize filtered games with all games
fetch('/assets/JSON/games.json')
.then(res => res.json())
.then(games => {
const searchBar = document.getElementById('searchInput');
renderGames(filteredGames); // render games initially
searchBar.addEventListener('input', () => {
if (searchBar.value) {
var result = false;
// Add event listener to search input
const searchInput = document.getElementById('searchInput');
searchInput.addEventListener('input', filterGames);
document.querySelectorAll('.games>.game').forEach(game => {
if (game.title.toLowerCase().includes(searchBar.value.toLowerCase())) {
result = true;
game.classList.remove('hidden');
}
else game.classList.add('hidden');
});
if (result) document.querySelector('.searchErr').classList.add('hidden');
else document.querySelector('.searchErr').classList.remove('hidden');
} else {
document.querySelectorAll('.game').forEach(game => game.classList.remove('hidden'));
document.querySelector('.searchErr').classList.add('hidden');
}
});
games.forEach(game => {
const el = document.createElement('div');
el.classList = 'game';
el.innerHTML = `<img loading="lazy" src="${game.image}"><h3>${game.name}</h3>`;
document.querySelector('.games').appendChild(el);
effects.hoverTilt({
max: 8,
perspective: 1000,
scale: 1.05,
speed: 800,
easing: 'cubic-bezier(.03,.98,.52,.99)'
}, el);
if (game.popular) {
const popularEl = document.createElement('div');
popularEl.classList = 'game';
popularEl.innerHTML = `<img loading='lazy' src='${game.image}'><h3>${game.name}</h3>`;
document.querySelector('.popular-games').appendChild(popularEl);
popularEl.addEventListener('click', async () => {
if (URL.canParse(game.target)) createViewPage({
target: game.target,
title: game.name,
proxied: true
});
else createViewPage({
target: game.target,
title: game.name
});
});
effects.hoverTilt({
max: 8,
perspective: 1000,
scale: 1.05,
speed: 800,
easing: 'cubic-bezier(.03,.98,.52,.99)'
}, popularEl);
}
el.addEventListener('click', async () => {
if (URL.canParse(game.target)) createViewPage({
target: game.target,
title: game.name,
proxied: true
});
else createViewPage({
target: game.target,
title: game.name
});
});
});
})
.catch(e => {
new PolarisError('Failed to load games');
});
.catch(e => new PolarisError('Failed to load games'));
};
function filterGames() {
const searchInput = document.getElementById('searchInput');
const searchTerm = searchInput.value.toLowerCase();
filteredGames = games.filter(game => game.name.toLowerCase().includes(searchTerm));
renderGames(filteredGames); // render filtered games
}
function renderGames(gamesToRender) {
const gamesContainer = document.querySelector('.games');
const popularGamesContainer = document.querySelector('.popular-games');
gamesContainer.innerHTML = ''; // clear previous games
popularGamesContainer.innerHTML = ''; // clear previous popular games
function openGameInNewTab(game) {
const x = window.open('about:blank', '_blank');
const index = game.source;
x.document.write(`<iframe src="${index}" style="position:fixed; top:0; left:0; bottom:0; right:0; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden; z-index:999999;"></iframe>`);
}
gamesToRender.forEach(game => {
const el = document.createElement('div');
el.classList = 'game';
el.innerHTML = `<img loading='lazy' src='${game.image}'><h3>${game.name}</h3>`;
gamesContainer.appendChild(el);
if (game.popular === 'yes') {
const popularEl = document.createElement('div');
popularEl.classList = 'game';
popularEl.innerHTML = `<img loading='lazy' src='${game.image}'><h3>${game.name}</h3>`;
popularGamesContainer.appendChild(popularEl);
popularEl.addEventListener('click', async () => {
if (!workerLoaded) await loadWorker();
const frameData = {
type: 'game',
game
};
if (game.openinnewtab === 'yes') {
window.open(game.source, '_blank');
console.log('Open game in new tab:', frameData);
} else if (game.openinaboutblank === 'yes') {
openGameInNewTab(game);
console.log('Open game in about:blank:', frameData);
} else {
localStorage.setItem('frameData', JSON.stringify(frameData));
location.href = '/view';
}
});
popularEl.addEventListener('mouseenter', gameMouseEnter);
popularEl.addEventListener('mousemove', gameMouseMove);
popularEl.addEventListener('mouseleave', gameMouseLeave);
}
el.addEventListener('click', async () => {
if (!workerLoaded) await loadWorker();
const frameData = {
type: 'game',
game
};
if (game.openinnewtab === 'yes') {
window.open(game.source, '_blank');
console.log('Open game in new tab:', frameData);
} else if (game.openinaboutblank === 'yes') {
openGameInNewTab(game);
console.log('Open game in about:blank:', frameData);
} else {
localStorage.setItem('frameData', JSON.stringify(frameData));
location.href = '/view';
}
});
el.addEventListener('mouseenter', gameMouseEnter);
el.addEventListener('mousemove', gameMouseMove);
el.addEventListener('mouseleave', gameMouseLeave);
});
}
function gameMouseEnter(event) {
setTransition(event);
}
function gameMouseMove(event) {
const game = event.currentTarget;
const gameWidth = game.offsetWidth;
const gameHeight = game.offsetHeight;
const centerX = game.offsetLeft + gameWidth / 2;
const centerY = game.offsetTop + gameHeight / 2;
const mouseX = event.clientX - centerX;
const mouseY = event.clientY - centerY;
const rotateXUncapped = (+1) * tiltEffectSettings.max * mouseY / (gameHeight / 2);
const rotateYUncapped = (-1) * tiltEffectSettings.max * mouseX / (gameWidth / 2);
const rotateX = rotateXUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max :
(rotateXUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateXUncapped);
const rotateY = rotateYUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max :
(rotateYUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateYUncapped);
game.style.transform = `perspective(${tiltEffectSettings.perspective}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(${tiltEffectSettings.scale}, ${tiltEffectSettings.scale}, ${tiltEffectSettings.scale})`;
}
function gameMouseLeave(event) {
event.currentTarget.style.transform = `perspective(${tiltEffectSettings.perspective}px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1)`;
setTransition(event);
}
function setTransition(event) {
const game = event.currentTarget;
clearTimeout(game.transitionTimeoutId);
game.style.transition = `transform ${tiltEffectSettings.speed}ms ${tiltEffectSettings.easing}`;
game.transitionTimeoutId = setTimeout(() => {
game.style.transition = '';
}, tiltEffectSettings.speed);
}
export default {
load
};
};
+64 -63
View File
@@ -1,86 +1,87 @@
// Don't touch
import { load } from './settings.js';
import Games from './games.js';
import Apps from './apps.js';
import loadEasterEggs from './eastereggs.js';
import { createViewPage } from './utils.js';
import PolarisError from './error.js';
import Settings from './settings.js';
import Search from './search.js';
import Cheats from './cheats.js';
import Frame from './frame.js';
import PolarisError from './error.js';
import Games from './games.js';
import Apps from './apps.js';
const Settings = {
load: load
};
loadEasterEggs();
onbeforeunload = (e) => {
if (localStorage.getItem('prevent_close') === 'true') {
e.preventDefault();
return e;
}
sessionStorage.clear();
}
/*await navigator.serviceWorker.register('/assets/js/offline.js', {
scope: '/'
});*/
window.onhashchange = () => {
if (location.hash === '#settings') document.querySelector('.sidebar').classList.add('active');
else document.querySelector('.sidebar').classList.remove('active');
};
if (window.self === window.top) {
setTimeout(async () => {
Settings.load();
if (window.self === window.top && location.pathname !== '/view') setTimeout(async () => {
Settings.load();
if (location.pathname === '/games') Games.load();
if (location.pathname === '/apps') Apps.load();
if (location.pathname === '/search') Search.load();
if (location.pathname === '/cheats') Cheats.load();
if (location.pathname === '/view') Frame.load();
}, 500);
}
if (location.pathname === '/games') Games.load();
if (location.pathname === '/apps') Apps.load();
if (location.pathname === '/search') Search.load();
if (location.pathname === '/cheats') Cheats.load();
}, 500);
if (location.pathname === '/') {
fetch('/assets/JSON/games.json').then(res => res.json()).then(games => {
const gameName = 'Tiny Fishing';
const game = games.filter(g => g.name === gameName)[0];
fetch('/assets/JSON/games.json')
.then(res => res.json())
.then(games => {
const gameName = 'Tiny Fishing';
const game = games.filter(g => g.name === gameName)[0];
document.querySelector('.featuredimg').addEventListener('click', () => {
localStorage.setItem('frameData', JSON.stringify({
type: 'game',
game
}));
location.href = '/view';
});
document.querySelector('.featuredimg').src = '/assets/img/wide/tinyfishing.png';
}).catch(e => new PolarisError('Failed to load featured game.'));
fetch('/assets/JSON/changelog.json').then(res => res.json()).then(changelog => changelog.forEach(change => {
const date = document.createElement('p');
date.textContent = change.date;
date.classList = 'small';
document.querySelector('#changelog').appendChild(date);
const descwrap = document.createElement('p');
const description = document.createElement('i');
description.textContent = change.simpleDescription;
description.classList = 'small';
document.querySelector('#changelog').appendChild(description);
}));
/*
var items = ['the start', 'What are you doing here?', '"School"', 'I dont get paid enough','What Up Son?','help','i like bagle','3.14159265359','Who thought this was a good idea?','Stage 4','i have a concerning lump on my back','Bean was here','Your Mother','Pacer Test','Why did he leave','by the way...','Kilroy was here','Kilroy is here','look behind you','West Virginia','theres a reason','Country road','Thats a wrap','Pretty','No','Yes','leave me','What square?','uhhh','Plutocracy','Practically Free*','capitalize this','Place Holder','Try me','fine','Why are we doing this again?','half eaten saltine crackers are underated','Javascript > Java','L + Ratio','Cope','I Love Refrigerators','That Happened.','Pedicure','(insert message here)','terminal','💀💀💀','finnish','who writes these?','reference','I am going to peel the skin off your face (:','bye','no','the fact is','run','uh what','hello world','Positively awful','tax fraud','comatose state','Not me','my second job is a discord mod','kids bop','Is it just me or','Hello people','74% Incomplete','wake up','Monster Energy','ew','The amount of pain I am in right now is unimaginable','chicken','men','What?','Your opinion is invalid','gay pride','Im going','4skin','/0','Who said that?','No Fair.','Famous... Enough','Parent Approved!','Teacher Approved!','Treason','Just do it already!','You\'re Fired','Not worth it','was there a reason?','the egg came first','patriotism','Family Friendly','Do you ever feel like a plastic bag Drifting through the windWanting to start again? Do you ever feel, feel so paper thin Like a house of cards One blow from caving in?','Why?','discord is in the first o','Shane Dawson likes cats','who stole this','unblock linux','darn you','gushers','yummy','charles loves you','mekhi loves anime', 'pls dont type smurf :)'];
document.querySelector('.featured').addEventListener('click', () => {
if (URL.canParse(game.target)) createViewPage({
target: game.target,
title: game.name,
proxied: true
});
else createViewPage({
target: game.target,
title: game.name
});
});
function getRandomFact() {
var randomIndex = Math.floor(Math.random() * items.length);
return items[randomIndex];
}
document.querySelector('.featured').src = '/assets/img/wide/tinyfishing.png';
}).catch(e => new PolarisError('Failed to load featured game.'));
// When the page loads, set the innerHTML of elements with class 'blue' to a random item
window.addEventListener('load', function() {
var blue = document.getElementsByClassName('blue');
for (var i = 0; i < blue.length; i++) {
blue[i].innerHTML = getRandomFact();
}
});
*/
fetch('/assets/JSON/changelog.json')
.then(res => res.json())
.then(changelog => changelog.forEach(change => {
const date = document.createElement('p');
date.textContent = change.date;
date.classList = 'small';
document.querySelector('#changelog').appendChild(date);
const descwrap = document.createElement('p');
const description = document.createElement('i');
description.textContent = change.simpleDescription;
description.classList = 'small';
document.querySelector('#changelog').appendChild(description);
}));
}
const Polaris = { Settings, Games, Apps, Frame, PolarisError };
export default Polaris;
if (window.self === window.top && location.pathname !== '/view') {
if (window.scrollY !== 0) document.querySelector('.navbar').classList.add('scrolling');
else document.querySelector('.navbar').classList.remove('scrolling');
}
if (window.self === window.top && location.pathname !== '/view') window.onscroll = () => {
if (window.scrollY !== 0) document.querySelector('.navbar').classList.add('scrolling');
else document.querySelector('.navbar').classList.remove('scrolling');
}
if (window.self !== window.top && document.querySelector('.navbar')) document.querySelector('.navbar').remove()
//export default { Settings, Games, Apps, Frame, PolarisError };
+15
View File
@@ -0,0 +1,15 @@
// wip
const serverOnline = () => {
return new Promise(async (resolve, reject) => {
try {
await fetch('/');
resolve(true);
} catch { resolve(false); }
});
}
self.addEventListener('fetch', async (e) => {
if (self.navigator.onLine) e.respondWith('offline');
else if (await serverOnline()) e.respondWith('nooo');
});
+131
View File
@@ -0,0 +1,131 @@
import PolarisError from '/assets/js/error.js';
import { loadProxyWorker } from '/assets/js/utils.js';
const tiltEffectSettings = {
max: 8,
perspective: 1000,
scale: 1.05,
speed: 800,
easing: 'cubic-bezier(.03,.98,.52,.99)'
};
let games = [];
let filteredGames = [];
const load = () => {
fetch('/assets/JSON/games.json').then(res => res.json()).then(data => {
games = data;
filteredGames = games;
renderGames(filteredGames);
const searchInput = document.getElementById('searchInput');
searchInput.addEventListener('input', filterGames);
})
.catch(e => new PolarisError('Failed to load games'));
};
function filterGames() {
const searchInput = document.getElementById('searchInput');
const searchTerm = searchInput.value.toLowerCase();
filteredGames = games.filter(game => game.name.toLowerCase().includes(searchTerm));
renderGames(filteredGames);
}
function renderGames(gamesToRender) {
const gamesContainer = document.querySelector('.games');
const popularGamesContainer = document.querySelector('.popular-games');
gamesContainer.innerHTML = '';
popularGamesContainer.innerHTML = '';
gamesToRender.forEach(game => {
const el = document.createElement('div');
el.classList = 'game';
el.innerHTML = `<img loading='lazy' src='${game.image}'><h3>${game.name}</h3>`;
gamesContainer.appendChild(el);
if (game.popular === 'yes') {
const popularEl = document.createElement('div');
popularEl.classList = 'game';
popularEl.innerHTML = `<img loading='lazy' src='${game.image}'><h3>${game.name}</h3>`;
popularGamesContainer.appendChild(popularEl);
popularEl.addEventListener('click', async () => {
await loadProxyWorker('uv');
if (game.openinnewtab === 'yes') window.open(game.source);
else {
localStorage.setItem('frameData', JSON.stringify({
type: 'game',
game
}));
location.href = '/view';
}
});
popularEl.addEventListener('mouseenter', gameMouseEnter);
popularEl.addEventListener('mousemove', gameMouseMove);
popularEl.addEventListener('mouseleave', gameMouseLeave);
}
el.addEventListener('click', async () => {
await loadProxyWorker();
const frameData = {
type: 'game',
game
};
if (game.openinnewtab === 'yes') {
window.open(game.source, '_blank');
console.log('Open game in new tab:', frameData);
} else {
localStorage.setItem('frameData', JSON.stringify(frameData));
location.href = '/view';
}
});
el.addEventListener('mouseenter', gameMouseEnter);
el.addEventListener('mousemove', gameMouseMove);
el.addEventListener('mouseleave', gameMouseLeave);
});
}
function gameMouseEnter(event) {
setTransition(event);
}
function gameMouseMove(event) {
const game = event.currentTarget;
const gameWidth = game.offsetWidth;
const gameHeight = game.offsetHeight;
const centerX = game.offsetLeft + gameWidth / 2;
const centerY = game.offsetTop + gameHeight / 2;
const mouseX = event.clientX - centerX;
const mouseY = event.clientY - centerY;
const rotateXUncapped = (+1) * tiltEffectSettings.max * mouseY / (gameHeight / 2);
const rotateYUncapped = (-1) * tiltEffectSettings.max * mouseX / (gameWidth / 2);
const rotateX = rotateXUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max : (rotateXUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateXUncapped);
const rotateY = rotateYUncapped < -tiltEffectSettings.max ? -tiltEffectSettings.max : (rotateYUncapped > tiltEffectSettings.max ? tiltEffectSettings.max : rotateYUncapped);
game.style.transform = `perspective(${tiltEffectSettings.perspective}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(${tiltEffectSettings.scale}, ${tiltEffectSettings.scale}, ${tiltEffectSettings.scale})`;
}
function gameMouseLeave(event) {
event.currentTarget.style.transform = `perspective(${tiltEffectSettings.perspective}px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1)`;
setTransition(event);
}
function setTransition(event) {
const game = event.currentTarget;
clearTimeout(game.transitionTimeoutId);
game.style.transition = `transform ${tiltEffectSettings.speed}ms ${tiltEffectSettings.easing}`;
game.transitionTimeoutId = setTimeout(() => game.style.transition = '', tiltEffectSettings.speed);
}
export default {
load
};
+10 -29
View File
@@ -1,39 +1,20 @@
import { workerLoaded, loadWorker } from './wpm.js';
import { createViewPage } from './utils.js';
const load = () => {
let xor = {
encode: (str, key = 2) => {
if (!str) return str;
return encodeURIComponent(str.split('').map((e, i) => i % key ? String.fromCharCode(e.charCodeAt(0) ^ key) : e).join(''));
},
decode: (str, key = 2) => {
if (!str) return str;
return decodeURIComponent(str).split('').map((e, i) => i % key ? String.fromCharCode(e.charCodeAt(0) ^ key) : e).join('');
}
};
window.xor = xor;
const form = document.querySelector('#wpf');
const query = document.querySelector('#query');
form.addEventListener('submit', async (e) => {
e.preventDefault();
if (typeof navigator.serviceWorker === 'undefined') new PolarisError('Failed to load Prxxy');
if (!workerLoaded) await loadWorker();
const url = /^(http(s)?:\/\/)?([\w-]+\.)+[\w]{2,}(\/.*)?$/.test(query.value) ?
((!query.value.startsWith('http://') && !query.value.startsWith('https://')) ? 'https://' + query.value : query.value) :
'https://www.google.com/search?q=' + encodeURIComponent(query.value);
const frameData = {
type: 'proxy',
source: `/service/${xor.encode(url)}`
};
localStorage.setItem('frameData', JSON.stringify(frameData));
location.href = '/view';
const url = /^(http(s)?:\/\/)?([\w-]+\.)+[\w]{2,}(\/.*)?$/.test(query.value) ? ((!query.value.startsWith('http://') && !query.value.startsWith('https://')) ? 'https://' + query.value : query.value) : 'https://www.google.com/search?q=' + encodeURIComponent(query.value);
createViewPage({
target: url,
proxied: true,
title: 'Search Results'
});
});
}
export default { load };
export default { load };
+3 -3
View File
@@ -1,5 +1,5 @@
import Theme from './themes.js';
import PolarisError from './error.js';
import Theme from './themes.js';
const isScrollable = (element) => element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight;
@@ -96,7 +96,7 @@ class Settings {
document.querySelector('#panic_key').value = e.key;
this.set('panic_key', document.querySelector('#panic_key').value);
} else {
if (e.key == this.get('panic_key')) {
if (e.key === this.get('panic_key')) {
if (this.get('panic_url')) window.location.href = this.get('panic_url');
else new PolarisError('A panic key was used but no url was found.');
}
@@ -205,4 +205,4 @@ const load = () => {
new Settings();
};
export { load, Settings };
export default { load, Settings };
+26 -103
View File
@@ -1,111 +1,34 @@
const set = (name, value) => {
if (!localStorage.getItem('settings')) {
localStorage.setItem('settings', JSON.stringify({}));
} else {
try {
JSON.parse(localStorage.getItem('settings'));
} catch (e) {
localStorage.setItem('settings', JSON.stringify({}));
}
}
import { storage } from './utils.js';
const settings = JSON.parse(localStorage.getItem('settings'));
settings[name] = value;
localStorage.setItem('settings', JSON.stringify(settings));
};
const get = (name) => {
if (!localStorage.getItem('settings')) {
localStorage.setItem('settings', JSON.stringify({}));
} else {
try {
JSON.parse(localStorage.getItem('settings'));
} catch (e) {
localStorage.setItem('settings', JSON.stringify({}));
}
}
const settings = JSON.parse(localStorage.getItem('settings'));
return settings[name];
}
const settingsStorage = storage('settings');
class Theme {
constructor() {
this.theme = get('theme');
constructor() {
this.theme = settingsStorage.get('theme');
if (this.theme) {
this.set(this.theme);
} else {
this.set('system default');
}
}
set = (theme, save) => {
document.body.setAttribute('data-theme', theme);
if (save !== false) {
set('theme', theme);
}
}
}
// Define a variable to track whether the audio has been played
let audioPlayed = false;
// Function to play the audio and display the image
function playSmurfAudio() {
if (!audioPlayed) {
const audio = new Audio('/assets/misc/smurf.mp3');
audio.play();
audioPlayed = true;
// Display the image
const imageElement = document.createElement('img');
imageElement.src = '/assets/img/smurf.jpg';
document.body.appendChild(imageElement);
// Delay theme change by 7 seconds
setTimeout(() => {
let themeToggleInterval = setInterval(() => {
// Toggle between light and dark themes
if (document.body.getAttribute('data-theme') === 'flamingo') {
document.body.setAttribute('data-theme', 'light');
} else {
document.body.setAttribute('data-theme', 'flamingo');
}
}, 300);
// Stop changing the theme when the audio ends
audio.onended = () => {
clearInterval(themeToggleInterval);
document.body.setAttribute('data-theme', 'dark');
// Remove the image when the audio ends
document.body.removeChild(imageElement);
};
}, 7000);
if (this.theme) this.set(this.theme);
else this.set('system-default');
}
/**
* Set the theme of the page
* @param {string} theme The name of the theme
* @param {boolean} save Whether or not the theme should be saved
*/
set = (theme, save) => {
document.body.setAttribute('data-theme', theme);
this.theme = theme;
if (save !== false) settingsStorage.set('theme', theme);
};
/**
* Get the current theme
* @returns {string}
*/
get = () => {
return document.body.getAttribute('data-theme');
};
}
// Event listener to check for the word "smurf"
document.addEventListener('keydown', (event) => {
if (event.key === 's' || event.key === 'm' || event.key === 'u' || event.key === 'r' || event.key === 'f') {
// Add the pressed key to a string and check if it matches "smurf"
if (event.key === 's') {
smurfString = 's';
} else {
smurfString += event.key;
}
if (smurfString === 'smurf') {
playSmurfAudio();
}
} else {
smurfString = ''; // Reset the string if a different key is pressed
}
});
// Variable to store the string as it's being typed
let smurfString = '';
export default new Theme();
+141
View File
@@ -0,0 +1,141 @@
/**
* The storage interface for polaris
* @param {string} containerName
*/
const storage = (containerName) => {
return {
/**
* Get a value from the storage container
* @param {string} name The name of the value
* @returns {string}
*/
get: (name) => {
if (!localStorage.getItem(containerName)) localStorage.setItem(containerName, JSON.stringify({}));
else {
try {
JSON.parse(localStorage.getItem(containerName));
} catch (e) {
localStorage.setItem(containerName, JSON.stringify({}));
}
}
const container = JSON.parse(localStorage.getItem(containerName));
return container[name];
},
/**
* Set a value from a storage container
* @param {string} name The name of the value
* @param {string | object} value The value to be set
*/
set: (name, value) => {
if (!localStorage.getItem(containerName)) localStorage.setItem(containerName, JSON.stringify({}));
else {
try {
JSON.parse(localStorage.getItem(containerName));
} catch (e) {
localStorage.setItem(containerName, JSON.stringify({}));
}
}
const container = JSON.parse(localStorage.getItem(containerName));
container[name] = value;
localStorage.setItem(containerName, JSON.stringify(container));
}
};
};
/**
* Register a proxy service worker
* @param {'uv' | 'dynamic'} proxy
*/
const loadProxyWorker = async (proxy) => await navigator.serviceWorker.register(`/${proxy}/sw.js`, {
scope: `/${proxy}/service/`
});
/**
Broken
* Get the current encoding method
* @param {'uv' | 'dynamic'} proxy
* @returns {Promise.<string>}
const getEncodingMethod = (proxy) => {
return new Promise(async (resolve, reject) => {
const config = await(await fetch(`/${proxy}/${proxy}.config.js`)).text();
const Ultraviolet = {
codec: {
xor: {},
base64: {},
plain: {}
}
};
eval(config);
const encodingConfig = String(self[`_${proxy}$config`][proxy === 'uv' ? 'encodeUrl' : (proxy === 'dynamic' ? 'encoding' : '')]);
if (proxy === 'uv') resolve(encodingConfig.replace('Ultraviolet.codec.', '').replace('.encode', ''));
else if (proxy === 'dynamic') resolve(encodingConfig);
});
}*/
/**
* WIP
*
* Load the page javascript
*/
const loadPageScript = () => {
if (location.href) {
}
};
const encoder = {
b64: {
encode: (data) => btoa(data),
decode: (data) => atob(data)
},
xor: {
encode: (data, key = 2) => encodeURIComponent(data.split('').map((e, i) => i % key ? String.fromCharCode(e.charCodeAt(0) ^ key) : e).join('')),
decode: (data, key = 2) => decodeURIComponent(data).split('').map((e, i) => i % key ? String.fromCharCode(e.charCodeAt(0) ^ key) : e).join('')
}
};
/**
* Redirect to an external url
* @param {string} target
* @param {{ trusted: boolean }} options
*/
const redirect = (target, options) => location.href = `/view?load=${btoa(JSON.stringify({
target,
redirect: true,
trusted: options.trusted
}))}`;
/**
* Load a url into the view page
* @param {{ target: string, title: string, return: string, proxied: boolean }} options
*/
const createViewPage = (options) => location.href = `/view?load=${btoa(JSON.stringify({
return: options.return || location.href,
proxied: options.proxied,
target: options.target,
title: options.title
}))}`;
export default {
storage,
loadProxyWorker,
encoder,
redirect,
createViewPage
};
export {
storage,
loadProxyWorker,
encoder,
redirect,
createViewPage
};
+68
View File
@@ -0,0 +1,68 @@
import { loadProxyWorker, encoder } from './utils.js';
const params = new URLSearchParams(location.search);
window.history.replaceState({}, '', location.pathname);
if (params.get('load')) {
try {
const parsedData = JSON.parse(atob(params.get('load')));
if (Boolean(parsedData.target && parsedData.title && parsedData.return)) {
document.body.classList.remove('hidden');
sessionStorage.setItem('loaddata', JSON.stringify(parsedData));
if (parsedData.proxied) {
await loadProxyWorker('uv');
document.querySelector('iframe').src = '/uv/service/' + encoder['xor'].encode(parsedData.target);
} else document.querySelector('iframe').src = parsedData.target;
document.querySelector('iframe').addEventListener('load', () => {
document.querySelector('.title').textContent = parsedData.title;
document.querySelector('iframe').style.transition = 'none';
document.querySelector('iframe').style.background = '#fff';
document.querySelector('iframe').contentWindow.addEventListener('mouseover', () => {
document.querySelector('.gamebar').classList.add('collapsed');
document.querySelector('.hitbox').classList.remove('active');
});
document.querySelector('iframe').contentWindow.addEventListener('mouseout', () => {
document.querySelector('.gamebar').classList.remove('collapsed');
document.querySelector('.hitbox').classList.add('active');
});
if (document.querySelector('iframe').matches(':hover')) setTimeout(() => {
document.querySelector('.gamebar').classList.remove('collapsed');
document.querySelector('.hitbox').classList.add('active');
}, 1000);
});
document.querySelector('#fullscreen').addEventListener('click', () => {
const iframe = document.querySelector('iframe');
if (iframe.requestFullscreen) iframe.requestFullscreen();
else if (iframe.webkitRequestFullscreen) iframe.webkitRequestFullscreen();
else if (iframe.mozRequestFullScreen) iframe.mozRequestFullScreen();
else if (iframe.msRequestFullscreen) iframe.msRequestFullscreen();
});
window.addEventListener('fullscreenchange', () => {
if (document.fullscreenElement) document.querySelector('iframe').style.borderRadius = '0px';
else document.querySelector('iframe').style.borderRadius = '';
});
document.querySelector('#return').addEventListener('click', () => location.href = parsedData.return);
} else if (parsedData.target && parsedData.redirect === true) {
window.history.replaceState({}, '', '/redirect');
if (parsedData.trusted) window.location.replace(parsedData.target);
else {
document.documentElement.textContent = `Redirecting to ${parsedData.target}`;
setTimeout(() => window.location.replace(parsedData.target), 1000);
}
} else window.location.replace(parsedData.return || '/');
} catch (e) { alert(e); window.location.replace('/'); }
} else if (sessionStorage.getItem('loaddata')) window.location.replace(`/view?load=${btoa(sessionStorage.getItem('loaddata'))}`);
else window.location.replace('/');
-25
View File
@@ -1,25 +0,0 @@
let workerLoaded = false;
let chosenProxy = 'uv'; // dynamic is broken so dont change this
let loadWorker = async (worker) => {
let allWorkers = await navigator.serviceWorker.getRegistrations();
allWorkers.forEach(worker => {
if (!worker.active?.scriptURL?.includes(chosenProxy)) worker.unregister();
});
await navigator.serviceWorker.register(`/${worker || chosenProxy}-sw.js`, {
scope: `/service/`,
});
};
(async () => {
await loadWorker();
workerLoaded = true;
})();
window.loadWorker = loadWorker;
export {
workerLoaded,
loadWorker
};
Binary file not shown.
Binary file not shown.
Binary file not shown.
+35
View File
@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!--el:meta-->
<!--el:adtop-->
<!--el:analytics-->
<link rel="stylesheet" href="/assets/css/main.css">
<title>Cheats | Polaris</title>
</head>
<body class="centered">
<!--el:navbar-->
<!--el:sidebar-->
<div class="content">
<h1>Cheats</h1>
<br>
<div class="cheats"></div>
</div>
<!--el:ad_horizontal-->
<!--el:ad_horizontal-->
<script src="/assets/js/main.js" type="module"></script>
<!--el:{{mode === 'dev'}}:development-->
</body>
</html>
+33
View File
@@ -0,0 +1,33 @@
<!--WIP-->
<!DOCTYPE html>
<html lang="en">
<head>
<!--el:meta-->
<!--el:adtop-->
<!--el:analytics-->
<link rel="stylesheet" href="/assets/css/main.css">
<title>Server Downtime | Polaris</title>
</head>
<body>
<!--el:navbar-->
<!--el:sidebar-->
<div class="container centered">
<h1 style="font-size: 50px;">Oh no!</h1>
<p>
We slipped up! Polaris's servers are currently down and we are working hard to fix them!
<br>
For more information on the downtime join our <a href="https://discord.gg/skool-community-950407933408198717" target="_blank" class="link">discord server</a>.
</p>
</div>
<!--el:{{mode === 'dev'}}:development-->
</body>
</html>
-2
View File
@@ -1,5 +1,3 @@
// See documentation for more information
self.__dynamic$config = {
prefix: '/service/',
encoding: 'xor',
+50
View File
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!--el:meta-->
<!--el:adtop-->
<!--el:analytics-->
<link rel="stylesheet" href="/assets/css/main.css">
<title>Games | Polaris</title>
</head>
<body>
<!--el:navbar-->
<!--el:sidebar-->
<div class="content centered">
<h1 style="font-size: 6vh;">Games</h1>
<h1 style="font-size: 4vh;" class="gamesectionheader">Popular</h1>
<div class="popular-games">
</div>
<h1 style="font-size: 4vh;" class="gamesectionheader">All Games</h1>
<input type="text" id="searchInput" placeholder="Search Games...">
<!--el:ad_horizontal-->
<!--el:ad_horizontal-->
<br>
<br>
<div class="games">
</div>
<div class="searchErr hidden">
<h1>¯\(°_o)/¯</h1>
<br>
<p>Oops, we couldn't find the game you were looking for.</p>
</div>
<script src="/assets/js/main.js" type="module"></script>
<!--el:{{mode === 'dev'}}:development-->
</body>
</html>
+55
View File
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!--el:meta-->
<!--el:adtop-->
<!--el:analytics-->
<link rel="stylesheet" href="/assets/css/main.css">
<title>Polaris</title>
</head>
<body>
<!--el:navbar-->
<!--el:sidebar-->
<div class="row mainpage">
<div class="container">
<h1 class="nomargin">Featured Game</h1>
<img class="featured" data-link="true" />
</div>
<div class="container right">
<h1>Polaris</h1>
<p>
<a href="https://discord.gg/skool-community-950407933408198717" target="_blank" class="link">Discord</a>
-
<a href="https://skoolworld.org" target="_blank" class="link">Links</a>
-
<a href="mailto:support@polarislearning.org" target="_blank" class="link">Support Email</a>
-
<a href="https://forms.gle/9knPLmyAua5Z3wZv5" target="_blank" class="link">Suggest a game</a>
-
<a href="/privacy" class="link">Privacy Policy</a>
-
<a href="/tos" class="link">Terms of Service</a>
</p>
<hr>
<h2>Changelog</h2>
<div id="changelog"></div>
</div>
</div>
<script src="/assets/js/main.js" type="module"></script>
<!--el:{{mode === 'dev'}}:development-->
</body>
</html>
+50
View File
@@ -0,0 +1,50 @@
<!--WIP-->
<!DOCTYPE html>
<html lang="en">
<head>
<!--el:meta-->
<!--el:adtop-->
<!--el:analytics-->
<link rel="stylesheet" href="/assets/css/main.css">
<title>Offline | Polaris</title>
</head>
<body>
<!--el:sidebar-->
<div class="container centered">
<h1 style="font-size: 50px;">Offline</h1>
<p>Looks you're offline. Connect to the internet to access polaris.</p>
</div>
<script>
try { document.body.dataset.theme = JSON.parse(localStorage.getItem('settings')).theme || 'system-default'; }
catch {
document.body.dataset.theme = 'system-default';
sessionStorage.setItem('settings', JSON.stringify({
theme: 'system-default'
}));
}
sessionStorage.setItem('wasoffline', !window.navigator.onLine);
if (sessionStorage.getItem('wasoffline') === 'true') {
sessionStorage.setItem('wasoffline', false);
window.location.replace('/');
} else (async () => {
document.documentElement.innerHTML = await (await fetch('/404')).text();
})();
window.addEventListener('online', () => window.location.replace('/'));
</script>
<!--el:{{mode === 'dev'}}:development-->
</body>
</html>
@@ -1,3 +1,6 @@
<!--el:meta-->
<!--el:analytics-->
By using our site your personal information may be collected including:
- email address
@@ -10,3 +13,5 @@ We do not store your personal information outside of advertising services and ou
Our sites code is open source and is hosted on github, it can be found here: https://github.com/Skoolgq
If you have any questions please contact us at skoolwrld@gmail.com
<!--el:{{mode === 'dev'}}:development-->
+37
View File
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!--el:meta-->
<!--el:adtop-->
<!--el:analytics-->
<link rel="stylesheet" href="/assets/css/main.css">
<title>Search | Polaris</title>
</head>
<body>
<!--el:navbar-->
<!--el:sidebar-->
<div class="content">
<div class="container centered">
<h1 class="title">Proxy</h1>
<text class="proxyDescription">You can search anything.</text>
<form id="wpf">
<input class="proxyinput" type="text" id="query" placeholder="URL or Search Query" />
</form>
</div>
</div>
<script src="/assets/js/main.js" type="module"></script>
<!--el:ad_horizontal-->
<!--el:ad_horizontal-->
<!--el:{{mode === 'dev'}}:development-->
</body>
</html>
+1910
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -4,4 +4,4 @@ importScripts('/uv/uv.sw.js');
const sw = new UVServiceWorker();
self.addEventListener('fetch', (event) => event.respondWith(sw.fetch(event)));
self.addEventListener('fetch', (event) => event.respondWith(sw.fetch(event)));
+7 -9
View File
@@ -1,13 +1,11 @@
// This file overwrites the stock UV config.js
self.__uv$config = {
prefix: "/service/",
bare: "/bare/",
prefix: '/uv/service/',
bare: '/bare/',
encodeUrl: Ultraviolet.codec.xor.encode,
decodeUrl: Ultraviolet.codec.xor.decode,
handler: "/uv/uv.handler.js",
client: "/uv/uv.client.js",
bundle: "/uv/uv.bundle.js",
config: "/uv/uv.config.js",
sw: "/uv/uv.sw.js",
handler: '/uv/uv.handler.js',
client: '/uv/uv.client.js',
bundle: '/uv/uv.bundle.js',
config: '/uv/uv.config.js',
sw: '/uv/uv.sw.js',
};
+44
View File
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!--el:meta-->
<!--el:adtop-->
<!--el:analytics-->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="stylesheet" href="/assets/css/view.css">
<title>View | Polaris</title>
</head>
<body class="hidden">
<iframe frameborder="0"></iframe>
<div class="gamebar">
<a href="/">
<img src="/assets/img/logo.png" class="logo">
</a>
<h1 class="title">Loading...</h1>
<div class="right">
<span class="item" id="return">
<i class="fa-solid fa-chevron-left"></i>
</span>
<span class="item" id="fullscreen">
<i class="fa-regular fa-expand"></i>
</span>
</div>
</div>
<div class="hitbox"></div>
<script src="/assets/js/view.js" type="module"></script>
<script src="/assets/js/main.js" type="module"></script>
<!--el:{{mode === 'dev'}}:development-->
</body>
</html>
+11
View File
@@ -0,0 +1,11 @@
<script type="text/javascript">
atOptions = {
'key': 'ae1638b56336895e2ecf7d1adc3492a4',
'format': 'iframe',
'height': 50,
'width': 320,
'params': {}
};
document.write('<scr' + 'ipt type="text/javascript" src="//outrightsham.com/ae1638b56336895e2ecf7d1adc3492a4/invoke.js"></scr' + 'ipt>');
</script>
+3
View File
@@ -0,0 +1,3 @@
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9661054437111080" crossorigin="anonymous"></script>
<script data-cfasync="false" async src="https://s.nitropay.com/ads-1751.js"></script>
<script data-cfasync="false">window.nitroAds = window.nitroAds || { createAd: function () { return new Promise(e => { window.nitroAds.queue.push(["createAd", arguments, e]) }) }, addUserToken: function () { window.nitroAds.queue.push(["addUserToken", arguments]) }, queue: [] };</script>
+10
View File
@@ -0,0 +1,10 @@
<script src="https://cdn.counter.dev/script.js" data-id="b0b2d4b2-daca-47e1-9287-b9e649b3dcd2" data-utcoffset="-5"></script>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-KZRKZE212Q"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'G-KZRKZE212Q');
</script>
<script src="https://polaris4.statuspage.io/embed/script.js"></script>
+5
View File
@@ -0,0 +1,5 @@
<script src="https://unpkg.com/eruda@latest/eruda.js"></script>
<script>
eruda.init();
</script>
+3
View File
@@ -0,0 +1,3 @@
<footer>
<!--May add this later-->
</footer>
+9 -6
View File
@@ -1,14 +1,17 @@
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="language" content="English">
<meta name="google" content="notranslate">
<meta name="charset" content="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Polaris">
<meta name="subject" content="unblocking">
<meta name="description" content="the future of school sites; bringing games, apps, proxies, advanced settings, and more.">
<meta name="author" content="Skool">
<meta name="description" content="The professional unblocked gaming site.">
<meta name="author" content="Polaris Development Group">
<meta name="og:type" content="website">
<meta name="og:url" content="https://polarislearning.org/">
<meta name="og:title" content="Polaris">
<meta name="og:description" content="the future of school sites; bringing games, apps, proxies, advanced settings, and more.">
<meta name="og:image" content="https://polarislearning.org/assets/img/logo.png">
<meta name="keywords" content="unblock, unblocked, unblocking, skool, skoolgq, skool game, skool app, skool roblox, skool github, skool tv, skool home, old skool, skoolgq, skool.gq, skool.world, skool.lol, skool hq, games, gaming, games unblocked, unblocked games, proxy, holy unblocker, titanium network, free games, online games, skool discord, chromebook unblocked, unblocked chromebook, school cheats, schoolcheats, school hacks, ezpuzzle hack, blooket hack, school hacks working, gimkit hack, polaris games, polaris apps, polaris cheats, autoclicker school, prodigy hack, quizizz hack, quizlet hack, discord unblocked, unblocked discord, tiktok unblocked, unblocked tiktok, twitch unblocked, unblocked twitch, youtube unblocked, unblocked youtube">
<meta name="og:description" content="The professional unblocked gaming site.">
<meta name="og:image" content="https://polarislearning.org/assets/img/logo.png">
+7 -56
View File
@@ -1,66 +1,17 @@
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-KZRKZE212Q"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-KZRKZE212Q');
</script>
<div class="navbar">
<a class="title" href="/">
<img src="/assets/img/logo.png" loading="eager" />
<span>Polaris<span>By Skool</span></span>
<img src="/assets/img/logo.png" />
<span>Polaris
<span>By Skool</span>
</span>
</a>
<div class="end">
<div class="right">
<a href="/games"><i class="fa-solid fa-gamepad-modern fa-xs"></i>Games</a>
<a href="/apps"><i class="fa-solid fa-rocket-launch fa-xs"></i>Apps</a>
<a href="/search"><i class="fa-solid fa-magnifying-glass fa-xs"></i>Proxy</a>
<a href="/cheats"><i class="fa-solid fa-computer fa-xs"></i>Cheats</a>
<a href="#settings" data-link="true" data-attr="sidebar_trigger"><i class="fa-solid fa-gear fa-sm"></i>Settings</a>
</div>
</div>
<div class="sidebar">
<div class="scroll">
<i class="fa-solid fa-chevron-down"></i>
</div>
<h1>Settings</h1>
<h3>Panic Key</h3>
<input class="settings-input" type="text" name="Panic Key" id="panic_key" value="No Key Selected" readonly />
<button class="settings-button" id="reset_panic">Reset</button>
<br>
<h3>Panic URL</h3>
<input class="settings-input" type="url" id="panic_url" placeholder="eg: https://google.com" />
<br>
<h3>Theme</h3>
<div id="themes">
<button class="settings-button">System Default</button>
<button class="settings-button">Dark</button>
<button class="settings-button">Light</button>
<button class="settings-button">Flamingo</button>
<button class="settings-button">Frost</button>
<button class="settings-button">Crimson</button>
<button class="settings-button">Inferno</button>
<button class="settings-button">Indigo</button>
<button class="settings-button">Violet</button>
</div>
<h3>Tab Cloak</h3>
<select id="cloak_select">
<option value="none">None</option>
<option value="custom">Custom</option>
<option value="canvas">Canvas Dashboard</option>
<option value="google">Google</option>
<option value="classroom">Google Classroom</option>
</select>
<div class="hidden" id="custom_cloak">
<input class="settings-input" type="text" placeholder="Title" id="title" />
<input class="settings-input" type="text" placeholder="eg: google.com" id="domain" />
</div>
<br>
<br>
</div>
<script src="https://polaris4.statuspage.io/embed/script.js"></script>
</div>
+48
View File
@@ -0,0 +1,48 @@
<div class="sidebar">
<div class="scroll">
<i class="fa-solid fa-chevron-down"></i>
</div>
<h1>Settings</h1>
<h3>Panic Key</h3>
<input class="settings-input" type="text" name="Panic Key" id="panic_key" value="No Key Selected" readonly />
<button class="settings-button" id="reset_panic">Reset</button>
<br>
<h3>Panic URL</h3>
<input class="settings-input" type="url" id="panic_url" placeholder="eg: https://google.com" />
<br>
<h3>Theme</h3>
<div id="themes">
<button class="settings-button">Dark</button>
<button class="settings-button">Light</button>
<button class="settings-button">Flamingo</button>
<button class="settings-button">Frost</button>
<button class="settings-button">Crimson</button>
<button class="settings-button">Inferno</button>
<button class="settings-button">Indigo</button>
<button class="settings-button">Violet</button>
</div>
<h3>Tab Cloak</h3>
<select id="cloak_select">
<option value="none">None</option>
<option value="custom">Custom</option>
<option value="canvas">Canvas Dashboard</option>
<option value="google">Google</option>
<option value="classroom">Google Classroom</option>
</select>
<div class="hidden" id="custom_cloak">
<input class="settings-input" type="text" placeholder="Title" id="title" />
<input class="settings-input" type="text" placeholder="eg: google.com" id="domain" />
</div>
</div>
+2 -2
View File
@@ -1,11 +1,11 @@
{
"version": 2,
"builds": [{
"src": "index.js",
"src": "server/index.js",
"use": "@vercel/node"
}],
"routes": [{
"src": "/(.*)",
"dest": "index.js"
"dest": "server/index.js"
}]
}