From 3bb6af73c3a49fae0f5b2285695425756c4b9897 Mon Sep 17 00:00:00 2001 From: w33b Date: Wed, 18 Feb 2026 12:34:10 +0100 Subject: [PATCH] Add matrix --- app/Http/Controllers/MatrixController.php | 55 +++++++ app/Http/Requests/MatrixRegisterRequest.php | 49 ++++++ app/Services/MatrixRegistrationService.php | 49 ++++++ config/services.php | 8 +- ...17_222326_add_matrix_id_to_users_table.php | 30 ++++ resources/views/layouts/navigation.blade.php | 16 ++ resources/views/matrix/index.blade.php | 149 ++++++++++++++++++ resources/views/matrix/register.blade.php | 31 ++++ routes/user.php | 7 + 9 files changed, 393 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/MatrixController.php create mode 100644 app/Http/Requests/MatrixRegisterRequest.php create mode 100644 app/Services/MatrixRegistrationService.php create mode 100644 database/migrations/2026_02_17_222326_add_matrix_id_to_users_table.php create mode 100644 resources/views/matrix/index.blade.php create mode 100644 resources/views/matrix/register.blade.php diff --git a/app/Http/Controllers/MatrixController.php b/app/Http/Controllers/MatrixController.php new file mode 100644 index 0000000..7c711ed --- /dev/null +++ b/app/Http/Controllers/MatrixController.php @@ -0,0 +1,55 @@ + '๐Ÿ  General', 'description' => 'Our main chat.', 'alias' => 'https://matrix.to/#/#general:hstream.moe'], + ['name' => '๐Ÿ“ก Releases', 'description' => 'Were we @everyone for new releases.', 'alias' => 'https://matrix.to/#/#releases:hstream.moe'] + ]; + + return view('matrix.index', [ + 'user' => $request->user(), + 'rooms' => $rooms, + ]); + } + + /** + * Create matrix user + */ + public function store( + MatrixRegisterRequest $request, + MatrixRegistrationService $matrixService + ) { + try { + $result = $matrixService->registerUser( + $request->username, + $request->password + ); + + $user = $request->user(); + $user->matrix_id = $result['user_id']; + $user->save(); + + return redirect() + ->back() + ->with('success', 'Matrix user created successfully.'); + } catch (\Exception $e) { + return back() + ->withErrors([ + 'username' => $e->getMessage() + ]) + ->withInput(); + } + } +} diff --git a/app/Http/Requests/MatrixRegisterRequest.php b/app/Http/Requests/MatrixRegisterRequest.php new file mode 100644 index 0000000..d2951ef --- /dev/null +++ b/app/Http/Requests/MatrixRegisterRequest.php @@ -0,0 +1,49 @@ +user()->created_at->lt(now()->subMonth()); + $noAccount = !$this->user()->matrix_id; + return $isOldEnough && $noAccount; + } + + /** + * Get the validation rules that apply to the request. + * + * @return array|string> + */ + public function rules(): array + { + return [ + 'username' => [ + 'required', + 'string', + 'min:3', + 'max:32', + 'regex:/^[a-z0-9._=-]+$/', // Valid Matrix localpart + ], + 'password' => [ + 'required', + 'string', + 'min:8', + 'confirmed', + ], + ]; + } + + public function messages(): array + { + return [ + 'username.regex' => 'Username may only contain lowercase letters, numbers and . _ = -', + ]; + } +} diff --git a/app/Services/MatrixRegistrationService.php b/app/Services/MatrixRegistrationService.php new file mode 100644 index 0000000..524e2cc --- /dev/null +++ b/app/Services/MatrixRegistrationService.php @@ -0,0 +1,49 @@ +ok()) { + throw new \Exception("Could not fetch nonce from Matrix."); + } + + $nonce = $nonceResponse->json()['nonce']; + + // Generate MAC + $mac = hash_hmac( + 'sha1', + $nonce . "\0" . + $username . "\0" . + $password . "\0" . + "notadmin", + $secret + ); + + // Send registration request + $response = Http::post("$server/_synapse/admin/v1/register", [ + 'nonce' => $nonce, + 'username' => $username, + 'password' => $password, + 'admin' => false, + 'mac' => $mac, + ]); + + if ($response->failed()) { + $error = $response->json()['error'] ?? $response->body(); + throw new \Exception($error); + } + + return $response->json(); + } +} diff --git a/config/services.php b/config/services.php index b02de0e..5622ee9 100644 --- a/config/services.php +++ b/config/services.php @@ -47,5 +47,11 @@ return [ 'avatar_default_extension' => env('DISCORD_EXTENSION_DEFAULT', 'webp'), // only pick from jpg, png, webp ], - + /** + * Matrix Registration + */ + 'matrix' => [ + 'server' => env('MATRIX_SERVER'), + 'shared_secret' => env('MATRIX_SHARED_SECRET'), + ], ]; diff --git a/database/migrations/2026_02_17_222326_add_matrix_id_to_users_table.php b/database/migrations/2026_02_17_222326_add_matrix_id_to_users_table.php new file mode 100644 index 0000000..2d1f4f1 --- /dev/null +++ b/database/migrations/2026_02_17_222326_add_matrix_id_to_users_table.php @@ -0,0 +1,30 @@ +string('matrix_id') + ->nullable() + ->after('discord_id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('matrix_id'); + }); + } +}; diff --git a/resources/views/layouts/navigation.blade.php b/resources/views/layouts/navigation.blade.php index 914cc13..35b2d46 100644 --- a/resources/views/layouts/navigation.blade.php +++ b/resources/views/layouts/navigation.blade.php @@ -49,6 +49,22 @@ {{ __('nav.our-discord-server') }} + +
+ + + + + + + + + Join our Matrix +
+
+

{{ __('nav.theme') }}

diff --git a/resources/views/matrix/index.blade.php b/resources/views/matrix/index.blade.php new file mode 100644 index 0000000..b49b8c9 --- /dev/null +++ b/resources/views/matrix/index.blade.php @@ -0,0 +1,149 @@ + +
+
+ + +
+

+ We're Moving to Matrix ๐Ÿš€ +

+

+ Due to recent changes with Discord, we are transitioning our community to + Matrix โ€” + an open, decentralized communication network. +

+
+ + +
+

What is Matrix?

+ +

+ Matrix is an open-source messaging system. Unlike Discord, it is + decentralized. That means no single company controls it. +

+ +
    +
  • You can choose which server (called a โ€œhomeserverโ€) you register on.
  • +
  • All servers communicate with each other (this is called federation).
  • +
  • You are not required to use our server to join our rooms.
  • +
+ +
+

+ Example: You can register at a different server like matrix.org and still join our rooms. +

+
+
+ + +
+

Our Matrix Server

+ +

+ We provide our own Matrix homeserver for community members. +

+ +
    +
  • Available to users registered for more than 1 month
  • +
  • Fully federated with the entire Matrix network
  • +
  • No obligation to use it โ€” itโ€™s optional
  • +
+ + @auth + @if(auth()->user()->created_at->lt(now()->subMonth())) + @if(auth()->user()->matrix_id) +
+

+ โœ… You are registered! +

+

+ Your Matrix account has been created successfully. +

+

+ Make sure to store your password, as we don't have a password reset function! +

+

+ You can now log in using any Matrix client of your choice. +

+

+ For the best experience, we recommend: +

+
    +
  • Downloading the official Element app for desktop or mobile
  • +
  • Or using our web client via Element Web
  • +
+

+ Simply sign in with your new username and password to get started. +

+
+ @else +
+

+ ๐ŸŽ‰ You are eligible! +

+

+ Your account is older than one month. You can create your account now. +

+ + @include('matrix.register') +
+ @endif + @else +
+

+ โณ Not Yet Eligible +

+

+ Your account must be at least one month old to register + on our Matrix server. +

+
+ @endif + @else +
+

+ Please log in to check if you're eligible for our Matrix server. +

+
+ @endauth +
+ + +
+

Our Matrix Space

+ +

+ All of our rooms are organized inside our main Matrix Space: +

+ + +
+ + +
+

Our Matrix Rooms

+ +
+ @foreach($rooms as $room) +
+

+ {{ $room['name'] }} +

+ +

+ {{ $room['description'] }} +

+ + +
+ @endforeach +
+
+
+
+
\ No newline at end of file diff --git a/resources/views/matrix/register.blade.php b/resources/views/matrix/register.blade.php new file mode 100644 index 0000000..b4cce75 --- /dev/null +++ b/resources/views/matrix/register.blade.php @@ -0,0 +1,31 @@ +
+ @csrf +
+ + + +
+ +
+ + + +
+ +
+ + +
+ +
+ + {{ __('Create Matrix User') }} + +
+
diff --git a/routes/user.php b/routes/user.php index fa67864..2514b37 100644 --- a/routes/user.php +++ b/routes/user.php @@ -11,7 +11,14 @@ use Illuminate\Support\Facades\Route; | User Routes |--------------------------------------------------------------------------------- */ + +// Matrix +Route::get('/join-matrix', [App\Http\Controllers\MatrixController::class, 'index'])->name('join.matrix'); + Route::middleware('auth')->group(function () { + // Matrix + Route::post('/join-matrix', [App\Http\Controllers\MatrixController::class, 'store'])->name('join.matrix.create'); + Route::get('/user/profile', [ProfileController::class, 'index'])->name('profile.show'); Route::get('/user/comments', [ProfileController::class, 'comments'])->name('profile.comments'); Route::get('/user/likes', [ProfileController::class, 'likes'])->name('profile.likes');