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,50 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Alert;
use Illuminate\Http\Request;
class AlertController extends Controller
{
/**
* Display alert index page
*/
public function index(): \Illuminate\View\View
{
return view('admin.alert.index');
}
/**
* Create Alert.
*/
public function store(Request $request): \Illuminate\Http\RedirectResponse
{
$validated = $request->validate([
'message' => 'required|string|max:255',
'type' => 'required|integer|min:0|digits_between:0,1',
]);
Alert::create([
'text' => $request->input('message'),
'type' => $request->input('type'),
]);
cache()->forget('alerts');
return redirect()->back();
}
/**
* Delete Alert.
*/
public function delete(int $alert_id): \Illuminate\Http\RedirectResponse
{
Alert::where('id', $alert_id)->forceDelete();
cache()->forget('alerts');
return redirect()->back();
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Contact;
class ContactController extends Controller
{
/**
* Display Contact Page.
*/
public function index(): \Illuminate\View\View
{
$contacts = Contact::orderBy('created_at', 'DESC')->get();
return view('admin.contact.index', [
'contacts' => $contacts
]);
}
/**
* Delete Contact.
*/
public function delete(int $contact_id): \Illuminate\Http\RedirectResponse
{
Contact::where('id', $contact_id)->delete();
return redirect()->back();
}
}

View File

@@ -0,0 +1,85 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Episode;
use App\Jobs\DiscordReleaseNotification;
use App\Services\DownloadService;
use App\Services\EpisodeService;
use App\Services\GalleryService;
use Illuminate\Http\Request;
class EpisodeController extends Controller
{
protected EpisodeService $episodeService;
protected GalleryService $galleryService;
protected DownloadService $downloadService;
public function __construct(
EpisodeService $episodeService,
GalleryService $galleryService,
DownloadService $downloadService
) {
$this->episodeService = $episodeService;
$this->galleryService = $galleryService;
$this->downloadService = $downloadService;
}
/**
* Add Episode to existing series
*/
public function store(Request $request): \Illuminate\Http\RedirectResponse
{
$referenceEpisode = Episode::with('hentai')->where('id', $request->input('episode_id'))->firstOrFail();
$episodeNumber = $referenceEpisode->hentai->episodes()->count() + 1;
// Create Episode
$episode = $this->episodeService->createEpisode($request, $referenceEpisode->hentai, $episodeNumber, null, $referenceEpisode);
$this->episodeService->createOrUpdateCover($request, $episode, $referenceEpisode->hentai->slug, 1);
$this->downloadService->createOrUpdateDownloads($request, $episode, 1);
$this->galleryService->createOrUpdateGallery($request, $referenceEpisode->hentai, $episode, $episodeNumber, true);
// Discord Alert
DiscordReleaseNotification::dispatch($episode->slug, 'release');
cache()->flush();
return to_route('hentai.index', [
'title' => $episode->slug
]);
}
/**
* Edit Episode
*/
public function update(Request $request): \Illuminate\Http\RedirectResponse
{
$episode = Episode::with('hentai')->where('id', $request->input('episode_id'))->firstOrFail();
$studio = $this->episodeService->getOrCreateStudio(json_decode($request->input('studio'))[0]->value);
$oldinterpolated = $episode->interpolated;
$oldInterpolatedUHD = $episode->interpolated_uhd;
$episode = $this->episodeService->updateEpisode($request, $studio, $episode->id);
$this->episodeService->createOrUpdateCover($request, $episode, $episode->hentai->slug, 1);
$this->downloadService->createOrUpdateDownloads($request, $episode, 1);
$this->galleryService->createOrUpdateGallery($request, $episode->hentai, $episode, $episode->episode, true);
// Discord Alert
if ($oldinterpolated !== (int) $episode->interpolated) {
DiscordReleaseNotification::dispatch($episode->slug, 'update');
}
if ($oldInterpolatedUHD !== (int) $episode->interpolated_uhd) {
DiscordReleaseNotification::dispatch($episode->slug, 'updateUHD');
}
cache()->flush();
return to_route('hentai.index', [
'title' => $episode->slug
]);
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Hentai;
use App\Jobs\DiscordReleaseNotification;
use App\Services\DownloadService;
use App\Services\EpisodeService;
use App\Services\GalleryService;
use Illuminate\Http\Request;
class ReleaseController extends Controller
{
protected EpisodeService $episodeService;
protected GalleryService $galleryService;
protected DownloadService $downloadService;
public function __construct(
EpisodeService $episodeService,
GalleryService $galleryService,
DownloadService $downloadService
) {
$this->episodeService = $episodeService;
$this->galleryService = $galleryService;
$this->downloadService = $downloadService;
}
/**
* Display release page
*/
public function index(): \Illuminate\View\View
{
return view('admin.release.create');
}
/**
* Upload New Hentai with One or Multipe Episodes
*/
public function store(Request $request): \Illuminate\Http\RedirectResponse
{
// Create new Hentai or find existing one
$slug = $this->episodeService->generateSlug($request->input('title'));
$hentai = Hentai::where('slug', $slug)->first();
// If hentai exists and was created today, return to home
if ($hentai?->created_at->isToday()) {
return to_route('home.index');
}
// If hentai does not exist, create a new instance
$hentai = Hentai::firstOrCreate(
['slug' => $slug],
['description' => $request->input('description1')]
);
// Studio
$studio = $this->episodeService->getOrCreateStudio(json_decode($request->input('studio'))[0]->value);
// Create Episode(s)
$releasedEpisodes = [];
for ($i = 1; $i <= $request->input('episodes'); $i++) {
$episode = $this->episodeService->createEpisode($request, $hentai, $i, $studio);
$this->episodeService->createOrUpdateCover($request, $episode, $slug, $i);
$this->downloadService->createOrUpdateDownloads($request, $episode, $i);
$this->galleryService->createOrUpdateGallery($request, $hentai, $episode, $i);
$releasedEpisodes[] = $episode->slug;
}
foreach ($releasedEpisodes as $slug) {
// Dispatch Discord Alert
DiscordReleaseNotification::dispatch($slug, 'release');
}
cache()->flush();
return to_route('home.index');
}
}

View File

@@ -0,0 +1,129 @@
<?php
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;
class SiteBackgroundController extends Controller
{
/**
* Display admin index page
*/
public function index(): \Illuminate\View\View
{
return view('admin.background.index', [
'images' => SiteBackground::all(),
]);
}
/**
* Create new site backgrounds
*/
public function create(Request $request): \Illuminate\Http\RedirectResponse
{
$request->validate([
'images' => 'required',
'date_start' => 'required',
'date_end' => 'required',
]);
foreach($request->file('images') as $file) {
// Initiating a database transaction in case something goes wrong.
DB::beginTransaction();
try {
$bg = SiteBackground::create(array_merge(
$request->only(['date_start', 'date_end']),
[
'default' => (bool) $request->input('default', false)
]
));
$resolutions = [1440, 1080, 720, 640];
foreach($resolutions as $resolution) {
// /images/background/1-2560p.webp
$targetPath = "/images/background/{$bg->id}-{$resolution}p.webp";
Image::read($file->getRealPath())
->scaleDown(height: $resolution)
->encode(new WebpEncoder())
->save(public_path($targetPath));
}
} catch (\Exception $e) {
DB::rollBack();
Log::error($e->getMessage());
return redirect()->back();
}
// Committing the database transaction.
DB::commit();
}
cache()->forget('background');
return redirect()->back();
}
public function update(Request $request): \Illuminate\Http\RedirectResponse
{
$request->validate([
'id' => 'required|exists:site_backgrounds,id',
'date_start' => 'required',
'date_end' => 'required',
]);
SiteBackground::where('id', $request->input('id'))->update(array_merge(
$request->only(['date_start', 'date_end']),
[
'default' => (bool) $request->input('default', false)
]
));
cache()->forget('background');
return redirect()->back();
}
/**
* Delete backround
*/
public function delete(Request $request): \Illuminate\Http\RedirectResponse
{
$id = $request->input('id');
// Initiating a database transaction in case something goes wrong.
DB::beginTransaction();
$bg = SiteBackground::where('id', $id)->firstOrFail();
$bg->forceDelete();
$resolutions = [1440, 1080, 720, 640];
try {
foreach($resolutions as $resolution) {
$targetPath = "/images/background/{$id}-{$resolution}p.webp";
File::delete(public_path($targetPath));
}
} catch (\Exception $e) {
DB::rollBack();
Log::error($e->getMessage());
return redirect()->back();
}
// Committing the database transaction.
DB::commit();
cache()->forget('background');
return redirect()->back();
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace App\Http\Controllers\Admin;
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
{
/**
* Add new Subtitle.
*/
public function store(Request $request): \Illuminate\Http\RedirectResponse
{
$subtitle = Subtitle::create([
'name' => $request->name,
'slug' => $request->slug,
]);
// Add to Episode
EpisodeSubtitle::create([
'episode_id' => $request->episode_id,
'subtitle_id' => $subtitle->id,
]);
return redirect()->back();
}
/**
* Update Episode Subtitles.
*/
public function update(Request $request): \Illuminate\Http\RedirectResponse
{
$episode = Episode::where('id', $request->input('episode_id'))->firstOrFail();
// Clear everything
foreach($episode->subtitles as $sub) {
$sub->forceDelete();
}
if (! $request->input('subtitles')) {
return redirect()->back();
}
// Re-Add
foreach (json_decode($request->input('subtitles')) as $sub) {
$subtitle = Subtitle::where('name', $sub->value)->firstOrFail();
// Add to Episode
EpisodeSubtitle::create([
'episode_id' => $episode->id,
'subtitle_id' => $subtitle->id,
]);
}
return redirect()->back();
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Torrents;
use Illuminate\Http\Request;
class TorrentController extends Controller
{
/**
* Display Add Torrent Page.
*/
public function index(int $hentai_id): \Illuminate\View\View
{
return view('admin.add-torrent', [
'hentai_id' => $hentai_id
]);
}
/**
* Add Torrent.
*/
public function store(Request $request): \Illuminate\Http\RedirectResponse
{
$validated = $request->validate([
'hentai_id' => 'required|exists:hentais,id',
'torrent_url' => 'required|string|max:256',
'torrent_episodes' => 'required|string|max:8',
]);
Torrents::create([
'hentai_id' => $request->hentai_id,
'torrent_url' => $request->torrent_url,
'episodes' => $request->torrent_episodes,
]);
return to_route('download.search');
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* Display Users Page.
*/
public function index(): \Illuminate\View\View
{
return view('admin.users.index');
}
/**
* Update user (ban/unban).
*/
public function update(Request $request)
{
$validated = $request->validate([
'id' => 'required|exists:users,id',
'action' => 'required',
]);
$user = User::findOrFail($validated['id']);
switch ($validated['action']) {
case 'ban':
$user->update(['is_banned' => 1]);
alert()->success('Banned', 'User has been banned.');
break;
case 'unban':
$user->update(['is_banned' => 0]);
alert()->success('Unbanned', 'User has been unbanned.');
break;
default:
alert()->error('Error','Invalid action provided');
}
return redirect()->back();
}
}