preparing for 2024 update
Co-authored-by: Cobalt-60 <plastics-eater@users.noreply.github.com>
This commit is contained in:
+2
-5
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "polaris",
|
||||
"version": "1.0.0",
|
||||
"description": "The future of school gaming",
|
||||
"description": "The professional unblocked games site.",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
@@ -9,7 +9,7 @@
|
||||
"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": "*",
|
||||
@@ -21,8 +21,5 @@
|
||||
"jsdom": "^23.0.1",
|
||||
"mime": "*",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
+33
-7
@@ -2,21 +2,47 @@
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!--el:meta-->
|
||||
<!--el:adtop-->
|
||||
<!--el:analytics-->
|
||||
|
||||
<title>Loading...</title>
|
||||
<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>
|
||||
navigator.serviceWorker.register('/assets/ultraviolet/sw.js', {
|
||||
scope: __uv$config.prefix
|
||||
}).then(e => location.reload()).catch(e => { });
|
||||
<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>
|
||||
+1
-1
@@ -7,6 +7,6 @@ export default {
|
||||
port: 8080,
|
||||
mode: 'dev',
|
||||
minify: false,
|
||||
assetScrambling: true,
|
||||
assetScrambling: false,
|
||||
allowDangerousTemplateInsert: true
|
||||
};
|
||||
+16
-8
@@ -18,6 +18,11 @@ const mode = (process.argv[2] === 'prod' || process.argv[2] === 'dev' ? process.
|
||||
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) => {
|
||||
@@ -38,6 +43,12 @@ app.get('/cdn/*', cors({
|
||||
} 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 {
|
||||
@@ -67,14 +78,11 @@ app.get('/asset/:token', async (req, res, next) => {
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/uv/service*', async (req, res) => {
|
||||
res.end(await rewriter.html(fs.readFileSync(path.join(__dirname, './pages/uv_404.html'))));
|
||||
res.setHeader('Service-Worker-Allowed', 'true');
|
||||
});
|
||||
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 {
|
||||
//if (req.path === '/index') res.redirect('/');
|
||||
//else {
|
||||
const {
|
||||
exists,
|
||||
path: filePath
|
||||
@@ -94,7 +102,7 @@ app.use(async (req, res, next) => {
|
||||
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) => {
|
||||
@@ -107,4 +115,4 @@ server.on('upgrade', (req, socket, head) => {
|
||||
else socket.end();
|
||||
});
|
||||
|
||||
server.listen(port, () => console.log(`Polaris listening\n\nPort: ${server.address().port}\nMode: ${mode}\nNode.js: ${process.version}`));
|
||||
server.listen(port, () => console.log(`Polaris running\n\nPort: ${server.address().port}\nMode: ${mode}\nNode.js: ${process.version}`));
|
||||
+29
-11
@@ -46,7 +46,7 @@ const html = (data) => {
|
||||
|
||||
const templates = await templateParser(data);
|
||||
|
||||
templates.forEach(template => htmlData = htmlData.replace(`<!--el:${template.name}-->`, template.file));
|
||||
for (let i = 0; i < templates.length; i++) htmlData = htmlData.replace(`<!--el:${templates[i].name}-->`, templates[i].file)
|
||||
|
||||
const dom = new JSDOM(htmlData);
|
||||
|
||||
@@ -79,6 +79,22 @@ const html = (data) => {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -94,6 +110,8 @@ const html = (data) => {
|
||||
|
||||
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))
|
||||
@@ -104,16 +122,16 @@ const javascript = (data, filePath) => {
|
||||
.replaceAll(';', ''))
|
||||
.map(data => {
|
||||
if (data.startsWith('./')) return {
|
||||
originalFile: data,
|
||||
newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data)
|
||||
originalFile: data.replaceAll('\r', ''),
|
||||
newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data).replaceAll('\r', '')
|
||||
};
|
||||
else if (data.startsWith('../')) return {
|
||||
originalFile: data,
|
||||
newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data)
|
||||
originalFile: data.replaceAll('\r', ''),
|
||||
newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data).replaceAll('\r', '')
|
||||
};
|
||||
else return {
|
||||
originalFile: data,
|
||||
newFile: data
|
||||
originalFile: data.replaceAll('\r', ''),
|
||||
newFile: data.replaceAll('\r', '')
|
||||
};
|
||||
})
|
||||
.filter(data => fs.existsSync(path.join(__dirname, '../static', data.newFile)));
|
||||
@@ -141,6 +159,8 @@ const javascript = (data, filePath) => {
|
||||
|
||||
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]
|
||||
@@ -151,7 +171,7 @@ const css = (data, filePath) => {
|
||||
.replaceAll('\'', '')
|
||||
.replaceAll('`', '')
|
||||
.replaceAll('"', '');
|
||||
else return undefined;
|
||||
else return null;
|
||||
})
|
||||
.filter(data => {
|
||||
if (data) try {
|
||||
@@ -163,8 +183,6 @@ const css = (data, filePath) => {
|
||||
} else return false;
|
||||
})
|
||||
.map(data => {
|
||||
// console.log(path.join(filePath.split('/').slice(0, -1).join('/')));
|
||||
|
||||
if (data.startsWith('./')) return {
|
||||
originalFile: data,
|
||||
newFile: path.join(filePath.split('/').slice(0, -1).join('/'), data)
|
||||
@@ -186,7 +204,7 @@ const css = (data, filePath) => {
|
||||
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);
|
||||
});
|
||||
|
||||
+2
-18
@@ -20,28 +20,12 @@
|
||||
<br>
|
||||
<div class="apps"></div>
|
||||
</div>
|
||||
|
||||
<!--el:footer-->
|
||||
<!--el:ad_horizontal-->
|
||||
<!--el:ad_horizontal-->
|
||||
|
||||
<script src="/assets/js/main.js" type="module"></script>
|
||||
|
||||
<!--el:{{mode === 'dev'}}:development-->
|
||||
|
||||
<script>
|
||||
window['nitroAds'].createAd('anchorad', {
|
||||
"refreshTime": 30,
|
||||
"format": "anchor",
|
||||
"anchor": "bottom",
|
||||
"anchorPersistClose": false,
|
||||
"report": {
|
||||
"enabled": true,
|
||||
"icon": true,
|
||||
"wording": "Report Ad",
|
||||
"position": "top-right"
|
||||
},
|
||||
"mediaQuery": "(min-width: 1025px)"
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
|
||||
+160
-224
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
@import url('https://site-assets.fontawesome.com/releases/v6.2.0/css/all.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');
|
||||
@@ -85,6 +85,10 @@ body::-webkit-scrollbar-corner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#searchInput {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
i {
|
||||
margin: 1vh;
|
||||
}
|
||||
@@ -339,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;
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
overflow-y: auto;
|
||||
padding: 1vh;
|
||||
transition: all 0.5s ease;
|
||||
backdrop-filter: blur(7.1px);
|
||||
-webkit-backdrop-filter: blur(7.1px);
|
||||
}
|
||||
|
||||
.sidebar.active {
|
||||
|
||||
@@ -2,16 +2,25 @@
|
||||
|
||||
.gamebar {
|
||||
background: var(--background-darker);
|
||||
z-index: 9;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 25px;
|
||||
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 {
|
||||
@@ -26,4 +35,53 @@
|
||||
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);
|
||||
}
|
||||
@@ -1,13 +1,6 @@
|
||||
import { loadProxyWorker } from './utils.js';
|
||||
import PolarisError from './error.js';
|
||||
|
||||
const tiltEffectSettings = {
|
||||
max: 8,
|
||||
perspective: 1000,
|
||||
scale: 1.05,
|
||||
speed: 800,
|
||||
easing: 'cubic-bezier(.03,.98,.52,.99)'
|
||||
};
|
||||
import effects from './effects.js';
|
||||
|
||||
const load = () => {
|
||||
fetch('/assets/JSON/apps.json').then(res => res.json()).then(apps => {
|
||||
@@ -17,6 +10,14 @@ 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 () => {
|
||||
await loadProxyWorker('uv');
|
||||
|
||||
@@ -26,46 +27,10 @@ const load = () => {
|
||||
}));
|
||||
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
-57
@@ -1,65 +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.'));
|
||||
};
|
||||
|
||||
const gameMouseEnter = setTransition;
|
||||
|
||||
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
|
||||
|
||||
Vendored
+79
@@ -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 };
|
||||
+80
-120
@@ -1,131 +1,91 @@
|
||||
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 = [];
|
||||
import { createViewPage } from './utils.js';
|
||||
import PolarisError from './error.js';
|
||||
import effects from './effects.js';
|
||||
|
||||
const load = () => {
|
||||
fetch('/assets/JSON/games.json').then(res => res.json()).then(data => {
|
||||
games = data;
|
||||
filteredGames = games;
|
||||
fetch('/assets/JSON/games.json')
|
||||
.then(res => res.json())
|
||||
.then(games => {
|
||||
const searchBar = document.getElementById('searchInput');
|
||||
|
||||
renderGames(filteredGames);
|
||||
searchBar.addEventListener('input', () => {
|
||||
if (searchBar.value) {
|
||||
var result = false;
|
||||
|
||||
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'));
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
+46
-33
@@ -1,10 +1,10 @@
|
||||
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 Games from './games.js';
|
||||
import Frame from './frame.js';
|
||||
import Apps from './apps.js';
|
||||
|
||||
loadEasterEggs();
|
||||
@@ -14,61 +14,74 @@ onbeforeunload = (e) => {
|
||||
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 () => {
|
||||
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 === '/') {
|
||||
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('.featured').addEventListener('click', () => {
|
||||
localStorage.setItem('frameData', JSON.stringify({
|
||||
type: 'game',
|
||||
game
|
||||
}));
|
||||
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
|
||||
});
|
||||
});
|
||||
|
||||
location.href = '/view';
|
||||
});
|
||||
document.querySelector('.featured').src = '/assets/img/wide/tinyfishing.png';
|
||||
}).catch(e => new PolarisError('Failed to load featured game.'));
|
||||
document.querySelector('.featured').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);
|
||||
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 descwrap = document.createElement('p');
|
||||
const description = document.createElement('i');
|
||||
description.textContent = change.simpleDescription;
|
||||
description.classList = 'small';
|
||||
document.querySelector('#changelog').appendChild(description);
|
||||
}));
|
||||
}
|
||||
|
||||
if (window.scrollY !== 0) document.querySelector('.navbar').classList.add('scrolling');
|
||||
else document.querySelector('.navbar').classList.remove('scrolling');
|
||||
|
||||
window.onscroll = () => {
|
||||
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');
|
||||
}
|
||||
|
||||
export default { Settings, Games, Apps, Frame, PolarisError };
|
||||
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 };
|
||||
@@ -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');
|
||||
});
|
||||
@@ -1,36 +1,20 @@
|
||||
import PolarisError from './error.js';
|
||||
import { loadProxyWorker } from './utils.js';
|
||||
import { createViewPage } from './utils.js';
|
||||
|
||||
const load = () => {
|
||||
const 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('');
|
||||
}
|
||||
};
|
||||
|
||||
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 Proxy');
|
||||
await loadProxyWorker('uv');
|
||||
|
||||
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);
|
||||
|
||||
localStorage.setItem('frameData', JSON.stringify({
|
||||
type: 'proxy',
|
||||
source: `/uv/service/${xor.encode(url)}`
|
||||
}));
|
||||
|
||||
location.href = '/view';
|
||||
createViewPage({
|
||||
target: url,
|
||||
proxied: true,
|
||||
title: 'Search Results'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default { load };
|
||||
export default { load };
|
||||
@@ -12,13 +12,13 @@ const storage = (containerName) => {
|
||||
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({}));
|
||||
}
|
||||
try {
|
||||
JSON.parse(localStorage.getItem(containerName));
|
||||
} catch (e) {
|
||||
localStorage.setItem(containerName, JSON.stringify({}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const container = JSON.parse(localStorage.getItem(containerName));
|
||||
return container[name];
|
||||
},
|
||||
@@ -54,6 +54,35 @@ const loadProxyWorker = async (proxy) => await navigator.serviceWorker.register(
|
||||
});
|
||||
|
||||
/**
|
||||
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 = () => {
|
||||
@@ -62,11 +91,51 @@ const loadPageScript = () => {
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
loadProxyWorker,
|
||||
encoder,
|
||||
redirect,
|
||||
createViewPage
|
||||
};
|
||||
|
||||
export {
|
||||
storage,
|
||||
loadProxyWorker
|
||||
loadProxyWorker,
|
||||
encoder,
|
||||
redirect,
|
||||
createViewPage
|
||||
};
|
||||
@@ -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('/');
|
||||
+5
-17
@@ -17,31 +17,19 @@
|
||||
|
||||
<div class="content">
|
||||
<h1>Cheats</h1>
|
||||
|
||||
<br>
|
||||
<div class="games"></div>
|
||||
|
||||
<div class="cheats"></div>
|
||||
</div>
|
||||
|
||||
<!--el:footer-->
|
||||
<!--el:ad_horizontal-->
|
||||
<!--el:ad_horizontal-->
|
||||
|
||||
<script src="/assets/js/main.js" type="module"></script>
|
||||
|
||||
<!--el:{{mode === 'dev'}}:development-->
|
||||
|
||||
<script>
|
||||
window['nitroAds'].createAd('anchorad', {
|
||||
"refreshTime": 30,
|
||||
"format": "anchor",
|
||||
"anchor": "bottom",
|
||||
"anchorPersistClose": false,
|
||||
"report": {
|
||||
"enabled": true,
|
||||
"icon": true,
|
||||
"wording": "Report Ad",
|
||||
"position": "top-right"
|
||||
},
|
||||
"mediaQuery": "(min-width: 1025px)"
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -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>
|
||||
@@ -1,5 +1,3 @@
|
||||
// See documentation for more information
|
||||
|
||||
self.__dynamic$config = {
|
||||
prefix: '/service/',
|
||||
encoding: 'xor',
|
||||
|
||||
+11
-17
@@ -25,32 +25,26 @@
|
||||
|
||||
<h1 style="font-size: 4vh;" class="gamesectionheader">All Games</h1>
|
||||
|
||||
<input type="text" id="searchInput" class="settings-input" placeholder="Search Games...">
|
||||
<input type="text" id="searchInput" placeholder="Search Games...">
|
||||
<!--el:ad_horizontal-->
|
||||
<!--el:ad_horizontal-->
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<div class="games">
|
||||
</div>
|
||||
|
||||
<!--el:footer-->
|
||||
<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-->
|
||||
|
||||
<script>
|
||||
window['nitroAds'].createAd('anchorad', {
|
||||
"refreshTime": 30,
|
||||
"format": "anchor",
|
||||
"anchor": "bottom",
|
||||
"anchorPersistClose": false,
|
||||
"report": {
|
||||
"enabled": true,
|
||||
"icon": true,
|
||||
"wording": "Report Ad",
|
||||
"position": "top-right"
|
||||
},
|
||||
"mediaQuery": "(min-width: 1025px)"
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -28,6 +28,8 @@
|
||||
<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>
|
||||
|
||||
@@ -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>
|
||||
+3
-17
@@ -7,7 +7,7 @@
|
||||
<!--el:analytics-->
|
||||
|
||||
<link rel="stylesheet" href="/assets/css/main.css">
|
||||
|
||||
|
||||
<title>Search | Polaris</title>
|
||||
</head>
|
||||
|
||||
@@ -26,26 +26,12 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/assets/js/main.js" type="module"></script>
|
||||
<!--el:ad_horizontal-->
|
||||
<!--el:ad_horizontal-->
|
||||
|
||||
<!--el:{{mode === 'dev'}}:development-->
|
||||
|
||||
<script>
|
||||
window['nitroAds'].createAd('anchorad', {
|
||||
"refreshTime": 30,
|
||||
"format": "anchor",
|
||||
"anchor": "bottom",
|
||||
"anchorPersistClose": false,
|
||||
"report": {
|
||||
"enabled": true,
|
||||
"icon": true,
|
||||
"wording": "Report Ad",
|
||||
"position": "top-right"
|
||||
},
|
||||
"mediaQuery": "(min-width: 1025px)"
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+1
-1
@@ -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)));
|
||||
@@ -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',
|
||||
};
|
||||
+17
-4
@@ -12,17 +12,30 @@
|
||||
<title>View | Polaris</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--//el:sidebar-->
|
||||
|
||||
<body class="hidden">
|
||||
<iframe frameborder="0"></iframe>
|
||||
|
||||
<div class="gamebar">
|
||||
<a href="/">
|
||||
<img src="/assets/img/logo.png" class="logo">
|
||||
</a>
|
||||
|
||||
<h1 class="title">Game</h1>
|
||||
<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-->
|
||||
|
||||
@@ -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>
|
||||
+1
-29
@@ -1,31 +1,3 @@
|
||||
<footer>
|
||||
<div class="title">
|
||||
<h1>Polaris</h1>
|
||||
|
||||
<img src="/assets/img/logo.png" title="Polaris Logo">
|
||||
</div>
|
||||
|
||||
<div class="socials">
|
||||
<a href="https://discord.gg/RXBbxQ4wuJ" target="_blank" rel="noopener noreferrer" title="EmberNetwork Discord">
|
||||
<i class="fa-brands fa-discord"></i>
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/Skoolgq/Polaris" target="_blank" rel="noopener noreferrer" title="Our Github">
|
||||
<i class="fa-brands fa-github"></i>
|
||||
</a>
|
||||
|
||||
<a href="mailto:support@polarislearning.org" target="_blank" title="Contact Email">
|
||||
<i class="fa-solid fa-envelope"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<a href="https://forms.gle/9knPLmyAua5Z3wZv5">Suggest a Game</a>
|
||||
|
||||
<a href="/privacy">Privace Policy</a>
|
||||
|
||||
<a href="/TOS">Terms of Service</a>
|
||||
</div>
|
||||
|
||||
<p>©2022-2023 Skool. All rights reserved.</p>
|
||||
<!--May add this later-->
|
||||
</footer>
|
||||
@@ -21,7 +21,6 @@
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user