Compare commits

...

335 commits
v2.0 ... main

Author SHA1 Message Date
wearrrrr
218155a00b Upgrade epoxy transport to try and narrow down the issue, still didn't fix but it should hopefully be fixed soon. 2024-12-03 14:58:52 -06:00
wearrrrr
58e7cb118e Upgrade to astro 5, for some reason epoxy is broken now? 2024-12-03 14:55:03 -06:00
wearrrrr
cef106b512 Add the ability to pin games on the games page. 2024-11-29 15:42:35 -06:00
wearrrrr
3d45aa6e66 remove the use of color-mix 2024-11-26 23:26:15 -06:00
wearrrrr
27c2c42df8 Add a donate page 2024-11-24 16:38:05 -06:00
wearrrrr
0f9befb6a6 this doesn't need to be optional I think 2024-11-24 00:43:44 -06:00
wearrrrr
10ac39b46f General code refactoring, move Notyf code into toast.ts 2024-11-24 00:42:35 -06:00
wearrrrr
5fc3995257 refactor: make the ExtensionMetadata interface much less cluttered by having other interfaces extend off of it. 2024-11-20 20:30:31 -06:00
wearrrrr
a05e112de9 Add eruda plugin, stylize navbar elements to be better, and patch some issues with marketplace manifests 2024-11-20 19:56:56 -06:00
wearrrrr
b0760dd553 add reload button 2024-11-20 18:31:04 -06:00
wearrrrr
a4efd90c0d will exempt_masqr work this time 2024-11-19 21:08:47 -06:00
wearrrrr
18540bf5c9 implement private masqr exemptions 2024-11-19 13:21:42 -06:00
wearrrrr
8ac7847122 properly disable @typescript-eslint/no-explicit-any 2024-10-28 00:06:30 -05:00
wearrrrr
960863a5a2 make it a little more concise, run prettier. 2024-10-27 22:28:44 -05:00
wearrrrr
f7ad2e3ba0 Define an addEventListener overload in alu.d.ts to prevent an annoying cast in settings.ts 2024-10-27 22:27:02 -05:00
wearrrrr
c819bce83e forgot to add dotenv-flow to the config file 2024-10-27 22:07:53 -05:00
wearrrrr
6d4c10dc21 Add back support for custom wisp urls, that took forever. 2024-10-27 22:04:28 -05:00
wearrrrr
7038f5f9ec wisp-js migration 2: electric boogaloo 2024-10-27 19:51:41 -05:00
wearrrrr
b6850af1ca revert epoxy back to 2.1.13 until we can figure out wtf is happening 2024-10-27 19:45:44 -05:00
wearrrrr
900d5e6272 switch to wisp-js 2024-10-27 19:19:13 -05:00
wearr
7dafacc43c
Merge pull request #28 from 3kho/main
Adding fonts to elements and more
2024-10-23 17:14:45 -05:00
Echo
f0dd3c9e46
Tiny grammar fixes 2024-10-12 17:34:06 -04:00
Echo
8e05734ee6
Add alt text for image 2024-10-12 17:27:29 -04:00
Echo
3005c96139
Add font to marketplace and cloaking 2024-10-12 17:27:21 -04:00
Echo
4ad7ae80cd
Combine all debug info into one statement 2024-10-12 17:26:15 -04:00
Echo
4cef641dbd
Update packages 2024-10-12 17:26:05 -04:00
Echo
95c2bb0ae6
Add font to inputs 2024-10-12 17:25:52 -04:00
wearrrrr
4ce7d5a065 Refactor, move some fa icons to dedicated components. Eventually get rid of fontawesome css hopefully. 2024-10-11 20:26:07 -05:00
wearrrrr
9a48ae3416 Better error handler 2024-10-04 12:09:51 -05:00
wearrrrr
7526623ce0 Add error catcher to Alu's server 2024-10-04 11:43:28 -05:00
wearrrrr
859d84969f readd localhost into whitelistedDomains 2024-10-03 21:03:43 -05:00
wearrrrr
8d0d1d1116 Fix masqr 2024-10-03 21:03:04 -05:00
wearrrrr
0ad5812cd3 Update games submodule, adds slope plus and a better version of regular slope. 2024-10-01 22:42:53 -05:00
wearrrrr
4b6614f952 Update Alu logo colors, and fix background in macchiato and mocha themes. 2024-09-30 23:02:28 -05:00
wearr
7be231fa31
Merge pull request #25 from 3kho/main
Fix 404 Page
2024-09-30 22:28:12 -05:00
Echo
e1d17b9345
Fix 404 page 2024-09-25 22:30:32 -04:00
Echo
6f85fafa6a
Prettier formatting 2024-09-25 22:30:18 -04:00
wearrrrr
3efee9b98d Update atom-one-dark logo 2024-09-22 10:41:21 -05:00
wearrrrr
f2839a035d some css changes 2024-09-22 10:36:23 -05:00
wearrrrr
9f0bf7c32b Fix the sitemap up a little bit. 2024-09-20 11:44:54 -05:00
wearrrrr
a921fbe4ad Move to @inox-tools/sitemap-ext, Now dynamic routes generate in the sitemap also :D 2024-09-20 11:21:36 -05:00
wearrrrr
237038cdea sitemap testing 2024-09-20 10:42:35 -05:00
wearrrrr
b3c04f1227 Update masqr middleware to use req.hostname instead of req.headers.host 2024-09-20 10:34:01 -05:00
wearrrrr
216d93c429 Change alt attribute 2024-09-19 13:19:19 -05:00
wearrrrr
be7edf5fcc Add descriptions to all games 2024-09-19 13:18:08 -05:00
wearrrrr
075ae062db Add several flash games to manifest, update games submodule. 2024-09-14 20:23:33 -05:00
wearrrrr
f6658cf533 Add some descriptions 2024-09-14 01:21:42 -05:00
wearrrrr
fc65ac0b9b Update games submodule 2024-09-14 01:15:33 -05:00
wearrrrr
97757441d8 Update games submodule 2024-09-14 01:13:22 -05:00
wearrrrr
1b3f2c4ffd Update games submodule 2024-09-14 01:10:50 -05:00
wearrrrr
b24b097994 small changes 2024-09-14 00:39:17 -05:00
wearrrrr
7da9869597 remove sass 2024-09-14 00:25:06 -05:00
wearrrrr
acf34d732d Move sass to dev dependency 2024-09-13 11:27:18 -05:00
wearrrrr
0339060ae9 Fix some css issues, add FaqCard component 2024-09-13 11:26:50 -05:00
wearrrrr
791c74672e Fix schema data 2024-09-13 02:32:38 -05:00
wearrrrr
268ba43869 Add schema data to proper index 2024-09-13 02:31:16 -05:00
wearrrrr
341565236f Add schema data 2024-09-13 02:29:26 -05:00
wearrrrr
1dc6481706 oops 2024-09-13 02:17:06 -05:00
wearrrrr
d83770ce3a Turns out fade in animations break lighthouse ;-; 2024-09-13 02:14:33 -05:00
wearrrrr
807064fa2f remove nanostores from package.json 2024-09-13 02:05:29 -05:00
wearrrrr
e849ea895f Repurpose optionalPreloads into optionalStylesheets, now only pages that need it will request it. 2024-09-13 02:05:02 -05:00
wearrrrr
20b7be723a Large CSS Refactor, adding a nice background detail :) 2024-09-13 00:04:58 -05:00
wearrrrr
064916b3b4 attempt 3 2024-09-12 20:45:22 -05:00
wearrrrr
623e30cc0b attempt 2 2024-09-12 20:44:32 -05:00
wearrrrr
4d28b54ced Potentially fix settings race condition 2024-09-12 20:42:02 -05:00
wearrrrr
eaa683a77e Update css 2024-09-12 20:40:10 -05:00
wearrrrr
bb5516af4e I probably should not have removed cookie-parser 2024-09-12 20:24:59 -05:00
wearrrrr
53a92c0016 add a reset button 2024-09-11 14:22:49 -05:00
wearrrrr
26ffd13f2b bump bare-mux 2024-09-11 14:00:48 -05:00
wearrrrr
b365acb7cc oops one more thing 2024-09-11 13:58:30 -05:00
wearrrrr
ec0171f0a4 oh my god 2024-09-11 13:55:52 -05:00
wearrrrr
ea226a01ff maybe? 2024-09-11 13:53:42 -05:00
wearrrrr
193cccecaa update more modules 2024-09-11 13:52:37 -05:00
wearrrrr
a9866208b4 add error logging in setTransport 2024-09-11 13:44:24 -05:00
wearrrrr
0c74bc1353 oops found the crash 2024-09-11 13:41:42 -05:00
wearrrrr
008da91719 Update masqr middleware, hopefully prevent crashes? 2024-09-11 13:40:02 -05:00
wearrrrr
0430b040d0 Update some deps 2024-09-11 13:28:53 -05:00
wearrrrr
c4e16dd2a6 Remove vencord from plugins list 2024-09-11 13:12:33 -05:00
wearrrrr
0e5c6af2b9 Update rammerhead 2024-08-23 03:52:53 -05:00
wearrrrr
d2b8adc40c Migrate to dotenv-flow 2024-08-22 19:33:54 -05:00
wearrrrr
025d2c58ae WIP Marketplace Provider middleware (server side), and add a kinda scuffed version of vencord. 2024-08-20 19:57:33 -05:00
wearrrrr
96267e5878 Migrate to ruby network's rammerhead. Create a banner for Alu Adblock 2024-08-13 22:29:25 -05:00
wearrrrr
e02e5f1cfc Make marketplace cards look better 2024-08-08 17:06:37 -05:00
wearrrrr
e3f1f1e4f0 okay *now* the images should be actually 16 / 9 2024-08-08 02:38:42 -05:00
wearrrrr
e7f7ac68dc Change how marketplace images work, they should now be 16 / 9 instead of 64x64. 2024-08-08 02:32:41 -05:00
wearrrrr
87504ad409 Overhaul the visual UI of marketplace 2024-08-07 21:49:23 -05:00
wearrrrr
b0ae707ce2 set min-height on Card component 2024-08-07 19:35:44 -05:00
wearrrrr
0765072ea2 Move the window global in settings.ts to Alu.settings 2024-08-06 23:17:17 -05:00
wearrrrr
255488ad16 Fix issue with utils.ts throwing type error. 2024-08-06 23:00:20 -05:00
wearrrrr
6e06134b77 Create Alu.ts, and add support for DDG as a search engine. 2024-08-06 03:08:54 -05:00
wearrrrr
2f5a65cc3e Refactor how AluStore handles the search parameter, and refactor settings.ts 2024-08-05 23:24:57 -05:00
wearrrrr
26797b6ee6 Rename mocha and macchiato i18n key to just catppuccin, only add eng translation. Move settings code to settings.ts, and fix links in credits page. 2024-08-04 01:46:43 -05:00
wearrrrr
e0a8eb0dd4 Add clever and edgenuity cloaks 2024-08-03 20:43:05 -05:00
wearrrrr
ad2cbbc98a Update some icons, make input placeholders use accented text color. 2024-08-01 22:55:37 -05:00
wearrrrr
8332c191d2 Nearly completely refactor how the settings UI looks, and ensure mobile responsiveness. Slightly clean up code and run prettier. 2024-08-01 19:34:25 -05:00
wearrrrr
92f23fb7c6 Add a vencord injection, commented out for now. 2024-08-01 16:15:39 -05:00
wearrrrr
4674bd182e Completely migrate settings.astro to use typescript instead of inline JS for it's logic. 2024-07-30 04:41:29 -05:00
wearrrrr
554c3a695d epic fail (namespace doesn't load fast enough) 2024-07-30 04:10:52 -05:00
wearrrrr
73077c7565 Migrate window.loadedContentStorage and window.currentlySelectedTab to Alu namespace vars. 2024-07-30 04:01:36 -05:00
wearrrrr
2fc7f56b47 Make the loading content text better and much less hacky, also revert ExtensionMetadata type name back from IExtensionMetadata. 2024-07-29 23:16:49 -05:00
wearr
f2fcf29317
Update README.md 2024-07-29 20:22:17 -05:00
wearrrrr
6754ab22da Add the item version in the marketplace page. 2024-07-29 20:07:36 -05:00
wearrrrr
977f723614 Add synthwave '84 and atom one dark 2024-07-29 20:05:59 -05:00
wearrrrr
88fa88c623 Add nord theme to marketplace 2024-07-29 19:37:16 -05:00
wearrrrr
e6b1d52987 Fully migrate to Alu.store 2024-07-29 19:30:30 -05:00
wearrrrr
d41b427266 Begin migration to Alu.store.get for fetching values, stored in global Alu namespace. 2024-07-29 18:52:09 -05:00
wearrrrr
5a48e2d71e No comma needed lol 2024-07-29 14:30:05 -05:00
wearrrrr
ab3049dd84 Move to dynamically creating STATIC_PATHS, instead of it being static, and integrate spanish fully 2024-07-29 14:27:46 -05:00
wearr
311a8e649e
Merge pull request #23 from builtbyvys/feat/translation-es_EN
feat: add spanish translation
2024-07-29 14:13:25 -05:00
vys
af4856498c
bugfix: fixed invalid json
missing end quote at line 21
2024-07-29 15:12:43 -04:00
vys
2a127f06e2
Fix capitalization to reflect original text
"SearX" is changed to "Searx"
2024-07-29 13:28:49 -04:00
vys
415841ee35
Fix typo with "ultraviolet"
Changed from "ultravioletz" to "ultraviolet"
2024-07-29 13:28:07 -04:00
vys
e4e4bbee09
Add spanish translation 2024-07-29 13:27:21 -04:00
wearrrrr
b617851141 I plead oopsie daisy 2024-07-29 03:44:58 -05:00
wearrrrr
2365bc19dc Add canonical tag 2024-07-29 03:44:04 -05:00
wearrrrr
14d2f8e956 Add AluStore, will do more with this soon 2024-07-29 00:43:07 -05:00
wearrrrr
90e5bbb7f2 Format settings code nicer and run prettier 2024-07-28 22:31:52 -05:00
wearrrrr
33e80ef1eb Add 4 new games, add vertical property to metada, and update games page 2024-07-28 21:13:43 -05:00
wearrrrr
e7aa57adcb Move themes into their own style tag in Layout.astro 2024-07-27 21:22:36 -05:00
wearrrrr
0fe23c7020 Fix bug with IDB, it should be much more stable now 2024-07-27 19:05:01 -05:00
wearrrrr
09914ab8f7 Update "there are no bare clients" translation 2024-07-27 18:47:56 -05:00
wearr
900a604f5a
Merge pull request #22 from notboeing747/main
Consistency change
2024-07-27 18:44:35 -05:00
notboeing747
55a0c620b4
Consistency change 2024-07-27 12:01:29 -04:00
wearr
954c375a5f
Merge pull request #21 from 3kho/main
Add Chinese and Russian Translations
2024-07-27 03:10:00 -05:00
Echo
8cb071bb0b
Merge branch 'main' into main 2024-07-27 04:05:27 -04:00
Echo
8e847df600
Apply Prettier formatting 2024-07-27 04:02:41 -04:00
Echo
850977b6ec
Update packages for pnpm 2024-07-27 04:00:53 -04:00
Echo
ae0177959f
Update packages for npm 2024-07-27 04:00:36 -04:00
Echo
2254f6e639
Add Chinese and Russian Translation credits 2024-07-27 03:53:37 -04:00
Echo
f761393a99
Add Chinese and Russian Translations 2024-07-27 03:53:26 -04:00
wearrrrr
3806d64f66 Make eslint a bit stricter, and lint + format. 2024-07-27 01:47:25 -05:00
wearr
622855db01
Merge pull request #20 from notboeing747/main
I swear this is the last mistake lmao
2024-07-27 00:42:34 -05:00
notboeing747
aaa6334561
Merge branch 'titaniumnetwork-dev:main' into main 2024-07-27 00:29:45 -04:00
notboeing747
1da4dd3ec9
supvent 🧠 2024-07-27 00:28:15 -04:00
wearrrrr
adab5005ad Update patreon link 2024-07-26 23:26:20 -05:00
wearr
5eb2ec5f6e
Merge pull request #19 from notboeing747/main
Fixed punctuation
2024-07-26 23:24:35 -05:00
wearrrrr
92952437d8 I was being really dumb about how different languages were handled, should be better now :D 2024-07-26 23:23:39 -05:00
notboeing747
1e094d1a79
Fixed punctuation 2024-07-27 00:20:40 -04:00
wearrrrr
00ed3fe3b4 Credit french translator, fix up dracula theme slightly, and mitigate a bug causing addThemeToDropdown to get called repeatedly. 2024-07-26 23:12:22 -05:00
wearr
67e7fcf72d
Merge pull request #18 from notboeing747/main
Translate Alu into French
2024-07-26 22:33:18 -05:00
notboeing747
a3a9f2c84f
finished translating into french 2024-07-26 23:16:33 -04:00
notboeing747
2ff4ed096c
Update fr.json 2024-07-26 22:53:29 -04:00
notboeing747
bd1f8c6ced
Update fr.json 2024-07-26 22:45:09 -04:00
notboeing747
4823932aea
qucksave 2024-07-26 22:38:17 -04:00
notboeing747
00ed00b0d9
ugh I don't wanna do faq 2024-07-26 22:15:38 -04:00
notboeing747
6aec8c3e3f
More shit I don't wanna lose progress 2024-07-26 22:13:47 -04:00
notboeing747
69881c3dd7
Random translations 2024-07-26 22:09:55 -04:00
notboeing747
993564ed24
we ran out of bare clients 2024-07-26 15:54:03 -04:00
notboeing747
66ba68f479
Translated a handful of strings 2024-07-26 13:36:14 -04:00
notboeing747
deb9193b9a
Merge branch 'titaniumnetwork-dev:main' into main 2024-07-26 13:31:15 -04:00
wearrrrr
6a3b062644 Add Dracula theme and overhaul IDBManager.ts, misc fixes and changes 2024-07-25 23:57:53 -05:00
wearrrrr
35c167503d Add WispServerTiming.ts, begin work on a dropdown that shows wisp servers and their ping 2024-07-25 22:15:11 -05:00
notboeing747
8faa1c147a
clone en.json and rename it to fr.json
Will be using this as a template
2024-07-25 14:37:54 -04:00
notboeing747
76c5560449
clone en.json 2024-07-25 14:35:38 -04:00
wearrrrr
c9843beae5 Remove vencord plugin until Error.stack is properly proxied in UV. Make better use of the Link component I made 2024-07-24 17:39:11 -05:00
wearr
eb94275c94
Update README.md 2024-07-24 13:40:49 -05:00
wearrrrr
07b0255a01 Bump wisp-server-node, make log() nicer in index.js 2024-07-24 13:39:14 -05:00
wearrrrr
29177bbfac Optimize masqr middleware, src will be published soon, 2024-07-23 23:54:33 -05:00
wearrrrr
f1dc7c91a7 i18n/utils.ts slight refactor 2024-07-23 19:48:51 -05:00
wearrrrr
04952867ef Add bloons, optimize the flash initialization 2024-07-23 15:37:16 -05:00
wearrrrr
213c729a70 Add a mechanism for flash games to be loaded in the games page, and add a couple 2024-07-23 01:46:20 -05:00
wearr
0a4a32974f
Update README.md 2024-07-19 19:12:30 -05:00
wearr
e5da668e59
Add some shield icons 2024-07-19 19:11:21 -05:00
wearr
7e3d3c1a0d
Merge pull request #17 from titaniumnetwork-dev/workerware
Merge workerware support into main branch, as well as a far superior games system 🎉
2024-07-19 18:57:09 -05:00
wearrrrr
65de29cd92 Add more games, add fullscreen button, and remove testing marketplace items. 2024-07-19 18:54:53 -05:00
wearrrrr
021b314e6b Add games, and polish a system for loading stuff without having to provide all of the unity build assets for each instance. 2024-07-19 00:27:28 -05:00
wearrrrr
c3e17ea81a Updates games, and add ssr games page. 2024-07-18 02:58:35 -05:00
wearrrrr
4579865ee4 bump bare-mux version, make some minor changes 2024-07-17 17:19:19 -05:00
wearrrrr
67d9de5adc Fix A small bug with the marketplace uninstall button and some css, run format. 2024-07-12 15:24:14 -05:00
wearrrrr
fe8833e4ec make typescript stfu 2024-07-11 17:21:09 -05:00
wearrrrr
033feebb14 Seems like vscode doesn't throw a fit anymore with bare-mux :D 2024-07-11 17:18:44 -05:00
wearr
160e043181
Merge pull request #16 from Percslol/upstream-main
Add support for bare-mux v2 and latest version of ultraviolet
2024-07-11 17:12:09 -05:00
Percs
839d23d104 update to ultraviolet 3.2.2 2024-07-11 17:03:35 -05:00
Percs
10d1a84d9c
Merge branch 'workerware' into upstream-main 2024-07-11 16:46:46 -05:00
Percs
3745c0cec5 update epoxytransport 2024-07-11 11:33:53 -05:00
Percs
d66fcbdf65 update package lock 2024-07-11 10:06:39 -05:00
Percs
1a2d0cccf7 update to latest version of libcurl 2024-07-11 09:55:00 -05:00
Percs
aae94e6275 change value of bare option 2024-07-11 09:28:32 -05:00
Percs
dda3ee5ee6 fix default transport 2024-07-11 09:26:02 -05:00
Percs
62b9925767 start work to upgrade alu to bare mux 2.0 2024-07-11 01:55:11 -05:00
wearrrrr
ed4714bd16 Merge importScripts into one call. 2024-07-09 21:31:08 -05:00
wearrrrr
529f6d6086 Add searching to games page, and refine the page a lot. 2024-07-08 23:14:11 -05:00
wearrrrr
82cb084744 Add description field to extension manifest 2024-07-08 22:44:08 -05:00
wearrrrr
fc77fccc55 Theme support!!!!!! 2024-07-08 21:08:44 -05:00
wearrrrr
6953527d2a Lint, add IDBManager, and add a proper way to restart the service worker when an extension is installed. 2024-07-08 19:14:01 -05:00
wearrrrr
5371feea2d Add partytown (WIP) 2024-07-06 22:14:37 -05:00
wearrrrr
d58e31e8d9 Middleware can now be loaded from indexedDB, merge into main soon!! 2024-07-06 14:33:24 -05:00
wearrrrr
e9167fda9a Some code fixups, we should now be close to ready to merge into main, just need to make the marketplace. 2024-07-01 23:47:11 -05:00
wearrrrr
8cc6dc57fc Rename deleteByID to deleteByName 2024-06-23 23:28:58 -05:00
wearrrrr
bc34a6a85c remove redundant method 2024-06-23 23:28:17 -05:00
wearrrrr
b6b86e4f2f Update this._opt to reflect how it should behave 2024-06-23 23:20:09 -05:00
wearrrrr
eee76b356c Add info function to workerware. 2024-06-23 22:15:36 -05:00
wearrrrr
df248d213c just move the position of a comment 2024-06-18 23:21:35 -05:00
wearrrrr
4b75efbddd Push update to workerware, this adds configuration support, timing, ability to make middleware names random and delete middleware by name, id, or event. 2024-06-18 23:19:32 -05:00
wearrrrr
9d74ddf394 Add /blocklist route because cors. Remove dbg statement from workerware, and add more filter lists to adblocker middleware. 2024-06-17 19:34:27 -05:00
wearrrrr
b9f64617dd Add proof of concept adblocker and continue working on refining the use hook. 2024-06-17 14:30:36 -05:00
wearrrrr
6f4f234c82 add middlewareManifest type, ensure events to hook into are valid when calling use(middleware) 2024-06-17 02:09:12 -05:00
wearrrrr
4395c41041 Begin to work on workerware. 2024-06-16 20:44:25 -05:00
wearr
118d62f392
Update README.md 2024-06-16 19:31:56 -05:00
wearrrrr
9e0360cb2b Add Dockerfile and update readme to reflect it. 2024-06-14 22:17:15 -05:00
wearr
aac5e5feb7
Merge pull request #15 from NotLawson/patch-1
Update README with steps suggested in #12
2024-06-14 22:02:09 -05:00
Lawson C
b04d3f8b41
Update README.md with the example in #12 2024-06-14 09:18:33 +10:00
wearrrrr
597492b387 eeeee 2024-05-07 13:12:51 -05:00
wearrrrr
e54b1c9b21 hopefully make games submodule sane again 2024-05-07 13:10:55 -05:00
wearrrrr
9d7630bb5e e 2024-05-07 13:02:36 -05:00
wearrrrr
3444c98bf3 update games submodule 2024-05-07 13:00:40 -05:00
wearrrrr
1a47676a9e re-add games submodule 2024-05-07 12:59:11 -05:00
wearrrrr
94e30e9925 remove submodule 2024-05-07 12:57:05 -05:00
wearrrrr
e42e83e3a9 Update games submodule 2024-05-07 12:56:02 -05:00
wearrrrr
bea33a22c6 I was greatly overcomplicating the custom favicon system LOL 2024-05-07 09:47:55 -05:00
wearrrrr
9bc3473bc7 Update games submodule, add analytics. 2024-05-07 09:00:41 -05:00
wearrrrr
688d871c15 Add terms and conditions, format with prettier 2024-05-06 14:12:39 -05:00
wearrrrr
a88c5993b0 Update dependencies, fix bug with share button. 2024-04-29 13:14:34 -05:00
wearrrrr
d9113c3c13 Remove marketplace header item, refactoring and bug fixing in index.js 2024-04-24 10:40:25 -05:00
wearr
c0ea8fda4d
Merge pull request #10 from localer/patch-1
Update jp.json
2024-04-23 09:46:01 -05:00
Local
fb2b77f4d9
Update jp.json 2024-04-23 23:40:42 +09:00
wearrrrr
d25112f5e2 Fix bug with search suggestions again, and add marketplace.astro again. 2024-04-22 19:01:13 -05:00
wearrrrr
e9ec201450 Revert 2024-04-22 18:55:37 -05:00
wearrrrr
93d48c7277 Revert "Fix bug with clicking search suggestions, start working on proper API for hooking into the service worker."
This reverts commit fdae47c9b3.
2024-04-22 18:55:29 -05:00
wearrrrr
91488e88f5 Tried to make progress on dynamic fetch events, currently does NOT work. 2024-04-19 10:06:51 -05:00
wearrrrr
fdae47c9b3 Fix bug with clicking search suggestions, start working on proper API for hooking into the service worker. 2024-04-18 18:00:26 -05:00
wearrrrr
8b3abae5f5 Script is now fetched and btoa'd inside of indexeddb. 2024-04-17 09:47:10 -05:00
wearrrrr
0b87af884e Fix bug with adding extensions to indexedDB 2024-04-17 09:24:12 -05:00
wearrrrr
3040dfc66e Each installed script now saves a reference in IDB. 2024-04-16 12:41:08 -05:00
wearrrrr
caf81f9f06 Merge branch 'main' of https://github.com/wearrrrr/AlusUnblocker 2024-04-16 09:27:01 -05:00
wearrrrr
f8bde78717 Add support for optionally enabling masqr via .env and optionally enabling wisp, format using prettier. 2024-04-16 09:27:00 -05:00
wearrrrr
a86046949a WIP Marketplace page, hopefully will be functional soon 🎉 2024-04-15 16:34:59 -05:00
wearrrrr
64d8b75f3e Add autocomplete attribute to Input component 2024-04-15 13:58:02 -05:00
wearrrrr
f1a56b9f91 Update faq section to be a bit better 2024-04-15 12:14:26 -05:00
wearrrrr
645fd818d4 fix small bug with skip to main content button 2024-04-12 13:14:59 -05:00
wearrrrr
19b4026a50 Add skip to main content button, make things more semantic and accessible. 2024-04-12 13:13:15 -05:00
wearrrrr
81bf6d6ed9 fix bug with how custom-favicon was parsing favicons with weird content-types. 2024-04-12 10:06:43 -05:00
wearrrrr
50cac67efe Add some more navigation buttons in the topbar, add some extra typing, and fix some bugs :) 2024-04-11 21:33:08 -05:00
wearr
a2d600a27e
Merge pull request #8 from Percslol/main
fix "there are no bare clients" issue
2024-04-11 20:19:24 -05:00
Percs
cb3ae9363d there are bare clients 2024-04-11 19:29:53 -05:00
wearrrrr
e602896dae add a ton of metadata to the index.astro redirect 2024-04-11 13:56:55 -05:00
wearrrrr
beef2fd55b The bug fixing and optimizing update (tm) 2024-04-11 10:01:39 -05:00
wearrrrr
23bcc6924f move registerSW into index.astro 2024-04-10 19:12:18 -05:00
wearrrrr
2b5130a972 mitigation #12398129310238102983 for there are no bare clients issue (bare-mux issue) 2024-04-10 18:40:22 -05:00
wearrrrr
c23e57939e turns out Astro.redirect is borked 2024-04-10 18:12:12 -05:00
wearrrrr
949f7c4936 Make loading much more efficient and have it not shit itself when you start on anything other than the index page. 2024-04-09 19:47:57 -05:00
wearr
55b0708016
Merge pull request #6 from LizzyEll/patch-1
Fix Deploy Information
2024-04-09 09:13:53 -05:00
Lizzy Ell
376db85cf7
Fix Deploy Information
The `git clone` command had the invalid flag `--recursive-submodules` which was a typo of the flag `--recurse-submodules`.
2024-04-09 09:10:21 -05:00
wearrrrr
118469caa2 Remove SettingsTablist and move it to settings.astro 2024-04-08 19:42:26 -05:00
wearrrrr
2391cf2cfe Maybe fix the no bare clients issue?? 2024-04-08 19:10:50 -05:00
wearrrrr
9934d87ffb I am le mentally disabled 2024-04-07 23:15:40 -05:00
wearrrrr
af050c52d3 get rid of the boundIFrameLoad nightmare, makes Alu look MUCH more responsive. 2024-04-07 23:01:59 -05:00
wearrrrr
2bd41a9552 Fix misc bugs with cloaking, empty localStorage values, and remove redundant transportManager code. 2024-04-07 22:57:51 -05:00
wearrrrr
171a163531 Add much better system for style lists in Input.astro, and format. 2024-04-07 22:49:25 -05:00
wearrrrr
0caa823ad6 Add pnpm-lock, remove bare-client dependency. 2024-04-07 22:37:09 -05:00
wearrrrr
7a39f24182 Change input on Index.astro to Input component, add defaultStyles prop. 2024-04-07 12:37:17 -05:00
wearrrrr
760e1b8ec8 Misc changes, notably moving ProxyRegistrar out of Layout.astro 2024-04-04 12:04:32 -05:00
wearrrrr
772ad1a884 Add better sitemap generation 2024-04-04 09:33:44 -05:00
wearrrrr
da9413930e Dynamic robots.txt file, and add sitemap.xml. 2024-04-04 09:24:01 -05:00
wearrrrr
74cd71e255 Fix small bug with ProxyRegistrar on first load. 2024-04-03 22:04:52 -05:00
wearrrrr
390f3e73d9 Update games submodule 2024-04-02 21:11:04 -05:00
wearrrrr
9436d8b1c8 games submodule update to hopefully unfuck git 2024-04-02 21:03:03 -05:00
wearrrrr
39f2b22d69 oops 2024-04-02 21:00:00 -05:00
wearrrrr
e0de8bde94 Make savedWispUrl and savedBareUrl behave MUCH nicer. 2024-04-02 20:54:17 -05:00
wearrrrr
f5fdaf32e6 Fix bug with data urls attempting to route to the favicon proxy. 2024-04-01 13:48:57 -05:00
wearrrrr
e54858620b Add path aliases, optimize adding i18n to a page, and general cleanup. 2024-04-01 12:22:02 -05:00
wearrrrr
ece900b353 Lots of optimizations :D 2024-04-01 10:06:58 -05:00
wearrrrr
3e3773aab5 Make favicon in proxy-frame use favicon proxy. 2024-03-29 23:19:26 -05:00
wearrrrr
774f26066b Attempt to prevent Alu from allowing Epoxy to load, as it causes the tab to hang (firefox bug) 2024-03-29 23:07:06 -05:00
wearrrrr
c56fff2e78 Fix custom favicon url, replace instructure.jpg with canvas.png, general bug fixes. 2024-03-29 23:01:39 -05:00
wearr
c524f5bbfd
Merge pull request #5 from NottPeak/main
Fixed icons in settings page
2024-03-29 22:14:43 -05:00
NottPeak
fa4f0ae240 Fixed icons in settings page 2024-03-30 03:06:36 +00:00
wearrrrr
fd401108ee Make everything cross origin isolated 2024-03-29 13:00:18 -05:00
wearrrrr
52af3fed5d Dynamically inject epoxy, libcurl, and bare transport. 2024-03-29 12:55:58 -05:00
wearrrrr
52005fd480 remove source map declaration from bare_transport 2024-03-29 12:48:14 -05:00
wearrrrr
d618a67826 Convert ProxyRegistrar to use TS instead of inline JS, and rewrite debounce. 2024-03-29 12:44:34 -05:00
wearrrrr
1d9bcd1dba Fix small CSS inconsistencies 2024-03-29 12:08:19 -05:00
wearrrrr
22c5324532 add bufferutil, update games submodule 2024-03-29 11:39:28 -05:00
wearrrrr
7b808bb821 Change iframe.src to Loading... in the topbar. 2024-03-28 10:33:14 -05:00
wearrrrr
551034179a Add more logic to updateTopbarTitle, add bareURL option. 2024-03-28 10:29:18 -05:00
wearrrrr
4d6ab9ad4b add bare transport support!!! 2024-03-28 10:08:14 -05:00
wearrrrr
ab6457d95c Fix issue with updateTopbarTitle 2024-03-27 10:39:38 -05:00
wearrrrr
46d5cef377 Run prettier on codebase, and make iframe favicon and title grabbing much better. 2024-03-27 10:06:46 -05:00
wearrrrr
f3e347c1cd Add eslint support! 🎉 2024-03-18 00:11:58 -05:00
wearrrrr
a5d590b7ab Move transport manager to ts file, hopefully libcurl will work sometime in the following days 2024-03-16 23:06:33 -05:00
wearrrrr
1393206d07 Update games submodule 2024-03-16 18:11:17 -05:00
wearrrrr
c3cc83dd1c try to get libcurl working, didn't work 2024-03-16 18:09:25 -05:00
wearrrrr
fdb93bbd96 potentially fix the issue with no bare clients, libcurl and baremod are still broken 2024-03-11 13:57:34 -05:00
wearrrrr
ffb4721afd fix bare endpoint and set default to epoxy 2024-03-08 13:40:28 -06:00
wearrrrr
9559f0986e epoxy works but everything else is womp womp for now 2024-03-08 10:08:05 -06:00
Riftriot
c8f4ceff9c Simple masqr setup 2024-03-08 09:02:19 -06:00
wearrrrr
63b20d1388 Create STATIC_PATHS export for astro, and make TransportManager 2024-03-07 15:56:43 -06:00
wearrrrr
3f560d81a0 Upgrade to UV 3.0 and EpxMod 2024-03-07 14:43:14 -06:00
wearrrrr
f8b92dc0b9 Shows favicon when page is loaded in embed mode now. 2024-03-01 22:48:04 -06:00
wearrrrr
815f4d5999 Implement new tab and about:blank opening modes 2024-02-26 10:04:17 -06:00
wearrrrr
59515a314e update games submodule 2024-02-26 09:10:39 -06:00
wearrrrr
4ff12abc79 oops, don't use += on document.cookie, also fix some css. 2024-02-25 18:30:28 -06:00
wearrrrr
32cfc7676e Add origin_proxy cookie (ty sm binaryperson), and remove helmet. 2024-02-25 18:20:23 -06:00
wearrrrr
d5ecbaadac I think this will work? 2024-02-25 18:09:24 -06:00
wearrrrr
872f46798a Update games submodule and hotfix 2024-02-25 18:07:36 -06:00
wearrrrr
a9eda0a981 Merge remote-tracking branch 'refs/remotes/origin/main' 2024-02-25 18:07:30 -06:00
wearrrrr
0dcaace2aa stupid dumb patch because guh rammerhead 2024-02-25 18:06:52 -06:00
wearrrrr
c5a2b2563b Fix body overflow issues and add some forgotten i18n keys. 2024-02-23 14:55:24 -06:00
wearrrrr
5636a91028 Mobile responsive settings, and fix bug with index.js 2024-02-23 13:56:21 -06:00
wearrrrr
a9df5402e5 Update games submodule 2024-02-23 13:06:54 -06:00
wearrrrr
cb6323288e Fix suika game 2024-02-23 13:06:29 -06:00
wearrrrr
de7fbef45d update games 2024-02-23 10:07:46 -06:00
wearrrrr
e3133f28d4 add suika combination 2024-02-23 10:07:09 -06:00
wearrrrr
ad0f40e638 god I hate you rammerhead 😭 2024-02-22 23:17:47 -06:00
wearrrrr
3d8cbf3e72 WAY better system for iframe / topbar handling, and topbar url changes when the iframe url does. 2024-02-22 20:03:15 -06:00
wearrrrr
2bf4c596d8 Close other dropdowns when a new dropdown is clicked. 2024-02-22 13:19:06 -06:00
wearrrrr
2b4534f403 small refactor of index.js 2024-02-22 12:25:48 -06:00
wearrrrr
7b273166ed maybe fix it? 2024-02-22 12:20:29 -06:00
wearrrrr
ca37615bef im a dummy lol, forgot the createRammerhead call 2024-02-22 12:10:39 -06:00
wearrrrr
34fdf7c5ce (hopefully) actually fix rh 2024-02-22 12:08:07 -06:00
wearrrrr
75d0e73836 Fix rammerhead in prod (ty rift) 2024-02-22 09:52:43 -06:00
wearrrrr
f9b1a9e909 Add box shadow, looks a bit better imo 2024-02-21 14:55:25 -06:00
wearrrrr
b589a5ff46 Fix issue with click events being duplicated in settings, i18n update, new favicon 2024-02-21 14:11:41 -06:00
wearrrrr
9ae1e5220f Fix settings bug.. again. 2024-02-21 10:55:27 -06:00
wearrrrr
f1ace2f821 cull unnecessary dependencies 2024-02-20 14:58:30 -06:00
wearrrrr
5246e6e83b Fix long standing bug with settings and lint. 2024-02-20 13:58:27 -06:00
wearrrrr
1cab054da7 rename window.loadContent to window.loadFormContent 2024-02-20 13:23:32 -06:00
wearrrrr
e2b3d7cdc6 Make search suggestions better, and actually use function.prototype.call for once 2024-02-20 12:32:08 -06:00
wearrrrr
a9a75b9280 Add /search endpoint, working on impl. 2024-02-20 10:06:58 -06:00
wearr
585f937b81
Delete public/rammerhead.js 2024-02-15 12:23:48 -06:00
wearr
029331aeb5
Delete public/hammerhead.js 2024-02-15 12:23:42 -06:00
wearrrrr
b612957863 Update games submodule and games.json 2024-02-12 09:28:02 -06:00
wearrrrr
6e79bc92f9 rammerhead uyghsurhgush 2024-02-11 20:19:57 -06:00
wearrrrr
5b08275dfe add dotenv variable for rammerhead URL constructor 2024-02-11 20:14:37 -06:00
wearrrrr
4030166454 fix rammerhead so that it actually works oops 2024-02-11 20:10:43 -06:00
wearrrrr
025d7f0c50 update ultraviolet from nebula 2024-02-11 19:23:49 -06:00
wearrrrr
1922c24a7c um 2024-02-11 19:23:28 -06:00
wearrrrr
66bd055455 tsconfig and small ui change 2024-02-11 18:55:36 -06:00
wearrrrr
bded1098bb Fix a lot of the UI for mobile 2024-02-11 18:52:16 -06:00
wearrrrr
4a3faa9761 Fix bug where iframe isn't fully destroyed, add FAQ. 2024-02-11 16:49:57 -06:00
wearrrrr
e471f4a03f minor html fuckup lol 2024-02-11 01:15:31 -06:00
wearrrrr
07dd11d97a Lint and add Link component for better link handling 2024-02-11 01:12:46 -06:00
wearrrrr
f4b52d3a67 Update games.json 2024-02-10 23:02:50 -06:00
wearrrrr
b71b56962d update footer css and games submodule 2024-02-10 22:44:09 -06:00
wearr
3a2a27f5cc
Update README.md 2024-02-09 13:39:55 -06:00
146 changed files with 21283 additions and 7534 deletions

2
.env.defaults Normal file
View file

@ -0,0 +1,2 @@
MASQR_ENABLED=false
PORT=3000

3
.eslintignore Normal file
View file

@ -0,0 +1,3 @@
node_modules/
dist/
public/

47
.eslintrc.cjs Normal file
View file

@ -0,0 +1,47 @@
module.exports = {
env: {
node: true,
es2022: true,
browser: true,
},
extends: ["eslint:recommended", "plugin:astro/recommended"],
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
rules: {
"no-unused-vars": "error",
"no-undef": "off",
"prefer-const": "error",
"no-case-declarations": "off",
},
ignorePatterns: ["env.d.ts", "middleware/", "public/"],
overrides: [
{
files: ["*.astro"],
parser: "astro-eslint-parser",
parserOptions: {
parser: "@typescript-eslint/parser",
extraFileExtensions: [".astro"],
},
},
{
files: ["*.ts", "*.tsx"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: "./tsconfig.json",
},
plugins: ["@typescript-eslint"],
extends: ["plugin:@typescript-eslint/recommended"],
rules: {
"@typescript-eslint/no-explicit-any": "off",
},
},
{
// Define the configuration for `<script>` tag.
// Script in `<script>` is assigned a virtual file name with the `.js` extension.
files: ["**/*.astro/*.js", "*.astro/*.js"],
parser: "@typescript-eslint/parser",
},
],
};

1
.gitignore vendored
View file

@ -5,3 +5,4 @@ node_modules/
npm-debug.log* npm-debug.log*
.env .env
public/games/** public/games/**
exempt_masqr.txt

View file

@ -1,2 +1,3 @@
dist dist
node_modules node_modules
public

View file

@ -1,4 +0,0 @@
{
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
}

11
.vscode/launch.json vendored
View file

@ -1,11 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

11
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,11 @@
{
"search.exclude": {
"/public/games/**": true
},
"files.exclude": {
"**/*.rpyc": true,
"**/*.rpa": true,
"**/*.rpymc": true,
"**/cache/": true
}
}

38
Checkfailed.html Normal file
View file

@ -0,0 +1,38 @@
<!doctype html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html {
color-scheme: light dark;
}
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>
If you see this page, the nginx web server is successfully installed and working. Further configuration is required. If you are expecting another page, please check your network or
<a href="/" id="rcheck"><b>Refresh this page</b></a>
</p>
<p>
For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br />
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.
</p>
<p><em>Thank you for using nginx.</em></p>
<script>
if (!localStorage["auth"] && new URL(document.all.rcheck.href).password) {
window.location.reload();
localStorage["auth"] = 1;
}
</script>
</body>
</html>

18
Dockerfile Normal file
View file

@ -0,0 +1,18 @@
FROM node:lts
WORKDIR /usr/src/app
# Copying package.json and pnpm-lock helps with caching
COPY package.json pnpm-lock.yaml ./
RUN npm i -g pnpm
RUN pnpm install
COPY . .
RUN pnpm run build
EXPOSE 3000
CMD ["pnpm", "start"]

View file

@ -1,39 +1,58 @@
<p align="center">
<img src="https://github.com/titaniumnetwork-dev/Alu/assets/99224452/d740378b-3fba-4470-8f06-3eefdae8a313" alt="AluLogo" width="250"/>
</p>
# Alu # Alu
Alu is a beautiful, functional, and sleek web proxy, which focuses on customization and ease of use. Alu is a beautiful, functional, and sleek web proxy that prioritizes customization and ease of use.
![Code size](https://shields.io/github/languages/code-size/titaniumnetwork-dev/Alu?style=flat-square&logo=github)
![Star count](https://shields.io/github/stars/titaniumnetwork-dev/Alu?style=flat-square&logo=github)
![Made with coffee](https://img.shields.io/badge/made%20with-coffee-452515?style=flat-square&logo=coffeescript)
# Features # Features
- 🌐 UV and Rammerhead support - 🌐 UV and Rammerhead support
- 🎨 Themes - 🎨 Multiple Themes to choose from
- 🏬 Marketplace for Themes and Extensions
- 🕶 Multiple site cloaking options - 🕶 Multiple site cloaking options
- 🎮 50+ Games to choose from - 🎮 50+ Games to choose from
- 🌎 English and Japanese support - 🌎 Support for **6** Languages
- 🚀 High performance - 🚀 High performance
- 🔍 Multiple Search Engines to pick from - 🔍 Multiple Search Engines to pick from
# Deploying Alu # Deploying Alu
Deploying Alu is about as simple as it gets, from your terminal, type
`git clone https://github.com/wearrrrr/Alu --recursive-submodules` Deploying Alu is about as simple as it gets.
This command should clone Alu's frontend, as well as [alu-games](https://github.com/wearrrrr/alu-games). If you wish to skip cloning games, then leave out the last flag. 1. Open your terminal and type `git clone https://github.com/titaniumnetwork-dev/Alu --recurse-submodules`
Then simply run `npm i` to install all node_modules, and then build the frontend with `npm run build`, this shouldn't take more than a couple seconds. 2. Install pnpm with `npm i -g pnpm`.
Finally, run `npm start` to actually serve Alu! It defaults to port 3000 for everything, but this can be specified in an env file. 3. Then simply run `pnpm i` to install all node_modules, and build the frontend with `pnpm run build`; this shouldn't take more than a couple seconds.
Congrats, you've now deployed your very own web proxy! 4. Finally, run `pnpm start` to actually serve Alu! It defaults to port 3000 for everything, but this can be specified in an env file.
Congrats! You should now be running your very own instance of Alu! 🎉
> [!WARNING]
> Recursing all submodules will install [alu-games](https://github.com/wearrrrr/alu-games) as well. This repo contains _all_ games for Alu and is quite large! If you wish to skip it, simply remove `--recurse-submodules` from your clone command.
## What about Docker?
Alu can be easily dockerized with the `Dockerfile` provided in the repository. Simply run `docker build -t alu .` to build the image, and then `docker run -p 3000:3000 alu` to run the container, and you're good to go!
# Technologies # Technologies
- Ultraviolet by Titanium Network - Ultraviolet by Titanium Network
- Bare Server from TompHTTP - Bare Server from TompHTTP
- Wisp Server Node by Mercury Workshop
- Rammerhead by binary-person - Rammerhead by binary-person
- Astro from astro.build - Astro from astro.build
- Typescript - Typescript
- ExpressJS - ExpressJS
- Prettier - Prettier
- ESLint
# License # License

View file

@ -1,12 +1,31 @@
import { defineConfig } from "astro/config"; import { defineConfig } from "astro/config";
import node from "@astrojs/node"; import node from "@astrojs/node";
import dotenv from "dotenv-flow";
import sitemap from '@astrojs/sitemap';
dotenv.config();
// Check if node is running in production mode
// const prodBuild = process.env.NODE_ENV === "production";
const prodBuild = process.env.IS_PROD === "true";
const site = prodBuild ? "https://aluu.xyz" : "http://localhost:3000";
// https://astro.build/config
export default defineConfig({ export default defineConfig({
integrations: [], site: site,
output: "hybrid", integrations: [
sitemap({
lastmod: new Date(),
}),
],
output: "server",
adapter: node({ adapter: node({
mode: "middleware", mode: "middleware",
}), }),
vite: {
server: {
watch: {
usePolling: true,
},
},
},
}); });

186
index.js
View file

@ -1,97 +1,139 @@
import { uvPath } from "@nebula-services/ultraviolet"; import "./middleware/catchErrors.js";
import { createBareServer } from "@tomphttp/bare-server-node"; import dotenv from "dotenv-flow";
import { uvPath } from "@titaniumnetwork-dev/ultraviolet";
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 express from "express"; import express from "express";
import { createServer } from "http"; import { createServer } from "http";
import path from "node:path"; import path from "node:path";
import createRammerhead from "rammerhead/src/server/index.js";
import compression from "compression";
import { build } from "astro";
import chalk from "chalk"; import chalk from "chalk";
import { existsSync } from "fs"; import { server as wisp, logging as wispLogging } from "@mercuryworkshop/wisp-js/server";
import dotenv from "dotenv"; import { handler as astroSSR } from "./dist/server/entry.mjs";
import cookies from "cookie-parser";
import { existsSync, readFileSync } from "fs";
dotenv.config(); dotenv.config();
if (!existsSync("./dist")) build(); const whiteListedDomains = ["aluu.xyz", "localhost"];
const PORT = process.env.PORT || 3000; if (existsSync("exempt_masqr.txt")) {
const file = readFileSync("exempt_masqr.txt", "utf-8");
const bare = createBareServer("/bare/"); const exemptDomains = file.split("\n");
console.log(chalk.gray("Starting Bare...")); exemptDomains.forEach((domain) => {
whiteListedDomains.push(domain.trim());
const rh = createRammerhead();
console.log(chalk.gray("Starting Rammerhead..."));
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",
];
const rammerheadSession = /^\/[a-z0-9]{32}/;
function shouldRouteRh(req) {
const url = new URL(req.url, "http://0.0.0.0");
return rammerheadScopes.includes(url.pathname) || rammerheadSession.test(url.pathname);
}
function routeRhRequest(req, res) {
rh.emit("request", req, res);
}
function routeRhUpgrade(req, socket, head) {
rh.emit("upgrade", req, socket, head);
}
let server = createServer();
server.on("request", (req, res) => {
if (bare.shouldRoute(req)) {
bare.routeRequest(req, res);
} else if (shouldRouteRh(req)) {
routeRhRequest(req, res);
} else {
app(req, res);
}
}); });
server.on("upgrade", (req, socket, head) => {
if (bare.shouldRoute(req)) {
bare.routeUpgrade(req, socket, head);
} else if (shouldRouteRh(req)) {
routeRhUpgrade(req, socket, head);
} else {
socket.end();
} }
});
const LICENSE_SERVER_URL = "https://license.mercurywork.shop/validate?license=";
const MASQR_ENABLED = process.env.MASQR_ENABLED;
wispLogging.set_level(wispLogging.WARN);
const log = (message) => console.log(chalk.gray.bold("[Alu] " + message));
const success = (message) => console.log(chalk.green.bold("[Alu] " + message));
const PORT = process.env.PORT;
const app = express(); const app = express();
app.use(compression());
app.use(cookies());
// Set process.env.MASQR_ENABLED to "true" to enable masqr protection.
if (MASQR_ENABLED == "true") {
log("Starting Masqr...");
const masqrCheck = (await import("./middleware/Masqr/index.js")).masqrCheck;
app.use(await masqrCheck({ whitelist: whiteListedDomains, licenseServer: LICENSE_SERVER_URL, htmlFile: "Checkfailed.html" }));
}
app.use(astroSSR);
app.use(express.static(path.join(process.cwd(), "static"))); app.use(express.static(path.join(process.cwd(), "static")));
app.use(express.static(path.join(process.cwd(), "build"))); app.use(express.static(path.join(process.cwd(), "build")));
app.use("/uv/", express.static(uvPath)); app.use("/uv/", express.static(uvPath));
app.use("/epoxy/", express.static(epoxyPath));
app.use("/libcurl/", express.static(libcurlPath));
app.use("/baremux/", express.static(baremuxPath));
app.use("/baremod/", express.static(bareModulePath));
app.use(express.json()); app.use(express.json());
app.use( app.use(
express.urlencoded({ express.urlencoded({
extended: true, extended: true,
}) })
); );
app.use("/", express.static("dist/client/")); app.use((req, res, next) => {
if (req.url.includes("/games/")) {
res.header("Cross-Origin-Opener-Policy", "same-origin");
res.header("Cross-Origin-Embedder-Policy", "require-corp");
}
next();
});
app.use("/custom-favicon", async (req, res) => {
try {
const { url } = req.query;
const response = await fetch(`https://www.google.com/s2/favicons?domain=${url}&sz=128`);
const buffer = new Buffer.from(await response.arrayBuffer());
res.set("Content-Type", "image/png");
res.send(buffer);
} catch {
res.sendStatus(500);
}
});
console.log(chalk.gray("Starting Alu...")); app.use("/blocklist", async (req, res) => {
console.log(chalk.green("Alu started successfully!")); try {
const { url } = req.query;
const response = await fetch(url).then((r) => r.text());
res.set("Content-Type", "text/plain");
res.send(response);
} catch {
res.sendStatus(500);
}
});
app.use("/", express.static("dist/client/"));
app.get("/favicon.ico", (req, res) => {
res.sendFile(path.join(process.cwd(), "dist/client/favicon.svg"));
});
app.get("/robots.txt", (req, res) => {
if (req.headers.host && whiteListedDomains.includes(req.headers.host)) {
res.sendFile(path.join(process.cwd(), "dist/client/robots-allow.txt"));
} else {
res.sendFile(path.join(process.cwd(), "dist/client/robots-deny.txt"));
}
});
app.get("/search", async (req, res) => {
try {
const { query } = req.query;
const response = await fetch(`http://api.duckduckgo.com/ac?q=${query}&format=json`).then((apiRes) => apiRes.json());
res.send(response);
} catch (err) {
res.redirect(302, "/404.html");
}
});
app.get("*", (req, res) => {
res.redirect(302, "/404");
});
const server = createServer();
server.on("request", (req, res) => {
app(req, res);
});
server.on("upgrade", (req, socket, head) => {
if (req.url.endsWith("/wisp/")) {
wisp.routeRequest(req, socket, head);
} else {
socket.end();
}
});
log("Starting Alu...");
success("Alu started successfully!");
server.on("listening", () => { server.on("listening", () => {
console.log(chalk.green(`Server running at http://localhost:${PORT}/.`)); success(`Server running at http://localhost:${PORT}/.`);
}); });
server.listen({ server.listen({

73
middleware/Masqr/index.js Normal file
View file

@ -0,0 +1,73 @@
import path from "path";
import fs from "fs";
export async function masqrCheck(config) {
return async (req, res, next) => {
try {
const loadedHtmlFile = fs.readFileSync(process.cwd() + "/" + config.htmlFile, "utf8");
if (config.whitelist.includes(req.hostname)) {
next();
return;
}
const authheader = req.headers.authorization;
if (!req.cookies) {
// Send an error
return res.send("Request failed!");
}
if (req.cookies.authcheck) {
next();
return;
}
if (!authheader) {
res.setHeader("WWW-Authenticate", "Basic");
res.status(401);
MasqrFail(req, res, loadedHtmlFile);
return;
}
// If we are at this point, then the request should be a valid masqr request, and we are going to check the license server
const auth = Buffer.from(authheader.split(" ")[1], "base64").toString().split(":");
const pass = auth[1];
const licenseCheck = (await (await fetch(config.licenseServer + pass + "&host=" + req.headers.host)).json())["status"];
if (licenseCheck === "License valid") {
// Authenticated, set cookie for a year
res.cookie("authcheck", "true", {
expires: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000),
});
res.send(`<script>window.location.href = window.location.href</script>`); // fun hack to make the browser refresh and remove the auth params from the URL
return;
} else {
res.setHeader("WWW-Authenticate", "Basic");
res.status(401);
MasqrFail(req, res, loadedHtmlFile);
return;
}
} catch (err) {
console.error(err);
res.status(500);
res.send("Internal server error");
return;
}
};
}
async function MasqrFail(req, res, failureFile) {
if (!req.headers.host) {
return;
}
const unsafeSuffix = req.headers.host + ".html";
const safeSuffix = path.normalize(unsafeSuffix).replace(/^(\.\.(\/|\\|$))+/, "");
const safeJoin = path.join(process.cwd() + "/Masqrd", safeSuffix);
try {
await fs.promises.access(safeJoin); // man do I wish this was an if-then instead of a "exception on fail"
const failureFileLocal = await fs.promises.readFile(safeJoin, "utf8");
res.setHeader("Content-Type", "text/html");
res.send(failureFileLocal);
return;
} catch (e) {
res.setHeader("Content-Type", "text/html");
res.status(401);
res.send(failureFile);
return;
}
}

11
middleware/catchErrors.js Normal file
View file

@ -0,0 +1,11 @@
import chalk from "chalk";
process.on("uncaughtException", (err) => {
console.log(chalk.bold.red(`[Alu] Caught error!\n${err.stack}`));
process.exit(1);
});
process.on("uncaughtExceptionMonitor", (err) => {
console.log(chalk.bold.red(`[Alu] Caught error!\n${err.stack}`));
process.exit(1);
});

9772
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,36 +1,47 @@
{ {
"name": "alus-unblocker", "name": "alu",
"type": "module", "type": "module",
"version": "0.0.1", "version": "0.0.1",
"scripts": { "scripts": {
"build:all": "npm run format && npm run lint && npm run build",
"start": "node .", "start": "node .",
"build": "astro build", "build": "astro build",
"lint": "prettier --write .", "dev": "npm run build && npm run start",
"lint:check": "prettier --check ." "format": "prettier --write .",
"format:check": "prettier --check .",
"lint": "eslint .",
"lint:fix": "eslint --fix ."
}, },
"dependencies": { "dependencies": {
"@astrojs/check": "^0.4.0", "@astrojs/node": "^9.0.0",
"@astrojs/node": "^7.0.4", "@astrojs/sitemap": "^3.2.1",
"@nebula-services/ultraviolet": "^1.0.1-1.patch.5", "@mercuryworkshop/bare-as-module3": "^2.2.5",
"@tomphttp/bare-server-node": "^2.0.1", "@mercuryworkshop/bare-mux": "^2.1.5",
"astro": "^4.3.3", "@mercuryworkshop/epoxy-transport": "^2.1.26",
"astro-i18n": "^2.2.4", "@mercuryworkshop/libcurl-transport": "^1.3.14",
"astro-i18next": "^1.0.0-beta.21", "@mercuryworkshop/wisp-js": "^0.3.3",
"@rubynetwork/rammerhead": "^1.3.5",
"@titaniumnetwork-dev/ultraviolet": "^3.2.10",
"@tomphttp/bare-server-node": "^2.0.5",
"@types/node": "^22.10.1",
"astro": "^5.0.1",
"chalk": "^5.3.0", "chalk": "^5.3.0",
"compression": "^1.7.4", "cookie-parser": "^1.4.7",
"dotenv": "^16.3.1",
"dotenv-flow": "^4.1.0", "dotenv-flow": "^4.1.0",
"express": "^4.18.2", "express": "^4.21.1",
"i": "^0.3.7", "notyf": "^3.10.0",
"i18next": "^23.7.18", "sequelize": "^6.37.5",
"i18next-browser-languagedetector": "^7.2.0", "sqlite3": "^5.1.7"
"npm": "^10.2.5",
"path": "^0.12.7",
"rammerhead": "https://github.com/holy-unblocker/rammerhead/releases/download/v1.2.41-holy.5/rammerhead-1.2.41-holy.5.tgz",
"typescript": "^5.3.3"
}, },
"devDependencies": { "devDependencies": {
"prettier": "3.2.5", "@typescript-eslint/eslint-plugin": "^8.17.0",
"prettier-plugin-astro": "^0.13.0" "@typescript-eslint/parser": "^8.17.0",
"eslint": "^9.16.0",
"eslint-plugin-astro": "^1.3.1",
"prettier": "3.4.1",
"prettier-plugin-astro": "^0.14.1"
},
"optionalDependencies": {
"bufferutil": "^4.0.8"
} }
} }

6360
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@ const config = {
bracketSameLine: true, bracketSameLine: true,
arrowParens: "always", arrowParens: "always",
plugins: ["prettier-plugin-astro"], plugins: ["prettier-plugin-astro"],
printWidth: 100, printWidth: 200,
}; };
export default config; export default config;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

37
public/favicon.svg Normal file
View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<svg height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512" xml:space="preserve">
<path style="fill:#7067a1;" d="M494.176,64.787c15.4,22.42,20.974,52.758,16.123,88.421c-4.751,34.914-19.365,74.181-42.346,113.946
c52.234,90.354,58.519,172.178,16.073,214.624c-18.729,18.729-45.127,27.981-76.537,27.981c-39.777,0-87.598-14.839-138.087-44.017
c-50.489,29.178-98.309,44.017-138.087,44.017c-31.411,0-57.796-9.252-76.525-27.981c-42.458-42.434-36.186-124.245,16.036-214.611
c-10.287-17.806-18.904-35.525-25.724-52.858c-0.262,0-0.511,0.012-0.773,0.012C19.889,214.321,0,194.444,0,169.992
c0-18.23,11.073-33.917,26.834-40.713c-0.037-31.884,9.514-58.282,27.956-76.724C97.224,10.096,179.036,16.368,269.402,68.59
c52.92-30.575,104.057-45.912,145.818-43.83c7.619-13.43,22.046-22.52,38.568-22.52c24.44,0,44.329,19.889,44.329,44.329
C498.116,53.066,496.695,59.226,494.176,64.787z M485.585,149.854c3.591-26.41,0.611-48.755-8.616-65.514
c-6.758,4.152-14.689,6.559-23.181,6.559c-23.455,0-42.695-18.318-44.217-41.386c-33.119-0.561-73.32,11.272-115.891,34.104
c30.4,20.051,59.741,44.142,87.436,71.836c27.695,27.695,51.773,57.035,71.811,87.423
C470.509,210.044,481.732,178.197,485.585,149.854z M473.178,46.569c0-10.686-8.704-19.39-19.39-19.39
c-10.686,0-19.39,8.704-19.39,19.39s8.704,19.39,19.39,19.39S473.178,57.256,473.178,46.569z M466.394,464.146
c31.884-31.897,26.273-98.421-13.467-172.689c-20.038,30.388-44.117,59.729-71.811,87.423
c-27.695,27.695-57.023,51.773-87.423,71.824C367.961,490.431,434.497,496.043,466.394,464.146z M438.887,267.166
c-20.35-32.745-45.688-64.367-75.403-94.082c-29.715-29.702-61.325-55.053-94.082-75.415
c-32.757,20.363-64.367,45.713-94.082,75.415c-29.702,29.715-55.053,61.325-75.415,94.082
c20.363,32.757,45.713,64.367,75.415,94.082c29.715,29.702,61.325,55.053,94.082,75.415c32.757-20.363,64.367-45.713,94.082-75.415
C393.199,331.533,418.537,299.911,438.887,267.166z M157.688,155.452c27.682-27.695,57.023-51.773,87.423-71.824
C170.831,43.901,104.307,38.29,72.422,70.186c-13.093,13.105-20.138,32.358-20.637,56.125c20.899,3.554,36.872,21.784,36.872,43.68
c0,15.337-7.818,28.867-19.677,36.835c4.738,11.834,10.375,23.891,16.884,36.062C105.915,212.488,129.994,183.147,157.688,155.452z
M245.112,450.704c-30.4-20.051-59.729-44.129-87.423-71.824c-27.695-27.695-51.773-57.023-71.824-87.423
c-39.728,74.268-45.339,140.805-13.442,172.689C104.307,496.043,170.831,490.431,245.112,450.704z M63.719,169.992
c0-10.686-8.691-19.39-19.39-19.39c-10.686,0-19.39,8.704-19.39,19.39c0,10.699,8.704,19.39,19.39,19.39
C55.028,189.382,63.719,180.691,63.719,169.992z"/>
<path style="fill:#9e8feb;" d="M453.788,27.179c10.686,0,19.39,8.704,19.39,19.39s-8.704,19.39-19.39,19.39
c-10.686,0-19.39-8.704-19.39-19.39S443.101,27.179,453.788,27.179z"/>
<path style="fill:#7067a1;" d="M269.402,201.253c36.348,0,65.913,29.565,65.913,65.913c0,36.336-29.565,65.913-65.913,65.913
c-36.336,0-65.901-29.577-65.901-65.913C203.501,230.818,233.066,201.253,269.402,201.253z M310.377,267.166
c0-22.595-18.38-40.975-40.975-40.975c-22.582,0-40.962,18.38-40.962,40.975s18.38,40.975,40.962,40.975
C291.997,308.141,310.377,289.761,310.377,267.166z"/>
<path style="fill:#fbb0ff;" d="M269.402,226.192c22.595,0,40.975,18.38,40.975,40.975s-18.38,40.975-40.975,40.975
c-22.582,0-40.962-18.38-40.962-40.975S246.82,226.192,269.402,226.192z"/>
<path style="fill:#9e8feb;" d="M44.329,150.602c10.699,0,19.39,8.704,19.39,19.39c0,10.699-8.691,19.39-19.39,19.39
c-10.686,0-19.39-8.691-19.39-19.39C24.939,159.306,33.643,150.602,44.329,150.602z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -0,0 +1,33 @@
const id = window.location.pathname.split("/").pop();
if (id && RufflePlayer) {
document.title = `Flash Game - ${id}`;
window.addEventListener("load", loadRuffle);
} else {
document.querySelector("#loader").classList.add("hidden");
document.querySelector("#error").classList.remove("hidden");
}
function loadRuffle() {
const ruffle = RufflePlayer.newest().createPlayer();
ruffle.config = {
splashScreen: false,
unmuteOverlay: "hidden",
autoplay: "on",
contextMenu: "on",
showSwfDownload: false
};
ruffle.style.width = "100%";
ruffle.style.height = "100%";
const gameContainer = document.querySelector("#gameContainer");
if (gameContainer != null) {
gameContainer.appendChild(ruffle);
}
ruffle.load(`/games/flash/${id}.swf`).then(() => {
let loader = document.querySelector("#loader");
loader.classList.remove("loading");
loader.classList.add("hidden");
document.querySelector("#gameContainer").classList.remove("hidden");
});
// Stop the event listener, saves miniscule amount of memory
window.removeEventListener("load", loadRuffle);
}

73
public/game.css Normal file
View file

@ -0,0 +1,73 @@
.vertical {
height: 70vh !important;
width: 30% !important;
aspect-ratio: auto !important;
}
#main-content {
margin-top: 2rem;
}
.game-container {
display: flex;
align-items: center;
flex-direction: column;
overflow: hidden;
background: var(--dropdown-background-color);
width: 80%;
margin: 0 auto;
margin-bottom: 4rem;
border-radius: 15px;
}
#game-frame {
aspect-ratio: 16 / 8;
height: 80vh;
width: 1350px;
border: 0;
}
.flash-frame {
width: 1024px !important;
height: 576px !important;
}
.game-info {
display: flex;
flex-direction: column;
gap: 1rem;
background-color: var(--background-highlight);
width: 100%;
padding: 1rem;
padding-top: 0;
}
.game-info-top {
display: flex;
justify-content: space-between;
margin-top: 0.5rem;
}
.icn {
width: 32px;
height: 32px;
cursor: pointer;
}
.game-info-left {
display: flex;
gap: 10px;
justify-content: center;
align-items: center;
height: 48px;
}
.game-title {
font-weight: bold;
font-size: 20px;
}
.game-img {
width: 48px;
height: 48px;
border-radius: 50%;
border: 3px solid var(--accent-color-brighter);
box-shadow: 0px 0px 20px 5px var(--accent-color-brighter);
}
.game-desc {
margin: 0;
}

@ -1 +1 @@
Subproject commit beacfb38111fdfd430f75bc9684fca4e25f4dccc Subproject commit 3b028f45966cc75fc1fd73e92d78f7eb0d7cfcba

BIN
public/icons/canvas.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
public/icons/classlink.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
public/icons/classroom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
public/icons/clever.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
public/icons/drive.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
public/icons/edgenuity.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
public/icons/google.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
public/icons/schoology.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
public/icons/youtube.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

11
public/iframe.css Normal file
View file

@ -0,0 +1,11 @@
/* CSS for about:blank iframes */
body {
margin: 0;
}
iframe {
width: 100%;
height: 100%;
border: none;
}

View file

@ -1,65 +0,0 @@
<svg width="100%" height="100%" preserveAspectRatio="none" id="svg" viewBox="0 0 1440 390"
xmlns="http://www.w3.org/2000/svg" class="transition duration-300 ease-in-out delay-150">
<style>
.path-0{
animation:pathAnim-0 15s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes pathAnim-0{
0%{
d: path("M 0,400 L 0,100 C 124.53333333333336,122.66666666666667 249.06666666666672,145.33333333333334 415,143 C 580.9333333333333,140.66666666666666 788.2666666666667,113.33333333333333 966,102 C 1143.7333333333333,90.66666666666667 1291.8666666666668,95.33333333333334 1440,100 L 1440,400 L 0,400 Z");
}
25%{
d: path("M 0,400 L 0,100 C 171.19999999999993,71.6 342.39999999999986,43.2 497,54 C 651.6000000000001,64.8 789.6000000000001,114.80000000000001 944,129 C 1098.3999999999999,143.2 1269.1999999999998,121.6 1440,100 L 1440,400 L 0,400 Z");
}
50%{
d: path("M 0,400 L 0,100 C 186.66666666666669,82.13333333333333 373.33333333333337,64.26666666666667 540,54 C 706.6666666666666,43.733333333333334 853.3333333333333,41.06666666666666 1000,50 C 1146.6666666666667,58.93333333333334 1293.3333333333335,79.46666666666667 1440,100 L 1440,400 L 0,400 Z");
}
75%{
d: path("M 0,400 L 0,100 C 110.13333333333333,74.53333333333333 220.26666666666665,49.06666666666666 393,58 C 565.7333333333333,66.93333333333334 801.0666666666666,110.26666666666668 986,123 C 1170.9333333333334,135.73333333333332 1305.4666666666667,117.86666666666666 1440,100 L 1440,400 L 0,400 Z");
}
100%{
d: path("M 0,400 L 0,100 C 124.53333333333336,122.66666666666667 249.06666666666672,145.33333333333334 415,143 C 580.9333333333333,140.66666666666666 788.2666666666667,113.33333333333333 966,102 C 1143.7333333333333,90.66666666666667 1291.8666666666668,95.33333333333334 1440,100 L 1440,400 L 0,400 Z");
}
}</style>
<style media="screen"></style>
<defs>
<linearGradient id="gradient" x1="0%" y1="53%" x2="100%" y2="47%">
<stop offset="5%" stop-color="#702dc2"></stop>
<stop offset="95%" stop-color="#3d097d"></stop>
</linearGradient>
</defs>
<path d="M 0,400 L 0,100 C 124.53333333333336,122.66666666666667 249.06666666666672,145.33333333333334 415,143 C 580.9333333333333,140.66666666666666 788.2666666666667,113.33333333333333 966,102 C 1143.7333333333333,90.66666666666667 1291.8666666666668,95.33333333333334 1440,100 L 1440,400 L 0,400 Z" stroke="none" stroke-width="0" fill="url(#gradient)" fill-opacity="0.53" class="transition-all duration-300 ease-in-out delay-150 path-0"></path>
<style>
.path-1{
animation:pathAnim-1 15s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes pathAnim-1{
0%{
d: path("M 0,400 L 0,233 C 170.53333333333336,233.66666666666666 341.0666666666667,234.33333333333331 507,236 C 672.9333333333333,237.66666666666669 834.2666666666667,240.33333333333334 989,240 C 1143.7333333333333,239.66666666666666 1291.8666666666668,236.33333333333331 1440,233 L 1440,400 L 0,400 Z");
}
25%{
d: path("M 0,400 L 0,233 C 202,220.46666666666667 404,207.93333333333334 539,220 C 674,232.06666666666666 742.0000000000001,268.7333333333333 881,275 C 1019.9999999999999,281.2666666666667 1230,257.1333333333333 1440,233 L 1440,400 L 0,400 Z");
}
50%{
d: path("M 0,400 L 0,233 C 181.33333333333337,210.86666666666667 362.66666666666674,188.73333333333332 512,188 C 661.3333333333333,187.26666666666668 778.6666666666665,207.93333333333334 928,219 C 1077.3333333333335,230.06666666666666 1258.6666666666667,231.53333333333333 1440,233 L 1440,400 L 0,400 Z");
}
75%{
d: path("M 0,400 L 0,233 C 195.06666666666666,222.86666666666667 390.1333333333333,212.73333333333332 559,216 C 727.8666666666667,219.26666666666668 870.5333333333333,235.93333333333334 1013,241 C 1155.4666666666667,246.06666666666666 1297.7333333333333,239.53333333333333 1440,233 L 1440,400 L 0,400 Z");
}
100%{
d: path("M 0,400 L 0,233 C 170.53333333333336,233.66666666666666 341.0666666666667,234.33333333333331 507,236 C 672.9333333333333,237.66666666666669 834.2666666666667,240.33333333333334 989,240 C 1143.7333333333333,239.66666666666666 1291.8666666666668,236.33333333333331 1440,233 L 1440,400 L 0,400 Z");
}
}</style>
<style media="screen"></style>
<defs>
<linearGradient id="gradient" x1="0%" y1="53%" x2="100%" y2="47%">
<stop offset="5%" stop-color="#702dc2"></stop>
<stop offset="95%" stop-color="#3d097d"></stop>
</linearGradient>
</defs>
<path d="M 0,400 L 0,233 C 170.53333333333336,233.66666666666666 341.0666666666667,234.33333333333331 507,236 C 672.9333333333333,237.66666666666669 834.2666666666667,240.33333333333334 989,240 C 1143.7333333333333,239.66666666666666 1291.8666666666668,236.33333333333331 1440,233 L 1440,400 L 0,400 Z" stroke="none" stroke-width="0" fill="url(#gradient)" fill-opacity="1" class="transition-all duration-300 ease-in-out delay-150 path-1"></path>
</svg>

Before

Width:  |  Height:  |  Size: 5.3 KiB

3
public/img/checkmark.svg Normal file
View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check" viewBox="0 0 16 16">
<path fill="#fff" d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425z"/>
</svg>

After

Width:  |  Height:  |  Size: 283 B

View file

@ -0,0 +1,4 @@
<svg stroke="#fff" fill="#fff" stroke-width="0" viewBox="0 0 256 256" height="1em" width="1em"
xmlns="http://www.w3.org/2000/svg">
<path d="M220,48V88a12,12,0,0,1-24,0V60H168a12,12,0,0,1,0-24h40A12,12,0,0,1,220,48ZM88,196H60V168a12,12,0,0,0-24,0v40a12,12,0,0,0,12,12H88a12,12,0,0,0,0-24Zm120-40a12,12,0,0,0-12,12v28H168a12,12,0,0,0,0,24h40a12,12,0,0,0,12-12V168A12,12,0,0,0,208,156ZM88,36H48A12,12,0,0,0,36,48V88a12,12,0,0,0,24,0V60H88a12,12,0,0,0,0-24Z"></path>
</svg>

After

Width:  |  Height:  |  Size: 477 B

View file

@ -0,0 +1,3 @@
<svg version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path fill="#fff" d="M21.436 7.586l-3.998-4.02c-.752-.756-2.063-.764-2.83-.006-.196.196-.35.436-.418.629-.653 1.362-1.354 2.215-2.254 2.727l-.217.105c-.968.485-2.285.979-4.719.979-.266 0-.521.052-.766.152-.484.202-.879.595-1.082 1.084-.199.484-.199 1.041 0 1.525.104.249.25.471.435.651l3.235 3.235-3.822 5.353 5.352-3.822 3.227 3.227c.186.189.406.339.656.441.247.103.503.154.766.154s.519-.052.765-.154c.498-.205.883-.592 1.08-1.078.103-.242.155-.507.155-.768 0-2.436.494-3.752.978-4.721.496-.992 1.369-1.748 2.754-2.414.271-.104.51-.256.711-.457.772-.782.768-2.051-.008-2.822zm-5.248 4.801c-.819 1.643-1.188 3.37-1.195 5.604l-7.993-7.991c2.139 0 3.814-.335 5.396-1.084l.235-.105c1.399-.699 2.468-1.893 3.388-3.834l3.924 4.051c-1.863.893-3.056 1.96-3.755 3.359z" />
</svg>

After

Width:  |  Height:  |  Size: 892 B

3
public/img/games/pin.svg Normal file
View file

@ -0,0 +1,3 @@
<svg version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path fill="#fff" d="M16.729 4.271c-.389-.391-1.021-.393-1.414-.004-.104.104-.176.227-.225.355-.832 1.736-1.748 2.715-2.904 3.293-1.297.64-2.786 1.085-5.186 1.085-.13 0-.26.025-.382.076-.245.102-.439.297-.541.541-.101.244-.101.52 0 .764.051.123.124.234.217.326l3.243 3.243-4.537 6.05 6.05-4.537 3.242 3.242c.092.094.203.166.326.217.122.051.252.078.382.078s.26-.027.382-.078c.245-.102.44-.295.541-.541.051-.121.077-.252.077-.381 0-2.4.444-3.889 1.083-5.166.577-1.156 1.556-2.072 3.293-2.904.129-.049.251-.121.354-.225.389-.393.387-1.025-.004-1.414l-3.997-4.02z" />
</svg>

After

Width:  |  Height:  |  Size: 691 B

View file

@ -1,96 +0,0 @@
<svg width="100%" height="100%" id="svg" viewBox="0 0 1440 590"
xmlns="http://www.w3.org/2000/svg" class="transition duration-300 ease-in-out delay-150">
<style>
.path-0{
animation:pathAnim-0 15s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes pathAnim-0{
0%{
d: path("M 0,600 L 0,112 C 283.5,125.5 567,139 807,139 C 1047,139 1243.5,125.5 1440,112 L 1440,600 L 0,600 Z");
}
25%{
d: path("M 0,600 L 0,112 C 289.5,106 579,100 819,100 C 1059,100 1249.5,106 1440,112 L 1440,600 L 0,600 Z");
}
50%{
d: path("M 0,600 L 0,112 C 300.5,84 601,56 841,56 C 1081,56 1260.5,84 1440,112 L 1440,600 L 0,600 Z");
}
75%{
d: path("M 0,600 L 0,112 C 256,112.5 512,113 752,113 C 992,113 1216,112.5 1440,112 L 1440,600 L 0,600 Z");
}
100%{
d: path("M 0,600 L 0,112 C 283.5,125.5 567,139 807,139 C 1047,139 1243.5,125.5 1440,112 L 1440,600 L 0,600 Z");
}
}</style>
<style media="screen"></style>
<defs>
<linearGradient id="gradient" x1="0%" y1="50%" x2="100%" y2="50%">
<stop offset="5%" stop-color="#1e2030"></stop>
<stop offset="95%" stop-color="#181926"></stop>
</linearGradient>
</defs>
<path d="M 0,600 L 0,112 C 283.5,125.5 567,139 807,139 C 1047,139 1243.5,125.5 1440,112 L 1440,600 L 0,600 Z" stroke="none" stroke-width="0" fill="url(#gradient)" fill-opacity="0.4" class="transition-all duration-300 ease-in-out delay-150 path-0"></path>
<style>
.path-1{
animation:pathAnim-1 15s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes pathAnim-1{
0%{
d: path("M 0,600 L 0,262 C 259,246.5 518,231 758,231 C 998,231 1219,246.5 1440,262 L 1440,600 L 0,600 Z");
}
25%{
d: path("M 0,600 L 0,262 C 191,240.5 382,219 622,219 C 862,219 1151,240.5 1440,262 L 1440,600 L 0,600 Z");
}
50%{
d: path("M 0,600 L 0,262 C 305.5,268.5 611,275 851,275 C 1091,275 1265.5,268.5 1440,262 L 1440,600 L 0,600 Z");
}
75%{
d: path("M 0,600 L 0,262 C 286,273.5 572,285 812,285 C 1052,285 1246,273.5 1440,262 L 1440,600 L 0,600 Z");
}
100%{
d: path("M 0,600 L 0,262 C 259,246.5 518,231 758,231 C 998,231 1219,246.5 1440,262 L 1440,600 L 0,600 Z");
}
}</style>
<style media="screen"></style>
<defs>
<linearGradient id="gradient" x1="0%" y1="50%" x2="100%" y2="50%">
<stop offset="5%" stop-color="#1e2030"></stop>
<stop offset="95%" stop-color="#181926"></stop>
</linearGradient>
</defs>
<path d="M 0,600 L 0,262 C 259,246.5 518,231 758,231 C 998,231 1219,246.5 1440,262 L 1440,600 L 0,600 Z" stroke="none" stroke-width="0" fill="url(#gradient)" fill-opacity="0.53" class="transition-all duration-300 ease-in-out delay-150 path-1"></path>
<style>
.path-2{
animation:pathAnim-2 15s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes pathAnim-2{
0%{
d: path("M 0,600 L 0,412 C 209,406.5 418,401 658,401 C 898,401 1169,406.5 1440,412 L 1440,600 L 0,600 Z");
}
25%{
d: path("M 0,600 L 0,412 C 218,423 436,434 676,434 C 916,434 1178,423 1440,412 L 1440,600 L 0,600 Z");
}
50%{
d: path("M 0,600 L 0,412 C 264,431 528,450 768,450 C 1008,450 1224,431 1440,412 L 1440,600 L 0,600 Z");
}
75%{
d: path("M 0,600 L 0,412 C 245.5,439.5 491,467 731,467 C 971,467 1205.5,439.5 1440,412 L 1440,600 L 0,600 Z");
}
100%{
d: path("M 0,600 L 0,412 C 209,406.5 418,401 658,401 C 898,401 1169,406.5 1440,412 L 1440,600 L 0,600 Z");
}
}</style>
<style media="screen"></style>
<defs>
<linearGradient id="gradient" x1="0%" y1="50%" x2="100%" y2="50%">
<stop offset="5%" stop-color="#1e2030"></stop>
<stop offset="95%" stop-color="#181926"></stop>
</linearGradient>
</defs>
<path d="M 0,600 L 0,412 C 209,406.5 418,401 658,401 C 898,401 1169,406.5 1440,412 L 1440,600 L 0,600 Z" stroke="none" stroke-width="0" fill="url(#gradient)" fill-opacity="1" class="transition-all duration-300 ease-in-out delay-150 path-2"></path>
</svg>

Before

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -1,93 +0,0 @@
<svg width="100%" height="100%" id="svg" viewBox="0 0 1440 590"
xmlns="http://www.w3.org/2000/svg" class="transition duration-300 ease-in-out delay-150">
<style>
.path-0{
animation:pathAnim-0 15s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes pathAnim-0{
0%{
d: path("M 0,600 L 0,112 C 133.2,136.13333333333333 266.4,160.26666666666668 417,163 C 567.6,165.73333333333332 735.5999999999999,147.06666666666666 909,135 C 1082.4,122.93333333333334 1261.2,117.46666666666667 1440,112 L 1440,600 L 0,600 Z");
}
25%{
d: path("M 0,600 L 0,112 C 166.53333333333336,123.60000000000001 333.0666666666667,135.20000000000002 475,129 C 616.9333333333333,122.79999999999998 734.2666666666667,98.79999999999998 891,93 C 1047.7333333333333,87.20000000000002 1243.8666666666668,99.60000000000001 1440,112 L 1440,600 L 0,600 Z");
}
50%{
d: path("M 0,600 L 0,112 C 178.66666666666669,132.53333333333333 357.33333333333337,153.06666666666666 507,164 C 656.6666666666666,174.93333333333334 777.3333333333333,176.26666666666668 928,166 C 1078.6666666666667,155.73333333333332 1259.3333333333335,133.86666666666667 1440,112 L 1440,600 L 0,600 Z");
}
75%{
d: path("M 0,600 L 0,112 C 152,116.4 304,120.8 482,107 C 660,93.2 864,61.199999999999996 1028,59 C 1192,56.800000000000004 1316,84.4 1440,112 L 1440,600 L 0,600 Z");
}
100%{
d: path("M 0,600 L 0,112 C 133.2,136.13333333333333 266.4,160.26666666666668 417,163 C 567.6,165.73333333333332 735.5999999999999,147.06666666666666 909,135 C 1082.4,122.93333333333334 1261.2,117.46666666666667 1440,112 L 1440,600 L 0,600 Z");
}
}</style>
<defs>
<linearGradient id="gradient" x1="0%" y1="50%" x2="100%" y2="50%">
<stop offset="5%" stop-color="#181825"></stop>
<stop offset="95%" stop-color="#11111b"></stop>
</linearGradient>
</defs>
<path d="M 0,600 L 0,112 C 133.2,136.13333333333333 266.4,160.26666666666668 417,163 C 567.6,165.73333333333332 735.5999999999999,147.06666666666666 909,135 C 1082.4,122.93333333333334 1261.2,117.46666666666667 1440,112 L 1440,600 L 0,600 Z" stroke="none" stroke-width="0" fill="url(#gradient)" fill-opacity="0.4" class="transition-all duration-300 ease-in-out delay-150 path-0"></path>
<style>
.path-1{
animation:pathAnim-1 15s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes pathAnim-1{
0%{
d: path("M 0,600 L 0,262 C 126.53333333333336,275.4666666666667 253.06666666666672,288.93333333333334 423,294 C 592.9333333333333,299.06666666666666 806.2666666666667,295.73333333333335 983,289 C 1159.7333333333333,282.26666666666665 1299.8666666666668,272.1333333333333 1440,262 L 1440,600 L 0,600 Z");
}
25%{
d: path("M 0,600 L 0,262 C 111.46666666666664,236.13333333333333 222.93333333333328,210.26666666666668 393,211 C 563.0666666666667,211.73333333333332 791.7333333333333,239.06666666666666 976,252 C 1160.2666666666667,264.93333333333334 1300.1333333333332,263.4666666666667 1440,262 L 1440,600 L 0,600 Z");
}
50%{
d: path("M 0,600 L 0,262 C 164.66666666666663,293.3333333333333 329.33333333333326,324.66666666666663 508,314 C 686.6666666666667,303.33333333333337 879.3333333333335,250.66666666666669 1037,235 C 1194.6666666666665,219.33333333333331 1317.3333333333333,240.66666666666666 1440,262 L 1440,600 L 0,600 Z");
}
75%{
d: path("M 0,600 L 0,262 C 122.13333333333333,279.4666666666667 244.26666666666665,296.93333333333334 392,303 C 539.7333333333333,309.06666666666666 713.0666666666668,303.73333333333335 892,295 C 1070.9333333333332,286.26666666666665 1255.4666666666667,274.1333333333333 1440,262 L 1440,600 L 0,600 Z");
}
100%{
d: path("M 0,600 L 0,262 C 126.53333333333336,275.4666666666667 253.06666666666672,288.93333333333334 423,294 C 592.9333333333333,299.06666666666666 806.2666666666667,295.73333333333335 983,289 C 1159.7333333333333,282.26666666666665 1299.8666666666668,272.1333333333333 1440,262 L 1440,600 L 0,600 Z");
}
}</style>
<defs>
<linearGradient id="gradient" x1="0%" y1="50%" x2="100%" y2="50%">
<stop offset="5%" stop-color="#181825"></stop>
<stop offset="95%" stop-color="#11111b"></stop>
</linearGradient>
</defs>
<path d="M 0,600 L 0,262 C 126.53333333333336,275.4666666666667 253.06666666666672,288.93333333333334 423,294 C 592.9333333333333,299.06666666666666 806.2666666666667,295.73333333333335 983,289 C 1159.7333333333333,282.26666666666665 1299.8666666666668,272.1333333333333 1440,262 L 1440,600 L 0,600 Z" stroke="none" stroke-width="0" fill="url(#gradient)" fill-opacity="0.53" class="transition-all duration-300 ease-in-out delay-150 path-1"></path>
<style>
.path-2{
animation:pathAnim-2 15s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes pathAnim-2{
0%{
d: path("M 0,600 L 0,412 C 126,431.20000000000005 252,450.40000000000003 417,459 C 582,467.59999999999997 786,465.6 963,456 C 1140,446.4 1290,429.2 1440,412 L 1440,600 L 0,600 Z");
}
25%{
d: path("M 0,600 L 0,412 C 186.93333333333334,388 373.8666666666667,364 512,368 C 650.1333333333333,372 739.4666666666667,404 886,416 C 1032.5333333333333,428 1236.2666666666667,420 1440,412 L 1440,600 L 0,600 Z");
}
50%{
d: path("M 0,600 L 0,412 C 139.33333333333331,406.4 278.66666666666663,400.8 438,405 C 597.3333333333334,409.2 776.6666666666667,423.20000000000005 947,426 C 1117.3333333333333,428.79999999999995 1278.6666666666665,420.4 1440,412 L 1440,600 L 0,600 Z");
}
75%{
d: path("M 0,600 L 0,412 C 168.66666666666663,412.1333333333333 337.33333333333326,412.2666666666667 491,413 C 644.6666666666667,413.7333333333333 783.3333333333335,415.06666666666666 939,415 C 1094.6666666666665,414.93333333333334 1267.3333333333333,413.4666666666667 1440,412 L 1440,600 L 0,600 Z");
}
100%{
d: path("M 0,600 L 0,412 C 126,431.20000000000005 252,450.40000000000003 417,459 C 582,467.59999999999997 786,465.6 963,456 C 1140,446.4 1290,429.2 1440,412 L 1440,600 L 0,600 Z");
}
}</style>
<defs>
<linearGradient id="gradient" x1="0%" y1="50%" x2="100%" y2="50%">
<stop offset="5%" stop-color="#181825"></stop>
<stop offset="95%" stop-color="#11111b"></stop>
</linearGradient>
</defs>
<path d="M 0,600 L 0,412 C 126,431.20000000000005 252,450.40000000000003 417,459 C 582,467.59999999999997 786,465.6 963,456 C 1140,446.4 1290,429.2 1440,412 L 1440,600 L 0,600 Z" stroke="none" stroke-width="0" fill="url(#gradient)" fill-opacity="1" class="transition-all duration-300 ease-in-out delay-150 path-2"></path>
</svg>

Before

Width:  |  Height:  |  Size: 7.2 KiB

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="800px" height="800px" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path fill="#fff" fill-rule="evenodd" clip-rule="evenodd" d="M11.7071 4.29289C12.0976 4.68342 12.0976 5.31658 11.7071 5.70711L6.41421 11H20C20.5523 11 21 11.4477 21 12C21 12.5523 20.5523 13 20 13H6.41421L11.7071 18.2929C12.0976 18.6834 12.0976 19.3166 11.7071 19.7071C11.3166 20.0976 10.6834 20.0976 10.2929 19.7071L3.29289 12.7071C3.10536 12.5196 3 12.2652 3 12C3 11.7348 3.10536 11.4804 3.29289 11.2929L10.2929 4.29289C10.6834 3.90237 11.3166 3.90237 11.7071 4.29289Z"/>
</svg>

After

Width:  |  Height:  |  Size: 616 B

3
public/img/nav/close.svg Normal file
View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
<path fill="#fc847c" d="M376.6 84.5c11.3-13.6 9.5-33.8-4.1-45.1s-33.8-9.5-45.1 4.1L192 206 56.6 43.5C45.3 29.9 25.1 28.1 11.5 39.4S-3.9 70.9 7.4 84.5L150.3 256 7.4 427.5c-11.3 13.6-9.5 33.8 4.1 45.1s33.8 9.5 45.1-4.1L192 306 327.4 468.5c11.3 13.6 31.5 15.4 45.1 4.1s15.4-31.5 4.1-45.1L233.7 256 376.6 84.5z" />
</svg>

After

Width:  |  Height:  |  Size: 384 B

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="800px" height="800px" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path fill="#fff" fill-rule="evenodd" clip-rule="evenodd" d="M12.2929 4.29289C12.6834 3.90237 13.3166 3.90237 13.7071 4.29289L20.7071 11.2929C21.0976 11.6834 21.0976 12.3166 20.7071 12.7071L13.7071 19.7071C13.3166 20.0976 12.6834 20.0976 12.2929 19.7071C11.9024 19.3166 11.9024 18.6834 12.2929 18.2929L17.5858 13H4C3.44772 13 3 12.5523 3 12C3 11.4477 3.44772 11 4 11H17.5858L12.2929 5.70711C11.9024 5.31658 11.9024 4.68342 12.2929 4.29289Z"/>
</svg>

After

Width:  |  Height:  |  Size: 587 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path fill="#fff" d="M463.5 224l8.5 0c13.3 0 24-10.7 24-24l0-128c0-9.7-5.8-18.5-14.8-22.2s-19.3-1.7-26.2 5.2L413.4 96.6c-87.6-86.5-228.7-86.2-315.8 1c-87.5 87.5-87.5 229.3 0 316.8s229.3 87.5 316.8 0c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0c-62.5 62.5-163.8 62.5-226.3 0s-62.5-163.8 0-226.3c62.2-62.2 162.7-62.5 225.3-1L327 183c-6.9 6.9-8.9 17.2-5.2 26.2s12.5 14.8 22.2 14.8l119.5 0z" />
</svg>

After

Width:  |  Height:  |  Size: 464 B

15
public/img/nav/share.svg Normal file
View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#fff" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 458.624 458.624" xml:space="preserve">
<g>
<g>
<path d="M339.588,314.529c-14.215,0-27.456,4.133-38.621,11.239l-112.682-78.67c1.809-6.315,2.798-12.976,2.798-19.871
c0-6.896-0.989-13.557-2.798-19.871l109.64-76.547c11.764,8.356,26.133,13.286,41.662,13.286c39.79,0,72.047-32.257,72.047-72.047
C411.634,32.258,379.378,0,339.588,0c-39.79,0-72.047,32.257-72.047,72.047c0,5.255,0.578,10.373,1.646,15.308l-112.424,78.491
c-10.974-6.759-23.892-10.666-37.727-10.666c-39.79,0-72.047,32.257-72.047,72.047s32.256,72.047,72.047,72.047
c13.834,0,26.753-3.907,37.727-10.666l113.292,79.097c-1.629,6.017-2.514,12.34-2.514,18.872c0,39.79,32.257,72.047,72.047,72.047
c39.79,0,72.047-32.257,72.047-72.047C411.635,346.787,379.378,314.529,339.588,314.529z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1,7 +0,0 @@
{
"nav": {
"brand": "Alu",
"games": "Games",
"settings": "Settings"
}
}

View file

@ -1,5 +0,0 @@
{
"brand": "アルー",
"games": "ゲーム",
"settings": "設定"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -0,0 +1,9 @@
[data-theme="atom-one-dark"] {
--background-color: #1e2127;
--background-highlight: #434952;
--accent-color: #3a3f4b;
--accent-color-brighter: #4b515f;
--text-color: #abb2bf;
--text-color-accent: #989eaa;
--dropdown-background-color: #30353f;
}

View file

@ -0,0 +1,56 @@
<svg width="190" height="190" viewBox="0 0 190 190" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_511_171)">
<circle cx="95" cy="95" r="75" fill="white" fill-opacity="0.18" shape-rendering="crispEdges"/>
</g>
<g clip-path="url(#clip0_511_171)">
<path d="M95 165C133.66 165 165 133.66 165 95C165 56.3401 133.66 25 95 25C56.3401 25 25 56.3401 25 95C25 133.66 56.3401 165 95 165Z" fill="black" fill-opacity="0.24"/>
<path d="M153.503 83.6581C153.503 100.319 146.557 115.357 135.403 126.035C131.708 129.574 127.55 132.631 123.03 135.111C114.667 139.703 105.059 142.315 94.8455 142.315C84.6318 142.315 75.0289 139.706 66.6659 135.114C65.3178 134.376 64.0037 133.586 62.7251 132.746C59.7085 130.771 56.8855 128.52 54.2904 126.035C43.1357 115.359 36.1877 100.319 36.1877 83.6578C36.1877 51.262 62.4497 25 94.8455 25C127.241 25 153.503 51.2623 153.503 83.6581Z" fill="white" fill-opacity="0.3"/>
<path d="M143.397 145.571C138.988 149.794 134.026 153.443 128.631 156.403C118.652 161.883 107.186 165 94.9973 165C82.8088 165 71.3487 161.886 61.3688 156.406C55.9745 153.448 51.0116 149.797 46.6002 145.571C51.0775 134.205 61.966 126.068 74.8116 125.611C75.1886 125.594 75.5714 125.585 75.9545 125.585H114.043C114.426 125.585 114.809 125.594 115.186 125.611C128.032 126.068 138.92 134.206 143.397 145.571Z" fill="#0E0D11"/>
<path d="M94.9973 147.674C94.9973 147.674 143.476 112.481 141.733 109.313C139.131 104.579 135.267 101.349 131.45 99.1579C125.043 95.4813 118.76 94.7354 118.76 94.7354L80.1704 127.487L94.9973 147.674Z" fill="#F87359"/>
<path d="M94.9973 147.674C94.9973 147.674 143.476 112.481 141.733 109.313C139.131 104.579 135.267 101.349 131.45 99.1578C135.353 103.476 139.1 110.045 133.335 115.807C132.404 116.739 131.379 117.37 130.287 117.749C126.476 119.074 122.93 121.065 120.008 123.848L94.9973 147.674Z" fill="#0E0D11"/>
<path d="M94.9973 147.674C94.9973 147.674 46.519 112.481 48.2611 109.313C50.8634 104.579 54.7276 101.349 58.5442 99.1579C64.9514 95.4813 71.2347 94.7354 71.2347 94.7354L94.9973 147.674Z" fill="#F87359"/>
<path d="M135.102 65.9344L121.749 73.8097V89.8293C121.749 93.5166 124.738 96.5059 128.426 96.5059C132.113 96.5059 135.102 93.5166 135.102 89.8293V65.9344Z" fill="#CCCCCC"/>
<path d="M54.8916 65.9344L68.2447 73.8097V89.8293C68.2447 93.5166 65.2555 96.5059 61.5682 96.5059C57.8809 96.5059 54.8916 93.5166 54.8916 89.8293V65.9344Z" fill="#CCCCCC"/>
<path d="M109.826 109.273V125.202C109.826 133.391 103.188 140.029 94.9984 140.029C86.8092 140.029 80.1707 133.391 80.1707 125.202V109.273H109.826Z" fill="#CCCCCC"/>
<path d="M128.012 64.663V92.6572C128.012 101.774 124.317 110.029 118.346 116C112.366 121.98 104.114 125.672 94.9973 125.672C76.7631 125.672 61.983 110.891 61.983 92.6572V64.663C61.983 63.1571 62.0831 61.6715 62.2802 60.2201C62.8859 55.703 64.4086 51.4773 66.6544 47.7317C72.4173 38.0974 117.58 38.0974 123.34 47.7317C125.586 51.4775 127.109 55.7032 127.714 60.2201C127.911 61.6715 128.012 63.1571 128.012 64.663Z" fill="#EDEDED"/>
<path d="M71.5475 92.6575V64.6635C71.5475 48.0552 83.8139 34.3155 99.7802 31.9979C98.2184 31.7709 96.6223 31.6487 94.997 31.6487C76.7639 31.6487 61.9821 46.4304 61.9821 64.6635V92.6575C61.9821 110.891 76.7639 125.672 94.997 125.672C96.622 125.672 98.2181 125.55 99.7805 125.323C83.8139 123.006 71.5475 109.266 71.5475 92.6575Z" fill="#CCCCCC"/>
<path d="M111.432 86.1581V79.8308C111.432 78.1806 110.094 76.8427 108.444 76.8427C106.794 76.8427 105.456 78.1803 105.456 79.8308V86.1581C105.456 87.8083 106.793 89.1462 108.444 89.1462C110.094 89.146 111.432 87.8083 111.432 86.1581Z" fill="#0E0D11"/>
<path d="M78.5642 79.8305V86.1579C78.5642 87.8081 79.9019 89.146 81.5523 89.146C83.2025 89.146 84.5405 87.8083 84.5405 86.1579V79.8305C84.5405 78.1803 83.2028 76.8424 81.5523 76.8424C79.9019 76.8427 78.5642 78.1803 78.5642 79.8305Z" fill="#0E0D11"/>
<path d="M109.48 82.8925C110.558 82.8925 111.432 82.0184 111.432 80.9401C111.432 79.8619 110.558 78.9878 109.48 78.9878C108.402 78.9878 107.528 79.8619 107.528 80.9401C107.528 82.0184 108.402 82.8925 109.48 82.8925Z" fill="#7F7D89"/>
<path d="M82.5887 82.8925C83.6669 82.8925 84.541 82.0184 84.541 80.9401C84.541 79.8619 83.6669 78.9878 82.5887 78.9878C81.5104 78.9878 80.6363 79.8619 80.6363 80.9401C80.6363 82.0184 81.5104 82.8925 82.5887 82.8925Z" fill="#7F7D89"/>
<path d="M107.297 86.6995C107.917 86.6995 108.419 86.197 108.419 85.577C108.419 84.9571 107.917 84.4546 107.297 84.4546C106.677 84.4546 106.175 84.9571 106.175 85.577C106.175 86.197 106.677 86.6995 107.297 86.6995Z" fill="#7F7D89"/>
<path d="M80.4086 86.6995C81.0285 86.6995 81.531 86.197 81.531 85.577C81.531 84.9571 81.0285 84.4546 80.4086 84.4546C79.7886 84.4546 79.2861 84.9571 79.2861 85.577C79.2861 86.197 79.7886 86.6995 80.4086 86.6995Z" fill="#7F7D89"/>
<path d="M69.2829 60.2204C69.2829 60.5652 69.2963 60.907 69.3231 61.2452C69.6409 65.2842 68.1812 69.2835 65.1182 71.9355C64.1609 72.7646 63.1095 73.4884 61.9827 74.0891V64.6635C61.9827 58.472 63.6857 52.6833 66.6541 47.7319C68.4484 49.7291 69.774 52.1548 70.4625 54.8378C69.7057 56.4746 69.2829 58.3003 69.2829 60.2204Z" fill="#0E0D11"/>
<path d="M128.012 64.6629V74.0885C126.885 73.4878 125.834 72.764 124.876 71.9349C121.814 69.2829 120.353 65.2836 120.671 61.2446C120.698 60.9064 120.711 60.5646 120.711 60.2198C120.711 58.2997 120.289 56.474 119.531 54.8369C120.22 52.1539 121.546 49.7283 123.34 47.7311C126.309 52.6828 128.012 58.4714 128.012 64.6629Z" fill="#0E0D11"/>
<path d="M73.9132 78.0136L85.9927 82.6837L88.6714 75.7552L76.5919 71.085L73.9132 78.0136Z" fill="#EDEDED"/>
<path d="M113.406 71.0863L101.326 75.7565L104.005 82.685L116.085 78.0148L113.406 71.0863Z" fill="#EDEDED"/>
<path d="M110.617 95.4572C110.617 100.789 107.946 105.497 103.866 108.314C101.346 110.057 98.2914 111.077 94.997 111.077C91.7026 111.077 88.6483 110.057 86.1283 108.314C82.0484 105.497 79.3769 100.788 79.3769 95.4572C80.8225 96.1801 82.3084 96.7973 83.8197 97.3086C85.4026 97.8429 87.014 98.2629 88.6396 98.5629C90.7396 98.9514 92.868 99.1458 94.9967 99.1458C97.1252 99.1458 99.2539 98.9514 101.354 98.5629C102.979 98.2629 104.591 97.8429 106.174 97.3086C107.686 96.797 109.171 96.1798 110.617 95.4572Z" fill="#0E0D11"/>
<path d="M103.866 108.314C101.346 110.057 98.2914 111.077 94.997 111.077C91.7026 111.077 88.6483 110.057 86.1283 108.314C88.6483 106.571 91.7026 105.551 94.997 105.551C98.2914 105.551 101.346 106.571 103.866 108.314Z" fill="#F87359"/>
<path d="M113.404 71.4581H76.5903L86.9166 79.2019H88.0555C90.0456 79.2019 91.6589 80.8149 91.6589 82.8052V88.3929C91.6589 90.2318 93.0974 91.809 94.9357 91.8426C96.8085 91.8768 98.3379 90.3688 98.3379 88.5037V82.8052C98.3379 80.8152 99.9511 79.2019 101.941 79.2019H103.078L113.404 71.4581Z" fill="#CCCCCC"/>
<path d="M106.174 97.3086C106.003 98.623 105.706 99.8658 105.38 100.954C104.649 103.4 103.76 105.077 103.76 105.077L102.226 100.923L101.354 98.5629C102.98 98.2629 104.591 97.8429 106.174 97.3086Z" fill="#F0F0F0"/>
<path d="M88.6401 98.5629L87.7687 100.923L86.2344 105.077C86.2344 105.077 85.3457 103.4 84.6143 100.954C84.2886 99.8658 83.9914 98.623 83.82 97.3086C85.4029 97.8429 87.0143 98.2629 88.6401 98.5629Z" fill="#F0F0F0"/>
<path d="M71.3799 73.6013L74.2056 69.2049C74.7098 68.4205 75.7549 68.193 76.5397 68.6972L88.1006 76.1281C89.6786 77.1423 88.6743 79.5887 86.8387 79.2015L72.4521 76.1669C71.2952 75.923 70.7406 74.5963 71.3799 73.6013Z" fill="#0E0D11"/>
<path d="M118.614 73.6013L115.789 69.2049C115.284 68.4205 114.239 68.193 113.455 68.6972L101.894 76.1281C100.316 77.1423 101.32 79.5887 103.155 79.2015L117.542 76.1669C118.699 75.923 119.254 74.5963 118.614 73.6013Z" fill="#0E0D11"/>
<path d="M98.6162 116.791H91.3783C90.642 116.791 90.0448 116.194 90.0448 115.458C90.0448 114.721 90.6417 114.124 91.3783 114.124H98.6162C99.3526 114.124 99.9498 114.721 99.9498 115.458C99.9495 116.195 99.3526 116.791 98.6162 116.791Z" fill="#CCCCCC"/>
<path d="M123.34 47.7315C117.58 38.0972 107.043 31.6487 94.997 31.6487C82.9543 31.6487 72.4171 38.0972 66.6541 47.7315C64.4084 51.4773 62.8856 55.703 62.2799 60.2199H69.2827C69.2827 53.1198 75.0399 47.3629 82.1397 47.3629C82.3122 47.3629 82.4842 47.3664 82.6551 47.3733C88.6833 47.6111 93.3791 52.7179 93.3791 58.751V60.5075C93.3791 61.4009 94.1034 62.1252 94.9967 62.1252C95.89 62.1252 96.6144 61.4009 96.6144 60.5075V58.751C96.6144 52.7179 101.31 47.6111 107.338 47.3733C107.509 47.3664 107.681 47.3629 107.854 47.3629C114.954 47.3629 120.711 53.1201 120.711 60.2199H127.714C127.109 55.703 125.586 51.4773 123.34 47.7315Z" fill="#0E0D11"/>
<path d="M94.9973 147.674C94.9973 147.674 46.519 112.481 48.2611 109.313C50.8634 104.579 54.7276 101.349 58.5442 99.158C54.642 103.476 50.8943 110.045 56.6597 115.808C57.591 116.739 58.6159 117.37 59.7074 117.749C63.5189 119.075 67.0645 121.065 69.9862 123.848L94.9973 147.674Z" fill="#0E0D11"/>
<path d="M106.604 145.612L95.788 149.62C95.2786 149.809 94.7184 149.809 94.2089 149.62L83.3934 145.612C81.9095 145.062 80.3317 146.16 80.3317 147.743V154.412C80.3317 155.994 81.9095 157.092 83.3934 156.542L94.2089 152.534C94.7184 152.345 95.2786 152.345 95.788 152.534L106.604 156.542C108.088 157.092 109.665 155.994 109.665 154.412V147.743C109.665 146.16 108.088 145.062 106.604 145.612Z" fill="#F87359"/>
<path d="M105.38 100.954C104.649 103.4 103.76 105.077 103.76 105.077L102.226 100.923C102.703 100.746 103.22 100.649 103.76 100.649C104.331 100.649 104.877 100.757 105.38 100.954Z" fill="#F87359"/>
<path d="M87.7687 100.923L86.2344 105.077C86.2344 105.077 85.3457 103.4 84.6143 100.954C85.1172 100.757 85.6629 100.649 86.2344 100.649C86.7742 100.649 87.2915 100.746 87.7687 100.923Z" fill="#F87359"/>
</g>
<defs>
<filter id="filter0_d_511_171" x="0" y="0" width="190" height="190" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="10"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.06 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_511_171"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_511_171" result="shape"/>
</filter>
<clipPath id="clip0_511_171">
<rect width="140" height="140" fill="white" transform="translate(25 25)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1,9 @@
[data-theme="dracula"] {
--background-color: #282a36;
--background-highlight: #44475a;
--accent-color: #4e5268;
--accent-color-brighter: #2d2f3c;
--text-color: #f8f8f2;
--text-color-accent: #dddddd;
--dropdown-background-color: #343b52;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,9 @@
[data-theme="nord"] {
--background-color: #2e3440;
--background-highlight: #3b4252;
--accent-color: #434c5e;
--accent-color-brighter: #4c566a;
--text-color: #f8f8f2;
--text-color-accent: #dddddd;
--dropdown-background-color: #3b4252;
}

View file

@ -0,0 +1,9 @@
[data-theme="oled"] {
--background-color: #000;
--background-highlight: #111;
--accent-color: rgb(30 0 79);
--accent-color-brighter: rgb(60 0 155);
--text-color: #fff;
--text-color-accent: #dddddd;
--dropdown-background-color: #1a1a1a;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View file

@ -0,0 +1 @@
(()=>{async function i(e){let o=e.request.url,s=e.workerware.config;if(o.includes(self.__uv$config.prefix)){let r=self.__uv$config.decodeUrl(e.request.url.split(self.__uv$config.prefix)[1]);if(r==e.workerware.config.injectURL){console.log(`Injecting script into ${r}!`),console.log(s.injectURls);let n=(await e.uvResponse.text()).replace("</head>",`<script src="${s.injectURLs[0]}"><\/script><link rel="stylesheet" href="${s.injectURLs[1]}"></head>`);return new Response(n,{status:e.uvResponse.status,statusText:e.uvResponse.statusText,headers:e.uvResponse.headers})}return e.uvResponse}}self.scriptInjector={inject:i};})();

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View file

@ -0,0 +1,9 @@
[data-theme="synthwave84"] {
--background-color: #2a203a;
--background-highlight: #2e2342;
--accent-color: #1e1629;
--accent-color-brighter: #3e2e53;
--text-color: #c0bdc4;
--text-color-accent: #dddddd;
--dropdown-background-color: #231a30;
}

3
public/robots-allow.txt Normal file
View file

@ -0,0 +1,3 @@
User-agent: *
Allow: *
Sitemap: https://aluu.xyz/sitemap-index.xml

View file

@ -1,2 +1,2 @@
User-agent: * User-agent: *
Allow: * Disallow: *

View file

@ -1,18 +1,74 @@
/*global UVServiceWorker,__uv$config*/ importScripts("/uv/uv.bundle.js", "/uv.config.js", "/workerware/workerware.js");
/*
* Stock service worker script.
* Users can provide their own sw.js if they need to extend the functionality of the service worker.
* Ideally, this will be registered under the scope in uv.config.js so it will not need to be modified.
* However, if a user changes the location of uv.bundle.js/uv.config.js or sw.js is not relative to them, they will need to modify this script locally.
*/
importScripts("/uv/uv.bundle.js");
importScripts("/uv.config.js");
importScripts( __uv$config.sw); importScripts( __uv$config.sw);
importScripts("/marketplace/scriptInjector/index.js")
self.addEventListener("install", (event) => { const uv = new UVServiceWorker();
self.skipWaiting(); const ww = new WorkerWare({
debug: false,
}); });
const sw = new UVServiceWorker(); function loadExtensionScripts() {
try {
let db = indexedDB.open("AluDB", 1);
db.onsuccess = () => {
try {
let transaction = db.result.transaction("InstalledExtensions", "readonly");
let store = transaction.objectStore("InstalledExtensions");
let request = store.getAll();
request.onsuccess = () => {
let extensions = request.result.filter((extension) => extension.type == "serviceWorker");
extensions.forEach((extension) => {
const decoder = new TextDecoder();
const contents = decoder.decode(extension.scriptCopy);
self.addEventListener("fetch", (event) => event.respondWith(sw.fetch(event)));
eval(contents);
const func = self[extension.entryNamespace][extension.entryFunc];
switch (extension.type) {
case "serviceWorker":
// Loads the function to be added as a middleware into global scope.
ww.use({
function: self[extension.entryNamespace][extension.entryFunc],
name: extension.title,
events: ["fetch"],
});
break;
case "page":
console.log("Calling " + extension.entryFunc);
func();
break;
}
});
};
} catch {
console.error("Failed to open IndexedDB");
}
};
} catch (err) {
console.error(`Failed load extension scripts: ${err}`);
}
}
try {
loadExtensionScripts();
} catch (err) {
console.error(`Failed to load extension scripts: ${err}`);
}
self.addEventListener("fetch", async (event) => {
event.respondWith(
(async () => {
let mwResponse = await ww.run(event)();
if (mwResponse.includes(null)) {
return;
}
if (event.request.url.startsWith(location.origin + __uv$config.prefix)) {
return await uv.fetch(event);
}
return await fetch(event.request);
})()
);
});

4924
public/unity/UnityLoader.js Normal file

File diff suppressed because one or more lines are too long

423
public/unity/index.css Normal file
View file

@ -0,0 +1,423 @@
*,:before,:after {
box-sizing: border-box;
border-width: 0;
border-style: solid;
border-color: #e5e7eb
}
:before,:after {
--tw-content: ""
}
html {
line-height: 1.5;
-webkit-text-size-adjust: 100%;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
font-family: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";
font-feature-settings: normal;
font-variation-settings: normal
}
body {
margin: 0;
line-height: inherit
}
hr {
height: 0;
color: inherit;
border-top-width: 1px
}
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted
}
h1,h2,h3,h4,h5,h6 {
font-size: inherit;
font-weight: inherit
}
a {
color: inherit;
text-decoration: inherit
}
b,strong {
font-weight: bolder
}
code,kbd,samp,pre {
font-family: ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;
font-size: 1em
}
small {
font-size: 80%
}
sub,sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline
}
sub {
bottom: -.25em
}
sup {
top: -.5em
}
table {
text-indent: 0;
border-color: inherit;
border-collapse: collapse
}
button,input,optgroup,select,textarea {
font-family: inherit;
font-feature-settings: inherit;
font-variation-settings: inherit;
font-size: 100%;
font-weight: inherit;
line-height: inherit;
color: inherit;
margin: 0;
padding: 0
}
button,select {
text-transform: none
}
button,[type=button],[type=reset],[type=submit] {
-webkit-appearance: button;
background-color: transparent;
background-image: none
}
:-moz-focusring {
outline: auto
}
:-moz-ui-invalid {
box-shadow: none
}
progress {
vertical-align: baseline
}
::-webkit-inner-spin-button,::-webkit-outer-spin-button {
height: auto
}
[type=search] {
-webkit-appearance: textfield;
outline-offset: -2px
}
::-webkit-search-decoration {
-webkit-appearance: none
}
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit
}
summary {
display: list-item
}
blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre {
margin: 0
}
fieldset {
margin: 0;
padding: 0
}
legend {
padding: 0
}
ol,ul,menu {
list-style: none;
margin: 0;
padding: 0
}
dialog {
padding: 0
}
textarea {
resize: vertical
}
input::-moz-placeholder,textarea::-moz-placeholder {
opacity: 1;
color: #9ca3af
}
input::placeholder,textarea::placeholder {
opacity: 1;
color: #9ca3af
}
button,[role=button] {
cursor: pointer
}
:disabled {
cursor: default
}
img,svg,video,canvas,audio,iframe,embed,object {
display: block;
vertical-align: middle
}
img,video {
max-width: 100%;
height: auto
}
[hidden] {
display: none
}
*,:before,:after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / .5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia:
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / .5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia:
}
.container {
width: 100%
}
@media (min-width: 640px) {
.container {
max-width:640px
}
}
@media (min-width: 768px) {
.container {
max-width:768px
}
}
@media (min-width: 1024px) {
.container {
max-width:1024px
}
}
@media (min-width: 1280px) {
.container {
max-width:1280px
}
}
@media (min-width: 1536px) {
.container {
max-width:1536px
}
}
.flex {
display: flex
}
.hidden {
display: none
}
.h-5 {
height: 1.25rem
}
.h-full {
height: 100%
}
.w-10 {
width: 2.5rem
}
.w-5 {
width: 1.25rem
}
.w-full {
width: 100%
}
@keyframes spin {
to {
transform: rotate(360deg)
}
}
.animate-spin {
animation: spin 1s linear infinite
}
.cursor-pointer {
cursor: pointer
}
.flex-col {
flex-direction: column
}
.items-center {
align-items: center
}
.justify-center {
justify-content: center
}
.gap-5 {
gap: 1.25rem
}
.border {
border-width: 1px
}
.bg-slate-800 {
--tw-bg-opacity: 1;
background-color: rgb(30 41 59 / var(--tw-bg-opacity))
}
.bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity))
}
.text-slate-200 {
--tw-text-opacity: 1;
color: rgb(226 232 240 / var(--tw-text-opacity))
}
.underline {
text-decoration-line: underline
}
.opacity-25 {
opacity: .25
}
.opacity-75 {
opacity: .75
}
#gameContainer {
overflow: hidden
}

View file

@ -0,0 +1,35 @@
const a = window.location.pathname.split("/").pop();
if (a && UnityLoader) {
let t = function () {
setTimeout(() => {
n.Module.canvas.style.height = "100%"
}, 1000)
requestAnimationFrame(t)
};
// UnityLoader.Error.handler = e => {
// throw document.querySelector("#loader").classList.add("hidden"),
// document.querySelector("#error").classList.remove("hidden"),
// e
// };
const n = UnityLoader.instantiate("gameContainer", `/games/${a}/data.json`, {
onProgress: (e, r) => { },
Module: {
onRuntimeInitialized: () => {
document.querySelector("#loader").classList.add("hidden"),
document.querySelector("#gameContainer").classList.remove("hidden")
}
,
wasmRequest: function (e, r) {
e(this.wasmBinary).then(function (o) {
r(o.instance)
})
},
print: () => { },
printErr: () => { }
}
});
requestAnimationFrame(t)
} else
document.querySelector("#loader").classList.add("hidden"),
document.querySelector("#error").classList.remove("hidden");

32
public/unity/preload.js Normal file
View file

@ -0,0 +1,32 @@
(function() {
const t = document.createElement("link").relList;
if (t && t.supports && t.supports("modulepreload"))
return;
for (const e of document.querySelectorAll('link[rel="modulepreload"]'))
i(e);
new MutationObserver(e=>{
for (const r of e)
if (r.type === "childList")
for (const o of r.addedNodes)
o.tagName === "LINK" && o.rel === "modulepreload" && i(o)
}
).observe(document, {
childList: !0,
subtree: !0
});
function s(e) {
const r = {};
return e.integrity && (r.integrity = e.integrity),
e.referrerPolicy && (r.referrerPolicy = e.referrerPolicy),
e.crossOrigin === "use-credentials" ? r.credentials = "include" : e.crossOrigin === "anonymous" ? r.credentials = "omit" : r.credentials = "same-origin",
r
}
function i(e) {
if (e.ep)
return;
e.ep = !0;
const r = s(e);
fetch(e.href, r)
}
}
)();

View file

@ -1,12 +1,11 @@
/*global Ultraviolet*/ /*global Ultraviolet*/
self.__uv$config = { self.__uv$config = {
prefix: "/service/", prefix: "/service/",
bare: "/bare/",
encodeUrl: Ultraviolet.codec.xor.encode, encodeUrl: Ultraviolet.codec.xor.encode,
decodeUrl: Ultraviolet.codec.xor.decode, decodeUrl: Ultraviolet.codec.xor.decode,
handler: "/uv/uv.handler.js", handler: "/uv/uv.handler.js",
client: "/uv/uv.client.js", client: "/uv/uv.client.js",
bundle: "/uv/uv.bundle.js", bundle: "/uv/uv.bundle.js",
config: "/uv/uv.config.js", config: "/uv.config.js",
sw: "/uv/uv.sw.js", sw: "/uv/uv.sw.js",
}; };

Binary file not shown.

BIN
public/varela-latin.woff2 Normal file

Binary file not shown.

21
public/varela-round.css Normal file
View file

@ -0,0 +1,21 @@
/* latin-ext */
@font-face {
font-family: "Varela Round";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(varela-latin-ext.woff2) format("woff2");
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: "Varela Round";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(varela-latin.woff2) format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
U+FFFD;
}

View file

@ -0,0 +1,6 @@
class WWError extends Error {
constructor(message) {
super(message);
this.name = "[WorkerWare Exception]";
}
}

View file

@ -0,0 +1,168 @@
importScripts("/workerware/WWError.js");
const dbg = console.log.bind(console, "[WorkerWare]");
const time = console.time.bind(console, "[WorkerWare]");
const timeEnd = console.timeEnd.bind(console, "[WorkerWare]");
/*
OPTS:
debug - Enables debug logging.
randomNames - Generate random names for middlewares.
timing - Logs timing for each middleware.
*/
const defaultOpt = {
debug: false,
randomNames: false,
timing: false,
};
const validEvents = [
"abortpayment",
"activate",
"backgroundfetchabort",
"backgroundfetchclick",
"backgroundfetchfail",
"backgroundfetchsuccess",
"canmakepayment",
"contentdelete",
"cookiechange",
"fetch",
"install",
"message",
"messageerror",
"notificationclick",
"notificationclose",
"paymentrequest",
"periodicsync",
"push",
"pushsubscriptionchange",
"sync",
];
class WorkerWare {
constructor(opt) {
this._opt = Object.assign({}, defaultOpt, opt);
this._middlewares = [];
}
info() {
return {
version: "0.1.0",
middlewares: this._middlewares,
options: this._opt,
};
}
use(middleware) {
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.name) middleware.name = middleware.function.name;
if (this._opt.randomNames) middleware.name = crypto.randomUUID();
if (this._opt.debug) dbg("Adding middleware:", middleware.name);
this._middlewares.push(middleware);
}
// Run all middlewares for the event type passed in.
run(event) {
const middlewares = this._middlewares;
const returnList = [];
let fn = async () => {
for (let i = 0; i < middlewares.length; i++) {
if (middlewares[i].events.includes(event.type)) {
if (this._opt.timing) console.time(middlewares[i].name);
// Add the configuration to the event object.
event.workerware = {
config: middlewares[i].configuration || {},
};
if (!middlewares[i].explicitCall) {
let res = await middlewares[i].function(event);
if (this._opt.timing) console.timeEnd(middlewares[i].name);
returnList.push(res);
}
}
}
return returnList;
};
return fn;
}
deleteByName(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));
}
get() {
return this._middlewares;
}
/*
Run a single middleware by ID.
This assumes that the user knows what they're doing, and is running the middleware on an event that it's supposed to run on.
*/
runMW(name, event) {
const middlewares = this._middlewares;
if (this._opt.debug) dbg("Running middleware:", name);
// if (middlewares.includes(name)) {
// return middlewares[name](event);
// } else {
// throw new WWError("Middleware not found!");
// }
let didCall = false;
for (let i = 0; i < middlewares.length; i++) {
if (middlewares[i].name == name) {
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);
return call;
}
}
if (!didCall) {
throw new WWError("Middleware not found!");
}
}
// type middlewareManifest = {
// function: Function,
// name?: string,
// events: string[], // Should be a union of validEvents.
// configuration?: Object // Optional configuration for the middleware.
// }
validateMiddleware(middleware) {
if (!middleware.function)
return {
error: "middleware.function is required",
};
if (typeof middleware.function !== "function")
return {
error: "middleware.function must be typeof function",
};
if (typeof middleware.configuration !== "object" && middleware.configuration !== undefined) {
return {
error: "middleware.configuration must be typeof object",
};
}
if (!middleware.events)
return {
error: "middleware.events is required",
};
if (!Array.isArray(middleware.events))
return {
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(", "),
};
if (middleware.explicitCall && typeof middleware.explicitCall !== "boolean") {
return {
error: "middleware.explicitCall must be typeof boolean",
};
}
return {
error: undefined,
};
}
}

29
src/alu.d.ts vendored Normal file
View file

@ -0,0 +1,29 @@
export declare global {
// Hacky way to not have to cast the "event" type that lib.dom has to CustomEvent, which is what we actually use.
interface Document {
addEventListener(type: "setting-tabLoad", listener: (this: Document, ev: CustomEvent) => any, options?: boolean | AddEventListenerOptions);
}
namespace Alu {
let store: AluStore;
let eventList: Record<string, EventListener>;
let settings: {
loadedContentStorage: Record<string, string>;
currentTab: string;
};
type DefaultKeys = {
[key: string]: Key;
};
type Key = Record<string, string | KeyObj>;
type KeyObj = {
name: string;
value?: string;
icon?: string;
isCustom?: boolean;
};
type ValidStoreKeys = "proxy" | "search" | "openpage" | "wisp" | "bareUrl" | "transport" | "theme" | "lang" | "cloak";
}
}

View file

@ -0,0 +1,30 @@
---
export interface Props {
large?: boolean;
}
const { large } = Astro.props;
const classlist = "faq-card" + (large ? " faq-large" : "");
---
<div class={classlist}>
<slot />
</div>
<style>
.faq-card {
background-color: var(--dropdown-background-color);
border-radius: 10px;
padding: 20px;
color: var(--text-color);
box-shadow: 5px 5px 5px color-mix(in srgb, var(--background-color), black 40%);
}
@media (max-width: 768px) {
.faq-card {
grid-column: span 2;
}
}
.faq-large {
grid-column: span 2;
}
</style>

View file

@ -1,66 +0,0 @@
---
import { getLangFromUrl, useTranslations } from "../i18n/utils";
import WaveSVG from "./WaveSVG.astro";
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
---
<div class="footer">
<div class="wave-svg-container">
<WaveSVG />
</div>
<div class="footer-top">
<div class="footer-title">
<h2>{t("footer.brand")}</h2>
</div>
<div class="footer-madeby">
<a href="https://wearr.dev">{t("footer.madeWithLove")}</a>
</div>
</div>
<div class="footer-bottom">
<div class="footer-links">
<a href="https://titaniumnetwork.org">{t("footer.poweredBy")}</a>
</div>
<div class="footer-copyright">
<p>&copy; {t("footer.aluProject")} 2024</p>
</div>
</div>
</div>
<style>
.wave-svg-container {
bottom: 0;
left: 0;
position: absolute;
width: 100%;
z-index: -1;
overflow: hidden;
height: 300px;
filter: brightness(1.5);
}
.footer {
display: flex;
flex-direction: column;
justify-content: space-around;
color: var(--text-color);
position: relative;
padding-top: 100px;
gap: 50px;
}
.footer-top,
.footer-bottom {
width: 90%;
margin: 0 auto;
}
.footer-title {
font-size: 20px;
}
a {
color: var(--text-color);
}
</style>

View file

@ -1,32 +1,51 @@
--- ---
const { name, image, slugName } = Astro.props; const { game } = Astro.props;
--- ---
<div class="game"> <div class="game" data-name={game.name} data-id={game.slug}>
<a href=`/games/${slugName || name}`> <img class="pin-icon" src="/img/games/pin-outline.svg" />
<img class="game-img" src={image} alt="" /> <a class="game-link" href=`/game/${game.slug}`>
<img alt={game.name} class="game-img" src={game.image} alt="" />
<p class="game-title">{game.name}</p>
</a> </a>
<p class="game-title">{name}</p>
</div> </div>
<style> <style>
.game { .game {
position: relative;
background-color: var(--accent-color);
border: 2px solid var(--text-color); border: 2px solid var(--text-color);
padding: 1rem; padding: 1.2rem;
padding-bottom: 0;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
border-radius: 15px; border-radius: 10px;
} }
.game-img { .game-img {
width: 128px; width: 128px;
height: 128px; height: 128px;
border-radius: 5px;
}
.game-link {
text-decoration: none;
} }
.game-title { .game-title {
color: var(--text-color); color: var(--text-color);
text-align: center; text-align: center;
max-width: 125px; font-size: 18px;
height: 48px;
}
.pin-icon {
width: 24px;
height: 24px;
position: absolute;
top: 2px;
right: 2px;
cursor: pointer;
} }
</style> </style>

View file

@ -1,65 +0,0 @@
---
import { getLangFromUrl, useTranslations } from "../i18n/utils";
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
---
<div class="top-header">
<div id="title-background" class="title-background">
<div class="left">
<a href={`/${lang}/`} class="header-item">{t("nav.brand")}</a>
</div>
<div class="right">
<a href={`/${lang}/games/`} class="header-item">{t("nav.games")}</a>
<a href={`/${lang}/settings/`} class="header-item">{t("nav.settings")}</a>
</div>
</div>
</div>
<style>
.top-header {
display: flex;
box-sizing: border-box;
transition: 250ms ease-in;
}
.title-background {
background-color: var(--accent-color);
display: flex;
align-items: center;
justify-content: space-between;
padding-inline: 40px;
height: 70px;
width: 100%;
font-size: 1.05rem;
list-style-type: none;
border: none;
z-index: 10;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
.left,
.right {
display: flex;
align-items: center;
gap: 20px;
}
.header-item {
color: var(--text-color);
text-decoration: none;
font-size: 22px;
transition: 250ms ease-in-out;
}
.header-item:hover {
color: var(--text-color-accent);
}
@media only screen and (max-width: 1003px) {
.title-background {
width: 500%;
}
}
</style>

View file

@ -1,33 +0,0 @@
---
const { inputName, defaultTextContent, height, placeholder } = Astro.props;
interface Props {
inputName: string;
defaultTextContent?: string;
height: string;
placeholder?: string;
}
---
<input
style={`height: ${height}`}
id={inputName + "-input"}
placeholder={placeholder || ""}
value={defaultTextContent || ""}
type="text"
/>
<style>
input {
width: 100%;
border: 2px solid var(--background-highlight);
border-radius: 10px;
background-color: var(--accent-color);
color: var(--text-color);
transition: 0.1s ease-in-out;
}
input:focus {
outline: none;
border: 2px solid var(--text-color);
}
</style>

View file

@ -0,0 +1,29 @@
<img src="/favicon.svg" class="load-img" />
<svg class="loading-spinner" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="full-circle" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="indicator" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<style>
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.loading-spinner {
width: 2rem;
height: 2rem;
animation: spin 1s linear infinite;
}
.load-img {
width: 2.5rem;
height: 2.5rem;
margin: 0.5rem;
}
.full-circle {
opacity: 25%;
}
.indicator {
opacity: 75%;
}
</style>

View file

@ -1,45 +1,112 @@
<script src="/uv/uv.bundle.js" transition:persist></script>
<script src="/uv.config.js" transition:persist></script>
<script> <script>
//@ts-nocheck import { TransportMgr, initTransport } from "./ts/TransportManager";
let form = document.querySelector("form"); import "notyf/notyf.min.css";
let input = document.querySelector("input"); import { Notyf } from "notyf";
window.navigator.serviceWorker.register("/sw.js", { import EventMgr from "./ts/EventMgr";
scope: window.__uv$config.prefix,
}); const form = document.querySelector("form");
document.addEventListener("astro:after-swap", initForm); let input = document.querySelector("input")!;
EventMgr.listen("astro:after-swap", initForm);
function initForm() { function initForm() {
let formEle = document.querySelector("form"); const formEle = document.querySelector("form") as HTMLFormElement;
input = document.querySelector("input"); input = document.querySelector("input") as HTMLInputElement;
if (formEle) formEle.addEventListener("submit", formEventListener); if (formEle) EventMgr.listen("submit", formEventListener, formEle);
} }
if (form) { if (form) {
form.addEventListener("submit", formEventListener); form.addEventListener("submit", formEventListener);
} }
async function formEventListener(event) { setInterval(() => {
event.preventDefault(); const iframe = document.getElementById("proxy-frame") as HTMLIFrameElement;
let loadingContent = document.getElementById("loading-content"); if (iframe && iframe.src != "") {
loadingContent.style.opacity = 1; updateProxiedFavicon(iframe);
updateTopbarTitle(iframe);
}
}, 500);
async function getProxyURL() {
const preference = Alu.store.get("proxy").value;
let url = input.value.trim(); let url = input.value.trim();
if (!isUrl(url)) url = getSearchEngine() + url; if (!isUrl(url)) url = getSearchEngine() + url;
else if (!(url.startsWith("https://") || url.startsWith("http://"))) url = "http://" + url; if (preference === "ultraviolet") {
return window.__uv$config.prefix + window.__uv$config.encodeUrl(url);
} else if (preference == "rammerhead") {
// Check if rammerhead-session exists in cookies
const rammerheadSession = getCookie("rammerhead-session");
if (!rammerheadSession) {
const session = await fetch("/newsession");
const sessionID = await session.text();
await fetch("/editsession?id=" + sessionID + "&enableShuffling=0");
// Now save it in a cookie that expires in 72 hours.
document.cookie = `rammerhead-session=${sessionID}; max-age=${60 * 60 * 72}; path=/`;
}
return `/${getCookie("rammerhead-session")}/${url}`;
} else {
// Default to UV
return window.__uv$config.prefix + window.__uv$config.encodeUrl(url);
}
}
let iframe = document.getElementById("proxy-frame"); function getUVProxyURL(frame: HTMLIFrameElement) {
let preference = getProxyPreference(); return window.__uv$config.decodeUrl(frame.contentWindow!.location.href.split("/service/")[1]);
}
async function loadProxyContent(): Promise<void> {
const loadingContent = document.getElementById("loading-content") as HTMLElement;
if (loadingContent) loadingContent.style.opacity = "1";
await initTransport();
// The setTimeout is because service workers are a little silly and can take a while longer to register despite .then being called, which causes a bug on the first load.
setTimeout(async () => {
const openWith = Alu.store.get("openpage");
const proxy = Alu.store.get("proxy");
let url = input!.value.trim();
if (!isUrl(url)) url = getSearchEngine() + url;
else if (!(url.startsWith("https://") || url.startsWith("http://"))) url = "http://" + url;
if (openWith) {
if (openWith.value === "newTab" || proxy.value === "rammerhead") {
window.open(await getProxyURL(), "_blank");
return;
}
if (openWith.value === "about:blank") {
// Open about:blank window and inject iframe into it
const newWindow = window.open("about:blank", "_blank");
const newWindowDocument = newWindow!.document;
const iframe = newWindowDocument.createElement("iframe");
iframe.src = await getProxyURL();
// Inject css into the iframe
const css = newWindowDocument.createElement("link");
css.rel = "stylesheet";
css.href = "/iframe.css";
newWindowDocument.head.appendChild(css);
newWindowDocument.body.appendChild(iframe);
return;
}
}
const iframe = document.getElementById("proxy-frame") as HTMLIFrameElement;
const topbar = document.getElementById("top-bar") as HTMLDivElement;
const closeButton = document.getElementById("nav-close")!;
const backwardsButton = document.getElementById("nav-backwards")!;
const forwardsButton = document.getElementById("nav-forwards")!;
const reloadButton = document.getElementById("nav-reload")!;
const shareButton = document.getElementById("nav-share")!;
const preference = Alu.store.get("proxy").value;
if (preference === "ultraviolet") { if (preference === "ultraviolet") {
iframe.src = window.__uv$config.prefix + window.__uv$config.encodeUrl(url); iframe.src = window.__uv$config.prefix + window.__uv$config.encodeUrl(url);
} else if (preference == "rammerhead") { } else if (preference == "rammerhead") {
// Check if rammerhead-session exists in cookies // Check if rammerhead-session exists in cookies
let rammerheadSession = getCookie("rammerhead-session"); const rammerheadSession = getCookie("rammerhead-session");
console.log(rammerheadSession);
if (!rammerheadSession) { if (!rammerheadSession) {
let session = await fetch("/newsession"); const session = await fetch("/newsession");
let sessionID = await session.text(); const sessionID = await session.text();
// Disable URL shuffling on rewrite, eventually I'll try and figure out how it works, but for now, it's disabled.
await fetch("/editsession?id=" + sessionID + "&enableShuffling=0");
// Now save it in a cookie that expires in 72 hours. // Now save it in a cookie that expires in 72 hours.
document.cookie = `rammerhead-session=${sessionID}; max-age=${60 * 60 * 72}; path=/`; document.cookie = `rammerhead-session=${sessionID}; max-age=${60 * 60 * 72}; path=/`;
// Now add an origin_proxy cookie for our domain
document.cookie = `origin_proxy=${window.location.origin}; max-age=${60 * 60 * 72}; path=/`;
} }
iframe.src = `/${getCookie("rammerhead-session")}/${url}`; if (iframe) iframe.src = `/${getCookie("rammerhead-session")}/${url}`;
} else { } else {
// Default to UV // Default to UV
iframe.src = window.__uv$config.prefix + window.__uv$config.encodeUrl(url); iframe.src = window.__uv$config.prefix + window.__uv$config.encodeUrl(url);
@ -47,90 +114,123 @@
iframe.style.pointerEvents = "auto"; iframe.style.pointerEvents = "auto";
iframe.classList.add("proxy-frame"); iframe.classList.add("proxy-frame");
document.body.appendChild(iframe); document.body.appendChild(iframe);
iframe.addEventListener("load", () => { setTimeout(() => {
let topBar = document.getElementById("top-bar"); iframeLoad();
loadingContent.style.opacity = 0; }, 500);
topBar.innerHTML = "";
topBar.classList.add("top-bar"); function setActive() {
let closeButton = document.createElement("button"); iframe.classList.add("active");
closeButton.classList.add("close-button");
closeButton.innerText = "Close";
closeButton.addEventListener("click", () => {
iframe.style.opacity = 0;
topBar.style.opacity = 0;
iframe.style.pointerEvents = "none";
topBar.style.pointerEvents = "none";
});
let urlText = document.createElement("p");
urlText.classList.add("url-text");
urlText.innerText = window.__uv$config.decodeUrl(iframe.src.split(__uv$config.prefix)[1]);
iframe.style.opacity = 1;
topBar.style.opacity = 1;
topBar.style.pointerEvents = "auto";
topBar.appendChild(closeButton);
topBar.appendChild(urlText);
document.body.appendChild(topBar);
});
} }
function iframeLoad() {
loadingContent.style.opacity = "0";
iframe.style.opacity = "1";
topbar.style.opacity = "1";
topbar.style.pointerEvents = "auto";
document.body.style.overflow = "hidden";
iframe.addEventListener("load", setActive);
closeButton.onclick = () => {
iframe.style.opacity = "0";
topbar.style.opacity = "0";
iframe.style.pointerEvents = "none";
topbar.style.pointerEvents = "none";
document.body.style.overflow = "auto";
iframe.classList.remove("active");
iframe.removeEventListener("load", setActive);
setTimeout(() => {
iframe.src = "about:blank";
}, 500);
};
forwardsButton.onclick = () => {
if (iframe.contentWindow) {
iframe.contentWindow.history.forward();
}
};
backwardsButton.onclick = () => {
if (iframe.contentWindow) {
iframe.contentWindow.history.back();
}
};
reloadButton.onclick = () => {
if (iframe.contentWindow) {
iframe.contentWindow.location.reload();
}
};
shareButton.onclick = () => {
const proxyFrame = document.getElementById("proxy-frame") as HTMLIFrameElement;
if (proxy.value === "rammerhead") {
navigator.clipboard.writeText(window.location.origin + "/" + getCookie("rammerhead-session") + "/" + input!.value.trim());
} else {
navigator.clipboard.writeText(getUVProxyURL(proxyFrame));
}
new Notyf({
duration: 2000,
position: { x: "right", y: "bottom" },
dismissible: true,
ripple: true,
}).success("Copied URL to clipboard!");
};
}
}, 100);
}
async function formEventListener(event: Event) {
event.preventDefault();
event.stopImmediatePropagation();
await TransportMgr.updateTransport();
loadProxyContent();
}
window.loadFormContent = loadProxyContent;
function isUrl(val = "") { function isUrl(val = "") {
if (/^http(s?):\/\//.test(val) || (val.includes(".") && val.substr(0, 1) !== " ")) return true; if (/^http(s?):\/\//.test(val) || (val.includes(".") && val.substr(0, 1) !== " ")) return true;
return false; return false;
} }
function getCookie(name) { function getCookie(name: string) {
const value = `; ${document.cookie}`; const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`); const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(";").shift(); if (parts.length === 2 && parts) {
const lastPart = parts.pop();
if (lastPart) {
return lastPart.split(";").shift();
} else {
return null;
}
}
} }
function getSearchEngine() { function getSearchEngine() {
let localStorageSearchEngine = localStorage.getItem("alu__search_engine"); return Alu.store.get("search").value;
if (!localStorageSearchEngine) {
return "https://google.com/search?q=";
}
switch (JSON.parse(localStorage.getItem("alu__search_engine")).value.toLowerCase()) {
case "google": {
return "https://google.com/search?q=";
}
case "bing": {
return "https://bing.com/search?q=d";
}
case "brave": {
return "https://search.brave.com/search?q=";
}
case "searx": {
let localStorageURL = localStorage.getItem("alu__searxngUrl");
if (localStorageURL) {
if (localStorageURL == "") return "https://searxng.site/search?q=";
// Ugly hack to remove the trailing slash :)
if (localStorageURL.endsWith("/")) localStorageURL = localStorageURL.slice(0, -1);
return localStorageURL + "/search?q=";
} else return "https://searxng.site/search?q=";
}
default: {
return "https://google.com/search?q=";
}
}
} }
function getProxyPreference() { function updateProxiedFavicon(iframe: HTMLIFrameElement) {
let localStorageItem = localStorage.getItem("alu__selectedProxy"); const proxiedFavicon = document.getElementById("proxied-favicon") as HTMLImageElement;
if (iframe) {
if (!localStorageItem) return "uv"; if (iframe.contentDocument) {
const favicon = (iframe.contentDocument.querySelector("link[rel='icon']") as HTMLLinkElement) || (iframe.contentDocument.querySelector("link[rel*='icon']") as HTMLLinkElement);
switch (JSON.parse(localStorageItem).value.toLowerCase()) { if (favicon && favicon.href.includes("data:image")) {
case "ultraviolet": { proxiedFavicon.src = favicon.href;
return "ultraviolet"; return;
} }
case "rammerhead": const UVURL = getUVProxyURL(iframe);
return "rammerhead"; if (proxiedFavicon.src == `${window.location.origin}/custom-favicon?url=${UVURL}`) return;
case "dynamic": proxiedFavicon.src = `/custom-favicon?url=${UVURL}`;
// temporary because dynamic is not implemented yet :)
return "ultraviolet";
default: {
return "uv";
} }
} }
} }
function updateTopbarTitle(iframe: HTMLIFrameElement) {
if (!iframe.contentDocument) return;
const topbarTitle = document.getElementById("url-text") as HTMLElement;
if (iframe.contentDocument.title == "") {
topbarTitle.innerText = "Loading...";
} else {
if (iframe.contentDocument.title.length > 65) {
topbarTitle.innerText = iframe.contentDocument.title.slice(0, 65) + "...";
return;
}
topbarTitle.innerText = iframe.contentDocument.title;
}
}
</script> </script>

View file

@ -0,0 +1,12 @@
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "Alu",
"url": "https://aluu.xyz",
"accessMode": "visual",
"acquireLicensePage": "https://github.com/titaniumnetwork-dev/Alu/blob/main/LICENSE",
"description": "Alu is a sleek web proxy supporting multiple standards of communication, and wide levels of customization. Similar to other proxies such as Holy Unblocker, Alu allows you to access blocked content while maintaining your privacy.",
"keywords": "web proxy, unblocker, alu, alu proxy, privacy, customization, wisp protocol, holy unblocker, titanium network, definitely science, kazwire, radon games, nebula, nebula proxy, censorship, bypass censorship, anura"
}
</script>

View file

@ -1,33 +1,48 @@
--- ---
import Input from "../Input.astro"; import Input from "@components/UI/Input.astro";
import { i18n } from "@i18n/utils";
const t = i18n.inferLangUseTranslations(Astro.url);
const presetCloaks = [ const presetCloaks = [
{ cloakTitle: "None", favicon: "/favicon.png" },
{ {
cloakTitle: "Google", cloakTitle: "None",
favicon: favicon: "/favicon.svg",
"https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://google.com&size=128",
}, },
{ {
cloakTitle: "Instructure", cloakTitle: "Google",
favicon: "https://du11hjcvx0uqb.cloudfront.net/dist/images/favicon-e10d657a73.ico", favicon: "/icons/google.png",
},
{
cloakTitle: "Canvas",
favicon: "/icons/canvas.png",
}, },
{ {
cloakTitle: "Google Classroom", cloakTitle: "Google Classroom",
favicon: "https://ssl.gstatic.com/classroom/ic_product_classroom_144.png", favicon: "/icons/classroom.png",
},
{
cloakTitle: "Imagine Edgenuity",
favicon: "/icons/edgenuity.png",
}, },
{ {
cloakTitle: "Classlink", cloakTitle: "Classlink",
favicon: favicon: "/icons/classlink.png",
"https://cdn.classlink.com/production/launchpad/resources/images/favicon/favicon-32x32.png", },
{
cloakTitle: "Clever",
favicon: "/icons/clever.jpg",
}, },
{ {
cloakTitle: "Google Drive", cloakTitle: "Google Drive",
favicon: "https://ssl.gstatic.com/docs/doclist/images/drive_2022q3_32dp.png", favicon: "/icons/drive.png",
}, },
{ {
cloakTitle: "Schoology", cloakTitle: "Schoology",
favicon: "https://asset-cdn.schoology.com/sites/all/themes/schoology_theme/favicon.ico", favicon: "/icons/schoology.webp",
},
{
cloakTitle: "YouTube",
favicon: "/icons/youtube.png",
}, },
]; ];
--- ---
@ -38,10 +53,7 @@ const presetCloaks = [
{ {
presetCloaks.map((cloak: any) => { presetCloaks.map((cloak: any) => {
return ( return (
<div <div class="cloak-item" data-cloak-name={cloak.cloakTitle} data-cloak-icon={cloak.favicon}>
class="cloak-item"
data-cloak-name={cloak.cloakTitle}
data-cloak-icon={cloak.favicon}>
<img class="cloak-image" src={cloak.favicon} alt={cloak.cloakTitle} /> <img class="cloak-image" src={cloak.favicon} alt={cloak.cloakTitle} />
</div> </div>
); );
@ -51,7 +63,7 @@ const presetCloaks = [
<div class="cloak-custom-override"> <div class="cloak-custom-override">
<Input inputName="cloak-custom-name" placeholder="Custom Name" height="30px" /> <Input inputName="cloak-custom-name" placeholder="Custom Name" height="30px" />
<Input inputName="cloak-custom-favicon" placeholder="Custom Favicon" height="30px" /> <Input inputName="cloak-custom-favicon" placeholder="Custom Favicon" height="30px" />
<button id="cloak-custom-button">Update Cloak</button> <button id="cloak-custom-button">{t("settings.cloaking.updateCloak")}</button>
</div> </div>
</div> </div>
</div> </div>
@ -67,6 +79,7 @@ const presetCloaks = [
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
gap: 15px; gap: 15px;
flex-wrap: wrap;
} }
.cloak-item { .cloak-item {
width: 75px; width: 75px;
@ -85,6 +98,7 @@ const presetCloaks = [
.cloak-image { .cloak-image {
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: 5px;
} }
.cloak-custom-override { .cloak-custom-override {
@ -101,6 +115,7 @@ const presetCloaks = [
border: 0; border: 0;
color: var(--text-color); color: var(--text-color);
cursor: pointer; cursor: pointer;
font-family: "Varela Round", sans-serif !important;
} }
.cloak-custom-input { .cloak-custom-input {
height: 40px; height: 40px;

View file

@ -1,49 +1,35 @@
--- ---
import { getLangFromUrl, useTranslations } from "../../i18n/utils"; import Card from "@components/UI/Card.astro";
const lang = getLangFromUrl(Astro.url); import { i18n } from "@i18n/utils";
const t = useTranslations(lang); const t = i18n.inferLangUseTranslations(Astro.url);
--- ---
<div class="settings-container"> <div class="settings-container">
<div class="credits-container"> <div class="credits-container">
<p class="credit-item"> <Card title={t("ultraviolet")} href="https://titaniumnetwork.org"> Titanium Network </Card>
{t("ultraviolet")} - <a <Card title={t("settings.credits.esTranslations")} href="https://github.com/builtbyvys/"> vys </Card>
target="_blank" <Card title={t("settings.credits.frTranslations")} href="https://github.com/notboeing747"> notboeing747 </Card>
rel="noreferrer noopener" <Card title={t("settings.credits.jpTranslations")} href="https://wearr.dev"> wearr </Card>
href="https://titaniumnetwork.org/">Titanium Network</a <Card title={t("settings.credits.ptTranslations")}> kersosina_ </Card>
> <Card title={t("settings.credits.ruTranslations")} href="https://3kh0.net"> Echo </Card>
</p> <Card title={t("settings.credits.zhTranslations")} href="https://3kh0.net"> Echo </Card>
<p class="credit-item"> <Card title={t("settings.credits.catppuccin")} href="https://github.com/catppuccin/catppuccin"> Catppuccin </Card>
{t("settings.credits.japaneseTranslations")} - <a <Card title="Wisp Server" href="https://github.com/MercuryWorkshop/wisp-server-node"> Mercury Workshop </Card>
target="_blank"
rel="noreferrer noopener"
href="https://wearr.dev">wearr</a
>
</p>
<p class="credit-item">
{t("settings.credits.mochaandmacchiatothemes")} - <a
target="_blank"
rel="noreferrer noopener"
href="https://github.com/catppuccin/catppuccin">Catppuccin</a
>
</p>
<p class="credit-item">
Rosé Pine Theme - <a
target="_blank"
rel="noreferrer noopener"
href="https://rosepinetheme.com/">Rosé Pine</a
>
</p>
</div> </div>
</div> </div>
<style> <style>
.credit-item { .credits-container {
color: var(--text-color); display: grid;
font-size: 18px; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
width: 100%;
gap: 10px;
} }
.credit-item > a { .credit-item {
color: var(--text-color); font-size: 20px;
font-weight: bold; margin: 10px 0 10px;
}
.credit-name {
min-width: 150px;
} }
</style> </style>

View file

@ -1,35 +1,33 @@
--- ---
import Dropdown from "../Dropdown.astro"; import Dropdown from "@components/UI/Dropdown.astro";
import { getLangFromUrl, useTranslations } from "../../i18n/utils"; import { i18n } from "@i18n/utils";
const lang = getLangFromUrl(Astro.url); const t = i18n.inferLangUseTranslations(Astro.url);
const t = useTranslations(lang);
const themeList = [ const themeList = [
{ name: t("settings.customization.theme.Alu"), value: "alu" }, { name: t("settings.customization.theme.Alu"), value: "alu" },
{ name: t("settings.customization.theme.Macchiato"), value: "macchiato" }, { name: t("settings.customization.theme.Macchiato"), value: "macchiato" },
{ name: t("settings.customization.theme.Mocha"), value: "mocha" }, { name: t("settings.customization.theme.Mocha"), value: "mocha" },
{ name: "Rosé Pine", value: "rose_pine" },
]; ];
const languageList = [ const languageList = [
{ name: "English", value: "en" }, { name: "English", value: "en" },
{ name: "Español", value: "es" },
{ name: "Français", value: "fr" },
{ name: "日本語", value: "jp" }, { name: "日本語", value: "jp" },
{ name: "Português", value: "pt" },
{ name: "Русский", value: "ru" },
{ name: "中文", value: "zh" },
]; ];
--- ---
<div class="settings-container"> <div class="settings-container">
<div class="setting__theme"> <div class="setting__theme">
<label class="setting-label">{t("settings.customization.theme")}</label> <label for="dropdown__selected-theme" aria-label="Theme" class="setting-label">{t("settings.customization.theme")}</label>
<Dropdown buttonNameDefault="Alu" dropdownList={themeList} , id="dropdown__selected-theme" /> <Dropdown buttonNameDefault="Alu" localStorageKey="theme" dropdownList={themeList} id="dropdown__selected-theme" />
</div> </div>
<div class="setting__language"> <div class="setting__language">
<label class="setting-label">{t("settings.customization.language")}</label> <label for="dropdown__selected-language" aria-label="Language" class="setting-label">{t("settings.customization.language")}</label>
<Dropdown <Dropdown buttonNameDefault="English" localStorageKey="lang" dropdownList={languageList} id="dropdown__selected-language" />
buttonNameDefault="English"
dropdownList={languageList}
,
id="dropdown__selected-language"
/>
</div> </div>
</div> </div>

View file

@ -1,23 +1,32 @@
--- ---
import Input from "../Input.astro"; import Input from "@components/UI/Input.astro";
import Dropdown from "../Dropdown.astro"; import Dropdown from "@components/UI/Dropdown.astro";
import { getLangFromUrl, useTranslations } from "../../i18n/utils"; import { i18n } from "@i18n/utils";
const lang = getLangFromUrl(Astro.url); const t = i18n.inferLangUseTranslations(Astro.url);
const t = useTranslations(lang);
const getWSProtocol = () => {
if (Astro.url.protocol === "https:") {
return "wss://";
} else {
return "ws://";
}
};
const proxyList = [ const proxyList = [
{ name: t("settings.proxy.auto"), value: "auto" }, { name: t("settings.proxy.auto"), value: "auto" },
{ name: t("ultraviolet"), value: "ultraviolet" }, { name: t("ultraviolet"), value: "ultraviolet" },
{ name: "Rammerhead", value: "rammerhead" }, { name: "Rammerhead", value: "rammerhead" },
{ name: "Dynamic", value: "dynamic" },
]; ];
const searchEngineList = [ const searchEngineList = [
{ name: "Google", value: "google" }, { name: "Google", value: "https://google.com/search?q=" },
{ name: "Bing", value: "bing" }, { name: "DuckDuckGo", value: "https://duckduckgo.com/?q=" },
{ name: "Brave", value: "brave" }, { name: "Bing", value: "https://bing.com/search?q=" },
{ name: "Searx", value: "searx" }, { name: "Brave", value: "https://search.brave.com/search?q=" },
// Ecosia for some reason doesn't work with the proxy, hopefully I'll be able to add it eventually.
// { name: "Ecosia", value: "https://ecosia.org/search?q=" },
{ name: "Searx", value: "https://searxng.site/?q=" },
]; ];
const openPageWith = [ const openPageWith = [
@ -25,42 +34,71 @@ const openPageWith = [
{ name: "About:Blank", value: "about:blank" }, { name: "About:Blank", value: "about:blank" },
{ name: t("settings.proxy.openPageWith.newTab"), value: "newTab" }, { name: t("settings.proxy.openPageWith.newTab"), value: "newTab" },
]; ];
const transportsList = [
{ name: "Epoxy", value: "/epoxy/index.mjs" },
{ name: "Libcurl", value: "/libcurl/index.mjs" },
{ name: "Bare", value: "/baremod/index.mjs" },
];
const wispURLList = [
{ name: "Alu (US)", value: "wss://aluu.xyz/wisp/" },
{ name: "Anura (US)", value: "wss://anura.pro/" },
{ name: "Custom", value: getWSProtocol() + Astro.url.host + "/wisp/" },
];
--- ---
<div class="settings-container"> <div class="settings-container">
<div class="setting__selected-proxy"> <div class="setting__selected-proxy">
<label class="setting-label">{t("settings.proxy.selectedProxy")}</label> <label aria-label="Selected Proxy" for="dropdown__selected-proxy" class="setting-label">{t("settings.proxy.selectedProxy")}</label>
<Dropdown <Dropdown buttonNameDefault="Ultraviolet" dropdownList={proxyList} localStorageKey="proxy" id="dropdown__selected-proxy" />
buttonNameDefault="Ultraviolet"
dropdownList={proxyList}
,
id="dropdown__selected-proxy"
/>
</div> </div>
<div class="setting__search-engine"> <div class="setting__search-engine">
<label class="setting-label">{t("settings.proxy.searchEngine")}</label> <label aria-label="Search Engine" for="dropdown__search-engine" class="setting-label">{t("settings.proxy.searchEngine")}</label>
<Dropdown <Dropdown buttonNameDefault="Google" dropdownList={searchEngineList} localStorageKey="search" id="dropdown__search-engine" />
buttonNameDefault="Google"
dropdownList={searchEngineList}
,
id="dropdown__search-engine"
/>
</div> </div>
<div class="setting__open_with"> <div class="setting__open_with">
<label class="setting-label">{t("settings.proxy.openPageWith")}</label> <label aria-label="Open Page With" for="dropdown__open-with" class="setting-label">{t("settings.proxy.openPageWith")}</label>
<Dropdown <Dropdown buttonNameDefault={t("settings.proxy.openPageWith.embed")} dropdownList={openPageWith} localStorageKey="openpage" id="dropdown__open-with" />
buttonNameDefault={t("settings.proxy.openPageWith.embed")}
dropdownList={openPageWith}
,
id="dropdown__open-with"
/>
</div> </div>
<div class="setting__bare-url"> <div class="setting__wisp_url">
<label class="setting-label" for="bare-url-input">{t("settings.proxy.bareURL")}</label> <label aria-label="Wisp URL" for="dropdown__wisp-url" for="dropdown__wisp-url" class="setting-label">{t("settings.proxy.wispURL")}</label>
<Input inputName="bare-url" height="50px" /> <Dropdown buttonNameDefault={wispURLList[0].value} dropdownList={wispURLList} localStorageKey="wisp" id="dropdown__wisp-url" />
</div>
<div class="setting__bare_url">
<label aria-label="Bare Server URL" for="bare-url-input" class="setting-label">{t("settings.proxy.bareURL")}</label>
<Input height="50px" inputName="bare-url" />
</div>
<div class="setting__transport">
<label aria-label="Wisp Transport" for="dropdown__transport" class="setting-label">{t("settings.proxy.transport")}</label>
<Dropdown buttonNameDefault="Epoxy" dropdownList={transportsList} localStorageKey="transport" id="dropdown__transport" />
</div>
<div class="setting__reset">
<button id="reset-button">Reset Settings</button>
</div> </div>
</div> </div>
<div class="setting__searxng-url"> <div class="setting__wisp-url setting-hidden">
<label for="searxng-url-input" class="setting-label">{t("settings.proxy.searxngURL")}</label> <label aria-label="Custom Wisp URL" for="wisp-url-input" class="setting-label">{t("settings.proxy.wispURL")}</label>
<Input height="50px" inputName="wisp-url" defaultTextContent={getWSProtocol() + Astro.url.host + "/wisp/"} />
</div>
<div class="setting__searxng-url setting-hidden">
<label aria-label="SearXNG URL" for="searxng-url-input" class="setting-label">{t("settings.proxy.searxngURL")}</label>
<Input height="50px" inputName="searxng-url" defaultTextContent="https://searxng.site/" /> <Input height="50px" inputName="searxng-url" defaultTextContent="https://searxng.site/" />
</div> </div>
<style>
.setting__reset {
display: flex;
justify-content: center;
align-items: center;
}
#reset-button {
background-color: var(--accent-color);
border: none;
color: var(--text-color);
border-radius: 1rem;
padding: 10px;
margin-top: 40px;
cursor: pointer;
}
</style>

View file

@ -1,481 +0,0 @@
---
import ProxyTab from "./SettingsContent/ProxyTab.astro";
import CustomizationTab from "./SettingsContent/CustomizationTab.astro";
import { getLangFromUrl, useTranslations } from "../i18n/utils";
import CloakingTab from "./SettingsContent/CloakingTab.astro";
import CreditsTab from "./SettingsContent/CreditsTab.astro";
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
---
<div class="content-hidden">
<div id="content-setting-tab-proxy">
<h1 class="content-setting-header">{t("settings.proxy")}</h1>
<ProxyTab />
</div>
<div id="content-setting-tab-customization">
<h1 class="content-setting-header">{t("settings.customization")}</h1>
<CustomizationTab />
</div>
<div id="content-setting-tab-cloaking">
<h1 class="content-setting-header">{t("settings.cloaking")}</h1>
<p class="content-setting-subtext">{t("settings.cloaking.subtext")}</p>
<CloakingTab />
</div>
<div id="content-setting-tab-credits">
<h1 class="content-setting-header">{t("settings.credits")}</h1>
<CreditsTab />
</div>
</div>
<div class="popup">
<div class="tabs">
<input type="radio" id="setting-tab-proxy" class="setting-tab" name="tab" checked="true" />
<label for="setting-tab-proxy">Proxy</label>
<input type="radio" id="setting-tab-customization" class="setting-tab" name="tab" />
<label for="setting-tab-customization">Customization</label>
<input type="radio" id="setting-tab-cloaking" class="setting-tab" name="tab" />
<label for="setting-tab-cloaking">Cloaking</label>
<input type="radio" id="setting-tab-credits" class="setting-tab" name="tab" />
<label for="setting-tab-credits">Credits</label>
<div class="marker">
<div id="top"></div>
<div id="bottom"></div>
</div>
</div>
<div id="current-content"></div>
</div>
<script is:inline>
document.addEventListener("astro:before-swap", () => {
window.currentlySelectedTab = "";
document.removeEventListener("setting-tabChange", determineListener);
});
window.currentlySelectedTab;
window.loadedContentStorage = {};
Array.from(document.getElementsByClassName("setting-tab")).forEach((tab) => {
let contentToLoad = document.getElementById("content-" + tab.id);
if (contentToLoad) {
window.loadedContentStorage[tab.id] = contentToLoad.innerHTML;
contentToLoad.remove();
}
tab.addEventListener("click", (event) => {
loadContent(event.target.id);
});
});
function loadContent(tabID) {
if (window.currentlySelectedTab == tabID) return;
else window.currentlySelectedTab = tabID;
let currentContent = document.getElementById("current-content");
if (currentContent) {
currentContent.style.opacity = "0";
setTimeout(() => {
currentContent.innerHTML = window.loadedContentStorage[tabID];
currentContent.style.opacity = "1";
document.dispatchEvent(new CustomEvent("setting-tabChange", { detail: tabID }));
document.dispatchEvent(new CustomEvent("setting-tabLoad", { detail: tabID }));
}, 250);
}
}
function addDropdownListener() {
let dropdown_toggles = document.getElementsByClassName("dropdown-toggle");
Array.from(dropdown_toggles).forEach((toggle) => {
toggle.addEventListener("click", () => {
let dropdown = document.getElementById(toggle.id + "-menu");
if (dropdown) {
if (dropdown.style.maxHeight == "0px" || dropdown.style.maxHeight == "") {
dropdown.style.maxHeight = dropdown.scrollHeight + "px";
toggle.style.borderRadius = "10px 10px 0 0";
} else {
dropdown.style.maxHeight = "0px";
setTimeout(() => {
toggle.style.borderRadius = "10px";
}, 300);
}
}
});
});
}
function determineListener(event) {
if (event.detail == "setting-tab-proxy") {
addDropdownListener();
} else if (event.detail == "setting-tab-customization") {
addDropdownListener();
}
}
function closeDropdown(dropdownID) {
let dropdown = document.getElementById(dropdownID);
if (dropdown) {
dropdown.style.maxHeight = "0px";
setTimeout(() => {
let dropdown_toggle = document.getElementById(dropdownID.replace("-menu", ""));
dropdown_toggle.style.borderRadius = "10px";
}, 300);
}
}
function getLocalStorageValue(localStorageItem, dropdownID) {
// I was kinda dumb for not doing this earlier.
let dropdown = document.getElementById(dropdownID);
let dropdownMenu = document.getElementById(dropdownID + "-menu");
if (dropdown && dropdownMenu) {
// Now we find the child that matches localStorageItem.value.
let dropdownItem = Array.from(dropdownMenu.children).find((item) => {
return JSON.parse(localStorage.getItem(localStorageItem)).value == item.dataset.setting;
});
// Now set the inner text to the name in the dropdownItem.
return dropdownItem.innerText;
}
}
function applySavedLocalStorage(localStorageItem, dropdownID) {
if (localStorage.getItem(localStorageItem)) {
let dropdown_toggle = document.getElementById(dropdownID);
if (dropdown_toggle) {
dropdown_toggle.innerText = getLocalStorageValue(localStorageItem, dropdownID);
}
}
}
function applyDropdownEventListeners(item, dropdownID, localStorageItem, optionalCallback) {
Array.from(item.children).forEach((item) => {
item.addEventListener("click", () => {
let localStorageItemContent = {
name: item.innerText,
value: item.dataset.setting,
};
localStorage.setItem(localStorageItem, JSON.stringify(localStorageItemContent));
applySavedLocalStorage(localStorageItem, dropdownID);
closeDropdown(item.parentElement.id);
if (typeof optionalCallback == "function") {
optionalCallback();
}
});
});
// Array.from(item.children).forEach((item) => {
// item.addEventListener('click', () => {
// localStorage.setItem(localStorageItem, item.dataset.setting)
// applySavedLocalStorage(localStorageItem, dropdownID)
// closeDropdown(item.parentElement.id);
// if (typeof optionalCallback == "function") {
// optionalCallback();
// }
// })
// })
}
function applyInputListeners(item, localStorageItem) {
item.addEventListener("input", () => {
localStorage.setItem(localStorageItem, item.value);
});
}
document.addEventListener("setting-tabChange", determineListener);
loadContent("setting-tab-proxy");
function setupCustomizationSettings() {
applySavedLocalStorage("alu__selectedTheme", "dropdown__selected-theme");
applySavedLocalStorage("alu__selectedLanguage", "dropdown__selected-language");
let themeDropdown = document.getElementById("dropdown__selected-theme-menu");
let languageDropdown = document.getElementById("dropdown__selected-language-menu");
applyDropdownEventListeners(
themeDropdown,
"dropdown__selected-theme",
"alu__selectedTheme",
changeTheme
);
applyDropdownEventListeners(
languageDropdown,
"dropdown__selected-language",
"alu__selectedLanguage",
navigateToNewLangaugePage
);
}
function setupCloakingSettings() {
Array.from(document.getElementById("cloak-list").children).forEach((cloak) => {
cloak.addEventListener("click", () => {
let cloakName = cloak.dataset.cloakName;
let cloakIcon = cloak.dataset.cloakIcon;
let localStorageItem = {
name: cloakName,
icon: cloakIcon,
isCustom: false,
};
localStorage.setItem("alu__selectedCloak", JSON.stringify(localStorageItem));
if (cloakName == "None") {
localStorage.removeItem("alu__selectedCloak");
cloakName = "Settings | Alu";
cloakIcon = "/favicon.png";
}
let link = document.querySelector("link[rel~='icon']");
if (!link) {
link = document.createElement("link");
link.rel = "icon";
document.head.appendChild(link);
}
link.href = cloakIcon;
document.title = cloakName;
if (!cloak.classList.contains("selected")) {
Array.from(document.getElementById("cloak-list").children).forEach((cloak2) => {
cloak2.classList.remove("selected");
});
cloak.classList.add("selected");
}
});
});
let customNameInput = document.getElementById("cloak-custom-name-input");
let customFaviconInput = document.getElementById("cloak-custom-favicon-input");
if (localStorage.getItem("alu__selectedCloak")) {
let selectedCloak = JSON.parse(localStorage.getItem("alu__selectedCloak"));
if (selectedCloak.isCustom) {
customNameInput.value = selectedCloak.name;
customFaviconInput.value = selectedCloak.icon;
}
}
document.getElementById("cloak-custom-button").addEventListener("click", () => {
let cloakName = document.getElementById("cloak-custom-name-input").value;
let cloakIcon = document.getElementById("cloak-custom-favicon-input").value;
let localStorageItem = {
name: cloakName,
icon: cloakIcon,
isCustom: true,
};
localStorage.setItem("alu__selectedCloak", JSON.stringify(localStorageItem));
if (cloakName == "None") {
localStorage.removeItem("alu__selectedCloak");
cloakName = "Settings | Alu";
cloakIcon = "/favicon.png";
}
let link = document.querySelector("link[rel~='icon']");
if (!link) {
link = document.createElement("link");
link.rel = "icon";
document.head.appendChild(link);
}
link.href = cloakIcon;
document.title = cloakName;
});
}
function changeTheme() {
let theme = JSON.parse(localStorage.getItem("alu__selectedTheme")).value;
if (theme) {
document.documentElement.setAttribute("data-theme", theme.toLowerCase());
let footer = document.getElementById("footer");
if (footer) {
footer.dataset.theme = theme.toLowerCase();
}
}
}
function setupSettings(event) {
if (event.detail == "setting-tab-proxy") {
applySavedLocalStorage("alu__selectedProxy", "dropdown__selected-proxy");
applySavedLocalStorage("alu__search_engine", "dropdown__search-engine");
applySavedLocalStorage("alu__selectedOpenWith", "dropdown__open-with");
let selectedProxyDropdown = document.getElementById("dropdown__selected-proxy-menu");
let searchEngineDropdown = document.getElementById("dropdown__search-engine-menu");
let openWithDropdown = document.getElementById("dropdown__open-with-menu");
let bareUrlInput = document.getElementById("bare-url-input");
let searxngUrlInput = document.getElementById("searxng-url-input");
let savedSearxngUrl = localStorage.getItem("alu__searxngUrl");
if (savedSearxngUrl != undefined) {
if (savedSearxngUrl == "") localStorage.setItem("alu__searxngUrl", "https://searxng.site/");
searxngUrlInput.value = localStorage.getItem("alu__searxngUrl");
}
// Proxy settings
applyInputListeners(bareUrlInput, "alu__bareUrl");
applyInputListeners(searxngUrlInput, "alu__searxngUrl");
applyDropdownEventListeners(
searchEngineDropdown,
"dropdown__search-engine",
"alu__search_engine",
checkSearxng
);
applyDropdownEventListeners(
selectedProxyDropdown,
"dropdown__selected-proxy",
"alu__selectedProxy"
);
applyDropdownEventListeners(openWithDropdown, "dropdown__open-with", "alu__selectedOpenWith");
if (localStorage.getItem("bareUrl")) {
bareUrlInput.value = localStorage.getItem("bareUrl");
} else {
bareUrlInput.value = "/bare/";
}
checkSearxng();
} else if (event.detail == "setting-tab-customization") {
setupCustomizationSettings();
} else if (event.detail == "setting-tab-cloaking") {
setupCloakingSettings();
}
}
function checkSearxng() {
// This function checks if the "searxng" option was clicked, display an additional option if so.
if (localStorage.getItem("alu__search_engine")) {
if (JSON.parse(localStorage.getItem("alu__search_engine")).value.toLowerCase() == "searx") {
document.getElementsByClassName("setting__searxng-url")[0].style.opacity = "1";
} else {
document.getElementsByClassName("setting__searxng-url")[0].style.opacity = "0";
}
}
}
document.addEventListener("setting-tabLoad", setupSettings);
function navigateToNewLangaugePage() {
let value = JSON.parse(localStorage.getItem("alu__selectedLanguage")).value;
let currentLanguage = window.location.pathname.split("/")[1];
// Do nothing.. because we're already on the page.
if (value == currentLanguage) return;
switch (value) {
case "en":
window.location.href = "/en/settings/";
break;
case "jp":
window.location.href = "/jp/settings/";
break;
}
}
</script>
<style is:global>
.content-hidden {
display: none;
}
#current-content {
transition: opacity 250ms ease-in-out;
margin-left: 20px;
}
.settings-container {
display: flex;
gap: 20px;
position: relative;
z-index: 2;
}
.content-setting-header {
color: var(--text-color);
font-weight: 400;
}
.content-setting-subtext {
font-size: 20px;
color: var(--text-color-accent);
}
.setting-label {
color: var(--text-color);
font-size: 18px;
font-weight: 400;
/* annoying stuff with label elements. */
display: block;
opacity: 1;
margin-block: 1em;
margin-inline: 0;
user-select: none;
width: 100%;
cursor: auto;
}
.setting__searxng-url {
margin-top: 10px;
opacity: 0;
transition: opacity 250ms ease-in-out;
}
label {
font-size: 24px;
font-weight: 700;
cursor: pointer;
color: #d8d8d8;
opacity: 0.6;
transition: opacity 0.4s ease-in-out;
display: block;
width: calc(100% - 48px);
text-align: right;
z-index: 100;
user-select: none;
text-align: start;
margin-left: 20px;
}
input[type="radio"] {
display: none;
width: 0;
}
label:hover,
input[type="radio"]:checked + label {
opacity: 1;
}
.popup {
width: 98%;
height: 80%;
margin: 0 auto;
min-height: 400px;
max-height: 400px;
border-radius: 48px;
box-sizing: border-box;
background-color: var(--background-color);
overflow: hidden;
display: flex;
align-self: center;
}
.tabs {
width: 100%;
max-width: 240px;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
position: relative;
gap: 25px;
}
.marker {
position: absolute;
width: 100%;
height: 200%;
display: flex;
flex-direction: column;
top: calc(-100%);
left: 0;
transition: transform 0.2s ease-in-out;
background-color: var(--accent-color);
}
.marker #bottom,
.marker #top {
background-color: var(--background-highlight);
}
.marker #top {
height: calc(50%);
margin-bottom: auto;
border-radius: 0 0 32px 0;
}
.marker #bottom {
height: calc(50% - 72px);
border-radius: 0 32px 0 0;
}
#setting-tab-proxy:checked ~ .marker {
transform: translateY(0%);
}
#setting-tab-customization:checked ~ .marker {
transform: translateY(13.5%);
}
#setting-tab-cloaking:checked ~ .marker {
transform: translateY(27%);
}
#setting-tab-credits:checked ~ .marker {
transform: translateY(41%);
}
</style>

View file

@ -1,192 +0,0 @@
---
const { inputID } = Astro.props;
---
<label class="switch">
<input id={inputID} checked="" type="checkbox" />
<div class="slider">
<div class="circle">
<svg
class="cross"
xml:space="preserve"
style="enable-background:new 0 0 512 512"
viewBox="0 0 365.696 365.696"
y="0"
x="0"
height="6"
width="6"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
xmlns="http://www.w3.org/2000/svg">
<g>
<path
data-original="#000000"
fill="currentColor"
d="M243.188 182.86 356.32 69.726c12.5-12.5 12.5-32.766 0-45.247L341.238 9.398c-12.504-12.503-32.77-12.503-45.25 0L182.86 122.528 69.727 9.374c-12.5-12.5-32.766-12.5-45.247 0L9.375 24.457c-12.5 12.504-12.5 32.77 0 45.25l113.152 113.152L9.398 295.99c-12.503 12.503-12.503 32.769 0 45.25L24.48 356.32c12.5 12.5 32.766 12.5 45.247 0l113.132-113.132L295.99 356.32c12.503 12.5 32.769 12.5 45.25 0l15.081-15.082c12.5-12.504 12.5-32.77 0-45.25zm0 0"
></path>
</g>
</svg>
<svg
class="checkmark"
xml:space="preserve"
style="enable-background:new 0 0 512 512"
viewBox="0 0 24 24"
y="0"
x="0"
height="10"
width="10"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
xmlns="http://www.w3.org/2000/svg">
<g>
<path
class=""
data-original="#000000"
fill="currentColor"
d="M9.707 19.121a.997.997 0 0 1-1.414 0l-5.646-5.647a1.5 1.5 0 0 1 0-2.121l.707-.707a1.5 1.5 0 0 1 2.121 0L9 14.171l9.525-9.525a1.5 1.5 0 0 1 2.121 0l.707.707a1.5 1.5 0 0 1 0 2.121z"
></path>
</g>
</svg>
</div>
</div>
</label>
<style>
.switch {
--switch-width: 46px;
--switch-height: 24px;
--switch-bg: rgb(131, 131, 131);
--switch-checked-bg: rgb(0, 218, 80);
--switch-offset: calc((var(--switch-height) - var(--circle-diameter)) / 2);
--switch-transition: all 0.2s cubic-bezier(0.27, 0.2, 0.25, 1.51);
--circle-diameter: 18px;
--circle-bg: #fff;
--circle-shadow: 1px 1px 2px rgba(146, 146, 146, 0.45);
--circle-checked-shadow: -1px 1px 2px rgba(163, 163, 163, 0.45);
--circle-transition: var(--switch-transition);
--icon-transition: all 0.2s cubic-bezier(0.27, 0.2, 0.25, 1.51);
--icon-cross-color: var(--switch-bg);
--icon-cross-size: 6px;
--icon-checkmark-color: var(--switch-checked-bg);
--icon-checkmark-size: 10px;
--effect-width: calc(var(--circle-diameter) / 2);
--effect-height: calc(var(--effect-width) / 2 - 1px);
--effect-bg: var(--circle-bg);
--effect-border-radius: 1px;
--effect-transition: all 0.2s ease-in-out;
}
.switch input {
display: none;
}
.switch {
display: inline-block;
}
.switch svg {
-webkit-transition: var(--icon-transition);
-o-transition: var(--icon-transition);
transition: var(--icon-transition);
position: absolute;
height: auto;
}
.switch .checkmark {
width: var(--icon-checkmark-size);
color: var(--icon-checkmark-color);
-webkit-transform: scale(0);
-ms-transform: scale(0);
transform: scale(0);
}
.switch .cross {
width: var(--icon-cross-size);
color: var(--icon-cross-color);
}
.slider {
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: var(--switch-width);
height: var(--switch-height);
background: var(--switch-bg);
border-radius: 999px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
position: relative;
-webkit-transition: var(--switch-transition);
-o-transition: var(--switch-transition);
transition: var(--switch-transition);
cursor: pointer;
}
.circle {
width: var(--circle-diameter);
height: var(--circle-diameter);
background: var(--circle-bg);
border-radius: inherit;
-webkit-box-shadow: var(--circle-shadow);
box-shadow: var(--circle-shadow);
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-transition: var(--circle-transition);
-o-transition: var(--circle-transition);
transition: var(--circle-transition);
z-index: 1;
position: absolute;
left: var(--switch-offset);
}
.slider::before {
content: "";
position: absolute;
width: var(--effect-width);
height: var(--effect-height);
left: calc(var(--switch-offset) + (var(--effect-width) / 2));
background: var(--effect-bg);
border-radius: var(--effect-border-radius);
-webkit-transition: var(--effect-transition);
-o-transition: var(--effect-transition);
transition: var(--effect-transition);
}
/* actions */
.switch input:checked + .slider {
background: var(--switch-checked-bg);
}
.switch input:checked + .slider .checkmark {
-webkit-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
}
.switch input:checked + .slider .cross {
-webkit-transform: scale(0);
-ms-transform: scale(0);
transform: scale(0);
}
.switch input:checked + .slider::before {
left: calc(100% - var(--effect-width) - (var(--effect-width) / 2) - var(--switch-offset));
}
.switch input:checked + .slider .circle {
left: calc(100% - var(--circle-diameter) - var(--switch-offset));
-webkit-box-shadow: var(--circle-checked-shadow);
box-shadow: var(--circle-checked-shadow);
}
</style>

View file

@ -1,19 +0,0 @@
<script>
function switchTheme() {
let currentTheme = localStorage.getItem("alu__selectedTheme");
if (currentTheme) {
document.documentElement.setAttribute(
"data-theme",
JSON.parse(currentTheme).value.toLowerCase()
);
let footer = document.getElementById("footer");
if (footer) {
footer.dataset.theme = JSON.parse(currentTheme).value.toLowerCase();
}
}
}
switchTheme();
document.addEventListener("astro:after-swap", switchTheme);
</script>

View file

@ -0,0 +1,53 @@
---
import Link from "./Link.astro";
const { title, href } = Astro.props;
interface Props {
title: string;
href?: string;
}
const ID = title.toLowerCase().replaceAll(" ", "-");
---
{
href ? (
<Link href={href} newTab>
<div class="card card-link" id={"card-" + ID}>
<h2 class="card-title">{title}</h2>
<slot />
</div>
</Link>
) : (
<div class="card" id={"card-" + ID}>
<h2 class="card-title">{title}</h2>
<slot />
</div>
)
}
<style>
.card {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 18px;
background-color: var(--background-highlight);
border-radius: 10px;
padding-bottom: 1rem;
min-height: 140px;
}
.card-link {
cursor: pointer;
transition: 250ms ease-in-out;
}
.card-link:hover {
filter: brightness(0.9);
}
.card-title {
margin: 1rem;
text-align: center;
}
</style>

View file

@ -1,12 +1,18 @@
--- ---
const { buttonNameDefault, dropdownList, id } = Astro.props; const { buttonNameDefault, dropdownList, id, localStorageKey } = Astro.props;
interface Props {
buttonNameDefault: string;
dropdownList: { name: string; value: string }[];
id: string;
localStorageKey: Alu.ValidStoreKeys;
}
--- ---
<div class="dropdown"> <div class="dropdown">
<button id={id} class="dropdown-toggle" type="button" data-toggle="dropdown"> <button data-local-storage-key={localStorageKey} id={id} class="dropdown-toggle" type="button" data-toggle="dropdown">
{buttonNameDefault} {buttonNameDefault}
<span class="caret"></span></button </button>
>
<ul class="dropdown-menu" id={id + "-menu"}> <ul class="dropdown-menu" id={id + "-menu"}>
{ {
dropdownList.map((item: any) => { dropdownList.map((item: any) => {
@ -19,7 +25,7 @@ const { buttonNameDefault, dropdownList, id } = Astro.props;
} }
</ul> </ul>
</div> </div>
<style> <style is:global>
.dropdown { .dropdown {
box-shadow: 4px 6px 15px 0px var(--background-color); box-shadow: 4px 6px 15px 0px var(--background-color);
border-bottom-left-radius: 10px; border-bottom-left-radius: 10px;
@ -52,6 +58,7 @@ const { buttonNameDefault, dropdownList, id } = Astro.props;
background-color: var(--dropdown-background-color); background-color: var(--dropdown-background-color);
position: absolute; position: absolute;
width: 100%; width: 100%;
z-index: 5;
} }
.dropdown-item { .dropdown-item {
border-bottom: 1px solid var(--text-color-accent); border-bottom: 1px solid var(--text-color-accent);

View file

@ -0,0 +1,87 @@
---
import { i18n } from "@i18n/utils";
import Link from "./Link.astro";
import WaveSVG from "../WaveSVG.astro";
const t = i18n.inferLangUseTranslations(Astro.url);
---
<footer class="footer">
<div aria-hidden="true" class="wave-svg-container">
<WaveSVG />
</div>
<div class="footer-top">
<div class="footer-title">
<h2>{t("footer.brand")}</h2>
</div>
<div class="footer-madeby">
<Link href="https://wearr.dev" newTab>{t("footer.madeWithLove")}</Link>
</div>
</div>
<div class="footer-bottom">
<div class="footer-left">
<div class="footer-links">
<Link href="https://discord.gg/unblock" newTab>Join the discord!</Link>
<Link href="https://titaniumnetwork.org" newTab>{t("footer.poweredBy")}</Link>
<div class="footer-copyright">
<p>&copy; {t("footer.aluProject")} 2024</p>
</div>
</div>
</div>
<div class="footer-right">
<div class="footer-links">
<Link href="/privacy">Privacy</Link>
<Link href="/terms">Terms</Link>
<Link href="https://wearr.dev/contact" newTab>Contact</Link>
</div>
</div>
</div>
<style>
.wave-svg-container {
bottom: 0;
left: 0;
position: absolute;
width: 100%;
z-index: -1;
overflow: hidden;
height: 300px;
filter: brightness(1.5);
}
.footer {
display: flex;
flex-direction: column;
justify-content: space-around;
color: var(--text-color);
position: relative;
padding-top: 275px;
gap: 20px;
}
.footer-top,
.footer-bottom {
width: 90%;
margin: 0 auto;
}
.footer-title {
font-size: 20px;
}
.footer-bottom {
display: flex;
justify-content: space-between;
}
.footer-links {
display: flex;
gap: 10px;
flex-direction: column;
}
a {
color: var(--text-color);
}
</style>
</footer>

View file

@ -0,0 +1,84 @@
---
import { i18n } from "@i18n/utils";
const lang = i18n.getLangFromUrl(Astro.url);
const t = i18n.useTranslations(lang);
---
<nav class="top-header">
<div id="title-background" class="title-background">
<div class="left">
<a href={`/${lang}/`} class="header-item flex-item"><img class="nav-img" src="/favicon.svg" alt="Alu Logo" /><span>{t("nav.brand")}</span></a>
</div>
<div class="right">
<a href={`/${lang}/donate/`} class="header-item">Donate</a>
<a href={`/${lang}/marketplace/`} class="header-item">Marketplace</a>
<a href={`/${lang}/games/`} class="header-item">{t("nav.games")}</a>
<a href={`/${lang}/settings/`} class="header-item">{t("nav.settings")}</a>
</div>
</div>
</nav>
<style>
.top-header {
display: flex;
box-sizing: border-box;
transition: 250ms ease-in;
}
.title-background {
background-color: var(--accent-color);
display: flex;
align-items: center;
justify-content: space-between;
padding-inline: 2.5rem;
height: 4.25rem;
width: 100%;
border-bottom-left-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
box-shadow: -2px 5px 10px 0 var(--accent-color);
}
@media (max-width: 600px) {
.title-background {
padding-inline: 0.5rem;
}
.right > a:first-child {
display: none;
}
}
.left,
.right {
display: flex;
align-items: center;
gap: 10px;
}
.header-item {
color: var(--text-color);
text-decoration: none;
font-size: 22px;
transition: 250ms ease-in-out;
}
@media (max-width: 470px) {
.header-item {
font-size: 18px;
}
}
.header-item:hover {
color: var(--text-color-accent);
}
.nav-img {
height: 50px;
}
.flex-item {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
}
</style>

View file

@ -0,0 +1,34 @@
---
const { inputName, defaultTextContent, height, placeholder, className, defaultStyles = true, autocomplete = "on" } = Astro.props;
const styleList = className ? className.split(" ") : [];
if (defaultStyles) {
styleList.push("astro-input");
}
interface Props {
inputName: string;
defaultTextContent?: string;
height?: string;
placeholder?: string;
className?: string;
defaultStyles?: boolean;
autocomplete?: string;
}
let inputHeight = height;
if (!height) {
inputHeight = "3rem";
}
---
<input
style={`height: ${inputHeight}; font-family: 'Varela Round', sans-serif !important;`}
id={inputName + "-input"}
placeholder={placeholder || ""}
value={defaultTextContent || ""}
type="text"
class={styleList.map((style) => style).join(" ")}
autocomplete={autocomplete}
/>

View file

@ -0,0 +1,21 @@
---
interface LinkProps {
href: string;
newTab?: boolean;
content: string;
}
const { href, newTab } = Astro.props as LinkProps;
const target = newTab ? "_blank" : "_self";
const rel = newTab ? "noopener noreferrer" : "";
---
<a href={href} target={target} rel={rel}>
<slot />
</a>
<style>
a {
color: var(--text-color);
}
</style>

View file

@ -0,0 +1,29 @@
---
import Paintbrush from "@components/icons/paintbrush.astro";
import Scroll from "@components/icons/scroll.astro";
const { type } = Astro.props;
type Props = {
type: ExtType;
};
---
<div class="marketplace-icon">
<abbr title={type === "theme" ? "Theme" : "Script"}>
{type === "theme" ? <Paintbrush class="icon" /> : <Scroll class="icon" />}
</abbr>
</div>
<style is:global>
.marketplace-icon {
width: 32px;
filter: brightness(0.8);
align-self: flex-start;
padding-bottom: 1rem;
}
.mp-icon {
height: 24px;
}
</style>

Some files were not shown because too many files have changed in this diff Show more