Formatting and workflow organization changes

This commit is contained in:
00Fjongl 2024-08-08 23:10:58 -05:00
parent 461c89212f
commit 8c9f79d3e7
13 changed files with 1010 additions and 979 deletions

View file

@ -26,7 +26,7 @@ jobs:
run: npm run build run: npm run build
- name: Start server - name: Start server
run: npm run manual-start run: npm run workflow-test
- name: Test server response - name: Test server response
run: npm test run: npm test
@ -53,7 +53,7 @@ jobs:
run: npm run build run: npm run build
- name: Start server - name: Start server
run: npm run manual-start run: npm run workflow-test
- name: Test server response - name: Test server response
run: npm test run: npm test

View file

@ -1 +1,2 @@
/lib /lib
/views/assets/js/*.js

View file

@ -12,7 +12,8 @@
"manual-start": "node run-command.mjs start", "manual-start": "node run-command.mjs start",
"kill": "node run-command.mjs stop kill", "kill": "node run-command.mjs stop kill",
"build": "node run-command.mjs build && cd lib/rammerhead && npm install && npm run build", "build": "node run-command.mjs build && cd lib/rammerhead && npm install && npm run build",
"proxy-validator": "node proxyServiceValidator.js" "proxy-validator": "node proxyServiceValidator.js",
"workflow-test": "node run-command.mjs workflow"
}, },
"keywords": [ "keywords": [
"proxy", "proxy",

View file

@ -311,7 +311,7 @@ xx xx
} }
}; };
// Run tests for Rammerhead and Ultraviolet // Run tests for Rammerhead and Ultraviolet.
const rammerheadPassed = await testRammerhead(); const rammerheadPassed = await testRammerhead();
const ultravioletPassed = await testUltraviolet(); const ultravioletPassed = await testUltraviolet();

View file

@ -42,8 +42,8 @@ commands: for (let i = 2; i < process.argv.length; i++)
console.log(stdout); console.log(stdout);
} }
); );
// Handle setup on Windows differently from platforms with POSIX-compliant shells. // Handle setup on Windows differently from platforms with POSIX-compliant
// This should run the server as a background process. // shells. This should run the server as a background process.
else if (process.platform === 'win32') else if (process.platform === 'win32')
exec('START /MIN "" node backend.js', (error, stdout) => { exec('START /MIN "" node backend.js', (error, stdout) => {
if (error) { if (error) {
@ -57,28 +57,8 @@ commands: for (let i = 2; i < process.argv.length; i++)
else { else {
const server = fork( const server = fork(
fileURLToPath(new URL('./backend.js', import.meta.url)), fileURLToPath(new URL('./backend.js', import.meta.url)),
{ { cwd: process.cwd(), detached: true }
cwd: process.cwd(),
stdio: ['inherit', 'pipe', 'pipe', 'ipc'],
detached: true
}
); );
server.stderr.on("data", stderr => {
console.error(stderr.toString());
if (stderr.toString().indexOf("DeprecationWarning") + 1)
return;
server.stderr.destroy();
process.exitCode = 1;
});
server.stdout.on("data", () => {
server.kill();
const server2 = fork(
fileURLToPath(new URL('./backend.js', import.meta.url)),
{cwd: process.cwd(), detached: true}
);
server2.unref();
server2.disconnect();
});
server.unref(); server.unref();
server.disconnect(); server.disconnect();
} }
@ -91,9 +71,10 @@ commands: for (let i = 2; i < process.argv.length; i++)
let timeoutId, let timeoutId,
hasErrored = false; hasErrored = false;
try { try {
// Give the server 5 seconds to respond, otherwise cancel this and throw an /* Give the server 5 seconds to respond, otherwise cancel this and throw an
// error to the console. The fetch request will also throw an error immediately * error to the console. The fetch request will also throw an error
// if checking the server on localhost and the port is unused. * immediately if checking the server on localhost and the port is unused.
*/
const response = await Promise.race([ const response = await Promise.race([
fetch(new URL('/test-shutdown', serverUrl)), fetch(new URL('/test-shutdown', serverUrl)),
new Promise((resolve) => { new Promise((resolve) => {
@ -154,9 +135,10 @@ commands: for (let i = 2; i < process.argv.length; i++)
break; break;
} }
// Kill all node processes and fully reset PM2. To be used for debugging. /* Kill all node processes and fully reset PM2. To be used for debugging.
// Using npx pm2 monit, or npx pm2 list in the terminal will also bring up * Using npx pm2 monit, or npx pm2 list in the terminal will also bring up
// more PM2 debugging tools. * more PM2 debugging tools.
*/
case 'kill': case 'kill':
if (process.platform === 'win32') if (process.platform === 'win32')
exec( exec(
@ -174,6 +156,56 @@ commands: for (let i = 2; i < process.argv.length; i++)
); );
break; break;
case 'workflow':
if (config.production)
exec(
'npx pm2 start ecosystem.config.js --env production',
(error, stdout) => {
if (error) throw error;
console.log(stdout);
}
);
// Handle setup on Windows differently from platforms with POSIX-compliant
// shells. This should run the server as a background process.
else if (process.platform === 'win32')
exec('START /MIN "" node backend.js', (error, stdout) => {
if (error) {
console.error(error);
process.exitCode = 1;
}
console.log(stdout);
});
// The following approach (and similar approaches) will not work on Windows,
// because exiting this program will also terminate backend.js on Windows.
else {
const server = fork(
fileURLToPath(new URL('./backend.js', import.meta.url)),
{
cwd: process.cwd(),
stdio: ['inherit', 'pipe', 'pipe', 'ipc'],
detached: true,
}
);
server.stderr.on('data', (stderr) => {
console.error(stderr.toString());
if (stderr.toString().indexOf('DeprecationWarning') + 1) return;
server.stderr.destroy();
process.exitCode = 1;
});
server.stdout.on('data', () => {
server.kill();
const server2 = fork(
fileURLToPath(new URL('./backend.js', import.meta.url)),
{ cwd: process.cwd(), detached: true }
);
server2.unref();
server2.disconnect();
});
server.unref();
server.disconnect();
}
break;
// No default case. // No default case.
} }

View file

@ -63,7 +63,7 @@ const rammerheadSession = /^\/[a-z0-9]{32}/,
if (bare.shouldRoute(req)) { if (bare.shouldRoute(req)) {
bare.routeRequest(req, res); bare.routeRequest(req, res);
} else } else
*/ */
if (shouldRouteRh(req)) { if (shouldRouteRh(req)) {
routeRhRequest(req, res); routeRhRequest(req, res);
} else { } else {
@ -76,7 +76,7 @@ server.on('upgrade', (req, socket, head) => {
if (bare.shouldRoute(req)) { if (bare.shouldRoute(req)) {
bare.routeUpgrade(req, socket, head); bare.routeUpgrade(req, socket, head);
} else } else
*/ */
if (shouldRouteRh(req)) { if (shouldRouteRh(req)) {
routeRhUpgrade(req, socket, head); routeRhUpgrade(req, socket, head);
} else if (req.url.endsWith('/wisp/')) { } else if (req.url.endsWith('/wisp/')) {
@ -84,17 +84,18 @@ server.on('upgrade', (req, socket, head) => {
} }
}); });
// Apply Helmet middleware for security // Apply Helmet middleware for security.
app.use( app.use(
helmet({ helmet({
contentSecurityPolicy: false, // Disable CSP contentSecurityPolicy: false, // Disable CSP
}) })
); );
// All website files are stored in the /views directory. /* All website files are stored in the /views directory.
// This takes one of those files and displays it for a site visitor. * This takes one of those files and displays it for a site visitor.
// Query strings like /?j are converted into paths like /views/hidden.html * Query strings like /?j are converted into paths like /views/hidden.html
// back here. Which query string converts to what is defined in routes.mjs. * back here. Which query string converts to what is defined in routes.mjs.
*/
router.get('/', async (req, res) => router.get('/', async (req, res) =>
res.send( res.send(
paintSource( paintSource(

View file

@ -11,9 +11,10 @@ const {
text404, text404,
} = pkg; } = pkg;
// Below are lots of function definitions used to obfuscate the website. /* Below are lots of function definitions used to obfuscate the website.
// This makes the website harder to properly categorize, as its source code * This makes the website harder to properly categorize, as its source code
// changes with each time it is loaded. * changes with each time it is loaded.
*/
const randomListItem = (lis) => () => lis[(Math.random() * lis.length) | 0], const randomListItem = (lis) => () => lis[(Math.random() * lis.length) | 0],
charset = /&#173;|&#8203;|&shy;|<wbr>/gi, charset = /&#173;|&#8203;|&shy;|<wbr>/gi,
getRandomChar = randomListItem(charRandom), getRandomChar = randomListItem(charRandom),
@ -44,10 +45,9 @@ const randomListItem = (lis) => () => lis[(Math.random() * lis.length) | 0],
existsSync(file + '') ? readFileSync(file + '', 'utf8') : preloaded404; existsSync(file + '') ? readFileSync(file + '', 'utf8') : preloaded404;
/* /*
// All of this is now old code.
// The newer versions of these functions are directly above. All of this is now old code.
*/ The newer versions of these functions are directly above.
/*
function randomListItem(lis) { function randomListItem(lis) {
return lis[Math.floor(Math.random() * lis.length)]; return lis[Math.floor(Math.random() * lis.length)];

View file

@ -27,9 +27,10 @@ const config = Object.freeze(
{ pages, externalPages } = pageRoutes, { pages, externalPages } = pageRoutes,
__dirname = path.resolve(); __dirname = path.resolve();
// Record the server's location as a URL object, including its host and port. /* Record the server's location as a URL object, including its host and port.
// The host can be modified at /src/config.json, whereas the ports can be modified * The host can be modified at /src/config.json, whereas the ports can be modified
// at /ecosystem.config.js. * at /ecosystem.config.js.
*/
const serverUrl = ((base) => { const serverUrl = ((base) => {
try { try {
base = new URL(config.host); base = new URL(config.host);
@ -98,7 +99,7 @@ const serverFactory = (handler) => {
}); });
}; };
// Set logger to true for logs // Set logger to true for logs.
const app = Fastify({ const app = Fastify({
ignoreDuplicateSlashes: true, ignoreDuplicateSlashes: true,
ignoreTrailingSlash: true, ignoreTrailingSlash: true,
@ -106,7 +107,7 @@ const app = Fastify({
serverFactory: serverFactory, serverFactory: serverFactory,
}); });
// Apply Helmet middleware for security // Apply Helmet middleware for security.
app.register(fastifyHelmet, { app.register(fastifyHelmet, {
contentSecurityPolicy: false, // Disable CSP contentSecurityPolicy: false, // Disable CSP
xPoweredBy: false, xPoweredBy: false,
@ -196,10 +197,11 @@ app.register(fastifyStatic, {
decorateReply: false, decorateReply: false,
}); });
// All website files are stored in the /views directory. /* All website files are stored in the /views directory.
// This takes one of those files and displays it for a site visitor. * This takes one of those files and displays it for a site visitor.
// Paths like /browsing are converted into paths like /views/pages/surf.html * Paths like /browsing are converted into paths like /views/pages/surf.html
// back here. Which path converts to what is defined in routes.mjs. * back here. Which path converts to what is defined in routes.mjs.
*/
app.get('/:path', (req, reply) => { app.get('/:path', (req, reply) => {
// Testing for future features that need cookies to deliver alternate source files. // Testing for future features that need cookies to deliver alternate source files.
if (req.raw.rawHeaders.includes('Cookie')) if (req.raw.rawHeaders.includes('Cookie'))

View file

@ -7,9 +7,9 @@
// Encase everything in a new scope so that variables are not accidentally // Encase everything in a new scope so that variables are not accidentally
// attached to the global scope. // attached to the global scope.
(() => { (() => {
// Track the cursor position with respect to the top left of the card. // Track the cursor position with respect to the top left of the card.
// The "this" keyword gets the element that invoked the event listener. // The "this" keyword gets the element that invoked the event listener.
const handleMouseMove = (element) => { const handleMouseMove = (element) => {
element.addEventListener('mousemove', (e) => { element.addEventListener('mousemove', (e) => {
const rect = element.getBoundingClientRect(); const rect = element.getBoundingClientRect();
const x = e.clientX - rect.left; const x = e.clientX - rect.left;
@ -29,9 +29,10 @@
// Get the box card elements and add the event listeners to them. // Get the box card elements and add the event listeners to them.
shimmerEffects = document.querySelectorAll('.box-card, .box-hero'); shimmerEffects = document.querySelectorAll('.box-card, .box-hero');
// Attach CSS variables, mouse-x and mouse-y, to elements that will be /* Attach CSS variables, mouse-x and mouse-y, to elements that will be
// given shimmer effects, by adding or modifying the style attribute. * given shimmer effects, by adding or modifying the style attribute.
// CSS calculates and renders the actual shimmer effect from there. * CSS calculates and renders the actual shimmer effect from there.
shimmerEffects.forEach(handleMouseMove); */
shimmerEffects.forEach(handleMouseLeave); shimmerEffects.forEach(handleMouseMove);
shimmerEffects.forEach(handleMouseLeave);
})(); })();

View file

@ -7,19 +7,20 @@
// Encase everything in a new scope so that variables are not accidentally // Encase everything in a new scope so that variables are not accidentally
// attached to the global scope. // attached to the global scope.
(() => { (() => {
// Get the preferred apex domain name. Not exactly apex, as any // Get the preferred apex domain name. Not exactly apex, as any
// subdomain other than those listed will be ignored. // subdomain other than those listed will be ignored.
const getDomain = () => const getDomain = () =>
location.host.replace(/^(?:www|edu|cooking|beta)\./, ''), location.host.replace(/^(?:www|edu|cooking|beta)\./, ''),
// This is used for stealth mode when visiting external sites. // This is used for stealth mode when visiting external sites.
goFrame = (url) => { goFrame = (url) => {
localStorage.setItem('huframesrc', url); localStorage.setItem('huframesrc', url);
location.href = '/s'; location.href = '/s';
}, },
// Used to set functions for the goProx object at the bottom. /* Used to set functions for the goProx object at the bottom.
// See the goProx object at the bottom for some usage examples * See the goProx object at the bottom for some usage examples
// on the URL handlers, omnibox functions, and the uvUrl and * on the URL handlers, omnibox functions, and the uvUrl and
// RammerheadEncode functions. * RammerheadEncode functions.
*/
urlHandler = (parser) => urlHandler = (parser) =>
typeof parser === 'function' typeof parser === 'function'
? // Return different functions based on whether a URL has already been set. ? // Return different functions based on whether a URL has already been set.
@ -48,19 +49,19 @@
else return url; else return url;
}; };
/* COOKIE AUTH DEMO */ /* COOKIE AUTH DEMO */
const setAuthCookie = (s, lax) => { const setAuthCookie = (s, lax) => {
document.cookie = document.cookie =
s + s +
`; expires=${Date.now() + 259200}; SameSite=${lax ? 'Lax' : 'None'}; domain=.${getDomain()}; path=/; Secure;`; `; expires=${Date.now() + 259200}; SameSite=${lax ? 'Lax' : 'None'}; domain=.${getDomain()}; path=/; Secure;`;
}; };
/* OMNIBOX */ /* OMNIBOX */
// Search engine is set to Bing. Intended to work just like the usual // Search engine is set to Bing. Intended to work just like the usual
// bar at the top of a browser. // bar at the top of a browser.
const sx = 'bing.com' + '/search?q=', const sx = 'bing.com' + '/search?q=',
/* /*
omnibox = url => omnibox = url =>
(url.indexOf("http") (url.indexOf("http")
@ -106,10 +107,10 @@
return url; return url;
}; };
/* RAMMERHEAD CONFIGURATION */ /* RAMMERHEAD CONFIGURATION */
// Parse a URL to use with Rammerhead. Only usable if the server is active. // Parse a URL to use with Rammerhead. Only usable if the server is active.
const RammerheadEncode = async (baseUrl) => { const RammerheadEncode = async (baseUrl) => {
// Hellhead // Hellhead
const mod = (n, m) => ((n % m) + m) % m, const mod = (n, m) => ((n % m) + m) % m,
baseDictionary = baseDictionary =
@ -141,9 +142,10 @@
const char = str[i], const char = str[i],
idx = baseDictionary.indexOf(char); idx = baseDictionary.indexOf(char);
// For URL encoded characters and characters not included in the /* For URL encoded characters and characters not included in the
// dictionary, leave untouched. Otherwise, replace with a character * dictionary, leave untouched. Otherwise, replace with a character
// from the dictionary. * from the dictionary.
*/
if (char === '%' && str.length - i >= 3) if (char === '%' && str.length - i >= 3)
// A % symbol denotes that the next 2 characters are URL encoded. // A % symbol denotes that the next 2 characters are URL encoded.
shuffledStr += char + str[++i] + str[++i]; shuffledStr += char + str[++i] + str[++i];
@ -172,17 +174,17 @@
const char = str[i], const char = str[i],
idx = this.dictionary.indexOf(char); idx = this.dictionary.indexOf(char);
// Convert the dictionary entry characters back into their base /* Convert the dictionary entry characters back into their base
// characters using the base dictionary. Again, leave URL encoded * characters using the base dictionary. Again, leave URL encoded
// characters and unrecognized symbols alone. * characters and unrecognized symbols alone.
*/
if (char === '%' && str.length - i >= 3) if (char === '%' && str.length - i >= 3)
unshuffledStr += char + str[++i] + str[++i]; unshuffledStr += char + str[++i] + str[++i];
else if (idx == -1) unshuffledStr += char; else if (idx == -1) unshuffledStr += char;
// Find the corresponding base character entry and use the character // Find the corresponding base character entry and use the character
// that is i places to the left of it. // that is i places to the left of it.
else else
unshuffledStr += unshuffledStr += baseDictionary[mod(idx - i, baseDictionary.length)];
baseDictionary[mod(idx - i, baseDictionary.length)];
} }
return unshuffledStr; return unshuffledStr;
} }
@ -230,9 +232,10 @@
}); });
}, },
}, },
// Organize Rammerhead sessions via the browser's local storage. /* Organize Rammerhead sessions via the browser's local storage.
// Local data consists of session creation timestamps and session IDs. * Local data consists of session creation timestamps and session IDs.
// The rest of the data is stored on the server. * The rest of the data is stored on the server.
*/
localStorageKey = 'rammerhead_sessionids', localStorageKey = 'rammerhead_sessionids',
localStorageKeyDefault = 'rammerhead_default_sessionid', localStorageKeyDefault = 'rammerhead_default_sessionid',
sessionIdsStore = { sessionIdsStore = {
@ -314,9 +317,9 @@
}); });
}) })
); );
}; };
/* To use: /* To use:
* goProx.proxy(url-string, mode-as-string-or-number); * goProx.proxy(url-string, mode-as-string-or-number);
* *
* Key: 1 = "stealth" * Key: 1 = "stealth"
@ -348,7 +351,7 @@
* *
* goProx.searx(); * goProx.searx();
*/ */
addEventListener('DOMContentLoaded', async () => { addEventListener('DOMContentLoaded', async () => {
const goProx = { const goProx = {
// `location.protocol + "//" + getDomain()` more like `location.origin` // `location.protocol + "//" + getDomain()` more like `location.origin`
// setAuthCookie("__cor_auth=1", false); // setAuthCookie("__cor_auth=1", false);
@ -368,9 +371,7 @@
mcnow: urlHandler(uvUrl('https://now.gg/play/a/10010/b')), mcnow: urlHandler(uvUrl('https://now.gg/play/a/10010/b')),
glife: urlHandler( glife: urlHandler(uvUrl('https://now.gg/apps/lunime/5767/gacha-life.html')),
uvUrl('https://now.gg/apps/lunime/5767/gacha-life.html')
),
roblox: urlHandler( roblox: urlHandler(
uvUrl('https://now.gg/apps/roblox-corporation/5349/roblox.html') uvUrl('https://now.gg/apps/roblox-corporation/5349/roblox.html')
@ -381,9 +382,7 @@
), ),
pubg: urlHandler( pubg: urlHandler(
uvUrl( uvUrl('https://now.gg/apps/proxima-beta/2609/pubg-mobile-resistance.html')
'https://now.gg/apps/proxima-beta/2609/pubg-mobile-resistance.html'
)
), ),
train: urlHandler(uvUrl('https://hby.itch.io/last-train-home')), train: urlHandler(uvUrl('https://hby.itch.io/last-train-home')),
@ -394,9 +393,7 @@
rpg: urlHandler(uvUrl('https://alarts.itch.io/die-in-the-dungeon')), rpg: urlHandler(uvUrl('https://alarts.itch.io/die-in-the-dungeon')),
speed: urlHandler( speed: urlHandler(uvUrl('https://captain4lk.itch.io/what-the-road-brings')),
uvUrl('https://captain4lk.itch.io/what-the-road-brings')
),
heli: urlHandler(uvUrl('https://benjames171.itch.io/helo-storm')), heli: urlHandler(uvUrl('https://benjames171.itch.io/helo-storm')),
@ -538,8 +535,7 @@
// the corresponding location/index in the dirnames object. // the corresponding location/index in the dirnames object.
const functionsList = [ const functionsList = [
() => goFrame(item.path), () => goFrame(item.path),
() => () => goFrame('/webretro?core=' + item.core + '&rom=' + item.rom),
goFrame('/webretro?core=' + item.core + '&rom=' + item.rom),
item.custom item.custom
? () => goProx[item.custom]('stealth') ? () => goProx[item.custom]('stealth')
: () => goFrame('/archive/g/' + item.path), : () => goFrame('/archive/g/' + item.path),
@ -580,5 +576,5 @@
} }
} }
} }
}); });
})(); })();

View file

@ -8,21 +8,20 @@
// Encase everything in a new scope so that variables are not accidentally // Encase everything in a new scope so that variables are not accidentally
// attached to the global scope. // attached to the global scope.
(() => { (() => {
// Determine the expiration date of a new cookie. // Determine the expiration date of a new cookie.
let date = new Date(); let date = new Date();
date.setFullYear(date.getFullYear() + 100); date.setFullYear(date.getFullYear() + 100);
date = date.toUTCString(); date = date.toUTCString();
// All cookies should be secure and are intended to work in iframes. // All cookies should be secure and are intended to work in iframes.
const setCookie = (name, value) => { const setCookie = (name, value) => {
document.cookie = document.cookie =
name + name +
`=${encodeURIComponent(value)}; expires=${date}; SameSite=None; Secure;`; `=${encodeURIComponent(value)}; expires=${date}; SameSite=None; Secure;`;
}, },
removeCookie = (name) => { removeCookie = (name) => {
document.cookie = document.cookie =
name + name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=None; Secure;';
'=; expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=None; Secure;';
}, },
readCookie = async (name) => { readCookie = async (name) => {
// Get the first cookie that has the same name. // Get the first cookie that has the same name.
@ -81,32 +80,32 @@
? 'epoxy' ? 'epoxy'
: 'libcurl'; : 'libcurl';
// Load a custom page title and favicon if it was previously stored. // Load a custom page title and favicon if it was previously stored.
readCookie('HBTitle').then((s) => { readCookie('HBTitle').then((s) => {
s != undefined && pageTitle(s); s != undefined && pageTitle(s);
}); });
readCookie('HBIcon').then((s) => { readCookie('HBIcon').then((s) => {
s != undefined && pageIcon(s); s != undefined && pageIcon(s);
}); });
// Load the UV transport mode that was last used, or use the default. // Load the UV transport mode that was last used, or use the default.
readCookie('HBTransport').then((s) => { readCookie('HBTransport').then((s) => {
let transportMode = document.querySelector( let transportMode = document.querySelector(
`#uv-transport-list input[value="${s || defaultMode}"]` `#uv-transport-list input[value="${s || defaultMode}"]`
); );
if (transportMode) transportMode.click(); if (transportMode) transportMode.click();
}); });
// Ads are disabled by default. Load ads if ads were enabled previously. // Ads are disabled by default. Load ads if ads were enabled previously.
// Change !== to === here if ads should be enabled by default. // Change !== to === here if ads should be enabled by default.
readCookie('HBHideAds').then((s) => { readCookie('HBHideAds').then((s) => {
s !== 'false' s !== 'false'
? pageHideAds() ? pageHideAds()
: pageShowAds(((document.getElementById('hideads') || {}).checked = 0)); : pageShowAds(((document.getElementById('hideads') || {}).checked = 0));
}); });
// Tor is disabled by default. Enable Tor if it was enabled previously. // Tor is disabled by default. Enable Tor if it was enabled previously.
readCookie('HBUseOnion').then((s) => { readCookie('HBUseOnion').then((s) => {
if (s === 'true') { if (s === 'true') {
let torCheck = document.getElementById('useonion') || { let torCheck = document.getElementById('useonion') || {
dispatchEvent: () => {}, dispatchEvent: () => {},
@ -114,10 +113,10 @@
torCheck.checked = 1; torCheck.checked = 1;
torCheck.dispatchEvent(new Event('change')); torCheck.dispatchEvent(new Event('change'));
} }
}); });
// All code below is used by the Settings UI in the navigation bar. // All code below is used by the Settings UI in the navigation bar.
if (document.getElementById('csel')) { if (document.getElementById('csel')) {
const attachEventListener = (selector, ...args) => const attachEventListener = (selector, ...args) =>
( (
document.getElementById(selector) || document.querySelector(selector) document.getElementById(selector) || document.querySelector(selector)
@ -126,13 +125,9 @@
.getElementsByClassName('dropdown-settings')[0] .getElementsByClassName('dropdown-settings')[0]
.parentElement.querySelector("a[href='#']"); .parentElement.querySelector("a[href='#']");
attachEventListener( attachEventListener('.dropdown-settings .close-settings-btn', 'click', () => {
'.dropdown-settings .close-settings-btn',
'click',
() => {
document.activeElement.blur(); document.activeElement.blur();
} });
);
// Allow users to set a custom title with the UI. // Allow users to set a custom title with the UI.
attachEventListener('titleform', 'submit', (e) => { attachEventListener('titleform', 'submit', (e) => {
@ -170,8 +165,8 @@
This is unused in the current settings menu. This is unused in the current settings menu.
// Allow users to make a new about:blank tab and view the site from there. // Allow users to make a new about:blank tab and view the site from there.
// An iframe of the current page is inserted into the new tab. // An iframe of the current page is inserted into the new tab.
attachEventListener("cselab", "click", () => { attachEventListener("cselab", "click", () => {
let win = window.open(); let win = window.open();
let iframe = win.document.createElement("iframe"); let iframe = win.document.createElement("iframe");
@ -179,7 +174,7 @@
iframe.src = location.href; iframe.src = location.href;
win.document.body.appendChild(iframe); win.document.body.appendChild(iframe);
}); });
*/ */
// Provides users with a handy set of title and icon autofill options. // Provides users with a handy set of title and icon autofill options.
attachEventListener('icon-list', 'change', (e) => { attachEventListener('icon-list', 'change', (e) => {
@ -216,9 +211,10 @@
} }
}); });
// Allow users to toggle onion routing in Ultraviolet with the UI. Only /* Allow users to toggle onion routing in Ultraviolet with the UI. Only
// the libcurl transport mode supports Tor at the moment, so ensure that * the libcurl transport mode supports Tor at the moment, so ensure that
// users are aware that they cannot use Tor with other modes. * users are aware that they cannot use Tor with other modes.
*/
attachEventListener('useonion', 'change', (e) => { attachEventListener('useonion', 'change', (e) => {
let unselectedModes = document.querySelectorAll( let unselectedModes = document.querySelectorAll(
'#uv-transport-list input:not([value=libcurl])' '#uv-transport-list input:not([value=libcurl])'
@ -242,7 +238,7 @@
removeCookie('HBUseOnion'); removeCookie('HBUseOnion');
} }
}); });
} }
})(); })();
/* ----------------------------------------------- /* -----------------------------------------------

View file

@ -1,7 +1,7 @@
// Encase everything in a new scope so that variables are not accidentally // Encase everything in a new scope so that variables are not accidentally
// attached to the global scope. // attached to the global scope.
(() => { (() => {
const stockSW = '/uv/sw.js', const stockSW = '/uv/sw.js',
blacklistSW = '/uv/sw-blacklist.js', blacklistSW = '/uv/sw-blacklist.js',
swAllowedHostnames = ['localhost', '127.0.0.1'], swAllowedHostnames = ['localhost', '127.0.0.1'],
connection = new BareMux.BareMuxConnection('/baremux/worker.js'), connection = new BareMux.BareMuxConnection('/baremux/worker.js'),
@ -31,12 +31,12 @@
? 'epoxy' ? 'epoxy'
: 'libcurl'; : 'libcurl';
transports.default = transports[defaultMode]; transports.default = transports[defaultMode];
// Prevent the transports object from accidentally being edited. // Prevent the transports object from accidentally being edited.
Object.freeze(transports); Object.freeze(transports);
const registerSW = async () => { const registerSW = async () => {
if (!navigator.serviceWorker) { if (!navigator.serviceWorker) {
if ( if (
location.protocol !== 'https:' && location.protocol !== 'https:' &&
@ -58,9 +58,10 @@
await connection.setTransport(transportMode, [transportOptions]); await connection.setTransport(transportMode, [transportOptions]);
// Choose a service worker to register based on whether or not the user /* Choose a service worker to register based on whether or not the user
// has ads enabled. If the user changes this setting, this script needs * has ads enabled. If the user changes this setting, this script needs
// to be reloaded for this to update, such as by refreshing the page. * to be reloaded for this to update, such as by refreshing the page.
*/
const registrations = await navigator.serviceWorker.getRegistrations(), const registrations = await navigator.serviceWorker.getRegistrations(),
usedSW = usedSW =
(await readCookie('HBHideAds')) !== 'false' ? blacklistSW : stockSW; (await readCookie('HBHideAds')) !== 'false' ? blacklistSW : stockSW;
@ -75,9 +76,9 @@
await registration.unregister(); await registration.unregister();
await navigator.serviceWorker.register(usedSW); await navigator.serviceWorker.register(usedSW);
}; };
/* /*
Commented out upon discovering that a duplicate BareMux connection may be Commented out upon discovering that a duplicate BareMux connection may be
unnecessary; previously thought to have prevented issues with refreshing. unnecessary; previously thought to have prevented issues with refreshing.
@ -93,5 +94,5 @@ async function setupTransportOnLoad() {
setupTransportOnLoad(); setupTransportOnLoad();
*/ */
registerSW(); registerSW();
})(); })();