Compare commits
12 Commits
laravel-12
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5b4d3d435e | |||
| 564f816fb9 | |||
| 3709e378c3 | |||
| 4a45dae593 | |||
| 2b0448d517 | |||
| 3bb6af73c3 | |||
| 57cf153560 | |||
| e45fd4b148 | |||
|
d479369770
|
|||
| b8ba17b33f | |||
| 5a8dd12cb8 | |||
| 3a77c4320d |
14
README.md
14
README.md
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
## hstream Website
|
## hstream Website
|
||||||
|
|
||||||
### Install
|
### Install (Ubuntu)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Install PHP
|
# Install PHP
|
||||||
sudo add-apt-repository ppa:ondrej/php
|
sudo add-apt-repository ppa:ondrej/php
|
||||||
apt update && apt upgrade
|
apt update && apt upgrade
|
||||||
apt install php8.3 php8.3-xml php8.3-mysql php8.3-gd php8.3-zip php8.3-curl php8.3-mbstring
|
apt install php8.4 php8.4-xml php8.4-mysql php8.4-gd php8.4-zip php8.4-curl php8.4-mbstring
|
||||||
|
|
||||||
# Install NodeJS
|
# Install NodeJS
|
||||||
curl -sL https://deb.nodesource.com/setup_20.x -o /tmp/nodesource_setup.sh
|
curl -sL https://deb.nodesource.com/setup_20.x -o /tmp/nodesource_setup.sh
|
||||||
@@ -22,7 +22,7 @@ mv composer.phar composer
|
|||||||
|
|
||||||
# Install NGINX (skip for local dev)
|
# Install NGINX (skip for local dev)
|
||||||
apt install nginx
|
apt install nginx
|
||||||
apt install php8.3-fpm
|
apt install php8.4-fpm
|
||||||
|
|
||||||
# Install MariaDB
|
# Install MariaDB
|
||||||
apt install mariadb-server
|
apt install mariadb-server
|
||||||
@@ -54,7 +54,7 @@ nano /etc/supervisor/conf.d/laravel-queue.conf :
|
|||||||
|
|
||||||
[program:laravel-queue]
|
[program:laravel-queue]
|
||||||
process_name=%(program_name)s_%(process_num)02d
|
process_name=%(program_name)s_%(process_num)02d
|
||||||
command=php /var/www/hstream/artisan queue:work --queue=default --sleep=3 --tries=3 --max-time=3600
|
command=php84 /var/www/hstream/artisan queue:work --queue=default --sleep=3 --tries=3 --max-time=3600
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
stopasgroup=true
|
stopasgroup=true
|
||||||
@@ -83,9 +83,9 @@ zip -r hstream_2023_11_30.zip hstream/
|
|||||||
|
|
||||||
### Update
|
### Update
|
||||||
```bash
|
```bash
|
||||||
php artisan down
|
php84 artisan down
|
||||||
git pull
|
git pull
|
||||||
npm run build
|
npm run build
|
||||||
php artisan view:clear && php artisan optimize:clear && php artisan cache:clear && service php8.4-fpm restart
|
php84 artisan view:clear && php84 artisan optimize:clear && php84 artisan cache:clear && service php8.4-fpm restart
|
||||||
php artisan up
|
php84 artisan up
|
||||||
```
|
```
|
||||||
|
|||||||
57
app/Http/Controllers/MatrixController.php
Normal file
57
app/Http/Controllers/MatrixController.php
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Requests\MatrixRegisterRequest;
|
||||||
|
use App\Services\MatrixRegistrationService;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class MatrixController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display the user page.
|
||||||
|
*/
|
||||||
|
public function index(Request $request): \Illuminate\View\View
|
||||||
|
{
|
||||||
|
$rooms = [
|
||||||
|
['name' => '🏠 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'],
|
||||||
|
['name' => '👗 NSFW 2D', 'description' => 'Channel for R18 2D Media.', 'alias' => 'https://matrix.to/#/#nsfw:hstream.moe'],
|
||||||
|
['name' => '👗 NSFW IRL', 'description' => 'Channel for R18 IRL Media.', 'alias' => 'https://matrix.to/#/#nsfw-irl: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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
app/Http/Requests/MatrixRegisterRequest.php
Normal file
49
app/Http/Requests/MatrixRegisterRequest.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class MatrixRegisterRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
$isOldEnough = $this->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, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|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 . _ = -',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,15 @@ class DownloadButton extends Component
|
|||||||
|
|
||||||
public $background = 'bg-rose-600';
|
public $background = 'bg-rose-600';
|
||||||
|
|
||||||
|
public $fileExtension = 'HEVC';
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
if (str_contains($this->downloadUrl, 'AV1')) {
|
||||||
|
$this->fileExtension = 'AV1';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function clicked($downloadId)
|
public function clicked($downloadId)
|
||||||
{
|
{
|
||||||
$download = Downloads::find($downloadId);
|
$download = Downloads::find($downloadId);
|
||||||
|
|||||||
49
app/Services/MatrixRegistrationService.php
Normal file
49
app/Services/MatrixRegistrationService.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
|
||||||
|
class MatrixRegistrationService
|
||||||
|
{
|
||||||
|
public function registerUser(string $username, string $password)
|
||||||
|
{
|
||||||
|
$server = config('services.matrix.server');
|
||||||
|
$secret = config('services.matrix.shared_secret');
|
||||||
|
|
||||||
|
// Get nonce from Synapse
|
||||||
|
$nonceResponse = Http::get("$server/_synapse/admin/v1/register");
|
||||||
|
|
||||||
|
if (!$nonceResponse->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();
|
||||||
|
}
|
||||||
|
}
|
||||||
16
composer.lock
generated
16
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "2e359f5cfd56c822e336b74becc9c9d9",
|
"content-hash": "3400111a6254560d548639295422875c",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "altcha-org/altcha",
|
"name": "altcha-org/altcha",
|
||||||
@@ -3036,16 +3036,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "livewire/livewire",
|
"name": "livewire/livewire",
|
||||||
"version": "v3.7.3",
|
"version": "v3.7.10",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/livewire/livewire.git",
|
"url": "https://github.com/livewire/livewire.git",
|
||||||
"reference": "a5384df9fbd3eaf02e053bc49aabc8ace293fc1c"
|
"reference": "0dc679eb4c8b4470cb12522b5927ef08ca2358bb"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/livewire/livewire/zipball/a5384df9fbd3eaf02e053bc49aabc8ace293fc1c",
|
"url": "https://api.github.com/repos/livewire/livewire/zipball/0dc679eb4c8b4470cb12522b5927ef08ca2358bb",
|
||||||
"reference": "a5384df9fbd3eaf02e053bc49aabc8ace293fc1c",
|
"reference": "0dc679eb4c8b4470cb12522b5927ef08ca2358bb",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3100,7 +3100,7 @@
|
|||||||
"description": "A front-end framework for Laravel.",
|
"description": "A front-end framework for Laravel.",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/livewire/livewire/issues",
|
"issues": "https://github.com/livewire/livewire/issues",
|
||||||
"source": "https://github.com/livewire/livewire/tree/v3.7.3"
|
"source": "https://github.com/livewire/livewire/tree/v3.7.10"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3108,7 +3108,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-12-19T02:00:29+00:00"
|
"time": "2026-02-09T22:49:33+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "maize-tech/laravel-markable",
|
"name": "maize-tech/laravel-markable",
|
||||||
@@ -11584,5 +11584,5 @@
|
|||||||
"php": "^8.2"
|
"php": "^8.2"
|
||||||
},
|
},
|
||||||
"platform-dev": {},
|
"platform-dev": {},
|
||||||
"plugin-api-version": "2.9.0"
|
"plugin-api-version": "2.6.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,5 +47,11 @@ return [
|
|||||||
'avatar_default_extension' => env('DISCORD_EXTENSION_DEFAULT', 'webp'), // only pick from jpg, png, webp
|
'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'),
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->string('matrix_id')
|
||||||
|
->nullable()
|
||||||
|
->after('discord_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('matrix_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
11
package-lock.json
generated
11
package-lock.json
generated
@@ -4,6 +4,7 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
|
"name": "hstream",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^6.5.1",
|
"@fortawesome/fontawesome-free": "^6.5.1",
|
||||||
"@jellyfin/libass-wasm": "^4.1.1",
|
"@jellyfin/libass-wasm": "^4.1.1",
|
||||||
@@ -1263,14 +1264,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.13.2",
|
"version": "1.13.5",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz",
|
||||||
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
|
"integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.6",
|
"follow-redirects": "^1.15.11",
|
||||||
"form-data": "^4.0.4",
|
"form-data": "^4.0.5",
|
||||||
"proxy-from-env": "^1.1.0"
|
"proxy-from-env": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -49,6 +49,22 @@
|
|||||||
<i class="fa-brands fa-discord"></i> {{ __('nav.our-discord-server') }}
|
<i class="fa-brands fa-discord"></i> {{ __('nav.our-discord-server') }}
|
||||||
</x-dropdown-link>
|
</x-dropdown-link>
|
||||||
|
|
||||||
|
<x-dropdown-link :href="route('join.matrix')">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
class="icon icon-tabler icons-tabler-outline icon-tabler-brand-matrix pr-1">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||||
|
<path d="M4 3h-1v18h1" />
|
||||||
|
<path d="M20 21h1v-18h-1" />
|
||||||
|
<path d="M7 9v6" />
|
||||||
|
<path d="M12 15v-3.5a2.5 2.5 0 1 0 -5 0v.5" />
|
||||||
|
<path d="M17 15v-3.5a2.5 2.5 0 1 0 -5 0v.5" />
|
||||||
|
</svg>
|
||||||
|
Join our Matrix
|
||||||
|
</div>
|
||||||
|
</x-dropdown-link>
|
||||||
|
|
||||||
<x-dropdown-link>
|
<x-dropdown-link>
|
||||||
<div class="grid grid-cols-2">
|
<div class="grid grid-cols-2">
|
||||||
<p class="cursor-default">{{ __('nav.theme') }}</p>
|
<p class="cursor-default">{{ __('nav.theme') }}</p>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
@else
|
@else
|
||||||
<p class="text-lg">Episode {{ $episodeNumber }}</p>
|
<p class="text-lg">Episode {{ $episodeNumber }}</p>
|
||||||
@endif
|
@endif
|
||||||
<p class="text-xs">HEVC MKV {{ $fileSize ?? '' }}</p>
|
<p class="text-xs">{{ $fileExtension }} MKV {{ $fileSize ?? '' }}</p>
|
||||||
<p class="text-xs" id="count-{{ $downloadId }}">Downloaded {{ $downloadCount }} times</p>
|
<p class="text-xs" id="count-{{ $downloadId }}">Downloaded {{ $downloadCount }} times</p>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -235,6 +235,11 @@
|
|||||||
'/' .
|
'/' .
|
||||||
$expire;
|
$expire;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$fileExtension = "HEVC";
|
||||||
|
if (str_contains($download->url, 'AV1')) {
|
||||||
|
$fileExtension = "AV1";
|
||||||
|
}
|
||||||
@endphp
|
@endphp
|
||||||
<a href="{{ $downloadURL }}" wire:click="clicked({{ $download->id }})"
|
<a href="{{ $downloadURL }}" wire:click="clicked({{ $download->id }})"
|
||||||
download>
|
download>
|
||||||
@@ -249,7 +254,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col text-center w-full">
|
<div class="flex flex-col text-center w-full">
|
||||||
<p class="text-xs">HEVC MKV</p>
|
<p class="text-xs">{{ $fileExtension }} MKV</p>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
<a href="{{ $dldomains[array_rand($dldomains)] }}/{{ $hdl->getDownloadByType('FHD')->url }}">
|
<a href="{{ $dldomains[array_rand($dldomains)] }}/{{ $hdl->getDownloadByType('FHD')->url }}">
|
||||||
|
@php
|
||||||
|
$fileExtension = "HEVC";
|
||||||
|
if (str_contains($hdl->getDownloadByType('FHD')->url, 'AV1')) {
|
||||||
|
$fileExtension = "AV1";
|
||||||
|
}
|
||||||
|
@endphp
|
||||||
<button class="group rounded-md shadow bg-rose-600 text-white cursor-pointer flex justify-between items-center overflow-hidden transition-all hover:glow m-1 w-[150px]">
|
<button class="group rounded-md shadow bg-rose-600 text-white cursor-pointer flex justify-between items-center overflow-hidden transition-all hover:glow m-1 w-[150px]">
|
||||||
<div class="relative w-12 h-12 bg-white bg-opacity-20 text-white flex justify-center items-center transition-all"><svg id="arrow" class="w-4 h-4 transition-all group-hover:-translate-y-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
<div class="relative w-12 h-12 bg-white bg-opacity-20 text-white flex justify-center items-center transition-all"><svg id="arrow" class="w-4 h-4 transition-all group-hover:-translate-y-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||||
@@ -7,7 +13,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="w-32 text-center">
|
<div class="w-32 text-center">
|
||||||
<p class="px-5 text-sm row-span-2">Episode {{ $hdl->episode }}</p>
|
<p class="px-5 text-sm row-span-2">Episode {{ $hdl->episode }}</p>
|
||||||
<p class="px-5 text-xs">HEVC MKV</p>
|
<p class="px-5 text-xs">{{ $fileExtension }} MKV</p>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
169
resources/views/matrix/index.blade.php
Normal file
169
resources/views/matrix/index.blade.php
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
<x-app-layout>
|
||||||
|
<div class="min-h-screen">
|
||||||
|
<div class="max-w-5xl mx-auto py-16 px-6">
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="text-center mb-8">
|
||||||
|
<h1 class="text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||||
|
We're Moving to Matrix 🚀
|
||||||
|
</h1>
|
||||||
|
<p class="text-lg text-gray-600 dark:text-neutral-200 max-w-3xl mx-auto">
|
||||||
|
Due to recent changes with Discord, we are transitioning our community to
|
||||||
|
<span class="font-semibold text-indigo-600">Matrix</span> —
|
||||||
|
an open, decentralized communication network.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Why Matrix -->
|
||||||
|
<div class="bg-white dark:bg-neutral-800 rounded-2xl shadow-sm p-8 mb-8">
|
||||||
|
<h2 class="text-2xl dark:text-white font-semibold mb-4">What is Matrix?</h2>
|
||||||
|
|
||||||
|
<p class="text-gray-700 dark:text-neutral-300 mb-4">
|
||||||
|
Matrix is an open-source messaging system. Unlike Discord, it is
|
||||||
|
<strong>decentralized</strong>. That means no single company controls it.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul class="list-disc pl-6 text-gray-700 dark:text-neutral-300 space-y-2">
|
||||||
|
<li>You can choose which server (called a “homeserver”) you register on.</li>
|
||||||
|
<li>All servers communicate with each other (this is called federation).</li>
|
||||||
|
<li>You are <strong>not required</strong> to use our server to join our rooms.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="mt-6 p-4 bg-pink-50 dark:bg-pink-950 border border-pink-100 dark:border-pink-700 rounded-lg">
|
||||||
|
<p class="text-pink-500 text-sm">
|
||||||
|
Example: You can register at a different server like matrix.org and still join our rooms.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Our Server -->
|
||||||
|
<div class="bg-white dark:bg-neutral-800 rounded-2xl shadow-sm p-8 mb-8">
|
||||||
|
<h2 class="text-2xl dark:text-white font-semibold mb-4">Our Matrix Server</h2>
|
||||||
|
|
||||||
|
<p class="text-gray-700 dark:text-neutral-300 mb-4">
|
||||||
|
We provide our own Matrix homeserver for community members.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul class="list-disc pl-6 text-gray-700 dark:text-neutral-300 space-y-2 mb-6">
|
||||||
|
<li>Available to users registered for more than 1 month</li>
|
||||||
|
<li>Fully federated with the entire Matrix network</li>
|
||||||
|
<li>No obligation to use it - it’s optional</li>
|
||||||
|
<li>Anonymized IP addresses to protect your privacy</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
@auth
|
||||||
|
@if(auth()->user()->created_at->lt(now()->subMonth()))
|
||||||
|
@if(auth()->user()->matrix_id)
|
||||||
|
<div class="bg-green-50 dark:bg-green-950 dark:border-green-700 border border-green-200 p-6 rounded-xl">
|
||||||
|
<h3 class="font-semibold text-green-800 dark:text-green-300 mb-2">
|
||||||
|
✅ You are registered!
|
||||||
|
</h3>
|
||||||
|
<p class="text-green-700 dark:text-green-400 mb-4">
|
||||||
|
Your Matrix account has been created successfully.
|
||||||
|
</p>
|
||||||
|
<p class="text-green-700 dark:text-green-400 mb-4">
|
||||||
|
Make sure to store your password, as we don't have a password reset function!
|
||||||
|
</p>
|
||||||
|
<p class="text-green-700 dark:text-green-400 mb-4">
|
||||||
|
You can now log in using any Matrix client of your choice.
|
||||||
|
</p>
|
||||||
|
<p class="text-green-700 dark:text-green-400 mb-4">
|
||||||
|
For the best experience, we recommend:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc text-green-700 dark:text-green-400 pl-6 space-y-2 mb-6">
|
||||||
|
<li>Downloading the official <strong><a href="https://element.io/download" target="_blank" class="underline">Element</a></strong> app for desktop or mobile</li>
|
||||||
|
<li>Or using our web client via <strong><a href="https://element.hstream.moe/" target="_blank" class="underline">Element Web</a></strong></li>
|
||||||
|
</ul>
|
||||||
|
<p class="text-green-700 dark:text-green-400 mb-4">
|
||||||
|
Simply sign in with your new username (<code>{{ $user->matrix_id }}</code>) and password to get started.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="bg-green-50 dark:bg-green-950 dark:border-green-700 border border-green-200 p-6 rounded-xl">
|
||||||
|
<h3 class="font-semibold text-green-800 dark:text-green-300 mb-2">
|
||||||
|
🎉 You are eligible!
|
||||||
|
</h3>
|
||||||
|
<p class="text-green-700 dark:text-green-400 mb-2">
|
||||||
|
Your account is older than one month. You can create your account now.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="p-4 bg-red-100 dark:bg-red-950 border border-red-100 dark:border-red-700 rounded-lg mb-4">
|
||||||
|
<p class="text-red-500 text-sm font-bold">
|
||||||
|
Important: Save your password! We don't have a password reset function yet!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@include('matrix.register')
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@else
|
||||||
|
<div class="bg-yellow-50 dark:bg-yellow-900 border border-yellow-200 dark:border-yellow-700 p-6 rounded-xl">
|
||||||
|
<h3 class="font-semibold text-yellow-800 dark:text-yellow-300 mb-2">
|
||||||
|
⏳ Not Yet Eligible
|
||||||
|
</h3>
|
||||||
|
<p class="text-yellow-700 dark:text-yellow-400">
|
||||||
|
Your account must be at least one month old to register
|
||||||
|
on our Matrix server.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@else
|
||||||
|
<div class="bg-gray-100 dark:bg-neutral-700 p-6 rounded-xl text-center">
|
||||||
|
<p class="text-gray-700 dark:text-gray-100">
|
||||||
|
Please log in to check if you're eligible for our Matrix server.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
@endauth
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Our Space -->
|
||||||
|
<div class="bg-white dark:bg-neutral-800 rounded-2xl shadow-sm p-8 mb-8">
|
||||||
|
<h2 class="text-2xl dark:text-white font-semibold mb-4">Our Matrix Space</h2>
|
||||||
|
|
||||||
|
<p class="text-gray-700 dark:text-neutral-300 mb-4">
|
||||||
|
All of our rooms are organized inside our main Matrix Space:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="bg-gray-100 dark:bg-neutral-700 dark:text-neutral-300 p-4 rounded-lg font-mono text-sm break-all">
|
||||||
|
<a href="https://matrix.to/#/#hstream:hstream.moe" target="_blank">https://matrix.to/#/#hstream:hstream.moe</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Room List -->
|
||||||
|
<div class="bg-white dark:bg-neutral-800 rounded-2xl shadow-sm p-8 mb-8">
|
||||||
|
<h2 class="text-2xl dark:text-white font-semibold mb-6">Our Matrix Rooms</h2>
|
||||||
|
|
||||||
|
<div class="grid md:grid-cols-2 gap-6">
|
||||||
|
@foreach($rooms as $room)
|
||||||
|
<div class="border dark:border-neutral-900 rounded-xl p-6 hover:shadow-md dark:bg-neutral-800 hover:dark:bg-neutral-900/60 transition">
|
||||||
|
<h3 class="font-semibold dark:text-neutral-100 text-lg mb-2">
|
||||||
|
{{ $room['name'] }}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p class="text-gray-600 dark:text-neutral-300 text-sm mb-4">
|
||||||
|
{{ $room['description'] }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="bg-gray-100 dark:bg-neutral-700 dark:text-neutral-300 p-3 rounded text-xs font-mono break-all">
|
||||||
|
<a href="{{ $room['alias'] }}" target="_blank">{{ $room['alias'] }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Guide -->
|
||||||
|
<div class="bg-white dark:bg-neutral-800 rounded-2xl shadow-sm p-8">
|
||||||
|
<h2 class="text-2xl dark:text-white font-semibold mb-4">Matrix Guide</h2>
|
||||||
|
|
||||||
|
<p class="text-gray-700 dark:text-neutral-300 mb-4">
|
||||||
|
Matrix and Element can be overwhelming for new users, so here is a guide from Element:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul class="list-disc pl-6 text-gray-700 dark:text-neutral-300 space-y-2 mb-6">
|
||||||
|
<li>Element Guide: <a class="font-bold text-green-800 dark:text-green-300 underline" referrerPolicy="no-referrer" href="https://static.element.io/pdfs/element-user-guide.pdf" target="_blank">element-user-guide.pdf</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</x-app-layout>
|
||||||
31
resources/views/matrix/register.blade.php
Normal file
31
resources/views/matrix/register.blade.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<form method="POST" action="{{ route('join.matrix.create') }}">
|
||||||
|
@csrf
|
||||||
|
<div>
|
||||||
|
<x-input-label for="username" :value="__('Username')" />
|
||||||
|
<x-text-input id="username" class="block mt-1 w-full" type="text" name="username" :value="old('username')" required autofocus autocomplete="username" />
|
||||||
|
<x-input-error :messages="$errors->get('username')" class="mt-2" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<x-input-label for="password" :value="__('Password')" />
|
||||||
|
<x-text-input id="password" class="block mt-1 w-full"
|
||||||
|
type="password"
|
||||||
|
name="password"
|
||||||
|
required/>
|
||||||
|
<x-input-error :messages="$errors->get('password')" class="mt-2" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<x-input-label for="password_confirmation" :value="__('Confirm Password')" />
|
||||||
|
<x-text-input id="password_confirmation" class="block mt-1 w-full"
|
||||||
|
type="password"
|
||||||
|
name="password_confirmation"
|
||||||
|
required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-end mt-4">
|
||||||
|
<x-primary-button class="ms-4">
|
||||||
|
{{ __('Create Matrix Account') }}
|
||||||
|
</x-primary-button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@@ -52,7 +52,19 @@
|
|||||||
<br>
|
<br>
|
||||||
@php $download = $episode->getDownloadByType('UHD'); @endphp
|
@php $download = $episode->getDownloadByType('UHD'); @endphp
|
||||||
@isset($download)
|
@isset($download)
|
||||||
@if (!Auth::user()->hasRole(\App\Enums\UserRole::SUPPORTER))
|
@if (Auth::user()->hasRole(\App\Enums\UserRole::SUPPORTER) || Auth::user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR))
|
||||||
|
<p class="font-bold text-gray-800 dark:text-gray-200">
|
||||||
|
<i class="fa-solid fa-lock-open pr-[4px] text-green-400"></i> 4k
|
||||||
|
</p>
|
||||||
|
|
||||||
|
@php $dlpdomains = config('hstream.download_domain_4k'); @endphp
|
||||||
|
|
||||||
|
<div class="flex flex-wrap justify-around">
|
||||||
|
@foreach ($dlList as $hdl)
|
||||||
|
@include('modals.partials.download-button-patreon')
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
@if (config('hstream.free_downloads'))
|
@if (config('hstream.free_downloads'))
|
||||||
<p class="font-bold text-gray-800 dark:text-gray-200">
|
<p class="font-bold text-gray-800 dark:text-gray-200">
|
||||||
<i class="fa-solid fa-lock-open pr-[4px] text-yellow-600"></i> 4k
|
<i class="fa-solid fa-lock-open pr-[4px] text-yellow-600"></i> 4k
|
||||||
@@ -67,18 +79,6 @@
|
|||||||
on our Discord server, you have to logout and login again.
|
on our Discord server, you have to logout and login again.
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
@else
|
|
||||||
<p class="font-bold text-gray-800 dark:text-gray-200">
|
|
||||||
<i class="fa-solid fa-lock-open pr-[4px] text-green-400"></i> 4k
|
|
||||||
</p>
|
|
||||||
|
|
||||||
@php $dlpdomains = config('hstream.download_domain_4k'); @endphp
|
|
||||||
|
|
||||||
<div class="flex flex-wrap justify-around">
|
|
||||||
@foreach ($dlList as $hdl)
|
|
||||||
@include('modals.partials.download-button-patreon')
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
@endif
|
@endif
|
||||||
@else
|
@else
|
||||||
<p class="text-gray-800 dark:text-gray-200 font-bold">
|
<p class="text-gray-800 dark:text-gray-200 font-bold">
|
||||||
@@ -91,7 +91,19 @@
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
@if ($episode->interpolated_uhd)
|
@if ($episode->interpolated_uhd)
|
||||||
@if (!Auth::user()->hasRole(\App\Enums\UserRole::SUPPORTER))
|
@if (Auth::user()->hasRole(\App\Enums\UserRole::SUPPORTER) || Auth::user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR) )
|
||||||
|
<p class="font-bold text-gray-800 dark:text-gray-200">
|
||||||
|
<i class="fa-solid fa-lock-open pr-[4px] text-green-400"></i> 4k 48fps
|
||||||
|
</p>
|
||||||
|
|
||||||
|
@php $dlpdomains = config('hstream.download_domain_4k'); @endphp
|
||||||
|
|
||||||
|
<div class="flex flex-wrap justify-around">
|
||||||
|
@foreach ($dlList as $hdl)
|
||||||
|
@include('modals.partials.download-button-patreon-interpolated')
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
@if (config('hstream.free_downloads'))
|
@if (config('hstream.free_downloads'))
|
||||||
<p class="font-bold text-gray-800 dark:text-gray-200">
|
<p class="font-bold text-gray-800 dark:text-gray-200">
|
||||||
<i class="fa-solid fa-lock-open pr-[4px] text-yellow-600"></i> 4k 48fps
|
<i class="fa-solid fa-lock-open pr-[4px] text-yellow-600"></i> 4k 48fps
|
||||||
@@ -106,18 +118,6 @@
|
|||||||
on our Discord server, you have to logout and login again.
|
on our Discord server, you have to logout and login again.
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
@else
|
|
||||||
<p class="font-bold text-gray-800 dark:text-gray-200">
|
|
||||||
<i class="fa-solid fa-lock-open pr-[4px] text-green-400"></i> 4k 48fps
|
|
||||||
</p>
|
|
||||||
|
|
||||||
@php $dlpdomains = config('hstream.download_domain_4k'); @endphp
|
|
||||||
|
|
||||||
<div class="flex flex-wrap justify-around">
|
|
||||||
@foreach ($dlList as $hdl)
|
|
||||||
@include('modals.partials.download-button-patreon-interpolated')
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|||||||
@@ -28,9 +28,15 @@
|
|||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
@php
|
||||||
|
$fileExtension = "HEVC";
|
||||||
|
if (str_contains($episode->getDownloadByType('FHD')->url, 'AV1')) {
|
||||||
|
$fileExtension = "AV1";
|
||||||
|
}
|
||||||
|
@endphp
|
||||||
<div class="flex flex-col text-center w-full">
|
<div class="flex flex-col text-center w-full">
|
||||||
<p class="text-xl">Episode {{ $episode->episode }}</p>
|
<p class="text-xl">Episode {{ $episode->episode }}</p>
|
||||||
<p class="text-xs">HEVC MKV {{ $episode->getDownloadByType('FHD')->getFileSize() ?? '' }}</p>
|
<p class="text-xs">{{ $fileExtension }} MKV {{ $episode->getDownloadByType('FHD')->getFileSize() ?? '' }}</p>
|
||||||
<p class="text-xs" id="downloadCount">Downloaded {{ $episode->getDownloadByType('FHD')->count }} times</p>
|
<p class="text-xs" id="downloadCount">Downloaded {{ $episode->getDownloadByType('FHD')->count }} times</p>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -11,7 +11,14 @@ use Illuminate\Support\Facades\Route;
|
|||||||
| User Routes
|
| User Routes
|
||||||
|---------------------------------------------------------------------------------
|
|---------------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Matrix
|
||||||
|
Route::get('/join-matrix', [App\Http\Controllers\MatrixController::class, 'index'])->name('join.matrix');
|
||||||
|
|
||||||
Route::middleware('auth')->group(function () {
|
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/profile', [ProfileController::class, 'index'])->name('profile.show');
|
||||||
Route::get('/user/comments', [ProfileController::class, 'comments'])->name('profile.comments');
|
Route::get('/user/comments', [ProfileController::class, 'comments'])->name('profile.comments');
|
||||||
Route::get('/user/likes', [ProfileController::class, 'likes'])->name('profile.likes');
|
Route::get('/user/likes', [ProfileController::class, 'likes'])->name('profile.likes');
|
||||||
|
|||||||
Reference in New Issue
Block a user