diff --git a/composer.json b/composer.json
index a0e74ae..ee5660e 100644
--- a/composer.json
+++ b/composer.json
@@ -26,7 +26,8 @@
"pragmarx/google2fa": "^8.0",
"spatie/laravel-permission": "^5.7",
"stancl/tenancy": "^3.7",
- "tightenco/ziggy": "^v1.4.3"
+ "tightenco/ziggy": "^v1.4.3",
+ "ext-zlib": "*"
},
"require-dev": {
"barryvdh/laravel-ide-helper": "^2.12",
diff --git a/resources/js/Components/Icon.vue b/resources/js/Components/Icon.vue
index c3bacef..ae4fe5f 100644
--- a/resources/js/Components/Icon.vue
+++ b/resources/js/Components/Icon.vue
@@ -22,5 +22,10 @@ onMounted(async () => {
})
-
+
+
diff --git a/resources/js/Components/Tooltip.vue b/resources/js/Components/Tooltip.vue
index 89e4b4d..47c3775 100644
--- a/resources/js/Components/Tooltip.vue
+++ b/resources/js/Components/Tooltip.vue
@@ -55,7 +55,7 @@ const positioning = () => {
diff --git a/routes/web.php b/routes/web.php
index 07c40f9..63a567f 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -36,6 +36,8 @@
use App\Http\Controllers\System\SearchController;
use App\Http\Controllers\System\UploadController;
use App\Http\Controllers\System\UserController;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Route;
/*
@@ -247,6 +249,77 @@
//Route::get('/servers', [\App\Http\Controllers\ServerController::class, 'index'])->name('servers.index');
+
+Route::get('/tools/music', function () {
+ $library = Cache::get('boomlings:sfxLibrary');
+ if (! $library) {
+ $secret = '8501f9c2-75ba-4230-8188-51037c4da102';
+ $expires = 9_999_999_999;
+ $token = base64_urldecode(hash('sha256', $secret . $secret));
+ //$res = Http::get('https://geometrydashfiles.b-cdn.net/music/musiclibrary.dat?token=' . $token . '&expires=' . $expires)->body();
+ $res = Http::get('https://geometrydashfiles.b-cdn.net/music/musiclibrary.dat')->body();
+ $res = mb_convert_encoding($res, 'UTF-8', 'UTF-8');;
+ $res = base64_urldecode($res);
+ $res = zlib_decode($res);
+ $res = explode('|', $res);
+ $library = [];
+ for ($i = 1; $i < count($res); $i++) {
+ $res[$i] = explode(';', $res[$i]);
+ array_pop($res[$i]); // Remove trailing ';'
+ for ($j = 0; $j < count($res[$i]); $j++) {
+ $bits = explode(',', $res[$i][$j]);
+ switch ($i) {
+ case 1: // Artist
+ $library['artists'][(int)$bits[0]] = [
+ 'name' => $bits[1],
+ 'website' => empty(trim($bits[2])) ? null : $bits[2],
+ 'youtube' => empty(trim($bits[3])) ? null : $bits[3],
+ ];
+ break;
+ case 2: // Song
+ $tags = explode('.', $bits[5]);
+ array_pop($tags);
+ array_shift($tags); // todo: slice?
+ for ($k = 0; $k < count($tags); $k++) $tags[$k] = (int) $tags[$k];
+ $library['songs'][(int)$bits[0]] = [
+ 'name' => $bits[1],
+ 'artist' => (int) $bits[2],
+ 'bytes' => (int) $bits[3],
+ 'seconds' => (int) $bits[4],
+ 'tags' => $tags,
+ ];
+ break;
+ case 3: // Tag
+ $library['tags'][(int)$bits[0]] = [
+ 'name' => $bits[1],
+ ];
+ break;
+ }
+ }
+ }
+ $library['version'] = $res[0];
+ $library = json_decode(json_encode($library, JSON_INVALID_UTF8_IGNORE));
+ Cache::put('boomlings:musicLibrary', $library, 60 * 60);
+ }
+ return page('Tools/Music', [
+ 'library' => json_decode(json_encode($library, JSON_INVALID_UTF8_IGNORE)) // FIXME: this sucks
+ ]);
+})->name('tools.music');
+
+Route::get('/guide', function () {
+ return page('Guide');
+})->name('guide');
+
+Route::get('/guide/{page}', function (string $page) {
+ $page = rtrim($page, '/');
+ $page = str_replace('/', ' ', $page);
+ $page = ucwords($page);
+ $page = str_replace(' ', '/', $page);
+ if (str_contains($page, '..')) abort(404);
+ if (!file_exists(base_path() . '/resources/js/Pages/Guide/' . $page . '.vue')) abort(404);
+ return page('Guide/' . $page);
+})->where('page', '.*')->name('guide.show');
+
Route::impersonate();
require_once 'auth.php';