This commit is contained in:
2025-09-18 15:31:27 +02:00
commit 2abba0c2b7
406 changed files with 31879 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
<?php
namespace App\Livewire;
use App\Models\User;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
class AdminUserSearch extends Component
{
use WithPagination;
#[Url(history: true)]
public $search = '';
#[Url(history: true)]
public $filtered = ['true'];
#[Url(history: true)]
public $patreon = [];
#[Url(history: true)]
public $banned = [];
public function render()
{
$users = User::when($this->filtered !== [], fn ($query) => $query->where('id', '>=', 10000))
->when($this->patreon !== [], fn ($query) => $query->where('is_patreon', 1))
->when($this->banned !== [], fn ($query) => $query->where('is_banned', 1))
->when($this->search !== '', fn ($query) => $query->where(function($query) {
$query->where('username', 'like', '%'.$this->search.'%')
->orWhere('global_name', 'like', '%'.$this->search.'%');
}))
->paginate(20);
return view('livewire.admin-user-search', [
'users' => $users
]);
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Livewire;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
use App\Models\SiteBackground;
use Illuminate\Support\Carbon;
class BackgroundImages extends Component
{
use WithPagination;
#[Url(history: true)]
public $filter = 'all';
public function render()
{
$now = Carbon::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)
)
->paginate(10);
return view('livewire.background-images', [
'images' => $images
]);
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace App\Livewire;
use App\Models\Downloads;
use Livewire\Component;
class DownloadButton extends Component
{
public $downloadUrl;
public $downloadId;
public $downloadCount;
public $episodeNumber;
public $fillNumbers;
public $fileSize;
public $background = 'bg-rose-600';
public function clicked($downloadId)
{
$download = Downloads::find($downloadId);
if (!$download) {
return;
}
$download->count++;
$download->save();
$this->downloadCount = $download->count;
cache()->forget("episode_{$download->episode->id}_download_{$download->type}");
}
public function render()
{
return view('livewire.download-button');
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Livewire;
use App\Models\Hentai;
use Livewire\Component;
use Livewire\WithPagination;
class Downloads extends Component
{
use WithPagination;
public $search;
public $order = 'az';
public $withTorrents;
protected $queryString = [
'search' => ['except' => '', 'as' => 's'],
'withTorrents' => ['withTorrents' => '', 'as' => 'withTorrents'],
'order' => ['except' => '', 'as' => 'order'],
];
public function updatingSearch()
{
$this->resetPage();
}
public function render()
{
$orderby = 'slug';
$orderdirection = 'desc';
switch ($this->order) {
case 'az':
$orderby = 'slug';
$orderdirection = 'asc';
break;
case 'za':
$orderby = 'slug';
$orderdirection = 'desc';
break;
default:
$orderby = 'created_at';
$orderdirection = 'desc';
}
$hentai = Hentai::with('episodes')
->when($this->search != '', fn ($query) => $query->whereHas('episodes', fn ($q) => $q->where('title', 'like', '%'.$this->search.'%')->orWhere('title_jpn', 'like', '%'.$this->search.'%')))
->when($this->withTorrents != '', fn ($query) => $query->whereHas('torrents'))
->orderBy($orderby, $orderdirection)
->paginate(10);
return view('livewire.downloads', [
'hentai' => $hentai,
'query' => $this->search,
]);
}
}

View File

@@ -0,0 +1,89 @@
<?php
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 Illuminate\Support\Facades\Cache;
class DownloadsFree extends Component
{
public $episodeId = 0;
public $downloadsLeft = 5;
public $granted = 0;
public $override = false;
public $interpolated = false;
public function mount(Episode $episode, $interpolated = false)
{
$this->episodeId = $episode->id;
$this->interpolated = $interpolated;
$user = Auth::user()->id;
if (Auth::check()) {
$this->downloadsLeft = (int) User::where('id', $user)->firstOrFail()->downloads_left;
}
if ($this->downloadsLeft === 0) {
$this->granted = 3;
}
if ($episode->created_at >= Carbon::now()->subDays(7)) {
$this->granted = 4;
}
$alreadyDownloaded = UserDownload::where('user_id', $user)
->where('episode_id', $this->episodeId)
->where('interpolated', $this->interpolated)
->first();
if ($alreadyDownloaded) {
// Check timestamp
if (Carbon::parse($alreadyDownloaded->created_at)->addHours(6) <= Carbon::now()) {
// Already expired
$alreadyDownloaded->forceDelete();
return;
}
$this->override = true;
}
}
public function generate()
{
$user = User::where('id', Auth::user()->id)->firstOrFail();
if ($user->downloads_left <= 0) {
// Daily limit reached
$this->granted = 3;
return;
}
$user->downloads_left -= 1;
$user->save();
$this->downloadsLeft -= 1;
$this->granted = 1;
UserDownload::create([
'user_id' => $user->id,
'episode_id' => $this->episodeId,
'interpolated' => $this->interpolated,
]);
}
public function render()
{
return view('livewire.downloads-free');
}
}

View File

@@ -0,0 +1,66 @@
<?php
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 Maize\Markable\Models\Like;
class LikeButton extends Component
{
public $episodeId = 0;
public $likeCount = 0;
public $liked = false;
public function mount(Episode $episode)
{
$this->episodeId = $episode->id;
$this->likeCount = $episode->likes->count();
if (Auth::check()) {
$this->liked = Like::has($episode, User::where('id', Auth::user()->id)->firstOrFail());
}
}
public function update()
{
$episode = Episode::where('id', $this->episodeId)->firstOrFail();
$this->likeCount = $episode->likes->count();
if (Auth::check()) {
$this->liked = Like::has($episode, User::where('id', Auth::user()->id)->firstOrFail());
}
}
public function like()
{
if (! Auth::check()) {
return;
}
$episode = Episode::where('id', $this->episodeId)->firstOrFail();
Like::toggle($episode, User::where('id', Auth::user()->id)->firstOrFail());
Cache::forget('episodeLikes'.$this->episodeId);
if ($this->liked) {
$this->liked = false;
$this->likeCount--;
return;
}
$this->liked = true;
$this->likeCount++;
}
public function render()
{
return view('livewire.like-button');
}
}

155
app/Livewire/LiveSearch.php Normal file
View File

@@ -0,0 +1,155 @@
<?php
namespace App\Livewire;
use App\Models\Episode;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
use Illuminate\Support\Facades\Auth;
class LiveSearch extends Component
{
use WithPagination;
#[Url(history: true)]
public $search = '';
#[Url(history: true)]
public $order = 'recently-uploaded';
#[Url(history: true)]
public $tags = [];
public $tagsCopy = [];
#[Url(history: true)]
public $studios = [];
public $studiosCopy = [];
#[Url(history: true)]
public $blacklist = [];
public $blacklistCopy = [];
#[Url(history: true)]
public $hideWatched = [];
#[Url(history: true)]
public $view = 'thumbnail';
public $pagination = 25;
public function updatingSearch(): void
{
$this->resetPage();
}
public function updatingHideWatched(): void
{
$this->resetPage();
}
public function updatedView(): void
{
$this->pagination = $this->view == 'thumbnail' ? 25 : 24;
$this->resetPage();
}
public function revertFilters(): void
{
$this->tags = $this->tagsCopy;
$this->studios = $this->studiosCopy;
$this->blacklist = $this->blacklistCopy;
}
public function applyFilters(): void
{
$this->tagsCopy = $this->tags;
$this->studiosCopy = $this->studios;
$this->blacklistCopy = $this->blacklist;
$this->resetPage();
}
public function mount()
{
// User blacklist
if (Auth::check() && empty($this->blacklist) && !empty(auth()->user()->tag_blacklist)) {
$this->blacklist = auth()->user()->tag_blacklist;
}
if (Auth::check()) {
$this->view = auth()->user()->search_design ? 'thumbnail' : 'poster';
$this->pagination = $this->view == 'thumbnail' ? 25 : 24;
}
}
public function render()
{
$orderby = 'created_at';
$orderdirection = 'desc';
switch ($this->order) {
case 'az':
$orderby = 'title';
$orderdirection = 'asc';
break;
case 'za':
$orderby = 'title';
$orderdirection = 'desc';
break;
case 'recently-released':
$orderby = 'release_date';
$orderdirection = 'desc';
break;
case 'oldest-uploads':
$orderby = 'created_at';
$orderdirection = 'asc';
break;
case 'oldest-releases':
$orderby = 'release_date';
$orderdirection = 'asc';
break;
case 'view-count':
$orderby = 'view_count';
$orderdirection = 'desc';
break;
default:
$orderby = 'created_at';
$orderdirection = 'desc';
}
$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.'%'); }))
->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->hideWatched !== [] && Auth::check(), fn ($query) => $query->whereDoesntHave('watched', function ($query) use ($user_id) {
$query->where('user_id', $user_id);
}))
->when(Auth::guest(), fn ($query) => $query->withoutTags(['loli', 'shota']))
->orderBy($orderby, $orderdirection)
->paginate($this->pagination);
$searchIsJpn = false;
if (! empty($this->search)) {
if (strlen($this->search) != strlen(utf8_decode($this->search))) {
$searchIsJpn = true;
}
}
// Dispatch Event to trigger JS reload for thumbnails
$this->dispatch('contentChanged');
return view('livewire.live-search', [
'episodes' => $episodes,
'tagcount' => is_array($this->tags) ? count($this->tags) : 0,
'studiocount' => is_array($this->studios) ? count($this->studios) : 0,
'blacklistcount' => is_array($this->blacklist) ? count($this->blacklist) : 0,
'query' => $this->search,
'selectedtags' => $this->tags,
'selectedstudios' => $this->studios,
'selectedblacklist' => $this->blacklist,
'searchIsJpn' => $searchIsJpn,
'view' => $this->view,
]);
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Livewire;
use App\Models\Episode;
use App\Models\Gallery;
use Livewire\Component;
use Illuminate\Support\Facades\Auth;
class NavLiveSearch extends Component
{
public $navSearch;
protected $queryString = [
'navSearch' => ['except' => '', 'as' => 's'],
];
public function render()
{
$episodes = [];
$randomimage = null;
if ($this->navSearch != '') {
$episodes = Episode::with('gallery')->where('title', 'like', '%'.$this->navSearch.'%')
->orWhere('title_jpn', 'like', '%'.$this->navSearch.'%')
->when(Auth::guest(), fn ($query) => $query->withoutTags(['loli', 'shota']))
->take(10)
->get();
$randomimage = Gallery::all()
->random(1)
->first();
}
return view('livewire.nav-live-search', [
'episodes' => $episodes,
'randomimage' => $randomimage,
'query' => $this->navSearch,
'hide' => empty($this->navSearch),
]);
}
}

View File

@@ -0,0 +1,123 @@
<?php
namespace App\Livewire;
use App\Models\Playlist;
use App\Models\PlaylistEpisode;
use App\Services\PlaylistService;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\Collection;
class PlaylistOverview extends Component
{
use WithPagination;
protected PlaylistService $playlistService;
#[Url(history: true)]
public $search;
public int $pagination = 25;
public Playlist $playlist;
public Collection $playlistEpisodes;
public function boot(PlaylistService $playlistService)
{
$this->playlistService = $playlistService;
}
public function mount($playlist_id)
{
$this->playlist = Playlist::with(['episodes.episode'])->findOrFail($playlist_id);
// Set position if null
$this->playlist->episodes->each(function ($item, $index) {
if ($item->position === null) {
$item->position = $index + 1;
$item->save();
}
});
$this->refreshEpisodes();
}
public function refreshEpisodes()
{
$this->playlistEpisodes = $this->playlist->episodes()->orderBy('position')->with('episode')->get();
}
public function moveUp($episodeId)
{
if (! Auth::check()) {
return;
}
if (Auth::user()->id !== $this->playlist->user->id) {
return;
}
$episode = PlaylistEpisode::find($episodeId);
$above = PlaylistEpisode::where('playlist_id', $episode->playlist_id)
->where('position', '<', $episode->position)
->orderBy('position', 'desc')
->first();
if ($above) {
$this->playlistService->swapPositions($episode, $above);
}
$this->refreshEpisodes();
}
public function moveDown($episodeId)
{
if (! Auth::check()) {
return;
}
if (Auth::user()->id !== $this->playlist->user->id) {
return;
}
$episode = PlaylistEpisode::find($episodeId);
$below = PlaylistEpisode::where('playlist_id', $episode->playlist_id)
->where('position', '>', $episode->position)
->orderBy('position')
->first();
if ($below) {
$this->playlistService->swapPositions($episode, $below);
}
$this->refreshEpisodes();
}
public function remove($episodeId)
{
if (! Auth::check()) {
return;
}
if (Auth::user()->id !== $this->playlist->user->id) {
return;
}
PlaylistEpisode::find($episodeId)?->delete();
$this->playlistService->reorderPositions($this->playlist);
$this->refreshEpisodes();
}
public function render()
{
return view('livewire.playlist-overview', [
'query' => $this->search,
]);
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace App\Livewire;
use App\Models\Playlist;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
class Playlists extends Component
{
use WithPagination;
#[Url(history: true)]
public $search;
#[Url(history: true)]
public $order = 'episode-count';
public $pagination = 12;
public function render()
{
$orderby = 'episodes_count';
$orderdirection = 'desc';
switch ($this->order) {
case 'az':
$orderby = 'name';
$orderdirection = 'asc';
break;
case 'za':
$orderby = 'name';
$orderdirection = 'desc';
break;
case 'episode-count':
$orderby = 'episodes_count';
$orderdirection = 'desc';
break;
case 'newest':
$orderby = 'created_at';
$orderdirection = 'desc';
break;
case 'oldest':
$orderby = 'created_at';
$orderdirection = 'asc';
break;
default:
$orderby = 'episodes_count';
$orderdirection = 'desc';
}
$playlists = Playlist::where('is_private', 0)
->withCount('episodes')
->having('episodes_count', '>', 1)
->when($this->search != '', fn($query) => $query->where('name', 'like', '%' . $this->search . '%'))
->orderBy($orderby, $orderdirection)
->paginate($this->pagination);
return view('livewire.playlists', [
'playlists' => $playlists
]);
}
}

152
app/Livewire/UserLikes.php Normal file
View File

@@ -0,0 +1,152 @@
<?php
namespace App\Livewire;
use App\Models\Episode;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
use Illuminate\Support\Facades\Auth;
class UserLikes extends Component
{
use WithPagination;
#[Url(history: true)]
public $search;
#[Url(history: true)]
public $order = 'recently-uploaded';
#[Url(history: true)]
public $tags = [];
public $tagsCopy = [];
#[Url(history: true)]
public $studios = [];
public $studiosCopy = [];
#[Url(history: true)]
public $blacklist = [];
public $blacklistCopy = [];
#[Url(history: true)]
public $hideWatched = [];
#[Url(history: true)]
public string $view = 'thumbnail';
public int $pagination = 25;
public function updatingSearch(): void
{
$this->resetPage();
}
public function updatingHideWatched(): void
{
$this->resetPage();
}
public function revertFilters(): void
{
$this->tags = $this->tagsCopy;
$this->studios = $this->studiosCopy;
$this->blacklist = $this->blacklistCopy;
}
public function applyFilters(): void
{
$this->tagsCopy = $this->tags;
$this->studiosCopy = $this->studios;
$this->blacklistCopy = $this->blacklist;
$this->resetPage();
}
public function updatedView(): void
{
$this->pagination = $this->view == 'thumbnail' ? 25 : 24;
$this->resetPage();
}
public function mount()
{
// User blacklist
if (Auth::check() && empty($this->blacklist) && !empty(auth()->user()->tag_blacklist)) {
$this->blacklist = auth()->user()->tag_blacklist;
}
if (Auth::check()) {
$this->view = auth()->user()->search_design ? 'thumbnail' : 'poster';
$this->pagination = $this->view == 'thumbnail' ? 25 : 24;
}
}
public function render()
{
$orderby = 'created_at';
$orderdirection = 'desc';
switch ($this->order) {
case 'az':
$orderby = 'title';
$orderdirection = 'asc';
break;
case 'za':
$orderby = 'title';
$orderdirection = 'desc';
break;
case 'recently-released':
$orderby = 'release_date';
$orderdirection = 'desc';
break;
case 'oldest-uploads':
$orderby = 'created_at';
$orderdirection = 'asc';
break;
case 'oldest-releases':
$orderby = 'release_date';
$orderdirection = 'asc';
break;
case 'view-count':
$orderby = 'view_count';
$orderdirection = 'desc';
break;
default:
$orderby = 'created_at';
$orderdirection = 'desc';
}
$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->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->hideWatched !== [] && Auth::check(), fn ($query) => $query->whereDoesntHave('watched', function ($query) use ($user_id) {
$query->where('user_id', $user_id);
}))
->orderBy($orderby, $orderdirection)
->paginate($this->pagination);
$searchIsJpn = false;
if (! empty($this->search)) {
if (strlen($this->search) != strlen(utf8_decode($this->search))) {
$searchIsJpn = true;
}
}
return view('livewire.user-likes', [
'episodes' => $episodes,
'tagcount' => is_array($this->tags) ? count($this->tags) : 0,
'studiocount' => is_array($this->studios) ? count($this->studios) : 0,
'blacklistcount' => is_array($this->blacklist) ? count($this->blacklist) : 0,
'query' => $this->search,
'selectedtags' => $this->tags,
'selectedstudios' => $this->studios,
'selectedblacklist' => $this->blacklist,
'searchIsJpn' => $searchIsJpn,
'view' => $this->view,
]);
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace App\Livewire;
use App\Models\Episode;
use Livewire\Component;
class ViewCount extends Component
{
public $episodeId = 0;
public $viewCount = 0;
public function mount(Episode $episode)
{
$this->episodeId = $episode->id;
$this->viewCount = $episode->view_count;
}
public function update()
{
$this->viewCount = Episode::where('id', $this->episodeId)->firstOrFail()->view_count;
}
public function render()
{
return view('livewire.view-count');
}
}

34
app/Livewire/Watched.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
namespace App\Livewire;
use App\Models\Watched as UserWatched;
use App\Models\User;
use Illuminate\Support\Carbon;
use Livewire\Component;
use Livewire\WithPagination;
class Watched extends Component
{
use WithPagination;
public $userId;
public function mount($user)
{
$this->userId = $user ? $user->id : auth()->user()->id;
}
public function render()
{
$watched = UserWatched::where('user_id', $this->userId)->orderBy('created_at', 'desc')->paginate(25);
$watchedGrouped = $watched->groupBy(function ($val) {
return Carbon::parse($val->created_at)->format('h');
});
return view('livewire.watched', [
'watched' => $watched,
'watchedGrouped' => $watchedGrouped,
]);
}
}