Compare commits

...

17 Commits

Author SHA1 Message Date
w33b 1bc505057f Fix adding theme switch event listener on login page 2026-04-18 19:15:43 +02:00
w33b a78b1c41ac Remove unused code & Move files to correct folder 2026-04-18 18:42:09 +02:00
w33b 2480c5b309 Redo user comments list 2026-04-18 16:28:50 +02:00
w33b 4fc11d7329 Redo notification list 2026-04-18 15:47:06 +02:00
w33b f3e5100d5d Pint 2026-04-18 14:18:52 +02:00
w33b 5b4d3d435e Display the correct file extension on download button 2026-03-06 22:06:20 +01:00
w33b 564f816fb9 Add matrix nsfw rooms 2026-03-04 14:34:16 +01:00
w33b 3709e378c3 Fix Admin Download Buttons 2026-03-03 21:17:43 +01:00
w33b 4a45dae593 Update Readme 2026-03-01 16:07:09 +01:00
w33b 2b0448d517 Add Disclaimer and Guide for Matrix 2026-03-01 16:06:58 +01:00
w33b 3bb6af73c3 Add matrix 2026-02-18 12:34:10 +01:00
w33b 57cf153560 Update Livewire to fix CorruptComponentPayloadException 2026-02-15 14:52:16 +01:00
w33b e45fd4b148 Update axios 2026-02-15 13:02:08 +01:00
w33b d479369770 Merge branch 'laravel-12' 2026-01-18 18:54:25 +01:00
w33b b8ba17b33f Fix patreon role check (again again) 2026-01-16 15:18:29 +00:00
w33b 5a8dd12cb8 Fix patreon role check (again)
Life without typecast is hard
2026-01-16 15:11:28 +00:00
w33b 3a77c4320d Fix patreon role check
We compare the roles using a strict type check, the json contents from the discord api are strings and not integers.
2026-01-16 14:42:39 +00:00
157 changed files with 1390 additions and 1055 deletions
+7 -7
View File
@@ -2,13 +2,13 @@
## hstream Website
### Install
### Install (Ubuntu)
```bash
# Install PHP
sudo add-apt-repository ppa:ondrej/php
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
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)
apt install nginx
apt install php8.3-fpm
apt install php8.4-fpm
# Install MariaDB
apt install mariadb-server
@@ -54,7 +54,7 @@ nano /etc/supervisor/conf.d/laravel-queue.conf :
[program:laravel-queue]
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
autorestart=true
stopasgroup=true
@@ -83,9 +83,9 @@ zip -r hstream_2023_11_30.zip hstream/
### Update
```bash
php artisan down
php84 artisan down
git pull
npm run build
php artisan view:clear && php artisan optimize:clear && php artisan cache:clear && service php8.4-fpm restart
php artisan up
php84 artisan view:clear && php84 artisan optimize:clear && php84 artisan cache:clear && service php8.4-fpm restart
php84 artisan up
```
+2 -3
View File
@@ -3,11 +3,10 @@
namespace App\Console\Commands;
use App\Models\PopularDaily;
use App\Models\PopularWeekly;
use App\Models\PopularMonthly;
use Illuminate\Support\Carbon;
use App\Models\PopularWeekly;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
class AutoStats extends Command
{
-1
View File
@@ -4,7 +4,6 @@ namespace App\Console\Commands;
use App\Models\Episode;
use App\Models\Hentai;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Spatie\Sitemap\Sitemap;
+1 -2
View File
@@ -2,9 +2,8 @@
namespace App\Console\Commands;
use App\Models\Downloads;
use App\Jobs\GetFileSizeFromCDN;
use App\Models\Downloads;
use Illuminate\Console\Command;
class GetFileSize extends Command
+1 -2
View File
@@ -4,9 +4,8 @@ namespace App\Console\Commands;
use App\Models\User;
use App\Models\UserDownload;
use Illuminate\Support\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
class ResetUserDownloads extends Command
{
+17 -16
View File
@@ -5,21 +5,20 @@ namespace App\Helpers;
use App\Models\Comment;
use App\Models\Episode;
use App\Models\Hentai;
use App\Models\PopularDaily;
use App\Models\PopularMonthly;
use App\Models\PopularWeekly;
use App\Models\PopularDaily;
use Conner\Tagging\Model\Tag;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class CacheHelper
{
public static function getRecentlyReleased(bool $guest)
{
$guestString = $guest ? 'guest' : 'authed';
return Cache::remember("recently_released_".$guestString, now()->addMinutes(60), function () use ($guest) {
return Cache::remember('recently_released_'.$guestString, now()->addMinutes(60), function () use ($guest) {
return Episode::with('gallery')
->when($guest, fn ($query) => $query->withoutTags(['loli', 'shota']))
->orderBy('release_date', 'desc')
@@ -31,7 +30,8 @@ class CacheHelper
public static function getRecentlyUploaded(bool $guest)
{
$guestString = $guest ? 'guest' : 'authed';
return Cache::remember("recently_uploaded".$guestString, now()->addMinutes(5), function () use ($guest) {
return Cache::remember('recently_uploaded'.$guestString, now()->addMinutes(5), function () use ($guest) {
return Episode::with('gallery')
->when($guest, fn ($query) => $query->withoutTags(['loli', 'shota']))
->orderBy('created_at', 'desc')
@@ -42,21 +42,21 @@ class CacheHelper
public static function getTotalViewCount()
{
return Cache::remember("total_view_count", now()->addMinutes(60), function () {
return Cache::remember('total_view_count', now()->addMinutes(60), function () {
return Episode::sum('view_count');
});
}
public static function getTotalEpisodeCount()
{
return Cache::remember("total_episode_count", now()->addMinutes(60), function () {
return Cache::remember('total_episode_count', now()->addMinutes(60), function () {
return Episode::count();
});
}
public static function getTotalHentaiCount()
{
return Cache::remember("total_hentai_count", now()->addMinutes(60), function () {
return Cache::remember('total_hentai_count', now()->addMinutes(60), function () {
return Hentai::count();
});
}
@@ -64,7 +64,8 @@ class CacheHelper
public static function getPopularAllTime(bool $guest)
{
$guestString = $guest ? 'guest' : 'authed';
return Cache::remember("top_hentai_alltime".$guestString, now()->addMinutes(360), function () use ($guest) {
return Cache::remember('top_hentai_alltime'.$guestString, now()->addMinutes(360), function () use ($guest) {
return Episode::with('gallery')
->when($guest, fn ($query) => $query->withoutTags(['loli', 'shota']))
->orderBy('view_count', 'desc')
@@ -75,7 +76,7 @@ class CacheHelper
public static function getPopularMonthly()
{
return Cache::remember("top_hentai_monthly", now()->addMinutes(360), function () {
return Cache::remember('top_hentai_monthly', now()->addMinutes(360), function () {
return PopularMonthly::groupBy('episode_id')
->select('episode_id', DB::raw('count(*) as total'))
->with('episode.gallery')
@@ -87,7 +88,7 @@ class CacheHelper
public static function getPopularWeekly()
{
return Cache::remember("top_hentai_weekly", now()->addMinutes(360), function () {
return Cache::remember('top_hentai_weekly', now()->addMinutes(360), function () {
return PopularWeekly::groupBy('episode_id')
->select('episode_id', DB::raw('count(*) as total'))
->with('episode.gallery')
@@ -100,7 +101,7 @@ class CacheHelper
public static function getPopularDaily()
{
return Cache::remember("top_hentai_daily", now()->addMinutes(30), function () {
return Cache::remember('top_hentai_daily', now()->addMinutes(30), function () {
return PopularDaily::groupBy('episode_id')
->select('episode_id', DB::raw('count(*) as total'))
->with('episode.gallery')
@@ -112,21 +113,21 @@ class CacheHelper
public static function getMostLikes()
{
return Cache::remember("top_likes", now()->addMinutes(30), function () {
return Cache::remember('top_likes', now()->addMinutes(30), function () {
return DB::table('markable_likes')->groupBy('markable_id')->select('markable_id', DB::raw('count(*) as total'))->orderBy('total', 'desc')->limit(16)->get();
});
}
public static function getAllTags()
{
return Cache::remember("all_tags", now()->addMinutes(10080), function () {
return Cache::remember('all_tags', now()->addMinutes(10080), function () {
return Tag::where('count', '>', 0)->orderBy('slug', 'ASC')->get();
});
}
public static function getLatestComments()
{
return Cache::remember("latest_comments", now()->addMinutes(60), function () {
return Cache::remember('latest_comments', now()->addMinutes(60), function () {
return Comment::latest()->take(10)->get();
});
}
+1 -1
View File
@@ -8,7 +8,7 @@ class GitHelper
{
public static function shortCommit()
{
return Cache::remember("git_commit", now()->addMinutes(60), function () {
return Cache::remember('git_commit', now()->addMinutes(60), function () {
try {
return trim(exec('git rev-parse --short HEAD'));
} catch (\Exception $e) {
@@ -15,7 +15,7 @@ class ContactController extends Controller
$contacts = Contact::orderBy('created_at', 'DESC')->get();
return view('admin.contact.index', [
'contacts' => $contacts
'contacts' => $contacts,
]);
}
@@ -3,9 +3,8 @@
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Episode;
use App\Jobs\DiscordReleaseNotification;
use App\Models\Episode;
use App\Services\DownloadService;
use App\Services\EpisodeService;
use App\Services\GalleryService;
@@ -14,7 +13,9 @@ use Illuminate\Http\Request;
class EpisodeController extends Controller
{
protected EpisodeService $episodeService;
protected GalleryService $galleryService;
protected DownloadService $downloadService;
public function __construct(
@@ -43,7 +44,7 @@ class EpisodeController extends Controller
// Discord Alert
if ($request->has('censored')) {
DiscordReleaseNotification::dispatch($referenceEpisode->title." - ".$episodeNumber, 'release-censored');
DiscordReleaseNotification::dispatch($referenceEpisode->title.' - '.$episodeNumber, 'release-censored');
} else {
DiscordReleaseNotification::dispatch($episode->slug, 'release');
}
@@ -51,7 +52,7 @@ class EpisodeController extends Controller
cache()->flush();
return to_route('hentai.index', [
'title' => $episode->slug
'title' => $episode->slug,
]);
}
@@ -87,7 +88,7 @@ class EpisodeController extends Controller
cache()->flush();
return to_route('hentai.index', [
'title' => $episode->slug
'title' => $episode->slug,
]);
}
}
@@ -3,9 +3,8 @@
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Hentai;
use App\Jobs\DiscordReleaseNotification;
use App\Models\Hentai;
use App\Services\DownloadService;
use App\Services\EpisodeService;
use App\Services\GalleryService;
@@ -14,7 +13,9 @@ use Illuminate\Http\Request;
class ReleaseController extends Controller
{
protected EpisodeService $episodeService;
protected GalleryService $galleryService;
protected DownloadService $downloadService;
public function __construct(
@@ -3,15 +3,13 @@
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\SiteBackground;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Intervention\Image\Laravel\Facades\Image;
use Intervention\Image\Encoders\WebpEncoder;
use Intervention\Image\Laravel\Facades\Image;
class SiteBackgroundController extends Controller
{
@@ -44,7 +42,7 @@ class SiteBackgroundController extends Controller
$bg = SiteBackground::create(array_merge(
$request->only(['date_start', 'date_end']),
[
'default' => (bool) $request->input('default', false)
'default' => (bool) $request->input('default', false),
]
));
@@ -55,13 +53,14 @@ class SiteBackgroundController extends Controller
Image::read($file->getRealPath())
->scaleDown(height: $resolution)
->encode(new WebpEncoder())
->encode(new WebpEncoder)
->save(public_path($targetPath));
}
} catch (\Exception $e) {
DB::rollBack();
Log::error($e->getMessage());
return redirect()->back();
}
@@ -85,7 +84,7 @@ class SiteBackgroundController extends Controller
SiteBackground::where('id', $request->input('id'))->update(array_merge(
$request->only(['date_start', 'date_end']),
[
'default' => (bool) $request->input('default', false)
'default' => (bool) $request->input('default', false),
]
));
@@ -116,6 +115,7 @@ class SiteBackgroundController extends Controller
} catch (\Exception $e) {
DB::rollBack();
Log::error($e->getMessage());
return redirect()->back();
}
@@ -2,10 +2,10 @@
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Episode;
use App\Models\EpisodeSubtitle;
use App\Models\Subtitle;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class SubtitleController extends Controller
@@ -3,8 +3,8 @@
namespace App\Http\Controllers\Admin;
use App\Enums\UserRole;
use App\Models\User;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
class UserController extends Controller
@@ -27,7 +27,6 @@ class UserController extends Controller
'action' => 'required',
]);
$user = User::findOrFail($validated['id']);
switch ($validated['action']) {
@@ -3,10 +3,10 @@
namespace App\Http\Controllers\Api;
use App\Helpers\CacheHelper;
use App\Http\Controllers\Controller;
use App\Models\Episode;
use App\Models\Studios;
use App\Models\Subtitle;
use App\Http\Controllers\Controller;
class AdminApiController extends Controller
{
@@ -2,13 +2,11 @@
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Downloads;
use App\Models\Episode;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use GrantHolle\Altcha\Rules\ValidAltcha;
use Illuminate\Http\Request;
class DownloadApiController extends Controller
{
@@ -2,12 +2,11 @@
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Hentai;
use App\Models\PopularMonthly;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use App\Http\Controllers\Controller;
class HentaiApiController extends Controller
{
@@ -3,9 +3,7 @@
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Episode;
use Illuminate\Http\Request;
class StreamApiController extends Controller
@@ -33,7 +31,7 @@ class StreamApiController extends Controller
'stream_url' => $episode->dmca_takedown ? 'stuff/dmca' : $episode->url,
'stream_domains' => config('hstream.stream_domain'),
'asia_stream_domains' => config('hstream.asia_stream_domain'),
'extra_subtitles' => $subtitles
'extra_subtitles' => $subtitles,
], 200);
}
}
@@ -4,9 +4,8 @@ namespace App\Http\Controllers\Api;
use App\Helpers\CacheHelper;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Conner\Tagging\Model\Tag;
use Illuminate\Http\Request;
class UserApiController extends Controller
{
@@ -33,11 +32,10 @@ class UserApiController extends Controller
}
}
return response()->json([
'message' => 'success',
'tags' => $tagWhiteList,
'usertags' => $tagBlackList
'usertags' => $tagBlackList,
], 200);
}
}
@@ -3,11 +3,9 @@
namespace App\Http\Controllers\Auth;
use App\Enums\UserRole;
use App\Models\User;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
@@ -90,6 +88,7 @@ class DiscordAuthController extends Controller
// User is not in the guild
if ($response->status() === 404) {
$user->removeRole(UserRole::SUPPORTER);
return;
}
@@ -114,6 +113,7 @@ class DiscordAuthController extends Controller
if (! $hasSupporterRole) {
// Remove role if not found
$user->removeRole(UserRole::SUPPORTER);
return;
}
@@ -16,8 +16,7 @@ class PasswordController extends Controller
public function update(Request $request): RedirectResponse
{
// If user logged in with Discord and has not yet a password, allow to set password
if ($request->user()->discord_id && is_null($request->user()->password))
{
if ($request->user()->discord_id && is_null($request->user()->password)) {
$validated = $request->validateWithBag('updatePassword', [
'password' => ['required', Password::defaults(), 'confirmed'],
]);
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use GrantHolle\Altcha\Rules\ValidAltcha;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
@@ -11,8 +12,6 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules;
use GrantHolle\Altcha\Rules\ValidAltcha;
class RegisteredUserController extends Controller
{
/**
+2 -3
View File
@@ -3,9 +3,8 @@
namespace App\Http\Controllers;
use App\Models\Contact;
use Illuminate\Http\Request;
use GrantHolle\Altcha\Rules\ValidAltcha;
use Illuminate\Http\Request;
class ContactController extends Controller
{
@@ -30,7 +29,7 @@ class ContactController extends Controller
'altcha' => ['required', new ValidAltcha],
]);
$contact = new Contact();
$contact = new Contact;
$contact->name = $request->input('name');
$contact->email = $request->input('email');
$contact->message = $request->input('message');
+3 -5
View File
@@ -2,11 +2,10 @@
namespace App\Http\Controllers;
use App\Models\Episode;
use App\Helpers\CacheHelper;
use App\Models\Episode;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cookie;
class HomeController extends Controller
{
@@ -19,15 +18,14 @@ class HomeController extends Controller
$guestString = $guest ? 'guest' : 'authed';
$mostLikes = \cache()->remember('mostLikes'.$guestString, 300, fn () =>
Episode::with('gallery')
$mostLikes = \cache()->remember('mostLikes'.$guestString, 300, fn () => Episode::with('gallery')
->when($guest, fn ($query) => $query->withoutTags(['loli', 'shota']))
->whereIn('id', function ($query) {
$mostLikesIds = CacheHelper::getMostLikes()->pluck('markable_id')->toArray();
$query->selectRaw('id')
->from('episodes')
->whereIn('id', $mostLikesIds)
->orderByRaw("FIELD(id, " . implode(',', $mostLikesIds) . ")");
->orderByRaw('FIELD(id, '.implode(',', $mostLikesIds).')');
})
->get()
);
+57
View 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();
}
}
}
@@ -3,7 +3,6 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class NotificationController extends Controller
{
+7 -9
View File
@@ -7,7 +7,6 @@ use App\Models\Playlist;
use App\Models\PlaylistEpisode;
use App\Services\PlaylistService;
use Illuminate\Http\Request;
use RealRashid\SweetAlert\Facades\Alert;
class PlaylistController extends Controller
{
@@ -42,14 +41,13 @@ class PlaylistController extends Controller
]);
}
/**
* Display the user's playlists page.
*/
public function playlists(Request $request): \Illuminate\View\View
{
$title = 'Delete Playlist!';
$text = "Are you sure you want to delete?";
$text = 'Are you sure you want to delete?';
confirmDelete($title, $text);
return view('profile.playlists', [
@@ -85,7 +83,7 @@ class PlaylistController extends Controller
'name' => 'required|max:30',
]);
$playlist = new Playlist();
$playlist = new Playlist;
$playlist->user_id = $request->user()->id;
$playlist->name = $request->input('name');
$playlist->is_private = $request->input('visiblity') === 'private';
@@ -151,7 +149,7 @@ class PlaylistController extends Controller
$validated = $request->validate([
'playlist' => 'required|max:30',
'episode_id' => 'required'
'episode_id' => 'required',
]);
$playlist = Playlist::where('user_id', $user->id)->where('id', $request->input('playlist'))->firstOrFail();
@@ -161,7 +159,7 @@ class PlaylistController extends Controller
$exists = PlaylistEpisode::where('playlist_id', $playlist->id)->where('episode_id', $episode->id)->exists();
if ($exists) {
return response()->json([
'message' => 'already-added'
'message' => 'already-added',
], 200);
}
@@ -175,7 +173,7 @@ class PlaylistController extends Controller
]);
return response()->json([
'message' => 'success'
'message' => 'success',
], 200);
}
@@ -188,7 +186,7 @@ class PlaylistController extends Controller
'name' => 'required|max:30',
]);
$playlist = new Playlist();
$playlist = new Playlist;
$playlist->user_id = $request->user()->id;
$playlist->name = $request->input('name');
$playlist->is_private = $request->input('visiblity') === 'private';
@@ -196,7 +194,7 @@ class PlaylistController extends Controller
return response()->json([
'message' => 'success',
'playlist_id' => $playlist->id
'playlist_id' => $playlist->id,
], 200);
}
}
+6 -8
View File
@@ -2,22 +2,20 @@
namespace App\Http\Controllers;
use App\Http\Requests\ProfileUpdateRequest;
use App\Models\Episode;
use App\Models\User;
use App\Http\Requests\ProfileUpdateRequest;
use Conner\Tagging\Model\Tag;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\View\View;
use Intervention\Image\Laravel\Facades\Image;
use Conner\Tagging\Model\Tag;
class ProfileController extends Controller
{
/**
@@ -121,6 +119,7 @@ class ProfileController extends Controller
if (! $tags) {
$user->tag_blacklist = null;
$user->save();
return Redirect::route('profile.settings')->with('status', 'blacklist-updated');
}
@@ -177,8 +176,8 @@ class ProfileController extends Controller
protected function storeAvatar(\Illuminate\Http\UploadedFile $file, User $user): void
{
// Create Folder for Image Upload
if (! Storage::disk('public')->exists("/images/avatars")) {
Storage::disk('public')->makeDirectory("/images/avatars");
if (! Storage::disk('public')->exists('/images/avatars')) {
Storage::disk('public')->makeDirectory('/images/avatars');
}
// Delete old avatar if it exists
@@ -196,5 +195,4 @@ class ProfileController extends Controller
$user->avatar = $filename;
}
}
+2 -5
View File
@@ -2,20 +2,18 @@
namespace App\Http\Controllers;
use App\Helpers\CacheHelper;
use App\Models\Episode;
use App\Models\Gallery;
use App\Models\Hentai;
use App\Models\Playlist;
use App\Models\PlaylistEpisode;
use App\Models\Watched;
use App\Helpers\CacheHelper;
use hisorange\BrowserDetect\Facade as Browser;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use hisorange\BrowserDetect\Facade as Browser;
class StreamController extends Controller
{
/**
@@ -37,7 +35,6 @@ class StreamController extends Controller
]);
}
$episode = Episode::where('slug', $title)->firstOrFail();
$gallery = Gallery::where('episode_id', $episode->id)->get();
$moreEpisodes = Episode::with(['gallery', 'studio'])->where('hentai_id', $episode->hentai_id)->whereNot('id', $episode->id)->get();
+7 -8
View File
@@ -1,29 +1,28 @@
<?php namespace app\Http\Middleware;
<?php
namespace app\Http\Middleware;
use App\Enums\UserRole;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class IsAdmin {
class IsAdmin
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next): Response
{
if(Auth::check() && Auth::user()->hasRole(UserRole::ADMINISTRATOR))
{
if (Auth::check() && Auth::user()->hasRole(UserRole::ADMINISTRATOR)) {
return $next($request);
}
session()->flash('error_msg', 'This resource is restricted to Administrators!');
return redirect()->route('home.index');
}
}
+7 -9
View File
@@ -1,32 +1,30 @@
<?php namespace app\Http\Middleware;
<?php
namespace app\Http\Middleware;
use App\Enums\UserRole;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class IsBanned {
class IsBanned
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next): Response
{
if(Auth::check() && Auth::user()->hasRole(UserRole::BANNED))
{
if (Auth::check() && Auth::user()->hasRole(UserRole::BANNED)) {
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect()->route('home.banned');
}
return $next($request);
}
}
+2 -3
View File
@@ -3,7 +3,6 @@
namespace App\Http\Middleware;
use App\Enums\UserRole;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@@ -18,12 +17,12 @@ class IsModerator
*/
public function handle(Request $request, Closure $next): Response
{
if (Auth::check() && Auth::user()->hasRole(UserRole::MODERATOR))
{
if (Auth::check() && Auth::user()->hasRole(UserRole::MODERATOR)) {
return $next($request);
}
session()->flash('error_msg', 'This resource is restricted to Administrators!');
return redirect()->route('home.index');
}
}
+2
View File
@@ -20,12 +20,14 @@ class SetLocale
// 1. Logged-in user preference
if (Auth::check() && Auth::user()->locale) {
App::setLocale(Auth::user()->locale);
return $next($request);
}
// 2. Session (guest or user override)
if (session()->has('locale') && in_array($request->language, config('app.supported_locales'), true)) {
App::setLocale(session('locale'));
return $next($request);
}
+1 -2
View File
@@ -2,6 +2,7 @@
namespace App\Http\Requests\Auth;
use GrantHolle\Altcha\Rules\ValidAltcha;
use Illuminate\Auth\Events\Lockout;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
@@ -9,8 +10,6 @@ use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use GrantHolle\Altcha\Rules\ValidAltcha;
class LoginRequest extends FormRequest
{
/**
@@ -0,0 +1,50 @@
<?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 . _ = -',
];
}
}
+1 -1
View File
@@ -21,7 +21,7 @@ class ProfileUpdateRequest extends FormRequest
'nullable',
'image',
'mimes:jpg,png,jpeg,webp,gif',
'max:8192'
'max:8192',
],
'email' => [
'required',
+10 -12
View File
@@ -7,7 +7,6 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Spatie\DiscordAlerts\Facades\DiscordAlert;
class DiscordReleaseNotification implements ShouldQueue
@@ -32,26 +31,25 @@ class DiscordReleaseNotification implements ShouldQueue
*/
public function handle(): void
{
switch($this->messageType)
{
switch ($this->messageType) {
case 'release':
DiscordAlert::message("<@&868457842250764289> (´• ω •`)ノ New **4k** Release! Check it out here: https://hstream.moe/hentai/".$this->slug);
DiscordAlert::message('<@&868457842250764289> (´• ω •`)ノ New **4k** Release! Check it out here: https://hstream.moe/hentai/'.$this->slug);
break;
case 'release-censored':
# Because Discord TOS
DiscordAlert::message("<@&868457842250764289> (´• ω •`)ノ New **4k** Release: ".$this->slug." - *No link here because of* :pLoli:");
// Because Discord TOS
DiscordAlert::message('<@&868457842250764289> (´• ω •`)ノ New **4k** Release: '.$this->slug.' - *No link here because of* :pLoli:');
break;
case 'update':
# 1080p 48fps added
DiscordAlert::to('update')->message("<@&1283518462584426598> (´• ω •`)ノ Added **48fps** to Release! Check it out here: https://hstream.moe/hentai/".$this->slug);
// 1080p 48fps added
DiscordAlert::to('update')->message('<@&1283518462584426598> (´• ω •`)ノ Added **48fps** to Release! Check it out here: https://hstream.moe/hentai/'.$this->slug);
break;
case 'updateUHD':
# 4k 48fps added
DiscordAlert::to('update')->message("<@&1326860920902778963> (´• ω •`)ノ Added **48fps 4k** to Release! Check it out here: https://hstream.moe/hentai/".$this->slug);
// 4k 48fps added
DiscordAlert::to('update')->message('<@&1326860920902778963> (´• ω •`)ノ Added **48fps 4k** to Release! Check it out here: https://hstream.moe/hentai/'.$this->slug);
break;
case 'v2':
# v2 re-release
DiscordAlert::to('rerelease')->message("<@&1425505303075754035> (´• ω •`)ノ **v2 Re-**Release! Check it out here: https://hstream.moe/hentai/".$this->slug);
// v2 re-release
DiscordAlert::to('rerelease')->message('<@&1425505303075754035> (´• ω •`)ノ **v2 Re-**Release! Check it out here: https://hstream.moe/hentai/'.$this->slug);
break;
default:
break;
+3 -2
View File
@@ -7,12 +7,12 @@ use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Http\Client\RequestException;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class GetFileSizeFromCDN implements ShouldQueue
{
@@ -37,6 +37,7 @@ class GetFileSizeFromCDN implements ShouldQueue
$download = Downloads::find($this->downloadId);
if (! $download) {
Log::error("Download not found for ID: {$this->downloadId}");
return;
}
+1 -2
View File
@@ -5,7 +5,6 @@ namespace App\Livewire;
use App\Models\Comment;
use Livewire\Component;
use Livewire\WithPagination;
use Illuminate\Support\Facades\DB;
class AdminCommentSearch extends Component
{
@@ -41,7 +40,7 @@ class AdminCommentSearch extends Component
->paginate(12);
return view('livewire.admin-comment-search', [
'comments' => $comments
'comments' => $comments,
]);
}
}
+2 -3
View File
@@ -5,10 +5,9 @@ namespace App\Livewire;
use App\Enums\UserRole;
use App\Models\Comment;
use App\Models\User;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
class AdminUserSearch extends Component
{
@@ -46,7 +45,7 @@ class AdminUserSearch extends Component
->paginate(20);
return view('livewire.admin-user-search', [
'users' => $users
'users' => $users,
]);
}
}
+6 -9
View File
@@ -2,12 +2,11 @@
namespace App\Livewire;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
use App\Models\SiteBackground;
use Illuminate\Support\Carbon;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
class BackgroundImages extends Component
{
@@ -20,16 +19,14 @@ class BackgroundImages extends Component
{
$now = Carbon::now();
$images = SiteBackground::when($this->filter === 'active', fn ($query) =>
$query->whereDate('date_start', '<=', $now)->whereDate('date_end', '>=', $now)
$images = SiteBackground::when($this->filter === 'active', fn ($query) => $query->whereDate('date_start', '<=', $now)->whereDate('date_end', '>=', $now)
)
->when($this->filter === 'inactive', fn ($query) =>
$query->whereDate('date_start', '>', $now)->orWhereDate('date_end', '<', $now)
->when($this->filter === 'inactive', fn ($query) => $query->whereDate('date_start', '>', $now)->orWhereDate('date_end', '<', $now)
)
->paginate(10);
return view('livewire.background-images', [
'images' => $images
'images' => $images,
]);
}
}
+15 -16
View File
@@ -1,20 +1,16 @@
<?php
namespace App\Livewire;
use App\Models\User;
use App\Models\Episode;
use App\Models\User;
use App\Notifications\CommentNotification;
use Livewire\Component;
use Illuminate\Support\Str;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Str;
use Livewire\Component;
use Maize\Markable\Models\Like;
class Comment extends Component
@@ -30,21 +26,21 @@ class Comment extends Component
public $liked = false;
public $replyState = [
'body' => ''
'body' => '',
];
public $isEditing = false;
public $editState = [
'body' => ''
'body' => '',
];
protected $listeners = [
'refresh' => '$refresh'
'refresh' => '$refresh',
];
protected $validationAttributes = [
'replyState.body' => 'reply'
'replyState.body' => 'reply',
];
public function updatedIsEditing($isEditing)
@@ -54,7 +50,7 @@ class Comment extends Component
}
$this->editState = [
'body' => $this->comment->body
'body' => $this->comment->body,
];
}
@@ -79,7 +75,8 @@ class Comment extends Component
public function postReply()
{
if (! ($this->comment->depth() < 2)) {
$this->addError('replyState.body', "Too many sub comments.");
$this->addError('replyState.body', 'Too many sub comments.');
return;
}
@@ -91,13 +88,14 @@ class Comment extends Component
$seconds = RateLimiter::availableIn($rateLimitKey);
$this->addError('replyState.body', "Too many comments. Try again in {$seconds} seconds.");
return;
}
RateLimiter::hit($rateLimitKey, $rateLimitMinutes);
$this->validate([
'replyState.body' => 'required'
'replyState.body' => 'required',
]);
$reply = $this->comment->children()->make($this->replyState);
@@ -123,7 +121,7 @@ class Comment extends Component
}
$this->replyState = [
'body' => ''
'body' => '',
];
$this->isReplying = false;
@@ -144,6 +142,7 @@ class Comment extends Component
if ($this->liked) {
$this->liked = false;
$this->likeCount--;
return;
}
+8 -8
View File
@@ -2,11 +2,10 @@
namespace App\Livewire;
use Illuminate\Support\Facades\RateLimiter;
use Livewire\Component;
use Livewire\WithPagination;
use Illuminate\Support\Facades\RateLimiter;
class Comments extends Component
{
use WithPagination;
@@ -14,21 +13,21 @@ class Comments extends Component
public $model;
public $newCommentState = [
'body' => ''
'body' => '',
];
protected $validationAttributes = [
'newCommentState.body' => 'comment'
'newCommentState.body' => 'comment',
];
protected $listeners = [
'refresh' => '$refresh'
'refresh' => '$refresh',
];
public function postComment()
{
$this->validate([
'newCommentState.body' => 'required'
'newCommentState.body' => 'required',
]);
$user = auth()->user();
@@ -39,6 +38,7 @@ class Comments extends Component
$seconds = RateLimiter::availableIn($rateLimitKey);
$this->addError('newCommentState.body', "Too many comments. Try again in {$seconds} seconds.");
return;
}
@@ -49,7 +49,7 @@ class Comments extends Component
$comment->save();
$this->newCommentState = [
'body' => ''
'body' => '',
];
$this->resetPage();
@@ -65,7 +65,7 @@ class Comments extends Component
->paginate(50);
return view('livewire.comments', [
'comments' => $comments
'comments' => $comments,
]);
}
}
+9
View File
@@ -21,6 +21,15 @@ class DownloadButton extends Component
public $background = 'bg-rose-600';
public $fileExtension = 'HEVC';
public function mount()
{
if (str_contains($this->downloadUrl, 'AV1')) {
$this->fileExtension = 'AV1';
}
}
public function clicked($downloadId)
{
$download = Downloads::find($downloadId);
+3 -3
View File
@@ -5,11 +5,9 @@ namespace App\Livewire;
use App\Models\Episode;
use App\Models\User;
use App\Models\UserDownload;
use Livewire\Component;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
class DownloadsFree extends Component
{
@@ -51,6 +49,7 @@ class DownloadsFree extends Component
if (Carbon::parse($alreadyDownloaded->created_at)->addHours(6) <= Carbon::now()) {
// Already expired
$alreadyDownloaded->delete();
return;
}
@@ -65,6 +64,7 @@ class DownloadsFree extends Component
if ($user->downloads_left <= 0) {
// Daily limit reached
$this->granted = 3;
return;
}
+5 -2
View File
@@ -3,9 +3,9 @@
namespace App\Livewire;
use App\Models\Downloads;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
class DownloadsSearch extends Component
{
@@ -25,6 +25,7 @@ class DownloadsSearch extends Component
#[Url(history: true)]
public $studios = [];
public $studiosCopy = [];
// To toggle individual option selection
@@ -144,7 +145,9 @@ class DownloadsSearch extends Component
$downloads = Downloads::when($this->fileSearch != '', fn ($query) => $query->where('url', 'like', '%'.$this->fileSearch.'%'))
->whereIn('type', $this->getSelectedTypes())
->when($this->studios !== [], fn ($q) => $q->whereHas('episode', fn ($query) => $query->whereHas('studio', function ($query) { $query->whereIn('slug', $this->studios); })))
->when($this->studios !== [], fn ($q) => $q->whereHas('episode', fn ($query) => $query->whereHas('studio', function ($query) {
$query->whereIn('slug', $this->studios);
})))
->whereNotNull('size')
->orderBy($orderby, $orderdirection)
->paginate(20);
+2 -2
View File
@@ -4,10 +4,9 @@ namespace App\Livewire;
use App\Models\Episode;
use App\Models\User;
use Livewire\Component;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Livewire\Component;
use Maize\Markable\Models\Like;
class LikeButton extends Component
@@ -52,6 +51,7 @@ class LikeButton extends Component
if ($this->liked) {
$this->liked = false;
$this->likeCount--;
return;
}
+11 -4
View File
@@ -3,10 +3,10 @@
namespace App\Livewire;
use App\Models\Episode;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
use Illuminate\Support\Facades\Auth;
class LiveSearch extends Component
{
@@ -20,14 +20,17 @@ class LiveSearch extends Component
#[Url(history: true)]
public $tags = [];
public $tagsCopy = [];
#[Url(history: true)]
public $studios = [];
public $studiosCopy = [];
#[Url(history: true)]
public $blacklist = [];
public $blacklistCopy = [];
#[Url(history: true)]
@@ -118,10 +121,14 @@ class LiveSearch extends Component
}
$user_id = Auth::check() ? auth()->user()->id : 0;
$episodes = Episode::with('gallery')->when($this->search != '', fn ($query) => $query->where(function($query) { $query->where('title', 'like', '%'.$this->search.'%')->orWhere('title_search', 'like', '%'.$this->search.'%')->orWhere('title_jpn', 'like', '%'.$this->search.'%'); }))
$episodes = Episode::with('gallery')->when($this->search != '', fn ($query) => $query->where(function ($query) {
$query->where('title', 'like', '%'.$this->search.'%')->orWhere('title_search', 'like', '%'.$this->search.'%')->orWhere('title_jpn', 'like', '%'.$this->search.'%');
}))
->when($this->tags !== [], fn ($query) => $query->withAllTags($this->tags))
->when($this->blacklist !== [], fn ($query) => $query->withoutTags($this->blacklist))
->when($this->studios !== [], fn ($query) => $query->whereHas('studio', function ($query) { $query->whereIn('slug', $this->studios); }))
->when($this->studios !== [], fn ($query) => $query->whereHas('studio', function ($query) {
$query->whereIn('slug', $this->studios);
}))
->when($this->hideWatched !== [] && Auth::check(), fn ($query) => $query->whereDoesntHave('watched', function ($query) use ($user_id) {
$query->where('user_id', $user_id);
}))
+1 -1
View File
@@ -3,8 +3,8 @@
namespace App\Livewire;
use App\Models\Episode;
use Livewire\Component;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
class NavLiveSearch extends Component
{
+3 -5
View File
@@ -5,13 +5,11 @@ namespace App\Livewire;
use App\Models\Playlist;
use App\Models\PlaylistEpisode;
use App\Services\PlaylistService;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\Collection;
class PlaylistOverview extends Component
{
+2 -3
View File
@@ -3,10 +3,9 @@
namespace App\Livewire;
use App\Models\Playlist;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
class Playlists extends Component
{
@@ -59,7 +58,7 @@ class Playlists extends Component
->paginate($this->pagination);
return view('livewire.playlists', [
'playlists' => $playlists
'playlists' => $playlists,
]);
}
}
+2 -4
View File
@@ -3,7 +3,6 @@
namespace App\Livewire;
use App\Models\Comment;
use Livewire\Component;
use Livewire\WithPagination;
@@ -36,14 +35,13 @@ class UserComments extends Component
$orderdirection = 'desc';
}
$comments = Comment::where('user_id', $this->model->id)
->when($this->commentSearch != '', fn ($query) => $query->where('body', 'like', '%'.$this->commentSearch.'%'))
->orderBy($orderby, $orderdirection)
->paginate(10);
->paginate(6);
return view('livewire.user-comments', [
'comments' => $comments
'comments' => $comments,
]);
}
}
+11 -4
View File
@@ -3,10 +3,10 @@
namespace App\Livewire;
use App\Models\Episode;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
use Illuminate\Support\Facades\Auth;
class UserLikes extends Component
{
@@ -20,14 +20,17 @@ class UserLikes extends Component
#[Url(history: true)]
public $tags = [];
public $tagsCopy = [];
#[Url(history: true)]
public $studios = [];
public $studiosCopy = [];
#[Url(history: true)]
public $blacklist = [];
public $blacklistCopy = [];
#[Url(history: true)]
@@ -119,10 +122,14 @@ class UserLikes extends Component
$user_id = Auth::check() ? auth()->user()->id : 0;
$episodes = Episode::whereHasLike(auth()->user())
->when($this->search !== '', fn ($query) => $query->where(function($query) { $query->where('title', 'like', '%'.$this->search.'%')->orWhere('title_search', 'like', '%'.$this->search.'%')->orWhere('title_jpn', 'like', '%'.$this->search.'%'); }))
->when($this->search !== '', fn ($query) => $query->where(function ($query) {
$query->where('title', 'like', '%'.$this->search.'%')->orWhere('title_search', 'like', '%'.$this->search.'%')->orWhere('title_jpn', 'like', '%'.$this->search.'%');
}))
->when($this->tags !== [], fn ($query) => $query->withAllTags($this->tags))
->when($this->blacklist !== [], fn ($query) => $query->withoutTags($this->blacklist))
->when($this->studios !== [], fn ($query) => $query->whereHas('studio', function ($query) { $query->whereIn('slug', $this->studios); }))
->when($this->studios !== [], fn ($query) => $query->whereHas('studio', function ($query) {
$query->whereIn('slug', $this->studios);
}))
->when($this->hideWatched !== [] && Auth::check(), fn ($query) => $query->whereDoesntHave('watched', function ($query) use ($user_id) {
$query->where('user_id', $user_id);
}))
-1
View File
@@ -3,7 +3,6 @@
namespace App\Livewire;
use App\Models\Watched as UserWatched;
use App\Models\User;
use Illuminate\Support\Carbon;
use Livewire\Component;
use Livewire\WithPagination;
+5 -6
View File
@@ -4,19 +4,18 @@ namespace App\Models;
use App\Models\Presenters\CommentPresenter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Maize\Markable\Markable;
use Maize\Markable\Models\Like;
class Comment extends Model
{
use HasFactory, SoftDeletes, Markable;
use HasFactory, Markable, SoftDeletes;
protected static $marks = [
Like::class
Like::class,
];
/**
@@ -25,7 +24,7 @@ class Comment extends Model
* @var string[]
*/
protected $fillable = [
'body'
'body',
];
public function presenter()
+13 -18
View File
@@ -2,35 +2,28 @@
namespace App\Models;
use App\Models\Downloads;
use App\Models\PopularMonthly;
use App\Models\PopularWeekly;
use App\Models\PopularDaily;
use Conner\Tagging\Taggable;
use Laravel\Scout\Searchable;
use Maize\Markable\Markable;
use Maize\Markable\Models\Like;
use Spatie\Sitemap\Contracts\Sitemapable;
use Spatie\Sitemap\Tags\Url;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Laravel\Scout\Searchable;
use Maize\Markable\Markable;
use Maize\Markable\Models\Like;
use Spatie\Sitemap\Contracts\Sitemapable;
use Spatie\Sitemap\Tags\Url;
class Episode extends Model implements Sitemapable
{
use Markable, Taggable;
use HasFactory;
use Markable, Taggable;
use Searchable;
protected static $marks = [
Like::class
Like::class,
];
/**
@@ -180,6 +173,7 @@ class Episode extends Model implements Sitemapable
$problematicResults .= $pTag;
}
return $problematicResults;
}
@@ -234,9 +228,10 @@ class Episode extends Model implements Sitemapable
return $this->hasMany(Watched::class);
}
public function getDownloadByType(string $type): Downloads | null
public function getDownloadByType(string $type): ?Downloads
{
$cacheKey = "episode_{$this->id}_download_{$type}";
return Cache::remember($cacheKey, now()->addMinutes(10), function () use ($type) {
return $this->downloads()->where('type', $type)->first();
});
+7 -8
View File
@@ -2,19 +2,18 @@
namespace App\Models;
use Conner\Tagging\Taggable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Spatie\Sitemap\Contracts\Sitemapable;
use Spatie\Sitemap\Tags\Url;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Conner\Tagging\Taggable;
class Hentai extends Model implements Sitemapable
{
use Taggable;
use HasFactory;
use Taggable;
/**
* The attributes that are mass assignable.
@@ -31,7 +30,7 @@ class Hentai extends Model implements Sitemapable
return $this->hasMany(Episode::class, 'hentai_id');
}
public function title(): String
public function title(): string
{
return $this->episodes->first()->title;
}
+1 -1
View File
@@ -2,8 +2,8 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Playlist extends Model
{
+1 -1
View File
@@ -2,8 +2,8 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class PlaylistEpisode extends Model
{
+1 -2
View File
@@ -4,7 +4,6 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
class SiteBackground extends Model
{
@@ -16,7 +15,7 @@ class SiteBackground extends Model
protected $fillable = [
'date_start',
'date_end',
'default'
'default',
];
/**
+1 -1
View File
@@ -3,8 +3,8 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Studios extends Model
{
+4 -8
View File
@@ -5,13 +5,12 @@ namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use App\Enums\UserRole;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
class User extends Authenticatable
{
@@ -62,7 +61,6 @@ class User extends Authenticatable
'discord_avatar' => 'string',
];
/**
* Has Many Playlists.
*/
@@ -108,13 +106,11 @@ class User extends Authenticatable
*/
public function getAvatar(): string
{
if ($this->discord_id && $this->discord_avatar && !$this->avatar)
{
if ($this->discord_id && $this->discord_avatar && ! $this->avatar) {
return "https://external-content.duckduckgo.com/iu/?u={$this->discord_avatar}";
}
if ($this->avatar)
{
if ($this->avatar) {
return Storage::url($this->avatar);
}
+1 -1
View File
@@ -2,8 +2,8 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class UserDownload extends Model
{
+1 -1
View File
@@ -2,8 +2,8 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Watched extends Model
{
+2 -2
View File
@@ -3,8 +3,6 @@
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class CommentNotification extends Notification
@@ -12,7 +10,9 @@ class CommentNotification extends Notification
use Queueable;
protected $type;
protected $message;
protected $url;
/**
+1 -1
View File
@@ -2,8 +2,8 @@
namespace App\Policies;
use App\Models\User;
use App\Models\Comment;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class CommentPolicy
+1 -3
View File
@@ -2,11 +2,9 @@
namespace App\Services;
use App\Jobs\GetFileSizeFromCDN;
use App\Models\Downloads;
use App\Models\Episode;
use App\Jobs\GetFileSizeFromCDN;
use Illuminate\Http\Request;
class DownloadService
+7 -10
View File
@@ -5,14 +5,12 @@ namespace App\Services;
use App\Models\Episode;
use App\Models\Hentai;
use App\Models\Studios;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Laravel\Facades\Image;
use Illuminate\Support\Str;
use Intervention\Image\Encoders\WebpEncoder;
use Intervention\Image\Laravel\Facades\Image;
class EpisodeService
{
@@ -24,6 +22,7 @@ class EpisodeService
if (is_numeric($lastPart) && $lastPart < 1000) {
$slugParts[array_key_last($slugParts)] = 's'.$lastPart;
return implode('-', $slugParts);
}
@@ -36,11 +35,10 @@ class EpisodeService
int $episodeNumber,
?Studios $studio = null,
?Episode $referenceEpisode = null
): Episode
{
$episode = new Episode();
): Episode {
$episode = new Episode;
$episode->title = $referenceEpisode->title ?? $request->input('title');
$episode->title_search = preg_replace("/[^A-Za-z0-9 ]/", '', $episode->title);
$episode->title_search = preg_replace('/[^A-Za-z0-9 ]/', '', $episode->title);
$episode->title_jpn = $referenceEpisode->title_jpn ?? $request->input('title_jpn');
$episode->slug = "{$hentai->slug}-{$episodeNumber}";
$episode->hentai_id = $hentai->id;
@@ -96,7 +94,6 @@ class EpisodeService
);
}
public function createOrUpdateCover(Request $request, Episode $episode, string $slug, int $episodeNumber): void
{
if (! $request->hasFile("episodecover{$episodeNumber}")) {
@@ -111,7 +108,7 @@ class EpisodeService
// Encode and save cover image
Image::read($request->file("episodecover{$episodeNumber}")->getRealPath())
->cover(268, 394)
->encode(new WebpEncoder())
->encode(new WebpEncoder)
->save(Storage::disk('public')->path($episode->cover_url));
}
}
+4 -8
View File
@@ -5,17 +5,13 @@ namespace App\Services;
use App\Models\Episode;
use App\Models\Gallery;
use App\Models\Hentai;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Laravel\Facades\Image;
use Intervention\Image\Encoders\WebpEncoder;
use Intervention\Image\Laravel\Facades\Image;
class GalleryService
{
public function createOrUpdateGallery(Request $request, Hentai $hentai, Episode $episode, int $episodeNumber, bool $override = false): void
{
$galleryInputNumber = $override ? 1 : $episodeNumber;
@@ -45,7 +41,7 @@ class GalleryService
private function createGallery(Hentai $hentai, Episode $episode, int $episodeNumber, int $counter): Gallery
{
$gallery = new Gallery();
$gallery = new Gallery;
$gallery->hentai_id = $hentai->id;
$gallery->episode_id = $episode->id;
$gallery->image_url = "/images/hentai/{$hentai->slug}/gallery-ep-{$episodeNumber}-{$counter}.webp";
@@ -59,12 +55,12 @@ class GalleryService
{
Image::read($sourceImage->getRealPath())
->cover(1920, 1080)
->encode(new WebpEncoder())
->encode(new WebpEncoder)
->save(Storage::disk('public')->path($gallery->image_url));
Image::read($sourceImage->getRealPath())
->cover(960, 540)
->encode(new WebpEncoder())
->encode(new WebpEncoder)
->save(Storage::disk('public')->path($gallery->thumbnail_url));
}
@@ -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();
}
}
Generated
+8 -8
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "2e359f5cfd56c822e336b74becc9c9d9",
"content-hash": "3400111a6254560d548639295422875c",
"packages": [
{
"name": "altcha-org/altcha",
@@ -3036,16 +3036,16 @@
},
{
"name": "livewire/livewire",
"version": "v3.7.3",
"version": "v3.7.10",
"source": {
"type": "git",
"url": "https://github.com/livewire/livewire.git",
"reference": "a5384df9fbd3eaf02e053bc49aabc8ace293fc1c"
"reference": "0dc679eb4c8b4470cb12522b5927ef08ca2358bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/livewire/livewire/zipball/a5384df9fbd3eaf02e053bc49aabc8ace293fc1c",
"reference": "a5384df9fbd3eaf02e053bc49aabc8ace293fc1c",
"url": "https://api.github.com/repos/livewire/livewire/zipball/0dc679eb4c8b4470cb12522b5927ef08ca2358bb",
"reference": "0dc679eb4c8b4470cb12522b5927ef08ca2358bb",
"shasum": ""
},
"require": {
@@ -3100,7 +3100,7 @@
"description": "A front-end framework for Laravel.",
"support": {
"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": [
{
@@ -3108,7 +3108,7 @@
"type": "github"
}
],
"time": "2025-12-19T02:00:29+00:00"
"time": "2026-02-09T22:49:33+00:00"
},
{
"name": "maize-tech/laravel-markable",
@@ -11584,5 +11584,5 @@
"php": "^8.2"
},
"platform-dev": {},
"plugin-api-version": "2.9.0"
"plugin-api-version": "2.6.0"
}
+1 -1
View File
@@ -12,7 +12,7 @@ return [
'803325441942356059', // Tier-3
'803322725576736858', // Tier-2
'802270568912519198', // Tier-1
'802234830384267315' // admin
'802234830384267315', // admin
],
'discord_bot_token' => env('DISCORD_BOT_TOKEN'),
+2 -2
View File
@@ -30,11 +30,11 @@ return [
// Asia Fallback (HTTP)
'asia_download_domain' => [
'https://komako-b-ddl.musume-h.xyz'
'https://komako-b-ddl.musume-h.xyz',
],
'asia_stream_domain' => [
'https://komako-b-str.musume-h.xyz'
'https://komako-b-str.musume-h.xyz',
],
// Free 4k Downloads
+1 -1
View File
@@ -38,5 +38,5 @@ return [
'autoOrientation' => true,
'decodeAnimation' => true,
'blendingColor' => 'ffffff',
]
],
];
+2 -2
View File
@@ -149,12 +149,12 @@ return [
'title_jpn',
'slug',
'description',
'tags'
'tags',
],
'sortableAttributes' => [
'created_at',
'release_date',
'title'
'title',
],
],
],
+7 -1
View File
@@ -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'),
],
];
-1
View File
@@ -263,5 +263,4 @@ return [
'confirm_delete_icon' => env('SWEET_ALERT_CONFIRM_DELETE_ICON', 'warning'),
'confirm_delete_show_loader_on_confirm' => env('SWEET_ALERT_CONFIRM_DELETE_SHOW_LOADER_ON_CONFIRM', true),
];
-1
View File
@@ -2,7 +2,6 @@
namespace Database\Factories;
use App\Models\Studios;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
@@ -5,8 +5,8 @@ use App\Models\Hentai;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
@@ -22,8 +22,7 @@ return new class extends Migration
*/
public function down()
{
Schema::table('gallery', function (Blueprint $table)
{
Schema::table('gallery', function (Blueprint $table) {
$table->dropIndex(['episode_id', 'hentai_id']);
});
}
@@ -2,8 +2,8 @@
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
@@ -29,7 +29,7 @@ return new class extends Migration
Downloads::create([
'episode_id' => $episode->id,
'type' => 'FHD',
'url' => $episode->download_url
'url' => $episode->download_url,
]);
}
@@ -38,7 +38,7 @@ return new class extends Migration
Downloads::create([
'episode_id' => $episode->id,
'type' => 'FHDi',
'url' => $episode->download_url_interpolated
'url' => $episode->download_url_interpolated,
]);
}
@@ -47,7 +47,7 @@ return new class extends Migration
Downloads::create([
'episode_id' => $episode->id,
'type' => 'UHD',
'url' => $episode->download_url_4k
'url' => $episode->download_url_4k,
]);
}
}
@@ -2,7 +2,6 @@
use App\Models\Episode;
use App\Models\Hentai;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
@@ -18,7 +18,7 @@ return new class extends Migration
// Update the title_search field with sanitized titles
DB::table('episodes')->update([
'title_search' => DB::raw("REGEXP_REPLACE(title, '[^A-Za-z0-9 ]', '')")
'title_search' => DB::raw("REGEXP_REPLACE(title, '[^A-Za-z0-9 ]', '')"),
]);
}
@@ -2,8 +2,8 @@
use App\Models\Playlist;
use App\Models\PlaylistEpisode;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
@@ -1,11 +1,10 @@
<?php
use App\Models\Downloads;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
@@ -14,10 +13,10 @@ return new class extends Migration
*/
public function up(): void
{
# Delete entries with "#" as URL
// Delete entries with "#" as URL
Downloads::where('url', '#')->delete();
# Remove duplicate entries
// Remove duplicate entries
$duplicates = DB::table('downloads')
->select('episode_id', 'type', DB::raw('COUNT(*) as count'))
->groupBy('episode_id', 'type')
@@ -1,7 +1,6 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
@@ -46,7 +46,6 @@ return new class extends Migration
$table->rememberToken()->after('password');
});
/**
* --------------------------------------------------------------------
* Fix Discord Profile Pictures
@@ -54,8 +53,7 @@ return new class extends Migration
* The oauth package by socialite now returns a full url of the avatar.
* Meaning all the old entries have to be fixed.
*/
foreach (User::whereNotNull('discord_avatar')->get() as $user)
{
foreach (User::whereNotNull('discord_avatar')->get() as $user) {
$isGif = preg_match('/a_.+/m', $user->discord_avatar) === 1;
$extension = $isGif ? 'gif' : 'webp';
$user->discord_avatar = sprintf('https://cdn.discordapp.com/avatars/%s/%s.%s', $user->id, $user->discord_avatar, $extension);
@@ -3,8 +3,8 @@
use App\Models\Playlist;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
@@ -69,7 +69,7 @@ return new class extends Migration
// Re-Add foreign key constraint and index
Schema::table('comments', function (Blueprint $table) {
$table->foreign('child_id')->references('id')->on('comments')->onDelete('cascade');
$table->index(["commenter_id", "commenter_type"]);
$table->index(['commenter_id', 'commenter_type']);
});
}
};
@@ -14,17 +14,17 @@ return new class extends Migration
{
// Migrate supporters
DB::table('users')->where('is_patreon', 1)->update([
'roles' => DB::raw("JSON_ARRAY('supporter')")
'roles' => DB::raw("JSON_ARRAY('supporter')"),
]);
// Migrate banned
DB::table('users')->where('is_banned', 1)->update([
'roles' => DB::raw("JSON_ARRAY('banned')")
'roles' => DB::raw("JSON_ARRAY('banned')"),
]);
// Migrate admins
DB::table('users')->where('is_admin', 1)->update([
'roles' => DB::raw("JSON_ARRAY('admin')")
'roles' => DB::raw("JSON_ARRAY('admin')"),
]);
// Drop columns
@@ -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');
});
}
};
+1 -1
View File
@@ -13,7 +13,7 @@ class DatabaseSeeder extends Seeder
public function run(): void
{
$this->call([
DeletedUserSeeder::class
DeletedUserSeeder::class,
]);
}
}
+1 -3
View File
@@ -3,11 +3,9 @@
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DeletedUserSeeder extends Seeder
{
+6 -5
View File
@@ -4,6 +4,7 @@
"requires": true,
"packages": {
"": {
"name": "hstream",
"dependencies": {
"@fortawesome/fontawesome-free": "^6.5.1",
"@jellyfin/libass-wasm": "^4.1.1",
@@ -1263,14 +1264,14 @@
}
},
"node_modules/axios": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
"version": "1.13.5",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz",
"integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.4",
"follow-redirects": "^1.15.11",
"form-data": "^4.0.5",
"proxy-from-env": "^1.1.0"
}
},
+3
View File
@@ -0,0 +1,3 @@
{
"preset": "laravel"
}
+7 -2
View File
@@ -7,14 +7,19 @@ function darkModeListener() {
}
}
document.querySelector("input[type='checkbox']#toogleTheme").addEventListener("click", darkModeListener);
document.querySelector("input[type='checkbox']#toogleTheme")?.addEventListener("click", darkModeListener);
if(localStorage.theme) {
if (localStorage.theme == 'light') {
if (document.querySelector("html").classList.contains('dark')) {
document.querySelector("html").classList.toggle("dark");
}
document.getElementById("toogleTheme").checked = true;
const toggleThemeButton = document.getElementById("toogleTheme");
if (toggleThemeButton) {
toggleThemeButton.checked = true;
}
}
} else {
// Default Dark Theme
+1 -1
View File
@@ -4,7 +4,7 @@
<body class="font-sans antialiased">
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
@include('layouts.navigation')
@include('user.partials.background')
@include('partials.background')
<div class="mt-[65px]">
@include('admin.partials.sidenav')
<div class="pl-64">
@@ -49,6 +49,22 @@
<i class="fa-brands fa-discord"></i> {{ __('nav.our-discord-server') }}
</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>
<div class="grid grid-cols-2">
<p class="cursor-default">{{ __('nav.theme') }}</p>
@@ -12,7 +12,7 @@
@else
<p class="text-lg">Episode {{ $episodeNumber }}</p>
@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>
</div>
</button>
@@ -235,6 +235,11 @@
'/' .
$expire;
}
$fileExtension = "HEVC";
if (str_contains($download->url, 'AV1')) {
$fileExtension = "AV1";
}
@endphp
<a href="{{ $downloadURL }}" wire:click="clicked({{ $download->id }})"
download>
@@ -249,7 +254,7 @@
</svg>
</div>
<div class="flex flex-col text-center w-full">
<p class="text-xs">HEVC MKV</p>
<p class="text-xs">{{ $fileExtension }} MKV</p>
</div>
</button>
</a>

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