mirror of
https://github.com/QuiteAFancyEmerald/Holy-Unblocker.git
synced 2025-05-12 11:30:01 -04:00
added prettier properly
This commit is contained in:
parent
995183d239
commit
bdc83ba579
45 changed files with 3796 additions and 3134 deletions
1
.prettierignore
Normal file
1
.prettierignore
Normal file
|
@ -0,0 +1 @@
|
|||
/lib
|
197
README.md
197
README.md
|
@ -1,4 +1,5 @@
|
|||
<img align="left" width="70px" src="https://raw.githubusercontent.com/titaniumnetwork-dev/Holy-Unblocker/master/views/assets/img/icon.png"></img>
|
||||
|
||||
# Holy Unblocker LTS (v6.x.x)
|
||||
|
||||
Holy Unblocker LTS, an experimental web proxy service, can bypass web filters or 'blockers' regardless of whether the method of censorship is client-side or network-based. This includes the potential ability to bypass content blockers overseas, Chrome extensions, localized client firewalls, and network-related filters.
|
||||
|
@ -9,6 +10,7 @@ Works with a large number of sites, including YouTube, Discord, and more!
|
|||
Also has a good amount of locally hosted games featured on the site.
|
||||
|
||||
#### Supports
|
||||
|
||||
- Youtube.com
|
||||
- Discord.com
|
||||
- Google.com
|
||||
|
@ -17,6 +19,7 @@ Also has a good amount of locally hosted games featured on the site.
|
|||
- And more sites!
|
||||
|
||||
#### Features:
|
||||
|
||||
- Tab customization using the Options menu for improved stealth
|
||||
- Considerable variety with the open selection of proxy types
|
||||
- Game library with moderately decent titles
|
||||
|
@ -44,6 +47,7 @@ Read below for information if the official site is blocked or for obtaining more
|
|||
|
||||
[](https://railway.app/new/template?template=https%3A%2F%2Fgithub.com%2FQuiteAFancyEmerald%2FHoly-Unblocker)
|
||||
[](https://app.koyeb.com/deploy?type=git&repository=github.com/QuiteAFancyEmerald/Holy-Unblocker-Old&branch=master&name=HolyUnblocker&run_command=npm%start)
|
||||
|
||||
</details>
|
||||
|
||||
## Table of contents:
|
||||
|
@ -81,8 +85,8 @@ The default place for the proxy when its started is `http://localhost:8080`, but
|
|||
|
||||
This website is hosted locally with Ultraviolet and Rammerhead built-in.
|
||||
|
||||
|
||||
## Structure
|
||||
|
||||
<details><summary>Web Pages</summary>
|
||||
|
||||
- `index.html`: The homepage of the site.
|
||||
|
@ -109,15 +113,18 @@ This website is hosted locally with Ultraviolet and Rammerhead built-in.
|
|||
</details>
|
||||
|
||||
### Structure Information
|
||||
|
||||
- `/views/`: The physical site base of Holy Unblocker goes here where static assets are served.
|
||||
- `/src/`: For future implementation of obfuscation and keyword removing features.
|
||||
|
||||
#### Details of `/views/`
|
||||
|
||||
- `/archive/` is used for game pages and vibeOS.
|
||||
- `/pages/` is used for the HTML for the site.
|
||||
- `/assets/` is used for storing various CSS, JS, image, and JSON files.
|
||||
|
||||
#### Scripts located in `/views/assets/js/`
|
||||
|
||||
- `bareTransport.js` is a locally installed version of the bare transport module which allows Ultraviolet to function.
|
||||
- `card.js` adds a fancy visual effect to the box cards displayed on the welcome screen.
|
||||
- `common.js` is used on all pages and allows commonly used features to function.
|
||||
|
@ -126,109 +133,114 @@ This website is hosted locally with Ultraviolet and Rammerhead built-in.
|
|||
- `register-sw.js` creates and manages service workers that allow Ultraviolet to function, and also uses bare transport.
|
||||
|
||||
## Future Additions
|
||||
|
||||
This will be our nonexhaustive todo list for Holy Unblocker LTS v6.x.x and above.
|
||||
|
||||
## Code Cleanup
|
||||
|
||||
- [ ] Remove all current obfuscation in the source code. It needs to be dynamically obfuscated if anything, or not obfuscated at all. This option will be a config option on the server side before rendering with Express for a performance focus. Meta elements will have an additonal attribute indicating if they should be moved. This is to ensure a SEO source can be served by config or a source focused on pure censorship evasion.
|
||||
- [ ] Optimize the stylesheets and the HTML layout. Add more proper commenting and redivide the code so that it's less hard on the eyes.
|
||||
- [ ] Optimize the JS. This time it won't be in one line and will be somewhat thoroughly commented.
|
||||
- [ ] Restructure navigation scripts to ensure updated proxy functionality is sanitized and effective
|
||||
- [x] Particles.js automatically adjusting per display size - done
|
||||
- [x] Fix routes.mjs throwing with incorrect paths - done
|
||||
- [x] Create test script - done
|
||||
- [x] XSS and fingerprinting protection (may need updates) - done
|
||||
- [x] Update games navigation JS and page/change to JSON object system - done
|
||||
- [ ] Ensure all the original submodules get added back to HU-Archive
|
||||
- [x] Mobile support - (welcome screen only, partial/needs work)
|
||||
- [ ] SEO overhaul adapted from the v2 SEO Guide format
|
||||
- [ ] Randomize the __uv$config global, and optionally randomize the UV prefix and URL encoding via cookies
|
||||
- [ ] Remove all current obfuscation in the source code. It needs to be dynamically obfuscated if anything, or not obfuscated at all. This option will be a config option on the server side before rendering with Express for a performance focus. Meta elements will have an additonal attribute indicating if they should be moved. This is to ensure a SEO source can be served by config or a source focused on pure censorship evasion.
|
||||
- [ ] Optimize the stylesheets and the HTML layout. Add more proper commenting and redivide the code so that it's less hard on the eyes.
|
||||
- [ ] Optimize the JS. This time it won't be in one line and will be somewhat thoroughly commented.
|
||||
- [ ] Restructure navigation scripts to ensure updated proxy functionality is sanitized and effective
|
||||
- [x] Particles.js automatically adjusting per display size - done
|
||||
- [x] Fix routes.mjs throwing with incorrect paths - done
|
||||
- [x] Create test script - done
|
||||
- [x] XSS and fingerprinting protection (may need updates) - done
|
||||
- [x] Update games navigation JS and page/change to JSON object system - done
|
||||
- [ ] Ensure all the original submodules get added back to HU-Archive
|
||||
- [x] Mobile support - (welcome screen only, partial/needs work)
|
||||
- [ ] SEO overhaul adapted from the v2 SEO Guide format
|
||||
- [ ] Randomize the \_\_uv$config global, and optionally randomize the UV prefix and URL encoding via cookies
|
||||
|
||||
## Proxy/Site Functionality
|
||||
- [x] Ensure Ultraviolet is updated to support bare-mux and wisp - done
|
||||
- [x] Add Rammerhead support - done
|
||||
- [x] Fix slow Ultraviolet speeds despite being local; something on the backend?? - done
|
||||
- [x] Fix Ultraviolet on Firefox - (partial/needs work)
|
||||
- [ ] Adapt Applications page to use either Rammerhead or UV (for Reddit, YouTube, Discord)
|
||||
- [x] libcurl, epoxy and all that fun stuff - done
|
||||
- [x] socks5/tor routing option that can be configured (enabled) via either a cookie or pathname as a settings meny option - done
|
||||
- [ ] Update games page content
|
||||
- [ ] Update settings menu again to make more room for more features
|
||||
- [x] Update csel.js (after Setting menu redesign) to support custom transports, icon swap, routing - done
|
||||
- [x] Update csel.js to support network based adblocking (partial/needs work)
|
||||
- [ ] Add a "website self-destruct" button to the settings menu
|
||||
- [ ] Flesh out and rework the UV / bare client error page
|
||||
- [ ] Update sw.js to support workerware (https://github.com/MercuryWorkshop/workerware)
|
||||
- [ ] Omnibox autoupdate script (for the Google/Bing style auto suggest feature)
|
||||
- [ ] Games library will feature 10000 items; 5000 flash games and 5000 other game types
|
||||
|
||||
- [x] Ensure Ultraviolet is updated to support bare-mux and wisp - done
|
||||
- [x] Add Rammerhead support - done
|
||||
- [x] Fix slow Ultraviolet speeds despite being local; something on the backend?? - done
|
||||
- [x] Fix Ultraviolet on Firefox - (partial/needs work)
|
||||
- [ ] Adapt Applications page to use either Rammerhead or UV (for Reddit, YouTube, Discord)
|
||||
- [x] libcurl, epoxy and all that fun stuff - done
|
||||
- [x] socks5/tor routing option that can be configured (enabled) via either a cookie or pathname as a settings meny option - done
|
||||
- [ ] Update games page content
|
||||
- [ ] Update settings menu again to make more room for more features
|
||||
- [x] Update csel.js (after Setting menu redesign) to support custom transports, icon swap, routing - done
|
||||
- [x] Update csel.js to support network based adblocking (partial/needs work)
|
||||
- [ ] Add a "website self-destruct" button to the settings menu
|
||||
- [ ] Flesh out and rework the UV / bare client error page
|
||||
- [ ] Update sw.js to support workerware (https://github.com/MercuryWorkshop/workerware)
|
||||
- [ ] Omnibox autoupdate script (for the Google/Bing style auto suggest feature)
|
||||
- [ ] Games library will feature 10000 items; 5000 flash games and 5000 other game types
|
||||
|
||||
## Site Redesign
|
||||
- [x] Landing Cards - done
|
||||
- [x] Change fonts to cleaner look
|
||||
- [ ] Add more AOS interactions on scroll or hover
|
||||
- [ ] Add subtle noise to background elements
|
||||
- [ ] Update colors + add themes
|
||||
- [ ] Toggle elements
|
||||
- [ ] Other card options
|
||||
- [ ] Radial blur elements
|
||||
- [ ] Code standard examples
|
||||
- [ ] Horizontal/general movement on scroll with AOS
|
||||
- [ ] Showcase dev dependencies
|
||||
- [ ] Update icons
|
||||
- [x] Landing Page - (partial/needs work)
|
||||
- [x] Settings Menu - (partial/needs work)
|
||||
- [ ] More Dropdown Menu
|
||||
- [ ] Web Proxies page
|
||||
- [ ] Application page
|
||||
- [ ] Hosting page
|
||||
- [ ] Resources page
|
||||
- [ ] Games Library page
|
||||
- [ ] Emulators Library page
|
||||
- [ ] Emu Library page
|
||||
- [ ] Web Games page
|
||||
- [ ] Flash Games page
|
||||
- [ ] Documentation page
|
||||
- [ ] FAQ page
|
||||
- [ ] Credits page
|
||||
- [ ] TOS page
|
||||
- [x] Footer Design - (partial/needs work)
|
||||
- [x] Header Design - (partial/needs work)
|
||||
|
||||
- [x] Landing Cards - done
|
||||
- [x] Change fonts to cleaner look
|
||||
- [ ] Add more AOS interactions on scroll or hover
|
||||
- [ ] Add subtle noise to background elements
|
||||
- [ ] Update colors + add themes
|
||||
- [ ] Toggle elements
|
||||
- [ ] Other card options
|
||||
- [ ] Radial blur elements
|
||||
- [ ] Code standard examples
|
||||
- [ ] Horizontal/general movement on scroll with AOS
|
||||
- [ ] Showcase dev dependencies
|
||||
- [ ] Update icons
|
||||
- [x] Landing Page - (partial/needs work)
|
||||
- [x] Settings Menu - (partial/needs work)
|
||||
- [ ] More Dropdown Menu
|
||||
- [ ] Web Proxies page
|
||||
- [ ] Application page
|
||||
- [ ] Hosting page
|
||||
- [ ] Resources page
|
||||
- [ ] Games Library page
|
||||
- [ ] Emulators Library page
|
||||
- [ ] Emu Library page
|
||||
- [ ] Web Games page
|
||||
- [ ] Flash Games page
|
||||
- [ ] Documentation page
|
||||
- [ ] FAQ page
|
||||
- [ ] Credits page
|
||||
- [ ] TOS page
|
||||
- [x] Footer Design - (partial/needs work)
|
||||
- [x] Header Design - (partial/needs work)
|
||||
|
||||
## Community Requests
|
||||
- [ ] Add [Quake WASM](https://github.com/GMH-Code/Quake-WASM)
|
||||
- [ ] Celeste WASM
|
||||
- [ ] Doom WASM
|
||||
|
||||
- [ ] Add [Quake WASM](https://github.com/GMH-Code/Quake-WASM)
|
||||
- [ ] Celeste WASM
|
||||
- [ ] Doom WASM
|
||||
|
||||
## Changelog
|
||||
|
||||
- Added wisp support
|
||||
- Fixed AD config setting being opt-out; ads are not implemented in the project however
|
||||
- Added Rammerhead support (locally)
|
||||
- Drastically updated visuals across the service and refactored stylesheets
|
||||
- Bumped games page functionality
|
||||
- Updated randomization scripts to ES6 syntax and implemented the alternative to RegEx string replacement
|
||||
- Helmet for express implemented into backend
|
||||
- Improved component handling via templates.mjs along with deletion of obsolete files that previously handled this standard in a poor format
|
||||
- Fixed oddly slow speeds with Ultraviolet (as well as a general version bump to support epoxy-tls and bare-mux)
|
||||
- Implemented testing scripts for an improved GitHub actions workflow by doing a quick test on proxy + site functionality
|
||||
- Greatly optimized client-side scripts across the site with a new standard, and generally reworked to no longer leave global variables
|
||||
- Changes to server.mjs with path logic and error handling
|
||||
- Updated standards for common scripts
|
||||
- libcurl and bare-as-module support added
|
||||
- Deleted 5 JS scripts and moved lots of data into JSON files. Big reorganization. Games menu core scripts now nested inside of common.js utilizing a JSON system
|
||||
- Massive updates to the Settings menu visually and functionality wise; added Bare-Mux support for swapping transports to work with Ultraviolet, default icons and selective adblocking + Tor on any proxy instances
|
||||
- CSS Has been partially restructured for mobile support, and is now properly arranged into clearly labeled sections (for the most part)
|
||||
- Incorporated makeshift domain blacklisting functionality into Ultraviolet, currently used for blocking ads if ads are disabled in settings
|
||||
- Fleshed out the SEO with more descriptions and better labeling
|
||||
- Switched to Fastify for serving content from the backend; a separate Express backend file is kept in case it's still needed
|
||||
- Rammerhead is now locally built into the HU LTS repository
|
||||
- Simplified the HU LTS setup process and added more default npm commands
|
||||
- Added wisp support
|
||||
- Fixed AD config setting being opt-out; ads are not implemented in the project however
|
||||
- Added Rammerhead support (locally)
|
||||
- Drastically updated visuals across the service and refactored stylesheets
|
||||
- Bumped games page functionality
|
||||
- Updated randomization scripts to ES6 syntax and implemented the alternative to RegEx string replacement
|
||||
- Helmet for express implemented into backend
|
||||
- Improved component handling via templates.mjs along with deletion of obsolete files that previously handled this standard in a poor format
|
||||
- Fixed oddly slow speeds with Ultraviolet (as well as a general version bump to support epoxy-tls and bare-mux)
|
||||
- Implemented testing scripts for an improved GitHub actions workflow by doing a quick test on proxy + site functionality
|
||||
- Greatly optimized client-side scripts across the site with a new standard, and generally reworked to no longer leave global variables
|
||||
- Changes to server.mjs with path logic and error handling
|
||||
- Updated standards for common scripts
|
||||
- libcurl and bare-as-module support added
|
||||
- Deleted 5 JS scripts and moved lots of data into JSON files. Big reorganization. Games menu core scripts now nested inside of common.js utilizing a JSON system
|
||||
- Massive updates to the Settings menu visually and functionality wise; added Bare-Mux support for swapping transports to work with Ultraviolet, default icons and selective adblocking + Tor on any proxy instances
|
||||
- CSS Has been partially restructured for mobile support, and is now properly arranged into clearly labeled sections (for the most part)
|
||||
- Incorporated makeshift domain blacklisting functionality into Ultraviolet, currently used for blocking ads if ads are disabled in settings
|
||||
- Fleshed out the SEO with more descriptions and better labeling
|
||||
- Switched to Fastify for serving content from the backend; a separate Express backend file is kept in case it's still needed
|
||||
- Rammerhead is now locally built into the HU LTS repository
|
||||
- Simplified the HU LTS setup process and added more default npm commands
|
||||
|
||||
## Vague Explanation for Beginners With External Proxies and Hosting
|
||||
|
||||
You will first want to host your proxies locally or externally. OUTDATED
|
||||
|
||||
#### List of some good hosting options:
|
||||
|
||||
- <a href="#">Oracle Cloud</a> (Free, Paid, Dedicated)
|
||||
- <a href="https://repl.it">Repl.it</a> (Free)
|
||||
- <a href="https://azure.microsoft.com">Azure</a> (Free and Paid)
|
||||
|
@ -248,13 +260,15 @@ This is an example of DNS records involving Heroku. Self-hosting will require `A
|
|||
As stated previously, Holy Unblocker is hosted locally with Ultraviolet.
|
||||
|
||||
#### Freenom/Domain Steps
|
||||
|
||||
For beginners, Freenom is a good provider for obtaining domains for free. However, Freenom only provides their TLDs (`.cf`, `.ml`, `.gq`, `.ga`, and `.tk`) for free, which can be easily blocked.
|
||||
|
||||
- Get some Freenom domains then add them to your Heroku instance (Personal > [App Name] > Settings > Domains)
|
||||
Add a domain for both `www.example.cf` and `example.cf` with .cf being interchangeable with other Freenom domain names.
|
||||
Add a domain for both `www.example.cf` and `example.cf` with .cf being interchangeable with other Freenom domain names.
|
||||
- If you prefer to obtain premium domains (TLDs) then use <a href="https://porkbun.com">Porkbun</a>, which offers domains for amazing prices. Literally a `.net` domain normally costs around $10. On Porkbun for the first year it costs $3 so its definitely a deal.
|
||||
|
||||
#### Cloudflare Steps
|
||||
|
||||
- Use Cloudflare (make an account), add your site (Freenom Domain or other) and then add your various DNS targets to Cloudflare. Make sure you add Cloudflare's Nameservers which will be given later when you are adding your site.
|
||||
|
||||
Make sure they are CNAME although A records also work and try to follow this structure:
|
||||
|
@ -268,11 +282,10 @@ Make sure they are CNAME although A records also work and try to follow this str
|
|||
|
||||
`CNAME | a | your-womginx-instance-here.herokudns.com`
|
||||
|
||||
|
||||
|
||||
Make sure HTTPS is forced and have SSL set to Flexible for some services. Otherwise you can have SSL set to Full.
|
||||
|
||||
#### Workspace Configurations
|
||||
|
||||
Preferably if you have your own device use Visual Studio Code. Pretty much the best option you can get but obviously this is an opinion. Also make sure you have <a href="https://nodejs.org/">Node.JS</a> installed on your machine.
|
||||
|
||||
Not going to go too in depth with this part but first fork this repository. The clone it locally through a Terminal of some sort depending on what OS you are on. Make sure you navigate to the folder you want to set this up in.
|
||||
|
@ -294,16 +307,19 @@ node_modules
|
|||
Now you have your following workspace environment setup. To deploy the following workspace you just created you will need to look up depending on your hosting provider.
|
||||
|
||||
For an online IDE that you can use on your school computer and/or chromebook use GitPod. Basically the equivalent of Visual Studio Code but with in-browser support.
|
||||
|
||||
- Make an account: `https://gitpod.io/`
|
||||
- Fork this repo and enter in this URL to setup your workspace: `https://gitpod.io#https://github.com/YourNameHere/Holy-Unblocker/`
|
||||
|
||||
Use the same steps above by running `npm install` in your repository and adding a `.gitignore` in your root directory specifying to exclude `node_modules`.
|
||||
|
||||
## Detailed FAQ
|
||||
|
||||
<details>
|
||||
<summary>Quick FAQ</summary>
|
||||
|
||||
#### Where can I find the games for this repo? (404 errors, etc.)
|
||||
|
||||
Due to piracy concerns, size, etc. this has been moved over <a href="https://github.com/QuiteAFancyEmerald/HU-Archive">here</a>. EmuLibrary is not featured in the public version.
|
||||
|
||||
**Why is the site I am on not working correctly or having CAPTCHA errors?**
|
||||
|
@ -319,6 +335,7 @@ If you still have any questions feel free to ask them in the discord linked here
|
|||
</details>
|
||||
|
||||
### Why are official domains now numbered? Is this project maintained again?
|
||||
|
||||
Yes, this project is active again for LTS support! However, the approach is now much simpler to ensure functionality: traffic will be focused on a single domain. More than ever, this project serves as a proof of concept for the brave souls willing to innovate in the web proxy service space.
|
||||
|
||||
<details><summary>Former Closing Message (Original - 2022)</summary>
|
||||
|
@ -338,8 +355,8 @@ Emerald :HuTaoHype:
|
|||
|
||||
</details>
|
||||
|
||||
|
||||
## More Information
|
||||
|
||||
This project is maintained by the Holy Unblocker LTS team and is an official flagship Titanium Network web proxy site.
|
||||
|
||||
- <a href="https://github.com/titaniumnetwork-dev/">https://github.com/titaniumnetwork-dev/</a>
|
||||
|
@ -348,6 +365,7 @@ This project is maintained by the Holy Unblocker LTS team and is an official fla
|
|||
View the official website for more detail and credits.
|
||||
|
||||
### Web Proxy Sources:
|
||||
|
||||
This project currently uses Ultraviolet, Wisp, Womginx, and Rammerhead, linked below.
|
||||
|
||||
- <a href="https://github.com/titaniumnetwork-dev/Ultraviolet">Ultraviolet</a>
|
||||
|
@ -357,7 +375,6 @@ This project currently uses Ultraviolet, Wisp, Womginx, and Rammerhead, linked b
|
|||
- <a href="https://github.com/MercuryWorkshop/bare-mux">Bare-Mux</a>
|
||||
- <a href="https://github.com/tomphttp/bare-server-node">TOMP Bare Server</a>
|
||||
|
||||
|
||||
### Other Dependencies:
|
||||
|
||||
- <a href="https://github.com/tsparticles/tsparticles">tsparticles</a>
|
||||
|
|
170
TODO.md
170
TODO.md
|
@ -2,97 +2,99 @@ This will be our nonexhaustive todo list for Holy Unblocker LTS v6.x.x and above
|
|||
|
||||
## Code Cleanup
|
||||
|
||||
- [ ] Remove all current obfuscation in the source code. It needs to be dynamically obfuscated if anything, or not obfuscated at all. This option will be a config option on the server side before rendering with Express for a performance focus. Meta elements will have an additonal attribute indicating if they should be moved. This is to ensure a SEO source can be served by config or a source focused on pure censorship evasion.
|
||||
- [ ] Optimize the stylesheets and the HTML layout. Add more proper commenting and redivide the code so that it's less hard on the eyes.
|
||||
- [ ] Optimize the JS. This time it won't be in one line and will be somewhat thoroughly commented.
|
||||
- [ ] Restructure navigation scripts to ensure updated proxy functionality is sanitized and effective
|
||||
- [x] Particles.js automatically adjusting per display size - done
|
||||
- [x] Fix routes.mjs throwing with incorrect paths - done
|
||||
- [x] Create test script - done
|
||||
- [x] XSS and fingerprinting protection (may need updates) - done
|
||||
- [x] Update games navigation JS and page/change to JSON object system - done
|
||||
- [ ] Ensure all the original submodules get added back to HU-Archive
|
||||
- [x] Mobile support - (welcome screen only, partial/needs work)
|
||||
- [ ] SEO overhaul adapted from the v2 SEO Guide format
|
||||
- [ ] Randomize the __uv$config global, and optionally randomize the UV prefix and URL encoding via cookies
|
||||
- [ ] Remove all current obfuscation in the source code. It needs to be dynamically obfuscated if anything, or not obfuscated at all. This option will be a config option on the server side before rendering with Express for a performance focus. Meta elements will have an additonal attribute indicating if they should be moved. This is to ensure a SEO source can be served by config or a source focused on pure censorship evasion.
|
||||
- [ ] Optimize the stylesheets and the HTML layout. Add more proper commenting and redivide the code so that it's less hard on the eyes.
|
||||
- [ ] Optimize the JS. This time it won't be in one line and will be somewhat thoroughly commented.
|
||||
- [ ] Restructure navigation scripts to ensure updated proxy functionality is sanitized and effective
|
||||
- [x] Particles.js automatically adjusting per display size - done
|
||||
- [x] Fix routes.mjs throwing with incorrect paths - done
|
||||
- [x] Create test script - done
|
||||
- [x] XSS and fingerprinting protection (may need updates) - done
|
||||
- [x] Update games navigation JS and page/change to JSON object system - done
|
||||
- [ ] Ensure all the original submodules get added back to HU-Archive
|
||||
- [x] Mobile support - (welcome screen only, partial/needs work)
|
||||
- [ ] SEO overhaul adapted from the v2 SEO Guide format
|
||||
- [ ] Randomize the \_\_uv$config global, and optionally randomize the UV prefix and URL encoding via cookies
|
||||
|
||||
## Proxy/Site Functionality
|
||||
- [x] Ensure Ultraviolet is updated to support bare-mux and wisp - done
|
||||
- [x] Add Rammerhead support - done
|
||||
- [x] Fix slow Ultraviolet speeds despite being local; something on the backend?? - done
|
||||
- [x] Fix Ultraviolet on Firefox - (partial/needs work)
|
||||
- [ ] Adapt Applications page to use either Rammerhead or UV (for Reddit, YouTube, Discord)
|
||||
- [x] libcurl, epoxy and all that fun stuff - done
|
||||
- [x] socks5/tor routing option that can be configured (enabled) via either a cookie or pathname as a settings meny option - done
|
||||
- [ ] Update games page content
|
||||
- [ ] Update settings menu again to make more room for more features
|
||||
- [x] Update csel.js (after Setting menu redesign) to support custom transports, icon swap, routing - done
|
||||
- [x] Update csel.js to support network based adblocking (partial/needs work)
|
||||
- [ ] Add a "website self-destruct" button to the settings menu
|
||||
- [ ] Flesh out and rework the UV / bare client error page
|
||||
- [ ] Update sw.js to support workerware (https://github.com/MercuryWorkshop/workerware)
|
||||
- [ ] Omnibox autoupdate script (for the Google/Bing style auto suggest feature)
|
||||
- [ ] Games library will feature 10000 items; 5000 flash games and 5000 other game types
|
||||
|
||||
- [x] Ensure Ultraviolet is updated to support bare-mux and wisp - done
|
||||
- [x] Add Rammerhead support - done
|
||||
- [x] Fix slow Ultraviolet speeds despite being local; something on the backend?? - done
|
||||
- [x] Fix Ultraviolet on Firefox - (partial/needs work)
|
||||
- [ ] Adapt Applications page to use either Rammerhead or UV (for Reddit, YouTube, Discord)
|
||||
- [x] libcurl, epoxy and all that fun stuff - done
|
||||
- [x] socks5/tor routing option that can be configured (enabled) via either a cookie or pathname as a settings meny option - done
|
||||
- [ ] Update games page content
|
||||
- [ ] Update settings menu again to make more room for more features
|
||||
- [x] Update csel.js (after Setting menu redesign) to support custom transports, icon swap, routing - done
|
||||
- [x] Update csel.js to support network based adblocking (partial/needs work)
|
||||
- [ ] Add a "website self-destruct" button to the settings menu
|
||||
- [ ] Flesh out and rework the UV / bare client error page
|
||||
- [ ] Update sw.js to support workerware (https://github.com/MercuryWorkshop/workerware)
|
||||
- [ ] Omnibox autoupdate script (for the Google/Bing style auto suggest feature)
|
||||
- [ ] Games library will feature 10000 items; 5000 flash games and 5000 other game types
|
||||
|
||||
## Site Redesign
|
||||
- [x] Landing Cards - done
|
||||
- [x] Change fonts to cleaner look
|
||||
- [ ] Add more AOS interactions on scroll or hover
|
||||
- [ ] Add subtle noise to background elements
|
||||
- [ ] Update colors + add themes
|
||||
- [ ] Toggle elements
|
||||
- [ ] Other card options
|
||||
- [ ] Radial blur elements
|
||||
- [ ] Code standard examples
|
||||
- [ ] Horizontal/general movement on scroll with AOS
|
||||
- [ ] Showcase dev dependencies
|
||||
- [ ] Update icons
|
||||
- [x] Landing Page - (partial/needs work)
|
||||
- [x] Settings Menu - (partial/needs work)
|
||||
- [ ] More Dropdown Menu
|
||||
- [ ] Web Proxies page
|
||||
- [ ] Application page
|
||||
- [ ] Hosting page
|
||||
- [ ] Resources page
|
||||
- [ ] Games Library page
|
||||
- [ ] Emulators Library page
|
||||
- [ ] Emu Library page
|
||||
- [ ] Web Games page
|
||||
- [ ] Flash Games page
|
||||
- [ ] Documentation page
|
||||
- [ ] FAQ page
|
||||
- [ ] Credits page
|
||||
- [ ] TOS page
|
||||
- [x] Footer Design - (partial/needs work)
|
||||
- [x] Header Design - (partial/needs work)
|
||||
|
||||
- [x] Landing Cards - done
|
||||
- [x] Change fonts to cleaner look
|
||||
- [ ] Add more AOS interactions on scroll or hover
|
||||
- [ ] Add subtle noise to background elements
|
||||
- [ ] Update colors + add themes
|
||||
- [ ] Toggle elements
|
||||
- [ ] Other card options
|
||||
- [ ] Radial blur elements
|
||||
- [ ] Code standard examples
|
||||
- [ ] Horizontal/general movement on scroll with AOS
|
||||
- [ ] Showcase dev dependencies
|
||||
- [ ] Update icons
|
||||
- [x] Landing Page - (partial/needs work)
|
||||
- [x] Settings Menu - (partial/needs work)
|
||||
- [ ] More Dropdown Menu
|
||||
- [ ] Web Proxies page
|
||||
- [ ] Application page
|
||||
- [ ] Hosting page
|
||||
- [ ] Resources page
|
||||
- [ ] Games Library page
|
||||
- [ ] Emulators Library page
|
||||
- [ ] Emu Library page
|
||||
- [ ] Web Games page
|
||||
- [ ] Flash Games page
|
||||
- [ ] Documentation page
|
||||
- [ ] FAQ page
|
||||
- [ ] Credits page
|
||||
- [ ] TOS page
|
||||
- [x] Footer Design - (partial/needs work)
|
||||
- [x] Header Design - (partial/needs work)
|
||||
|
||||
## Community Requests
|
||||
- [ ] Add [Quake WASM](https://github.com/GMH-Code/Quake-WASM)
|
||||
- [ ] Celeste WASM
|
||||
- [ ] Doom WASM
|
||||
|
||||
- [ ] Add [Quake WASM](https://github.com/GMH-Code/Quake-WASM)
|
||||
- [ ] Celeste WASM
|
||||
- [ ] Doom WASM
|
||||
|
||||
## Changelog
|
||||
|
||||
- Added wisp support
|
||||
- Fixed AD config setting being opt-out; ads are not implemented in the project however
|
||||
- Added Rammerhead support (locally)
|
||||
- Drastically updated visuals across the service and refactored stylesheets
|
||||
- Bumped games page functionality
|
||||
- Updated randomization scripts to ES6 syntax and implemented the alternative to RegEx string replacement
|
||||
- Helmet for express implemented into backend
|
||||
- Improved component handling via templates.mjs along with deletion of obsolete files that previously handled this standard in a poor format
|
||||
- Fixed oddly slow speeds with Ultraviolet (as well as a general version bump to support epoxy-tls and bare-mux)
|
||||
- Implemented testing scripts for an improved GitHub actions workflow by doing a quick test on proxy + site functionality
|
||||
- Greatly optimized client-side scripts across the site with a new standard, and generally reworked to no longer leave global variables
|
||||
- Changes to server.mjs with path logic and error handling
|
||||
- Updated standards for common scripts
|
||||
- libcurl and bare-as-module support added
|
||||
- Deleted 5 JS scripts and moved lots of data into JSON files. Big reorganization. Games menu core scripts now nested inside of common.js utilizing a JSON system
|
||||
- Massive updates to the Settings menu visually and functionality wise; added Bare-Mux support for swapping transports to work with Ultraviolet, default icons and selective adblocking + Tor on any proxy instances
|
||||
- CSS Has been partially restructured for mobile support, and is now properly arranged into clearly labeled sections (for the most part)
|
||||
- Incorporated makeshift domain blacklisting functionality into Ultraviolet, currently used for blocking ads if ads are disabled in settings
|
||||
- Fleshed out the SEO with more descriptions and better labeling
|
||||
- Switched to Fastify for serving content from the backend; a separate Express backend file is kept in case it's still needed
|
||||
- Rammerhead is now locally built into the HU LTS repository
|
||||
- Simplified the HU LTS setup process and added more default npm commands
|
||||
- Added wisp support
|
||||
- Fixed AD config setting being opt-out; ads are not implemented in the project however
|
||||
- Added Rammerhead support (locally)
|
||||
- Drastically updated visuals across the service and refactored stylesheets
|
||||
- Bumped games page functionality
|
||||
- Updated randomization scripts to ES6 syntax and implemented the alternative to RegEx string replacement
|
||||
- Helmet for express implemented into backend
|
||||
- Improved component handling via templates.mjs along with deletion of obsolete files that previously handled this standard in a poor format
|
||||
- Fixed oddly slow speeds with Ultraviolet (as well as a general version bump to support epoxy-tls and bare-mux)
|
||||
- Implemented testing scripts for an improved GitHub actions workflow by doing a quick test on proxy + site functionality
|
||||
- Greatly optimized client-side scripts across the site with a new standard, and generally reworked to no longer leave global variables
|
||||
- Changes to server.mjs with path logic and error handling
|
||||
- Updated standards for common scripts
|
||||
- libcurl and bare-as-module support added
|
||||
- Deleted 5 JS scripts and moved lots of data into JSON files. Big reorganization. Games menu core scripts now nested inside of common.js utilizing a JSON system
|
||||
- Massive updates to the Settings menu visually and functionality wise; added Bare-Mux support for swapping transports to work with Ultraviolet, default icons and selective adblocking + Tor on any proxy instances
|
||||
- CSS Has been partially restructured for mobile support, and is now properly arranged into clearly labeled sections (for the most part)
|
||||
- Incorporated makeshift domain blacklisting functionality into Ultraviolet, currently used for blocking ads if ads are disabled in settings
|
||||
- Fleshed out the SEO with more descriptions and better labeling
|
||||
- Switched to Fastify for serving content from the backend; a separate Express backend file is kept in case it's still needed
|
||||
- Rammerhead is now locally built into the HU LTS repository
|
||||
- Simplified the HU LTS setup process and added more default npm commands
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
(async () => {
|
||||
await import("./src/server.mjs");
|
||||
await import('./src/server.mjs');
|
||||
})();
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: "HolyUB",
|
||||
script: "./backend.js",
|
||||
name: 'HolyUB',
|
||||
script: './backend.js',
|
||||
env: {
|
||||
PORT: 8080,
|
||||
NODE_ENV: "development",
|
||||
NODE_ENV: 'development',
|
||||
},
|
||||
env_production: {
|
||||
PORT: 8080,
|
||||
NODE_ENV: "production",
|
||||
NODE_ENV: 'production',
|
||||
},
|
||||
instances: "1",
|
||||
exec_interpreter: "babel-node",
|
||||
exec_mode: "fork",
|
||||
instances: '1',
|
||||
exec_interpreter: 'babel-node',
|
||||
exec_mode: 'fork',
|
||||
autorestart: true,
|
||||
exp_backoff_restart_delay: 100,
|
||||
cron_restart: "*/10 * * * *",
|
||||
cron_restart: '*/10 * * * *',
|
||||
kill_timeout: 3000,
|
||||
watch: false,
|
||||
},
|
||||
|
|
16
prettier.config.js
Normal file
16
prettier.config.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
module.exports = {
|
||||
printWidth: 80, // Wrap lines at 80 characters
|
||||
tabWidth: 2, // Use 2 spaces per indentation level
|
||||
useTabs: false, // Use spaces instead of tabs
|
||||
semi: true, // Add a semicolon at the end of every statement
|
||||
singleQuote: true, // Use single quotes instead of double quotes
|
||||
quoteProps: 'as-needed', // Only add quotes around object properties where required
|
||||
jsxSingleQuote: false, // Use double quotes in JSX
|
||||
trailingComma: 'es5', // Add trailing commas where valid in ES5 (objects, arrays, etc.)
|
||||
bracketSpacing: true, // Print spaces between brackets in object literals
|
||||
jsxBracketSameLine: false, // Put the `>` of a multi-line JSX element at the end of the last line
|
||||
arrowParens: 'always', // Always include parentheses around arrow function arguments
|
||||
htmlWhitespaceSensitivity: 'css', // Respect the default value of CSS display property
|
||||
endOfLine: 'lf', // Use line feed only (\n) for newlines
|
||||
embeddedLanguageFormatting: 'auto', // Format embedded code if Prettier can automatically identify it
|
||||
};
|
|
@ -1,10 +1,10 @@
|
|||
// This file is solely used for the automatically run GitHub job, which checks to
|
||||
// see if all HU LTS code is working properly (at least on an Ubuntu machine).
|
||||
|
||||
const axios = require("axios");
|
||||
const puppeteer = require("puppeteer");
|
||||
const axios = require('axios');
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
const testEndpoint = async url => {
|
||||
const testEndpoint = async (url) => {
|
||||
try {
|
||||
const response = await axios.get(url);
|
||||
return response.status === 200;
|
||||
|
@ -29,58 +29,58 @@ const testGeneratedUrl = async (url, headers) => {
|
|||
|
||||
const testServerResponse = async () => {
|
||||
const endpoints = [
|
||||
"http://localhost:8080/",
|
||||
"http://localhost:8080/test-404",
|
||||
"http://localhost:8080/browsing",
|
||||
"http://localhost:8080/rammerhead",
|
||||
"http://localhost:8080/ultraviolet",
|
||||
"http://localhost:8080/documentation",
|
||||
"http://localhost:8080/questions",
|
||||
"http://localhost:8080/s",
|
||||
"http://localhost:8080/credits",
|
||||
"http://localhost:8080/bookmarklets",
|
||||
"http://localhost:8080/terms",
|
||||
"http://localhost:8080/games",
|
||||
"http://localhost:8080/web-games",
|
||||
"http://localhost:8080/emulators",
|
||||
"http://localhost:8080/flash-games",
|
||||
"http://localhost:8080/retro-games",
|
||||
"http://localhost:8080/youtube",
|
||||
"http://localhost:8080/apps",
|
||||
"http://localhost:8080/flash",
|
||||
"http://localhost:8080/webretro",
|
||||
"http://localhost:8080/vibe-os",
|
||||
"http://localhost:8080/assets/js/particlesjs/particles.js",
|
||||
"http://localhost:8080/assets/js/bareTransport.js",
|
||||
"http://localhost:8080/assets/js/card.js",
|
||||
"http://localhost:8080/assets/js/common-16451543478.js",
|
||||
"http://localhost:8080/assets/js/csel.js",
|
||||
"http://localhost:8080/assets/js/register-sw.js",
|
||||
"http://localhost:8080/assets/json/emu-nav.json",
|
||||
"http://localhost:8080/assets/json/blacklist.json",
|
||||
"http://localhost:8080/assets/json/emulib-nav.json",
|
||||
"http://localhost:8080/assets/json/flash-nav.json",
|
||||
"http://localhost:8080/assets/json/h5-nav.json",
|
||||
"http://localhost:8080/assets/json/links.json",
|
||||
"http://localhost:8080/baremux/index.js",
|
||||
"http://localhost:8080/baremux/worker.js",
|
||||
"http://localhost:8080/epoxy/index.mjs",
|
||||
"http://localhost:8080/uv/uv.bundle.js",
|
||||
"http://localhost:8080/uv/sw.js",
|
||||
"http://localhost:8080/uv/uv.config.js",
|
||||
"http://localhost:8080/uv/workerware.js",
|
||||
"http://localhost:8080/uv/WWError.js"
|
||||
'http://localhost:8080/',
|
||||
'http://localhost:8080/test-404',
|
||||
'http://localhost:8080/browsing',
|
||||
'http://localhost:8080/rammerhead',
|
||||
'http://localhost:8080/ultraviolet',
|
||||
'http://localhost:8080/documentation',
|
||||
'http://localhost:8080/questions',
|
||||
'http://localhost:8080/s',
|
||||
'http://localhost:8080/credits',
|
||||
'http://localhost:8080/bookmarklets',
|
||||
'http://localhost:8080/terms',
|
||||
'http://localhost:8080/games',
|
||||
'http://localhost:8080/web-games',
|
||||
'http://localhost:8080/emulators',
|
||||
'http://localhost:8080/flash-games',
|
||||
'http://localhost:8080/retro-games',
|
||||
'http://localhost:8080/youtube',
|
||||
'http://localhost:8080/apps',
|
||||
'http://localhost:8080/flash',
|
||||
'http://localhost:8080/webretro',
|
||||
'http://localhost:8080/vibe-os',
|
||||
'http://localhost:8080/assets/js/particlesjs/particles.js',
|
||||
'http://localhost:8080/assets/js/bareTransport.js',
|
||||
'http://localhost:8080/assets/js/card.js',
|
||||
'http://localhost:8080/assets/js/common-16451543478.js',
|
||||
'http://localhost:8080/assets/js/csel.js',
|
||||
'http://localhost:8080/assets/js/register-sw.js',
|
||||
'http://localhost:8080/assets/json/emu-nav.json',
|
||||
'http://localhost:8080/assets/json/blacklist.json',
|
||||
'http://localhost:8080/assets/json/emulib-nav.json',
|
||||
'http://localhost:8080/assets/json/flash-nav.json',
|
||||
'http://localhost:8080/assets/json/h5-nav.json',
|
||||
'http://localhost:8080/assets/json/links.json',
|
||||
'http://localhost:8080/baremux/index.js',
|
||||
'http://localhost:8080/baremux/worker.js',
|
||||
'http://localhost:8080/epoxy/index.mjs',
|
||||
'http://localhost:8080/uv/uv.bundle.js',
|
||||
'http://localhost:8080/uv/sw.js',
|
||||
'http://localhost:8080/uv/uv.config.js',
|
||||
'http://localhost:8080/uv/workerware.js',
|
||||
'http://localhost:8080/uv/WWError.js',
|
||||
];
|
||||
|
||||
const results = await Promise.all(endpoints.map(testEndpoint));
|
||||
const allPassed = results.every((result) => result);
|
||||
|
||||
if (allPassed) {
|
||||
console.log("All endpoints responded with status code 200. Test passed.");
|
||||
console.log('All endpoints responded with status code 200. Test passed.');
|
||||
await testCommonJSOnPage();
|
||||
} else {
|
||||
console.error(
|
||||
"One or more endpoints failed to respond with status code 200. Test failed."
|
||||
'One or more endpoints failed to respond with status code 200. Test failed.'
|
||||
);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
|
@ -89,9 +89,9 @@ const testServerResponse = async () => {
|
|||
const testCommonJSOnPage = async () => {
|
||||
const browser = await puppeteer.launch({
|
||||
args: [
|
||||
"--enable-features=NetworkService",
|
||||
"--enable-features=ServiceWorker",
|
||||
"--enable-features=InsecureOrigins",
|
||||
'--enable-features=NetworkService',
|
||||
'--enable-features=ServiceWorker',
|
||||
'--enable-features=InsecureOrigins',
|
||||
],
|
||||
headless: true,
|
||||
ignoreHTTPSErrors: true,
|
||||
|
@ -102,73 +102,75 @@ const testCommonJSOnPage = async () => {
|
|||
const getHeaders = async () => {
|
||||
const headers = {};
|
||||
|
||||
headers["User-Agent"] = await page.evaluate(() => navigator.userAgent);
|
||||
headers["Referer"] = await page.evaluate(() => window.location.href);
|
||||
headers['User-Agent'] = await page.evaluate(() => navigator.userAgent);
|
||||
headers['Referer'] = await page.evaluate(() => window.location.href);
|
||||
|
||||
return headers;
|
||||
};
|
||||
|
||||
const testRammerhead = async () => {
|
||||
await page.goto("http://localhost:8080/rammerhead");
|
||||
await page.goto('http://localhost:8080/rammerhead');
|
||||
|
||||
const testResults = await page.evaluate(async () => {
|
||||
const results = {};
|
||||
|
||||
await new Promise((resolve) => {
|
||||
if (document.readyState === "complete") {
|
||||
if (document.readyState === 'complete') {
|
||||
resolve();
|
||||
} else {
|
||||
window.addEventListener("load", resolve);
|
||||
window.addEventListener('load', resolve);
|
||||
}
|
||||
});
|
||||
|
||||
// Locate the omnibox element on the Rammerhead page.
|
||||
let omnibox = document.getElementById("pr-rh");
|
||||
omnibox = omnibox && omnibox.querySelector("input[type=text]");
|
||||
// Locate the omnibox element on the Rammerhead page.
|
||||
let omnibox = document.getElementById('pr-rh');
|
||||
omnibox = omnibox && omnibox.querySelector('input[type=text]');
|
||||
|
||||
if (omnibox) {
|
||||
try {
|
||||
// Send an artificial input to the omnibox. The omnibox will create
|
||||
// a proxy URL and leave it as the input value in response.
|
||||
const urlPath = "example.com";
|
||||
// Send an artificial input to the omnibox. The omnibox will create
|
||||
// a proxy URL and leave it as the input value in response.
|
||||
const urlPath = 'example.com';
|
||||
omnibox.value = urlPath;
|
||||
await omnibox.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {code: "Validator Test"})
|
||||
new KeyboardEvent('keydown', { code: 'Validator Test' })
|
||||
);
|
||||
|
||||
// Wait up to 5 seconds for the omnibox to finish updating.
|
||||
const loadUrl = new Promise(resolve => {
|
||||
// Wait up to 5 seconds for the omnibox to finish updating.
|
||||
const loadUrl = new Promise((resolve) => {
|
||||
if (omnibox.value !== urlPath) resolve(omnibox.value);
|
||||
else omnibox.addEventListener("change", () => resolve(omnibox.value));
|
||||
else
|
||||
omnibox.addEventListener('change', () =>
|
||||
resolve(omnibox.value)
|
||||
);
|
||||
}),
|
||||
timeout = new Promise(resolve => {
|
||||
timeout = new Promise((resolve) => {
|
||||
setTimeout(() => resolve(omnibox.value), 40000);
|
||||
}),
|
||||
|
||||
// Record the proxy URL that the omnibox left here.
|
||||
// Record the proxy URL that the omnibox left here.
|
||||
rammerheadUrl = await Promise.race([loadUrl, timeout]);
|
||||
console.log("Generated Rammerhead URL:", rammerheadUrl);
|
||||
results.rammerhead = rammerheadUrl ? rammerheadUrl : "failure";
|
||||
console.log('Generated Rammerhead URL:', rammerheadUrl);
|
||||
results.rammerhead = rammerheadUrl ? rammerheadUrl : 'failure';
|
||||
} catch (e) {
|
||||
results.rammerhead = "failure: " + e.message;
|
||||
results.rammerhead = 'failure: ' + e.message;
|
||||
}
|
||||
} else {
|
||||
results.goProx = "not defined";
|
||||
results.goProx = 'not defined';
|
||||
}
|
||||
|
||||
return results;
|
||||
});
|
||||
|
||||
console.log("Rammerhead test results:", testResults);
|
||||
console.log('Rammerhead test results:', testResults);
|
||||
|
||||
const headers = await getHeaders();
|
||||
const rammerheadTestPassed =
|
||||
testResults.rammerhead !== "failure" &&
|
||||
testResults.rammerhead !== 'failure' &&
|
||||
(await testGeneratedUrl(testResults.rammerhead, headers));
|
||||
|
||||
console.log(
|
||||
`Rammerhead test result: ${
|
||||
rammerheadTestPassed ? "success" : "failure"
|
||||
rammerheadTestPassed ? 'success' : 'failure'
|
||||
}`
|
||||
);
|
||||
|
||||
|
@ -211,90 +213,96 @@ xx xx
|
|||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
const testUltraviolet = async () => {
|
||||
await page.goto("http://localhost:8080/ultraviolet");
|
||||
await page.goto('http://localhost:8080/ultraviolet');
|
||||
|
||||
const testResults = await page.evaluate(async () => {
|
||||
const results = [{}, {}];
|
||||
|
||||
await new Promise((resolve) => {
|
||||
|
||||
const waitForDocument = () => document.readyState === "complete"
|
||||
const waitForDocument = () =>
|
||||
document.readyState === 'complete'
|
||||
? resolve()
|
||||
: window.addEventListener("load", resolve);
|
||||
: window.addEventListener('load', resolve);
|
||||
|
||||
// Wait until a service worker is registered before continuing.
|
||||
// Also make sure the document is loaded.
|
||||
const waitForWorker = async () => setTimeout(async () => {
|
||||
// Wait until a service worker is registered before continuing.
|
||||
// Also make sure the document is loaded.
|
||||
const waitForWorker = async () =>
|
||||
setTimeout(async () => {
|
||||
(await navigator.serviceWorker.getRegistrations()).length >= 1
|
||||
? waitForDocument()
|
||||
: waitForWorker()
|
||||
: waitForWorker();
|
||||
}, 1000);
|
||||
|
||||
waitForWorker();
|
||||
});
|
||||
|
||||
// Locate the omnibox element on the Ultraviolet page.
|
||||
let omnibox = document.getElementById("pr-uv");
|
||||
omnibox = omnibox && omnibox.querySelector("input[type=text]");
|
||||
// Locate the omnibox element on the Ultraviolet page.
|
||||
let omnibox = document.getElementById('pr-uv');
|
||||
omnibox = omnibox && omnibox.querySelector('input[type=text]');
|
||||
|
||||
if (omnibox) {
|
||||
// For the hacky URL test, use the URL page's EXACT title.
|
||||
// For the hacky URL test, use the URL page's EXACT title.
|
||||
const website = {
|
||||
path: "example.com",
|
||||
title: "Example Domain"
|
||||
path: 'example.com',
|
||||
title: 'Example Domain',
|
||||
};
|
||||
|
||||
try {
|
||||
// Send an artificial input to the omnibox. The omnibox will create
|
||||
// a proxy URL and leave it as the input value in response.
|
||||
// Send an artificial input to the omnibox. The omnibox will create
|
||||
// a proxy URL and leave it as the input value in response.
|
||||
omnibox.value = website.path;
|
||||
await omnibox.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {code: "Validator Test"})
|
||||
new KeyboardEvent('keydown', { code: 'Validator Test' })
|
||||
);
|
||||
|
||||
// Record the proxy URL that the omnibox left here.
|
||||
// Record the proxy URL that the omnibox left here.
|
||||
const generatedUrl = omnibox.value;
|
||||
console.log("Generated Ultraviolet URL:", generatedUrl);
|
||||
results[0].ultraviolet = generatedUrl ? generatedUrl : "failure";
|
||||
console.log('Generated Ultraviolet URL:', generatedUrl);
|
||||
results[0].ultraviolet = generatedUrl ? generatedUrl : 'failure';
|
||||
|
||||
// Test to see if the document title for example.com has loaded,
|
||||
// by appending an IFrame to the document and grabbing its content.
|
||||
// Test to see if the document title for example.com has loaded,
|
||||
// by appending an IFrame to the document and grabbing its content.
|
||||
const testGeneratedUrlHacky = async (url) => {
|
||||
let result = false;
|
||||
const exampleIFrame = document.createElement("iframe");
|
||||
const waitForDocument = new Promise(resolve => {
|
||||
const exampleIFrame = document.createElement('iframe');
|
||||
const waitForDocument = new Promise((resolve) => {
|
||||
document.documentElement.appendChild(exampleIFrame);
|
||||
exampleIFrame.addEventListener("load", () => {
|
||||
result = exampleIFrame.contentWindow.document.title === website.title;
|
||||
exampleIFrame.addEventListener('load', () => {
|
||||
result =
|
||||
exampleIFrame.contentWindow.document.title ===
|
||||
website.title;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
exampleIFrame.src = url;
|
||||
exampleIFrame.style.display = "none";
|
||||
exampleIFrame.style.display = 'none';
|
||||
await waitForDocument;
|
||||
return result;
|
||||
};
|
||||
|
||||
results[1].uvTestPassed = await testGeneratedUrlHacky(results[0].ultraviolet);
|
||||
results[1].uvTestPassed = await testGeneratedUrlHacky(
|
||||
results[0].ultraviolet
|
||||
);
|
||||
} catch (e) {
|
||||
results[0].ultraviolet = "failure: " + e.message;
|
||||
results[0].ultraviolet = 'failure: ' + e.message;
|
||||
}
|
||||
} else {
|
||||
results[0].goProx = "not defined";
|
||||
results[0].goProx = 'not defined';
|
||||
}
|
||||
|
||||
return results;
|
||||
});
|
||||
|
||||
console.log("Ultraviolet test results:", testResults[0]);
|
||||
console.log('Ultraviolet test results:', testResults[0]);
|
||||
|
||||
if (testResults[0].ultraviolet && testResults[0].ultraviolet !== "failure") {
|
||||
if (
|
||||
testResults[0].ultraviolet &&
|
||||
testResults[0].ultraviolet !== 'failure'
|
||||
) {
|
||||
const uvTestPassed = testResults[1].uvTestPassed;
|
||||
console.log(
|
||||
`Ultraviolet test result: ${uvTestPassed ? "success" : "failure"}`
|
||||
`Ultraviolet test result: ${uvTestPassed ? 'success' : 'failure'}`
|
||||
);
|
||||
return uvTestPassed;
|
||||
} else {
|
||||
|
@ -308,14 +316,14 @@ xx xx
|
|||
const ultravioletPassed = await testUltraviolet();
|
||||
|
||||
if (rammerheadPassed && ultravioletPassed) {
|
||||
console.log("Both tests passed.");
|
||||
console.log('Both tests passed.');
|
||||
process.exitCode = 0;
|
||||
} else {
|
||||
console.error("Tests failed.");
|
||||
console.error('Tests failed.');
|
||||
process.exitCode = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error in testCommonJSOnPage:", error.message);
|
||||
console.error('Error in testCommonJSOnPage:', error.message);
|
||||
process.exitCode = 1;
|
||||
} finally {
|
||||
await browser.close();
|
||||
|
|
117
run-command.mjs
117
run-command.mjs
|
@ -7,129 +7,136 @@ import ecosystem from './ecosystem.config.js';
|
|||
// Some necessary constants are copied over from /src/server.mjs.
|
||||
|
||||
const config = Object.freeze(
|
||||
JSON.parse(await readFile(new URL("./src/config.json", import.meta.url)))
|
||||
JSON.parse(await readFile(new URL('./src/config.json', import.meta.url)))
|
||||
),
|
||||
ecosystemConfig = Object.freeze(
|
||||
ecosystem.apps.find(app => app.name === "HolyUB") || ecosystem.apps[0]
|
||||
ecosystem.apps.find((app) => app.name === 'HolyUB') || ecosystem.apps[0]
|
||||
);
|
||||
|
||||
const serverUrl = (base => {
|
||||
const serverUrl = ((base) => {
|
||||
try {
|
||||
base = new URL(config.host);
|
||||
} catch (e) {
|
||||
base = new URL("http://a");
|
||||
base = new URL('http://a');
|
||||
base.host = config.host;
|
||||
}
|
||||
base.port = ecosystemConfig[ config.production ? "env_production" : "env" ].PORT;
|
||||
base.port =
|
||||
ecosystemConfig[config.production ? 'env_production' : 'env'].PORT;
|
||||
return Object.freeze(base);
|
||||
})();
|
||||
|
||||
const shutdown = fileURLToPath(new URL("./src/.shutdown", import.meta.url));
|
||||
const shutdown = fileURLToPath(new URL('./src/.shutdown', import.meta.url));
|
||||
|
||||
// Run each command line argument passed after node run-command.mjs.
|
||||
// Commands are defined in the switch case statement below.
|
||||
for (let i = 2; i < process.argv.length; i++)
|
||||
switch (process.argv[i]) {
|
||||
// Commmand to boot up the server. Use PM2 to run if production is true in the
|
||||
// config file.
|
||||
case "start":
|
||||
// Commmand to boot up the server. Use PM2 to run if production is true in the
|
||||
// config file.
|
||||
case 'start':
|
||||
if (config.production)
|
||||
exec("npx pm2 start ecosystem.config.js --env 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")
|
||||
// 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) throw error;
|
||||
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.
|
||||
// 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)),
|
||||
{detached: true}
|
||||
fileURLToPath(new URL('./backend.js', import.meta.url)),
|
||||
{ detached: true }
|
||||
);
|
||||
server.unref();
|
||||
server.disconnect();
|
||||
}
|
||||
break;
|
||||
|
||||
// Stop the server. Make a temporary file that the server will check for if told
|
||||
// to shut down. This is done by sending a GET request to the server.
|
||||
case "stop": {
|
||||
await writeFile(shutdown, "");
|
||||
// Stop the server. Make a temporary file that the server will check for if told
|
||||
// to shut down. This is done by sending a GET request to the server.
|
||||
case 'stop': {
|
||||
await writeFile(shutdown, '');
|
||||
let timeoutId = undefined;
|
||||
try {
|
||||
// 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
|
||||
// if checking the server on localhost and the port is unused.
|
||||
// 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
|
||||
// if checking the server on localhost and the port is unused.
|
||||
const response = await Promise.race([
|
||||
fetch(new URL("/test-shutdown", serverUrl)),
|
||||
new Promise(resolve => {
|
||||
fetch(new URL('/test-shutdown', serverUrl)),
|
||||
new Promise((resolve) => {
|
||||
timeoutId = setTimeout(() => {
|
||||
resolve("Error");
|
||||
resolve('Error');
|
||||
}, 5000);
|
||||
})
|
||||
}),
|
||||
]);
|
||||
clearTimeout(timeoutId);
|
||||
if (response === "Error") throw new Error("Server is unresponsive.");
|
||||
if (response === 'Error') throw new Error('Server is unresponsive.');
|
||||
} catch (e) {
|
||||
// Check if this is the error thrown by the fetch request for an unused port.
|
||||
// Don't print the unused port error, since nothing has actually broken.
|
||||
// Check if this is the error thrown by the fetch request for an unused port.
|
||||
// Don't print the unused port error, since nothing has actually broken.
|
||||
if (e instanceof TypeError) clearTimeout(timeoutId);
|
||||
else console.error(e);
|
||||
await unlink(shutdown);
|
||||
}
|
||||
// Do not run this if Node will be killed later in this script. It will fail.
|
||||
if (config.production && !process.argv.slice(i + 1).includes("kill"))
|
||||
exec("npx pm2 stop ecosystem.config.js", (error, stdout) => {
|
||||
// Do not run this if Node will be killed later in this script. It will fail.
|
||||
if (config.production && !process.argv.slice(i + 1).includes('kill'))
|
||||
exec('npx pm2 stop ecosystem.config.js', (error, stdout) => {
|
||||
if (error) throw error;
|
||||
console.log(stdout);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "build": {
|
||||
const dist = fileURLToPath(new URL("./views/dist", import.meta.url));
|
||||
await rm(dist, {force: true, recursive: true});
|
||||
case 'build': {
|
||||
const dist = fileURLToPath(new URL('./views/dist', import.meta.url));
|
||||
await rm(dist, { force: true, recursive: true });
|
||||
await mkdir(dist);
|
||||
await build({
|
||||
entryPoints: [
|
||||
"./views/uv/**/*.js",
|
||||
"./views/assets/js/**/*.js",
|
||||
"./views/assets/css/**/*.css"
|
||||
'./views/uv/**/*.js',
|
||||
'./views/assets/js/**/*.js',
|
||||
'./views/assets/css/**/*.css',
|
||||
],
|
||||
platform: "browser",
|
||||
platform: 'browser',
|
||||
sourcemap: true,
|
||||
bundle: true,
|
||||
minify: true,
|
||||
external: ["*.png", "*.jpg", "*.jpeg", "*.webp", "*.svg"],
|
||||
outdir: dist
|
||||
external: ['*.png', '*.jpg', '*.jpeg', '*.webp', '*.svg'],
|
||||
outdir: dist,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
// 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
|
||||
// more PM2 debugging tools.
|
||||
case "kill":
|
||||
if (process.platform === "win32")
|
||||
exec("( npx pm2 delete ecosystem.config.js ) ; taskkill /F /IM node*",
|
||||
(error, stdout) => {console.log(stdout)}
|
||||
// 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
|
||||
// more PM2 debugging tools.
|
||||
case 'kill':
|
||||
if (process.platform === 'win32')
|
||||
exec(
|
||||
'( npx pm2 delete ecosystem.config.js ) ; taskkill /F /IM node*',
|
||||
(error, stdout) => {
|
||||
console.log(stdout);
|
||||
}
|
||||
);
|
||||
else exec("npx pm2 delete ecosystem.config.js; pkill node",
|
||||
(error, stdout) => {console.log(stdout)}
|
||||
else
|
||||
exec(
|
||||
'npx pm2 delete ecosystem.config.js; pkill node',
|
||||
(error, stdout) => {
|
||||
console.log(stdout);
|
||||
}
|
||||
);
|
||||
break;
|
||||
|
||||
// No default case.
|
||||
|
||||
// No default case.
|
||||
}
|
||||
|
||||
|
||||
process.exitCode = 0;
|
||||
|
|
|
@ -18,7 +18,5 @@
|
|||
"splash": [
|
||||
"This version is the public LTS build of the web proxy service project and may be hosted unofficially. Check your domain or jo­in the <a id='tnlink' target='_blank'>T­N Dis­co­rd</a> for official pr­iva️te site lin­ks for your safety."
|
||||
],
|
||||
"version": [
|
||||
"6.3.7"
|
||||
]
|
||||
"version": ["6.3.7"]
|
||||
}
|
||||
|
|
144
src/express.mjs
144
src/express.mjs
|
@ -1,69 +1,65 @@
|
|||
import { paintSource, tryReadFile } from "./randomization.mjs";
|
||||
import loadTemplates from "./templates.mjs";
|
||||
import pkg from "./routes.mjs";
|
||||
import { readFile } from "fs/promises";
|
||||
import path from "path";
|
||||
import express from "express";
|
||||
import helmet from "helmet";
|
||||
import http from "http";
|
||||
import createRammerhead from "rammerhead/src/server/index.js";
|
||||
import wisp from "wisp-server-node";
|
||||
import { epoxyPath } from "@mercuryworkshop/epoxy-transport";
|
||||
import { libcurlPath } from "@mercuryworkshop/libcurl-transport";
|
||||
import { bareModulePath } from "@mercuryworkshop/bare-as-module3";
|
||||
import { baremuxPath } from "@mercuryworkshop/bare-mux/node";
|
||||
import { uvPath } from "@titaniumnetwork-dev/ultraviolet";
|
||||
import { paintSource, tryReadFile } from './randomization.mjs';
|
||||
import loadTemplates from './templates.mjs';
|
||||
import pkg from './routes.mjs';
|
||||
import { readFile } from 'fs/promises';
|
||||
import path from 'path';
|
||||
import express from 'express';
|
||||
import helmet from 'helmet';
|
||||
import http from 'http';
|
||||
import createRammerhead from 'rammerhead/src/server/index.js';
|
||||
import wisp from 'wisp-server-node';
|
||||
import { epoxyPath } from '@mercuryworkshop/epoxy-transport';
|
||||
import { libcurlPath } from '@mercuryworkshop/libcurl-transport';
|
||||
import { bareModulePath } from '@mercuryworkshop/bare-as-module3';
|
||||
import { baremuxPath } from '@mercuryworkshop/bare-mux/node';
|
||||
import { uvPath } from '@titaniumnetwork-dev/ultraviolet';
|
||||
// import { createBareServer } from "@tomphttp/bare-server-node";
|
||||
|
||||
const config = JSON.parse(
|
||||
await readFile(new URL("./config.json", import.meta.url))
|
||||
),
|
||||
{ pages, text404 } = pkg,
|
||||
__dirname = path.resolve(),
|
||||
port = process.env.PORT || config.port,
|
||||
app = express(),
|
||||
router = express.Router(),
|
||||
// bare = createBareServer("/bare/"),
|
||||
rh = createRammerhead();
|
||||
await readFile(new URL('./config.json', import.meta.url))
|
||||
),
|
||||
{ pages, text404 } = pkg,
|
||||
__dirname = path.resolve(),
|
||||
port = process.env.PORT || config.port,
|
||||
app = express(),
|
||||
router = express.Router(),
|
||||
// bare = createBareServer("/bare/"),
|
||||
rh = createRammerhead();
|
||||
|
||||
const rammerheadScopes = [
|
||||
"/rammerhead.js",
|
||||
"/hammerhead.js",
|
||||
"/transport-worker.js",
|
||||
"/task.js",
|
||||
"/iframe-task.js",
|
||||
"/worker-hammerhead.js",
|
||||
"/messaging",
|
||||
"/sessionexists",
|
||||
"/deletesession",
|
||||
"/newsession",
|
||||
"/editsession",
|
||||
"/needpassword",
|
||||
"/syncLocalStorage",
|
||||
"/api/shuffleDict",
|
||||
"/mainport",
|
||||
'/rammerhead.js',
|
||||
'/hammerhead.js',
|
||||
'/transport-worker.js',
|
||||
'/task.js',
|
||||
'/iframe-task.js',
|
||||
'/worker-hammerhead.js',
|
||||
'/messaging',
|
||||
'/sessionexists',
|
||||
'/deletesession',
|
||||
'/newsession',
|
||||
'/editsession',
|
||||
'/needpassword',
|
||||
'/syncLocalStorage',
|
||||
'/api/shuffleDict',
|
||||
'/mainport',
|
||||
];
|
||||
|
||||
const rammerheadSession = /^\/[a-z0-9]{32}/,
|
||||
|
||||
shouldRouteRh = req => {
|
||||
const url = new URL(req.url, "http://0.0.0.0");
|
||||
shouldRouteRh = (req) => {
|
||||
const url = new URL(req.url, 'http://0.0.0.0');
|
||||
return (
|
||||
rammerheadScopes.includes(url.pathname) ||
|
||||
rammerheadSession.test(url.pathname)
|
||||
);
|
||||
},
|
||||
|
||||
routeRhRequest = (req, res) => {
|
||||
rh.emit("request", req, res);
|
||||
},
|
||||
|
||||
routeRhUpgrade = (req, socket, head) => {
|
||||
rh.emit("upgrade", req, socket, head);
|
||||
},
|
||||
|
||||
server = http.createServer((req, res) => {
|
||||
/*
|
||||
},
|
||||
routeRhRequest = (req, res) => {
|
||||
rh.emit('request', req, res);
|
||||
},
|
||||
routeRhUpgrade = (req, socket, head) => {
|
||||
rh.emit('upgrade', req, socket, head);
|
||||
},
|
||||
server = http.createServer((req, res) => {
|
||||
/*
|
||||
if (bare.shouldRoute(req)) {
|
||||
bare.routeRequest(req, res);
|
||||
} else
|
||||
|
@ -73,17 +69,17 @@ server = http.createServer((req, res) => {
|
|||
} else {
|
||||
app(req, res);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
server.on("upgrade", (req, socket, head) => {
|
||||
/*
|
||||
server.on('upgrade', (req, socket, head) => {
|
||||
/*
|
||||
if (bare.shouldRoute(req)) {
|
||||
bare.routeUpgrade(req, socket, head);
|
||||
} else
|
||||
*/
|
||||
if (shouldRouteRh(req)) {
|
||||
routeRhUpgrade(req, socket, head);
|
||||
} else if (req.url.endsWith("/wisp/")) {
|
||||
} else if (req.url.endsWith('/wisp/')) {
|
||||
wisp.routeRequest(req, socket, head);
|
||||
}
|
||||
});
|
||||
|
@ -99,16 +95,19 @@ app.use(
|
|||
// 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
|
||||
// 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(
|
||||
paintSource(
|
||||
loadTemplates(
|
||||
tryReadFile(
|
||||
path.join(__dirname,
|
||||
"views",
|
||||
// Return the error page if the query is not found in
|
||||
// routes.mjs. Also set index as the default page.
|
||||
"/?".indexOf(req.url) ? pages[Object.keys(req.query)[0]] || "error.html" : pages.index
|
||||
path.join(
|
||||
__dirname,
|
||||
'views',
|
||||
// Return the error page if the query is not found in
|
||||
// routes.mjs. Also set index as the default page.
|
||||
'/?'.indexOf(req.url)
|
||||
? pages[Object.keys(req.query)[0]] || 'error.html'
|
||||
: pages.index
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -116,16 +115,15 @@ router.get("/", async (req, res) =>
|
|||
)
|
||||
);
|
||||
|
||||
|
||||
app.use(router);
|
||||
app.use(express.static(path.join(__dirname, "views")));
|
||||
app.use("/uv/", express.static(uvPath));
|
||||
app.use("/epoxy/", express.static(epoxyPath));
|
||||
app.use("/libcurl/", express.static(libcurlPath));
|
||||
app.use("/bareasmodule/", express.static(bareModulePath));
|
||||
app.use("/baremux/", express.static(baremuxPath));
|
||||
app.use(express.static(path.join(__dirname, 'views')));
|
||||
app.use('/uv/', express.static(uvPath));
|
||||
app.use('/epoxy/', express.static(epoxyPath));
|
||||
app.use('/libcurl/', express.static(libcurlPath));
|
||||
app.use('/bareasmodule/', express.static(bareModulePath));
|
||||
app.use('/baremux/', express.static(baremuxPath));
|
||||
|
||||
app.disable("x-powered-by");
|
||||
app.disable('x-powered-by');
|
||||
|
||||
// Redundant code since 404 is handled elsewhere; left here as insurance.
|
||||
app.use((req, res) => {
|
||||
|
@ -133,4 +131,4 @@ app.use((req, res) => {
|
|||
});
|
||||
|
||||
server.listen(port);
|
||||
console.log("Holy Unblocker is listening on port " + port + ".");
|
||||
console.log('Holy Unblocker is listening on port ' + port + '.');
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import pkg from "./routes.mjs";
|
||||
import { existsSync, readFileSync } from "fs";
|
||||
import pkg from './routes.mjs';
|
||||
import { existsSync, readFileSync } from 'fs';
|
||||
export { paintSource, preloaded404, tryReadFile };
|
||||
const {
|
||||
cookingInserts,
|
||||
|
@ -9,7 +9,7 @@ const {
|
|||
cacheBustList,
|
||||
VersionValue,
|
||||
text404,
|
||||
} = pkg;
|
||||
} = pkg;
|
||||
|
||||
// Below are lots of function definitions used to obfuscate the website.
|
||||
// This makes the website harder to properly categorize, as its source code
|
||||
|
@ -19,29 +19,29 @@ const randomListItem = (lis) => () => lis[(Math.random() * lis.length) | 0],
|
|||
getRandomChar = randomListItem(charRandom),
|
||||
insertCharset = (str) => str.replace(charset, getRandomChar),
|
||||
getRandomSplash = randomListItem(splashRandom),
|
||||
hutaoInsert = (str) => str.replaceAll("<!--HUTAOWOA-->", getRandomSplash),
|
||||
versionInsert = (str) => str.replaceAll("<!-- VERSION -->", VersionValue),
|
||||
hutaoInsert = (str) => str.replaceAll('<!--HUTAOWOA-->', getRandomSplash),
|
||||
versionInsert = (str) => str.replaceAll('<!-- VERSION -->', VersionValue),
|
||||
getCookingText = () =>
|
||||
`<span style="display:none" data-fact="${randomListItem(vegetables)()}">${randomListItem(cookingInserts)()}</span>`,
|
||||
insertCooking = (str) =>
|
||||
str.replaceAll(
|
||||
"<!-- IMPORTANT-HUTAOCOOKINGINSERT-DONOTDELETE -->",
|
||||
'<!-- IMPORTANT-HUTAOCOOKINGINSERT-DONOTDELETE -->',
|
||||
getCookingText
|
||||
),
|
||||
// This one isn't for obfuscation; it's just for dealing with cache issues.
|
||||
// This one isn't for obfuscation; it's just for dealing with cache issues.
|
||||
cacheBusting = (str) => {
|
||||
for (let item of Object.entries(cacheBustList))
|
||||
str = str.replaceAll(item[0], item[1]);
|
||||
return str;
|
||||
},
|
||||
// Apply the final obfuscation changes to an entire file.
|
||||
// Apply the final obfuscation changes to an entire file.
|
||||
paintSource = (str) =>
|
||||
insertCharset(hutaoInsert(versionInsert(insertCooking(cacheBusting(str))))),
|
||||
// Use this instead of text404 for a preloaded error page.
|
||||
// Use this instead of text404 for a preloaded error page.
|
||||
preloaded404 = paintSource(text404),
|
||||
// Grab the text content of a file. Ensure the file is a string.
|
||||
// Grab the text content of a file. Ensure the file is a string.
|
||||
tryReadFile = (file) =>
|
||||
existsSync(file + "") ? readFileSync(file + "", "utf8") : preloaded404;
|
||||
existsSync(file + '') ? readFileSync(file + '', 'utf8') : preloaded404;
|
||||
|
||||
/*
|
||||
// All of this is now old code.
|
||||
|
|
|
@ -1,75 +1,75 @@
|
|||
import { readFileSync } from "fs";
|
||||
import path from "path";
|
||||
import { readFile } from "fs/promises";
|
||||
import { readFileSync } from 'fs';
|
||||
import path from 'path';
|
||||
import { readFile } from 'fs/promises';
|
||||
|
||||
const insert = JSON.parse(
|
||||
await readFile(new URL("./data.json", import.meta.url))
|
||||
await readFile(new URL('./data.json', import.meta.url))
|
||||
);
|
||||
|
||||
const __dirname = path.resolve();
|
||||
|
||||
const text404 = readFileSync(
|
||||
path.normalize(__dirname + "/views/error.html"),
|
||||
"utf8"
|
||||
path.normalize(__dirname + '/views/error.html'),
|
||||
'utf8'
|
||||
);
|
||||
|
||||
const pages = {
|
||||
index: "index.html",
|
||||
"manifest.json": "manifest.json",
|
||||
"test-404": "error.html",
|
||||
index: 'index.html',
|
||||
'manifest.json': 'manifest.json',
|
||||
'test-404': 'error.html',
|
||||
/* Main */
|
||||
documentation: "docs.html",
|
||||
questions: "faq.html",
|
||||
s: "pages/frame.html",
|
||||
browsing: "pages/surf.html",
|
||||
credits: "pages/nav/credits.html",
|
||||
bookmarklets: "pages/nav/bookmarklets.html",
|
||||
terms: "pages/nav/terms.html",
|
||||
documentation: 'docs.html',
|
||||
questions: 'faq.html',
|
||||
s: 'pages/frame.html',
|
||||
browsing: 'pages/surf.html',
|
||||
credits: 'pages/nav/credits.html',
|
||||
bookmarklets: 'pages/nav/bookmarklets.html',
|
||||
terms: 'pages/nav/terms.html',
|
||||
/* Games */
|
||||
games: "pages/nav/gtools.html",
|
||||
"web-games": "pages/nav/games5.html",
|
||||
emulators: "pages/nav/emulators.html",
|
||||
"flash-games": "pages/nav/flash.html",
|
||||
"retro-games": "pages/nav/emulibrary.html",
|
||||
games: 'pages/nav/gtools.html',
|
||||
'web-games': 'pages/nav/games5.html',
|
||||
emulators: 'pages/nav/emulators.html',
|
||||
'flash-games': 'pages/nav/flash.html',
|
||||
'retro-games': 'pages/nav/emulibrary.html',
|
||||
/* Proxies */
|
||||
ultraviolet: "pages/proxnav/ultraviolet.html",
|
||||
rammerhead: "pages/proxnav/rammerhead.html",
|
||||
ultraviolet: 'pages/proxnav/ultraviolet.html',
|
||||
rammerhead: 'pages/proxnav/rammerhead.html',
|
||||
/* Proxy Presets */
|
||||
youtube: "pages/proxnav/preset/youtube.html",
|
||||
apps: "pages/proxnav/preset/applications.html",
|
||||
youtube: 'pages/proxnav/preset/youtube.html',
|
||||
apps: 'pages/proxnav/preset/applications.html',
|
||||
/* Misc */
|
||||
flash: "archive/gfiles/flash/index.html",
|
||||
webretro: "archive/gfiles/rarch/index.html",
|
||||
"vibe-os": "archive/vibeOS/index.html",
|
||||
flash: 'archive/gfiles/flash/index.html',
|
||||
webretro: 'archive/gfiles/rarch/index.html',
|
||||
'vibe-os': 'archive/vibeOS/index.html',
|
||||
};
|
||||
|
||||
const externalPages = {
|
||||
github: {
|
||||
default: "https://github.com/QuiteAFancyEmerald/Holy-Unblocker",
|
||||
aos: "https://github.com/michalsnik/aos",
|
||||
"bare-module": "https://github.com/motortruck1221/bare-as-module3",
|
||||
"bare-mux": "https://github.com/MercuryWorkshop/bare-mux",
|
||||
epoxy: "https://github.com/MercuryWorkshop/epoxy-tls",
|
||||
fastify: "https://github.com/fastify/fastify",
|
||||
"font-awesome": "https://github.com/FortAwesome/Font-Awesome",
|
||||
"libcurl-js": "https://github.com/ading2210/libcurl.js",
|
||||
"nord-theme": "https://github.com/nordtheme",
|
||||
ultraviolet: "https://github.com/titaniumnetwork-dev/Ultraviolet",
|
||||
wisp: "https://github.com/MercuryWorkshop/wisp-protocol"
|
||||
default: 'https://github.com/QuiteAFancyEmerald/Holy-Unblocker',
|
||||
aos: 'https://github.com/michalsnik/aos',
|
||||
'bare-module': 'https://github.com/motortruck1221/bare-as-module3',
|
||||
'bare-mux': 'https://github.com/MercuryWorkshop/bare-mux',
|
||||
epoxy: 'https://github.com/MercuryWorkshop/epoxy-tls',
|
||||
fastify: 'https://github.com/fastify/fastify',
|
||||
'font-awesome': 'https://github.com/FortAwesome/Font-Awesome',
|
||||
'libcurl-js': 'https://github.com/ading2210/libcurl.js',
|
||||
'nord-theme': 'https://github.com/nordtheme',
|
||||
ultraviolet: 'https://github.com/titaniumnetwork-dev/Ultraviolet',
|
||||
wisp: 'https://github.com/MercuryWorkshop/wisp-protocol',
|
||||
},
|
||||
"titaniumnetwork-documentation": "https://docs.titaniumnetwork.org",
|
||||
"rammerhead-discord": "https://discord.gg/VNT4E7gN5Y"
|
||||
'titaniumnetwork-documentation': 'https://docs.titaniumnetwork.org',
|
||||
'rammerhead-discord': 'https://discord.gg/VNT4E7gN5Y',
|
||||
};
|
||||
|
||||
const cookingInserts = insert.content,
|
||||
vegetables = insert.keywords,
|
||||
charRandom = insert.chars,
|
||||
splashRandom = insert.splash,
|
||||
VersionValue = insert.version,
|
||||
cacheBustList = {
|
||||
"styles.css": "styles-1644738239.css",
|
||||
"common.js": "common-16451543478.js",
|
||||
};
|
||||
vegetables = insert.keywords,
|
||||
charRandom = insert.chars,
|
||||
splashRandom = insert.splash,
|
||||
VersionValue = insert.version,
|
||||
cacheBustList = {
|
||||
'styles.css': 'styles-1644738239.css',
|
||||
'common.js': 'common-16451543478.js',
|
||||
};
|
||||
|
||||
export default {
|
||||
pages,
|
||||
|
|
193
src/server.mjs
193
src/server.mjs
|
@ -1,15 +1,15 @@
|
|||
import Fastify from 'fastify';
|
||||
import { createServer } from 'node:http';
|
||||
import wisp from 'wisp-server-node';
|
||||
import createRammerhead from "../lib/rammerhead/src/server/index.js";
|
||||
import { epoxyPath } from "@mercuryworkshop/epoxy-transport";
|
||||
import { libcurlPath } from "@mercuryworkshop/libcurl-transport";
|
||||
import { bareModulePath } from "@mercuryworkshop/bare-as-module3";
|
||||
import { baremuxPath } from "@mercuryworkshop/bare-mux/node";
|
||||
import { uvPath } from "@titaniumnetwork-dev/ultraviolet";
|
||||
import createRammerhead from '../lib/rammerhead/src/server/index.js';
|
||||
import { epoxyPath } from '@mercuryworkshop/epoxy-transport';
|
||||
import { libcurlPath } from '@mercuryworkshop/libcurl-transport';
|
||||
import { bareModulePath } from '@mercuryworkshop/bare-as-module3';
|
||||
import { baremuxPath } from '@mercuryworkshop/bare-mux/node';
|
||||
import { uvPath } from '@titaniumnetwork-dev/ultraviolet';
|
||||
import fastifyHelmet from '@fastify/helmet';
|
||||
import fastifyStatic from '@fastify/static';
|
||||
import pageRoutes from "./routes.mjs";
|
||||
import pageRoutes from './routes.mjs';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { paintSource, preloaded404, tryReadFile } from './randomization.mjs';
|
||||
|
@ -19,10 +19,10 @@ import { existsSync, unlinkSync } from 'node:fs';
|
|||
import ecosystem from '../ecosystem.config.js';
|
||||
|
||||
const config = Object.freeze(
|
||||
JSON.parse(await readFile(new URL("./config.json", import.meta.url)))
|
||||
JSON.parse(await readFile(new URL('./config.json', import.meta.url)))
|
||||
),
|
||||
ecosystemConfig = Object.freeze(
|
||||
ecosystem.apps.find(app => app.name === "HolyUB") || ecosystem.apps[0]
|
||||
ecosystem.apps.find((app) => app.name === 'HolyUB') || ecosystem.apps[0]
|
||||
),
|
||||
{ pages, externalPages } = pageRoutes,
|
||||
__dirname = path.resolve();
|
||||
|
@ -30,71 +30,71 @@ const config = Object.freeze(
|
|||
// 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
|
||||
// at /ecosystem.config.js.
|
||||
const serverUrl = (base => {
|
||||
const serverUrl = ((base) => {
|
||||
try {
|
||||
base = new URL(config.host);
|
||||
} catch (e) {
|
||||
base = new URL("http://a");
|
||||
base = new URL('http://a');
|
||||
base.host = config.host;
|
||||
}
|
||||
base.port = ecosystemConfig[ config.production ? "env_production" : "env" ].PORT;
|
||||
base.port =
|
||||
ecosystemConfig[config.production ? 'env_production' : 'env'].PORT;
|
||||
return Object.freeze(base);
|
||||
})();
|
||||
console.log(serverUrl);
|
||||
|
||||
// The server will check for the existence of this file when a shutdown is requested.
|
||||
// The shutdown script in run-command.js will temporarily produce this file.
|
||||
const shutdown = fileURLToPath(new URL("./.shutdown", import.meta.url));
|
||||
const shutdown = fileURLToPath(new URL('./.shutdown', import.meta.url));
|
||||
|
||||
const rh = createRammerhead();
|
||||
const rammerheadScopes = [
|
||||
"/rammerhead.js",
|
||||
"/hammerhead.js",
|
||||
"/transport-worker.js",
|
||||
"/task.js",
|
||||
"/iframe-task.js",
|
||||
"/worker-hammerhead.js",
|
||||
"/messaging",
|
||||
"/sessionexists",
|
||||
"/deletesession",
|
||||
"/newsession",
|
||||
"/editsession",
|
||||
"/needpassword",
|
||||
"/syncLocalStorage",
|
||||
"/api/shuffleDict",
|
||||
"/mainport",
|
||||
'/rammerhead.js',
|
||||
'/hammerhead.js',
|
||||
'/transport-worker.js',
|
||||
'/task.js',
|
||||
'/iframe-task.js',
|
||||
'/worker-hammerhead.js',
|
||||
'/messaging',
|
||||
'/sessionexists',
|
||||
'/deletesession',
|
||||
'/newsession',
|
||||
'/editsession',
|
||||
'/needpassword',
|
||||
'/syncLocalStorage',
|
||||
'/api/shuffleDict',
|
||||
'/mainport',
|
||||
];
|
||||
|
||||
const rammerheadSession = /^\/[a-z0-9]{32}/,
|
||||
shouldRouteRh = req => {
|
||||
shouldRouteRh = (req) => {
|
||||
try {
|
||||
const url = new URL(req.url, serverUrl);
|
||||
return (
|
||||
rammerheadScopes.includes(url.pathname) ||
|
||||
rammerheadSession.test(url.pathname)
|
||||
);
|
||||
} catch (e) {return false}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
routeRhRequest = (req, res) => {
|
||||
rh.emit("request", req, res);
|
||||
rh.emit('request', req, res);
|
||||
},
|
||||
routeRhUpgrade = (req, socket, head) => {
|
||||
rh.emit("upgrade", req, socket, head);
|
||||
rh.emit('upgrade', req, socket, head);
|
||||
};
|
||||
|
||||
// Create a server factory for RH, and wisp (and bare if you please).
|
||||
const serverFactory = (handler) => {
|
||||
return createServer()
|
||||
.on('request', (req, res) => {
|
||||
if (shouldRouteRh(req))
|
||||
routeRhRequest(req, res);
|
||||
if (shouldRouteRh(req)) routeRhRequest(req, res);
|
||||
else handler(req, res);
|
||||
})
|
||||
.on('upgrade', (req, socket, head) => {
|
||||
if (shouldRouteRh(req))
|
||||
routeRhUpgrade(req, socket, head);
|
||||
else if (req.url.endsWith('/wisp/'))
|
||||
wisp.routeRequest(req, socket, head);
|
||||
if (shouldRouteRh(req)) routeRhUpgrade(req, socket, head);
|
||||
else if (req.url.endsWith('/wisp/')) wisp.routeRequest(req, socket, head);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -103,133 +103,138 @@ const app = Fastify({
|
|||
ignoreDuplicateSlashes: true,
|
||||
ignoreTrailingSlash: true,
|
||||
logger: false,
|
||||
serverFactory: serverFactory
|
||||
serverFactory: serverFactory,
|
||||
});
|
||||
|
||||
// Apply Helmet middleware for security
|
||||
app.register(fastifyHelmet, {
|
||||
contentSecurityPolicy: false, // Disable CSP
|
||||
xPoweredBy: false
|
||||
xPoweredBy: false,
|
||||
});
|
||||
|
||||
// Assign server file paths to different paths, for serving content on the website.
|
||||
app.register(fastifyStatic, {
|
||||
root: fileURLToPath(new URL("../views/pages", import.meta.url)),
|
||||
decorateReply: false
|
||||
root: fileURLToPath(new URL('../views/pages', import.meta.url)),
|
||||
decorateReply: false,
|
||||
});
|
||||
|
||||
app.register(fastifyStatic, {
|
||||
root: fileURLToPath(new URL("../views/assets", import.meta.url)),
|
||||
prefix: "/assets/",
|
||||
decorateReply: false
|
||||
root: fileURLToPath(new URL('../views/assets', import.meta.url)),
|
||||
prefix: '/assets/',
|
||||
decorateReply: false,
|
||||
});
|
||||
|
||||
app.register(fastifyStatic, {
|
||||
root: fileURLToPath(new URL("../views/archive", import.meta.url)),
|
||||
prefix: "/arcade/",
|
||||
decorateReply: false
|
||||
root: fileURLToPath(new URL('../views/archive', import.meta.url)),
|
||||
prefix: '/arcade/',
|
||||
decorateReply: false,
|
||||
});
|
||||
|
||||
app.register(fastifyStatic, {
|
||||
root: fileURLToPath(new URL(
|
||||
// Use the pre-compiled, minified scripts instead, if enabled in config.
|
||||
config.minifyScripts ? "../views/dist/assets/js" : "../views/assets/js",
|
||||
root: fileURLToPath(
|
||||
new URL(
|
||||
// Use the pre-compiled, minified scripts instead, if enabled in config.
|
||||
config.minifyScripts ? '../views/dist/assets/js' : '../views/assets/js',
|
||||
import.meta.url
|
||||
)),
|
||||
prefix: "/assets/js/",
|
||||
decorateReply: false
|
||||
)
|
||||
),
|
||||
prefix: '/assets/js/',
|
||||
decorateReply: false,
|
||||
});
|
||||
|
||||
app.register(fastifyStatic, {
|
||||
root: fileURLToPath(new URL(
|
||||
// Use the pre-compiled, minified stylesheets instead, if enabled in config.
|
||||
config.minifyScripts ? "../views/dist/assets/css" : "../views/assets/css",
|
||||
root: fileURLToPath(
|
||||
new URL(
|
||||
// Use the pre-compiled, minified stylesheets instead, if enabled in config.
|
||||
config.minifyScripts ? '../views/dist/assets/css' : '../views/assets/css',
|
||||
import.meta.url
|
||||
)),
|
||||
prefix: "/assets/css/",
|
||||
decorateReply: false
|
||||
)
|
||||
),
|
||||
prefix: '/assets/css/',
|
||||
decorateReply: false,
|
||||
});
|
||||
|
||||
// This combines scripts from the official UV repository with local UV scripts into
|
||||
// one directory path. Local versions of files override the official versions.
|
||||
app.register(fastifyStatic, {
|
||||
root: [
|
||||
fileURLToPath(new URL(
|
||||
// Use the pre-compiled, minified scripts instead, if enabled in config.
|
||||
config.minifyScripts ? "../views/dist/uv" : "../views/uv",
|
||||
fileURLToPath(
|
||||
new URL(
|
||||
// Use the pre-compiled, minified scripts instead, if enabled in config.
|
||||
config.minifyScripts ? '../views/dist/uv' : '../views/uv',
|
||||
import.meta.url
|
||||
)),
|
||||
uvPath
|
||||
)
|
||||
),
|
||||
uvPath,
|
||||
],
|
||||
prefix: "/uv/",
|
||||
decorateReply: false
|
||||
prefix: '/uv/',
|
||||
decorateReply: false,
|
||||
});
|
||||
|
||||
// Register proxy paths to the website.
|
||||
app.register(fastifyStatic, {
|
||||
root: epoxyPath,
|
||||
prefix: "/epoxy/",
|
||||
decorateReply: false
|
||||
prefix: '/epoxy/',
|
||||
decorateReply: false,
|
||||
});
|
||||
|
||||
app.register(fastifyStatic, {
|
||||
root: libcurlPath,
|
||||
prefix: "/libcurl/",
|
||||
decorateReply: false
|
||||
prefix: '/libcurl/',
|
||||
decorateReply: false,
|
||||
});
|
||||
|
||||
app.register(fastifyStatic, {
|
||||
root: bareModulePath,
|
||||
prefix: "/bareasmodule/",
|
||||
decorateReply: false
|
||||
prefix: '/bareasmodule/',
|
||||
decorateReply: false,
|
||||
});
|
||||
|
||||
app.register(fastifyStatic, {
|
||||
root: baremuxPath,
|
||||
prefix: "/baremux/",
|
||||
decorateReply: false
|
||||
prefix: '/baremux/',
|
||||
decorateReply: false,
|
||||
});
|
||||
|
||||
|
||||
// All website files are stored in the /views directory.
|
||||
// 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
|
||||
// back here. Which path converts to what is defined in routes.mjs.
|
||||
app.get("/:path", (req, reply) => {
|
||||
|
||||
// Testing for future features that need cookies to deliver alternate source files.
|
||||
if (req.raw.rawHeaders.includes("Cookie"))
|
||||
console.log(req.raw.rawHeaders[ req.raw.rawHeaders.indexOf("Cookie") + 1 ]);
|
||||
app.get('/:path', (req, reply) => {
|
||||
// Testing for future features that need cookies to deliver alternate source files.
|
||||
if (req.raw.rawHeaders.includes('Cookie'))
|
||||
console.log(req.raw.rawHeaders[req.raw.rawHeaders.indexOf('Cookie') + 1]);
|
||||
|
||||
const reqPath = req.params.path;
|
||||
|
||||
if (reqPath in externalPages) {
|
||||
let externalRoute = externalPages[reqPath];
|
||||
if (typeof externalRoute !== "string") externalRoute = externalRoute.default;
|
||||
if (typeof externalRoute !== 'string')
|
||||
externalRoute = externalRoute.default;
|
||||
return reply.redirect(externalRoute);
|
||||
}
|
||||
|
||||
// If a GET request is sent to /test-shutdown and a script-generated shutdown file
|
||||
// is present, gracefully shut the server down.
|
||||
if (reqPath === "test-shutdown" && existsSync(shutdown)) {
|
||||
console.log("Holy Unblocker is shutting down.");
|
||||
// If a GET request is sent to /test-shutdown and a script-generated shutdown file
|
||||
// is present, gracefully shut the server down.
|
||||
if (reqPath === 'test-shutdown' && existsSync(shutdown)) {
|
||||
console.log('Holy Unblocker is shutting down.');
|
||||
app.close();
|
||||
unlinkSync(shutdown);
|
||||
process.exitCode = 0;
|
||||
}
|
||||
|
||||
// Return the error page if the query is not found in routes.mjs.
|
||||
// Return the error page if the query is not found in routes.mjs.
|
||||
if (reqPath && !(reqPath in pages))
|
||||
return reply.code(404).type("text/html").send(preloaded404);
|
||||
return reply.code(404).type('text/html').send(preloaded404);
|
||||
|
||||
reply.type("text/html").send(
|
||||
reply.type('text/html').send(
|
||||
paintSource(
|
||||
loadTemplates(
|
||||
tryReadFile(
|
||||
path.join(
|
||||
__dirname,
|
||||
"views",
|
||||
// Set the index the as the default page.
|
||||
'views',
|
||||
// Set the index the as the default page.
|
||||
reqPath ? pages[reqPath] : pages.index
|
||||
)
|
||||
)
|
||||
|
@ -238,10 +243,10 @@ app.get("/:path", (req, reply) => {
|
|||
);
|
||||
});
|
||||
|
||||
app.get("/github/:redirect", (req, reply) => {
|
||||
app.get('/github/:redirect', (req, reply) => {
|
||||
if (req.params.redirect in externalPages.github)
|
||||
reply.redirect(externalPages.github[req.params.redirect]);
|
||||
else reply.code(404).type("text/html").send(preloaded404);
|
||||
else reply.code(404).type('text/html').send(preloaded404);
|
||||
});
|
||||
|
||||
/*
|
||||
|
@ -256,7 +261,7 @@ app.get("/assets/js/uv/uv.config.js", (req, reply) => {
|
|||
|
||||
// Set an error page for invalid paths outside the query string system.
|
||||
app.setNotFoundHandler((req, reply) => {
|
||||
reply.code(404).type("text/html").send(preloaded404);
|
||||
reply.code(404).type('text/html').send(preloaded404);
|
||||
});
|
||||
|
||||
app.listen({ port: serverUrl.port, host: serverUrl.hostname });
|
||||
|
|
|
@ -1,36 +1,25 @@
|
|||
import { tryReadFile } from "./randomization.mjs";
|
||||
import path from "path";
|
||||
import { tryReadFile } from './randomization.mjs';
|
||||
import path from 'path';
|
||||
export { loadTemplates as default };
|
||||
|
||||
const __dirname = path.resolve() + "/views/pages/misc/deobf";
|
||||
const __dirname = path.resolve() + '/views/pages/misc/deobf';
|
||||
|
||||
const header = tryReadFile(
|
||||
path.normalize(__dirname + "/header.html")
|
||||
),
|
||||
footer = tryReadFile(
|
||||
path.normalize(__dirname + "/footer.html")
|
||||
),
|
||||
documentation = tryReadFile(
|
||||
path.normalize(__dirname + "/docs.html")
|
||||
),
|
||||
faq = tryReadFile(
|
||||
path.normalize(__dirname + "/faq.html")
|
||||
),
|
||||
terms = tryReadFile(
|
||||
path.normalize(__dirname + "/tos.html")
|
||||
),
|
||||
settings = tryReadFile(
|
||||
path.normalize(__dirname + "/settings.html")
|
||||
),
|
||||
const header = tryReadFile(path.normalize(__dirname + '/header.html')),
|
||||
footer = tryReadFile(path.normalize(__dirname + '/footer.html')),
|
||||
documentation = tryReadFile(path.normalize(__dirname + '/docs.html')),
|
||||
faq = tryReadFile(path.normalize(__dirname + '/faq.html')),
|
||||
terms = tryReadFile(path.normalize(__dirname + '/tos.html')),
|
||||
settings = tryReadFile(path.normalize(__dirname + '/settings.html')),
|
||||
loadTemplates = (str) =>
|
||||
str.replace("<!--HEADER-->", header)
|
||||
.replace("<!--FOOTER-->", footer)
|
||||
str
|
||||
.replace('<!--HEADER-->', header)
|
||||
.replace('<!--FOOTER-->', footer)
|
||||
|
||||
// Used only on docs.html
|
||||
.replace("<!--DOCS-->", documentation)
|
||||
.replace('<!--DOCS-->', documentation)
|
||||
// Used only on faq.html
|
||||
.replace("<!--FAQ-->", faq)
|
||||
.replace('<!--FAQ-->', faq)
|
||||
// Used only on terms.html
|
||||
.replace("<!--TOS-->", terms)
|
||||
.replace('<!--TOS-->', terms)
|
||||
// Used only on header.html
|
||||
.replace("<!--SETTINGS-->", settings);
|
||||
.replace('<!--SETTINGS-->', settings);
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
/* HU CSS
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
@import url("https://fonts.googleapis.com/css?family=Lato:400,700,400italic");
|
||||
@import url("https://fonts.googleapis.com/css?family=Montserrat+Alternates");
|
||||
@import url("https://fonts.googleapis.com/css?family=Titillium+Web:400,600,700");
|
||||
@import url('https://fonts.googleapis.com/css?family=Lato:400,700,400italic');
|
||||
@import url('https://fonts.googleapis.com/css?family=Montserrat+Alternates');
|
||||
@import url('https://fonts.googleapis.com/css?family=Titillium+Web:400,600,700');
|
||||
@import url('https://fonts.googleapis.com/css2?family=Figtree:ital,wght@0,300..900;1,300..900&display=swap');
|
||||
@import url('https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,200..900;1,200..900&display=swap');
|
||||
@import url("https://unpkg.com/@fortawesome/fontawesome-free@5.15.4/css/all.min.css");
|
||||
@import url('https://unpkg.com/@fortawesome/fontawesome-free@5.15.4/css/all.min.css');
|
||||
|
||||
/*
|
||||
Nord Theme (https://nordtheme.com)
|
||||
|
@ -73,14 +73,13 @@ see https://raw.githubusercontent.com/arcticicestudio/nord-docs/develop/assets/i
|
|||
--dark: #303030;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------
|
||||
/* HU Page Layout / General Styling
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
html {
|
||||
color: white;
|
||||
font-family: "Figtree", sans-serif;
|
||||
font-family: 'Figtree', sans-serif;
|
||||
font-weight: 300;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
@ -114,7 +113,7 @@ h3,
|
|||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: "Figtree", sans-serif;
|
||||
font-family: 'Figtree', sans-serif;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
|
@ -159,11 +158,11 @@ details[open] summary {
|
|||
}
|
||||
|
||||
.font2 {
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
font-family: 'Titillium Web', sans-serif;
|
||||
}
|
||||
|
||||
.font3 {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-family: 'Lato', sans-serif;
|
||||
}
|
||||
|
||||
.notbold {
|
||||
|
@ -240,9 +239,10 @@ details[open] summary {
|
|||
/* To change the top padding on the footer, change the 3 vw values here to the same thing. */
|
||||
|
||||
#footer {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-family: 'Lato', sans-serif;
|
||||
padding-top: 15vw;
|
||||
background: url("/assets/img/waves.svg"), linear-gradient(to bottom, transparent 0 15vw, #1d2029 15vw 100%);
|
||||
background: url('/assets/img/waves.svg'),
|
||||
linear-gradient(to bottom, transparent 0 15vw, #1d2029 15vw 100%);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100vw auto;
|
||||
position: relative;
|
||||
|
@ -258,12 +258,12 @@ details[open] summary {
|
|||
color: white;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------
|
||||
/* Icons and Branding
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
.brand-logo-container, .new {
|
||||
.brand-logo-container,
|
||||
.new {
|
||||
display: flex;
|
||||
align-items: center; /* Align items vertically */
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ details[open] summary {
|
|||
line-height: 30px;
|
||||
white-space: nowrap;
|
||||
margin-right: 20px; /* Adjust margin as needed */
|
||||
font-family: "Figtree", sans-serif;
|
||||
font-family: 'Figtree', sans-serif;
|
||||
font-weight: 900;
|
||||
letter-spacing: 1px;
|
||||
text-decoration: none;
|
||||
|
@ -304,7 +304,7 @@ details[open] summary {
|
|||
}
|
||||
|
||||
.new::after {
|
||||
content: "";
|
||||
content: '';
|
||||
padding: 22.75px 25px;
|
||||
margin-left: 8px;
|
||||
background-image: url('/assets/img/new.svg');
|
||||
|
@ -312,7 +312,6 @@ details[open] summary {
|
|||
font-size: 0;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------
|
||||
/* Navigation Bar and Menus (Header Contents)
|
||||
/* ----------------------------------------------- */
|
||||
|
@ -370,7 +369,7 @@ details[open] summary {
|
|||
cursor: auto;
|
||||
padding: 15px 25px;
|
||||
margin-top: 10px;
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
font-family: 'Titillium Web', sans-serif;
|
||||
}
|
||||
|
||||
/* "More" Navigation Menu */
|
||||
|
@ -409,7 +408,8 @@ details[open] summary {
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
.dropdown-parent:focus-within .dropdown-settings:not(:is(:has(.close-settings-btn:active))) {
|
||||
.dropdown-parent:focus-within
|
||||
.dropdown-settings:not(:is(:has(.close-settings-btn:active))) {
|
||||
display: flex; /* Flexbox to center content */
|
||||
}
|
||||
|
||||
|
@ -463,7 +463,10 @@ details[open] summary {
|
|||
|
||||
.close-settings-btn:hover {
|
||||
color: lightgray;
|
||||
transition: background-color 0.3s ease, color 0.3s ease, transform 0.3s ease;
|
||||
transition:
|
||||
background-color 0.3s ease,
|
||||
color 0.3s ease,
|
||||
transform 0.3s ease;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
|
@ -472,7 +475,8 @@ details[open] summary {
|
|||
gap: 40px; /* Space between left and right columns */
|
||||
}
|
||||
|
||||
.csel-container-left, .settings-right-column {
|
||||
.csel-container-left,
|
||||
.settings-right-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px; /* Space between items within columns */
|
||||
|
@ -514,7 +518,7 @@ details[open] summary {
|
|||
flex: 1; /* Take up available space */
|
||||
}
|
||||
|
||||
.radio-group input[type="radio"] {
|
||||
.radio-group input[type='radio'] {
|
||||
accent-color: #88c0d0;
|
||||
cursor: pointer;
|
||||
width: 20px; /* Adjust size for better appearance */
|
||||
|
@ -547,7 +551,7 @@ details[open] summary {
|
|||
|
||||
.switch::after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
content: '';
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
left: 3px;
|
||||
|
@ -580,7 +584,9 @@ select:hover {
|
|||
background-color: #4c566a;
|
||||
}
|
||||
|
||||
.default-badge, .bare-badge, .beta-badge {
|
||||
.default-badge,
|
||||
.bare-badge,
|
||||
.beta-badge {
|
||||
display: inline-block;
|
||||
padding: 2px 5px;
|
||||
border-radius: 5px;
|
||||
|
@ -609,7 +615,7 @@ select:hover {
|
|||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.cloakform input[type="text"] {
|
||||
.cloakform input[type='text'] {
|
||||
flex: 1;
|
||||
background-color: #3b4252;
|
||||
border: 1px solid #4c566a;
|
||||
|
@ -619,7 +625,7 @@ select:hover {
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cloakform input[type="button"] {
|
||||
.cloakform input[type='button'] {
|
||||
background-color: #5e81ac;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
|
@ -628,11 +634,11 @@ select:hover {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cloakform input[type="button"]:hover {
|
||||
.cloakform input[type='button']:hover {
|
||||
background-color: #81a1c1;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
input[type='text'] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
background-color: #3b4252;
|
||||
|
@ -649,7 +655,7 @@ input[type="text"] {
|
|||
gap: 15px;
|
||||
}
|
||||
|
||||
#csel input:not([type=checkbox]),
|
||||
#csel input:not([type='checkbox']),
|
||||
#csel select {
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
|
@ -659,20 +665,26 @@ input[type="text"] {
|
|||
margin: 5px 0;
|
||||
background-color: var(--nord1);
|
||||
border: 1px solid var(--nord9);
|
||||
transition: background-color 0.3s ease, color 0.3s ease, transform 0.3s ease;
|
||||
transition:
|
||||
background-color 0.3s ease,
|
||||
color 0.3s ease,
|
||||
transform 0.3s ease;
|
||||
}
|
||||
|
||||
#csel input[type=text]:focus {
|
||||
#csel input[type='text']:focus {
|
||||
box-shadow: inset 0 0 5px 0 var(--nord3);
|
||||
transition: box-shadow 0.15s ease-out;
|
||||
}
|
||||
|
||||
#csel input:is([type=submit], [type=button]):hover {
|
||||
transition: background-color 0.3s ease, color 0.3s ease, transform 0.3s ease;
|
||||
#csel input:is([type='submit'], [type='button']):hover {
|
||||
transition:
|
||||
background-color 0.3s ease,
|
||||
color 0.3s ease,
|
||||
transform 0.3s ease;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
#csel input:is([type=submit], [type=button]):active {
|
||||
#csel input:is([type='submit'], [type='button']):active {
|
||||
background-color: #78b0c0;
|
||||
}
|
||||
|
||||
|
@ -695,7 +707,8 @@ input[type="text"] {
|
|||
gap: 10px;
|
||||
}
|
||||
|
||||
#hideads, #useonion {
|
||||
#hideads,
|
||||
#useonion {
|
||||
cursor: pointer;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
@ -771,7 +784,6 @@ input[type="text"] {
|
|||
vertical-align: top;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------
|
||||
/* Welcome Screen Content (i.e., Big Bold Words)
|
||||
/* ----------------------------------------------- */
|
||||
|
@ -822,7 +834,12 @@ input[type="text"] {
|
|||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
background-color: var(--nord0);
|
||||
background-image: url("/assets/img/noise.png"), linear-gradient(145deg, rgba(34,38,47,0.9) 0%, rgba(34,38,47,0.9) 100%);
|
||||
background-image: url('/assets/img/noise.png'),
|
||||
linear-gradient(
|
||||
145deg,
|
||||
rgba(34, 38, 47, 0.9) 0%,
|
||||
rgba(34, 38, 47, 0.9) 100%
|
||||
);
|
||||
background-blend-mode: overlay;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
@ -857,7 +874,9 @@ input[type="text"] {
|
|||
background-color: var(--nord3);
|
||||
}
|
||||
|
||||
.no-select, .comment, .mac-content br {
|
||||
.no-select,
|
||||
.comment,
|
||||
.mac-content br {
|
||||
user-select: none; /* Prevent text selection */
|
||||
-webkit-user-select: none; /* For Safari */
|
||||
-moz-user-select: none; /* For Firefox */
|
||||
|
@ -866,7 +885,7 @@ input[type="text"] {
|
|||
|
||||
.mac-content {
|
||||
color: var(--nord4);
|
||||
font-family: "Source Code Pro", monospace;
|
||||
font-family: 'Source Code Pro', monospace;
|
||||
font-optical-sizing: auto;
|
||||
padding: 40px 0 0 80px;
|
||||
flex: 1;
|
||||
|
@ -882,12 +901,12 @@ input[type="text"] {
|
|||
}
|
||||
|
||||
.cmd::before {
|
||||
content: "$ ";
|
||||
content: '$ ';
|
||||
color: var(--nord4);
|
||||
}
|
||||
|
||||
.cmd::after {
|
||||
content: "\a";
|
||||
content: '\a';
|
||||
}
|
||||
|
||||
.url {
|
||||
|
@ -895,11 +914,11 @@ input[type="text"] {
|
|||
}
|
||||
|
||||
.comment {
|
||||
color: #616E88;
|
||||
color: #616e88;
|
||||
}
|
||||
|
||||
.comment::before {
|
||||
content: "# ";
|
||||
content: '# ';
|
||||
}
|
||||
|
||||
.homebutton {
|
||||
|
@ -924,7 +943,9 @@ input[type="text"] {
|
|||
|
||||
/* NOTE: Currently unused. */
|
||||
.hovermessage:hover {
|
||||
transition: color 0.3s ease-in, font-size 0s linear 0.3s;
|
||||
transition:
|
||||
color 0.3s ease-in,
|
||||
font-size 0s linear 0.3s;
|
||||
}
|
||||
|
||||
/* NOTE: Currently unused. */
|
||||
|
@ -937,12 +958,14 @@ input[type="text"] {
|
|||
/* NOTE: Currently unused. */
|
||||
.hovermessage:hover::before {
|
||||
font-size: 16px;
|
||||
transition: font-size 0s linear 0.3s, color 0.3s ease-in 0.3s;
|
||||
transition:
|
||||
font-size 0s linear 0.3s,
|
||||
color 0.3s ease-in 0.3s;
|
||||
}
|
||||
|
||||
/* NOTE: Currently unused. */
|
||||
.buttonlink {
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
font-family: 'Titillium Web', sans-serif;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
|
@ -1002,8 +1025,7 @@ input[type="text"] {
|
|||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
iner
|
||||
.splashstrokeheader {
|
||||
iner .splashstrokeheader {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
font-size: 36px;
|
||||
|
@ -1098,20 +1120,28 @@ iner
|
|||
}
|
||||
|
||||
.box-hero::after {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url("/assets/img/noise.png") repeat, rgba(255, 255, 255, 0.03);
|
||||
background:
|
||||
url('/assets/img/noise.png') repeat,
|
||||
rgba(255, 255, 255, 0.03);
|
||||
opacity: var(--noise-opacity, 0.02);
|
||||
pointer-events: none;
|
||||
-webkit-mask-image: radial-gradient(circle, white 30%, transparent 50%);
|
||||
-webkit-mask-size: 800px 800px;
|
||||
-webkit-mask-position: calc(var(--mouse-x) - 400px) calc(var(--mouse-y) - 400px);
|
||||
-webkit-mask-position: calc(var(--mouse-x) - 400px)
|
||||
calc(var(--mouse-y) - 400px);
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-image: radial-gradient(closest-side, rgba(37, 35, 35, 0.377) 30%, rgba(255, 255, 255, 0.048) 70%, transparent 90%);
|
||||
mask-image: radial-gradient(
|
||||
closest-side,
|
||||
rgba(37, 35, 35, 0.377) 30%,
|
||||
rgba(255, 255, 255, 0.048) 70%,
|
||||
transparent 90%
|
||||
);
|
||||
mask-size: 800px 800px;
|
||||
mask-position: calc(var(--mouse-x) - 400px) calc(var(--mouse-y) - 400px);
|
||||
mask-repeat: no-repeat;
|
||||
|
@ -1205,20 +1235,28 @@ iner
|
|||
}
|
||||
|
||||
.box-card::after {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url("/assets/img/noise.png") repeat, rgba(46, 52, 64, 0.03);
|
||||
background:
|
||||
url('/assets/img/noise.png') repeat,
|
||||
rgba(46, 52, 64, 0.03);
|
||||
opacity: var(--noise-opacity, 0.02);
|
||||
pointer-events: none;
|
||||
-webkit-mask-image: radial-gradient(circle, white 30%, transparent 50%);
|
||||
-webkit-mask-size: 800px 800px;
|
||||
-webkit-mask-position: calc(var(--mouse-x) - 400px) calc(var(--mouse-y) - 400px);
|
||||
-webkit-mask-position: calc(var(--mouse-x) - 400px)
|
||||
calc(var(--mouse-y) - 400px);
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-image: radial-gradient(closest-side, rgba(37, 35, 35, 0.377) 30%, rgba(255, 255, 255, 0.048) 70%, transparent 90%);
|
||||
mask-image: radial-gradient(
|
||||
closest-side,
|
||||
rgba(37, 35, 35, 0.377) 30%,
|
||||
rgba(255, 255, 255, 0.048) 70%,
|
||||
transparent 90%
|
||||
);
|
||||
mask-size: 800px 800px;
|
||||
mask-position: calc(var(--mouse-x) - 400px) calc(var(--mouse-y) - 400px);
|
||||
mask-repeat: no-repeat;
|
||||
|
@ -1236,7 +1274,7 @@ iner
|
|||
width: calc(95% - min(30%, 180px) - 32px);
|
||||
margin-right: 20px;
|
||||
box-sizing: border-box;
|
||||
overflow-wrap: break-word
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.image-container {
|
||||
|
@ -1391,10 +1429,6 @@ iner
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.box-large {
|
||||
width: 80vw;
|
||||
margin: 20px auto;
|
||||
|
@ -1406,7 +1440,7 @@ iner
|
|||
|
||||
.box-error {
|
||||
margin: 40vh 0;
|
||||
font-family: "Lato", sans-serif;
|
||||
font-family: 'Lato', sans-serif;
|
||||
}
|
||||
|
||||
.box-error h1 {
|
||||
|
@ -1437,13 +1471,12 @@ iner
|
|||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------
|
||||
/* Documentation and FAQ Pages
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
#documentation {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-family: 'Lato', sans-serif;
|
||||
}
|
||||
|
||||
#documentation code {
|
||||
|
@ -1498,8 +1531,8 @@ iner
|
|||
}
|
||||
|
||||
.ad::before {
|
||||
content: "Advertisement";
|
||||
font-family: "Titillium Web", sans-serif;
|
||||
content: 'Advertisement';
|
||||
font-family: 'Titillium Web', sans-serif;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
left: 50%;
|
||||
|
@ -1527,21 +1560,21 @@ iner
|
|||
border-radius: 5px;
|
||||
padding: 10px 12px;
|
||||
color: white;
|
||||
font-family: "Montserrat Alternates", sans-serif;
|
||||
font-family: 'Montserrat Alternates', sans-serif;
|
||||
font-size: 20px;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
.pr-form input[type=text] {
|
||||
.pr-form input[type='text'] {
|
||||
max-width: 700px;
|
||||
width: calc(100% - 44px);
|
||||
}
|
||||
|
||||
.pr-form input[type=text]:focus {
|
||||
.pr-form input[type='text']:focus {
|
||||
animation: glowshadow 2s linear infinite;
|
||||
}
|
||||
|
||||
.pr-form input[type=text]::placeholder {
|
||||
.pr-form input[type='text']::placeholder {
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
|
@ -1604,7 +1637,6 @@ iner
|
|||
background-color: #111;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------
|
||||
/* HU Games Directory
|
||||
/* ----------------------------------------------- */
|
||||
|
@ -1616,7 +1648,7 @@ iner
|
|||
/* Games list for non-flash games */
|
||||
|
||||
.glist {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-family: 'Lato', sans-serif;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
|
@ -1660,7 +1692,7 @@ iner
|
|||
/* Flash Games Search Bar */
|
||||
|
||||
#fsearchbar {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 16px;
|
||||
background-color: var(--nord0);
|
||||
outline: none;
|
||||
|
@ -1678,7 +1710,7 @@ iner
|
|||
/* Flash Games List */
|
||||
|
||||
.flist {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-family: 'Lato', sans-serif;
|
||||
background-color: var(--nord0);
|
||||
width: 400px;
|
||||
height: calc(100vh - 92px);
|
||||
|
@ -1713,7 +1745,6 @@ iner
|
|||
margin: 40px 0 32px;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------
|
||||
/* CSS Animations
|
||||
/* ----------------------------------------------- */
|
||||
|
@ -1753,7 +1784,10 @@ iner
|
|||
}
|
||||
|
||||
.pulse:hover {
|
||||
transition: background-color 0.3s ease, color 0.3s ease, transform 0.3s ease;
|
||||
transition:
|
||||
background-color 0.3s ease,
|
||||
color 0.3s ease,
|
||||
transform 0.3s ease;
|
||||
transform: scale(1.05);
|
||||
-webkit-font-smoothing: subpixel-antialiased;
|
||||
}
|
||||
|
@ -1785,7 +1819,7 @@ iner
|
|||
}
|
||||
|
||||
.glowbutton::after {
|
||||
content: "";
|
||||
content: '';
|
||||
border-radius: inherit;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
|
@ -1806,10 +1840,11 @@ iner
|
|||
.glowbutton:active::after {
|
||||
background: linear-gradient(90deg, var(--nord7), var(--nord8), var(--nord7));
|
||||
background-size: 100px auto;
|
||||
animation: glowshadow 2s linear infinite, glowbg 2s linear infinite;
|
||||
animation:
|
||||
glowshadow 2s linear infinite,
|
||||
glowbg 2s linear infinite;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------
|
||||
/* Mobile Support
|
||||
/* ----------------------------------------------- */
|
||||
|
@ -1842,9 +1877,11 @@ iner
|
|||
|
||||
.mnavebutton::before,
|
||||
.mnavebutton::after {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
transition: transform 0.2s ease-out, top 0.2s ease-out;
|
||||
transition:
|
||||
transform 0.2s ease-out,
|
||||
top 0.2s ease-out;
|
||||
}
|
||||
|
||||
.mnavebutton {
|
||||
|
@ -1882,7 +1919,6 @@ iner
|
|||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------
|
||||
/* CSS Media Queries (largely for mobile support)
|
||||
/* ----------------------------------------------- */
|
||||
|
@ -1953,7 +1989,7 @@ iner
|
|||
#banner {
|
||||
display: none;
|
||||
}
|
||||
/*
|
||||
/*
|
||||
.mnave {
|
||||
display: none !important;
|
||||
}
|
||||
|
@ -2051,7 +2087,6 @@ iner
|
|||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
|
||||
#header {
|
||||
padding: 15px 30px;
|
||||
}
|
||||
|
@ -2065,7 +2100,8 @@ iner
|
|||
font-size: 14px;
|
||||
}
|
||||
|
||||
.navbar, .navbar-1 {
|
||||
.navbar,
|
||||
.navbar-1 {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
|
@ -2116,13 +2152,15 @@ iner
|
|||
margin-top: 7px;
|
||||
}
|
||||
|
||||
#csel input:not([type=checkbox]), #csel select {
|
||||
#csel input:not([type='checkbox']),
|
||||
#csel select {
|
||||
padding: 7px 8px;
|
||||
margin: 3.5px 1.75px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
#csel .cseltitle ~ input:not([type=checkbox]), #csel select {
|
||||
#csel .cseltitle ~ input:not([type='checkbox']),
|
||||
#csel select {
|
||||
width: calc(100% - 94.5px);
|
||||
}
|
||||
|
||||
|
@ -2134,7 +2172,8 @@ iner
|
|||
width: 60vw;
|
||||
}
|
||||
|
||||
.hero, .image-container {
|
||||
.hero,
|
||||
.image-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
//Built from: https://github.com/motortruck1221/bare-as-module3 (commit: 36759f801e0009027878edecff156408b06404c6)
|
||||
(function (global, factory) {
|
||||
typeof exports === "object" && typeof module !== "undefined"
|
||||
typeof exports === 'object' && typeof module !== 'undefined'
|
||||
? factory(exports)
|
||||
: typeof define === "function" && define.amd
|
||||
? define(["exports"], factory)
|
||||
: typeof define === 'function' && define.amd
|
||||
? define(['exports'], factory)
|
||||
: ((global =
|
||||
typeof globalThis !== "undefined" ? globalThis : global || self),
|
||||
typeof globalThis !== 'undefined' ? globalThis : global || self),
|
||||
factory((global.BareMod = {})));
|
||||
})(this, function (exports) {
|
||||
"use strict";
|
||||
})(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
|
||||
|
@ -17,12 +17,12 @@
|
|||
const WebSocket = globalThis.WebSocket;
|
||||
const WebSocketFields = {
|
||||
prototype: {
|
||||
send: WebSocket.prototype.send
|
||||
send: WebSocket.prototype.send,
|
||||
},
|
||||
CLOSED: WebSocket.CLOSED,
|
||||
CLOSING: WebSocket.CLOSING,
|
||||
CONNECTING: WebSocket.CONNECTING,
|
||||
OPEN: WebSocket.OPEN
|
||||
OPEN: WebSocket.OPEN,
|
||||
};
|
||||
|
||||
class BareError extends Error {
|
||||
|
@ -259,7 +259,7 @@
|
|||
* @returns MD5 string
|
||||
*/
|
||||
function binl2rstr(input) {
|
||||
let output = "";
|
||||
let output = '';
|
||||
const length32 = input.length * 32;
|
||||
for (let i = 0; i < length32; i += 8) {
|
||||
output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff);
|
||||
|
@ -322,8 +322,8 @@
|
|||
* @returns Hex encoded string
|
||||
*/
|
||||
function rstr2hex(input) {
|
||||
const hexTab = "0123456789abcdef";
|
||||
let output = "";
|
||||
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);
|
||||
|
@ -409,10 +409,10 @@
|
|||
*/
|
||||
function splitHeaders(headers) {
|
||||
const output = new Headers(headers);
|
||||
if (headers.has("x-bare-headers")) {
|
||||
const value = headers.get("x-bare-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");
|
||||
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);
|
||||
|
@ -430,25 +430,25 @@
|
|||
*/
|
||||
function joinHeaders(headers) {
|
||||
const output = new Headers(headers);
|
||||
const prefix = "x-bare-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(";")) {
|
||||
if (!value.startsWith(';')) {
|
||||
throw new BareError(400, {
|
||||
code: "INVALID_BARE_HEADER",
|
||||
code: 'INVALID_BARE_HEADER',
|
||||
id: `request.headers.${header}`,
|
||||
message: `Value didn't begin with semi-colon.`
|
||||
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(""));
|
||||
output.set(prefix, join.join(''));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
@ -463,10 +463,10 @@
|
|||
super(3, server);
|
||||
this.ws = new URL(this.base);
|
||||
this.http = new URL(this.base);
|
||||
if (this.ws.protocol === "https:") {
|
||||
this.ws.protocol = "wss:";
|
||||
if (this.ws.protocol === 'https:') {
|
||||
this.ws.protocol = 'wss:';
|
||||
} else {
|
||||
this.ws.protocol = "ws:";
|
||||
this.ws.protocol = 'ws:';
|
||||
}
|
||||
}
|
||||
ready = true;
|
||||
|
@ -485,8 +485,8 @@
|
|||
) {
|
||||
const ws = new WebSocket(this.ws);
|
||||
const cleanup = () => {
|
||||
ws.removeEventListener("close", closeListener);
|
||||
ws.removeEventListener("message", messageListener);
|
||||
ws.removeEventListener('close', closeListener);
|
||||
ws.removeEventListener('message', messageListener);
|
||||
};
|
||||
const closeListener = () => {
|
||||
cleanup();
|
||||
|
@ -494,39 +494,39 @@
|
|||
const messageListener = (event) => {
|
||||
cleanup();
|
||||
// ws.binaryType is irrelevant when sending text
|
||||
if (typeof event.data !== "string")
|
||||
if (typeof event.data !== 'string')
|
||||
throw new TypeError(
|
||||
"the first websocket message was not a text frame"
|
||||
'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");
|
||||
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) => {
|
||||
ws.addEventListener('message', (ev) => {
|
||||
onmessage(ev.data);
|
||||
});
|
||||
};
|
||||
ws.addEventListener("close", closeListener);
|
||||
ws.addEventListener("message", messageListener);
|
||||
ws.addEventListener('close', closeListener);
|
||||
ws.addEventListener('message', messageListener);
|
||||
// CONNECTED TO THE BARE SERVER, NOT THE REMOTE
|
||||
ws.addEventListener(
|
||||
"open",
|
||||
'open',
|
||||
(event) => {
|
||||
// getRequestHeaders().then((headers:any) =>
|
||||
WebSocketFields.prototype.send.call(
|
||||
ws,
|
||||
JSON.stringify({
|
||||
type: "connect",
|
||||
type: 'connect',
|
||||
remote: url.toString(),
|
||||
protocols,
|
||||
headers: requestHeaders,
|
||||
forwardHeaders: []
|
||||
forwardHeaders: [],
|
||||
})
|
||||
);
|
||||
// );
|
||||
|
@ -538,16 +538,16 @@
|
|||
}
|
||||
async request(remote, method, body, headers, signal) {
|
||||
const options = {
|
||||
credentials: "omit",
|
||||
credentials: 'omit',
|
||||
method: method,
|
||||
signal
|
||||
signal,
|
||||
};
|
||||
if (body !== undefined) {
|
||||
options.body = body;
|
||||
}
|
||||
options.headers = this.createBareHeaders(remote, headers);
|
||||
const response = await fetch(
|
||||
this.http + "?cache=" + md5(remote.toString()),
|
||||
this.http + '?cache=' + md5(remote.toString()),
|
||||
options
|
||||
);
|
||||
const readResponse = await this.readBareResponse(response);
|
||||
|
@ -566,7 +566,7 @@
|
|||
body: response.body,
|
||||
headers: readResponse.headers,
|
||||
status: readResponse.status,
|
||||
statusText: readResponse.statusText
|
||||
statusText: readResponse.statusText,
|
||||
};
|
||||
}
|
||||
async readBareResponse(response) {
|
||||
|
@ -575,11 +575,11 @@
|
|||
}
|
||||
const responseHeaders = joinHeaders(response.headers);
|
||||
const result = {};
|
||||
const xBareStatus = responseHeaders.get("x-bare-status");
|
||||
const xBareStatus = responseHeaders.get('x-bare-status');
|
||||
if (xBareStatus !== null) result.status = parseInt(xBareStatus);
|
||||
const xBareStatusText = responseHeaders.get("x-bare-status-text");
|
||||
const xBareStatusText = responseHeaders.get('x-bare-status-text');
|
||||
if (xBareStatusText !== null) result.statusText = xBareStatusText;
|
||||
const xBareHeaders = responseHeaders.get("x-bare-headers");
|
||||
const xBareHeaders = responseHeaders.get('x-bare-headers');
|
||||
if (xBareHeaders !== null) result.headers = JSON.parse(xBareHeaders);
|
||||
return result;
|
||||
}
|
||||
|
@ -591,16 +591,16 @@
|
|||
passStatus = []
|
||||
) {
|
||||
const headers = new Headers();
|
||||
headers.set("x-bare-url", remote.toString());
|
||||
headers.set("x-bare-headers", JSON.stringify(bareHeaders));
|
||||
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);
|
||||
headers.append('x-bare-forward-headers', header);
|
||||
}
|
||||
for (const header of passHeaders) {
|
||||
headers.append("x-bare-pass-headers", header);
|
||||
headers.append('x-bare-pass-headers', header);
|
||||
}
|
||||
for (const status of passStatus) {
|
||||
headers.append("x-bare-pass-status", status.toString());
|
||||
headers.append('x-bare-pass-status', status.toString());
|
||||
}
|
||||
splitHeaders(headers);
|
||||
return headers;
|
||||
|
@ -608,6 +608,5 @@
|
|||
}
|
||||
|
||||
exports.BareClient = ClientV3;
|
||||
});
|
||||
//# sourceMappingURL=bare.cjs.map
|
||||
|
||||
});
|
||||
//# sourceMappingURL=bare.cjs.map
|
||||
|
|
|
@ -7,35 +7,31 @@
|
|||
// Encase everything in a new scope so that variables are not accidentally
|
||||
// attached to the global scope.
|
||||
(() => {
|
||||
|
||||
// Track the cursor position with respect to the top left of the card.
|
||||
// The "this" keyword gets the element that invoked the event listener.
|
||||
const handleMouseMove = element => {
|
||||
element.addEventListener("mousemove", e => {
|
||||
// Track the cursor position with respect to the top left of the card.
|
||||
// The "this" keyword gets the element that invoked the event listener.
|
||||
const handleMouseMove = (element) => {
|
||||
element.addEventListener('mousemove', (e) => {
|
||||
const rect = element.getBoundingClientRect();
|
||||
const x = e.clientX - rect.left;
|
||||
const y = e.clientY - rect.top;
|
||||
|
||||
element.style.setProperty("--mouse-x", `${x}px`);
|
||||
element.style.setProperty("--mouse-y", `${y}px`);
|
||||
element.style.setProperty('--mouse-x', `${x}px`);
|
||||
element.style.setProperty('--mouse-y', `${y}px`);
|
||||
});
|
||||
},
|
||||
|
||||
// Reset the cursor tracking variables when the cursor leaves the card.
|
||||
handleMouseLeave = element => {
|
||||
element.addEventListener("mouseleave", () => {
|
||||
element.style.setProperty("--mouse-x", `50%`);
|
||||
element.style.setProperty("--mouse-y", `50%`);
|
||||
// Reset the cursor tracking variables when the cursor leaves the card.
|
||||
handleMouseLeave = (element) => {
|
||||
element.addEventListener('mouseleave', () => {
|
||||
element.style.setProperty('--mouse-x', `50%`);
|
||||
element.style.setProperty('--mouse-y', `50%`);
|
||||
});
|
||||
},
|
||||
// Get the box card elements and add the event listeners to them.
|
||||
shimmerEffects = document.querySelectorAll('.box-card, .box-hero');
|
||||
|
||||
// Get the box card elements and add the event listeners to them.
|
||||
shimmerEffects = document.querySelectorAll(".box-card, .box-hero");
|
||||
|
||||
// Attach CSS variables, mouse-x and mouse-y, to elements that will be
|
||||
// given shimmer effects, by adding or modifying the style attribute.
|
||||
// CSS calculates and renders the actual shimmer effect from there.
|
||||
shimmerEffects.forEach(handleMouseMove);
|
||||
shimmerEffects.forEach(handleMouseLeave);
|
||||
|
||||
// Attach CSS variables, mouse-x and mouse-y, to elements that will be
|
||||
// given shimmer effects, by adding or modifying the style attribute.
|
||||
// CSS calculates and renders the actual shimmer effect from there.
|
||||
shimmerEffects.forEach(handleMouseMove);
|
||||
shimmerEffects.forEach(handleMouseLeave);
|
||||
})();
|
|
@ -4,69 +4,64 @@
|
|||
/* MAIN Holy Unblocker LTS Common Script
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
|
||||
// Encase everything in a new scope so that variables are not accidentally
|
||||
// attached to the global scope.
|
||||
(() => {
|
||||
|
||||
// Get the preferred apex domain name. Not exactly apex, as any
|
||||
// subdomain other than those listed will be ignored.
|
||||
const getDomain =
|
||||
() => location.host.replace(/^(?:www|edu|cooking|beta)\./, ""),
|
||||
|
||||
// This is used for stealth mode when visiting external sites.
|
||||
goFrame = url => {
|
||||
localStorage.setItem("huframesrc", url);
|
||||
location.href = "/s";
|
||||
// Get the preferred apex domain name. Not exactly apex, as any
|
||||
// subdomain other than those listed will be ignored.
|
||||
const getDomain = () =>
|
||||
location.host.replace(/^(?:www|edu|cooking|beta)\./, ''),
|
||||
// This is used for stealth mode when visiting external sites.
|
||||
goFrame = (url) => {
|
||||
localStorage.setItem('huframesrc', url);
|
||||
location.href = '/s';
|
||||
},
|
||||
|
||||
// Used to set functions for the goProx object at the bottom.
|
||||
// See the goProx object at the bottom for some usage examples
|
||||
// on the URL handlers, omnibox functions, and the uvUrl and
|
||||
// RammerheadEncode functions.
|
||||
urlHandler = parser => typeof parser === "function"
|
||||
// Return different functions based on whether a URL has already been set.
|
||||
// Should help avoid confusion when using or adding to the goProx object.
|
||||
? (url, mode) => {
|
||||
// Used to set functions for the goProx object at the bottom.
|
||||
// See the goProx object at the bottom for some usage examples
|
||||
// on the URL handlers, omnibox functions, and the uvUrl and
|
||||
// RammerheadEncode functions.
|
||||
urlHandler = (parser) =>
|
||||
typeof parser === 'function'
|
||||
? // Return different functions based on whether a URL has already been set.
|
||||
// Should help avoid confusion when using or adding to the goProx object.
|
||||
(url, mode) => {
|
||||
if (!url) return;
|
||||
url = parser(url);
|
||||
mode = `${mode}`.toLowerCase();
|
||||
if (mode === "stealth" || mode == 1) goFrame(url);
|
||||
else if (mode === "window" || mode == 0) location.href = url;
|
||||
if (mode === 'stealth' || mode == 1) goFrame(url);
|
||||
else if (mode === 'window' || mode == 0) location.href = url;
|
||||
else return url;
|
||||
}
|
||||
: mode => {
|
||||
: (mode) => {
|
||||
mode = `${mode}`.toLowerCase();
|
||||
if (mode === "stealth" || mode == 1) goFrame(parser);
|
||||
else if (mode === "window" || mode == 0) location.href = parser;
|
||||
if (mode === 'stealth' || mode == 1) goFrame(parser);
|
||||
else if (mode === 'window' || mode == 0) location.href = parser;
|
||||
else return parser;
|
||||
},
|
||||
|
||||
// An asynchronous version of the function above, just in case.
|
||||
asyncUrlHandler = parser => async (url, mode) => {
|
||||
// An asynchronous version of the function above, just in case.
|
||||
asyncUrlHandler = (parser) => async (url, mode) => {
|
||||
if (!url) return;
|
||||
if (typeof parser === "function") url = await parser(url);
|
||||
if (typeof parser === 'function') url = await parser(url);
|
||||
mode = `${mode}`.toLowerCase();
|
||||
if (mode === "stealth" || mode == 1) goFrame(url);
|
||||
else if (mode === "window" || mode == 0) location.href = url;
|
||||
if (mode === 'stealth' || mode == 1) goFrame(url);
|
||||
else if (mode === 'window' || mode == 0) location.href = url;
|
||||
else return url;
|
||||
};
|
||||
|
||||
/* COOKIE AUTH DEMO */
|
||||
|
||||
/* COOKIE AUTH DEMO */
|
||||
const setAuthCookie = (s, lax) => {
|
||||
document.cookie =
|
||||
s +
|
||||
`; expires=${Date.now() + 259200}; SameSite=${lax ? 'Lax' : 'None'}; domain=.${getDomain()}; path=/; Secure;`;
|
||||
};
|
||||
|
||||
const setAuthCookie = (s, lax) => {
|
||||
document.cookie = s + `; 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
|
||||
// bar at the top of a browser.
|
||||
const sx = "bing.com" + "/search?q=",
|
||||
|
||||
/*
|
||||
// Search engine is set to Bing. Intended to work just like the usual
|
||||
// bar at the top of a browser.
|
||||
const sx = 'bing.com' + '/search?q=',
|
||||
/*
|
||||
omnibox = url =>
|
||||
(url.indexOf("http")
|
||||
? "https://" + (url.indexOf(".") < 1 ? sx : "")
|
||||
|
@ -74,59 +69,59 @@ const sx = "bing.com" + "/search?q=",
|
|||
+ url;
|
||||
*/
|
||||
|
||||
// Another omnibox function. Unsure if the version above is needed.
|
||||
// Another omnibox function. Unsure if the version above is needed.
|
||||
search = (input, template = `https://${sx}%s`) => {
|
||||
try {
|
||||
// Return the input if it is already a valid URL.
|
||||
// eg: https://example.com, https://example.com/test?q=param
|
||||
return new URL(input) + "";
|
||||
// Return the input if it is already a valid URL.
|
||||
// eg: https://example.com, https://example.com/test?q=param
|
||||
return new URL(input) + '';
|
||||
} catch (e) {
|
||||
// Continue if it is invalid.
|
||||
// Continue if it is invalid.
|
||||
}
|
||||
|
||||
try {
|
||||
// Check if the input is valid when http:// is added to the start.
|
||||
// eg: example.com, https://example.com/test?q=param
|
||||
// Check if the input is valid when http:// is added to the start.
|
||||
// eg: example.com, https://example.com/test?q=param
|
||||
const url = new URL(`http://${input}`);
|
||||
// Return only if the hostname has a TLD or a subdomain.
|
||||
if (url.hostname.indexOf(".") != -1) return url + "";
|
||||
// Return only if the hostname has a TLD or a subdomain.
|
||||
if (url.hostname.indexOf('.') != -1) return url + '';
|
||||
} catch (e) {
|
||||
// Continue if it is invalid.
|
||||
// Continue if it is invalid.
|
||||
}
|
||||
|
||||
// Treat the input as a search query instead of a website.
|
||||
return template.replace("%s", encodeURIComponent(input));
|
||||
// Treat the input as a search query instead of a website.
|
||||
return template.replace('%s', encodeURIComponent(input));
|
||||
},
|
||||
|
||||
// Parse a URL to use with Ultraviolet.
|
||||
uvUrl = url => {
|
||||
// Parse a URL to use with Ultraviolet.
|
||||
uvUrl = (url) => {
|
||||
try {
|
||||
url = location.origin + __uv$config.prefix + __uv$config.encodeUrl(search(url));
|
||||
url =
|
||||
location.origin +
|
||||
__uv$config.prefix +
|
||||
__uv$config.encodeUrl(search(url));
|
||||
} catch (e) {
|
||||
// This is for cases where the Ultraviolet scripts have not been loaded.
|
||||
// This is for cases where the Ultraviolet scripts have not been loaded.
|
||||
url = search(url);
|
||||
}
|
||||
return url;
|
||||
};
|
||||
|
||||
/* RAMMERHEAD CONFIGURATION */
|
||||
|
||||
/* RAMMERHEAD CONFIGURATION */
|
||||
|
||||
// Parse a URL to use with Rammerhead. Only usable if the server is active.
|
||||
const RammerheadEncode = async baseUrl => {
|
||||
|
||||
// Hellhead
|
||||
// Parse a URL to use with Rammerhead. Only usable if the server is active.
|
||||
const RammerheadEncode = async (baseUrl) => {
|
||||
// Hellhead
|
||||
const mod = (n, m) => ((n % m) + m) % m,
|
||||
baseDictionary =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~-",
|
||||
shuffledIndicator = "_rhs",
|
||||
// Return a copy of the base dictionary with a randomized character order.
|
||||
// Will be used as a Caesar cipher for URL encoding.
|
||||
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~-',
|
||||
shuffledIndicator = '_rhs',
|
||||
// Return a copy of the base dictionary with a randomized character order.
|
||||
// Will be used as a Caesar cipher for URL encoding.
|
||||
generateDictionary = () => {
|
||||
let str = "";
|
||||
const split = baseDictionary.split("");
|
||||
let str = '';
|
||||
const split = baseDictionary.split('');
|
||||
while (split.length > 0) {
|
||||
// Using .splice automatically rounds down to the nearest whole number.
|
||||
// Using .splice automatically rounds down to the nearest whole number.
|
||||
str += split.splice(Math.random() * split.length, 1)[0];
|
||||
}
|
||||
return str;
|
||||
|
@ -138,73 +133,70 @@ const RammerheadEncode = async baseUrl => {
|
|||
}
|
||||
|
||||
shuffle(str) {
|
||||
// Do not reshuffle an already shuffled string.
|
||||
// Do not reshuffle an already shuffled string.
|
||||
if (!str.indexOf(shuffledIndicator)) return str;
|
||||
|
||||
let shuffledStr = "";
|
||||
let shuffledStr = '';
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const char = str[i], idx = baseDictionary.indexOf(char);
|
||||
const char = str[i],
|
||||
idx = baseDictionary.indexOf(char);
|
||||
|
||||
// For URL encoded characters and characters not included in the
|
||||
// dictionary, leave untouched. Otherwise, replace with a character
|
||||
// from the dictionary.
|
||||
if (char === "%" && str.length - i >= 3)
|
||||
// A % symbol denotes that the next 2 characters are URL encoded.
|
||||
// For URL encoded characters and characters not included in the
|
||||
// dictionary, leave untouched. Otherwise, replace with a character
|
||||
// from the dictionary.
|
||||
if (char === '%' && str.length - i >= 3)
|
||||
// A % symbol denotes that the next 2 characters are URL encoded.
|
||||
shuffledStr += char + str[++i] + str[++i];
|
||||
|
||||
// Do not modify unrecognized characters.
|
||||
// Do not modify unrecognized characters.
|
||||
else if (idx == -1) shuffledStr += char;
|
||||
|
||||
// Find the corresponding dictionary entry and use the character
|
||||
// that is i places to the right of it.
|
||||
else shuffledStr += this.dictionary[
|
||||
mod(idx + i, baseDictionary.length)
|
||||
];
|
||||
// Find the corresponding dictionary entry and use the character
|
||||
// that is i places to the right of it.
|
||||
else
|
||||
shuffledStr += this.dictionary[mod(idx + i, baseDictionary.length)];
|
||||
}
|
||||
// Add a prefix signifying that the string has been shuffled.
|
||||
// Add a prefix signifying that the string has been shuffled.
|
||||
return shuffledIndicator + shuffledStr;
|
||||
}
|
||||
|
||||
// Unshuffling is currently not done on the client side, and likely
|
||||
// won't ever be for this implementation. It is used by the server instead.
|
||||
// Unshuffling is currently not done on the client side, and likely
|
||||
// won't ever be for this implementation. It is used by the server instead.
|
||||
unshuffle(str) {
|
||||
// Do not unshuffle an already unshuffled string.
|
||||
// Do not unshuffle an already unshuffled string.
|
||||
if (str.indexOf(shuffledIndicator)) return str;
|
||||
|
||||
// Remove the prefix signifying that the string has been shuffled.
|
||||
// Remove the prefix signifying that the string has been shuffled.
|
||||
str = str.slice(shuffledIndicator.length);
|
||||
|
||||
let unshuffledStr = "";
|
||||
let unshuffledStr = '';
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const char = str[i], idx = this.dictionary.indexOf(char);
|
||||
const char = str[i],
|
||||
idx = this.dictionary.indexOf(char);
|
||||
|
||||
// Convert the dictionary entry characters back into their base
|
||||
// characters using the base dictionary. Again, leave URL encoded
|
||||
// characters and unrecognized symbols alone.
|
||||
if (char === "%" && str.length - i >= 3)
|
||||
// Convert the dictionary entry characters back into their base
|
||||
// characters using the base dictionary. Again, leave URL encoded
|
||||
// characters and unrecognized symbols alone.
|
||||
if (char === '%' && str.length - i >= 3)
|
||||
unshuffledStr += char + str[++i] + str[++i];
|
||||
|
||||
else if (idx == -1) unshuffledStr += char;
|
||||
|
||||
// Find the corresponding base character entry and use the character
|
||||
// that is i places to the left of it.
|
||||
else unshuffledStr += baseDictionary[
|
||||
mod(idx - i, baseDictionary.length)
|
||||
];
|
||||
// Find the corresponding base character entry and use the character
|
||||
// that is i places to the left of it.
|
||||
else
|
||||
unshuffledStr +=
|
||||
baseDictionary[mod(idx - i, baseDictionary.length)];
|
||||
}
|
||||
return unshuffledStr;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Request information that's beiing stored elsewhere on the server.
|
||||
// Executes the callback function if the server responds as intended.
|
||||
// Request information that's beiing stored elsewhere on the server.
|
||||
// Executes the callback function if the server responds as intended.
|
||||
const get = (url, callback, shush = false) => {
|
||||
let request = new XMLHttpRequest();
|
||||
request.open("GET", url, true);
|
||||
request.open('GET', url, true);
|
||||
request.send();
|
||||
|
||||
request.onerror = () => {
|
||||
if (!shush) console.log("Cannot communicate with the server");
|
||||
if (!shush) console.log('Cannot communicate with the server');
|
||||
};
|
||||
request.onload = () => {
|
||||
if (request.status === 200) callback(request.responseText);
|
||||
|
@ -214,123 +206,117 @@ const RammerheadEncode = async baseUrl => {
|
|||
);
|
||||
};
|
||||
},
|
||||
|
||||
// Functions for interacting with Rammerhead backend code on the server.
|
||||
// Functions for interacting with Rammerhead backend code on the server.
|
||||
api = {
|
||||
|
||||
// Make a new Rammerhead session and do something with it.
|
||||
// Make a new Rammerhead session and do something with it.
|
||||
newsession(callback) {
|
||||
get("/newsession", callback);
|
||||
get('/newsession', callback);
|
||||
},
|
||||
|
||||
// Check if a session with the specified ID exists, then do something.
|
||||
// Check if a session with the specified ID exists, then do something.
|
||||
sessionexists(id, callback) {
|
||||
get("/sessionexists?id=" + encodeURIComponent(id), res => {
|
||||
if (res === "exists") return callback(true);
|
||||
if (res === "not found") return callback(false);
|
||||
console.log("Unexpected response from server. Received " + res);
|
||||
get('/sessionexists?id=' + encodeURIComponent(id), (res) => {
|
||||
if (res === 'exists') return callback(true);
|
||||
if (res === 'not found') return callback(false);
|
||||
console.log('Unexpected response from server. Received ' + res);
|
||||
});
|
||||
},
|
||||
|
||||
// Request a brand new encoding table to use for Rammerhead.
|
||||
// Request a brand new encoding table to use for Rammerhead.
|
||||
shuffleDict(id, callback) {
|
||||
console.log("Shuffling", id);
|
||||
get("/api/shuffleDict?id=" + encodeURIComponent(id), res => {
|
||||
console.log('Shuffling', id);
|
||||
get('/api/shuffleDict?id=' + encodeURIComponent(id), (res) => {
|
||||
callback(JSON.parse(res));
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
// Organize Rammerhead sessions via the browser's local storage.
|
||||
// Local data consists of session creation timestamps and session IDs.
|
||||
// The rest of the data is stored on the server.
|
||||
localStorageKey = "rammerhead_sessionids",
|
||||
localStorageKeyDefault = "rammerhead_default_sessionid",
|
||||
// Organize Rammerhead sessions via the browser's local storage.
|
||||
// Local data consists of session creation timestamps and session IDs.
|
||||
// The rest of the data is stored on the server.
|
||||
localStorageKey = 'rammerhead_sessionids',
|
||||
localStorageKeyDefault = 'rammerhead_default_sessionid',
|
||||
sessionIdsStore = {
|
||||
|
||||
// Get the local data of all stored sessions.
|
||||
// Get the local data of all stored sessions.
|
||||
get() {
|
||||
const rawData = localStorage.getItem(localStorageKey);
|
||||
if (!rawData) return [];
|
||||
try {
|
||||
const data = JSON.parse(rawData);
|
||||
|
||||
// Catch invalidly stored Rammerhead session data. Either that or
|
||||
// it's poorly spoofed.
|
||||
if (!Array.isArray(data)) throw "getout";
|
||||
// Catch invalidly stored Rammerhead session data. Either that or
|
||||
// it's poorly spoofed.
|
||||
if (!Array.isArray(data)) throw 'getout';
|
||||
return data;
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
// Store local Rammerhead session data in the form of an array.
|
||||
// Store local Rammerhead session data in the form of an array.
|
||||
set(data) {
|
||||
if (!Array.isArray(data)) throw new TypeError("Must be an array.");
|
||||
if (!Array.isArray(data)) throw new TypeError('Must be an array.');
|
||||
localStorage.setItem(localStorageKey, JSON.stringify(data));
|
||||
},
|
||||
|
||||
// Get the default session data.
|
||||
// Get the default session data.
|
||||
getDefault() {
|
||||
const sessionId = localStorage.getItem(localStorageKeyDefault);
|
||||
if (sessionId) {
|
||||
let data = sessionIdsStore.get();
|
||||
data.filter(session => session.id === sessionId);
|
||||
data.filter((session) => session.id === sessionId);
|
||||
if (data.length) return data[0];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// Set a new default session based on a given session ID.
|
||||
// Set a new default session based on a given session ID.
|
||||
setDefault(id) {
|
||||
localStorage.setItem(localStorageKeyDefault, id);
|
||||
},
|
||||
},
|
||||
|
||||
// Store or update local data for a Rammerhead session, which consists of
|
||||
// the session's ID and when the session was last created.
|
||||
addSession = id => {
|
||||
// Store or update local data for a Rammerhead session, which consists of
|
||||
// the session's ID and when the session was last created.
|
||||
addSession = (id) => {
|
||||
let data = sessionIdsStore.get();
|
||||
data.unshift({ id: id, createdOn: new Date().toLocaleString() });
|
||||
sessionIdsStore.set(data);
|
||||
},
|
||||
|
||||
// Attempt to load an existing session that has been stored on the server.
|
||||
// Attempt to load an existing session that has been stored on the server.
|
||||
getSessionId = () => {
|
||||
return new Promise(resolve => {
|
||||
// Check if the browser has stored an existing session.
|
||||
const id = localStorage.getItem("session-string");
|
||||
api.sessionexists(id, value => {
|
||||
// Create a new session if Rammerhead can't find an existing session.
|
||||
return new Promise((resolve) => {
|
||||
// Check if the browser has stored an existing session.
|
||||
const id = localStorage.getItem('session-string');
|
||||
api.sessionexists(id, (value) => {
|
||||
// Create a new session if Rammerhead can't find an existing session.
|
||||
if (!value) {
|
||||
console.log("Session validation failed");
|
||||
api.newsession(id => {
|
||||
console.log('Session validation failed');
|
||||
api.newsession((id) => {
|
||||
addSession(id);
|
||||
localStorage.setItem("session-string", id);
|
||||
localStorage.setItem('session-string', id);
|
||||
console.log(id);
|
||||
console.log("^ new id");
|
||||
console.log('^ new id');
|
||||
resolve(id);
|
||||
});
|
||||
}
|
||||
// Load the stored session now that Rammerhead has found it.
|
||||
// Load the stored session now that Rammerhead has found it.
|
||||
else resolve(id);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Load the URL that was last visited in the Rammerhead session.
|
||||
return getSessionId().then((id) =>
|
||||
new Promise(resolve => {
|
||||
api.shuffleDict(id, shuffleDict => {
|
||||
// Encode the URL with Rammerhead's encoding table and return the URL.
|
||||
// Load the URL that was last visited in the Rammerhead session.
|
||||
return getSessionId().then(
|
||||
(id) =>
|
||||
new Promise((resolve) => {
|
||||
api.shuffleDict(id, (shuffleDict) => {
|
||||
// Encode the URL with Rammerhead's encoding table and return the URL.
|
||||
resolve(`/${id}/` + new StrShuffler(shuffleDict).shuffle(baseUrl));
|
||||
});
|
||||
})
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* To use:
|
||||
/* To use:
|
||||
* goProx.proxy(url-string, mode-as-string-or-number);
|
||||
*
|
||||
* Key: 1 = "stealth"
|
||||
|
@ -362,211 +348,237 @@ const RammerheadEncode = async baseUrl => {
|
|||
*
|
||||
* goProx.searx();
|
||||
*/
|
||||
addEventListener("DOMContentLoaded", async () => {
|
||||
addEventListener('DOMContentLoaded', async () => {
|
||||
const goProx = {
|
||||
// `location.protocol + "//" + getDomain()` more like `location.origin`
|
||||
// setAuthCookie("__cor_auth=1", false);
|
||||
// `location.protocol + "//" + getDomain()` more like `location.origin`
|
||||
// setAuthCookie("__cor_auth=1", false);
|
||||
ultraviolet: urlHandler(uvUrl),
|
||||
|
||||
rammerhead: asyncUrlHandler(async url => location.origin + (await RammerheadEncode(search(url)))),
|
||||
rammerhead: asyncUrlHandler(
|
||||
async (url) => location.origin + (await RammerheadEncode(search(url)))
|
||||
),
|
||||
|
||||
searx: urlHandler(location.protocol + `//c.${getDomain()}/engine/`),
|
||||
|
||||
libreddit: urlHandler(location.protocol + "//c." + getDomain()),
|
||||
libreddit: urlHandler(location.protocol + '//c.' + getDomain()),
|
||||
|
||||
rnav: urlHandler(location.protocol + "//client." + getDomain()),
|
||||
rnav: urlHandler(location.protocol + '//client.' + getDomain()),
|
||||
|
||||
osu: urlHandler(location.origin + "/archive/osu"),
|
||||
osu: urlHandler(location.origin + '/archive/osu'),
|
||||
|
||||
mcnow: urlHandler(uvUrl("https://now.gg/play/a/10010/b")),
|
||||
mcnow: urlHandler(uvUrl('https://now.gg/play/a/10010/b')),
|
||||
|
||||
glife: urlHandler(uvUrl("https://now.gg/apps/lunime/5767/gacha-life.html")),
|
||||
glife: urlHandler(
|
||||
uvUrl('https://now.gg/apps/lunime/5767/gacha-life.html')
|
||||
),
|
||||
|
||||
roblox: urlHandler(uvUrl("https://now.gg/apps/roblox-corporation/5349/roblox.html")),
|
||||
roblox: urlHandler(
|
||||
uvUrl('https://now.gg/apps/roblox-corporation/5349/roblox.html')
|
||||
),
|
||||
|
||||
amongus: urlHandler(uvUrl("https://now.gg/apps/innersloth-llc/4047/among-us.html")),
|
||||
amongus: urlHandler(
|
||||
uvUrl('https://now.gg/apps/innersloth-llc/4047/among-us.html')
|
||||
),
|
||||
|
||||
pubg: urlHandler(uvUrl("https://now.gg/apps/proxima-beta/2609/pubg-mobile-resistance.html")),
|
||||
pubg: urlHandler(
|
||||
uvUrl(
|
||||
'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')),
|
||||
|
||||
village: urlHandler(uvUrl("https://kwoodhouse.itch.io/village-arsonist")),
|
||||
village: urlHandler(uvUrl('https://kwoodhouse.itch.io/village-arsonist')),
|
||||
|
||||
prison: urlHandler(uvUrl("https://vimlark.itch.io/pick-up-prison")),
|
||||
prison: urlHandler(uvUrl('https://vimlark.itch.io/pick-up-prison')),
|
||||
|
||||
rpg: urlHandler(uvUrl("https://alarts.itch.io/die-in-the-dungeon")),
|
||||
rpg: urlHandler(uvUrl('https://alarts.itch.io/die-in-the-dungeon')),
|
||||
|
||||
speed: urlHandler(uvUrl("https://captain4lk.itch.io/what-the-road-brings")),
|
||||
speed: urlHandler(
|
||||
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')),
|
||||
|
||||
youtube: urlHandler(uvUrl("https://youtube.com")),
|
||||
youtube: urlHandler(uvUrl('https://youtube.com')),
|
||||
|
||||
discordUV: urlHandler(uvUrl("https://discord.com/app"))
|
||||
discordUV: urlHandler(uvUrl('https://discord.com/app')),
|
||||
};
|
||||
|
||||
// Don't slow down the rest of the script while encoding the URL.
|
||||
RammerheadEncode("https://discord.com/app").then(url => {
|
||||
// Don't slow down the rest of the script while encoding the URL.
|
||||
RammerheadEncode('https://discord.com/app').then((url) => {
|
||||
goProx.discordRH = urlHandler(url);
|
||||
|
||||
// Object.freeze prevents goProx from accidentally being edited.
|
||||
// Object.freeze prevents goProx from accidentally being edited.
|
||||
Object.freeze(goProx);
|
||||
});
|
||||
|
||||
|
||||
// Attach event listeners using goProx to specific app menus that need it.
|
||||
// Attach event listeners using goProx to specific app menus that need it.
|
||||
const prSet = (id, type) => {
|
||||
const formElement = document.getElementById(id);
|
||||
if (!formElement) return;
|
||||
|
||||
let prUrl = formElement.querySelector("input[type=text]"),
|
||||
let prUrl = formElement.querySelector('input[type=text]'),
|
||||
prGo1 = document.querySelectorAll(`#${id}.pr-go1, #${id} .pr-go1`),
|
||||
prGo2 = document.querySelectorAll(`#${id}.pr-go2, #${id} .pr-go2`);
|
||||
|
||||
// Handle the other menu buttons differently if there is no omnibox. Menus
|
||||
// which lack an omnibox likely use buttons as mere links.
|
||||
// Handle the other menu buttons differently if there is no omnibox. Menus
|
||||
// which lack an omnibox likely use buttons as mere links.
|
||||
const goProxMethod = prUrl
|
||||
? mode => () => {goProx[type](prUrl.value, mode)}
|
||||
: mode => () => {goProx[type](mode)},
|
||||
? (mode) => () => {
|
||||
goProx[type](prUrl.value, mode);
|
||||
}
|
||||
: (mode) => () => {
|
||||
goProx[type](mode);
|
||||
},
|
||||
// Ultraviolet is currently incompatible with window mode.
|
||||
searchMode = type === 'ultraviolet' ? 'stealth' : 'window';
|
||||
|
||||
// Ultraviolet is currently incompatible with window mode.
|
||||
searchMode = type === "ultraviolet" ? "stealth" : "window";
|
||||
|
||||
if (prUrl) prUrl.addEventListener("keydown", async e => {
|
||||
if (e.code === "Enter") goProxMethod(searchMode)();
|
||||
|
||||
// This is exclusively used for the validator script.
|
||||
else if (e.code === "Validator Test") {
|
||||
if (prUrl)
|
||||
prUrl.addEventListener('keydown', async (e) => {
|
||||
if (e.code === 'Enter') goProxMethod(searchMode)();
|
||||
// This is exclusively used for the validator script.
|
||||
else if (e.code === 'Validator Test') {
|
||||
e.target.value = await goProx[type](e.target.value);
|
||||
e.target.dispatchEvent(new Event("change"));
|
||||
e.target.dispatchEvent(new Event('change'));
|
||||
}
|
||||
});
|
||||
|
||||
prGo1.forEach(element => {
|
||||
element.addEventListener("click", goProxMethod("window"));
|
||||
prGo1.forEach((element) => {
|
||||
element.addEventListener('click', goProxMethod('window'));
|
||||
});
|
||||
prGo2.forEach(element => {
|
||||
element.addEventListener("click", goProxMethod("stealth"));
|
||||
prGo2.forEach((element) => {
|
||||
element.addEventListener('click', goProxMethod('stealth'));
|
||||
});
|
||||
};
|
||||
|
||||
prSet('pr-uv', 'ultraviolet');
|
||||
prSet('pr-rh', 'rammerhead');
|
||||
prSet('pr-yt', 'youtube');
|
||||
prSet('pr-rh-dc', 'discordRH');
|
||||
prSet('pr-uv-dc', 'discordUV');
|
||||
|
||||
prSet("pr-uv", "ultraviolet");
|
||||
prSet("pr-rh", "rammerhead");
|
||||
prSet("pr-yt", "youtube");
|
||||
prSet("pr-rh-dc", "discordRH");
|
||||
prSet("pr-uv-dc", "discordUV");
|
||||
|
||||
|
||||
|
||||
// Load in relevant JSON files used to organize large sets of data.
|
||||
// This first one is for links, whereas the rest are for navigation menus.
|
||||
const huLinks = await fetch("/assets/json/links.json", {mode: "same-origin"}).then(response => response.json());
|
||||
// Load in relevant JSON files used to organize large sets of data.
|
||||
// This first one is for links, whereas the rest are for navigation menus.
|
||||
const huLinks = await fetch('/assets/json/links.json', {
|
||||
mode: 'same-origin',
|
||||
}).then((response) => response.json());
|
||||
|
||||
for (let items = Object.entries(huLinks), i = 0; i < items.length; i++)
|
||||
// Replace all placeholder links with the corresponding entry in huLinks.
|
||||
// Replace all placeholder links with the corresponding entry in huLinks.
|
||||
(document.getElementById(items[i][0]) || {}).href = items[i][1];
|
||||
|
||||
const navLists = {
|
||||
// Pair an element ID with a JSON file name. They are identical for now.
|
||||
"emu-nav": "emu-nav",
|
||||
"emulib-nav": "emulib-nav",
|
||||
"flash-nav": "flash-nav",
|
||||
"h5-nav": "h5-nav"
|
||||
// Pair an element ID with a JSON file name. They are identical for now.
|
||||
'emu-nav': 'emu-nav',
|
||||
'emulib-nav': 'emulib-nav',
|
||||
'flash-nav': 'flash-nav',
|
||||
'h5-nav': 'h5-nav',
|
||||
};
|
||||
|
||||
for (const [listId, filename] of Object.entries(navLists)) {
|
||||
|
||||
let navList = document.getElementById(listId);
|
||||
|
||||
if(navList) {
|
||||
// List items stored in JSON format will be returned as a JS object.
|
||||
const data = await fetch(`/assets/json/${filename}.json`, {mode: "same-origin"}).then(response => response.json());
|
||||
if (navList) {
|
||||
// List items stored in JSON format will be returned as a JS object.
|
||||
const data = await fetch(`/assets/json/${filename}.json`, {
|
||||
mode: 'same-origin',
|
||||
}).then((response) => response.json());
|
||||
|
||||
// Load the JSON lists into specific HTML parent elements as groups of
|
||||
// child elements, if the parent element is found.
|
||||
// Load the JSON lists into specific HTML parent elements as groups of
|
||||
// child elements, if the parent element is found.
|
||||
switch (filename) {
|
||||
case "emu-nav":
|
||||
case "emulib-nav":
|
||||
case "h5-nav": {
|
||||
case 'emu-nav':
|
||||
case 'emulib-nav':
|
||||
case 'h5-nav': {
|
||||
const dirnames = {
|
||||
// Set the directory of where each item of the corresponding JSON
|
||||
// list will be retrieved from.
|
||||
"emu-nav": "emu",
|
||||
"emulib-nav": "emulib",
|
||||
"h5-nav": "h5g"
|
||||
// Set the directory of where each item of the corresponding JSON
|
||||
// list will be retrieved from.
|
||||
'emu-nav': 'emu',
|
||||
'emulib-nav': 'emulib',
|
||||
'h5-nav': 'h5g',
|
||||
},
|
||||
|
||||
dir = dirnames[filename],
|
||||
|
||||
// Add a little functionality for each list item when clicked on.
|
||||
clickHandler = (parser, a) => e => {
|
||||
if (e.target == a || e.target.tagName != "A") {
|
||||
// Add a little functionality for each list item when clicked on.
|
||||
clickHandler = (parser, a) => (e) => {
|
||||
if (e.target == a || e.target.tagName != 'A') {
|
||||
e.preventDefault();
|
||||
parser(item);
|
||||
}
|
||||
};
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
// Load each item as an anchor tag with an image, heading,
|
||||
// description, and click event listener.
|
||||
// Load each item as an anchor tag with an image, heading,
|
||||
// description, and click event listener.
|
||||
const item = data[i],
|
||||
a = document.createElement("a"),
|
||||
img = document.createElement("img"),
|
||||
title = document.createElement("h3"),
|
||||
desc = document.createElement("p");
|
||||
a = document.createElement('a'),
|
||||
img = document.createElement('img'),
|
||||
title = document.createElement('h3'),
|
||||
desc = document.createElement('p');
|
||||
|
||||
a.href = "#";
|
||||
a.href = '#';
|
||||
img.src = `/assets/img/${dir}/` + item.img;
|
||||
title.textContent = item.name;
|
||||
desc.textContent = item.description;
|
||||
|
||||
if (filename === "h5-nav") {
|
||||
if (item.credits === "itch") desc.innerHTML += '<br>Credits: Game can be found <a target="_blank" href="https://itch.io">here</a>.';
|
||||
if (item.credits === "nowgg") desc.innerHTML += '<br>Credits: Game can be found <a target="_blank" href="https://now.gg">here</a>.';
|
||||
if (filename === 'h5-nav') {
|
||||
if (item.credits === 'itch')
|
||||
desc.innerHTML +=
|
||||
'<br>Credits: Game can be found <a target="_blank" href="https://itch.io">here</a>.';
|
||||
if (item.credits === 'nowgg')
|
||||
desc.innerHTML +=
|
||||
'<br>Credits: Game can be found <a target="_blank" href="https://now.gg">here</a>.';
|
||||
}
|
||||
|
||||
a.appendChild(img);
|
||||
a.appendChild(title);
|
||||
a.appendChild(desc);
|
||||
|
||||
// Which function is used for the click event is determined by
|
||||
// the corresponding location/index in the dirnames object.
|
||||
// Which function is used for the click event is determined by
|
||||
// the corresponding location/index in the dirnames object.
|
||||
const functionsList = [
|
||||
() => goFrame(item.path),
|
||||
() => goFrame("/webretro?core=" + item.core + "&rom=" + item.rom),
|
||||
item.custom ? () => goProx[item.custom]("stealth") : () => goFrame("/archive/g/" + item.path)
|
||||
() =>
|
||||
goFrame('/webretro?core=' + item.core + '&rom=' + item.rom),
|
||||
item.custom
|
||||
? () => goProx[item.custom]('stealth')
|
||||
: () => goFrame('/archive/g/' + item.path),
|
||||
];
|
||||
|
||||
a.addEventListener("click", clickHandler(functionsList[Object.values(dirnames).indexOf(dir)], a));
|
||||
a.addEventListener(
|
||||
'click',
|
||||
clickHandler(
|
||||
functionsList[Object.values(dirnames).indexOf(dir)],
|
||||
a
|
||||
)
|
||||
);
|
||||
|
||||
navList.appendChild(a);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "flash-nav":
|
||||
case 'flash-nav':
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
// Load each item as an anchor tag with a short title and click
|
||||
// event listener.
|
||||
const item = data[i], a = document.createElement("a");
|
||||
a.href = "#";
|
||||
// Load each item as an anchor tag with a short title and click
|
||||
// event listener.
|
||||
const item = data[i],
|
||||
a = document.createElement('a');
|
||||
a.href = '#';
|
||||
a.textContent = item.slice(0, -4);
|
||||
|
||||
a.addEventListener("click", e => {
|
||||
a.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
goFrame("/flash?swf=" + item);
|
||||
goFrame('/flash?swf=' + item);
|
||||
});
|
||||
|
||||
navList.appendChild(a);
|
||||
}
|
||||
break;
|
||||
|
||||
// No default case.
|
||||
|
||||
// No default case.
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
|
@ -5,150 +5,168 @@
|
|||
/* Settings Menu
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
|
||||
// Encase everything in a new scope so that variables are not accidentally
|
||||
// attached to the global scope.
|
||||
(() => {
|
||||
// Determine the expiration date of a new cookie.
|
||||
let date = new Date();
|
||||
date.setFullYear(date.getFullYear() + 100);
|
||||
date = date.toUTCString();
|
||||
|
||||
// Determine the expiration date of a new cookie.
|
||||
let date = new Date();
|
||||
date.setFullYear(date.getFullYear() + 100);
|
||||
date = date.toUTCString();
|
||||
|
||||
// All cookies should be secure and are intended to work in iframes.
|
||||
const setCookie = (name, value) => {
|
||||
document.cookie = name + `=${encodeURIComponent(value)}; expires=${date}; SameSite=None; Secure;`;
|
||||
// All cookies should be secure and are intended to work in iframes.
|
||||
const setCookie = (name, value) => {
|
||||
document.cookie =
|
||||
name +
|
||||
`=${encodeURIComponent(value)}; expires=${date}; SameSite=None; Secure;`;
|
||||
},
|
||||
|
||||
removeCookie = name => {
|
||||
document.cookie = name + "=; expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=None; Secure;";
|
||||
removeCookie = (name) => {
|
||||
document.cookie =
|
||||
name +
|
||||
'=; expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=None; Secure;';
|
||||
},
|
||||
|
||||
readCookie = async name => {
|
||||
for (let cookie of document.cookie.split("; "))
|
||||
// Get the first cookie that has the same name.
|
||||
if (!cookie.indexOf(name + "="))
|
||||
// Return the cookie's stored content.
|
||||
readCookie = async (name) => {
|
||||
// Get the first cookie that has the same name.
|
||||
for (let cookie of document.cookie.split('; '))
|
||||
if (!cookie.indexOf(name + '='))
|
||||
// Return the cookie's stored content.
|
||||
return decodeURIComponent(cookie.slice(name.length + 1));
|
||||
},
|
||||
|
||||
// Customize the page's title.
|
||||
pageTitle = value => {
|
||||
let tag = document.getElementsByTagName("title")[0] || document.createElement("title");
|
||||
// Customize the page's title.
|
||||
pageTitle = (value) => {
|
||||
let tag =
|
||||
document.getElementsByTagName('title')[0] ||
|
||||
document.createElement('title');
|
||||
tag.innerHTML = value;
|
||||
document.head.appendChild(tag);
|
||||
},
|
||||
|
||||
// Set the page's favicon to a new URL.
|
||||
pageIcon = value => {
|
||||
let tag = document.querySelector("link[rel*='icon']") || document.createElement("link");
|
||||
tag.rel = "icon";
|
||||
// Set the page's favicon to a new URL.
|
||||
pageIcon = (value) => {
|
||||
let tag =
|
||||
document.querySelector("link[rel*='icon']") ||
|
||||
document.createElement('link');
|
||||
tag.rel = 'icon';
|
||||
tag.href = value;
|
||||
document.head.appendChild(tag);
|
||||
},
|
||||
|
||||
// Make a small stylesheet to override a setting from the main stylesheet.
|
||||
// Make a small stylesheet to override a setting from the main stylesheet.
|
||||
pageShowAds = () => {
|
||||
let advertising = document.createElement("style");
|
||||
advertising.id = "advertising";
|
||||
advertising.innerText = ".ad { display:block; }";
|
||||
(document.head || document.body || document.documentElement || document).appendChild(advertising);
|
||||
let advertising = document.createElement('style');
|
||||
advertising.id = 'advertising';
|
||||
advertising.innerText = '.ad { display:block; }';
|
||||
(
|
||||
document.head ||
|
||||
document.body ||
|
||||
document.documentElement ||
|
||||
document
|
||||
).appendChild(advertising);
|
||||
},
|
||||
|
||||
// Remove the stylesheet made by the function above, if it exists.
|
||||
// Remove the stylesheet made by the function above, if it exists.
|
||||
pageHideAds = () => {
|
||||
(document.getElementById("advertising")||new Text()).remove();
|
||||
(document.getElementById('advertising') || new Text()).remove();
|
||||
},
|
||||
|
||||
// These titles and icons are used as autofill templates by settings.html.
|
||||
// The icon URLs and tab titles may need to be updated over time.
|
||||
// These titles and icons are used as autofill templates by settings.html.
|
||||
// The icon URLs and tab titles may need to be updated over time.
|
||||
presetIcons = Object.freeze({
|
||||
"": " \n ",
|
||||
"Google": "Google \n https://www.google.com/favicon.ico",
|
||||
"Bing": "Bing \n https://www.bing.com/sa/simg/favicon-trans-bg-blue-mg-28.ico",
|
||||
"Google Drive": "Home - Google Drive \n https://ssl.gstatic.com/images/branding/product/2x/drive_2020q4_48dp.png",
|
||||
"Gmail": "Inbox - Gmail \n https://ssl.gstatic.com/ui/v1/icons/mail/rfr/gmail.ico"
|
||||
'': ' \n ',
|
||||
Google: 'Google \n https://www.google.com/favicon.ico',
|
||||
Bing: 'Bing \n https://www.bing.com/sa/simg/favicon-trans-bg-blue-mg-28.ico',
|
||||
'Google Drive':
|
||||
'Home - Google Drive \n https://ssl.gstatic.com/images/branding/product/2x/drive_2020q4_48dp.png',
|
||||
Gmail:
|
||||
'Inbox - Gmail \n https://ssl.gstatic.com/ui/v1/icons/mail/rfr/gmail.ico',
|
||||
}),
|
||||
|
||||
// Choose the default transport mode, for proxying, based on the browser.
|
||||
// Firefox is not supported by epoxy yet, which is why this is implemented.
|
||||
// Choose the default transport mode, for proxying, based on the browser.
|
||||
// Firefox is not supported by epoxy yet, which is why this is implemented.
|
||||
defaultMode = /(?:Chrome|AppleWebKit)\//.test(navigator.userAgent)
|
||||
? "epoxy"
|
||||
: "libcurl";
|
||||
? 'epoxy'
|
||||
: 'libcurl';
|
||||
|
||||
// Load a custom page title and favicon if it was previously stored.
|
||||
readCookie('HBTitle').then((s) => {
|
||||
s != undefined && pageTitle(s);
|
||||
});
|
||||
readCookie('HBIcon').then((s) => {
|
||||
s != undefined && pageIcon(s);
|
||||
});
|
||||
|
||||
// Load a custom page title and favicon if it was previously stored.
|
||||
readCookie("HBTitle").then(s => {(s != undefined) && pageTitle(s)});
|
||||
readCookie("HBIcon").then(s => {(s != undefined) && pageIcon(s)});
|
||||
|
||||
// Load the UV transport mode that was last used, or use the default.
|
||||
readCookie("HBTransport").then(s => {
|
||||
let transportMode =
|
||||
document.querySelector(`#uv-transport-list input[value="${
|
||||
s || defaultMode
|
||||
}"]`);
|
||||
// Load the UV transport mode that was last used, or use the default.
|
||||
readCookie('HBTransport').then((s) => {
|
||||
let transportMode = document.querySelector(
|
||||
`#uv-transport-list input[value="${s || defaultMode}"]`
|
||||
);
|
||||
if (transportMode) transportMode.click();
|
||||
});
|
||||
});
|
||||
|
||||
// Ads are disabled by default. Load ads if ads were enabled previously.
|
||||
// Change !== to === here if ads should be enabled by default.
|
||||
readCookie("HBHideAds").then(s => {(s !== "false") ? pageHideAds() : pageShowAds((document.getElementById("hideads") || {}).checked = 0)});
|
||||
// Ads are disabled by default. Load ads if ads were enabled previously.
|
||||
// Change !== to === here if ads should be enabled by default.
|
||||
readCookie('HBHideAds').then((s) => {
|
||||
s !== 'false'
|
||||
? pageHideAds()
|
||||
: pageShowAds(((document.getElementById('hideads') || {}).checked = 0));
|
||||
});
|
||||
|
||||
// Tor is disabled by default. Enable Tor if it was enabled previously.
|
||||
readCookie("HBUseOnion").then(s => {if (s === "true") {
|
||||
let torCheck = document.getElementById("useonion") ||
|
||||
{dispatchEvent: () => {}};
|
||||
// Tor is disabled by default. Enable Tor if it was enabled previously.
|
||||
readCookie('HBUseOnion').then((s) => {
|
||||
if (s === 'true') {
|
||||
let torCheck = document.getElementById('useonion') || {
|
||||
dispatchEvent: () => {},
|
||||
};
|
||||
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.
|
||||
if (document.getElementById("csel")) {
|
||||
const attachEventListener = (selector, ...args) => (
|
||||
document.getElementById(selector) ||
|
||||
document.querySelector(selector)
|
||||
// All code below is used by the Settings UI in the navigation bar.
|
||||
if (document.getElementById('csel')) {
|
||||
const attachEventListener = (selector, ...args) =>
|
||||
(
|
||||
document.getElementById(selector) || document.querySelector(selector)
|
||||
).addEventListener(...args),
|
||||
focusElement =
|
||||
document.getElementsByClassName("dropdown-settings")[0].parentElement.querySelector("a[href='#']");
|
||||
focusElement = document
|
||||
.getElementsByClassName('dropdown-settings')[0]
|
||||
.parentElement.querySelector("a[href='#']");
|
||||
|
||||
attachEventListener(".dropdown-settings .close-settings-btn", "click",
|
||||
() => {document.activeElement.blur()}
|
||||
attachEventListener(
|
||||
'.dropdown-settings .close-settings-btn',
|
||||
'click',
|
||||
() => {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
);
|
||||
|
||||
// Allow users to set a custom title with the UI.
|
||||
attachEventListener("titleform", "submit", e => {
|
||||
// Allow users to set a custom title with the UI.
|
||||
attachEventListener('titleform', 'submit', (e) => {
|
||||
e.preventDefault();
|
||||
e = e.target.firstElementChild;
|
||||
if (e.value) {
|
||||
pageTitle(e.value);
|
||||
setCookie("HBTitle", e.value);
|
||||
e.value = "";
|
||||
} else if (confirm("Reset the title to default?")) {
|
||||
// Allow users to reset the title to default if nothing is entered.
|
||||
setCookie('HBTitle', e.value);
|
||||
e.value = '';
|
||||
} else if (confirm('Reset the title to default?')) {
|
||||
// Allow users to reset the title to default if nothing is entered.
|
||||
focusElement.focus();
|
||||
removeCookie("HBTitle");
|
||||
pageTitle("Holy Unblocker LTS");
|
||||
removeCookie('HBTitle');
|
||||
pageTitle('Holy Unblocker LTS');
|
||||
}
|
||||
});
|
||||
|
||||
// Allow users to set a custom favicon with the UI.
|
||||
attachEventListener("iconform", "submit", e => {
|
||||
// Allow users to set a custom favicon with the UI.
|
||||
attachEventListener('iconform', 'submit', (e) => {
|
||||
e.preventDefault();
|
||||
e = e.target.firstElementChild;
|
||||
if (e.value) {
|
||||
pageIcon(e.value);
|
||||
setCookie("HBIcon", e.value);
|
||||
e.value = "";
|
||||
} else if (confirm("Reset the icon to default?")) {
|
||||
// Allow users to reset the favicon to default if nothing is entered.
|
||||
setCookie('HBIcon', e.value);
|
||||
e.value = '';
|
||||
} else if (confirm('Reset the icon to default?')) {
|
||||
// Allow users to reset the favicon to default if nothing is entered.
|
||||
focusElement.focus();
|
||||
removeCookie("HBIcon");
|
||||
pageIcon("assets/img/icon.png");
|
||||
removeCookie('HBIcon');
|
||||
pageIcon('assets/img/icon.png');
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
/*
|
||||
|
||||
This is unused in the current settings menu.
|
||||
|
||||
|
@ -163,67 +181,70 @@ if (document.getElementById("csel")) {
|
|||
});
|
||||
*/
|
||||
|
||||
// Provides users with a handy set of title and icon autofill options.
|
||||
attachEventListener("icon-list", "change", e => {
|
||||
let titleform = document.getElementById("titleform"),
|
||||
iconform = document.getElementById("iconform");
|
||||
[titleform.firstElementChild.value,
|
||||
iconform.firstElementChild.value] =
|
||||
(presetIcons[e.target.value] || " \n ").split(" \n ");
|
||||
// Provides users with a handy set of title and icon autofill options.
|
||||
attachEventListener('icon-list', 'change', (e) => {
|
||||
let titleform = document.getElementById('titleform'),
|
||||
iconform = document.getElementById('iconform');
|
||||
[titleform.firstElementChild.value, iconform.firstElementChild.value] = (
|
||||
presetIcons[e.target.value] || ' \n '
|
||||
).split(' \n ');
|
||||
});
|
||||
|
||||
// Allow users to change the UV transport mode, for proxying, with the UI.
|
||||
const uvTransportList = document.getElementById("uv-transport-list");
|
||||
uvTransportList.querySelectorAll("input").forEach(element => {
|
||||
element.addEventListener("change", e => {
|
||||
!uvTransportList.querySelector("input:checked") ||
|
||||
// Allow users to change the UV transport mode, for proxying, with the UI.
|
||||
const uvTransportList = document.getElementById('uv-transport-list');
|
||||
uvTransportList.querySelectorAll('input').forEach((element) => {
|
||||
element.addEventListener('change', (e) => {
|
||||
!uvTransportList.querySelector('input:checked') ||
|
||||
e.target.value === defaultMode
|
||||
? removeCookie("HBTransport")
|
||||
: setCookie("HBTransport", e.target.value);
|
||||
? removeCookie('HBTransport')
|
||||
: setCookie('HBTransport', e.target.value);
|
||||
|
||||
// Only the libcurl transport mode supports Tor at the moment.
|
||||
let torCheck = document.getElementById("useonion");
|
||||
if(e.target.value !== "libcurl" && torCheck.checked)
|
||||
torCheck.click();
|
||||
})
|
||||
});
|
||||
let torCheck = document.getElementById('useonion');
|
||||
if (e.target.value !== 'libcurl' && torCheck.checked) torCheck.click();
|
||||
});
|
||||
});
|
||||
|
||||
// Allow users to toggle ads with the UI.
|
||||
attachEventListener("hideads", "change", e => {
|
||||
// Allow users to toggle ads with the UI.
|
||||
attachEventListener('hideads', 'change', (e) => {
|
||||
if (e.target.checked) {
|
||||
pageHideAds();
|
||||
setCookie("HBHideAds", "true");
|
||||
setCookie('HBHideAds', 'true');
|
||||
} else {
|
||||
pageShowAds();
|
||||
setCookie("HBHideAds", "false");
|
||||
setCookie('HBHideAds', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
// Allow users to toggle onion routing in Ultraviolet with the UI. Only
|
||||
// the libcurl transport mode supports Tor at the moment, so ensure that
|
||||
// users are aware that they cannot use Tor with other modes.
|
||||
attachEventListener("useonion", "change", e => {
|
||||
let unselectedModes =
|
||||
document.querySelectorAll("#uv-transport-list input:not([value=libcurl])");
|
||||
// Allow users to toggle onion routing in Ultraviolet with the UI. Only
|
||||
// the libcurl transport mode supports Tor at the moment, so ensure that
|
||||
// users are aware that they cannot use Tor with other modes.
|
||||
attachEventListener('useonion', 'change', (e) => {
|
||||
let unselectedModes = document.querySelectorAll(
|
||||
'#uv-transport-list input:not([value=libcurl])'
|
||||
);
|
||||
if (e.target.checked) {
|
||||
let selectedMode =
|
||||
document.querySelector("#uv-transport-list input[value=libcurl]");
|
||||
unselectedModes.forEach(e => {e.setAttribute("disabled", "true")});
|
||||
let selectedMode = document.querySelector(
|
||||
'#uv-transport-list input[value=libcurl]'
|
||||
);
|
||||
unselectedModes.forEach((e) => {
|
||||
e.setAttribute('disabled', 'true');
|
||||
});
|
||||
selectedMode.click();
|
||||
setCookie("HBUseOnion", "true");
|
||||
setCookie('HBUseOnion', 'true');
|
||||
} else {
|
||||
unselectedModes.forEach(e => {e.removeAttribute("disabled")});
|
||||
unselectedModes.forEach((e) => {
|
||||
e.removeAttribute('disabled');
|
||||
});
|
||||
|
||||
// Tor will likely never be enabled by default, so removing the cookie
|
||||
// here may be better than setting it to false.
|
||||
removeCookie("HBUseOnion");
|
||||
// Tor will likely never be enabled by default, so removing the cookie
|
||||
// here may be better than setting it to false.
|
||||
removeCookie('HBUseOnion');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
/* -----------------------------------------------
|
||||
/* Original code written by OlyB
|
||||
/* -----------------------------------------------
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
await loadFull(tsParticles);
|
||||
|
||||
await tsParticles.load({
|
||||
id: "particles-js",
|
||||
id: 'particles-js',
|
||||
options: {
|
||||
background: {
|
||||
color: { value: "#1d232a" },
|
||||
color: { value: '#1d232a' },
|
||||
},
|
||||
fullScreen: {
|
||||
enable: true,
|
||||
|
@ -22,14 +22,14 @@
|
|||
},
|
||||
particles: {
|
||||
color: {
|
||||
value: "#ffffff",
|
||||
value: '#ffffff',
|
||||
},
|
||||
move: {
|
||||
enable: true,
|
||||
speed: 0.8,
|
||||
direction: "none",
|
||||
direction: 'none',
|
||||
outModes: {
|
||||
default: "out",
|
||||
default: 'out',
|
||||
},
|
||||
},
|
||||
number: {
|
||||
|
@ -48,7 +48,7 @@
|
|||
},
|
||||
},
|
||||
shape: {
|
||||
type: "circle",
|
||||
type: 'circle',
|
||||
},
|
||||
size: {
|
||||
value: { min: 1, max: 5 },
|
||||
|
@ -61,7 +61,7 @@
|
|||
links: {
|
||||
enable: true,
|
||||
distance: 150,
|
||||
color: "#ffffff",
|
||||
color: '#ffffff',
|
||||
opacity: 0.4,
|
||||
width: 1,
|
||||
},
|
||||
|
|
|
@ -1,81 +1,83 @@
|
|||
// Encase everything in a new scope so that variables are not accidentally
|
||||
// attached to the global scope.
|
||||
(() => {
|
||||
|
||||
const stockSW = "/uv/sw.js",
|
||||
blacklistSW = "/uv/sw-blacklist.js",
|
||||
swAllowedHostnames = ["localhost", "127.0.0.1"],
|
||||
connection = new BareMux.BareMuxConnection("/baremux/worker.js"),
|
||||
wispUrl = (location.protocol === "https:" ? "wss" : "ws") + "://" + location.host + "/wisp/",
|
||||
|
||||
// Proxy configuration
|
||||
proxyUrl = "socks5h://localhost:9050", // Replace with your proxy URL
|
||||
const stockSW = '/uv/sw.js',
|
||||
blacklistSW = '/uv/sw-blacklist.js',
|
||||
swAllowedHostnames = ['localhost', '127.0.0.1'],
|
||||
connection = new BareMux.BareMuxConnection('/baremux/worker.js'),
|
||||
wispUrl =
|
||||
(location.protocol === 'https:' ? 'wss' : 'ws') +
|
||||
'://' +
|
||||
location.host +
|
||||
'/wisp/',
|
||||
// Proxy configuration
|
||||
proxyUrl = 'socks5h://localhost:9050', // Replace with your proxy URL
|
||||
transports = {
|
||||
epoxy: "/epoxy/index.mjs",
|
||||
libcurl: "/libcurl/index.mjs",
|
||||
bare: "/baremux/index.mjs"
|
||||
epoxy: '/epoxy/index.mjs',
|
||||
libcurl: '/libcurl/index.mjs',
|
||||
bare: '/baremux/index.mjs',
|
||||
},
|
||||
|
||||
// The following two variables are copied and pasted here from csel.js.
|
||||
readCookie = async name => {
|
||||
for (let cookie of document.cookie.split("; "))
|
||||
// Get the first cookie that has the same name.
|
||||
if (!cookie.indexOf(name + "="))
|
||||
// Return the cookie's stored content.
|
||||
// The following two variables are copied and pasted here from csel.js.
|
||||
readCookie = async (name) => {
|
||||
// Get the first cookie that has the same name.
|
||||
for (let cookie of document.cookie.split('; '))
|
||||
if (!cookie.indexOf(name + '='))
|
||||
// Return the cookie's stored content.
|
||||
return decodeURIComponent(cookie.slice(name.length + 1));
|
||||
},
|
||||
|
||||
// Sets the default transport mode based on the browser. Firefox is not
|
||||
// supported by epoxy yet, which is why this is implemented.
|
||||
// Sets the default transport mode based on the browser. Firefox is not
|
||||
// supported by epoxy yet, which is why this is implemented.
|
||||
defaultMode = /(?:Chrome|AppleWebKit)\//.test(navigator.userAgent)
|
||||
? "epoxy"
|
||||
: "libcurl";
|
||||
? 'epoxy'
|
||||
: 'libcurl';
|
||||
|
||||
transports.default = transports[defaultMode];
|
||||
transports.default = transports[defaultMode];
|
||||
|
||||
// Prevent the transports object from accidentally being edited.
|
||||
Object.freeze(transports);
|
||||
// Prevent the transports object from accidentally being edited.
|
||||
Object.freeze(transports);
|
||||
|
||||
const registerSW = async () => {
|
||||
const registerSW = async () => {
|
||||
if (!navigator.serviceWorker) {
|
||||
if (
|
||||
location.protocol !== "https:" &&
|
||||
location.protocol !== 'https:' &&
|
||||
!swAllowedHostnames.includes(location.hostname)
|
||||
)
|
||||
throw new Error("Service workers cannot be registered without https.");
|
||||
throw new Error('Service workers cannot be registered without https.');
|
||||
|
||||
throw new Error("Your browser doesn't support service workers.");
|
||||
}
|
||||
|
||||
// If the user has changed the transport mode, use that over the default.
|
||||
const transportMode = transports[await readCookie("HBTransport")] ||
|
||||
transports.default;
|
||||
// If the user has changed the transport mode, use that over the default.
|
||||
const transportMode =
|
||||
transports[await readCookie('HBTransport')] || transports.default;
|
||||
let transportOptions = { wisp: wispUrl };
|
||||
|
||||
// Only use Tor with the proxy if the user has enabled it in settings.
|
||||
if (await readCookie("HBUseOnion") === "true")
|
||||
// Only use Tor with the proxy if the user has enabled it in settings.
|
||||
if ((await readCookie('HBUseOnion')) === 'true')
|
||||
transportOptions.proxy = proxyUrl;
|
||||
|
||||
await connection.setTransport(transportMode, [transportOptions]);
|
||||
|
||||
// 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
|
||||
// to be reloaded for this to update, such as by refreshing the page.
|
||||
// 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
|
||||
// to be reloaded for this to update, such as by refreshing the page.
|
||||
const registrations = await navigator.serviceWorker.getRegistrations(),
|
||||
usedSW = await readCookie("HBHideAds") !== "false"
|
||||
? blacklistSW
|
||||
: stockSW;
|
||||
usedSW =
|
||||
(await readCookie('HBHideAds')) !== 'false' ? blacklistSW : stockSW;
|
||||
|
||||
// Unregister a service worker if it isn't the one being used.
|
||||
// Unregister a service worker if it isn't the one being used.
|
||||
for (const registration of registrations)
|
||||
if (registration.active &&
|
||||
new URL(registration.active.scriptURL).pathname !== new URL(usedSW, location.origin).pathname)
|
||||
if (
|
||||
registration.active &&
|
||||
new URL(registration.active.scriptURL).pathname !==
|
||||
new URL(usedSW, location.origin).pathname
|
||||
)
|
||||
await registration.unregister();
|
||||
|
||||
await navigator.serviceWorker.register(usedSW);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
/*
|
||||
|
||||
Commented out upon discovering that a duplicate BareMux connection may be
|
||||
unnecessary; previously thought to have prevented issues with refreshing.
|
||||
|
@ -91,6 +93,5 @@ async function setupTransportOnLoad() {
|
|||
setupTransportOnLoad();
|
||||
*/
|
||||
|
||||
registerSW();
|
||||
|
||||
registerSW();
|
||||
})();
|
|
@ -44,18 +44,18 @@
|
|||
<script src="assets/js/particlesjs/particles.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
var v = document.getElementById("vsc");
|
||||
var v = document.getElementById('vsc');
|
||||
var t, a;
|
||||
v.addEventListener(
|
||||
"mouseenter",
|
||||
'mouseenter',
|
||||
function () {
|
||||
t = setTimeout(function () {
|
||||
if (!a) {
|
||||
a = true;
|
||||
var e = new Audio("assets/misc/visualstudiocode.mp3");
|
||||
var e = new Audio('assets/misc/visualstudiocode.mp3');
|
||||
e.play();
|
||||
e.addEventListener(
|
||||
"ended",
|
||||
'ended',
|
||||
function () {
|
||||
a = false;
|
||||
},
|
||||
|
@ -67,7 +67,7 @@
|
|||
false
|
||||
);
|
||||
v.addEventListener(
|
||||
"mouseleave",
|
||||
'mouseleave',
|
||||
function () {
|
||||
clearTimeout(t);
|
||||
},
|
||||
|
|
384
views/index.html
384
views/index.html
|
@ -1,26 +1,47 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, shrink-to-fit=no"
|
||||
/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="version" content="<!-- VERSION -->" />
|
||||
<meta name="theme-color" content="#b4213b" media="(prefers-color-scheme: dark)" />
|
||||
<meta
|
||||
name="theme-color"
|
||||
content="#b4213b"
|
||||
media="(prefers-color-scheme: dark)"
|
||||
/>
|
||||
<meta name="googlebot" content="index, follow, snippet" />
|
||||
<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1" />
|
||||
<meta
|
||||
name="robots"
|
||||
content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1"
|
||||
/>
|
||||
<meta name="author" content="Titanium Network" />
|
||||
<meta name="generator" content="Fastify, HTML5" />
|
||||
<meta name="application-name" content="Holy Unblocker LTS" />
|
||||
<link rel="canonical" href="https://holyunblocker.org/" />
|
||||
<title>Holy Unblocker LTS | Secure & Free Web Proxy Service</title>
|
||||
<meta name="description" content="Holy Unblocker LTS is a cutting-edge web proxy service designed to bypass web filters and blockers. Whether dealing with client-side or network-based censorship, Holy Unblocker LTS provides seamless access to blocked sites and secure, private browsing on devices like Chromebooks. Overcome content blockers, Chrome extensions, firewalls, and more with our advanced proxy solution." />
|
||||
<meta name="keywords" content="web proxy, free web proxy, proxy web browser, proxy web, proxy web page, proxy for web, secure proxy, unblock websites, free proxy, bypass censorship, unblock Chromebook, proxy service, online security, private browsing, unblock social media, access blocked content, Titanium Network, proxy server, internet freedom, unblock at school, unblock at work" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Holy Unblocker LTS is a cutting-edge web proxy service designed to bypass web filters and blockers. Whether dealing with client-side or network-based censorship, Holy Unblocker LTS provides seamless access to blocked sites and secure, private browsing on devices like Chromebooks. Overcome content blockers, Chrome extensions, firewalls, and more with our advanced proxy solution."
|
||||
/>
|
||||
<meta
|
||||
name="keywords"
|
||||
content="web proxy, free web proxy, proxy web browser, proxy web, proxy web page, proxy for web, secure proxy, unblock websites, free proxy, bypass censorship, unblock Chromebook, proxy service, online security, private browsing, unblock social media, access blocked content, Titanium Network, proxy server, internet freedom, unblock at school, unblock at work"
|
||||
/>
|
||||
<meta property="og:site_name" content="Holy Unblocker LTS" />
|
||||
<meta property="og:url" content="https://holyunblocker.org/" />
|
||||
<meta property="og:title" content="Holy Unblocker LTS | Secure & Advanced Web Proxy Service" />
|
||||
<meta
|
||||
property="og:title"
|
||||
content="Holy Unblocker LTS | Secure & Advanced Web Proxy Service"
|
||||
/>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:description" content="Holy Unblocker LTS is a top-tier web proxy service that bypasses network and browser restrictions to access blocked websites securely. Enjoy a seamless browsing experience with robust security and advanced features." />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Holy Unblocker LTS is a top-tier web proxy service that bypasses network and browser restrictions to access blocked websites securely. Enjoy a seamless browsing experience with robust security and advanced features."
|
||||
/>
|
||||
<meta property="og:image" content="assets/img/icon.png" />
|
||||
<meta property="og:image:secure_url" content="assets/img/icon.png" />
|
||||
<meta property="og:image:alt" content="Holy Unblocker Logo" />
|
||||
|
@ -28,18 +49,41 @@
|
|||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@titaniumnetdev" />
|
||||
<meta name="twitter:creator" content="@titaniumnetdev" />
|
||||
<meta name="twitter:title" content="Holy Unblocker LTS | Secure & Advanced Web Proxy Service" />
|
||||
<meta name="twitter:description" content="Discover Holy Unblocker LTS, a premier web proxy service that bypasses censorship and filters to provide secure access to blocked websites. Ideal for private browsing and overcoming network restrictions on devices like Chromebooks." />
|
||||
<meta
|
||||
name="twitter:title"
|
||||
content="Holy Unblocker LTS | Secure & Advanced Web Proxy Service"
|
||||
/>
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content="Discover Holy Unblocker LTS, a premier web proxy service that bypasses censorship and filters to provide secure access to blocked websites. Ideal for private browsing and overcoming network restrictions on devices like Chromebooks."
|
||||
/>
|
||||
<meta name="twitter:image" content="assets/img/icon2.png" />
|
||||
<meta name="twitter:image:alt" content="Holy Unblocker Icon" />
|
||||
<meta name="msapplication-TileColor" content="#b4213b" />
|
||||
<meta name="msapplication-TileImage" content="assets/img/icon.png" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<meta
|
||||
name="apple-mobile-web-app-status-bar-style"
|
||||
content="black-translucent"
|
||||
/>
|
||||
<meta name="apple-mobile-web-app-title" content="Holy Unblocker LTS" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="assets/img/icon.png" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="assets/img/apple-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="assets/img/icon-small.png" />
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="32x32"
|
||||
href="assets/img/icon.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="assets/img/apple-icon.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="16x16"
|
||||
href="assets/img/icon-small.png"
|
||||
/>
|
||||
<link rel="mask-icon" href="new.svg" color="#b4213b" />
|
||||
<link rel="manifest" href="manifest.json" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
|
@ -88,131 +132,158 @@
|
|||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "FAQPage",
|
||||
"mainEntity": [{
|
||||
"mainEntity": [
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "What is Holy Unblocker?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Holy Unblocker is a free and secure web proxy service designed to bypass web filters and blockers. It supports numerous sites, emphasizing detailed design, mechanics, and advanced features to provide a seamless browsing experience."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "How do I unblock websites at school using Holy Unblocker?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "To unblock websites at school, use Holy Unblocker, a free web proxy service that is frequently updated. If a site gets blocked, join the Titanium Network Discord to request a new site. Monthly restocks help prevent mass blocking."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "What websites can I access with Holy Unblocker?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Holy Unblocker allows access to a wide variety of websites, including popular sites like Discord, Spotify, YouTube, and many game sites."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Is Holy Unblocker safe to use?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Absolutely! Holy Unblocker ensures a safe browsing experience by not collecting or logging any user data. Refer to our Privacy Policy for more details. Additionally, Holy Unblocker is open-source, ensuring full transparency."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Does Holy Unblocker hide my search history?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Yes, Holy Unblocker hides your search history. You can customize your tab appearance via Settings > Tab Cloak and use Stealth mode for private browsing."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "How can I get more Holy Unblocker sites?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Join the Titanium Network Discord at discord.gg/unblock and type \"/proxy\" in our bots channel to receive a new site via DMs from our bot."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Is Holy Unblocker open-source?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Yes, Holy Unblocker is open-source. Visit our GitHub to deploy or host your own instance of Holy Unblocker, ensuring maximum privacy control."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "How fast and advanced is Holy Unblocker?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Holy Unblocker is a fast and highly advanced web proxy service, featuring CAPTCHA integration, customizable blacklist settings, leak prevention mechanisms, robust security measures, and extensive site compatibility via Ultraviolet + Wisp."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Can I self-host Holy Unblocker for better privacy?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Yes, you can easily fork the Holy Unblocker repository and self-host it for maximum privacy control, ensuring no user data is collected."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "What makes Holy Unblocker different from other web proxy services?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Holy Unblocker stands out with its transparency and privacy control, collecting no user data. It leverages custom source randomization and projects like Epoxy, Wisp, and Ultraviolet to effectively bypass web and network filters."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "What design principles does Holy Unblocker follow?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Holy Unblocker uses the Nord Theme for its optimal design color palette, prioritizing readable code syntax and user-friendly UI components."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "How do I start using Holy Unblocker?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Head to the Web Proxies page and select one of the featured proxies. Then, type the site you wish to access in the search box. Each web proxy has its own level of effectiveness, speed, and security. Ultraviolet is highly recommended for the best experience."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "What pre-linked applications does Holy Unblocker feature?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Holy Unblocker features a collection of pre-linked applications, including YouTube, Spotify, Webretro (an online everything emulator), Ruffle.fs (Adobe Flash Emulator), and an expansive library for each respective app."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Is Holy Unblocker planning to support more applications?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Yes, Holy Unblocker is soon to support the Anura games library, expanding its range of pre-linked applications."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "How do I deploy Holy Unblocker on my own server?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Holy Unblocker is designed to be easy to deploy and use on personal setups or production loads. Detailed guides can be found at the official GitHub repository and Titanium Network Docs."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Where is the default proxy location when starting Holy Unblocker?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "The default place for the proxy when started is http://localhost:8080. You can change this setting if needed in config.json. This website is hosted locally with Ultraviolet and Rammerhead built-in."
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "How can I contribute to Holy Unblocker?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Holy Unblocker thrives thanks to its contributors. You can get involved in various ways, including design, core development, applications and games, documentation, and testing and QA. Visit our GitHub repository and join our Discord server to get started."
|
||||
}
|
||||
}]
|
||||
}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- IMPORTANT-HUCOOKINGINSERT-DONOTDELETE -->
|
||||
<div id="header" class="fullwidth" role="navigation" aria-label="Main navigation"><!--HEADER--></div>
|
||||
<div
|
||||
id="header"
|
||||
class="fullwidth"
|
||||
role="navigation"
|
||||
aria-label="Main navigation"
|
||||
>
|
||||
<!--HEADER-->
|
||||
</div>
|
||||
<div id="banner" class="fullwidth">
|
||||
<p class="text-center">
|
||||
<!--HUTAOWOA-->
|
||||
|
@ -224,27 +295,41 @@
|
|||
<div class="home-text" role="banner">
|
||||
<h1><span>End Internet Censorship.</span></h1>
|
||||
<h1>Privacy right at your fingertips.</h1>
|
||||
<a class="homebutton" href="#scrollfix" aria-label="Bypass now">Bypass now?</a>
|
||||
<a class="homebutton mobile" href="/browsing" aria-label="Browse now">Bypass now?</a>
|
||||
<a class="homebutton" href="#scrollfix" aria-label="Bypass now"
|
||||
>Bypass now?</a
|
||||
>
|
||||
<a class="homebutton mobile" href="/browsing" aria-label="Browse now"
|
||||
>Bypass now?</a
|
||||
>
|
||||
</div>
|
||||
<div class="mac-window" aria-label="Command Line Instructions">
|
||||
<div class="mac-title-bar" role="banner" aria-label="Mac Window Title Bar">
|
||||
<div
|
||||
class="mac-title-bar"
|
||||
role="banner"
|
||||
aria-label="Mac Window Title Bar"
|
||||
>
|
||||
<div class="mac-buttons" aria-label="Mac Window Buttons">
|
||||
<span class="mac-close" aria-label="Close Window"></span>
|
||||
<span class="mac-minimize" aria-label="Minimize Window"></span>
|
||||
<span class="mac-maximize" aria-label="Maximize Window"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class=mac-content>
|
||||
<div class="mac-content">
|
||||
<p>
|
||||
<span class=cmd>git clone <span class=url>https://github.com/QuiteAFancyEmerald/Holy-Unblocker.git</span> </span><br>
|
||||
<span class=cmd>cd Holy-Unblocker </span><br><br>
|
||||
<span class=cmd>npm start </span><br>
|
||||
<span class=comment>Or on subsequent uses...</span><br>
|
||||
<span class=cmd>npm restart </span><br><br>
|
||||
<span class=comment>Holy Unblocker LTS v<!-- VERSION --></span><br>
|
||||
<span class=comment>Node.js v20</span><br>
|
||||
<span class=comment>Fastify v4.28.1</span>
|
||||
<span class="cmd"
|
||||
>git clone
|
||||
<span class="url"
|
||||
>https://github.com/QuiteAFancyEmerald/Holy-Unblocker.git</span
|
||||
> </span
|
||||
><br />
|
||||
<span class="cmd">cd Holy-Unblocker </span><br /><br />
|
||||
<span class="cmd">npm start </span><br />
|
||||
<span class="comment">Or on subsequent uses...</span><br />
|
||||
<span class="cmd">npm restart </span><br /><br />
|
||||
<span class="comment">Holy Unblocker LTS v<!-- VERSION --></span
|
||||
><br />
|
||||
<span class="comment">Node.js v20</span><br />
|
||||
<span class="comment">Fastify v4.28.1</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -267,7 +352,9 @@
|
|||
</p>
|
||||
<div class="brand-logo-container">
|
||||
<i class="far fa-window-restore palered"></i>
|
||||
<h2 class="hero-content-header">Holy Unblocker is fast and highly advanced.</h2>
|
||||
<h2 class="hero-content-header">
|
||||
Holy Unblocker is fast and highly advanced.
|
||||
</h2>
|
||||
</div>
|
||||
<p>
|
||||
HU LTS delivers exceptional web proxy performance. It boasts a
|
||||
|
@ -278,7 +365,9 @@
|
|||
</p>
|
||||
<div class="brand-logo-container">
|
||||
<i class="far fa-window-restore palered"></i>
|
||||
<h2 class="hero-content-header">Holy Unblocker is fast and highly advanced.</h2>
|
||||
<h2 class="hero-content-header">
|
||||
Holy Unblocker is fast and highly advanced.
|
||||
</h2>
|
||||
</div>
|
||||
<p>
|
||||
Leveraging our custom source randomization and projects like
|
||||
|
@ -364,20 +453,33 @@
|
|||
</div>
|
||||
<svg class="underline-svg" viewBox="0 0 390 55" fill="none">
|
||||
<defs>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" x1="192.539" y1="1.537" x2="192.539" y2="51.098"
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="192.539"
|
||||
y1="1.537"
|
||||
x2="192.539"
|
||||
y2="51.098"
|
||||
id="gradient-0"
|
||||
gradientTransform="matrix(-0.001215, 0.999999, -7.795296, -0.009463, 402.484802, -163.600372)">
|
||||
<stop offset="0" style="stop-color: rgba(135, 149, 221, 1)"></stop>
|
||||
<stop offset="1" style="stop-color: rgba(56, 80, 198, 1)"></stop>
|
||||
gradientTransform="matrix(-0.001215, 0.999999, -7.795296, -0.009463, 402.484802, -163.600372)"
|
||||
>
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color: rgba(135, 149, 221, 1)"
|
||||
></stop>
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color: rgba(56, 80, 198, 1)"
|
||||
></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path style="
|
||||
<path
|
||||
style="
|
||||
stroke: url(#gradient-0);
|
||||
stroke-width: 2px;
|
||||
stroke-linecap: round;
|
||||
"
|
||||
d="M 3 8.997 C 3 8.997 386.2758229569146 -1.5119911685214125 386.872 5.292 C 387.1840859001393 8.853743500517725 283.1432491171007 17.09919545317559 283.106 22.586 C 283.07461319934777 27.209283823450303 356.0628379238926 30.04524568361604 356.607 35.864 C 357.0292218177662 40.3788405823717 314.606 51.924 314.606 51.924">
|
||||
</path>
|
||||
d="M 3 8.997 C 3 8.997 386.2758229569146 -1.5119911685214125 386.872 5.292 C 387.1840859001393 8.853743500517725 283.1432491171007 17.09919545317559 283.106 22.586 C 283.07461319934777 27.209283823450303 356.0628379238926 30.04524568361604 356.607 35.864 C 357.0292218177662 40.3788405823717 314.606 51.924 314.606 51.924"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -397,7 +499,11 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="image-container">
|
||||
<img class="hero" src="/assets/img/toolbox.png" alt="Toolbox Kit Icon" />
|
||||
<img
|
||||
class="hero"
|
||||
src="/assets/img/toolbox.png"
|
||||
alt="Toolbox Kit Icon"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Repeat the above structure for the second box-card -->
|
||||
|
@ -421,7 +527,11 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="image-container">
|
||||
<img class="hero" src="/assets/img/filecode.png" alt="File Code Icon" />
|
||||
<img
|
||||
class="hero"
|
||||
src="/assets/img/filecode.png"
|
||||
alt="File Code Icon"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-right" id="info2" class="box-card">
|
||||
|
@ -429,11 +539,12 @@
|
|||
<div class="text-wrap">
|
||||
<h1>Usage</h1>
|
||||
<p>
|
||||
Head to the <a href="/browsing">Web Proxies</a> page and select one of
|
||||
the proxies featured! Afterwards, type out the site you wish to
|
||||
access in the search box. Each web proxy has its own level of
|
||||
effectiveness, speed and security. It is recommended to use
|
||||
Ultraviolet.<br /><br />Example Website To Unblock: <code>https://coolmathgames.com</code>
|
||||
Head to the <a href="/browsing">Web Proxies</a> page and select
|
||||
one of the proxies featured! Afterwards, type out the site you
|
||||
wish to access in the search box. Each web proxy has its own
|
||||
level of effectiveness, speed and security. It is recommended to
|
||||
use Ultraviolet.<br /><br />Example Website To Unblock:
|
||||
<code>https://coolmathgames.com</code>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -447,16 +558,20 @@
|
|||
<h1>Apps</h1>
|
||||
<p>
|
||||
HU LTS features a collection of pre-linked applications,
|
||||
including YouTube, Spotify, <a href="/emulators">Webretro</a> (an
|
||||
online everything emulator), <a href="/flash-games">Ruffle.fs</a> (Adobe
|
||||
Flash Emulator), and an expansive library for each respective
|
||||
app.
|
||||
including YouTube, Spotify,
|
||||
<a href="/emulators">Webretro</a> (an online everything
|
||||
emulator), <a href="/flash-games">Ruffle.fs</a> (Adobe Flash
|
||||
Emulator), and an expansive library for each respective app.
|
||||
</p>
|
||||
<p>This project is soon to support the Anura games library.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="image-container">
|
||||
<img class="hero" src="/assets/img/apps.png" alt="Application Icon" />
|
||||
<img
|
||||
class="hero"
|
||||
src="/assets/img/apps.png"
|
||||
alt="Application Icon"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-right" id="info2" class="box-card">
|
||||
|
@ -464,22 +579,54 @@
|
|||
<div class="text-wrap">
|
||||
<h1>Hosting and Deployment</h1>
|
||||
<p>
|
||||
<strong>Holy Unblocker LTS</strong> is designed with flexibility and ease of deployment in mind. As an open-source solution, it is straightforward to set up on both personal and production environments. Key features include modularity for ad-blocking, source randomization, and advanced proxy navigation.<br /><br />
|
||||
For comprehensive setup instructions, visit our official <a href="https://github.com/QuiteAFancyEmerald/Holy-Unblocker" title="Holy Unblocker LTS GitHub Repository" target="_blank" rel="noopener noreferrer">GitHub repository</a>, the <a href="https://docs.titaniumnetwork.org/services/holyunblocker" title="Titanium Network Documentation" target="_blank" rel="noopener noreferrer">Titanium Network Docs</a>, or <a href="?documentation" title="Additional Hosting Information">linked here on the main site</a>.
|
||||
<strong>Holy Unblocker LTS</strong> is designed with flexibility
|
||||
and ease of deployment in mind. As an open-source solution, it
|
||||
is straightforward to set up on both personal and production
|
||||
environments. Key features include modularity for ad-blocking,
|
||||
source randomization, and advanced proxy navigation.<br /><br />
|
||||
For comprehensive setup instructions, visit our official
|
||||
<a
|
||||
href="https://github.com/QuiteAFancyEmerald/Holy-Unblocker"
|
||||
title="Holy Unblocker LTS GitHub Repository"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>GitHub repository</a
|
||||
>, the
|
||||
<a
|
||||
href="https://docs.titaniumnetwork.org/services/holyunblocker"
|
||||
title="Titanium Network Documentation"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>Titanium Network Docs</a
|
||||
>, or
|
||||
<a href="?documentation" title="Additional Hosting Information"
|
||||
>linked here on the main site</a
|
||||
>.
|
||||
</p>
|
||||
<p>
|
||||
Additional scripts can be found in <code>/views/assets/js/</code>:<br />
|
||||
- <strong>bareTransport.js</strong>: Locally installed module for Ultraviolet functionality.<br />
|
||||
- <strong>card.js</strong>: Adds visual effects to the box cards.<br />
|
||||
- <strong>common.js</strong>: Provides essential features across all pages.<br />
|
||||
Additional scripts can be found in
|
||||
<code>/views/assets/js/</code>:<br />
|
||||
- <strong>bareTransport.js</strong>: Locally installed module
|
||||
for Ultraviolet functionality.<br />
|
||||
- <strong>card.js</strong>: Adds visual effects to the box
|
||||
cards.<br />
|
||||
- <strong>common.js</strong>: Provides essential features across
|
||||
all pages.<br />
|
||||
- <strong>csel.js</strong>: Manages the settings menu.<br />
|
||||
- <strong>particles.js</strong>: Creates animated background effects.<br />
|
||||
- <strong>register-sw.js</strong>: Handles service workers and Ultraviolet integration.
|
||||
- <strong>particles.js</strong>: Creates animated background
|
||||
effects.<br />
|
||||
- <strong>register-sw.js</strong>: Handles service workers and
|
||||
Ultraviolet integration.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="image-container">
|
||||
<img class="hero" src="/assets/img/hosting.png" alt="Hosting and Deployment Icon" title="Hosting and Deployment for Holy Unblocker LTS" />
|
||||
<img
|
||||
class="hero"
|
||||
src="/assets/img/hosting.png"
|
||||
alt="Hosting and Deployment Icon"
|
||||
title="Hosting and Deployment for Holy Unblocker LTS"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left" id="info2" class="box-card">
|
||||
|
@ -487,23 +634,54 @@
|
|||
<div class="text-wrap">
|
||||
<h1>Contributing</h1>
|
||||
<p>
|
||||
<strong>Holy Unblocker LTS</strong> thrives due to the dedicated efforts of our amazing contributors. As an open-source project, <strong>HU LTS</strong> relies on the collective skills and passion of its community to drive continuous improvement and deliver the best experience for all users.
|
||||
<strong>Holy Unblocker LTS</strong> thrives due to the dedicated
|
||||
efforts of our amazing contributors. As an open-source project,
|
||||
<strong>HU LTS</strong> relies on the collective skills and
|
||||
passion of its community to drive continuous improvement and
|
||||
deliver the best experience for all users.
|
||||
</p>
|
||||
<p>
|
||||
There are numerous ways to get involved and make a meaningful impact on <strong>Holy Unblocker LTS</strong>:<br /><br />
|
||||
- <strong>Design</strong>: Contribute to the visual aesthetics and user experience.<br />
|
||||
- <strong>Core Development</strong>: Help enhance the core functionality and performance.<br />
|
||||
- <strong>Applications and Games</strong>: Develop and integrate new features or games.<br />
|
||||
- <strong>Documentation</strong>: Assist with creating and refining project documentation.<br />
|
||||
- <strong>Testing and QA</strong>: Ensure the software is bug-free and meets quality standards.
|
||||
There are numerous ways to get involved and make a meaningful
|
||||
impact on <strong>Holy Unblocker LTS</strong>:<br /><br />
|
||||
- <strong>Design</strong>: Contribute to the visual aesthetics
|
||||
and user experience.<br />
|
||||
- <strong>Core Development</strong>: Help enhance the core
|
||||
functionality and performance.<br />
|
||||
- <strong>Applications and Games</strong>: Develop and integrate
|
||||
new features or games.<br />
|
||||
- <strong>Documentation</strong>: Assist with creating and
|
||||
refining project documentation.<br />
|
||||
- <strong>Testing and QA</strong>: Ensure the software is
|
||||
bug-free and meets quality standards.
|
||||
</p>
|
||||
<p>
|
||||
To start contributing, visit our <a href="https://github.com/QuiteAFancyEmerald/Holy-Unblocker" title="Holy Unblocker LTS GitHub Repository" target="_blank" rel="noopener noreferrer">GitHub repository</a> and join our <a href="https://discord.gg/unblock" title="Holy Unblocker LTS Discord Server" target="_blank" rel="noopener noreferrer">Discord server</a> for real-time discussions and updates.
|
||||
To start contributing, visit our
|
||||
<a
|
||||
href="https://github.com/QuiteAFancyEmerald/Holy-Unblocker"
|
||||
title="Holy Unblocker LTS GitHub Repository"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>GitHub repository</a
|
||||
>
|
||||
and join our
|
||||
<a
|
||||
href="https://discord.gg/unblock"
|
||||
title="Holy Unblocker LTS Discord Server"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>Discord server</a
|
||||
>
|
||||
for real-time discussions and updates.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="image-container">
|
||||
<img class="hero" src="/assets/img/git.png" alt="Contributing GitHub Icon" title="Contribute to Holy Unblocker LTS on GitHub" />
|
||||
<img
|
||||
class="hero"
|
||||
src="/assets/img/git.png"
|
||||
alt="Contributing GitHub Icon"
|
||||
title="Contribute to Holy Unblocker LTS on GitHub"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -513,24 +691,39 @@
|
|||
<div class="hero-text-wrap">
|
||||
<div class="brand-logo-container">
|
||||
<i class="far fa-window-restore palered"></i>
|
||||
<h2 class="hero-content-header">Unblock Websites with Holy Unblocker LTS</h2>
|
||||
<h2 class="hero-content-header">
|
||||
Unblock Websites with Holy Unblocker LTS
|
||||
</h2>
|
||||
</div>
|
||||
<p>
|
||||
Holy Unblocker LTS is an open-source <strong>public web proxy</strong>. Enjoy unrestricted access to online content and secure browsing with our advanced <strong>web proxy unblocking</strong> features.
|
||||
Holy Unblocker LTS is an open-source
|
||||
<strong>public web proxy</strong>. Enjoy unrestricted access to
|
||||
online content and secure browsing with our advanced
|
||||
<strong>web proxy unblocking</strong> features.
|
||||
</p>
|
||||
<div class="brand-logo-container">
|
||||
<i class="far fa-window-restore palered"></i>
|
||||
<h2 class="hero-content-header">Free and Accessible Proxy Services</h2>
|
||||
<h2 class="hero-content-header">
|
||||
Free and Accessible Proxy Services
|
||||
</h2>
|
||||
</div>
|
||||
<p>
|
||||
Benefit from our <strong>free web proxy service</strong> that helps you <strong>unblock websites</strong> and access restricted content at no cost. Perfect for navigating educational or workplace filters, our service ensures seamless and reliable access.
|
||||
Benefit from our <strong>free web proxy service</strong> that
|
||||
helps you <strong>unblock websites</strong> and access
|
||||
restricted content at no cost. Perfect for navigating
|
||||
educational or workplace filters, our service ensures seamless
|
||||
and reliable access.
|
||||
</p>
|
||||
<div class="brand-logo-container">
|
||||
<i class="far fa-window-restore palered"></i>
|
||||
<h2 class="hero-content-header">Efficient and Reliable Access</h2>
|
||||
<h2 class="hero-content-header">
|
||||
Efficient and Reliable Access
|
||||
</h2>
|
||||
</div>
|
||||
<p>
|
||||
Our <strong>unblocked web proxy</strong> is designed to meet diverse needs, providing a robust solution for overcoming web filters and enjoying a high-quality browsing experience.
|
||||
Our <strong>unblocked web proxy</strong> is designed to meet
|
||||
diverse needs, providing a robust solution for overcoming web
|
||||
filters and enjoying a high-quality browsing experience.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -556,6 +749,5 @@
|
|||
AOS.init();
|
||||
</script>
|
||||
<script defer="defer" src="assets/js/particlesjs/particles.js"></script>
|
||||
</body>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -36,7 +36,7 @@
|
|||
<!-- IMPORTANT-HUCOOKINGINSERT-DONOTDELETE -->
|
||||
<iframe id="frame" allow="fullscreen" autofocus></iframe>
|
||||
<script>
|
||||
document.getElementById("frame").src = localStorage.getItem("huframesrc");
|
||||
document.getElementById('frame').src = localStorage.getItem('huframesrc');
|
||||
</script>
|
||||
<script src="assets/js/csel.js"></script>
|
||||
</body>
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
<!-- https://markdowntohtml.com/ -->
|
||||
<h1 id="holy-unblocker-img-align-left-src-https-raw-githubusercontent-com-titaniumnetwork-dev-holy-unblocker-master-views-assets-img-icon-png-img-">Holy Unblocker Documentation</h1>
|
||||
<p>Holy Unblocker, an official flagship Titanium Network site, can bypass web filters regardless of whether it is an extension or network-based. Being a secure web proxy service, it supports numerous sites while being updated frequently and concentrating on detail with design, mechanics, and features.</p>
|
||||
<h1
|
||||
id="holy-unblocker-img-align-left-src-https-raw-githubusercontent-com-titaniumnetwork-dev-holy-unblocker-master-views-assets-img-icon-png-img-"
|
||||
>
|
||||
Holy Unblocker Documentation
|
||||
</h1>
|
||||
<p>
|
||||
Holy Unblocker, an official flagship Titanium Network site, can bypass web
|
||||
filters regardless of whether it is an extension or network-based. Being a
|
||||
secure web proxy service, it supports numerous sites while being updated
|
||||
frequently and concentrating on detail with design, mechanics, and features.
|
||||
</p>
|
||||
<p>Works with a large number of sites, including YouTube, Discord, and more!</p>
|
||||
<p>Also has a good amount of locally hosted games featured on the site.</p>
|
||||
<p><strong>Read below for information if the official site is blocked or for obtaining more links.</strong></p>
|
||||
<p>
|
||||
<strong
|
||||
>Read below for information if the official site is blocked or for obtaining
|
||||
more links.</strong
|
||||
>
|
||||
</p>
|
||||
<h4 id="supports">Supports</h4>
|
||||
<ul>
|
||||
<li>Youtube.com</li>
|
||||
|
@ -15,20 +29,37 @@
|
|||
</ul>
|
||||
<h4 id="features-">Features:</h4>
|
||||
<ul>
|
||||
<li>Tab customization using the Options menu for improved stealth </li>
|
||||
<li>Considerable variety with the open selection of proxy types </li>
|
||||
<li>Tab customization using the Options menu for improved stealth</li>
|
||||
<li>Considerable variety with the open selection of proxy types</li>
|
||||
<li>Game library with moderately decent titles</li>
|
||||
<li>Has frequent support articles for issues relating to the various proxy instances</li>
|
||||
<li>
|
||||
Has frequent support articles for issues relating to the various proxy
|
||||
instances
|
||||
</li>
|
||||
</ul>
|
||||
<p>Note: EmuLibrary is not featured in the public version.</p>
|
||||
<p>Official Site: <a href="https://holyubofficial.net">https://holyubofficial.net</a></p>
|
||||
<p><strong>Be sure to join Titanium Network's Discord for more official site links:</strong> <a href="https://discord.gg/unblock">https://discord.gg/unblock</a></p>
|
||||
<p>Simply do <code>%proxy hu</code> in <code>#proxy-commands</code> for more Holy Unblocker links on the TN Discord server.</p>
|
||||
<p>
|
||||
Official Site:
|
||||
<a href="https://holyubofficial.net">https://holyubofficial.net</a>
|
||||
</p>
|
||||
<p>
|
||||
<strong
|
||||
>Be sure to join Titanium Network's Discord for more official site
|
||||
links:</strong
|
||||
>
|
||||
<a href="https://discord.gg/unblock">https://discord.gg/unblock</a>
|
||||
</p>
|
||||
<p>
|
||||
Simply do <code>%proxy hu</code> in <code>#proxy-commands</code> for more Holy
|
||||
Unblocker links on the TN Discord server.
|
||||
</p>
|
||||
<h2 id="table-of-contents-">Table of contents:</h2>
|
||||
<ul>
|
||||
<li><a href="#how-to-setup">Setup</a>
|
||||
<li>
|
||||
<a href="#how-to-setup">Setup</a>
|
||||
<ul>
|
||||
<li><a href="#structure">Structure</a>
|
||||
<li>
|
||||
<a href="#structure">Structure</a>
|
||||
<ul>
|
||||
<li><a href="#structure-information">Structure Information</a></li>
|
||||
<li><a href="#details-of-views">Static Files</a></li>
|
||||
|
@ -36,13 +67,21 @@
|
|||
</ul>
|
||||
</li>
|
||||
<li><a href="#future-additions">Future Additions</a></li>
|
||||
<li><a href="#vauge-explanation-for-beginners-with-external-proxies-and-hosting">Beginner's Explanation</a>
|
||||
<li>
|
||||
<a
|
||||
href="#vauge-explanation-for-beginners-with-external-proxies-and-hosting"
|
||||
>Beginner's Explanation</a
|
||||
>
|
||||
<ul>
|
||||
<li><a href="#list-of-some-good-hosting-options">Hosting Providers</a></li>
|
||||
<li>
|
||||
<a href="#list-of-some-good-hosting-options">Hosting Providers</a>
|
||||
</li>
|
||||
<li><a href="#heroku-steps">Heroku Setup</a></li>
|
||||
<li><a href="#freenomdomain-steps">Domain Setup</a></li>
|
||||
<li><a href="#cloudflare-steps">Cloudflare Setup</a></li>
|
||||
<li><a href="#workspace-configurations">Workspace Configurations</a></li>
|
||||
<li>
|
||||
<a href="#workspace-configurations">Workspace Configurations</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#detailed-faq">Detailed FAQ</a></li>
|
||||
|
@ -60,8 +99,15 @@ npm install
|
|||
|
||||
npm <span class="hljs-literal">start</span>
|
||||
</code></pre>
|
||||
<p>The default place for the proxy when its started is <code>http://localhost:8080</code> but you can change it if needed in config.json</p>
|
||||
<p>This website is hosted locally with Corrosion built-in. More more information go to the Corrosion repository below.</p>
|
||||
<p>
|
||||
The default place for the proxy when its started is
|
||||
<code>http://localhost:8080</code> but you can change it if needed in
|
||||
config.json
|
||||
</p>
|
||||
<p>
|
||||
This website is hosted locally with Corrosion built-in. More more information
|
||||
go to the Corrosion repository below.
|
||||
</p>
|
||||
<h2 id="structure">Structure</h2>
|
||||
<ul>
|
||||
<li><code>index.html</code>: The homepage of the site.</li>
|
||||
|
@ -69,39 +115,87 @@ npm <span class="hljs-literal">start</span>
|
|||
<li><code>error.html</code>: Other errors that are not 404.</li>
|
||||
<li><code>info.html</code>: Documentation (This page!)</li>
|
||||
<li><code>faq.html</code>: Frequently asked questions page.</li>
|
||||
<li><code>hidden.html</code>: Fake "Site not Found" page (unused)</li>
|
||||
<li>
|
||||
<code>hidden.html</code>: Fake "Site not Found" page (unused)
|
||||
</li>
|
||||
<li><code>frame.html</code>: Handles any pages under stealth.</li>
|
||||
<li><code>surf.html</code>: Web Proxies page, page offers to be redirected to any proxies you would like to add. In this case, Corrosion, Womginx, and Palladium.</li>
|
||||
<li>
|
||||
<code>surf.html</code>: Web Proxies page, page offers to be redirected to
|
||||
any proxies you would like to add. In this case, Corrosion, Womginx, and
|
||||
Palladium.
|
||||
</li>
|
||||
<li><code>credits.html</code>: List of all contributors to the site.</li>
|
||||
<li><code>bookmarklets.html</code>: Bookmarklets page, to be worked on more in the future.</li>
|
||||
<li><code>icons.html</code>: Information regarding Settings Menu page. Added this in for standard users.</li>
|
||||
<li><code>terms.html</code>: Terms of Services, AUP and Privacy Policy page.</li>
|
||||
<li><code>gtools.html</code>: Games page, help from @BinBashBanana and @kinglalu.</li>
|
||||
<li>
|
||||
<code>bookmarklets.html</code>: Bookmarklets page, to be worked on more in
|
||||
the future.
|
||||
</li>
|
||||
<li>
|
||||
<code>icons.html</code>: Information regarding Settings Menu page. Added
|
||||
this in for standard users.
|
||||
</li>
|
||||
<li>
|
||||
<code>terms.html</code>: Terms of Services, AUP and Privacy Policy page.
|
||||
</li>
|
||||
<li>
|
||||
<code>gtools.html</code>: Games page, help from @BinBashBanana and
|
||||
@kinglalu.
|
||||
</li>
|
||||
<li><code>games5.html</code>: HTML5 game navigation page.</li>
|
||||
<li><code>emulators.html</code>: Emulator navigation page, using <a href="https://github.com/BinBashBanana/webretro">webretro</a>.</li>
|
||||
<li><code>emulibrary.html</code>: Games page for emulated games (not included in public release)</li>
|
||||
<li><code>flash.html</code>: Games page for flash games, credits given to @BinBashBanana and Titanium Network for its assets.</li>
|
||||
<li><code>corrosion.html</code>: Corrosion Proxy page which features Corrosion hosted locally but can be configured to redirect to an external instance.</li>
|
||||
<li><code>womginx.html</code>: Womginx Proxy page. Script links to a subdomain for Womginx, a highly fast proxy with reCaptcha and discord support.</li>
|
||||
<li>
|
||||
<code>emulators.html</code>: Emulator navigation page, using
|
||||
<a href="https://github.com/BinBashBanana/webretro">webretro</a>.
|
||||
</li>
|
||||
<li>
|
||||
<code>emulibrary.html</code>: Games page for emulated games (not included in
|
||||
public release)
|
||||
</li>
|
||||
<li>
|
||||
<code>flash.html</code>: Games page for flash games, credits given to
|
||||
@BinBashBanana and Titanium Network for its assets.
|
||||
</li>
|
||||
<li>
|
||||
<code>corrosion.html</code>: Corrosion Proxy page which features Corrosion
|
||||
hosted locally but can be configured to redirect to an external instance.
|
||||
</li>
|
||||
<li>
|
||||
<code>womginx.html</code>: Womginx Proxy page. Script links to a subdomain
|
||||
for Womginx, a highly fast proxy with reCaptcha and discord support.
|
||||
</li>
|
||||
<li><code>palladium.html</code>: Palladium Proxy page.</li>
|
||||
<li><code>youtube.html</code>: An proxied version of Youtube running off of the locally hosted Corrosion.</li>
|
||||
<li>
|
||||
<code>youtube.html</code>: An proxied version of Youtube running off of the
|
||||
locally hosted Corrosion.
|
||||
</li>
|
||||
<li><code>discord.html</code>: Hub for the Discord proxy.</li>
|
||||
<li><code>reddit.html</code>: Hub for the Reddit proxy.</li>
|
||||
</ul>
|
||||
<h3 id="structure-information">Structure Information</h3>
|
||||
<ul>
|
||||
<li><code>/views/</code>: The physical site base of Holy Unblocker goes here where static assets are served.</li>
|
||||
<li><code>/src/</code>: For future implementation of obfuscation and keyword removing features.</li>
|
||||
<li>
|
||||
<code>/views/</code>: The physical site base of Holy Unblocker goes here
|
||||
where static assets are served.
|
||||
</li>
|
||||
<li>
|
||||
<code>/src/</code>: For future implementation of obfuscation and keyword
|
||||
removing features.
|
||||
</li>
|
||||
</ul>
|
||||
<h4 id="details-of-views-">Details of <code>/views/</code></h4>
|
||||
<ul>
|
||||
<li><code>/archive/</code> is used for game pages and vibeOS.</li>
|
||||
<li><code>/pages/</code> is used for the HTML for the site.</li>
|
||||
<li><code>/assets/</code> is used for various assets for CSS, JS, and images.</li>
|
||||
<li>
|
||||
<code>/assets/</code> is used for various assets for CSS, JS, and images.
|
||||
</li>
|
||||
</ul>
|
||||
<h4 id="scripts-located-in-views-assets-js-">Scripts located in <code>/views/assets/js/</code></h4>
|
||||
<h4 id="scripts-located-in-views-assets-js-">
|
||||
Scripts located in <code>/views/assets/js/</code>
|
||||
</h4>
|
||||
<ul>
|
||||
<li><code>common.js</code> is used on all of the pages for common useful functions.</li>
|
||||
<li>
|
||||
<code>common.js</code> is used on all of the pages for common useful
|
||||
functions.
|
||||
</li>
|
||||
<li><code>csel.js</code> manages the settings menu on the header.</li>
|
||||
</ul>
|
||||
<h2 id="future-additions">Future Additions</h2>
|
||||
|
@ -109,9 +203,13 @@ npm <span class="hljs-literal">start</span>
|
|||
<li>Expansive game library</li>
|
||||
<li>Various parity changes.</li>
|
||||
</ul>
|
||||
<h2 id="vauge-explanation-for-beginners-with-external-proxies-and-hosting">Vauge Explanation for Beginners With External Proxies and Hosting</h2>
|
||||
<p>You will first want to host your proxies locally or externally. </p>
|
||||
<h4 id="list-of-some-good-hosting-options-">List of some good hosting options:</h4>
|
||||
<h2 id="vauge-explanation-for-beginners-with-external-proxies-and-hosting">
|
||||
Vauge Explanation for Beginners With External Proxies and Hosting
|
||||
</h2>
|
||||
<p>You will first want to host your proxies locally or externally.</p>
|
||||
<h4 id="list-of-some-good-hosting-options-">
|
||||
List of some good hosting options:
|
||||
</h4>
|
||||
<ul>
|
||||
<li><a href="https://dedipath.com">Dedipath</a> (Paid and Dedicated)</li>
|
||||
<li><a href="https://heroku.com">Heroku</a> (Free)</li>
|
||||
|
@ -120,96 +218,238 @@ npm <span class="hljs-literal">start</span>
|
|||
<li><a href="https://repl.it">Repl.it</a> (Free)</li>
|
||||
<li><a href="https://azure.microsoft.com">Azure</a> (Free and Paid)</li>
|
||||
</ul>
|
||||
<p>Out of the list of hosting providers Heroku and NodeClusters rank first as a preference. You may also self-host.</p>
|
||||
<p>After you have selected a decent VPS, use Cloudflare for the DNS records for both the site and the subdomains for the proxies.</p>
|
||||
<p>This is an example of DNS records involving Heroku. Self-hosting will require <code>A records</code> preferably.</p>
|
||||
<p><img src="/assets/img/dnssetup.png" width="500"></img></p>
|
||||
<p>
|
||||
Out of the list of hosting providers Heroku and NodeClusters rank first as a
|
||||
preference. You may also self-host.
|
||||
</p>
|
||||
<p>
|
||||
After you have selected a decent VPS, use Cloudflare for the DNS records for
|
||||
both the site and the subdomains for the proxies.
|
||||
</p>
|
||||
<p>
|
||||
This is an example of DNS records involving Heroku. Self-hosting will require
|
||||
<code>A records</code> preferably.
|
||||
</p>
|
||||
<p><img src="/assets/img/dnssetup.png" width="500" /></p>
|
||||
<ul>
|
||||
<li><code>@</code> and <code>www.deepsoil.ml</code> are being used for the local Corrosion proxy.</li>
|
||||
<li>
|
||||
<code>@</code> and <code>www.deepsoil.ml</code> are being used for the local
|
||||
Corrosion proxy.
|
||||
</li>
|
||||
<li><code>p.deepsoil.ml</code> is being used for Palladium.</li>
|
||||
<li><code>a.deepsoil.ml</code> is being used for womginx.</li>
|
||||
<li><code>cdn.deepsoil.ml</code> is being used for a private Corrosion host on the official sites.</li>
|
||||
<li>
|
||||
<code>cdn.deepsoil.ml</code> is being used for a private Corrosion host on
|
||||
the official sites.
|
||||
</li>
|
||||
</ul>
|
||||
<p>As stated previously, Holy Unblocker is hosted locally with Corrosion.</p>
|
||||
<h4 id="heroku-steps">Heroku Steps</h4>
|
||||
<p>So you chose to use Heroku to host. I personally favor it as a free choice.</p>
|
||||
<p>
|
||||
So you chose to use Heroku to host. I personally favor it as a free choice.
|
||||
</p>
|
||||
<ul>
|
||||
<li>First obtain a card; (Prepaid, Debit, and Credit Cards work). You need this to add custom domains to your Heroku instance.</li>
|
||||
<li>
|
||||
First obtain a card; (Prepaid, Debit, and Credit Cards work). You need this
|
||||
to add custom domains to your Heroku instance.
|
||||
</li>
|
||||
</ul>
|
||||
<p>Make sure you connect your Heroku app to your GitHub and enable automatic deploys. Will make things easier. :) </p>
|
||||
<p>
|
||||
Make sure you connect your Heroku app to your GitHub and enable automatic
|
||||
deploys. Will make things easier. :)
|
||||
</p>
|
||||
<h4 id="freenom-domain-steps">Freenom/Domain Steps</h4>
|
||||
<p>For beginners, Freenom is a good provider for obtaining domains for free. However the catch is that you can only use properly "Freenom" domains for free being .cf, .ml, .gq, ga and .tk. However these can be blocked rather easily.</p>
|
||||
<p>
|
||||
For beginners, Freenom is a good provider for obtaining domains for free.
|
||||
However the catch is that you can only use properly "Freenom"
|
||||
domains for free being .cf, .ml, .gq, ga and .tk. However these can be blocked
|
||||
rather easily.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Get some Freenom domains then add them to your Heroku instance (Personal > [App Name] > Settings > Domains) Add a domain for both <code>www.youdomainhere.cf</code> and <code>yourdomainhere.cf</code> with .cf being interchangeable with other
|
||||
Freenom domain names.</li>
|
||||
<li>If you prefer to obtain premium domains (TLDs) then use <a href="https://porkbun.com">Porkbun</a>, which offers domains for amazing prices. Literally a <code>.net</code> domain normally costs around $10. On Porkbun for the first year it costs $3 so
|
||||
its definitely a deal.</li>
|
||||
<li>
|
||||
Get some Freenom domains then add them to your Heroku instance (Personal
|
||||
> [App Name] > Settings > Domains) Add a domain for both
|
||||
<code>www.youdomainhere.cf</code> and <code>yourdomainhere.cf</code> with
|
||||
.cf being interchangeable with other Freenom domain names.
|
||||
</li>
|
||||
<li>
|
||||
If you prefer to obtain premium domains (TLDs) then use
|
||||
<a href="https://porkbun.com">Porkbun</a>, which offers domains for amazing
|
||||
prices. Literally a <code>.net</code> domain normally costs around $10. On
|
||||
Porkbun for the first year it costs $3 so its definitely a deal.
|
||||
</li>
|
||||
</ul>
|
||||
<h4 id="cloudflare-steps">Cloudflare Steps</h4>
|
||||
<ul>
|
||||
<li>Use Cloudflare (make an account), add your site (Freenom Domain or other) and then add your various DNS targets to Cloudflare. Make sure you add Cloudflare's Nameservers which will be given later when you are adding your site. </li>
|
||||
<li>
|
||||
Use Cloudflare (make an account), add your site (Freenom Domain or other)
|
||||
and then add your various DNS targets to Cloudflare. Make sure you add
|
||||
Cloudflare's Nameservers which will be given later when you are adding
|
||||
your site.
|
||||
</li>
|
||||
</ul>
|
||||
<p>Make sure they are CNAME although A records also work and try to follow this structure:</p>
|
||||
<p>
|
||||
Make sure they are CNAME although A records also work and try to follow this
|
||||
structure:
|
||||
</p>
|
||||
<p><strong>Type | Name | Target</strong></p>
|
||||
<p><code>CNAME | @ | your-main-heroku-target-here.herokudns.com</code><br><code>CNAME | www | your-main-heroku-target-here.herokudns.com</code></p>
|
||||
<p><strong>Below are if you want external proxies also with your site:</strong></p>
|
||||
<p><code>CNAME | p | your-palladium-instance-here.herokudns.com</code><br><code>CNAME | a | your-womginx-instance-here.herokudns.com</code><br><code>CNAME | pd | your-pydodgeb-instance-here.herokudns.com</code></p>
|
||||
<p>Make sure HTTPS is forced and have SSL set to Flexible for Heroku. Otherwise you can have SSL set to Full.</p>
|
||||
<p>
|
||||
<code>CNAME | @ | your-main-heroku-target-here.herokudns.com</code><br /><code
|
||||
>CNAME | www | your-main-heroku-target-here.herokudns.com</code
|
||||
>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Below are if you want external proxies also with your site:</strong>
|
||||
</p>
|
||||
<p>
|
||||
<code>CNAME | p | your-palladium-instance-here.herokudns.com</code><br /><code
|
||||
>CNAME | a | your-womginx-instance-here.herokudns.com</code
|
||||
><br /><code>CNAME | pd | your-pydodgeb-instance-here.herokudns.com</code>
|
||||
</p>
|
||||
<p>
|
||||
Make sure HTTPS is forced and have SSL set to Flexible for Heroku. Otherwise
|
||||
you can have SSL set to Full.
|
||||
</p>
|
||||
<h4 id="workspace-configurations">Workspace Configurations</h4>
|
||||
<p>Preferably if you have your own device use Visual Studio Code. Pretty much the best option you can get but obviously this is an opinion. Also make sure you have <a href="https://nodejs.org/">Node.JS</a> installed on your machine.</p>
|
||||
<p>Not going to go too in depth with this part but first fork this repository. The clone it locally through a Terminal of some sort depending on what OS you are on. Make sure you navigate to the folder you want to set this up in.</p>
|
||||
<p>
|
||||
Preferably if you have your own device use Visual Studio Code. Pretty much the
|
||||
best option you can get but obviously this is an opinion. Also make sure you
|
||||
have <a href="https://nodejs.org/">Node.JS</a> installed on your machine.
|
||||
</p>
|
||||
<p>
|
||||
Not going to go too in depth with this part but first fork this repository.
|
||||
The clone it locally through a Terminal of some sort depending on what OS you
|
||||
are on. Make sure you navigate to the folder you want to set this up in.
|
||||
</p>
|
||||
<pre><code>git <span class="hljs-keyword">clone</span> <span class="hljs-title">https</span>://github.com/titaniumnetwork-dev/Holy-Unblocker.git
|
||||
|
||||
cd Holy-Unblocker
|
||||
|
||||
npm install
|
||||
</code></pre>
|
||||
<p>Now simply add the folder you cloned this repo in in <span id="vsc" style="cursor: help;">VSC</span>. Then run <code>npm install</code>. I recommend that if you are releasing this publically on GitHub that you add a <code>.gitignore</code> in your root directory with the following exclusions:</p>
|
||||
<p>
|
||||
Now simply add the folder you cloned this repo in in
|
||||
<span id="vsc" style="cursor: help">VSC</span>. Then run
|
||||
<code>npm install</code>. I recommend that if you are releasing this
|
||||
publically on GitHub that you add a <code>.gitignore</code> in your root
|
||||
directory with the following exclusions:
|
||||
</p>
|
||||
<pre><code>node_modules
|
||||
</code></pre>
|
||||
<p>Now you have your following workspace environment setup. To deploy the following workspace you just created you will need to look up depending on your hosting provider.</p>
|
||||
<p>For an online IDE that you can use on your school computer and/or chromebook use GitPod. Basically the equivalent of Visual Studio Code but with in-browser support.</p>
|
||||
<p>
|
||||
Now you have your following workspace environment setup. To deploy the
|
||||
following workspace you just created you will need to look up depending on
|
||||
your hosting provider.
|
||||
</p>
|
||||
<p>
|
||||
For an online IDE that you can use on your school computer and/or chromebook
|
||||
use GitPod. Basically the equivalent of Visual Studio Code but with in-browser
|
||||
support.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Make an account: <code>https://gitpod.io/</code></li>
|
||||
<li>Fork this repo and enter in this URL to setup your workspace: <code>https://gitpod.io#https://github.com/YourNameHere/Holy-Unblocker/</code></li>
|
||||
<li>
|
||||
Fork this repo and enter in this URL to setup your workspace:
|
||||
<code
|
||||
>https://gitpod.io#https://github.com/YourNameHere/Holy-Unblocker/</code
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Use the same steps above by running <code>npm install</code> in your repository and adding a <code>.gitignore</code> in your root directory specifying to exclude <code>node_modules</code>.</p>
|
||||
<p>
|
||||
Use the same steps above by running <code>npm install</code> in your
|
||||
repository and adding a <code>.gitignore</code> in your root directory
|
||||
specifying to exclude <code>node_modules</code>.
|
||||
</p>
|
||||
<h2 id="detailed-faq">Detailed FAQ</h2>
|
||||
<p>A detailed FAQ with common issues and solutions can be found <a href="https://holyunblocker.org/questions">here</a> or on any official HU site on the FAQ page.</p>
|
||||
<p>
|
||||
A detailed FAQ with common issues and solutions can be found
|
||||
<a href="https://holyunblocker.org/questions">here</a> or on any official HU
|
||||
site on the FAQ page.
|
||||
</p>
|
||||
<details>
|
||||
<summary>Quick FAQ</summary>
|
||||
|
||||
<p><strong>Why is the site I am on not working correctly or having CAPTCHA errors?</strong></p> Captcha support is currently not available on all of the current proxies sadly. Therefore some sites may not work with any of the sites. Read below for issues
|
||||
with links on sites.
|
||||
<p>
|
||||
<strong
|
||||
>Why is the site I am on not working correctly or having CAPTCHA
|
||||
errors?</strong
|
||||
>
|
||||
</p>
|
||||
Captcha support is currently not available on all of the current proxies
|
||||
sadly. Therefore some sites may not work with any of the sites. Read below for
|
||||
issues with links on sites.
|
||||
|
||||
<p><strong>Why are some page links not working or leading to 404 pages?</strong></p> This is an issue with the latest release of Alloy proxy but it may also occur with other proxies. In this case manually entering the URL of the page you would like to view
|
||||
can solve this or try navigating using the home button. (Reddit, Twitter) The next release of Alloy may fix this also.
|
||||
<p>
|
||||
<strong
|
||||
>Why are some page links not working or leading to 404 pages?</strong
|
||||
>
|
||||
</p>
|
||||
This is an issue with the latest release of Alloy proxy but it may also occur
|
||||
with other proxies. In this case manually entering the URL of the page you
|
||||
would like to view can solve this or try navigating using the home button.
|
||||
(Reddit, Twitter) The next release of Alloy may fix this also.
|
||||
|
||||
<p><strong>When using YouTube on any of the proxy sites, why does the page not load fully or the video is just white?</strong></p> There are two methods for fixing this: - Reloading the page normally when the error above happens should load the video. -
|
||||
Or right-clicking the page and doing Reload Frame if you are using some form of Stealth Mode.
|
||||
<p>
|
||||
<strong
|
||||
>When using YouTube on any of the proxy sites, why does the page not load
|
||||
fully or the video is just white?</strong
|
||||
>
|
||||
</p>
|
||||
There are two methods for fixing this: - Reloading the page normally when the
|
||||
error above happens should load the video. - Or right-clicking the page and
|
||||
doing Reload Frame if you are using some form of Stealth Mode.
|
||||
|
||||
<p><strong>When using Discord under Alloy or SysYa, why does the page stay gray/white or the QR code not load?</strong></p> Once again do the same steps above: - Reloading the page normally when the error above happens should load the video - Or right-clicking
|
||||
the page and doing Reload Frame if you are using some form of Stealth Mode. Make sure you are also doing the steps correctly. Simply view link above for extended Discord proxy information/steps.
|
||||
|
||||
<p><strong>I am getting 502 errors. What do I do?</strong></p> When this happens you may either switch sites to fix the error or wait a bit. Sometimes clearing your cache can help. If you still have any questions feel free to ask them in the discord linked
|
||||
here.
|
||||
<p>
|
||||
<strong
|
||||
>When using Discord under Alloy or SysYa, why does the page stay
|
||||
gray/white or the QR code not load?</strong
|
||||
>
|
||||
</p>
|
||||
Once again do the same steps above: - Reloading the page normally when the
|
||||
error above happens should load the video - Or right-clicking the page and
|
||||
doing Reload Frame if you are using some form of Stealth Mode. Make sure you
|
||||
are also doing the steps correctly. Simply view link above for extended
|
||||
Discord proxy information/steps.
|
||||
|
||||
<p><strong>I am getting 502 errors. What do I do?</strong></p>
|
||||
When this happens you may either switch sites to fix the error or wait a bit.
|
||||
Sometimes clearing your cache can help. If you still have any questions feel
|
||||
free to ask them in the discord linked here.
|
||||
</details>
|
||||
|
||||
<h2 id="more-information">More Information</h2>
|
||||
<p>This project is maintained by Quite A Fancy Emerald with massive help from BinBashBanana (OlyB) and is an official flagship Titanium Network proxy site.</p>
|
||||
<p>
|
||||
This project is maintained by Quite A Fancy Emerald with massive help from
|
||||
BinBashBanana (OlyB) and is an official flagship Titanium Network proxy site.
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="https://github.com/titaniumnetwork-dev/Holy-Unblocker">GitHub link</a></li>
|
||||
<li><a href="https://github.com/titaniumnetwork-dev/">https://github.com/titaniumnetwork-dev/</a></li>
|
||||
<li><a href="https://titaniumnetwork.org/">https://titaniumnetwork.org/</a></li>
|
||||
<li>
|
||||
<a href="https://github.com/titaniumnetwork-dev/Holy-Unblocker"
|
||||
>GitHub link</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/titaniumnetwork-dev/"
|
||||
>https://github.com/titaniumnetwork-dev/</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://titaniumnetwork.org/">https://titaniumnetwork.org/</a>
|
||||
</li>
|
||||
</ul>
|
||||
<p>View the official website for more detail and credits.</p>
|
||||
<h3 id="proxy-sources-">Proxy Sources:</h3>
|
||||
<p>This project currently uses Corrosion, Womginx, and Palladium, linked below.</p>
|
||||
<p>
|
||||
This project currently uses Corrosion, Womginx, and Palladium, linked below.
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="https://github.com/titaniumnetwork-dev/Corrosion">Corrosion</a></li>
|
||||
<li>
|
||||
<a href="https://github.com/titaniumnetwork-dev/Corrosion">Corrosion</a>
|
||||
</li>
|
||||
<li><a href="https://github.com/binary-person/womginx">Womginx</a></li>
|
||||
<li><a href="https://github.com/LudicrousDevelopment/Palladium">Palladium</a></li>
|
||||
<li>
|
||||
<a href="https://github.com/LudicrousDevelopment/Palladium">Palladium</a>
|
||||
</li>
|
||||
<li><a href="https://github.com/BinBashBanana/PyDodge">PyDodge</a></li>
|
||||
</ul>
|
||||
<h3 id="other-">Other:</h3>
|
||||
|
@ -221,6 +461,8 @@ npm install
|
|||
</ul>
|
||||
<h3 id="notable-mentions-">Notable Mentions:</h3>
|
||||
<ul>
|
||||
<li><a href="https://soyoustart.com/">SoYouStart / OVH</a> (Hosting Provider)</li>
|
||||
<li>
|
||||
<a href="https://soyoustart.com/">SoYouStart / OVH</a> (Hosting Provider)
|
||||
</li>
|
||||
</ul>
|
||||
<p>Thanks :D</p>
|
|
@ -23,7 +23,7 @@
|
|||
<a id="iconfinder" class="fancybutton fb-l glowbutton">Find Icon URL</a>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById("iconfinder").href =
|
||||
document.getElementById('iconfinder').href =
|
||||
`javascript:alert((Array.from(document.head.querySelectorAll("link[rel*='icon']")).slice(-1)[0]||0).href||location.origin+"/favicon.ico")`;
|
||||
</script>
|
||||
<p>
|
||||
|
|
|
@ -7,111 +7,143 @@
|
|||
<div class="footerlist">
|
||||
<h3>Dependencies</h3>
|
||||
<ul>
|
||||
<li><a
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/github/fastify"
|
||||
title="Fastify - Fast and low overhead web framework, for Node.js "
|
||||
>Fastify</a
|
||||
></li>
|
||||
<li><a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/github/nord-theme"
|
||||
title="Nord Theme - An arctic, north-bluish color palette."
|
||||
>Nord Theme</a
|
||||
></li>
|
||||
<li><a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/github/aos"
|
||||
title="AOS - Animate on scroll library "
|
||||
>AOS</a
|
||||
></li>
|
||||
<li><a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/github/font-awesome"
|
||||
title="Font Awesome - The iconic SVG, font, and CSS toolkit"
|
||||
>Font Awesome </a
|
||||
></li>
|
||||
>Font Awesome
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footerlist">
|
||||
<h3>Transports</h3>
|
||||
<ul>
|
||||
<li><a
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/github/epoxy"
|
||||
title="Epoxy - Epoxy is an encrypted proxy for browser javascript. It allows you to make requests that bypass CORS without compromising security, by running SSL/TLS inside webassembly."
|
||||
>Epoxy</a
|
||||
></li>
|
||||
<li><a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/github/libcurl-js"
|
||||
title="A port of libcurl to WebAssembly, for proxying HTTPS requests from the browser with full TLS encryption"
|
||||
>Libcurl</a
|
||||
></li>
|
||||
<li><a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/github/bare-module"
|
||||
title="Bare Module - Tomp Bare Client as a bare-mux module"
|
||||
>Bare Module</a
|
||||
></li>
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footerlist">
|
||||
<h3>Services</h3>
|
||||
<ul>
|
||||
<li><a
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/github/ultraviolet"
|
||||
title="Ultraviolet - Explore Ultraviolet"
|
||||
>Ultraviolet</a
|
||||
></li>
|
||||
<li><a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/github/wisp"
|
||||
title="Wisp - Wisp is a low-overhead, easy to implement protocol for proxying multiple TCP/UDP sockets over a single websocket. "
|
||||
>Wisp Protocol</a
|
||||
></li>
|
||||
<li><a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/rammerhead-discord"
|
||||
title="Rammerhead - Join Rammerhead on Discord"
|
||||
>Rammerhead</a
|
||||
></li>
|
||||
<li><a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/github/bare-mux"
|
||||
title="BareMux - A system for managing http transports in a project such as Ultraviolet"
|
||||
>Bare-Mux</a
|
||||
></li>
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footerlist">
|
||||
<h3>About</h3>
|
||||
<ul>
|
||||
<li><a
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/github"
|
||||
title="Holy Unblocker GitHub Repository"
|
||||
>GitHub</a
|
||||
></li>
|
||||
<li><a href="/terms" title="Privacy Policy and Terms of Service">Privacy and Terms of Service</a></li>
|
||||
<li><a href="/credits" title="Credits and Acknowledgements">Credits</a></li>
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/terms" title="Privacy Policy and Terms of Service"
|
||||
>Privacy and Terms of Service</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/credits" title="Credits and Acknowledgements">Credits</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footerlist">
|
||||
<a href="#header" title="Back to Top"><i class="fas fa-angle-double-up" aria-hidden="true"></i></a>
|
||||
<a href="#header" title="Back to Top"
|
||||
><i class="fas fa-angle-double-up" aria-hidden="true"></i
|
||||
></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footersocials">
|
||||
|
|
|
@ -1,20 +1,38 @@
|
|||
<div class="brand-logo-container" aria-label="Brand Logo">
|
||||
<div class="logo" role="img" aria-label="Holy Unblocker Logo"></div>
|
||||
<a href="/" class="brand pulse" title="Holy Unblocker Home Page">Holy Unblocker v6.3.x</a>
|
||||
<a href="/" class="brand pulse" title="Holy Unblocker Home Page"
|
||||
>Holy Unblocker v6.3.x</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<ul class="navbar-1" role="list" aria-label="Primary navigation">
|
||||
<li class="pulse" style="margin-left: 0;" role="listitem">
|
||||
<a href="/browsing" title="Web Proxies - Access various web proxies to bypass restrictions">Web Proxies</a>
|
||||
<li class="pulse" style="margin-left: 0" role="listitem">
|
||||
<a
|
||||
href="/browsing"
|
||||
title="Web Proxies - Access various web proxies to bypass restrictions"
|
||||
>Web Proxies</a
|
||||
>
|
||||
</li>
|
||||
<li class="pulse" role="listitem">
|
||||
<a href="/games" title="Games - Explore a range of games available through our service">Games</a>
|
||||
<a
|
||||
href="/games"
|
||||
title="Games - Explore a range of games available through our service"
|
||||
>Games</a
|
||||
>
|
||||
</li>
|
||||
<li class="pulse" role="listitem">
|
||||
<a href="/youtube" title="YouTube - Access YouTube content through our proxy service">YouTube</a>
|
||||
<a
|
||||
href="/youtube"
|
||||
title="YouTube - Access YouTube content through our proxy service"
|
||||
>YouTube</a
|
||||
>
|
||||
</li>
|
||||
<li class="pulse new" role="listitem">
|
||||
<a href="/apps" title="Applications - Browse a selection of useful applications">Applications</a>
|
||||
<a
|
||||
href="/apps"
|
||||
title="Applications - Browse a selection of useful applications"
|
||||
>Applications</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
@ -26,33 +44,65 @@
|
|||
<ul class="navbar" role="list" aria-label="Secondary navigation">
|
||||
<li class="dropdown-parent" role="listitem">
|
||||
<div class="pulse white-text" aria-haspopup="true" aria-expanded="false">
|
||||
<a href="#" aria-label="More options">More <i class="fas fa-ellipsis-v" aria-hidden="true"></i></a>
|
||||
<a href="#" aria-label="More options"
|
||||
>More <i class="fas fa-ellipsis-v" aria-hidden="true"></i
|
||||
></a>
|
||||
</div>
|
||||
<div class="dropdown-child" tabindex="0" role="menu" aria-label="More options submenu">
|
||||
<div
|
||||
class="dropdown-child"
|
||||
tabindex="0"
|
||||
role="menu"
|
||||
aria-label="More options submenu"
|
||||
>
|
||||
<ul class="subnavbar" role="menu">
|
||||
<li role="menuitem">
|
||||
<a href="/bookmarklets" title="Bookmarklets - Useful tools and shortcuts for your browser">Bookmarklets</a>
|
||||
<a
|
||||
href="/bookmarklets"
|
||||
title="Bookmarklets - Useful tools and shortcuts for your browser"
|
||||
>Bookmarklets</a
|
||||
>
|
||||
</li>
|
||||
<li role="menuitem">
|
||||
<a href="/?documentation" title="Documentation - Detailed information and guides">Docs</a>
|
||||
<a
|
||||
href="/?documentation"
|
||||
title="Documentation - Detailed information and guides"
|
||||
>Docs</a
|
||||
>
|
||||
</li>
|
||||
<li role="menuitem">
|
||||
<a href="/questions" title="FAQ - Frequently asked questions and answers">FAQ</a>
|
||||
<a
|
||||
href="/questions"
|
||||
title="FAQ - Frequently asked questions and answers"
|
||||
>FAQ</a
|
||||
>
|
||||
</li>
|
||||
<li role="menuitem">
|
||||
<a href="/credits" title="Credits - Acknowledgements and contributions">Credits</a>
|
||||
<a
|
||||
href="/credits"
|
||||
title="Credits - Acknowledgements and contributions"
|
||||
>Credits</a
|
||||
>
|
||||
</li>
|
||||
<li role="menuitem">
|
||||
<a href="/terms" title="Terms of Service - Rules and policies of use">TOS</a>
|
||||
<a href="/terms" title="Terms of Service - Rules and policies of use"
|
||||
>TOS</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="dropdown-parent" role="listitem">
|
||||
<div class="pulse white-text" aria-haspopup="true" aria-expanded="false">
|
||||
<a href="#" aria-label="Settings menu">Settings <i class="fas fa-cog pulse" aria-hidden="true"></i></a>
|
||||
<a href="#" aria-label="Settings menu"
|
||||
>Settings <i class="fas fa-cog pulse" aria-hidden="true"></i
|
||||
></a>
|
||||
</div>
|
||||
<div class="dropdown-settings" tabindex="0" role="menu" aria-label="Settings menu">
|
||||
<div
|
||||
class="dropdown-settings"
|
||||
tabindex="0"
|
||||
role="menu"
|
||||
aria-label="Settings menu"
|
||||
>
|
||||
<div id="csel"><!--SETTINGS--></div>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -7,37 +7,43 @@
|
|||
<div class="csel-container-left">
|
||||
<p class="cseltitle">Tab Cloak</p>
|
||||
<form id="titleform" class="cloakform">
|
||||
<input type="text" placeholder="Tab Title" spellcheck="false">
|
||||
<input type="submit" value="Apply">
|
||||
<input type="text" placeholder="Tab Title" spellcheck="false" />
|
||||
<input type="submit" value="Apply" />
|
||||
</form>
|
||||
<form id="iconform" class="cloakform">
|
||||
<input type="text" placeholder="Icon URL" spellcheck="false">
|
||||
<input type="submit" value="Apply">
|
||||
<input type="text" placeholder="Icon URL" spellcheck="false" />
|
||||
<input type="submit" value="Apply" />
|
||||
</form>
|
||||
<p class="cseltitle">Ultraviolet Proxy Transport</p>
|
||||
<div class="radio-group" id=uv-transport-list>
|
||||
<div class="radio-group" id="uv-transport-list">
|
||||
<label>
|
||||
<p>Libcurl <span class="default-badge">Cross-Browser/Secure (Firefox)</span></p>
|
||||
<input type="radio" name="uv-transport" value="libcurl" checked>
|
||||
<p>
|
||||
Libcurl
|
||||
<span class="default-badge">Cross-Browser/Secure (Firefox)</span>
|
||||
</p>
|
||||
<input type="radio" name="uv-transport" value="libcurl" checked />
|
||||
</label>
|
||||
<label>
|
||||
<p>Epoxy <span class="bare-badge">Fastest/Secure (Chromium, Apple)</span></p>
|
||||
<input type="radio" name="uv-transport" value="epoxy">
|
||||
<p>
|
||||
Epoxy
|
||||
<span class="bare-badge">Fastest/Secure (Chromium, Apple)</span>
|
||||
</p>
|
||||
<input type="radio" name="uv-transport" value="epoxy" />
|
||||
</label>
|
||||
<label>
|
||||
<p>Bare <span class="beta-badge">Least Secure (All)</span></p>
|
||||
<input type="radio" name="uv-transport" value="bare">
|
||||
<input type="radio" name="uv-transport" value="bare" />
|
||||
</label>
|
||||
</div>
|
||||
<p class="cseltitle">Advanced Options</p>
|
||||
<div class="radio-group">
|
||||
<label>
|
||||
<p>Hide Ads <span class="default-badge">AdGuard</span></p>
|
||||
<input type="checkbox" id="hideads" class="switch" checked>
|
||||
<input type="checkbox" id="hideads" class="switch" checked />
|
||||
</label>
|
||||
<label>
|
||||
<p>Enable Tor <span class="bare-badge">SOCKS5 Onion Routing</span></p>
|
||||
<input type="checkbox" id="useonion" class="switch">
|
||||
<input type="checkbox" id="useonion" class="switch" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -52,21 +58,21 @@
|
|||
<p class="cseltitle">About:Blank</p>
|
||||
<div class="switch-container">
|
||||
<p>Stealth Tab <span class="default-badge">Default</span></p>
|
||||
<input type="checkbox" class="switch">
|
||||
<input type="checkbox" class="switch" />
|
||||
</div>
|
||||
<p class="cseltitle">Select Theme</p>
|
||||
<div class="radio-group">
|
||||
<label>
|
||||
<p>Light</p>
|
||||
<input type="radio" name="theme" value="lighttheme" checked>
|
||||
<input type="radio" name="theme" value="lighttheme" checked />
|
||||
</label>
|
||||
<label>
|
||||
<p>Dark</p>
|
||||
<input type="radio" name="theme" value="darktheme">
|
||||
<input type="radio" name="theme" value="darktheme" />
|
||||
</label>
|
||||
</div>
|
||||
<p class="cseltitle">Icon Presets</p>
|
||||
<select id=icon-list>
|
||||
<select id="icon-list">
|
||||
<option><!-- Leave this blank to avoid a bug. --></option>
|
||||
<option>Google</option>
|
||||
<option>Bing</option>
|
||||
|
@ -77,7 +83,7 @@
|
|||
<div class="radio-group">
|
||||
<label>
|
||||
<p>Eruda Devtools<span class="bare-badge">CTRL+SHIFT+I</span></p>
|
||||
<input type="radio" name="theme" value="lighttheme" checked>
|
||||
<input type="radio" name="theme" value="lighttheme" checked />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<div id="particles-js" class="fullwidth"></div>
|
||||
<div id="mainbody" class="fullwidth">
|
||||
<div class="box-g text-center textm">
|
||||
<div id=emu-nav class=glist></div>
|
||||
<div id="emu-nav" class="glist"></div>
|
||||
<div class="gfooter">
|
||||
<p>I promise I'll fix N64 and add DS soon ._.</p>
|
||||
</div>
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<div id="particles-js" class="fullwidth"></div>
|
||||
<div id="mainbody" class="fullwidth">
|
||||
<div class="box-g text-center textm">
|
||||
<div id=emulib-nav class=glist></div>
|
||||
<div id="emulib-nav" class="glist"></div>
|
||||
<div class="gfooter">
|
||||
<p>
|
||||
Have a game request? Contact us on <a id="tnlink">discord</a> or
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
autocomplete="off"
|
||||
placeholder="Search"
|
||||
/>
|
||||
<div id=flash-nav class=flist></div>
|
||||
<div id="flash-nav" class="flist"></div>
|
||||
<div class="gfooter-only">
|
||||
<p>
|
||||
Have a game request? Contact us on <a id="tnlink">discord</a> or
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<div id="particles-js" class="fullwidth"></div>
|
||||
<div id="mainbody" class="fullwidth">
|
||||
<div class="box-g text-center textm">
|
||||
<div id=h5-nav class=glist></div>
|
||||
<div id="h5-nav" class="glist"></div>
|
||||
<div class="gfooter">
|
||||
<p>
|
||||
Have a game request? Contact us on <a id="tnlink">discord</a> or
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById("iconfinder").href =
|
||||
document.getElementById('iconfinder').href =
|
||||
`javascript:alert((Array.from(document.head.querySelectorAll("link[rel*='icon']")).slice(-1)[0]||0).href||location.origin+"/favicon.ico")`;
|
||||
</script>
|
||||
<p>
|
||||
|
|
|
@ -90,13 +90,24 @@
|
|||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<div id=pr-rh-dc>
|
||||
<a href="#" class="fancybutton glowbutton pr-go1">Ra­mmer­head (Classic)</a>
|
||||
<a href="#" class="fancybutton glowbutton pr-go2">Ra­mmer­head (Stealth)</a>
|
||||
<div id="pr-rh-dc">
|
||||
<a href="#" class="fancybutton glowbutton pr-go1"
|
||||
>Ra­mmer­head (Classic)</a
|
||||
>
|
||||
<a href="#" class="fancybutton glowbutton pr-go2"
|
||||
>Ra­mmer­head (Stealth)</a
|
||||
>
|
||||
</div>
|
||||
<div id=pr-uv-dc>
|
||||
<a href="#" style="display:none;" class="fancybutton glowbutton pr-go1">Ultr­av­iol­et (Classic)</a>
|
||||
<a href="#" class="fancybutton glowbutton pr-go2">Ultr­avi­ole­t (Stealth)</a>
|
||||
<div id="pr-uv-dc">
|
||||
<a
|
||||
href="#"
|
||||
style="display: none"
|
||||
class="fancybutton glowbutton pr-go1"
|
||||
>Ultr­av­iol­et (Classic)</a
|
||||
>
|
||||
<a href="#" class="fancybutton glowbutton pr-go2"
|
||||
>Ultr­avi­ole­t (Stealth)</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -57,8 +57,13 @@
|
|||
<br />Sometimes the proxies are under high load so things may be slow,
|
||||
sorry. In that case simply wait for the page to load.
|
||||
</p>
|
||||
<div id=pr-yt class="responsive-fix">
|
||||
<a href="#" style="display:none;" class="fancybutton glowbutton pr-go1">Classic</a>
|
||||
<div id="pr-yt" class="responsive-fix">
|
||||
<a
|
||||
href="#"
|
||||
style="display: none"
|
||||
class="fancybutton glowbutton pr-go1"
|
||||
>Classic</a
|
||||
>
|
||||
<a href="#" class="fancybutton glowbutton pr-go2">Stealth</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
Its session-based proxying concept enables much support for webites
|
||||
like Discord, YouTube, and more!
|
||||
</p>
|
||||
<div id=pr-rh class="pr-form">
|
||||
<div id="pr-rh" class="pr-form">
|
||||
<input
|
||||
type="text"
|
||||
spellcheck="false"
|
||||
|
|
|
@ -55,15 +55,17 @@
|
|||
such as service workers and sophisticated rewriting techniques with
|
||||
CAPTCHA support.
|
||||
</p>
|
||||
<div id=pr-uv class="pr-form">
|
||||
<div id="pr-uv" class="pr-form">
|
||||
<input
|
||||
type="text"
|
||||
spellcheck="false"
|
||||
autocomplete="off"
|
||||
placeholder="Search or enter in a target site!"
|
||||
/>
|
||||
<a href="#" style="display:none;" class="pr-button glowbutton pr-go1">Stea­lth</a>
|
||||
<a href="#"" class="pr-button glowbutton pr-go2">Stea­lth</a>
|
||||
<a href="#" style="display: none" class="pr-button glowbutton pr-go1"
|
||||
>Stea­lth</a
|
||||
>
|
||||
<a href="#" class="pr-button glowbutton pr-go2">Stea­lth</a>
|
||||
</div>
|
||||
<h3>More Information:</h3>
|
||||
<div class="font3">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
|
|
@ -7,6 +7,6 @@
|
|||
class WWError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "[WorkerWare Exception]";
|
||||
this.name = '[WorkerWare Exception]';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
importScripts("/uv/uv.bundle.js");
|
||||
importScripts("/uv/uv.config.js");
|
||||
importScripts(__uv$config.sw || "/uv/uv.sw.js");
|
||||
importScripts('/uv/uv.bundle.js');
|
||||
importScripts('/uv/uv.config.js');
|
||||
importScripts(__uv$config.sw || '/uv/uv.sw.js');
|
||||
|
||||
/*
|
||||
|
||||
|
@ -28,53 +28,54 @@ ww.use({
|
|||
|
||||
*/
|
||||
|
||||
|
||||
const uv = new UVServiceWorker();
|
||||
|
||||
// Get list of blacklisted domains.
|
||||
const blacklist = {};
|
||||
fetch("/assets/json/blacklist.json").then(request => {
|
||||
request.json().then(jsonData => {
|
||||
fetch('/assets/json/blacklist.json').then((request) => {
|
||||
request.json().then((jsonData) => {
|
||||
// Organize each domain by their tld (top level domain) ending.
|
||||
jsonData.forEach((domain) => {
|
||||
const domainTld = domain.replace(/.+(?=\.\w)/, '');
|
||||
if (!blacklist.hasOwnProperty(domainTld)) blacklist[domainTld] = [];
|
||||
|
||||
// Organize each domain by their tld (top level domain) ending.
|
||||
jsonData.forEach(domain => {
|
||||
const domainTld = domain.replace(/.+(?=\.\w)/, "");
|
||||
if (!blacklist.hasOwnProperty(domainTld))
|
||||
blacklist[domainTld] = [];
|
||||
|
||||
// Store each entry in an array. Each tld has its own array, which will
|
||||
// later be concatenated into a regular expression.
|
||||
// Store each entry in an array. Each tld has its own array, which will
|
||||
// later be concatenated into a regular expression.
|
||||
blacklist[domainTld].push(
|
||||
encodeURIComponent(domain.slice(0, -domainTld.length))
|
||||
.replace(/([()])/g, "\\$1")
|
||||
.replace(/([()])/g, '\\$1')
|
||||
.replace(/(\*\.)|\./g, (match, firstExpression) =>
|
||||
firstExpression ? "(?:.+\\.)?" : "\\" + match)
|
||||
firstExpression ? '(?:.+\\.)?' : '\\' + match
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
// Turn each domain list into a regular expression and prevent this
|
||||
// from being accidentally modified afterward.
|
||||
// Turn each domain list into a regular expression and prevent this
|
||||
// from being accidentally modified afterward.
|
||||
for (let [domainTld, domainList] of Object.entries(blacklist))
|
||||
blacklist[domainTld] = new RegExp(`^(?:${domainList.join("|")})$`);
|
||||
blacklist[domainTld] = new RegExp(`^(?:${domainList.join('|')})$`);
|
||||
Object.freeze(blacklist);
|
||||
});
|
||||
});
|
||||
|
||||
self.addEventListener("fetch", (event) => {
|
||||
self.addEventListener('fetch', (event) => {
|
||||
event.respondWith(
|
||||
(async () => {
|
||||
if (uv.route(event)) {
|
||||
// The one and only ghetto domain blacklist.
|
||||
const domain = new URL(uv.config.decodeUrl(
|
||||
new URL(event.request.url).pathname
|
||||
.replace(uv.config.prefix, "")
|
||||
)).hostname,
|
||||
domainTld = domain.replace(/.+(?=\.\w)/, "");
|
||||
// The one and only ghetto domain blacklist.
|
||||
const domain = new URL(
|
||||
uv.config.decodeUrl(
|
||||
new URL(event.request.url).pathname.replace(uv.config.prefix, '')
|
||||
)
|
||||
).hostname,
|
||||
domainTld = domain.replace(/.+(?=\.\w)/, '');
|
||||
|
||||
// If the domain is in the blacklist, return a 406 response code.
|
||||
if (blacklist.hasOwnProperty(domainTld) &&
|
||||
blacklist[domainTld].test(domain.slice(0, -domainTld.length)))
|
||||
return new Response(new Blob(), {status: 406});
|
||||
// If the domain is in the blacklist, return a 406 response code.
|
||||
if (
|
||||
blacklist.hasOwnProperty(domainTld) &&
|
||||
blacklist[domainTld].test(domain.slice(0, -domainTld.length))
|
||||
)
|
||||
return new Response(new Blob(), { status: 406 });
|
||||
|
||||
return await uv.fetch(event);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
importScripts("/uv/uv.bundle.js");
|
||||
importScripts("/uv/uv.config.js");
|
||||
importScripts(__uv$config.sw || "/uv/uv.sw.js");
|
||||
|
||||
importScripts('/uv/uv.bundle.js');
|
||||
importScripts('/uv/uv.config.js');
|
||||
importScripts(__uv$config.sw || '/uv/uv.sw.js');
|
||||
|
||||
const uv = new UVServiceWorker();
|
||||
|
||||
self.addEventListener("fetch", (event) => {
|
||||
self.addEventListener('fetch', (event) => {
|
||||
event.respondWith(
|
||||
(async () => {
|
||||
if (uv.route(event)) return await uv.fetch(event);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// This file overwrites the stock UV config.js
|
||||
|
||||
self.__uv$config = {
|
||||
prefix: "/uv/service/",
|
||||
prefix: '/uv/service/',
|
||||
encodeUrl: Ultraviolet.codec.xor.encode,
|
||||
decodeUrl: Ultraviolet.codec.xor.decode,
|
||||
handler: "/uv/uv.handler.js",
|
||||
client: "/uv/uv.client.js",
|
||||
bundle: "/uv/uv.bundle.js",
|
||||
config: "/uv/uv.config.js",
|
||||
sw: "/uv/uv.sw.js",
|
||||
handler: '/uv/uv.handler.js',
|
||||
client: '/uv/uv.client.js',
|
||||
bundle: '/uv/uv.bundle.js',
|
||||
config: '/uv/uv.config.js',
|
||||
sw: '/uv/uv.sw.js',
|
||||
};
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
/* Service Worker Middleware Script
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
importScripts("./WWError.js");
|
||||
const dbg = console.log.bind(console, "[WorkerWare]");
|
||||
const time = console.time.bind(console, "[WorkerWare]");
|
||||
const timeEnd = console.timeEnd.bind(console, "[WorkerWare]");
|
||||
importScripts('./WWError.js');
|
||||
const dbg = console.log.bind(console, '[WorkerWare]');
|
||||
const time = console.time.bind(console, '[WorkerWare]');
|
||||
const timeEnd = console.timeEnd.bind(console, '[WorkerWare]');
|
||||
|
||||
/*
|
||||
OPTS:
|
||||
|
@ -23,26 +23,26 @@ const defaultOpt = {
|
|||
};
|
||||
|
||||
const validEvents = [
|
||||
"abortpayment",
|
||||
"activate",
|
||||
"backgroundfetchabort",
|
||||
"backgroundfetchclick",
|
||||
"backgroundfetchfail",
|
||||
"backgroundfetchsuccess",
|
||||
"canmakepayment",
|
||||
"contentdelete",
|
||||
"cookiechange",
|
||||
"fetch",
|
||||
"install",
|
||||
"message",
|
||||
"messageerror",
|
||||
"notificationclick",
|
||||
"notificationclose",
|
||||
"paymentrequest",
|
||||
"periodicsync",
|
||||
"push",
|
||||
"pushsubscriptionchange",
|
||||
"sync",
|
||||
'abortpayment',
|
||||
'activate',
|
||||
'backgroundfetchabort',
|
||||
'backgroundfetchclick',
|
||||
'backgroundfetchfail',
|
||||
'backgroundfetchsuccess',
|
||||
'canmakepayment',
|
||||
'contentdelete',
|
||||
'cookiechange',
|
||||
'fetch',
|
||||
'install',
|
||||
'message',
|
||||
'messageerror',
|
||||
'notificationclick',
|
||||
'notificationclose',
|
||||
'paymentrequest',
|
||||
'periodicsync',
|
||||
'push',
|
||||
'pushsubscriptionchange',
|
||||
'sync',
|
||||
];
|
||||
|
||||
class WorkerWare {
|
||||
|
@ -52,7 +52,7 @@ class WorkerWare {
|
|||
}
|
||||
info() {
|
||||
return {
|
||||
version: "0.1.0",
|
||||
version: '0.1.0',
|
||||
middlewares: this._middlewares,
|
||||
options: this._opt,
|
||||
};
|
||||
|
@ -61,10 +61,11 @@ class WorkerWare {
|
|||
let validateMW = this.validateMiddleware(middleware);
|
||||
if (validateMW.error) throw new WWError(validateMW.error);
|
||||
// This means the middleware is an anonymous function, or the user is silly and named their function "function"
|
||||
if (middleware.function.name == "function") middleware.name = crypto.randomUUID();
|
||||
if (middleware.function.name == 'function')
|
||||
middleware.name = crypto.randomUUID();
|
||||
if (!middleware.name) middleware.name = middleware.function.name;
|
||||
if (this._opt.randomNames) middleware.name = crypto.randomUUID();
|
||||
if (this._opt.debug) dbg("Adding middleware:", middleware.name);
|
||||
if (this._opt.debug) dbg('Adding middleware:', middleware.name);
|
||||
this._middlewares.push(middleware);
|
||||
}
|
||||
// Run all middlewares for the event type passed in.
|
||||
|
@ -91,12 +92,16 @@ class WorkerWare {
|
|||
return fn;
|
||||
}
|
||||
deleteByName(middlewareID) {
|
||||
if (this._opt.debug) dbg("Deleting middleware:", middlewareID);
|
||||
this._middlewares = this._middlewares.filter((mw) => mw.name !== middlewareID);
|
||||
if (this._opt.debug) dbg('Deleting middleware:', middlewareID);
|
||||
this._middlewares = this._middlewares.filter(
|
||||
(mw) => mw.name !== middlewareID
|
||||
);
|
||||
}
|
||||
deleteByEvent(middlewareEvent) {
|
||||
if (this._opt.debug) dbg("Deleting middleware by event:", middlewareEvent);
|
||||
this._middlewares = this._middlewares.filter((mw) => !mw.events.includes(middlewareEvent));
|
||||
if (this._opt.debug) dbg('Deleting middleware by event:', middlewareEvent);
|
||||
this._middlewares = this._middlewares.filter(
|
||||
(mw) => !mw.events.includes(middlewareEvent)
|
||||
);
|
||||
}
|
||||
get() {
|
||||
return this._middlewares;
|
||||
|
@ -107,7 +112,7 @@ class WorkerWare {
|
|||
*/
|
||||
runMW(name, event) {
|
||||
const middlewares = this._middlewares;
|
||||
if (this._opt.debug) dbg("Running middleware:", name);
|
||||
if (this._opt.debug) dbg('Running middleware:', name);
|
||||
// if (middlewares.includes(name)) {
|
||||
// return middlewares[name](event);
|
||||
// } else {
|
||||
|
@ -119,7 +124,7 @@ class WorkerWare {
|
|||
didCall = true;
|
||||
event.workerware = {
|
||||
config: middlewares[i].configuration || {},
|
||||
}
|
||||
};
|
||||
if (this._opt.timing) console.time(middlewares[i].name);
|
||||
let call = middlewares[i].function(event);
|
||||
if (this._opt.timing) console.timeEnd(middlewares[i].name);
|
||||
|
@ -127,7 +132,7 @@ class WorkerWare {
|
|||
}
|
||||
}
|
||||
if (!didCall) {
|
||||
throw new WWError("Middleware not found!");
|
||||
throw new WWError('Middleware not found!');
|
||||
}
|
||||
}
|
||||
// type middlewareManifest = {
|
||||
|
@ -139,32 +144,40 @@ class WorkerWare {
|
|||
validateMiddleware(middleware) {
|
||||
if (!middleware.function)
|
||||
return {
|
||||
error: "middleware.function is required",
|
||||
error: 'middleware.function is required',
|
||||
};
|
||||
if (typeof middleware.function !== "function")
|
||||
if (typeof middleware.function !== 'function')
|
||||
return {
|
||||
error: "middleware.function must be typeof function",
|
||||
error: 'middleware.function must be typeof function',
|
||||
};
|
||||
if (typeof middleware.configuration !== "object" && middleware.configuration !== undefined) {
|
||||
if (
|
||||
typeof middleware.configuration !== 'object' &&
|
||||
middleware.configuration !== undefined
|
||||
) {
|
||||
return {
|
||||
error: "middleware.configuration must be typeof object",
|
||||
error: 'middleware.configuration must be typeof object',
|
||||
};
|
||||
}
|
||||
if (!middleware.events)
|
||||
return {
|
||||
error: "middleware.events is required",
|
||||
error: 'middleware.events is required',
|
||||
};
|
||||
if (!Array.isArray(middleware.events))
|
||||
return {
|
||||
error: "middleware.events must be an array",
|
||||
error: 'middleware.events must be an array',
|
||||
};
|
||||
if (middleware.events.some((ev) => !validEvents.includes(ev)))
|
||||
return {
|
||||
error: "Invalid event type! Must be one of the following: " + validEvents.join(", "),
|
||||
error:
|
||||
'Invalid event type! Must be one of the following: ' +
|
||||
validEvents.join(', '),
|
||||
};
|
||||
if (middleware.explicitCall && typeof middleware.explicitCall !== "boolean") {
|
||||
if (
|
||||
middleware.explicitCall &&
|
||||
typeof middleware.explicitCall !== 'boolean'
|
||||
) {
|
||||
return {
|
||||
error: "middleware.explicitCall must be typeof boolean",
|
||||
error: 'middleware.explicitCall must be typeof boolean',
|
||||
};
|
||||
}
|
||||
return {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue