Compare commits
152 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 84ccc040b5 | |||
| 0b5ca9b022 | |||
| 53e4a0cefc | |||
| 51d365f295 | |||
| cc500e24d7 | |||
| 8b6ee50625 | |||
| 37b0d18c3e | |||
| bab31cf334 | |||
| 619ba75aad | |||
| 62eb659a7a | |||
| 93eac6f917 | |||
| 2f758462c1 | |||
| 1e762e1b97 | |||
| 4636034214 | |||
| ab0468bd7c | |||
| 2e1250ca92 | |||
| 0490072fbf | |||
| 84b2546c45 | |||
| 0ccd3671b2 | |||
| 5b2d02b60a | |||
| bb8e5fcdf2 | |||
| fc9da6d97e | |||
| d59652c540 | |||
| d54842104e | |||
| 80431ee7c2 | |||
| bc3a593cf7 | |||
| fb8b9e1469 | |||
| 777c8724b6 | |||
| 6737f39c32 | |||
| bc2d9744da | |||
| 43fa80856d | |||
| 30b8c18f57 | |||
| b2809532eb | |||
| 81fd089e49 | |||
| 8ff12d71cc | |||
| 55e86ec13b | |||
| cbec8f452f | |||
| 00d8eb5dda | |||
| 30a6a8857d | |||
| 15820f1359 | |||
| bd2998c350 | |||
| 7e4dfeea16 | |||
| c101ff2511 | |||
| d55717635e | |||
| e3bb53eb75 | |||
| e3521dcd7c | |||
| e9b80a0cbd | |||
| 4d14a7b047 | |||
| acefe31674 | |||
| 3381de4607 | |||
| 0d90131711 | |||
| 60a7c76762 | |||
| ace64c553a | |||
| 020667f73e | |||
| 6002398ce6 | |||
| bfd6519602 | |||
| 65ef750e7c | |||
| 6e38da7dbb | |||
| a7f650e9b0 | |||
| 5ae4a2d026 | |||
| 48ad4de694 | |||
| 91b6edeb0d | |||
| 9233042162 | |||
| 99c72394bd | |||
| 0c22df7b70 | |||
| 6c22331a5b | |||
| c3fb216261 | |||
| 590c95b461 | |||
| 050f4b68af | |||
| 036ff8f280 | |||
| c0b5bda1a7 | |||
| 3355300168 | |||
| f7eef1bce6 | |||
| 3b35aa885b | |||
| e854af7c67 | |||
| 6b9971852e | |||
| 06bf63cc2c | |||
| ac47011b8e | |||
| 4f3bce4d4a | |||
| 9b6323a7cd | |||
| a126b64540 | |||
| 2fa3364df8 | |||
| d11a1806ab | |||
| 1e181b580f | |||
| d05af82c8e | |||
| 64c162ebcb | |||
| bd537f9179 | |||
| 968ff2f78b | |||
| 30628b3b82 | |||
| 51470399e5 | |||
| afa3c28a0a | |||
| d3224ddc22 | |||
| b4cf5dafd4 | |||
| c01acfd2ff | |||
| 033ffd8710 | |||
| 9f120ba33f | |||
| 9e14a4d9fd | |||
| e739121a83 | |||
| 0077478709 | |||
| 71db58c437 | |||
| 91c555f6ca | |||
| 2dfa8c937c | |||
| b024ff985c | |||
| 98fc37875f | |||
| c92a276a5e | |||
| 3692d0435d | |||
| 1c4c61261a | |||
| f1da3aa4b2 | |||
| 5f346904fa | |||
| 207ef93246 | |||
| 1c39fbca66 | |||
| f4ab143a02 | |||
| 0a5171f1e1 | |||
| a12aaed9e3 | |||
| 00de3d95b7 | |||
| 6548d604b1 | |||
| aa766ec15f | |||
| fcc0343d95 | |||
| 2858dbb475 | |||
| 1f77fdc60d | |||
| 6aa6e40c5f | |||
| 33c038d544 | |||
| 9e8043dc7c | |||
| 69aafc8d15 | |||
| 315bb6f70c | |||
| 158e78561b | |||
| b63efc1f5b | |||
| 2309f466e0 | |||
| 277e591706 | |||
| e53858b6ce | |||
| 078da78f41 | |||
| 35d2473b74 | |||
| 58d974a74d | |||
| 48e02c2a48 | |||
| 55592d3e22 | |||
| b6e7612634 | |||
| 7a466eb073 | |||
| d5e81d012f | |||
| 32571322ff | |||
| 71345680e9 | |||
| d74f4accf4 | |||
| 48973c4808 | |||
| 35c98b0ae4 | |||
| f91616a48e | |||
| 879aafa14e | |||
| e6154e5e04 | |||
| 2371d76557 | |||
| 1a8c1c8aa6 | |||
| 0584a313ef | |||
| 0b4d0be9d1 | |||
| 4d6658c3b9 | |||
| 4113c74194 |
@@ -1,12 +1,11 @@
|
||||
<div align="center">
|
||||
<img src="./static/android-chrome-512x512.png" width="300px">
|
||||
<h1>Polaris</h1>
|
||||
<p>The professional unblocked games site.</p>
|
||||
<img src="https://github.com/Skoolgq/Polaris/assets/93336301/dc994d43-06f4-4947-a15f-226c840f6880" width="600px">
|
||||
|
||||
<h2><a href="https://dsc.gg/skoolworld">Join our Discord server</a></h2>
|
||||
|
||||

|
||||

|
||||
|
||||
<br>
|
||||
<h2>Quick Web Deployment</h2>
|
||||
|
||||
[](https://vercel.com/new/clone?repository-url=https://github.com/Skoolgq/Polaris)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
name: Polaris
|
||||
|
||||
services:
|
||||
polaris:
|
||||
build: .
|
||||
ports:
|
||||
- "8080:8080"
|
||||
Generated
+3219
-223
File diff suppressed because it is too large
Load Diff
+13
-8
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "polaris",
|
||||
"version": "1.2.1",
|
||||
"version": "1.3.2",
|
||||
"description": "The professional unblocked games site.",
|
||||
"main": "index.js",
|
||||
"main": "server/index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "node server",
|
||||
@@ -12,14 +12,19 @@
|
||||
"author": "Polaris Development Group",
|
||||
"license": "GNU-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@tomphttp/bare-server-node": "^2.0.1",
|
||||
"cors": "*",
|
||||
"easyviolet": "github:Russell2259/Easyviolet",
|
||||
"express": "*",
|
||||
"@mercuryworkshop/bare-mux": "^1.0.5",
|
||||
"@mercuryworkshop/epoxy-transport": "^1.1.0",
|
||||
"@mercuryworkshop/libcurl-transport": "^1.2.2",
|
||||
"@nebula-services/dynamic": "^0.7.2-patch.2",
|
||||
"@titaniumnetwork-dev/ultraviolet": "^3.0.0",
|
||||
"@tomphttp/bare-server-node": "^2.0.3",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.18.3",
|
||||
"html-minifier": "^4.0.0",
|
||||
"javascript-obfuscator": "^4.1.0",
|
||||
"jsdom": "^23.0.1",
|
||||
"mime": "*",
|
||||
"uuid": "^9.0.1"
|
||||
"mime": "^4.0.1",
|
||||
"uuid": "^9.0.1",
|
||||
"wisp-server-node": "^1.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import { loadProxyWorker, storage } from '/assets/js/utils.js';
|
||||
import { loadProxyWorker, storage, loadCJS } from '/assets/js/utils.js';
|
||||
|
||||
const settingsStorage = storage('settings');
|
||||
|
||||
@@ -33,7 +33,9 @@
|
||||
}));
|
||||
}
|
||||
|
||||
if (location.pathname.slice(1).startsWith(settingsStorage.get('proxy') || 'uv')) loadProxyWorker(settingsStorage.get('proxy') || 'uv')
|
||||
await loadCJS('/baremux/bare.cjs');
|
||||
|
||||
if (location.pathname.slice(1).startsWith((settingsStorage.get('proxy') || '').split(':')[0] || 'uv')) loadProxyWorker((settingsStorage.get('proxy') || '').split(':')[0] || 'uv')
|
||||
.then(() => location.reload())
|
||||
.catch(() => {
|
||||
document.querySelector('h1').textContent = 'Error';
|
||||
|
||||
+3
-3
@@ -8,10 +8,10 @@ export default useConfig({
|
||||
minify: false,
|
||||
//Beta
|
||||
assetScrambling: false,
|
||||
allowDangerousTemplateInsert: true,
|
||||
allowDangerousTemplateInsert: false,
|
||||
api: {
|
||||
domain: 'api.polarislearning.org',
|
||||
domain: 'api.skoolworld.org',
|
||||
secure: true
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+61
-43
@@ -1,4 +1,10 @@
|
||||
import { createBareServer } from '@tomphttp/bare-server-node';
|
||||
import { libcurlPath } from '@mercuryworkshop/libcurl-transport';
|
||||
import { epoxyPath } from '@mercuryworkshop/epoxy-transport';
|
||||
import { uvPath } from '@titaniumnetwork-dev/ultraviolet';
|
||||
import { baremuxPath } from '@mercuryworkshop/bare-mux';
|
||||
import { dynamicPath } from '@nebula-services/dynamic';
|
||||
import wisp from 'wisp-server-node';
|
||||
import express from 'express';
|
||||
import mime from 'mime';
|
||||
import cors from 'cors';
|
||||
@@ -28,44 +34,30 @@ app.use(express.json());
|
||||
|
||||
api(app);
|
||||
|
||||
app.get('/cdn/3kh0/*', cors({
|
||||
origin: false
|
||||
}), async (req, res, next) => {
|
||||
let reqTarget = `https://codeberg.org/derpman/echo/raw/branch/main/${req.path.replace('/cdn/3kh0/', '')}`;
|
||||
|
||||
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('/cdn/*', cors({
|
||||
origin: false
|
||||
}), async (req, res, next) => {
|
||||
let reqTarget = `https://raw.githubusercontent.com/Skoolgq/Polaris-Assets/main/${req.path.replace('/cdn/', '')}`;
|
||||
const reqTarget = req.path.startsWith('/cdn/3kh0/') ? `https://player.work/${req.path.replace('/cdn/3kh0/', '')}` : `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());
|
||||
try {
|
||||
const asset = await fetch(reqTarget);
|
||||
|
||||
const noRewrite = ['.unityweb'];
|
||||
if (!noRewrite.includes(mime.getExtension(reqTarget))) res.writeHead(200, {
|
||||
'content-type': mime.getType(reqTarget)
|
||||
});
|
||||
if (asset.status == 200) {
|
||||
var data = Buffer.from(await asset.arrayBuffer());
|
||||
|
||||
if (mime.getType(reqTarget) === 'text/html') data = data + '<script src=\'/assets/js/cdn.inject.js\' preload=\'true\'></script>';
|
||||
const noRewrite = ['.unityweb'];
|
||||
if (!noRewrite.includes(mime.getExtension(reqTarget))) res.writeHead(200, {
|
||||
'content-type': mime.getType(reqTarget)
|
||||
});
|
||||
|
||||
res.end(data);
|
||||
} else next();
|
||||
if (mime.getType(reqTarget) === 'text/html') data = data + '<script src=\'/assets/js/cdn.inject.js\' preload=\'true\'></script>';
|
||||
|
||||
res.end(data);
|
||||
} else next();
|
||||
} catch {
|
||||
res.setHeader('content-type', 'text/html');
|
||||
res.status(404).end(await rewriter.html(fs.readFileSync(path.join(__dirname, '../pages/404.html'))));
|
||||
}
|
||||
});
|
||||
|
||||
app.get('*', (req, res, next) => {
|
||||
@@ -106,6 +98,7 @@ 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/proxy_404.html')))));
|
||||
app.get('/dynamic/service/*', async (req, res) => res.end(await rewriter.html(fs.readFileSync(path.join(__dirname, '../pages/proxy_404.html')))));
|
||||
|
||||
|
||||
app.use(async (req, res, next) => {
|
||||
if (req.path === '/index') res.redirect('/');
|
||||
else {
|
||||
@@ -124,25 +117,50 @@ app.use(async (req, res, next) => {
|
||||
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'))));
|
||||
}
|
||||
} else next();
|
||||
}
|
||||
});
|
||||
|
||||
app.use('/uv/', express.static(uvPath, {
|
||||
setHeaders: (res, path) => {
|
||||
if (path.endsWith('.cjs')) res.setHeader('Content-Type', 'text/javascript');
|
||||
}
|
||||
}));
|
||||
app.use('/epoxy/', express.static(epoxyPath, {
|
||||
setHeaders: (res, path) => {
|
||||
if (path.endsWith('.cjs')) res.setHeader('Content-Type', 'text/javascript');
|
||||
}
|
||||
}));
|
||||
app.use('/baremux/', express.static(baremuxPath, {
|
||||
setHeaders: (res, path) => {
|
||||
if (path.endsWith('.cjs')) res.setHeader('Content-Type', 'text/javascript');
|
||||
}
|
||||
}));
|
||||
app.use('/libcurl/', express.static(libcurlPath, {
|
||||
setHeaders: (res, path) => {
|
||||
if (path.endsWith('.cjs')) res.setHeader('Content-Type', 'text/javascript');
|
||||
}
|
||||
}));
|
||||
app.use('/dynamic/', express.static(dynamicPath, {
|
||||
setHeaders: (res, path) => {
|
||||
if (path.endsWith('.cjs')) res.setHeader('Content-Type', 'text/javascript');
|
||||
}
|
||||
}));
|
||||
|
||||
app.use(async (req, res) => {
|
||||
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)) {
|
||||
//console.log('request', req.headers['x-bare-url']);
|
||||
bareServer.routeRequest(req, res);
|
||||
} else app(req, res);
|
||||
if (bareServer.shouldRoute(req)) bareServer.routeRequest(req, res);
|
||||
else app(req, res);
|
||||
});
|
||||
|
||||
server.on('upgrade', (req, socket, head) => {
|
||||
if (bareServer.shouldRoute(req)) {
|
||||
//console.log('upgrade', req.headers['x-bare-url']);
|
||||
bareServer.routeUpgrade(req, socket, head);
|
||||
} else socket.end();
|
||||
if (bareServer.shouldRoute(req)) bareServer.routeUpgrade(req, socket, head);
|
||||
else if (req.url.endsWith('/wisp/')) wisp.routeRequest(req, socket, head);
|
||||
else socket.end();
|
||||
});
|
||||
|
||||
server.listen(config.port, () => console.log(`Polaris running\n\nPort: ${server.address().port}\nVersion: ${packageFile.version + (Number(packageFile.version.split('.')[0]) <= 1 ? ' Beta' : '') || 'Unknown'} ${childProcess.execSync('git rev-parse HEAD').toString().trim().slice(0, 7) || 'Unknown'}\nMode: ${config.mode === 'dev' ? 'development' : 'production'}\nAPI Server: ${config.options.api.domain}\nNode.js: ${process.version}`));
|
||||
@@ -11,6 +11,7 @@ import url from 'node:url';
|
||||
import fs from 'node:fs';
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL('../', import.meta.url));
|
||||
const mode = config.mode;
|
||||
|
||||
const templateParser = (data) => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
@@ -22,7 +23,7 @@ const templateParser = (data) => {
|
||||
.map(data => {
|
||||
if (data) {
|
||||
if (data.startsWith('{{') && data.split(':')[data.split(':').length - 2].endsWith('}}')) {
|
||||
if (config.allowDangerousTemplateInsert) {
|
||||
if (config.options.allowDangerousTemplateInsert) {
|
||||
if (Boolean(eval(String(data.split(':')[data.split(':').length - 2]).slice(2, -2)))) return data;
|
||||
else return undefined;
|
||||
} else return undefined;
|
||||
|
||||
+34
-44
@@ -1,54 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!--el:meta-->
|
||||
<!--el:adtop-->
|
||||
<!--el:analytics-->
|
||||
|
||||
<head>
|
||||
<!--el:meta-->
|
||||
<!--el:adtop-->
|
||||
<!--el:analytics-->
|
||||
<link rel="stylesheet" href="/assets/css/main.css" />
|
||||
|
||||
<link rel="stylesheet" href="/assets/css/main.css">
|
||||
<title>Apps | Polaris</title>
|
||||
</head>
|
||||
|
||||
<title>Apps | Polaris</title>
|
||||
</head>
|
||||
<body>
|
||||
<!--el:navbar-->
|
||||
<!--el:sidebar-->
|
||||
|
||||
<body>
|
||||
<!--el:navbar-->
|
||||
<!--el:sidebar-->
|
||||
<div class="content centered">
|
||||
<h1>Apps</h1>
|
||||
<br />
|
||||
<div class="apps"></div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<div id="largebillboard1"></div>
|
||||
|
||||
<div class="content centered">
|
||||
<h1>Apps</h1>
|
||||
<br>
|
||||
<div class="apps"></div>
|
||||
<div class="centered">
|
||||
<!--<script type="text/javascript">
|
||||
atOptions = {
|
||||
'key' : 'cf0bb7d0401f5ae5534ac09c2e959d20',
|
||||
'format' : 'iframe',
|
||||
'height' : 90,
|
||||
'width' : 728,
|
||||
'params' : {}
|
||||
};
|
||||
document.write('<scr' + 'ipt type="text/javascript" src="//outrightsham.com/cf0bb7d0401f5ae5534ac09c2e959d20/invoke.js"></scr' + 'ipt>');
|
||||
</script>-->
|
||||
</div>
|
||||
<!--el:discord_widget-->
|
||||
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<div id="largebillboard1"></div>
|
||||
|
||||
<script>
|
||||
window['nitroAds'].createAd('largebillboard1', {
|
||||
"refreshTime": 30,
|
||||
"renderVisibleOnly": true,
|
||||
"sizes": [
|
||||
[
|
||||
"970",
|
||||
"250"
|
||||
]
|
||||
],
|
||||
"report": {
|
||||
"enabled": true,
|
||||
"icon": true,
|
||||
"wording": "Report Ad",
|
||||
"position": "top-right"
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!--el:discord_widget-->
|
||||
|
||||
<script src="/assets/js/main.js" type="module"></script>
|
||||
|
||||
<!--el:{{mode === 'dev'}}:development-->
|
||||
</body>
|
||||
<script src="/assets/js/main.js" type="module"></script>
|
||||
|
||||
<!--el:{{mode === 'dev'}}:development-->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
[
|
||||
{
|
||||
"name": "Android OS",
|
||||
"image": "/cdn/images/android.png",
|
||||
"target": "https://now.gg/iframe/snippet?app_pkg=com.uncube.launcher3&partner=skool"
|
||||
},
|
||||
{
|
||||
"name": "Spotify",
|
||||
"image": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Spotify_logo_without_text.svg/168px-Spotify_logo_without_text.svg.png",
|
||||
"target": "https://open.spotify.com/"
|
||||
},
|
||||
{
|
||||
"name": "ChatGPT",
|
||||
"image": "/cdn/images/chatgpt.webp",
|
||||
"target": "https://chat.shuttleai.app"
|
||||
},
|
||||
{
|
||||
"name": "Chess.com",
|
||||
"image": "https://play-lh.googleusercontent.com/a7R5nyeaX8lIEWdBOxjlvbyq9LcFwh3XMvNtBPEKR3LPGgdvgGrec4sJwn8tUaaSkw",
|
||||
@@ -37,7 +47,7 @@
|
||||
{
|
||||
"name": "Movies/TV",
|
||||
"image": "https://avatars.githubusercontent.com/u/121455091",
|
||||
"target": "//movie-web.app"
|
||||
"target": "https://movie-web.app"
|
||||
},
|
||||
{
|
||||
"name": "Paramount+",
|
||||
@@ -63,5 +73,15 @@
|
||||
"name": "Youtube",
|
||||
"image": "/cdn/images/youtube.png",
|
||||
"target": "https://youtube.com"
|
||||
},
|
||||
{
|
||||
"name": "Youtube Downloader",
|
||||
"image": "/cdn/images/youtubedownloader.png",
|
||||
"target": "https://cobalt.tools"
|
||||
},
|
||||
{
|
||||
"name": "Youtube Music",
|
||||
"image": "/cdn/images/yt-music.png",
|
||||
"target": "https://music.youtube.com"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,4 +1,72 @@
|
||||
[
|
||||
{
|
||||
"date": "3/28/2024",
|
||||
"simpleDescription": "Changed Navbar Style"
|
||||
},
|
||||
{
|
||||
"date": "3/10/2024",
|
||||
"simpleDescription": "Fixed Settings Menu and improved Game Search"
|
||||
},
|
||||
{
|
||||
"date": "3/7/2024",
|
||||
"simpleDescription": "Added 10 games"
|
||||
},
|
||||
{
|
||||
"date": "3/1/2024",
|
||||
"simpleDescription": "Fix roblox"
|
||||
},
|
||||
{
|
||||
"date": "2/28/2024",
|
||||
"simpleDescription": "Added 2 games"
|
||||
},
|
||||
{
|
||||
"date": "2/27/2024",
|
||||
"simpleDescription": "Added 4 games and removed Buckshot Roulette"
|
||||
},
|
||||
{
|
||||
"date": "2/26/2024",
|
||||
"simpleDescription": "Added Buckshot Roulette"
|
||||
},
|
||||
{
|
||||
"date": "2/24/2024",
|
||||
"simpleDescription": "Added a random game button"
|
||||
},
|
||||
{
|
||||
"date": "2/23/2024",
|
||||
"simpleDescription": "Added 6 games and changed popular games"
|
||||
},
|
||||
{
|
||||
"date": "2/22/2024",
|
||||
"simpleDescription": "Added 17 games (200+ games 🎉), and removed 1 game"
|
||||
},
|
||||
{
|
||||
"date": "2/21/2024",
|
||||
"simpleDescription": "Fixed more games, added 15 games, and added 2 new themes"
|
||||
},
|
||||
{
|
||||
"date": "2/20/2024",
|
||||
"simpleDescription": "Fixed Lots of games"
|
||||
},
|
||||
{
|
||||
"date": "2/16/2024",
|
||||
"simpleDescription": "Fixed Roblox"
|
||||
},
|
||||
{
|
||||
"date": "2/15/2024",
|
||||
"simpleDescription": "Added 4 games"
|
||||
},
|
||||
{
|
||||
"date": "2/14/2024",
|
||||
"simpleDescription": "Fixed 3 games, added 23 games, and added Youtube Music"
|
||||
},
|
||||
{
|
||||
"date": "2/13/2024",
|
||||
"simpleDescription": "Fixed issues with the cdn and added 8 new games"
|
||||
},
|
||||
{
|
||||
"date": "2/12/2024",
|
||||
"simpleDescription": "Added 15 games and changed the featured game to Run 3"
|
||||
},
|
||||
{
|
||||
"date": "1/25/2024",
|
||||
"simpleDescription": "Changed featured game to 99 Balls 3D"
|
||||
|
||||
+586
-37
@@ -40,6 +40,11 @@
|
||||
"target": "/cdn/amidst-the-clouds/index.html",
|
||||
"image": "/cdn/amidst-the-clouds/splash.png"
|
||||
},
|
||||
{
|
||||
"name": "Aquapark.io",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/ce67b95f0db44d66b8b0dc48ade7ce1a/index.html",
|
||||
"image": "https://teen.media/assets/aqua.jpeg"
|
||||
},
|
||||
{
|
||||
"name": "Archery World Tour",
|
||||
"target": "https://gamesnacks.com/embed/games/archery",
|
||||
@@ -57,7 +62,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Asphalt Retro",
|
||||
"target": "https://html5.gamedistribution.com/2c122cee7ef04222a962449e32a34e98/?gd_sdk_referrer_url=https://gamedistribution.com/games/asphalt-retro",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/2c122cee7ef04222a962449e32a34e98/?gd_sdk_referrer_url=https://gamedistribution.com/games/asphalt-retro",
|
||||
"image": "/cdn/images/asr.jpg"
|
||||
},
|
||||
{
|
||||
@@ -82,12 +87,12 @@
|
||||
},
|
||||
{
|
||||
"name": "Basket Random",
|
||||
"target": "https://html5.gamedistribution.com/bf1268dccb5d43e7970bb3edaa54afc8/?gd_sdk_referrer_url=https://gamedistribution.com/games/basket-random",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/bf1268dccb5d43e7970bb3edaa54afc8/?gd_sdk_referrer_url=https://gamedistribution.com/games/basket-random",
|
||||
"image": "https://img.gamedistribution.com/bf1268dccb5d43e7970bb3edaa54afc8-512x512.jpeg"
|
||||
},
|
||||
{
|
||||
"name": "Basketball Stars",
|
||||
"target": "https://html5.gamedistribution.com/69d78d071f704fa183d75b4114ae40ec/?gd_sdk_referrer_url=https://gamedistribution.com/games/basketball-stars",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/69d78d071f704fa183d75b4114ae40ec/?gd_sdk_referrer_url=https://gamedistribution.com/games/basketball-stars",
|
||||
"image": "https://img.gamedistribution.com/69d78d071f704fa183d75b4114ae40ec-512x512.jpeg"
|
||||
},
|
||||
{
|
||||
@@ -102,7 +107,7 @@
|
||||
},
|
||||
{
|
||||
"name": "BitLife",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/2e44fb60fd3f4606b1b06c17a2b9d60d/index.html",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/rvvASMiM/2e44fb60fd3f4606b1b06c17a2b9d60d/index.html",
|
||||
"image": "https://play-lh.googleusercontent.com/fUM-UyywXxjC8soxAZdIlxJrlRRXmql8wkE426SHzft4lJycSKVd2jCYQQX1BEG9Xw=w240-h480-rw"
|
||||
},
|
||||
{
|
||||
@@ -127,7 +132,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Bonk.io",
|
||||
"target": "//bonk.io",
|
||||
"target": "https://bonk.io",
|
||||
"image": "https://b.thumbs.redditmedia.com/9p8-wn2_KPdgjPTaR9fx-NIVgFhvsgBL0WPdbv5GMkA.png"
|
||||
},
|
||||
{
|
||||
@@ -163,8 +168,12 @@
|
||||
{
|
||||
"name": "COD Mobile",
|
||||
"target": "https://now.gg/play/activision-publishing-inc/7935/call-of-duty.html",
|
||||
"image": "https://static.wikia.nocookie.net/callofduty/images/f/f4/App_Icon_CODM_Global.jpg/revision/latest?cb=20200507033012",
|
||||
"popular": true
|
||||
"image": "https://static.wikia.nocookie.net/callofduty/images/f/f4/App_Icon_CODM_Global.jpg/revision/latest?cb=20200507033012"
|
||||
},
|
||||
{
|
||||
"name": "Counter Strike",
|
||||
"target": "https://play-cs.com",
|
||||
"image": "https://cdn2.iconfinder.com/data/icons/popular-games-1/50/csgo_squircle-512.png"
|
||||
},
|
||||
{
|
||||
"name": "Crossy Road",
|
||||
@@ -212,24 +221,19 @@
|
||||
"image": "/cdn/images/driftboss.png"
|
||||
},
|
||||
{
|
||||
"name": "Drift Hunters (have patience)",
|
||||
"name": "Drift Hunters",
|
||||
"target": "https://webglmath.github.io/drift-hunters/",
|
||||
"image": "https://play-lh.googleusercontent.com/smo8Ln-PRREDGq_QjA-Nws7ZNJQhvQfUB2oA8XV0GW12uq6hqdhvwXCB2rdl6zjekcow=w240-h480-rw"
|
||||
},
|
||||
{
|
||||
"name": "Drive Mad",
|
||||
"target": "/cdn/3kh0/drive-mad/index.html",
|
||||
"image": "/cdn/images/dmd.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Fortnite",
|
||||
"target": "https://now.gg/play/epic-games/7308/fortnite",
|
||||
"image": "https://upload.wikimedia.org/wikipedia/commons/7/7c/Fortnite_F_lettermark_logo.png",
|
||||
"image": "/cdn/images/dmd.jpg",
|
||||
"popular": true
|
||||
},
|
||||
{
|
||||
"name": "Fireboy and Watergirl",
|
||||
"target": "https://html5.gamedistribution.com/a55c9cc9c21e4fc683c8c6857f3d0c75/?gd_sdk_referrer_url=https://gamedistribution.com/games/fireboy-and-watergirl-1-forest-temple",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/a55c9cc9c21e4fc683c8c6857f3d0c75/?gd_sdk_referrer_url=https://gamedistribution.com/games/fireboy-and-watergirl-1-forest-temple",
|
||||
"image": "https://img.gamedistribution.com/a55c9cc9c21e4fc683c8c6857f3d0c75-512x512.jpeg"
|
||||
},
|
||||
{
|
||||
@@ -244,12 +248,12 @@
|
||||
},
|
||||
{
|
||||
"name": "Fruit Ninja",
|
||||
"target": "/cdn/fruit-ninja/index.html",
|
||||
"target": "/cdn/3kh0/fruitninja/index.html",
|
||||
"image": "/cdn/fruit-ninja/FruitNinjaTeaser.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Genshin Impact",
|
||||
"target": "https://now.gg/play/cognosphere-pte-ltd-/1773/genshin-impact.html",
|
||||
"target": "https://nowgg.nl/play/cognosphere-pte-ltd-/1773/genshin-impact.html",
|
||||
"image": "https://cdn2.steamgriddb.com/icon_thumb/73e5080f0f3804cb9cf470a8ce895dac.png"
|
||||
},
|
||||
{
|
||||
@@ -284,7 +288,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Janissary Battles",
|
||||
"target": "https://html5.gamedistribution.com/8b55f4f729be4e70b6155f27d2e04690/?gd_sdk_referrer_url=https://gamedistribution.com/games/janissary-battles",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/8b55f4f729be4e70b6155f27d2e04690/?gd_sdk_referrer_url=https://gamedistribution.com/games/janissary-battles",
|
||||
"image": "/cdn/images/janissary.png"
|
||||
},
|
||||
{
|
||||
@@ -324,7 +328,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Melon Sandbox",
|
||||
"target": "https://now.gg/play/playducky/7199/melon-sandbox.html",
|
||||
"target": "https://nowgg.nl/play/playducky/7199/melon-sandbox.html",
|
||||
"image": "https://play-lh.googleusercontent.com/6q7J7_wky8t9gMihsZsvmKAIvfJ1h1gen2SwakrzN7OGigFFN2_VUycZBaOTn2Qs6_E"
|
||||
},
|
||||
{
|
||||
@@ -333,10 +337,19 @@
|
||||
"image": "/cdn/mindustry/splash.png"
|
||||
},
|
||||
{
|
||||
"name": "Minecraft",
|
||||
"target": "/cdn/3kh0/minecraft-15/index.html",
|
||||
"image": "/cdn/images/mc.jpeg",
|
||||
"popular": true
|
||||
"name": "Minecraft 1.3",
|
||||
"target": "https://rawcdn.githack.com/CybriaTech/Opium/main/games/eagler-1.3/index.html",
|
||||
"image": "https://i.ytimg.com/vi/IB2h3OTbbvA/sddefault.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Minecraft 1.5.2",
|
||||
"target": "https://rawcdn.githack.com/CybriaTech/Opium/main/games/eagler-1.5.2/index.html",
|
||||
"image": "https://images.squarespace-cdn.com/content/v1/5e172d9413c1a94fc0a5a165/1596626261379-ZV6K2M7DC4S3QNIO82R7/block.jpg?format=500w"
|
||||
},
|
||||
{
|
||||
"name": "Minecraft 1.8",
|
||||
"target": "https://rawcdn.githack.com/CybriaTech/Opium/main/games/eagler-1.8/index.html",
|
||||
"image": "/cdn/images/minecraft.svg"
|
||||
},
|
||||
{
|
||||
"name": "Missiles",
|
||||
@@ -380,7 +393,7 @@
|
||||
},
|
||||
{
|
||||
"name": "osu!",
|
||||
"target": "https://skoolgq.github.io/skool-osu",
|
||||
"target": "/cdn/3kh0/osu/index.html",
|
||||
"image": "/cdn/images/osu.png"
|
||||
},
|
||||
{
|
||||
@@ -436,7 +449,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Roblox",
|
||||
"target": "https://now.gg/play/roblox-corporation/5349/roblox",
|
||||
"target": "https://now.gg/iframe/snippet?app_pkg=com.roblox.client&partner=skool",
|
||||
"image": "/cdn/images/roblox.png",
|
||||
"popular": true
|
||||
},
|
||||
@@ -452,7 +465,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Rotate",
|
||||
"target": "https://html5.gamedistribution.com/0faa4468d18e4f7aa2e0161b4fefa193/?gd_sdk_referrer_url=https://gamedistribution.com/games/rotate",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/0faa4468d18e4f7aa2e0161b4fefa193/?gd_sdk_referrer_url=https://gamedistribution.com/games/rotate",
|
||||
"image": "https://img.gamedistribution.com/0faa4468d18e4f7aa2e0161b4fefa193-512x512.jpeg"
|
||||
},
|
||||
{
|
||||
@@ -477,7 +490,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Soccer Random",
|
||||
"target": "https://html5.gamedistribution.com/308d826f20034d7b972f25258c8d0a44/?gd_sdk_referrer_url=https://gamedistribution.com/games/soccer-random",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/308d826f20034d7b972f25258c8d0a44/?gd_sdk_referrer_url=https://gamedistribution.com/games/soccer-random",
|
||||
"image": "https://img.gamedistribution.com/308d826f20034d7b972f25258c8d0a44-512x512.jpeg"
|
||||
},
|
||||
{
|
||||
@@ -487,9 +500,8 @@
|
||||
},
|
||||
{
|
||||
"name": "Stumble Guys",
|
||||
"target": "https://now.gg/play/kitka-games/7999/stumble-guys.html",
|
||||
"image": "https://play-lh.googleusercontent.com/Oci7f4WR0JShbn-n5hnwubbXaMssleb2b1Dv7AMOzFFcgstIdC9kg-E3LHx3em8RCaLf",
|
||||
"popular":true
|
||||
"target": "https://now.gg/iframe/snippet?app_pkg=com.kitkagames.fallbuddies&partner=skool",
|
||||
"image": "https://play-lh.googleusercontent.com/Oci7f4WR0JShbn-n5hnwubbXaMssleb2b1Dv7AMOzFFcgstIdC9kg-E3LHx3em8RCaLf"
|
||||
},
|
||||
{
|
||||
"name": "Subway Surfers",
|
||||
@@ -528,32 +540,32 @@
|
||||
},
|
||||
{
|
||||
"name": "Vex 3",
|
||||
"target": "https://html5.gamedistribution.com/762c932b4db74c6da0c1d101b2da8be6/?gd_sdk_referrer_url=https://gamedistribution.com/games/vex-3",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/762c932b4db74c6da0c1d101b2da8be6/?gd_sdk_referrer_url=https://gamedistribution.com/games/vex-3",
|
||||
"image": "https://is1-ssl.mzstatic.com/image/thumb/Purple128/v4/87/06/4e/87064e7a-c9fd-7135-6ba3-f321f013e01e/mzl.kqcjsyop.png/512x512bb.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Vex 4",
|
||||
"target": "https://html5.gamedistribution.com/80e6a5ae477f4d4fbcd1ea293d10087d/?gd_sdk_referrer_url=https://gamedistribution.com/games/vex-4",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/80e6a5ae477f4d4fbcd1ea293d10087d/?gd_sdk_referrer_url=https://gamedistribution.com/games/vex-4",
|
||||
"image": "https://mobimg.b-cdn.net/v2/fetch/1d/1d957ad4cb8024ec9b63d54d6c61235b.png"
|
||||
},
|
||||
{
|
||||
"name": "Vex 5",
|
||||
"target": "https://html5.gamedistribution.com/f120262ab72743039fbce88c1f370df8/?gd_sdk_referrer_url=https://gamedistribution.com/games/vex-5",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/f120262ab72743039fbce88c1f370df8/?gd_sdk_referrer_url=https://gamedistribution.com/games/vex-5",
|
||||
"image": "https://img.gamedistribution.com/f120262ab72743039fbce88c1f370df8-512x512.jpeg"
|
||||
},
|
||||
{
|
||||
"name": "Vex 6",
|
||||
"target": "https://html5.gamedistribution.com/4925e12574364121a48c61c35f649c36/?gd_sdk_referrer_url=https://gamedistribution.com/games/vex-6",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/4925e12574364121a48c61c35f649c36/?gd_sdk_referrer_url=https://gamedistribution.com/games/vex-6",
|
||||
"image": "/cdn/images/vex-6.png"
|
||||
},
|
||||
{
|
||||
"name": "Vex 7",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/0c454c9562d249d28ba3a2b50564042c/index.html?gd_sdk_referrer_url=https%3A%2F%2Ftr.y8.com%2Fgames%2Fvex_7&key=y8&value=default&gd_zone_config=eyJwYXJlbnRVUkwiOiJodHRwczovL3RyLnk4LmNvbS9nYW1lcy92ZXhfNyIsInBhcmVudERvbWFpbiI6InRyLnk4LmNvbSIsInRvcERvbWFpbiI6InRyLnk4LmNvbSIsImhhc0ltcHJlc3Npb24iOmZhbHNlLCJsb2FkZXJFbmFibGVkIjp0cnVlLCJob3N0IjoiaHRtbDUuZ2FtZWRpc3RyaWJ1dGlvbi5jb20iLCJ2ZXJzaW9uIjoiMS41LjE2In0%253D",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/rvvASMiM/0c454c9562d249d28ba3a2b50564042c/index.html?gd_sdk_referrer_url=https%3A%2F%2Ftr.y8.com%2Fgames%2Fvex_7&key=y8&value=default&gd_zone_config=eyJwYXJlbnRVUkwiOiJodHRwczovL3RyLnk4LmNvbS9nYW1lcy92ZXhfNyIsInBhcmVudERvbWFpbiI6InRyLnk4LmNvbSIsInRvcERvbWFpbiI6InRyLnk4LmNvbSIsImhhc0ltcHJlc3Npb24iOmZhbHNlLCJsb2FkZXJFbmFibGVkIjp0cnVlLCJob3N0IjoiaHRtbDUuZ2FtZWRpc3RyaWJ1dGlvbi5jb20iLCJ2ZXJzaW9uIjoiMS41LjE2In0%253D",
|
||||
"image": "https://img.gamedistribution.com/0c454c9562d249d28ba3a2b50564042c-512x512.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Volley Random",
|
||||
"target": "https://html5.gamedistribution.com/b6f03bdc505e4d78a17379a5a83e206b/?gd_sdk_referrer_url=https://gamedistribution.com/games/volley-random",
|
||||
"target": "https://html5.gamedistribution.com/rvvASMiM/b6f03bdc505e4d78a17379a5a83e206b/?gd_sdk_referrer_url=https://gamedistribution.com/games/volley-random",
|
||||
"image": "https://img.gamedistribution.com/b6f03bdc505e4d78a17379a5a83e206b-512x512.jpeg"
|
||||
},
|
||||
{
|
||||
@@ -575,5 +587,542 @@
|
||||
"name": "Super Mario Bros",
|
||||
"target": "/cdn/mario/index.html",
|
||||
"image": "https://lh3.googleusercontent.com/PwJw4lIjmSVwOkpaeYigpJgwzEnTKIRQhxy7PmV0qnEVh4xuHb2vojFtNU4JCrCJL5YL5xi8WG7peK2kscQXjaEQ=w640-h400-e365-rj-sc0x00ffffff"
|
||||
},
|
||||
{
|
||||
"name": "Funny Shooter 2",
|
||||
"target": "https://rawcdn.githack.com/nightrose-labs/quartz/master/1/6af3cc65-32f9-4f3d-a66c-6c8882a7c5df/index.html",
|
||||
"image": "https://raw.githubusercontent.com/nightrose-labs/quartz/master/thumb/6af3cc65-32f9-4f3d-a66c-6c8882a7c5df.jpg",
|
||||
"popular": true
|
||||
},
|
||||
{
|
||||
"name": "Amongus",
|
||||
"target": "/cdn/3kh0/among-us/index.html",
|
||||
"image": "https://play-lh.googleusercontent.com/8ddL1kuoNUB5vUvgDVjYY3_6HwQcrg1K2fd_R8soD-e2QYj8fT9cfhfh3G0hnSruLKec"
|
||||
},
|
||||
{
|
||||
"name": "Taming.io",
|
||||
"target": "https://taming.io",
|
||||
"image": "https://play-lh.googleusercontent.com/EoY1Ey67rMjTHXIUqZCL3m4Ad4Of8BQr7tUHIcHWkM4YEiMugylaTPBNPAZQ6J8jumI=w240-h480-rw"
|
||||
},
|
||||
{
|
||||
"name": "Rooftop Snipers",
|
||||
"target": "/cdn/3kh0/rooftop-snipers/index.html",
|
||||
"image": "https://img.poki.com/cdn-cgi/image/quality=78,width=600,height=600,fit=cover,f=auto/c127771edb0e821e4109b7058ae3f094.jpeg"
|
||||
},
|
||||
{
|
||||
"name": "Google Snake",
|
||||
"target": "/cdn/3kh0/google-snake/index.html",
|
||||
"image": "https://play-lh.googleusercontent.com/p19u9SINIT3SZUQ8NcdcX5ROSFeEgTBc8J2okk8TsqSz2cq6eFJ0ekT-TwwqEXAKrQ"
|
||||
},
|
||||
{
|
||||
"name": "Hextris",
|
||||
"target": "/cdn/3kh0/hextris/index.html",
|
||||
"image": "https://codeberg.org/derpman/echo/raw/branch/main/hextris/images/hextris-logo.png"
|
||||
},
|
||||
{
|
||||
"name": "HexGL",
|
||||
"target": "/cdn/3kh0/HexGL/index.html",
|
||||
"image": "https://codeberg.org/derpman/echo/raw/branch/main/HexGL/icon.png"
|
||||
},
|
||||
{
|
||||
"name": "Appel",
|
||||
"target": "/cdn/appel/index.html",
|
||||
"image": "https://store-images.s-microsoft.com/image/apps.14476.13631454430641262.37c87ec2-8482-46a7-a63a-261257b0eba0.238f1630-e1a2-4cdc-ab31-ae80905aacb4?mode=scale&q=90&h=300&w=300"
|
||||
},
|
||||
{
|
||||
"name": "Temple Run 2",
|
||||
"target": "/cdn/3kh0/temple-run-2/index.html",
|
||||
"image": "https://upload.wikimedia.org/wikipedia/en/9/98/Temple_Run_2.png"
|
||||
},
|
||||
{
|
||||
"name": "Stack Bump 3D",
|
||||
"target": "/cdn/3kh0/stack-bump-3d/index.html",
|
||||
"image": "/cdn/3kh0/stack-bump-3d/thumbnail.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Stack",
|
||||
"target": "/cdn/3kh0/stack/index.html",
|
||||
"image": "/cdn/3kh0/stack/stack.png"
|
||||
},
|
||||
{
|
||||
"name": "Death Run 3D",
|
||||
"target": "/cdn/3kh0/death-run-3d/index.html",
|
||||
"image": "/cdn/3kh0/death-run-3d/img/death.png"
|
||||
},
|
||||
{
|
||||
"name": "Cut the Rope Time Travel",
|
||||
"target": "/cdn/3kh0/ctr-tr/index.html",
|
||||
"image": "/cdn/3kh0/ctr-tr/logo.png"
|
||||
},
|
||||
{
|
||||
"name": "Cut the Rope Holiday",
|
||||
"target": "/cdn/3kh0/ctr-holiday/index.html",
|
||||
"image": "/cdn/3kh0/ctr-holiday/Holiday_Gift.webp"
|
||||
},
|
||||
{
|
||||
"name": "Ducklife 3",
|
||||
"target": "/cdn/3kh0/ducklife3/index.html",
|
||||
"image": "/cdn/3kh0/ducklife3/duck.png"
|
||||
},
|
||||
{
|
||||
"name": "Ducklife 4",
|
||||
"target": "/cdn/3kh0/ducklife4/index.html",
|
||||
"image": "/cdn/3kh0/ducklife4/splash.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Om-Nom Bounce",
|
||||
"target": "/cdn/3kh0/om-bounce/index.html",
|
||||
"image": "/cdn/3kh0/om-bounce/assets/icon.jpeg"
|
||||
},
|
||||
{
|
||||
"name": "Stickman Hook",
|
||||
"target": "/cdn/3kh0/stickman-hook/index.html",
|
||||
"image": "/cdn/3kh0/stickman-hook/unnamed.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Slither.io",
|
||||
"target": "https://slither.io",
|
||||
"image": "https://play-lh.googleusercontent.com/oObkhKfUXOY5yzheKe9w1Y1pXZBgdiSksMeNmT0BijoQ8J75maTCIW2TA7-6pA6EMA"
|
||||
},
|
||||
{
|
||||
"name": "Evowars.io",
|
||||
"target": "https://evowars.io",
|
||||
"image": "https://play-lh.googleusercontent.com/8MffWSh6-Onwm--Hb5r7UUi21c7MxurIFIrNbBfIPHbb6KIcthHB2PUKcch6L0dO7HA"
|
||||
},
|
||||
{
|
||||
"name": "Deepest Sword",
|
||||
"target": "https://html-classic.itch.zone/html/4017918/index.html",
|
||||
"image": "https://images.sftcdn.net/images/t_app-icon-m/p/f97701fd-a064-4cac-9247-9793e72d8220/2271577798/deepest-sword-logo"
|
||||
},
|
||||
{
|
||||
"name": "Tunnel Rush Mania",
|
||||
"target": "https://html5.gamemonetize.co/2fp4sd31llh6u6vjxe1wxbx8meapsgop/",
|
||||
"image": "https://play-lh.googleusercontent.com/tl2qr3PCg-vpzloUgjMAY9eXz9y58Gdmb77_d9RbmrWoQu8rIvj4Fn3eCurqBoWsY84"
|
||||
},
|
||||
{
|
||||
"name": "Bacon May Die",
|
||||
"target": "https://game.enjoy4fun.com/baconmaydie/v2/index.html",
|
||||
"image": "https://img.poki.com/cdn-cgi/image/quality=78,width=600,height=600,fit=cover,f=auto/0b3b5b2de68b3a604693bf23b3994aa7.png"
|
||||
},
|
||||
{
|
||||
"name": "Google Feud",
|
||||
"target": "/cdn/3kh0/google-feud/index.html",
|
||||
"image": "/cdn/3kh0/google-feud/splash.png"
|
||||
},
|
||||
{
|
||||
"name": "Eggy Car",
|
||||
"target": "https://webglmath.github.io/eggy-car/",
|
||||
"image": "https://eggy-car.github.io/img/hero/hero.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Cookie Clicker",
|
||||
"target": "https://orteil.dashnet.org/cookieclicker/",
|
||||
"image": "https://play-lh.googleusercontent.com/Z1MOuuiD05ZN5LkVmMEvKF0mqAc-FknaQ2j8s4dZiO-LSPQX4EEA3RVJdlQEtxe96ok"
|
||||
},
|
||||
{
|
||||
"name": "Papery Planes",
|
||||
"target": "/cdn/3kh0/papery-planes/index.html",
|
||||
"image": "/cdn/3kh0/papery-planes/splash.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Rolly Vortex",
|
||||
"target": "/cdn/3kh0/rolly-vortex/index.html",
|
||||
"image": "/cdn/3kh0/rolly-vortex/icon-256.png"
|
||||
},
|
||||
{
|
||||
"name": "Snowbattle.io",
|
||||
"target": "/cdn/3kh0/snowbattle/index.html",
|
||||
"image": "/cdn/3kh0/snowbattle/img/logo.png"
|
||||
},
|
||||
{
|
||||
"name": "Swerve",
|
||||
"target": "/cdn/3kh0/swerve/index.html",
|
||||
"image": "/cdn/3kh0/swerve/img/favicon.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Tube Jumpers",
|
||||
"target": "/cdn/3kh0/tube-jumpers/index.html",
|
||||
"image": "/cdn/3kh0/tube-jumpers/img/shark.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Superhot",
|
||||
"target": "/cdn/3kh0/superhot/index.html",
|
||||
"image": "/cdn/3kh0/superhot/hot.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Glass City",
|
||||
"target": "/cdn/3kh0/glass-city/index.html",
|
||||
"image": "/cdn/3kh0/glass-city/image.png"
|
||||
},
|
||||
{
|
||||
"name": "Connect 3",
|
||||
"target": "/cdn/3kh0/connect3/index.html",
|
||||
"image": "/cdn/3kh0/connect3/connect3.png"
|
||||
},
|
||||
{
|
||||
"name": "Henry Stickmin: Breaking the Bank",
|
||||
"target": "/cdn/3kh0/breakingthebank/index.html",
|
||||
"image": "/cdn/3kh0/breakingthebank/breakingthebank.png"
|
||||
},
|
||||
{
|
||||
"name": "Bloons TD",
|
||||
"target": "/cdn/3kh0/bloonstd/index.html",
|
||||
"image": "/cdn/3kh0/bloonstd/bloonstd.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Portal",
|
||||
"target": "/cdn/3kh0/portalflash/index.html",
|
||||
"image": "/cdn/3kh0/portalflash/portaltheflashversion.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Riddle School",
|
||||
"target": "/cdn/3kh0/riddleschool/index.html",
|
||||
"image": "/cdn/3kh0/riddleschool/riddleschool.png"
|
||||
},
|
||||
{
|
||||
"name": "Riddle School 2",
|
||||
"target": "/cdn/3kh0/riddleschool2/index.html",
|
||||
"image": "/cdn/3kh0/riddleschool2/riddleschool2.png"
|
||||
},
|
||||
{
|
||||
"name": "Riddle School 3",
|
||||
"target": "/cdn/3kh0/riddleschool3/index.html",
|
||||
"image": "/cdn/3kh0/riddleschool3/riddleschool3.png"
|
||||
},
|
||||
{
|
||||
"name": "Riddle School 4",
|
||||
"target": "/cdn/3kh0/riddleschool4/index.html",
|
||||
"image": "/cdn/3kh0/riddleschool4/riddleschool4.png"
|
||||
},
|
||||
{
|
||||
"name": "Riddle School 5",
|
||||
"target": "/cdn/3kh0/riddleschool5/index.html",
|
||||
"image": "/cdn/3kh0/riddleschool5/riddleschool5.png"
|
||||
},
|
||||
{
|
||||
"name": "Riddle Transfer",
|
||||
"target": "/cdn/3kh0/riddletransfer/index.html",
|
||||
"image": "/cdn/3kh0/riddletransfer/riddletransfer.png"
|
||||
},
|
||||
{
|
||||
"name": "Riddle Transfer 2",
|
||||
"target": "/cdn/3kh0/riddletransfer2/index.html",
|
||||
"image": "/cdn/3kh0/riddletransfer2/riddletransfer2.png"
|
||||
},
|
||||
{
|
||||
"name": "Slope 2",
|
||||
"target": "/cdn/3kh0/slope-2/index.html",
|
||||
"image": "/cdn/3kh0/slope-2/slope-2-logo.png"
|
||||
},
|
||||
{
|
||||
"name": "Slope Ball",
|
||||
"target": "/cdn/3kh0/slope-ball/index.html",
|
||||
"image": "/cdn/3kh0/slope-ball/splash.png"
|
||||
},
|
||||
{
|
||||
"name": "Rabbit Samurai",
|
||||
"target": "/cdn/3kh0/rabbit-samurai/index.html",
|
||||
"image": "/cdn/3kh0/rabbit-samurai/splash.png"
|
||||
},
|
||||
{
|
||||
"name": "Rabbit Samurai 2",
|
||||
"target": "/cdn/3kh0/rabbit-samurai2/index.html",
|
||||
"image": "/cdn/3kh0/rabbit-samurai2/splash.png"
|
||||
},
|
||||
{
|
||||
"name": "Little Alchemy",
|
||||
"target": "https://littlealchemy.com",
|
||||
"image": "https://assets-prd.ignimgs.com/2022/08/15/little-academy-mobile-1660600636606.png"
|
||||
},
|
||||
{
|
||||
"name": "Little Alchemy 2",
|
||||
"target": "https://littlealchemy2.com",
|
||||
"image": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTaLDbrBKQlCSOXK7WNgx3myLJKrMD--5F8YkpI7ILih54J3ka6hyXDGOmZJr8_aXhuQA4&usqp=CAU"
|
||||
},
|
||||
{
|
||||
"name": "OvO 2",
|
||||
"target": "https://dthesle.github.io/OvO2/",
|
||||
"image": "https://lh3.googleusercontent.com/FOaLiWCIhdC5K-oE5UofoDpn3w2ZEAq359yAembr-Q-7mRqNd9ramV97FqyqPuqohwDdQZOm5MF9DL-QcTliLNmf=w640-h400-e365-rj-sc0x00ffffff"
|
||||
},
|
||||
{
|
||||
"name": "OvO Dimensions",
|
||||
"target": "https://www.miniplay.com/embed/ovo-dimensions",
|
||||
"image": "https://img.poki.com/cdn-cgi/image/quality=78,width=600,height=600,fit=cover,f=auto/76d0bf7026c6bf569a2fa96e92289484.png"
|
||||
},
|
||||
{
|
||||
"name": "Ages of Conflict",
|
||||
"target": "/cdn/3kh0/ages-of-conflict/index.html",
|
||||
"image": "/cdn/3kh0/ages-of-conflict/splash.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Amazing Rope Police",
|
||||
"target": "/cdn/3kh0/amazing-rope-police/index.html",
|
||||
"image": "https://3kh0.github.io/images/amazing-rope.jpeg"
|
||||
},
|
||||
{
|
||||
"name": "99 Balls Evo",
|
||||
"target": "/cdn/3kh0/99balls/index.html",
|
||||
"image": "https://3kh0.github.io/images/99-balls-evo.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Bad Ice Cream",
|
||||
"target": "/cdn/3kh0/bad-ice-cream/index.html",
|
||||
"image": "/cdn/3kh0/bad-ice-cream/bad-ice-cream.png"
|
||||
},
|
||||
{
|
||||
"name": "Bad Ice Cream 2",
|
||||
"target": "/cdn/3kh0/bad-ice-cream-2/index.html",
|
||||
"image": "/cdn/3kh0/bad-ice-cream-2/bad-ice-cream-2.png"
|
||||
},
|
||||
{
|
||||
"name": "Bad Ice Cream 3",
|
||||
"target": "/cdn/3kh0/bad-ice-cream-3/index.html",
|
||||
"image": "/cdn/3kh0/bad-ice-cream-3/bad-ice-cream-3.png"
|
||||
},
|
||||
{
|
||||
"name": "Core Ball",
|
||||
"target": "/cdn/3kh0/core-ball/index.html",
|
||||
"image": "/cdn/3kh0/core-ball/pr_source.png"
|
||||
},
|
||||
{
|
||||
"name": "Champion Island",
|
||||
"target": "/cdn/3kh0/champion-island/index.html",
|
||||
"image": "/cdn/3kh0/champion-island/splash.png"
|
||||
},
|
||||
{
|
||||
"name": "Cannon Basketball 4",
|
||||
"target": "/cdn/3kh0/cannon-basketball-4/index.html",
|
||||
"image": "/cdn/3kh0/cannon-basketball-4/img/splash.png"
|
||||
},
|
||||
{
|
||||
"name": "Paper.io",
|
||||
"target": "https://g-class.biz/lessons/1/",
|
||||
"image": "https://gamaddy.com/paper-io.png"
|
||||
},
|
||||
{
|
||||
"name": "Slime Rush TD",
|
||||
"target": "/cdn/3kh0/slime-rush-td/index.html",
|
||||
"image": "/cdn/3kh0/slime-rush-td/splash.png"
|
||||
},
|
||||
{
|
||||
"name": "Station 141",
|
||||
"target": "/cdn/3kh0/station-141/index.html",
|
||||
"image": "https://img.itch.zone/aW1nLzU4ODM5NjMucG5n/original/75wxYs.png"
|
||||
},
|
||||
{
|
||||
"name": "Rolling Forests",
|
||||
"target": "/cdn/3kh0/rolling-forests/index.html",
|
||||
"image": "/cdn/3kh0/rolling-forests/icon.png"
|
||||
},
|
||||
{
|
||||
"name": "Veloce",
|
||||
"target": "/cdn/3kh0/veloce/index.html",
|
||||
"image": "https://img.itch.zone/aW1nLzI1NjI0MjgucG5n/original/qN6zkD.png"
|
||||
},
|
||||
{
|
||||
"name": "Polybranch",
|
||||
"target": "/cdn/3kh0/polybranch/index.html",
|
||||
"image": "/cdn/3kh0/polybranch/img/pic1.png"
|
||||
},
|
||||
{
|
||||
"name": "Stick Archers",
|
||||
"target": "/cdn/3kh0/stick-archers/index.html",
|
||||
"image": "/cdn/3kh0/stick-archers/splash.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Soccer Skills",
|
||||
"target": "/cdn/3kh0/soccer-skills/index.html",
|
||||
"image": "/cdn/3kh0/soccer-skills/splash.png"
|
||||
},
|
||||
{
|
||||
"name": "Stick Merge",
|
||||
"target": "/cdn/3kh0/stick-merge/index.html",
|
||||
"image": "/cdn/3kh0/stick-merge/splash.png"
|
||||
},
|
||||
{
|
||||
"name": "Subway Surfers: New York",
|
||||
"target": "/cdn/3kh0/subway-surfers-ny/index.html",
|
||||
"image": "/cdn/3kh0/subway-surfers-ny/NewYorkIcon.png"
|
||||
},
|
||||
{
|
||||
"name": "Henry Stickmin: Escaping The Prision",
|
||||
"target": "/cdn/3kh0/escapingtheprison/index.html",
|
||||
"image": "/cdn/3kh0/escapingtheprison/escapingtheprison.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Knife Master",
|
||||
"target": "/cdn/3kh0/knife-master/index.html",
|
||||
"image": "/cdn/3kh0/knife-master/512x512.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Monster Tracks",
|
||||
"target": "/cdn/3kh0/monster-tracks/index.html",
|
||||
"image": "https://3kh0.github.io/images/monster-tracks.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Madalin Stunt Cars 2",
|
||||
"target": "/cdn/3kh0/madalin-stunt-cars-2/index.html",
|
||||
"image": "/cdn/3kh0/madalin-stunt-cars-2/img/logo.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Madalin Stunt Cars 3",
|
||||
"target": "/cdn/3kh0/madalin-stunt-cars-3/index.html",
|
||||
"image": "/cdn/3kh0/madalin-stunt-cars-3/img/index.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Henry Stickmin: Fleeing The Complex",
|
||||
"target": "/cdn/3kh0/fleeingthecomplex/index.html",
|
||||
"image": "https://3kh0.github.io/images/fleeing.jpeg"
|
||||
},
|
||||
{
|
||||
"name": "Grey Box",
|
||||
"target": "/cdn/3kh0/greybox/index.html",
|
||||
"image": "/cdn/3kh0/greybox/ico.png"
|
||||
},
|
||||
{
|
||||
"name": "Cars Simulator",
|
||||
"target": "/cdn/3kh0/cars-simulator/index.html",
|
||||
"image": "/cdn/3kh0/cars-simulator/splash.png"
|
||||
},
|
||||
{
|
||||
"name": "Cell Machine",
|
||||
"target": "/cdn/3kh0/cell-machine/index.html",
|
||||
"image": "/cdn/3kh0/cell-machine/img/te9nDu.png"
|
||||
},
|
||||
{
|
||||
"name": "Stickman Survival",
|
||||
"target": "/cdn/3kh0/Stickman-Survival/index.html",
|
||||
"image": "/cdn/3kh0/Stickman-Survival/Icon.png"
|
||||
},
|
||||
{
|
||||
"name": "Avalanche",
|
||||
"target": "/cdn/3kh0/avalanche/index.html",
|
||||
"image": "/cdn/3kh0/avalanche/avalanche.png"
|
||||
},
|
||||
{
|
||||
"name": "Ducklife",
|
||||
"target": "/cdn/3kh0/ducklife1/index.html",
|
||||
"image": "/cdn/3kh0/ducklife1/ducklife.png"
|
||||
},
|
||||
{
|
||||
"name": "Ducklife 2",
|
||||
"target": "/cdn/3kh0/ducklife2/index.html",
|
||||
"image": "/cdn/3kh0/ducklife2/ducklife2.png"
|
||||
},
|
||||
{
|
||||
"name": "Pool/Billiards Classic",
|
||||
"target": "https://13582048327635951979.playables.usercontent.goog/v/assets/index.html",
|
||||
"image": "https://play-lh.googleusercontent.com/KAyIN39YIUSorZxZ8iDtwO12C4V90ZSdi3tO7RUfxPxqGOhF6BYXv5VpAxlvfUWozI18"
|
||||
},
|
||||
{
|
||||
"name": "Alien Shooter",
|
||||
"target": "https://16702553337040190672.playables.usercontent.goog/v/assets/index.html",
|
||||
"image": "https://www2.minijuegosgratis.com/v3/games/thumbnails/241062_7_sq.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Amaze!",
|
||||
"target": "https://580820627722902829.playables.usercontent.goog/v/assets/index.html",
|
||||
"image": "https://play-lh.googleusercontent.com/hypAu2hPcTpg-FkZr7CjrWDspK_9Nm3UKvPWln9zaFUnIr-m6WQvEZ2baAaG0ufzrg"
|
||||
},
|
||||
{
|
||||
"name": "Angry Birds: Showdown",
|
||||
"target": "https://6381249690777614785.playables.usercontent.goog/v/assets/index.html",
|
||||
"image": "https://static.wikia.nocookie.net/angrybirdsfanon/images/0/0a/Angry_Birds_Showdown_App_Icon_%28Alpha%29.png/revision/latest?cb=20190801034150"
|
||||
},
|
||||
{
|
||||
"name": "Basketball FRVR",
|
||||
"target": "https://11024365036548115513.playables.usercontent.goog/v/assets/index.html",
|
||||
"image": "https://img.poki.com/cdn-cgi/image/quality=78,width=600,height=600,fit=cover,f=auto/5aae527bebe68094c3d3276387150197.png"
|
||||
},
|
||||
{
|
||||
"name": "Cannon Balls 3D",
|
||||
"target": "https://14726002176993811037.playables.usercontent.goog/v/assets/index.html",
|
||||
"image": "https://gameforge.com/de-DE/littlegames/includes/images/games/7_5ea03e7e3fe27.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Radius Raid",
|
||||
"target": "https://jackrugile.com/radius-raid/",
|
||||
"image": "/cdn/images/radiusraid.jpg"
|
||||
},
|
||||
{
|
||||
"name": "The Chroma Incident",
|
||||
"target": "https://js13kgames.com/games/the-chroma-incident/index.html",
|
||||
"image": "/cdn/images/thechromaincident.png"
|
||||
},
|
||||
{
|
||||
"name": "Dino Run 3d",
|
||||
"target": "https://russell2259.github.io/dino3d/",
|
||||
"image": "/cdn/images/dino3d.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Burrito Bison: Launcha Libre",
|
||||
"target": "https://rawcdn.githack.com/GameHub88/Yexex-Assets/main/bb/index.html",
|
||||
"image": "https://play-lh.googleusercontent.com/vpTgm9u7-GzZP_MceTWpDi0HbinXd_4phCoTwf4ZspFL-115FtNRdo_SU1p-khLDnLA"
|
||||
},
|
||||
{
|
||||
"name": "Yohoho.io",
|
||||
"target": "https://rawcdn.githack.com/GameHub88/Yexex-Assets/main/yohoho/index.html",
|
||||
"image": "https://lh3.googleusercontent.com/BulAgT61Ocg2r5obu2apG_IOYUi3t16vdmBwy0uAgmiOatFUfcRVuRKFPGSsz0kRJN8N"
|
||||
},
|
||||
{
|
||||
"name": "Jacksmith",
|
||||
"target": "https://moonlight.silvereen.net/src/static/games/jacksmith/index.html",
|
||||
"image": "https://img.poki.com/cdn-cgi/image/quality=78,width=600,height=600,fit=cover,f=auto/ebe99c6629baa3ea5f4d9c13f36a37bb.png"
|
||||
},
|
||||
{
|
||||
"name": "Sans Fight Simulator",
|
||||
"target": "https://jcw87.github.io/c2-sans-fight/",
|
||||
"image": "https://img.itch.zone/aW1nLzE2MDEzODIucG5n/original/oNevX4.png"
|
||||
},
|
||||
{
|
||||
"name": "Slowroads",
|
||||
"target": "https://slowroads.io",
|
||||
"image": "https://cdn-1.webcatalog.io/catalog/slow-roads/slow-roads-icon-filled-256.png?v=1678597634783"
|
||||
},
|
||||
{
|
||||
"name": "Duck Life 5",
|
||||
"target": "https://rawcdn.githack.com/CybriaTech/Opium/main/games/duck-life-5/index.html",
|
||||
"image": "https://play-lh.googleusercontent.com/JQqSn7wuCj0SxBqpBThNI33qCR9gwY0str2TIAnu-m_xrVCgZk3IPxYK2S7zC9WG0ig"
|
||||
},
|
||||
{
|
||||
"name": "Bloons TD 4",
|
||||
"target": "https://rawcdn.githack.com/CybriaTech/Opium/main/games/btd-4/index.html",
|
||||
"image": "https://assets-prd.ignimgs.com/2022/08/16/bloons-td4-button-1660612386362.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Bloons TD 5",
|
||||
"target": "https://rawcdn.githack.com/CybriaTech/Opium/main/games/btd-5/index.html",
|
||||
"image": "https://m.media-amazon.com/images/M/MV5BNTkzYTJmNWEtOTdjMS00MzBjLWJiZmUtNzhlMDQzYzhkODA2XkEyXkFqcGdeQXVyNTgyNTA4MjM@._V1_.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Raft Wars",
|
||||
"target": "https://rawcdn.githack.com/CybriaTech/Opium/main/games/raft-wars/index.html",
|
||||
"image": "https://i.ytimg.com/vi/FPZMXwGSwpQ/hqdefault.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Raft Wars 2",
|
||||
"target": "https://rawcdn.githack.com/CybriaTech/Opium/main/games/raft-wars-2/index.html",
|
||||
"image": "https://static.wikia.nocookie.net/raftwars/images/c/c2/Rw2.jpg/revision/latest?cb=20141110013832"
|
||||
},
|
||||
{
|
||||
"name": "Run",
|
||||
"target": "https://rawcdn.githack.com/CybriaTech/Opium/main/games/run/index.html",
|
||||
"image": "https://www.coolmathgames.com/sites/default/files/Run_OG-logo.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Run 2",
|
||||
"target": "https://rawcdn.githack.com/CybriaTech/Opium/main/games/run2/index.html",
|
||||
"image": "https://www.coolmathgames.com/sites/default/files/run-2.png"
|
||||
},
|
||||
{
|
||||
"name": "Subway Surfers: Singapore",
|
||||
"target": "https://rawcdn.githack.com/CybriaTech/Opium/main/games/subway-surfers-singapore/index.html",
|
||||
"image": "https://static.wikia.nocookie.net/subwaysurf/images/6/6d/Singapore2019LoadingScreen.png/revision/latest/scale-to-width-down/250?cb=20220403173202"
|
||||
},
|
||||
{
|
||||
"name": "Polytrack",
|
||||
"target": "https:/game.glimbo.xyz/polytrack",
|
||||
"image": "https://www.speedrun.com/static/game/w6j7ml76/cover.jpg?v=05316e4",
|
||||
"popular": true
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -1,5 +0,0 @@
|
||||
[
|
||||
{
|
||||
"quote": "The <span class='blue'>first</span> quote??!"
|
||||
}
|
||||
]
|
||||
+107
-15
@@ -79,7 +79,7 @@ body::-webkit-scrollbar-corner {
|
||||
.row.mainpage {
|
||||
position: absolute;
|
||||
margin-top: 0px;
|
||||
top: calc(calc(9vh + 2.5em) + 100px);
|
||||
top: calc(calc(9vh + 2.5em) + 60px);
|
||||
bottom: 50px;
|
||||
}
|
||||
|
||||
@@ -87,12 +87,72 @@ body::-webkit-scrollbar-corner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#searchInput {
|
||||
.search {
|
||||
margin-bottom: 20px;
|
||||
width: 40vh;
|
||||
height: 7vh;
|
||||
border-radius: 2vh;
|
||||
font-size: 3vh;
|
||||
display: flex;
|
||||
|
||||
|
||||
input {
|
||||
width: 40vh;
|
||||
height: 7.5vh;
|
||||
border-radius: 2vh;
|
||||
font-size: 3vh;
|
||||
cursor: text;
|
||||
border-top-right-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
transition: all 0.5s ease;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
margin-right: 2.5px;
|
||||
margin-left: calc(50vw - calc(44vh + 45px));
|
||||
background-color: var(--background-darker);
|
||||
}
|
||||
|
||||
input:focus {
|
||||
width: 50vh;
|
||||
margin-left: calc(50vw - calc(54vh + 45px));
|
||||
}
|
||||
|
||||
input::placeholder {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
input:focus::placeholder {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
select {
|
||||
height: 7.5vh;
|
||||
border-radius: 2vh;
|
||||
font-size: 3vh;
|
||||
background-color: var(--background-darker);
|
||||
margin-left: 0px;
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
button {
|
||||
text-align: center;
|
||||
box-shadow: 0.5vh 0.5vh 1vh 0vh var(--shadow-color);
|
||||
cursor: pointer;
|
||||
height: 7.5vh;
|
||||
background-color: var(--background-darker);
|
||||
color: var(--text);
|
||||
margin-left: 0px;
|
||||
border-radius: 0px;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
outline: none;
|
||||
border: none;
|
||||
margin-right: 2.5px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
button i {
|
||||
font-size: 3vh;
|
||||
}
|
||||
}
|
||||
|
||||
i {
|
||||
@@ -116,7 +176,7 @@ h1.title {
|
||||
hr {
|
||||
border: 0;
|
||||
height: 0.3vh;
|
||||
background-image: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0));
|
||||
background-image: var(--hr-style);
|
||||
}
|
||||
|
||||
.small {
|
||||
@@ -150,6 +210,27 @@ hr {
|
||||
margin-top: 2vh;
|
||||
}
|
||||
|
||||
.proxyinput-index {
|
||||
text-align: center;
|
||||
font-size: 2vh;
|
||||
box-shadow: 0.5vh 0.5vh 1vh 0vh var(--shadow-color);
|
||||
border: none;
|
||||
border-radius: 2vh;
|
||||
cursor: pointer;
|
||||
background: var(--sidebar-bg);
|
||||
width: 20vw;
|
||||
height: 6vh;
|
||||
color: var(--text);
|
||||
transition: 0.5s;
|
||||
margin: auto;
|
||||
margin: 2vh;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.proxyinput-index:focus {
|
||||
width: 30vw;
|
||||
}
|
||||
|
||||
button {
|
||||
text-align: center;
|
||||
border: none;
|
||||
@@ -178,6 +259,11 @@ input {
|
||||
transition: 0.5s;
|
||||
margin: auto;
|
||||
margin-top: 2vh;
|
||||
transition: border-color 0.4s linear;
|
||||
}
|
||||
|
||||
input:hover{
|
||||
border-color: var(--nav-hover);
|
||||
}
|
||||
|
||||
input::placeholder {
|
||||
@@ -212,10 +298,6 @@ select {
|
||||
margin-top: 2vh;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
@@ -306,7 +388,8 @@ input:checked+.slider:before {
|
||||
display: block;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: .4s;
|
||||
transition: all 0.5s ease;
|
||||
filter: brightness(100%);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
box-shadow: 0vh 0.75vh 1.5vh 0vh black;
|
||||
@@ -320,7 +403,7 @@ input:checked+.slider:before {
|
||||
}
|
||||
|
||||
.game:hover {
|
||||
filter: brightness(95%);
|
||||
filter: brightness(105%);
|
||||
transform: translateY(-0.2vh);
|
||||
border-color: #ffffff;
|
||||
}
|
||||
@@ -539,7 +622,6 @@ input:checked+.slider:before {
|
||||
color: var(--text);
|
||||
overflow: hidden;
|
||||
margin-left: 50px;
|
||||
margin-right: 25px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -591,7 +673,17 @@ img.featured:hover {
|
||||
margin-right: 100px;
|
||||
}
|
||||
|
||||
#changelog i {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
display: block;
|
||||
/*Converting percentage into px so text-overflow: ellipsis; will apply*/
|
||||
width: calc(100% - 1px + 1px);
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@keyframes beat {
|
||||
|
||||
0%,
|
||||
50%,
|
||||
100% {
|
||||
@@ -654,4 +746,4 @@ img.featured:hover {
|
||||
100% {
|
||||
transform: translate(1px, -2px) rotate(-1deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
-62
@@ -1,85 +1,85 @@
|
||||
@media (max-width:960px) {
|
||||
.navbar>.right {
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 960px) {
|
||||
.navbar > .right {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar {
|
||||
box-shadow: 0vh 0.5vh 0.75vh 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: 35px;
|
||||
color: rgb(255, 255, 255);
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
border-radius: 2vh;
|
||||
padding: 1.5em;
|
||||
padding-bottom: 1em;
|
||||
text-align: center;
|
||||
backdrop-filter: blur(7.1px);
|
||||
-webkit-backdrop-filter: blur(7.1px);
|
||||
box-shadow: 0vh 0.5vh 0.75vh 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: 40px;
|
||||
color: rgb(255, 255, 255);
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
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);
|
||||
color: black;
|
||||
backdrop-filter: blur(3px);
|
||||
-webkit-backdrop-filter: blur(3px);
|
||||
|
||||
background-color: var(--background-darker);
|
||||
color: black;
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.navbar>.title {
|
||||
margin: 1vh;
|
||||
.navbar > .title {
|
||||
margin: 1vh;
|
||||
}
|
||||
|
||||
.navbar>.title>img {
|
||||
width: 6vh;
|
||||
border-radius: 1vh;
|
||||
.navbar > .title > img {
|
||||
width: 6vh;
|
||||
border-radius: 1vh;
|
||||
}
|
||||
|
||||
.navbar>.title>span {
|
||||
font-family: 'Lato-Black';
|
||||
font-size: 3vh;
|
||||
left: 11vh;
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
.navbar > .title > span {
|
||||
font-family: "Lato-Black";
|
||||
font-size: 3vh;
|
||||
left: 11vh;
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.navbar>.title>span>span {
|
||||
display: flex;
|
||||
position: relative;
|
||||
font-size: 1.2vh;
|
||||
width: auto;
|
||||
.navbar > .title > span > span {
|
||||
display: flex;
|
||||
position: relative;
|
||||
font-size: 1.2vh;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.navbar>.right {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
margin: 2vh;
|
||||
margin-top: 2.5vh;
|
||||
margin-right: 3vh;
|
||||
.navbar > .right {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
margin: 2vh;
|
||||
margin-top: 2.5vh;
|
||||
margin-right: 3vh;
|
||||
}
|
||||
|
||||
.navbar>.right>a {
|
||||
border-style: solid;
|
||||
border-width: 0.5vh;
|
||||
margin: 0.3rem;
|
||||
padding: 0.8rem;
|
||||
cursor: pointer;
|
||||
font-size: 2.7vh;
|
||||
border-radius: 1.5vh;
|
||||
border-color: rgba(0, 0, 0, 0);
|
||||
transition: border-color 0.4s linear;
|
||||
.navbar > .right > a {
|
||||
border-style: solid;
|
||||
border-width: 0.3vh;
|
||||
margin: 0.3rem;
|
||||
padding: 0.8rem;
|
||||
cursor: pointer;
|
||||
font-size: 2.7vh;
|
||||
border-radius: 1.5vh;
|
||||
border-color: var(--button-bg);
|
||||
transition: border-color 0.4s linear;
|
||||
background-color: var(--button-bg);
|
||||
}
|
||||
|
||||
.navbar>.right>a:hover {
|
||||
border-color: rgba(255, 255, 255, 1);
|
||||
.navbar > .right > a:hover {
|
||||
border-color: var(--nav-hover);
|
||||
}
|
||||
|
||||
.navbar>.right>a.active {
|
||||
border-color: rgba(255, 255, 255, 1);
|
||||
.navbar > .right > a.active {
|
||||
border-color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
@@ -1,33 +1,36 @@
|
||||
body[data-theme='dark'] {
|
||||
--background-color: rgba(0, 0, 0, 0.8);
|
||||
--background-darker: rgba(26, 25, 32, 0.75);
|
||||
--background-color: rgba(17, 22, 31, 0.8);
|
||||
--background-darker: rgba(0, 0, 0, 0.9);
|
||||
--text: #fff;
|
||||
--sidebar-bg: #161f2eef;
|
||||
--button-bg: #1c1c1c69;
|
||||
--button-bg: #44385e69;
|
||||
--shadow-color: #000;
|
||||
--switch-color: #42424259;
|
||||
--switch-active: #2196F3;
|
||||
--nav-hover: #2196F3;
|
||||
--scrollbar-color: #ffffff59;
|
||||
--solid: #1b2735;
|
||||
--hover: #757575;
|
||||
--hr-style: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0));
|
||||
|
||||
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: rgba(255, 255, 255, 0.8);
|
||||
--background-darker: rgba(235, 235, 235, 0.8);
|
||||
--background-color: #fff;
|
||||
--background-darker: var(--background-color);
|
||||
--text: #000;
|
||||
--hover: #757575;
|
||||
--sidebar-bg: #ffffffee;
|
||||
--sidebar-bg: #e9e9e9ee;
|
||||
--button-bg: #ecececee;
|
||||
--shadow-color: #c9c9c9;
|
||||
--switch-color: #111111b0;
|
||||
--nav-hover: #9c9c9c;
|
||||
--switch-active: #2196F3;
|
||||
--scrollbar-color: #4242424b;
|
||||
--solid: #ffffffee;
|
||||
--hover: #757575;
|
||||
--hr-style: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.75), rgba(255, 255, 255, 0));
|
||||
|
||||
background: radial-gradient(ellipse at bottom, #b1b1b1 0%, #f6f5f0 100%);
|
||||
background-repeat: no-repeat;
|
||||
@@ -213,8 +216,68 @@ body[data-theme='violet'] {
|
||||
}
|
||||
}
|
||||
|
||||
body[data-theme='cyan'] {
|
||||
--background-color: rgba(0, 0, 0, 0.8);
|
||||
--background-darker: rgba(0, 0, 0, 0.9);
|
||||
--text: #fff;
|
||||
--sidebar-bg: #000000;
|
||||
--button-bg: #000000;
|
||||
--shadow-color: #1f4e4c;
|
||||
--switch-color: #00404b;
|
||||
--switch-active: #00fff2;
|
||||
--scrollbar-color: #000000;
|
||||
--solid: #000000;
|
||||
--hover: #8fe0dc;
|
||||
background: linear-gradient(90deg, rgb(94, 255, 247) 0%, rgb(78, 138, 157) 85%);
|
||||
animation: cyan-gradient 12s ease infinite;
|
||||
|
||||
@keyframes cyan-gradient {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body[data-theme='bronze'] {
|
||||
--background-color: rgba(0, 0, 0, 0.8);
|
||||
--background-darker: rgba(0, 0, 0, 0.9);
|
||||
--text: #fff;
|
||||
--sidebar-bg: #000000;
|
||||
--button-bg: #000000;
|
||||
--shadow-color: #4c2b04;
|
||||
--switch-color: #643c00;
|
||||
--switch-active: #ffa318;
|
||||
--scrollbar-color: #000000;
|
||||
--solid: #000000;
|
||||
--hover: #ffb74a;
|
||||
background: linear-gradient(90deg, rgb(253, 135, 1) 0%, rgb(58, 32, 3));
|
||||
animation: bronze-gradient 12s ease infinite;
|
||||
|
||||
@keyframes bronze-gradient {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (prefers-color-scheme: light) {
|
||||
body[data-theme='light'] {
|
||||
body[data-theme='system-default'] {
|
||||
--background-color: #fff;
|
||||
--background-darker: var(--background-color);
|
||||
--text: #000;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 49 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 MiB |
@@ -9,7 +9,6 @@ const load = () => fetch('/api/apps').then(res => res.json()).then(apps => {
|
||||
|
||||
const image = document.createElement('img');
|
||||
image.src = app.image;
|
||||
image.loading = 'lazy';
|
||||
image.onerror = () => image.src = '/assets/img/logo.png';
|
||||
el.appendChild(image);
|
||||
|
||||
@@ -28,8 +27,6 @@ const load = () => fetch('/api/apps').then(res => res.json()).then(apps => {
|
||||
el.addEventListener('click', async () => {
|
||||
document.body.style.opacity = '0.7';
|
||||
|
||||
umami.track('app_' + app.name);
|
||||
|
||||
setTimeout(() => {
|
||||
if (isValidURL(app.target)) createViewPage({
|
||||
target: app.target,
|
||||
|
||||
@@ -0,0 +1,610 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === "object" && typeof module !== "undefined"
|
||||
? factory(exports)
|
||||
: typeof define === "function" && define.amd
|
||||
? define(["exports"], factory)
|
||||
: ((global =
|
||||
typeof globalThis !== "undefined" ? globalThis : global || self),
|
||||
factory((global.BareMod = {})));
|
||||
})(this, function (exports) {
|
||||
"use strict";
|
||||
|
||||
// The user likely has overwritten all networking functions after importing bare-client
|
||||
// It is our responsibility to make sure components of Bare-Client are using native networking functions
|
||||
// These exports are provided to plugins by @rollup/plugin-inject
|
||||
const fetch = globalThis.fetch;
|
||||
const WebSocket = globalThis.WebSocket;
|
||||
const WebSocketFields = {
|
||||
prototype: {
|
||||
send: WebSocket.prototype.send
|
||||
},
|
||||
CLOSED: WebSocket.CLOSED,
|
||||
CLOSING: WebSocket.CLOSING,
|
||||
CONNECTING: WebSocket.CONNECTING,
|
||||
OPEN: WebSocket.OPEN
|
||||
};
|
||||
|
||||
class BareError extends Error {
|
||||
status;
|
||||
body;
|
||||
constructor(status, body) {
|
||||
super(body.message || body.code);
|
||||
this.status = status;
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
class Client {
|
||||
base;
|
||||
/**
|
||||
*
|
||||
* @param version Version provided by extension
|
||||
* @param server Bare Server URL provided by BareClient
|
||||
*/
|
||||
constructor(version, server) {
|
||||
this.base = new URL(`./v${version}/`, server);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* JavaScript MD5
|
||||
* Adopted from https://github.com/blueimp/JavaScript-MD5
|
||||
*
|
||||
* Copyright 2011, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
* Based on
|
||||
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
||||
* Digest Algorithm, as defined in RFC 1321.
|
||||
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
|
||||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||||
* Distributed under the BSD License
|
||||
* See http://pajhome.org.uk/crypt/md5 for more info.
|
||||
*/
|
||||
/**
|
||||
* Add integers, wrapping at 2^32.
|
||||
* This uses 16-bit operations internally to work around bugs in interpreters.
|
||||
*
|
||||
* @param x First integer
|
||||
* @param y Second integer
|
||||
* @returns Sum
|
||||
*/
|
||||
function safeAdd(x, y) {
|
||||
const lsw = (x & 0xffff) + (y & 0xffff);
|
||||
const msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||||
return (msw << 16) | (lsw & 0xffff);
|
||||
}
|
||||
/**
|
||||
* Bitwise rotate a 32-bit number to the left.
|
||||
*
|
||||
* @param num 32-bit number
|
||||
* @param cnt Rotation count
|
||||
* @returns Rotated number
|
||||
*/
|
||||
function bitRotateLeft(num, cnt) {
|
||||
return (num << cnt) | (num >>> (32 - cnt));
|
||||
}
|
||||
/**
|
||||
* Basic operation the algorithm uses.
|
||||
*
|
||||
* @param q q
|
||||
* @param a a
|
||||
* @param b b
|
||||
* @param x x
|
||||
* @param s s
|
||||
* @param t t
|
||||
* @returns Result
|
||||
*/
|
||||
function md5cmn(q, a, b, x, s, t) {
|
||||
return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
|
||||
}
|
||||
/**
|
||||
* Basic operation the algorithm uses.
|
||||
*
|
||||
* @param a a
|
||||
* @param b b
|
||||
* @param c c
|
||||
* @param d d
|
||||
* @param x x
|
||||
* @param s s
|
||||
* @param t t
|
||||
* @returns Result
|
||||
*/
|
||||
function md5ff(a, b, c, d, x, s, t) {
|
||||
return md5cmn((b & c) | (~b & d), a, b, x, s, t);
|
||||
}
|
||||
/**
|
||||
* Basic operation the algorithm uses.
|
||||
*
|
||||
* @param a a
|
||||
* @param b b
|
||||
* @param c c
|
||||
* @param d d
|
||||
* @param x x
|
||||
* @param s s
|
||||
* @param t t
|
||||
* @returns Result
|
||||
*/
|
||||
function md5gg(a, b, c, d, x, s, t) {
|
||||
return md5cmn((b & d) | (c & ~d), a, b, x, s, t);
|
||||
}
|
||||
/**
|
||||
* Basic operation the algorithm uses.
|
||||
*
|
||||
* @param a a
|
||||
* @param b b
|
||||
* @param c c
|
||||
* @param d d
|
||||
* @param x x
|
||||
* @param s s
|
||||
* @param t t
|
||||
* @returns Result
|
||||
*/
|
||||
function md5hh(a, b, c, d, x, s, t) {
|
||||
return md5cmn(b ^ c ^ d, a, b, x, s, t);
|
||||
}
|
||||
/**
|
||||
* Basic operation the algorithm uses.
|
||||
*
|
||||
* @param a a
|
||||
* @param b b
|
||||
* @param c c
|
||||
* @param d d
|
||||
* @param x x
|
||||
* @param s s
|
||||
* @param t t
|
||||
* @returns Result
|
||||
*/
|
||||
function md5ii(a, b, c, d, x, s, t) {
|
||||
return md5cmn(c ^ (b | ~d), a, b, x, s, t);
|
||||
}
|
||||
/**
|
||||
* Calculate the MD5 of an array of little-endian words, and a bit length.
|
||||
*
|
||||
* @param x Array of little-endian words
|
||||
* @param len Bit length
|
||||
* @returns MD5 Array
|
||||
*/
|
||||
function binlMD5(x, len) {
|
||||
/* append padding */
|
||||
x[len >> 5] |= 0x80 << len % 32;
|
||||
x[(((len + 64) >>> 9) << 4) + 14] = len;
|
||||
let a = 1732584193;
|
||||
let b = -271733879;
|
||||
let c = -1732584194;
|
||||
let d = 271733878;
|
||||
for (let i = 0; i < x.length; i += 16) {
|
||||
const olda = a;
|
||||
const oldb = b;
|
||||
const oldc = c;
|
||||
const oldd = d;
|
||||
a = md5ff(a, b, c, d, x[i], 7, -680876936);
|
||||
d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
|
||||
c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
|
||||
b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
|
||||
a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
|
||||
d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
|
||||
c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
|
||||
b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
|
||||
a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
|
||||
d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
|
||||
c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
|
||||
b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
|
||||
a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
|
||||
d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
|
||||
c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
|
||||
b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
|
||||
a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
|
||||
d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
|
||||
c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
|
||||
b = md5gg(b, c, d, a, x[i], 20, -373897302);
|
||||
a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
|
||||
d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
|
||||
c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
|
||||
b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
|
||||
a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
|
||||
d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
|
||||
c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
|
||||
b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
|
||||
a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
|
||||
d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
|
||||
c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
|
||||
b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
|
||||
a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
|
||||
d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
|
||||
c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
|
||||
b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
|
||||
a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
|
||||
d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
|
||||
c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
|
||||
b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
|
||||
a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
|
||||
d = md5hh(d, a, b, c, x[i], 11, -358537222);
|
||||
c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
|
||||
b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
|
||||
a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
|
||||
d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
|
||||
c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
|
||||
b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
|
||||
a = md5ii(a, b, c, d, x[i], 6, -198630844);
|
||||
d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
|
||||
c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
|
||||
b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
|
||||
a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
|
||||
d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
|
||||
c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
|
||||
b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
|
||||
a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
|
||||
d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
|
||||
c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
|
||||
b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
|
||||
a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
|
||||
d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
|
||||
c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
|
||||
b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
|
||||
a = safeAdd(a, olda);
|
||||
b = safeAdd(b, oldb);
|
||||
c = safeAdd(c, oldc);
|
||||
d = safeAdd(d, oldd);
|
||||
}
|
||||
return [a, b, c, d];
|
||||
}
|
||||
/**
|
||||
* Convert an array of little-endian words to a string
|
||||
*
|
||||
* @param input MD5 Array
|
||||
* @returns MD5 string
|
||||
*/
|
||||
function binl2rstr(input) {
|
||||
let output = "";
|
||||
const length32 = input.length * 32;
|
||||
for (let i = 0; i < length32; i += 8) {
|
||||
output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
/**
|
||||
* Convert a raw string to an array of little-endian words
|
||||
* Characters >255 have their high-byte silently ignored.
|
||||
*
|
||||
* @param input Raw input string
|
||||
* @returns Array of little-endian words
|
||||
*/
|
||||
function rstr2binl(input) {
|
||||
const output = [];
|
||||
const outputLen = input.length >> 2;
|
||||
for (let i = 0; i < outputLen; i += 1) {
|
||||
output[i] = 0;
|
||||
}
|
||||
const length8 = input.length * 8;
|
||||
for (let i = 0; i < length8; i += 8) {
|
||||
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
/**
|
||||
* Calculate the MD5 of a raw string
|
||||
*
|
||||
* @param s Input string
|
||||
* @returns Raw MD5 string
|
||||
*/
|
||||
function rstrMD5(s) {
|
||||
return binl2rstr(binlMD5(rstr2binl(s), s.length * 8));
|
||||
}
|
||||
/**
|
||||
* Calculates the HMAC-MD5 of a key and some data (raw strings)
|
||||
*
|
||||
* @param key HMAC key
|
||||
* @param data Raw input string
|
||||
* @returns Raw MD5 string
|
||||
*/
|
||||
function rstrHMACMD5(key, data) {
|
||||
let bkey = rstr2binl(key);
|
||||
const ipad = [];
|
||||
const opad = [];
|
||||
if (bkey.length > 16) {
|
||||
bkey = binlMD5(bkey, key.length * 8);
|
||||
}
|
||||
for (let i = 0; i < 16; i += 1) {
|
||||
ipad[i] = bkey[i] ^ 0x36363636;
|
||||
opad[i] = bkey[i] ^ 0x5c5c5c5c;
|
||||
}
|
||||
const hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
|
||||
return binl2rstr(binlMD5(opad.concat(hash), 512 + 128));
|
||||
}
|
||||
/**
|
||||
* Convert a raw string to a hex string
|
||||
*
|
||||
* @param input Raw input string
|
||||
* @returns Hex encoded string
|
||||
*/
|
||||
function rstr2hex(input) {
|
||||
const hexTab = "0123456789abcdef";
|
||||
let output = "";
|
||||
for (let i = 0; i < input.length; i += 1) {
|
||||
const x = input.charCodeAt(i);
|
||||
output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
/**
|
||||
* Encode a string as UTF-8
|
||||
*
|
||||
* @param input Input string
|
||||
* @returns UTF8 string
|
||||
*/
|
||||
function str2rstrUTF8(input) {
|
||||
return unescape(encodeURIComponent(input));
|
||||
}
|
||||
/**
|
||||
* Encodes input string as raw MD5 string
|
||||
*
|
||||
* @param s Input string
|
||||
* @returns Raw MD5 string
|
||||
*/
|
||||
function rawMD5(s) {
|
||||
return rstrMD5(str2rstrUTF8(s));
|
||||
}
|
||||
/**
|
||||
* Encodes input string as Hex encoded string
|
||||
*
|
||||
* @param s Input string
|
||||
* @returns Hex encoded string
|
||||
*/
|
||||
function hexMD5(s) {
|
||||
return rstr2hex(rawMD5(s));
|
||||
}
|
||||
/**
|
||||
* Calculates the raw HMAC-MD5 for the given key and data
|
||||
*
|
||||
* @param k HMAC key
|
||||
* @param d Input string
|
||||
* @returns Raw MD5 string
|
||||
*/
|
||||
function rawHMACMD5(k, d) {
|
||||
return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d));
|
||||
}
|
||||
/**
|
||||
* Calculates the Hex encoded HMAC-MD5 for the given key and data
|
||||
*
|
||||
* @param k HMAC key
|
||||
* @param d Input string
|
||||
* @returns Raw MD5 string
|
||||
*/
|
||||
function hexHMACMD5(k, d) {
|
||||
return rstr2hex(rawHMACMD5(k, d));
|
||||
}
|
||||
/**
|
||||
* Calculates MD5 value for a given string.
|
||||
* If a key is provided, calculates the HMAC-MD5 value.
|
||||
* Returns a Hex encoded string unless the raw argument is given.
|
||||
*
|
||||
* @param string Input string
|
||||
* @param key HMAC key
|
||||
* @param raw Raw output switch
|
||||
* @returns MD5 output
|
||||
*/
|
||||
function md5(string, key, raw) {
|
||||
if (!key) {
|
||||
if (!raw) {
|
||||
return hexMD5(string);
|
||||
}
|
||||
return rawMD5(string);
|
||||
}
|
||||
if (!raw) {
|
||||
return hexHMACMD5(key, string);
|
||||
}
|
||||
return rawHMACMD5(key, string);
|
||||
}
|
||||
|
||||
const MAX_HEADER_VALUE = 3072;
|
||||
/**
|
||||
*
|
||||
* Splits headers according to spec
|
||||
* @param headers
|
||||
* @returns Split headers
|
||||
*/
|
||||
function splitHeaders(headers) {
|
||||
const output = new Headers(headers);
|
||||
if (headers.has("x-bare-headers")) {
|
||||
const value = headers.get("x-bare-headers");
|
||||
if (value.length > MAX_HEADER_VALUE) {
|
||||
output.delete("x-bare-headers");
|
||||
let split = 0;
|
||||
for (let i = 0; i < value.length; i += MAX_HEADER_VALUE) {
|
||||
const part = value.slice(i, i + MAX_HEADER_VALUE);
|
||||
const id = split++;
|
||||
output.set(`x-bare-headers-${id}`, `;${part}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
/**
|
||||
* Joins headers according to spec
|
||||
* @param headers
|
||||
* @returns Joined headers
|
||||
*/
|
||||
function joinHeaders(headers) {
|
||||
const output = new Headers(headers);
|
||||
const prefix = "x-bare-headers";
|
||||
if (headers.has(`${prefix}-0`)) {
|
||||
const join = [];
|
||||
for (const [header, value] of headers) {
|
||||
if (!header.startsWith(prefix)) {
|
||||
continue;
|
||||
}
|
||||
if (!value.startsWith(";")) {
|
||||
throw new BareError(400, {
|
||||
code: "INVALID_BARE_HEADER",
|
||||
id: `request.headers.${header}`,
|
||||
message: `Value didn't begin with semi-colon.`
|
||||
});
|
||||
}
|
||||
const id = parseInt(header.slice(prefix.length + 1));
|
||||
join[id] = value.slice(1);
|
||||
output.delete(header);
|
||||
}
|
||||
output.set(prefix, join.join(""));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
class ClientV3 extends Client {
|
||||
ws;
|
||||
http;
|
||||
meta() {
|
||||
return {};
|
||||
}
|
||||
constructor(server) {
|
||||
super(3, server);
|
||||
this.ws = new URL(this.base);
|
||||
this.http = new URL(this.base);
|
||||
if (this.ws.protocol === "https:") {
|
||||
this.ws.protocol = "wss:";
|
||||
} else {
|
||||
this.ws.protocol = "ws:";
|
||||
}
|
||||
}
|
||||
ready = true;
|
||||
async init() {
|
||||
this.ready = true;
|
||||
}
|
||||
connect(
|
||||
url,
|
||||
origin,
|
||||
protocols,
|
||||
requestHeaders,
|
||||
onopen,
|
||||
onmessage,
|
||||
onclose,
|
||||
onerror
|
||||
) {
|
||||
const ws = new WebSocket(this.ws);
|
||||
const cleanup = () => {
|
||||
ws.removeEventListener("close", closeListener);
|
||||
ws.removeEventListener("message", messageListener);
|
||||
};
|
||||
const closeListener = () => {
|
||||
cleanup();
|
||||
};
|
||||
const messageListener = (event) => {
|
||||
cleanup();
|
||||
// ws.binaryType is irrelevant when sending text
|
||||
if (typeof event.data !== "string")
|
||||
throw new TypeError(
|
||||
"the first websocket message was not a text frame"
|
||||
);
|
||||
const message = JSON.parse(event.data);
|
||||
// finally
|
||||
if (message.type !== "open")
|
||||
throw new TypeError("message was not of open type");
|
||||
// onMeta({
|
||||
// protocol: message.protocol,
|
||||
// setCookies: message.setCookies,
|
||||
// });
|
||||
onopen(message.protocol);
|
||||
// TODO
|
||||
ws.addEventListener("message", (ev) => {
|
||||
onmessage(ev.data);
|
||||
});
|
||||
};
|
||||
ws.addEventListener("close", closeListener);
|
||||
ws.addEventListener("message", messageListener);
|
||||
// CONNECTED TO THE BARE SERVER, NOT THE REMOTE
|
||||
ws.addEventListener(
|
||||
"open",
|
||||
(event) => {
|
||||
// getRequestHeaders().then((headers:any) =>
|
||||
WebSocketFields.prototype.send.call(
|
||||
ws,
|
||||
JSON.stringify({
|
||||
type: "connect",
|
||||
remote: url.toString(),
|
||||
protocols,
|
||||
headers: requestHeaders,
|
||||
forwardHeaders: []
|
||||
})
|
||||
);
|
||||
// );
|
||||
},
|
||||
// only block the open event once
|
||||
{ once: true }
|
||||
);
|
||||
return ws.send.bind(ws);
|
||||
}
|
||||
async request(remote, method, body, headers, signal) {
|
||||
const options = {
|
||||
credentials: "omit",
|
||||
method: method,
|
||||
signal
|
||||
};
|
||||
if (body !== undefined) {
|
||||
options.body = body;
|
||||
}
|
||||
options.headers = this.createBareHeaders(remote, headers);
|
||||
const response = await fetch(
|
||||
this.http + "?cache=" + md5(remote.toString()),
|
||||
options
|
||||
);
|
||||
const readResponse = await this.readBareResponse(response);
|
||||
// const result: Response & Partial<BareResponse> = new Response(
|
||||
// statusEmpty.includes(readResponse.status!) ? undefined : response.body,
|
||||
// {
|
||||
// status: readResponse.status,
|
||||
// statusText: readResponse.statusText ?? undefined,
|
||||
// headers: new Headers(readResponse.headers as HeadersInit),
|
||||
// }
|
||||
// );
|
||||
//
|
||||
// result.rawHeaders = readResponse.headers;
|
||||
// result.rawResponse = response;
|
||||
return {
|
||||
body: response.body,
|
||||
headers: readResponse.headers,
|
||||
status: readResponse.status,
|
||||
statusText: readResponse.statusText
|
||||
};
|
||||
}
|
||||
async readBareResponse(response) {
|
||||
if (!response.ok) {
|
||||
throw new BareError(response.status, await response.json());
|
||||
}
|
||||
const responseHeaders = joinHeaders(response.headers);
|
||||
const result = {};
|
||||
const xBareStatus = responseHeaders.get("x-bare-status");
|
||||
if (xBareStatus !== null) result.status = parseInt(xBareStatus);
|
||||
const xBareStatusText = responseHeaders.get("x-bare-status-text");
|
||||
if (xBareStatusText !== null) result.statusText = xBareStatusText;
|
||||
const xBareHeaders = responseHeaders.get("x-bare-headers");
|
||||
if (xBareHeaders !== null) result.headers = JSON.parse(xBareHeaders);
|
||||
return result;
|
||||
}
|
||||
createBareHeaders(
|
||||
remote,
|
||||
bareHeaders,
|
||||
forwardHeaders = [],
|
||||
passHeaders = [],
|
||||
passStatus = []
|
||||
) {
|
||||
const headers = new Headers();
|
||||
headers.set("x-bare-url", remote.toString());
|
||||
headers.set("x-bare-headers", JSON.stringify(bareHeaders));
|
||||
for (const header of forwardHeaders) {
|
||||
headers.append("x-bare-forward-headers", header);
|
||||
}
|
||||
for (const header of passHeaders) {
|
||||
headers.append("x-bare-pass-headers", header);
|
||||
}
|
||||
for (const status of passStatus) {
|
||||
headers.append("x-bare-pass-status", status.toString());
|
||||
}
|
||||
splitHeaders(headers);
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
|
||||
exports.BareClient = ClientV3;
|
||||
});
|
||||
@@ -10,7 +10,6 @@ const load = () => fetch('/api/cheats')
|
||||
|
||||
const image = document.createElement('img');
|
||||
image.src = cheat.image;
|
||||
image.loading = 'lazy';
|
||||
image.onerror = () => image.src = '/assets/img/logo.png';
|
||||
el.appendChild(image);
|
||||
|
||||
@@ -29,8 +28,6 @@ const load = () => fetch('/api/cheats')
|
||||
el.addEventListener('click', () => {
|
||||
document.body.style.opacity = '0.7';
|
||||
|
||||
umami.track('cheat_' + cheat.name);
|
||||
|
||||
setTimeout(() => {
|
||||
if (isValidURL(cheat.target)) createViewPage({
|
||||
target: cheat.target,
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
/**
|
||||
* @typedef easterEgg
|
||||
* @type {object}
|
||||
* @property {'keybind' | 'click'} easterEgg.type
|
||||
* @property {'keybind' | 'date'} easterEgg.type
|
||||
* @property {string} easterEgg.phrase
|
||||
* @property {string} easterEgg.date
|
||||
* @property {number} easterEgg.clickCount
|
||||
* @property {object} easterEgg.element
|
||||
* @property {object} easterEgg.variables
|
||||
@@ -55,6 +56,31 @@ const utils = {
|
||||
return {
|
||||
remove: () => window.removeEventListener(listener)
|
||||
};
|
||||
},
|
||||
/**
|
||||
* @param {string} date
|
||||
* @param {easterEgg['run']} script
|
||||
*/
|
||||
createDate: async (date, script) => {
|
||||
date = date.split('/');
|
||||
|
||||
if (date.length === 3) {
|
||||
const day = date[1] === '*' ? new Date().getDate() : date[1];
|
||||
const month = date[0] === '*' ? new Date().getMonth() : date[0];
|
||||
const year = date[2] === '*' ? new Date().getFullYear() : date[2];
|
||||
|
||||
if (!utils.easterEggActive && (new Date().getDate() === day && new Date().getMonth() === month && new Date().getFullYear() === year)) {
|
||||
try {
|
||||
await script({
|
||||
remove: () => window.removeEventListener('keydown', listener, true)
|
||||
});
|
||||
|
||||
utils.easterEggActive = false;
|
||||
} catch (e) {
|
||||
utils.easterEggActive = false;
|
||||
}
|
||||
}
|
||||
} else throw new Error('Invalid date');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -386,10 +412,24 @@ easterEggs.push({
|
||||
})
|
||||
});
|
||||
|
||||
easterEggs.push({
|
||||
type: 'date',
|
||||
date: '4/1/*',
|
||||
run: () => {
|
||||
// April fools =)
|
||||
}
|
||||
});
|
||||
|
||||
export default () => easterEggs.forEach(easterEgg => {
|
||||
if (easterEgg.type === 'keybind') {
|
||||
utils.createKeybind(easterEgg.phrase, easterEgg.run);
|
||||
|
||||
try {
|
||||
easterEgg.preload();
|
||||
} catch (e) { }
|
||||
} else if (easterEgg.type === 'date') {
|
||||
utils.createDate(easterEgg.date, easterEgg.run);
|
||||
|
||||
try {
|
||||
easterEgg.preload();
|
||||
} catch (e) { }
|
||||
|
||||
+103
-12
@@ -1,17 +1,79 @@
|
||||
import { createViewPage, isValidURL, PolarisError } from './utils.js';
|
||||
import { createViewPage, isValidURL, PolarisError, storage } from './utils.js';
|
||||
import effects from './effects.js';
|
||||
|
||||
const settingsStorage = storage('settings');
|
||||
|
||||
const load = () => {
|
||||
const sortListener = document.querySelector('#searchSort').addEventListener('change', () => {
|
||||
settingsStorage.set('game_sort', document.querySelector('#searchSort').value);
|
||||
|
||||
const games = document.querySelectorAll('.games>.game');
|
||||
|
||||
for (let i = 0; i < games.length; i++) games[i].remove();
|
||||
|
||||
fetch('/api/games')
|
||||
.then(res => res.json())
|
||||
.then(games => {
|
||||
if (settingsStorage.get('game_sort') === 'abc') games.all.sort((a, b) => a.name.localeCompare(b.name));
|
||||
if (settingsStorage.get('game_sort') === 'newest') games.all.reverse();
|
||||
|
||||
games.all.forEach(game => {
|
||||
const el = document.createElement('div');
|
||||
el.classList = 'game';
|
||||
document.querySelector('.games').appendChild(el);
|
||||
|
||||
const image = document.createElement('img');
|
||||
image.src = game.image;
|
||||
image.loading = 'lazy';
|
||||
image.onerror = () => image.src = '/assets/img/logo.png';
|
||||
el.appendChild(image);
|
||||
|
||||
const name = document.createElement('h3');
|
||||
name.textContent = game.name;
|
||||
el.appendChild(name);
|
||||
|
||||
effects.hoverTilt({
|
||||
max: 8,
|
||||
perspective: 1000,
|
||||
scale: 1.05,
|
||||
speed: 800,
|
||||
easing: 'cubic-bezier(.03,.98,.52,.99)'
|
||||
}, el);
|
||||
|
||||
el.addEventListener('click', async () => {
|
||||
document.body.style.opacity = '0.7';
|
||||
|
||||
setTimeout(() => {
|
||||
if (isValidURL(game.target)) createViewPage({
|
||||
target: game.target,
|
||||
title: game.name,
|
||||
proxied: true
|
||||
});
|
||||
else createViewPage({
|
||||
target: game.target,
|
||||
title: game.name
|
||||
});
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
if (!settingsStorage.get('game_sort')) settingsStorage.set('game_sort', 'none');
|
||||
|
||||
document.querySelector('#searchSort').value = settingsStorage.get('game_sort');
|
||||
|
||||
fetch('/api/games')
|
||||
.then(res => res.json())
|
||||
.then(games => {
|
||||
if (settingsStorage.get('game_sort') === 'abc') games.all.sort((a, b) => a.name.localeCompare(b.name));
|
||||
if (settingsStorage.get('game_sort') === 'newest') games.all.reverse();
|
||||
|
||||
const searchBar = document.querySelector('#searchInput');
|
||||
|
||||
searchBar.setAttribute('placeholder', `Search ${games.all.length} Games`);
|
||||
|
||||
searchBar.addEventListener('input', () => {
|
||||
console.log(searchBar.value);
|
||||
|
||||
if (searchBar.value) {
|
||||
var result = false;
|
||||
|
||||
@@ -36,10 +98,9 @@ const load = () => {
|
||||
const popularEl = document.createElement('div');
|
||||
popularEl.classList = 'game';
|
||||
document.querySelector('.popular-games').appendChild(popularEl);
|
||||
|
||||
|
||||
const image = document.createElement('img');
|
||||
image.src = game.image;
|
||||
image.loading = 'lazy';
|
||||
image.onerror = () => image.src = '/assets/img/logo.png';
|
||||
popularEl.appendChild(image);
|
||||
|
||||
@@ -50,17 +111,17 @@ const load = () => {
|
||||
popularEl.addEventListener('click', async () => {
|
||||
document.body.style.opacity = '0.7';
|
||||
|
||||
umami.track('popular-game_' + game.name);
|
||||
|
||||
setTimeout(() => {
|
||||
if (isValidURL(game.target)) createViewPage({
|
||||
target: game.target,
|
||||
title: game.name,
|
||||
image: game.image,
|
||||
proxied: true
|
||||
});
|
||||
else createViewPage({
|
||||
target: game.target,
|
||||
title: game.name
|
||||
title: game.name,
|
||||
image: game.image
|
||||
});
|
||||
}, 500);
|
||||
});
|
||||
@@ -81,7 +142,6 @@ const load = () => {
|
||||
|
||||
const image = document.createElement('img');
|
||||
image.src = game.image;
|
||||
image.loading = 'lazy';
|
||||
image.onerror = () => image.src = '/assets/img/logo.png';
|
||||
el.appendChild(image);
|
||||
|
||||
@@ -100,8 +160,6 @@ const load = () => {
|
||||
el.addEventListener('click', async () => {
|
||||
document.body.style.opacity = '0.7';
|
||||
|
||||
umami.track('game-' + game.name);
|
||||
|
||||
setTimeout(() => {
|
||||
if (isValidURL(game.target)) createViewPage({
|
||||
target: game.target,
|
||||
@@ -117,8 +175,41 @@ const load = () => {
|
||||
});
|
||||
})
|
||||
.catch(e => new PolarisError('Failed to load games'));
|
||||
|
||||
document.querySelector('#randomGame').addEventListener('click', () => {
|
||||
const games = document.querySelectorAll('.games>.game');
|
||||
|
||||
if (games.length > 0) {
|
||||
const randomGame = games[Math.floor(Math.random() * games.length)];
|
||||
|
||||
randomGame.click();
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
const loadGameFromURL = () => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const gameName = urlParams.get('game');
|
||||
|
||||
if (!gameName) {
|
||||
throw new PolarisError('No game specified in the URL');
|
||||
}
|
||||
|
||||
fetch('/assets/JSON/games.json')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
const game = data.find(g => g.name === decodeURIComponent(gameName));
|
||||
|
||||
if (!game) {
|
||||
throw new PolarisError(`Game "${gameName}" not found`);
|
||||
}
|
||||
|
||||
renderGames([game]);
|
||||
})
|
||||
.catch(e => new PolarisError('Failed to load game'));
|
||||
};
|
||||
|
||||
export default {
|
||||
load
|
||||
load,
|
||||
loadGameFromURL
|
||||
};
|
||||
+22
-27
@@ -7,7 +7,7 @@ import Cheats from './cheats.js';
|
||||
import Games from './games.js';
|
||||
import Apps from './apps.js';
|
||||
|
||||
await loadAnalytics();
|
||||
loadAnalytics();
|
||||
|
||||
if (location.pathname !== '/view') loadSidebarInterface();
|
||||
loadEasterEggs();
|
||||
@@ -35,20 +35,19 @@ window.addEventListener('beforeunload', (e) => {
|
||||
if (settingsStorage.get('prevent_close')) {
|
||||
e.preventDefault();
|
||||
|
||||
document.body.style.opacity = '1';
|
||||
|
||||
return e;
|
||||
}
|
||||
});
|
||||
|
||||
setInterval(() => {
|
||||
if (sessionStorage.getItem('was_closing') === 'true') document.body.style.opacity = '1';
|
||||
preventClose = settingsStorage.get('prevent_close');
|
||||
}, 1);
|
||||
|
||||
/*await navigator.serviceWorker.register('/assets/js/offline.js', {
|
||||
scope: '/'
|
||||
});*/
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => setTimeout(() => document.body.style.opacity = 1, 1000));
|
||||
window.addEventListener('load', () => setTimeout(() => document.body.style.opacity = 1, 1000));
|
||||
|
||||
setTimeout(() => document.body.style.opacity = 1, 5000);
|
||||
|
||||
/**
|
||||
* @param {HTMLAnchorElement} hyperlink
|
||||
@@ -106,15 +105,10 @@ const hyperlinkHandler = (hyperlink, e) => {
|
||||
|
||||
document.querySelectorAll('a').forEach(hyperlink => hyperlink.addEventListener('click', (e) => hyperlinkHandler(hyperlink, e)));
|
||||
|
||||
window.onhashchange = () => {
|
||||
if (location.hash === '#settings') {
|
||||
document.querySelector('.sidebar').classList.add('active');
|
||||
umami.track('sidebar-open');
|
||||
} else {
|
||||
document.querySelector('.sidebar').classList.remove('active');
|
||||
umami.track('sidebar-close');
|
||||
}
|
||||
};
|
||||
window.addEventListener('hashchange', () => {
|
||||
if (location.hash === '#settings') document.querySelector('.sidebar').classList.add('active');
|
||||
else document.querySelector('.sidebar').classList.remove('active');
|
||||
});
|
||||
|
||||
if (window.self === window.top && location.pathname !== '/view') setTimeout(async () => {
|
||||
loadSettings();
|
||||
@@ -138,14 +132,12 @@ if (location.pathname === '/') {
|
||||
fetch('/api/games')
|
||||
.then(res => res.json())
|
||||
.then(games => {
|
||||
const gameName = '99 Balls 3D';
|
||||
const gameName = 'Stickman Archero Fight';
|
||||
const game = games.all.filter(g => g.name === gameName)[0];
|
||||
|
||||
document.querySelector('.featured').addEventListener('click', () => {
|
||||
document.body.style.opacity = '0.7';
|
||||
|
||||
umami.track('featured-game_' + game.name);
|
||||
|
||||
setTimeout(() => {
|
||||
if (isValidURL(game.target)) createViewPage({
|
||||
target: game.target,
|
||||
@@ -159,7 +151,7 @@ if (location.pathname === '/') {
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
document.querySelector('.featured').src = '/assets/img/wide/99balls.jpg';
|
||||
document.querySelector('.featured').src = '/assets/img/wide/stickman-archero-fight.png';
|
||||
}).catch(e => new PolarisError('Failed to load featured game.'));
|
||||
|
||||
const logHeight = () => {
|
||||
@@ -209,10 +201,9 @@ if (location.pathname === '/') {
|
||||
description.textContent = change.simpleDescription;
|
||||
description.classList = 'small';
|
||||
log.appendChild(description);
|
||||
|
||||
});
|
||||
|
||||
const updateChangelog = (amount = 3) => {
|
||||
const resizeChangelog = (amount = 3) => {
|
||||
amount = amount - 1;
|
||||
|
||||
for (let i = 0; i < document.querySelector('#changelog').children.length; i++) {
|
||||
@@ -221,8 +212,8 @@ if (location.pathname === '/') {
|
||||
}
|
||||
}
|
||||
|
||||
updateChangelog(Math.floor(getAvalibleHeight() / logHeight()));
|
||||
window.addEventListener('resize', () => updateChangelog(Math.floor(getAvalibleHeight() / logHeight())));
|
||||
resizeChangelog(Math.floor(getAvalibleHeight() / logHeight()));
|
||||
window.addEventListener('resize', () => resizeChangelog(Math.floor(getAvalibleHeight() / logHeight())));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -231,9 +222,13 @@ if (window.self === window.top && location.pathname !== '/view') {
|
||||
else document.querySelector('.navbar').classList.remove('scrolling');
|
||||
}
|
||||
|
||||
if (window.self === window.top && location.pathname !== '/view') window.onscroll = () => {
|
||||
if (window.self === window.top && location.pathname !== '/view') window.addEventListener('scroll', () => {
|
||||
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();
|
||||
if (window.self !== window.top && document.querySelector('.navbar')) document.querySelector('.navbar').remove();
|
||||
|
||||
if (location.pathname === '/share' && new URLSearchParams(location.search).has('game')) {
|
||||
Games.loadGameFromURL();
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createViewPage, isValidURL } from './utils.js';
|
||||
|
||||
const load = () => {
|
||||
const load = async () => {
|
||||
const form = document.querySelector('#wpf');
|
||||
const query = document.querySelector('#query');
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Dexie from 'https://unpkg.com/dexie@latest/dist/modern/dexie.mjs';
|
||||
import Dexie from 'https://esm.sh/dexie@latest/dist/modern/dexie.mjs';
|
||||
|
||||
import { isScrollable, storage, indexedDBExporter, cookie, EventEmitter, PolarisError } from './utils.js';
|
||||
import Theme from './themes.js';
|
||||
@@ -278,12 +278,12 @@ const loadSidebarInterface = () => {
|
||||
|
||||
document.querySelector('#panic_url').addEventListener('input', (e) => settingsStorage.set('panic_url', document.querySelector('#panic_url').value));
|
||||
|
||||
window.onkeydown = (e) => {
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (document.querySelector('#panic_key') == document.activeElement) {
|
||||
document.querySelector('#panic_key').value = e.key;
|
||||
settingsStorage.set('panic_key', document.querySelector('#panic_key').value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelector('#themes').querySelectorAll('button').forEach(el => el.onclick = () => Theme.set(el.innerText.toLocaleLowerCase()));
|
||||
|
||||
@@ -349,12 +349,11 @@ const loadSettings = () => {
|
||||
});
|
||||
}
|
||||
|
||||
window.onkeydown = (e) => {
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (e.key === settingsStorage.get('panic_key')) {
|
||||
if (settingsStorage.get('panic_url')) window.location.href = settingsStorage.get('panic_url');
|
||||
else new PolarisError('A panic key was used but no url was found.');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*if (new URLSearchParams(location.search).get('clickoff')) {
|
||||
|
||||
|
||||
+66
-23
@@ -8,7 +8,7 @@ import ctc from './utils/ctc.js';
|
||||
* The storage interface for polaris
|
||||
* @param {string} containerName
|
||||
*/
|
||||
const storage = (containerName) => {
|
||||
export const storage = (containerName) => {
|
||||
return {
|
||||
/**
|
||||
* Get a value from the storage container
|
||||
@@ -54,16 +54,55 @@ const storage = (containerName) => {
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
const uuid = () => ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
|
||||
export const uuid = () => ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
|
||||
|
||||
/**
|
||||
* Register a proxy service worker
|
||||
* @param {'uv' | 'dynamic'} proxy
|
||||
*/
|
||||
const loadProxyWorker = async (proxy) => await navigator.serviceWorker.register(`/${proxy}/sw.js`, {
|
||||
scope: `/${proxy}/service/`
|
||||
export const loadProxyWorker = async (proxy) => await navigator.serviceWorker.register(`/${proxy.split(':')[0]}/sw.js`, {
|
||||
scope: `/${proxy.split(':')[0]}/service/`
|
||||
});
|
||||
|
||||
/**
|
||||
* Set the bare transport
|
||||
* @param {'epoxy' | 'libcurl' | 'bare'} name
|
||||
* @param {any} options
|
||||
*/
|
||||
export const setTransport = async (name, options) => {
|
||||
const transports = {
|
||||
'epoxy': {
|
||||
src: '/epoxy/index.js',
|
||||
id: 'EpxMod.EpoxyClient',
|
||||
options: {
|
||||
wisp: location.origin.replace('http', 'ws') + '/wisp/'
|
||||
}
|
||||
},
|
||||
'libcurl': {
|
||||
src: '/libcurl/index.cjs',
|
||||
id: 'CurlMod.LibcurlClient',
|
||||
options: {
|
||||
wisp: location.origin.replace('http', 'ws') + '/wisp/',
|
||||
wasm: location.origin + '/libcurl/libcurl.wasm'
|
||||
}
|
||||
},
|
||||
'bare': {
|
||||
src: '/assets/js/bare-transport.js',
|
||||
id: 'BareMod.BareClient',
|
||||
options: location.origin + '/bare/'
|
||||
}
|
||||
};
|
||||
|
||||
if (!Object.keys(transports).includes(name)) throw 'Invalid Transport';
|
||||
|
||||
const transport = transports[name];
|
||||
|
||||
await loadCJS(transport.src);
|
||||
await loadCJS('/baremux/bare.cjs');
|
||||
|
||||
BareMux.SetTransport(transport.id, options || transport.options);
|
||||
}
|
||||
|
||||
/**
|
||||
Broken
|
||||
|
||||
@@ -102,7 +141,7 @@ const loadPageScript = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const encoder = {
|
||||
export const encoder = {
|
||||
b64: {
|
||||
encode: (data) => btoa(data),
|
||||
decode: (data) => atob(data)
|
||||
@@ -118,7 +157,7 @@ const encoder = {
|
||||
* @param {string} target
|
||||
* @param {{ trusted: boolean }} options
|
||||
*/
|
||||
const redirect = (target, options) => location.href = `/view?load=${btoa(JSON.stringify({
|
||||
export const redirect = (target, options) => location.href = `/view?load=${btoa(JSON.stringify({
|
||||
target,
|
||||
redirect: true,
|
||||
trusted: options.trusted
|
||||
@@ -128,11 +167,12 @@ const redirect = (target, options) => location.href = `/view?load=${btoa(JSON.st
|
||||
* 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({
|
||||
export const createViewPage = (options) => location.href = `/view?load=${btoa(JSON.stringify({
|
||||
return: options.return || location.href,
|
||||
proxied: options.proxied,
|
||||
target: options.target,
|
||||
title: options.title
|
||||
title: options.title,
|
||||
image: options.image
|
||||
}))}`;
|
||||
|
||||
/**
|
||||
@@ -140,15 +180,28 @@ const createViewPage = (options) => location.href = `/view?load=${btoa(JSON.stri
|
||||
* @param {string} url
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isValidURL = (url) => /^(http(s)?:\/\/)?([\w-]+\.)+[\w]{2,}(\/.*)?$/.test(url);
|
||||
export const isValidURL = (url) => /^(http(s)?:\/\/)?([\w-]+\.)+[\w]{2,}(\/.*)?$/.test(url);
|
||||
/**
|
||||
* Get the css vh value
|
||||
* @param {*} value
|
||||
* @returns {number}
|
||||
*/
|
||||
const getVH = (value) => (value * Math.max(document.documentElement.clientHeight, window.innerHeight || 0)) / 100;
|
||||
const getVW = (value) => (value * Math.max(document.documentElement.clientWidth, window.innerWidth || 0)) / 100;
|
||||
const isScrollable = (element) => element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight;
|
||||
export const getVH = (value) => (value * Math.max(document.documentElement.clientHeight, window.innerHeight || 0)) / 100;
|
||||
export const getVW = (value) => (value * Math.max(document.documentElement.clientWidth, window.innerWidth || 0)) / 100;
|
||||
export const isScrollable = (element) => element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight;
|
||||
|
||||
/**
|
||||
* @param {() => {}} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export const evalify = (code) => '(' + String(code) + ')()';
|
||||
|
||||
export const loadCJS = (src) => new Promise((resolve, reject) => {
|
||||
const el = document.createElement('script');
|
||||
el.src = src;
|
||||
document.body.appendChild(el);
|
||||
el.onload = () => resolve();
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {import('./utils/ctc.js').CrossTabCommunication}
|
||||
@@ -157,7 +210,7 @@ var CrossTabCommunication;
|
||||
|
||||
try {
|
||||
CrossTabCommunication = ctc;
|
||||
} catch { CrossTabCommunication = () => {}; }
|
||||
} catch { CrossTabCommunication = () => { }; }
|
||||
|
||||
export default {
|
||||
storage,
|
||||
@@ -178,19 +231,9 @@ export default {
|
||||
};
|
||||
|
||||
export {
|
||||
storage,
|
||||
loadProxyWorker,
|
||||
encoder,
|
||||
redirect,
|
||||
createViewPage,
|
||||
isValidURL,
|
||||
getVH,
|
||||
getVW,
|
||||
isScrollable,
|
||||
indexedDBExporter,
|
||||
EventEmitter,
|
||||
cookie,
|
||||
uuid,
|
||||
CrossTabCommunication,
|
||||
PolarisError
|
||||
};
|
||||
@@ -1,11 +1,15 @@
|
||||
import { loadProxyWorker, encoder, storage } from './utils.js';
|
||||
import { loadProxyWorker, encoder, storage, loadCJS, setTransport } from './utils.js';
|
||||
import { loadSettings } from './settings.js';
|
||||
|
||||
await loadCJS('/baremux/bare.cjs');
|
||||
|
||||
loadSettings();
|
||||
|
||||
const params = new URLSearchParams(location.search);
|
||||
const settingsStorage = storage('settings');
|
||||
|
||||
if ((settingsStorage.get('proxy') || 'uv').startsWith('uv')) await setTransport((settingsStorage.get('proxy') || '').split(':')[1] || 'libcurl');
|
||||
|
||||
window.history.replaceState({}, '', location.pathname);
|
||||
|
||||
if (params.get('load')) {
|
||||
@@ -18,9 +22,9 @@ if (params.get('load')) {
|
||||
sessionStorage.setItem('loaddata', JSON.stringify(parsedData));
|
||||
|
||||
if (parsedData.proxied) {
|
||||
await loadProxyWorker(settingsStorage.get('proxy') || 'uv');
|
||||
await loadProxyWorker((settingsStorage.get('proxy') || '').split(':')[0] || 'uv');
|
||||
|
||||
document.querySelector('#loadframe').src = `/${settingsStorage.get('proxy') || 'uv'}/service/${encoder['xor'].encode(parsedData.target)}`;
|
||||
document.querySelector('#loadframe').src = `/${(settingsStorage.get('proxy') || '').split(':')[0] || 'uv'}/service/${encoder['xor'].encode(parsedData.target)}`;
|
||||
} else document.querySelector('#loadframe').src = parsedData.target;
|
||||
|
||||
document.querySelector('#loadframe').addEventListener('load', () => {
|
||||
@@ -28,7 +32,7 @@ if (params.get('load')) {
|
||||
|
||||
document.querySelector('#loadframe').style.transition = 'none';
|
||||
document.querySelector('#loadframe').style.background = '#fff';
|
||||
|
||||
|
||||
document.querySelector('#loadframe').addEventListener('mouseover', () => {
|
||||
document.querySelector('.gamebar').classList.add('collapsed');
|
||||
document.querySelector('.hitbox').classList.remove('active');
|
||||
@@ -61,7 +65,7 @@ if (params.get('load')) {
|
||||
|
||||
document.querySelector('#return').addEventListener('click', () => {
|
||||
document.body.style.opacity = '0.7';
|
||||
|
||||
|
||||
setTimeout(() => window.location.href = parsedData.return, 500);
|
||||
});
|
||||
} else if (parsedData.target && parsedData.redirect === true) {
|
||||
|
||||
@@ -21,12 +21,15 @@
|
||||
|
||||
<div id="changelog"></div>
|
||||
|
||||
<br><br><hr>
|
||||
<br><br>
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
Running Polaris <span id="changelog_version">unknown</span>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<small>
|
||||
Commit: <span id="changelog_version_sha">unknown</span>
|
||||
<br>
|
||||
|
||||
+22
-22
@@ -22,35 +22,35 @@
|
||||
|
||||
<div class="cheats"></div>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<br><br>
|
||||
|
||||
<div id="largebillboard1"></div>
|
||||
|
||||
<script>
|
||||
window['nitroAds'].createAd('largebillboard1', {
|
||||
"refreshTime": 30,
|
||||
"renderVisibleOnly": true,
|
||||
"sizes": [
|
||||
[
|
||||
"970",
|
||||
"250"
|
||||
]
|
||||
],
|
||||
"report": {
|
||||
"enabled": true,
|
||||
"icon": true,
|
||||
"wording": "Report Ad",
|
||||
"position": "top-right"
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
window['nitroAds'].createAd('largebillboard1', {
|
||||
"refreshTime": 30,
|
||||
"renderVisibleOnly": true,
|
||||
"sizes": [
|
||||
[
|
||||
"970",
|
||||
"250"
|
||||
]
|
||||
],
|
||||
"report": {
|
||||
"enabled": true,
|
||||
"icon": true,
|
||||
"wording": "Report Ad",
|
||||
"position": "top-right"
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!--el:discord_widget-->
|
||||
|
||||
<script src="/assets/js/main.js" type="module"></script>
|
||||
|
||||
<!--el:{{mode === 'dev'}}:development-->
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,45 +0,0 @@
|
||||
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 plain = {
|
||||
encode: (str) => {
|
||||
if (!str) return str;
|
||||
|
||||
return encodeURIComponent(str);
|
||||
},
|
||||
decode: (str) => {
|
||||
if (!str) return str;
|
||||
|
||||
return decodeURIComponent(str);
|
||||
}
|
||||
}
|
||||
|
||||
const none = {
|
||||
encode: (str) => str,
|
||||
decode: (str) => str,
|
||||
}
|
||||
|
||||
const base64 = {
|
||||
encode: (str) => {
|
||||
if (!str) return str;
|
||||
|
||||
return decodeURIComponent(btoa(str));
|
||||
},
|
||||
decode: (str) => {
|
||||
if (!str) return str;
|
||||
|
||||
return atob(str);
|
||||
}
|
||||
}
|
||||
|
||||
export { xor, plain, none, base64 };
|
||||
@@ -8,7 +8,7 @@ self.__dynamic$config = {
|
||||
path: '/bare/'
|
||||
},
|
||||
tab: {
|
||||
title: 'Service',
|
||||
title: null,
|
||||
icon: null,
|
||||
ua: null
|
||||
},
|
||||
@@ -21,8 +21,5 @@ self.__dynamic$config = {
|
||||
config: 'dynamic.config.js',
|
||||
inject: null
|
||||
}
|
||||
},
|
||||
block: [
|
||||
|
||||
]
|
||||
}
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+16
-5
@@ -1,9 +1,20 @@
|
||||
importScripts('/dynamic/dynamic.config.js');
|
||||
importScripts('/dynamic/dynamic.worker.js');
|
||||
|
||||
const sw = new Dynamic();
|
||||
const dynamic = new Dynamic();
|
||||
|
||||
self.addEventListener('fetch', async (event) => {
|
||||
/*if (await sw.route(event)) */event.respondWith(sw.fetch(event));
|
||||
//else event.respondWith(fetch(event.request));
|
||||
});
|
||||
self.dynamic = dynamic;
|
||||
|
||||
self.addEventListener('fetch',
|
||||
event => {
|
||||
event.respondWith(
|
||||
(async function() {
|
||||
if (await dynamic.route(event)) {
|
||||
return await dynamic.fetch(event);
|
||||
}
|
||||
|
||||
return await fetch(event.request);
|
||||
})()
|
||||
);
|
||||
}
|
||||
);
|
||||
+16
-22
@@ -14,36 +14,31 @@
|
||||
<body>
|
||||
<!--el:navbar-->
|
||||
<!--el:sidebar-->
|
||||
<script>
|
||||
window['nitroAds'].createAd('outstreamplayer1', {
|
||||
"refreshTime": 30,
|
||||
"format": "floating",
|
||||
"report": {
|
||||
"enabled": true,
|
||||
"icon": true,
|
||||
"wording": "Report Ad",
|
||||
"position": "top-left"
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<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">
|
||||
<br>
|
||||
|
||||
<!--el:ad_horizontal-->
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<div class="search">
|
||||
<input type="text" id="searchInput" placeholder="Search Games">
|
||||
|
||||
<button id="randomGame" title="Play a random game">
|
||||
<i class="fa-solid fa-dice"></i>
|
||||
</button>
|
||||
|
||||
<select id="searchSort" title="Sort the games">
|
||||
<option value="none" selected>Don't Sort</option>
|
||||
<option value="newest">Newest</option>
|
||||
<option value="abc">Alphabetical</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<!--<script type='text/javascript' src='//outrightsham.com/44/75/cd/4475cd08e506eb8c6ed41e04b8c16197.js'></script>-->
|
||||
<div class="games">
|
||||
</div>
|
||||
|
||||
@@ -52,7 +47,6 @@ window['nitroAds'].createAd('outstreamplayer1', {
|
||||
<br>
|
||||
<p>Oops, we couldn't find the game you were looking for.</p>
|
||||
</div>
|
||||
|
||||
<!--el:discord_widget-->
|
||||
|
||||
<script src="/assets/js/main.js" type="module"></script>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
<head>
|
||||
<!--el:meta-->
|
||||
<!--el:adtop-->
|
||||
<!--el:analytics-->
|
||||
|
||||
<link rel="stylesheet" href="/assets/css/main.css">
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<!--el:meta-->
|
||||
<!--el:adtop-->
|
||||
<!--el:analytics-->
|
||||
|
||||
<link rel="stylesheet" href="/assets/css/main.css">
|
||||
|
||||
<title>Premium | Polaris</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--el:navbar-->
|
||||
<!--el:sidebar-->
|
||||
<br>
|
||||
<div class="content">
|
||||
<div class="container centered">
|
||||
<h1 style="font-size: 6vh; margin: 0;" class="gamesectionheader">Premium</h1>
|
||||
<h1 style="font-size: 2vh; margin: 0;" class="gamesectionheader">Coming Soon...</h1>
|
||||
<br>
|
||||
<p>With a premium membership you will get access to</p>
|
||||
<ul style="text-align: left;">
|
||||
<li>High speed exclusive servers</li>
|
||||
<li>Insider information on future updates</li>
|
||||
<li>Early access to new links</li>
|
||||
<li>And much more to come</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!--el:discord_widget-->
|
||||
|
||||
<script src="/assets/js/main.js" type="module"></script>
|
||||
|
||||
<!--el:{{mode === 'dev'}}:development-->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+13
-2
@@ -19,18 +19,29 @@
|
||||
<div class="container centered">
|
||||
<h1 class="title">Proxy</h1>
|
||||
|
||||
<text class="proxyDescription">Access the World Wide Web with no restrictions</text>
|
||||
<p class="proxyDescription">Search the web without restrictions</p>
|
||||
|
||||
<form id="wpf">
|
||||
<input class="proxyinput" type="text" id="query" placeholder="URL or Search Query" />
|
||||
</form>
|
||||
<br>
|
||||
<br>
|
||||
<div class="centered">
|
||||
<button onclick="joinDiscord()">Join Our Discord (more links)</button>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<br>
|
||||
<!--el:discord_widget-->
|
||||
|
||||
<script src="/assets/js/main.js" type="module"></script>
|
||||
<script>
|
||||
function joinDiscord() {
|
||||
var url = "https://discord.gg/skool-community-950407933408198717";
|
||||
var input = document.getElementById('query');
|
||||
input.value = url;
|
||||
}
|
||||
</script>
|
||||
<!--el:{{mode === 'dev'}}:development-->
|
||||
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<!--el:meta-->
|
||||
<!--el:adtop-->
|
||||
<!--el:analytics-->
|
||||
|
||||
<link rel="stylesheet" href="/assets/css/main.css">
|
||||
|
||||
<title>Loading... | Polaris</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container centered">
|
||||
<h1 style="font-size: 50px;">Loading</h1>
|
||||
|
||||
<p>
|
||||
Loading game...
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import { createViewPage, isValidURL } from '/assets/js/utils.js';
|
||||
|
||||
fetch('/api/games')
|
||||
.then(res => res.json())
|
||||
.then(games => {
|
||||
const searchParams = new URLSearchParams(location.search);
|
||||
const game = games.all.filter(g => g.name.toLowerCase() === searchParams.get('name'))[0].toLowerCase() || games.all[searchParams.get('id')];
|
||||
|
||||
if (game) {
|
||||
if (isValidURL(game.target)) createViewPage({
|
||||
target: game.target,
|
||||
title: game.name,
|
||||
return: '/games',
|
||||
proxied: true,
|
||||
type: 'game'
|
||||
});
|
||||
else createViewPage({
|
||||
target: game.target,
|
||||
title: game.name,
|
||||
return: '/games',
|
||||
image: game.image,
|
||||
type: 'game'
|
||||
});
|
||||
} else location.replace('/');
|
||||
});
|
||||
</script>
|
||||
|
||||
<!--el:{{mode === 'dev'}}:development-->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+6
-1
@@ -1,6 +1,11 @@
|
||||
// UV Transports
|
||||
importScripts('/assets/js/bare-transport.js');
|
||||
importScripts('/libcurl/index.cjs');
|
||||
importScripts('/epoxy/index.js');
|
||||
|
||||
importScripts('/uv/uv.bundle.js');
|
||||
importScripts('/uv/uv.config.js');
|
||||
importScripts('/uv/uv.sw.js');
|
||||
importScripts(__uv$config.sw || '/uv/uv.sw.js');
|
||||
|
||||
const sw = new UVServiceWorker();
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+84
-3
@@ -1,11 +1,92 @@
|
||||
self.__uv$config = {
|
||||
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',
|
||||
};
|
||||
sw: '/uv/uv.sw.js'
|
||||
};
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const setTransport = (name, options) => {
|
||||
const transports = {
|
||||
'epoxy': {
|
||||
src: '/epoxy/index.js',
|
||||
id: 'EpxMod.EpoxyClient',
|
||||
options: {
|
||||
wisp: location.origin.replace('http', 'ws') + '/wisp/'
|
||||
}
|
||||
},
|
||||
'libcurl': {
|
||||
src: '/libcurl/index.cjs',
|
||||
id: 'CurlMod.LibcurlClient',
|
||||
options: {
|
||||
wisp: location.origin.replace('http', 'ws') + '/wisp/',
|
||||
wasm: location.origin + '/libcurl/libcurl.wasm'
|
||||
}
|
||||
},
|
||||
'bare': {
|
||||
src: '/assets/js/bare-transport.js',
|
||||
id: 'BareMod.BareClient',
|
||||
options: location.origin + '/bare/'
|
||||
}
|
||||
};
|
||||
|
||||
if (!Object.keys(transports).includes(name)) throw 'Invalid Transport';
|
||||
|
||||
const transport = transports[name];
|
||||
|
||||
BareMux.SetTransport(transport.id, options || transport.options);
|
||||
}
|
||||
|
||||
const settingsStorage = storage('settings');
|
||||
|
||||
setTransport((settingsStorage.get('proxy') || '').split(':')[1] || 'libcurl');*/
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+7
-4
@@ -3,7 +3,6 @@
|
||||
|
||||
<head>
|
||||
<!--el:meta-->
|
||||
<!--el:adtop-->
|
||||
<!--el:analytics-->
|
||||
|
||||
<link rel="stylesheet" href="/assets/css/main.css">
|
||||
@@ -11,8 +10,13 @@
|
||||
|
||||
<title>View | Polaris</title>
|
||||
</head>
|
||||
|
||||
<body class="hidden">
|
||||
<script>
|
||||
window.onload = function() {
|
||||
alert("IF YOU GET AN ERROR SUCH AS 'there are no bare clients' RELOAD THE PAGE!");
|
||||
};
|
||||
</script>
|
||||
|
||||
<iframe frameborder="0" id="loadframe"></iframe>
|
||||
|
||||
<div class="gamebar">
|
||||
@@ -21,10 +25,9 @@
|
||||
</a>
|
||||
|
||||
<h1 class="title">Loading...</h1>
|
||||
|
||||
<div class="right">
|
||||
<span class="item" id="return">
|
||||
<i class="fa-solid fa-chevron-left"></i>
|
||||
<i class="fa-solid fa-angle-left"></i>
|
||||
</span>
|
||||
|
||||
<span class="item" id="fullscreen">
|
||||
|
||||
@@ -1,20 +1,48 @@
|
||||
<div id="bannerad728"></div>
|
||||
<script src="//outrightsham.com/cf0bb7d0401f5ae5534ac09c2e959d20/invoke.js" type="text/html"></script>
|
||||
<script type="module">
|
||||
import { createBareClient } from 'https://esm.sh/@tomphttp/bare-client@latest/dist/index.js';
|
||||
import { evalify } from '/assets/js/utils.js';
|
||||
|
||||
<script>
|
||||
window['nitroAds'].createAd('bannerad728', {
|
||||
"refreshTime": 30,
|
||||
"renderVisibleOnly": false,
|
||||
"sizes": [
|
||||
[
|
||||
"728",
|
||||
"90"
|
||||
]
|
||||
],
|
||||
"report": {
|
||||
"enabled": true,
|
||||
"icon": true,
|
||||
"wording": "Report Ad",
|
||||
"position": "top-right"
|
||||
const client = await createBareClient(location.origin + '/bare/');
|
||||
|
||||
window.atOptions = {
|
||||
'key': 'cf0bb7d0401f5ae5534ac09c2e959d20',
|
||||
'format': 'iframe',
|
||||
'height': 90,
|
||||
'width': 728,
|
||||
'params': {}
|
||||
};
|
||||
|
||||
eval(evalify(() => {
|
||||
const window = {
|
||||
...self,
|
||||
location: {
|
||||
...self.location,
|
||||
replace: () => {
|
||||
throw new Error('Failed to redirect')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const location = {
|
||||
...self.location,
|
||||
replace: () => {
|
||||
throw new Error('Failed to redirect')
|
||||
}
|
||||
};
|
||||
|
||||
{{ ad_src }}
|
||||
}).replace('{{ ad_src }}', await (await client.fetch('//outrightsham.com/cf0bb7d0401f5ae5534ac09c2e959d20/invoke.js', {
|
||||
headers: {
|
||||
'Accept': '*/*',
|
||||
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
||||
'Accept-Language': 'en-US,en;q=0.9',
|
||||
'Connection': 'keep-alive',
|
||||
'Host': 'outrightsham.com',
|
||||
'Origin': location.origin,
|
||||
'Referer': document.referrer,
|
||||
'User-Agent': window.navigator.userAgent
|
||||
}
|
||||
});
|
||||
})).text()));
|
||||
</script>
|
||||
@@ -1,2 +1,4 @@
|
||||
<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>
|
||||
<!--
|
||||
<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>
|
||||
<script data-cfasync="false" async src="https://s.nitropay.com/ads-1751.js"></script>
|
||||
-->
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
<script src="https://polaris4.statuspage.io/embed/script.js"></script>
|
||||
<!-- 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>
|
||||
+32
-14
@@ -1,17 +1,35 @@
|
||||
<div class="navbar">
|
||||
<a class="title" href="/">
|
||||
<img src="/assets/img/logo.png" />
|
||||
<a class="title" href="/">
|
||||
<img src="/assets/img/logo.png" />
|
||||
|
||||
<span>Polaris
|
||||
<span>By Skool</span>
|
||||
</span>
|
||||
</a>
|
||||
<span
|
||||
>Polaris
|
||||
<span>By Skool</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<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-action="no_redirect" data-attr="sidebar_trigger"><i class="fa-solid fa-gear fa-sm"></i>Settings</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a href="/premium" class="premium" style="border-color: rgb(0, 60, 255);"
|
||||
><i class="fa-solid fa-star"></i>Premium</a
|
||||
>
|
||||
<a href="/games" class="navButton"
|
||||
><i class="fa-solid fa-gamepad-modern fa-xs"></i>Games</a
|
||||
>
|
||||
<a href="/apps" class="navButton"
|
||||
><i class="fa-solid fa-rocket-launch fa-xs"></i>Apps</a
|
||||
>
|
||||
<a href="/search" class="navButton"
|
||||
><i class="fa-solid fa-magnifying-glass fa-xs"></i>Proxy</a
|
||||
>
|
||||
<a href="/cheats" class="navButton"
|
||||
><i class="fa-solid fa-computer fa-xs"></i>Cheats</a
|
||||
>
|
||||
<a
|
||||
href="#settings"
|
||||
class="navButton"
|
||||
data-action="no_redirect"
|
||||
data-attr="sidebar_trigger"
|
||||
><i class="fa-solid fa-gear fa-sm"></i>Settings</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
|
||||
<h3>Panic Key</h3>
|
||||
|
||||
<input class="settings-input" type="text" name="Panic Key" id="panic_key" value="Click and press any key"
|
||||
readonly />
|
||||
<input class="settings-input" type="text" name="Panic Key" id="panic_key" value="Click and press any key" readonly />
|
||||
<button class="settings-button" id="reset_panic">Reset</button>
|
||||
|
||||
<br>
|
||||
@@ -30,6 +29,8 @@
|
||||
<button class="settings-button">Inferno</button>
|
||||
<button class="settings-button">Indigo</button>
|
||||
<button class="settings-button">Violet</button>
|
||||
<button class="settings-button">Cyan</button>
|
||||
<button class="settings-button">Bronze</button>
|
||||
</div>
|
||||
|
||||
<h3>Tab Cloak</h3>
|
||||
@@ -50,7 +51,9 @@
|
||||
<h3>Proxy</h3>
|
||||
|
||||
<select id="proxy_select">
|
||||
<option value="uv">Ultraviolet</option>
|
||||
<option value="uv:bare">Ultraviolet</option>
|
||||
<option value="uv:epoxy">Ultraviolet (Epoxy)</option>
|
||||
<option value="uv:libcurl" selected>Ultraviolet (Libcurl)</option>
|
||||
<option value="dynamic" disabled>Dynamic</option>
|
||||
</select>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user