Compare commits
20 Commits
c0a22e875c
...
main
Author | SHA1 | Date | |
---|---|---|---|
444feac1e0 | |||
c034c94db5 | |||
ca52584da9 | |||
dca4924e9a | |||
9ad7c7afc2 | |||
6c8d34b030 | |||
35a0d61437 | |||
725a441d9e | |||
96a9019eba | |||
e2497867f0 | |||
a6c47cf2e6 | |||
fffa320c08 | |||
2880547f3e | |||
b5dbf24e91 | |||
43cf5db6c9 | |||
9e0042b09f | |||
e717b2bd07 | |||
bbbc4ac329 | |||
55739a21b5 | |||
bc193c7141 |
@@ -8,7 +8,7 @@
|
|||||||
# Install PHP
|
# Install PHP
|
||||||
sudo add-apt-repository ppa:ondrej/php
|
sudo add-apt-repository ppa:ondrej/php
|
||||||
apt update && apt upgrade
|
apt update && apt upgrade
|
||||||
apt install php8.4 php8.4-xml php8.4-mysql php8.4-gd php8.4-zip php8.4-curl php8.4-mbstring
|
apt install php8.3 php8.3-xml php8.3-mysql php8.3-gd php8.3-zip php8.3-curl php8.3-mbstring
|
||||||
|
|
||||||
# Install NodeJS
|
# Install NodeJS
|
||||||
curl -sL https://deb.nodesource.com/setup_20.x -o /tmp/nodesource_setup.sh
|
curl -sL https://deb.nodesource.com/setup_20.x -o /tmp/nodesource_setup.sh
|
||||||
@@ -22,7 +22,7 @@ mv composer.phar composer
|
|||||||
|
|
||||||
# Install NGINX (skip for local dev)
|
# Install NGINX (skip for local dev)
|
||||||
apt install nginx
|
apt install nginx
|
||||||
apt install php8.4-fpm
|
apt install php8.3-fpm
|
||||||
|
|
||||||
# Install MariaDB
|
# Install MariaDB
|
||||||
apt install mariadb-server
|
apt install mariadb-server
|
||||||
|
@@ -60,13 +60,6 @@ class CacheHelper
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getTotalMonthlyViews()
|
|
||||||
{
|
|
||||||
return Cache::remember("total_monthly_view_count", now()->addMinutes(60), function () {
|
|
||||||
return PopularMonthly::count();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getPopularAllTime(bool $guest)
|
public static function getPopularAllTime(bool $guest)
|
||||||
{
|
{
|
||||||
$guestString = $guest ? 'guest' : 'authed';
|
$guestString = $guest ? 'guest' : 'authed';
|
||||||
|
19
app/Helpers/GitHelper.php
Normal file
19
app/Helpers/GitHelper.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
|
class GitHelper
|
||||||
|
{
|
||||||
|
public static function shortCommit()
|
||||||
|
{
|
||||||
|
return Cache::remember("git_commit", now()->addMinutes(60), function () {
|
||||||
|
try {
|
||||||
|
return trim(exec('git rev-parse --short HEAD'));
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -42,7 +42,11 @@ class EpisodeController extends Controller
|
|||||||
$this->galleryService->createOrUpdateGallery($request, $referenceEpisode->hentai, $episode, $episodeNumber, true);
|
$this->galleryService->createOrUpdateGallery($request, $referenceEpisode->hentai, $episode, $episodeNumber, true);
|
||||||
|
|
||||||
// Discord Alert
|
// Discord Alert
|
||||||
|
if ($request->has('censored')) {
|
||||||
|
DiscordReleaseNotification::dispatch($referenceEpisode->title." - ".$episodeNumber, 'release-censored');
|
||||||
|
} else {
|
||||||
DiscordReleaseNotification::dispatch($episode->slug, 'release');
|
DiscordReleaseNotification::dispatch($episode->slug, 'release');
|
||||||
|
}
|
||||||
|
|
||||||
cache()->flush();
|
cache()->flush();
|
||||||
|
|
||||||
@@ -76,6 +80,10 @@ class EpisodeController extends Controller
|
|||||||
DiscordReleaseNotification::dispatch($episode->slug, 'updateUHD');
|
DiscordReleaseNotification::dispatch($episode->slug, 'updateUHD');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($request->has('v2')) {
|
||||||
|
DiscordReleaseNotification::dispatch($episode->slug, 'v2');
|
||||||
|
}
|
||||||
|
|
||||||
cache()->flush();
|
cache()->flush();
|
||||||
|
|
||||||
return to_route('hentai.index', [
|
return to_route('hentai.index', [
|
||||||
|
@@ -72,10 +72,14 @@ class ReleaseController extends Controller
|
|||||||
$releasedEpisodes[] = $episode->slug;
|
$releasedEpisodes[] = $episode->slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($request->has('censored')) {
|
||||||
|
DiscordReleaseNotification::dispatch($request->input('title'), 'release-censored');
|
||||||
|
} else {
|
||||||
foreach ($releasedEpisodes as $slug) {
|
foreach ($releasedEpisodes as $slug) {
|
||||||
// Dispatch Discord Alert
|
// Dispatch Discord Alert
|
||||||
DiscordReleaseNotification::dispatch($slug, 'release');
|
DiscordReleaseNotification::dispatch($slug, 'release');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cache()->flush();
|
cache()->flush();
|
||||||
|
|
||||||
|
@@ -1,40 +0,0 @@
|
|||||||
<?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');
|
|
||||||
}
|
|
||||||
}
|
|
56
app/Http/Controllers/Api/HentaiApiController.php
Normal file
56
app/Http/Controllers/Api/HentaiApiController.php
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Models\Hentai;
|
||||||
|
use App\Models\PopularMonthly;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
class HentaiApiController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get a list of all hentai with it's episodes
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// Cache for 10 minutes
|
||||||
|
$data = Cache::remember('api_hentai_list', now()->addMinutes(10), function () {
|
||||||
|
return Hentai::with('episodes')
|
||||||
|
->orderBy('created_at', 'desc')
|
||||||
|
->get()
|
||||||
|
->map(function ($hentai) {
|
||||||
|
return [
|
||||||
|
'title' => $hentai->episodes[0]->title,
|
||||||
|
'title_jpn' => $hentai->episodes[0]->title_jpn,
|
||||||
|
'slug' => $hentai->slug,
|
||||||
|
'episodes' => $hentai->episodes->map(function ($ep) {
|
||||||
|
return [
|
||||||
|
'episode' => $ep->episode,
|
||||||
|
'slug' => $ep->slug,
|
||||||
|
];
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->json($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get monthly views by day for stats
|
||||||
|
*/
|
||||||
|
public function getMonthlyViews()
|
||||||
|
{
|
||||||
|
// Cache for 60 minutes
|
||||||
|
$data = Cache::remember('api_monthly_views', now()->addMinutes(60), function () {
|
||||||
|
return PopularMonthly::selectRaw('DATE(created_at) as date, COUNT(*) as count')
|
||||||
|
->groupBy('date')
|
||||||
|
->orderBy('date', 'asc')
|
||||||
|
->get();
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->json($data);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,21 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class DownloadsController extends Controller
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Display Downloads Page.
|
|
||||||
*/
|
|
||||||
public function index(Request $request): \Illuminate\View\View
|
|
||||||
{
|
|
||||||
$user = $request->user();
|
|
||||||
if (!$user->is_patreon) {
|
|
||||||
abort(404);
|
|
||||||
}
|
|
||||||
|
|
||||||
return view('search.download-patreon');
|
|
||||||
}
|
|
||||||
}
|
|
@@ -52,6 +52,22 @@ class HomeController extends Controller
|
|||||||
return view('auth.banned');
|
return view('auth.banned');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirects to a random Hentai episode
|
||||||
|
* Done due to performance reasons
|
||||||
|
*/
|
||||||
|
public function random(): \Illuminate\Http\RedirectResponse
|
||||||
|
{
|
||||||
|
$random = Episode::inRandomOrder()
|
||||||
|
->limit(1)
|
||||||
|
->pluck('slug')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
return redirect()->route('hentai.index', [
|
||||||
|
'title' => $random,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display Search Page.
|
* Display Search Page.
|
||||||
*/
|
*/
|
||||||
@@ -87,7 +103,6 @@ class HomeController extends Controller
|
|||||||
'viewCount' => CacheHelper::getTotalViewCount(),
|
'viewCount' => CacheHelper::getTotalViewCount(),
|
||||||
'episodeCount' => CacheHelper::getTotalEpisodeCount(),
|
'episodeCount' => CacheHelper::getTotalEpisodeCount(),
|
||||||
'hentaiCount' => CacheHelper::getTotalHentaiCount(),
|
'hentaiCount' => CacheHelper::getTotalHentaiCount(),
|
||||||
'monthlyCount' => CacheHelper::getTotalMonthlyViews()
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,19 +32,29 @@ class DiscordReleaseNotification implements ShouldQueue
|
|||||||
*/
|
*/
|
||||||
public function handle(): void
|
public function handle(): void
|
||||||
{
|
{
|
||||||
// Wait 2s to avoid Discord API Rate limit
|
switch($this->messageType)
|
||||||
sleep(2);
|
{
|
||||||
|
case 'release':
|
||||||
if ($this->messageType == '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':
|
||||||
if ($this->messageType == 'update') {
|
# 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);
|
DiscordAlert::to('update')->message("<@&1283518462584426598> (´• ω •`)ノ Added **48fps** to Release! Check it out here: https://hstream.moe/hentai/".$this->slug);
|
||||||
}
|
break;
|
||||||
|
case 'updateUHD':
|
||||||
if ($this->messageType == 'updateUHD') {
|
# 4k 48fps added
|
||||||
DiscordAlert::to('update')->message("<@&1326860920902778963> (´• ω •`)ノ Added **48fps 4k** to Release! Check it out here: https://hstream.moe/hentai/".$this->slug);
|
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);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -32,11 +32,6 @@ class Hentai extends Model implements Sitemapable
|
|||||||
return $this->hasMany(Episode::class, 'hentai_id');
|
return $this->hasMany(Episode::class, 'hentai_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function torrents()
|
|
||||||
{
|
|
||||||
return $this->hasMany(Torrents::class, 'hentai_id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function title(): String
|
public function title(): String
|
||||||
{
|
{
|
||||||
return $this->episodes->first()->title;
|
return $this->episodes->first()->title;
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Torrents extends Model
|
|
||||||
{
|
|
||||||
use HasFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The attributes that are mass assignable.
|
|
||||||
*
|
|
||||||
* @var string[]
|
|
||||||
*/
|
|
||||||
protected $fillable = [
|
|
||||||
'hentai_id',
|
|
||||||
'torrent_url',
|
|
||||||
'episodes',
|
|
||||||
];
|
|
||||||
}
|
|
@@ -19,7 +19,7 @@
|
|||||||
"laravel/tinker": "^2.10",
|
"laravel/tinker": "^2.10",
|
||||||
"laravelista/comments": "dev-l11-compatibility",
|
"laravelista/comments": "dev-l11-compatibility",
|
||||||
"livewire/livewire": "^3.6.4",
|
"livewire/livewire": "^3.6.4",
|
||||||
"maize-tech/laravel-markable": "2.2.0",
|
"maize-tech/laravel-markable": "^2.3.0",
|
||||||
"mews/captcha": "3.4.4",
|
"mews/captcha": "3.4.4",
|
||||||
"predis/predis": "^2.2",
|
"predis/predis": "^2.2",
|
||||||
"realrashid/sweet-alert": "^7.2",
|
"realrashid/sweet-alert": "^7.2",
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
"vluzrmos/language-detector": "^2.3"
|
"vluzrmos/language-detector": "^2.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"barryvdh/laravel-debugbar": "3.14.7",
|
"barryvdh/laravel-debugbar": "^3.14.7",
|
||||||
"fakerphp/faker": "^1.24.0",
|
"fakerphp/faker": "^1.24.0",
|
||||||
"laravel/pint": "^1.18",
|
"laravel/pint": "^1.18",
|
||||||
"laravel/sail": "^1.38",
|
"laravel/sail": "^1.38",
|
||||||
|
2565
composer.lock
generated
2565
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ return [
|
|||||||
'webhook_urls' => [
|
'webhook_urls' => [
|
||||||
'default' => env('DISCORD_ALERT_WEBHOOK'),
|
'default' => env('DISCORD_ALERT_WEBHOOK'),
|
||||||
'update' => env('DISCORD_ALERT_UPDATE_WEBHOOK'),
|
'update' => env('DISCORD_ALERT_UPDATE_WEBHOOK'),
|
||||||
|
'rerelease' => env('DISCORD_ALERT_RERELEASE_WEBHOOK'),
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -6,7 +6,8 @@ return [
|
|||||||
'https://imoto-ddl.ane-h.xyz',
|
'https://imoto-ddl.ane-h.xyz',
|
||||||
'https://chibi-ddl.imoto-h.xyz',
|
'https://chibi-ddl.imoto-h.xyz',
|
||||||
'https://koneko-ddl.musume-h.xyz',
|
'https://koneko-ddl.musume-h.xyz',
|
||||||
'https://shinobu-ddl.rorikon-h.xyz'
|
'https://shinobu-ddl.rorikon-h.xyz',
|
||||||
|
'https://oppai-ddl.shoujo-h.org',
|
||||||
],
|
],
|
||||||
|
|
||||||
// 4k Download Domain
|
// 4k Download Domain
|
||||||
@@ -14,7 +15,8 @@ return [
|
|||||||
'https://imoto-ddlp.ane-h.xyz',
|
'https://imoto-ddlp.ane-h.xyz',
|
||||||
'https://chibi-ddlp.imoto-h.xyz',
|
'https://chibi-ddlp.imoto-h.xyz',
|
||||||
'https://koneko-ddlp.musume-h.xyz',
|
'https://koneko-ddlp.musume-h.xyz',
|
||||||
'https://shinobu-ddlp.rorikon-h.xyz'
|
'https://shinobu-ddlp.rorikon-h.xyz',
|
||||||
|
'https://oppai-ddlp.shoujo-h.org',
|
||||||
],
|
],
|
||||||
|
|
||||||
// Stream Domain
|
// Stream Domain
|
||||||
@@ -22,7 +24,8 @@ return [
|
|||||||
'https://imoto-str.ane-h.xyz',
|
'https://imoto-str.ane-h.xyz',
|
||||||
'https://chibi-str.imoto-h.xyz',
|
'https://chibi-str.imoto-h.xyz',
|
||||||
'https://koneko-str.musume-h.xyz',
|
'https://koneko-str.musume-h.xyz',
|
||||||
'https://shinobu-str.rorikon-h.xyz'
|
'https://shinobu-str.rorikon-h.xyz',
|
||||||
|
'https://oppai-str.shoujo-h.org',
|
||||||
],
|
],
|
||||||
|
|
||||||
// Asia Fallback (HTTP)
|
// Asia Fallback (HTTP)
|
||||||
|
@@ -0,0 +1,24 @@
|
|||||||
|
<?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::dropIfExists('torrents');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
// Not reversible
|
||||||
|
}
|
||||||
|
};
|
1824
package-lock.json
generated
1824
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,17 +9,18 @@
|
|||||||
"@tailwindcss/forms": "^0.5.7",
|
"@tailwindcss/forms": "^0.5.7",
|
||||||
"autoprefixer": "^10.4.18",
|
"autoprefixer": "^10.4.18",
|
||||||
"axios": "^1.6.8",
|
"axios": "^1.6.8",
|
||||||
"laravel-vite-plugin": "^1.0.2",
|
"laravel-vite-plugin": "^2.0.0",
|
||||||
"postcss": "^8.4.35",
|
"postcss": "^8.4.35",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"vite": "^5.1.6",
|
"vite": "^7.1.6",
|
||||||
"vite-plugin-static-copy": "^1.0.1"
|
"vite-plugin-static-copy": "^3.0.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^6.5.1",
|
"@fortawesome/fontawesome-free": "^6.5.1",
|
||||||
"@jellyfin/libass-wasm": "^4.1.1",
|
"@jellyfin/libass-wasm": "^4.1.1",
|
||||||
"@yaireo/tagify": "^4.21.2",
|
"@yaireo/tagify": "^4.21.2",
|
||||||
"dashjs": "^4.7.4",
|
"chart.js": "^4.5.0",
|
||||||
|
"dashjs": "^5.0.0",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"plyr": "^3.7.8",
|
"plyr": "^3.7.8",
|
||||||
"tw-elements": "^1.1.0",
|
"tw-elements": "^1.1.0",
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
// Plyr Player
|
// Plyr Player
|
||||||
import Plyr from 'plyr/dist/plyr.polyfilled.min.js';
|
import Plyr from 'plyr';
|
||||||
import 'plyr/dist/plyr.css';
|
import 'plyr/dist/plyr.css';
|
||||||
|
|
||||||
// Vidstack Player
|
// Vidstack Player
|
||||||
@@ -8,7 +8,7 @@ import 'vidstack/player/styles/default/layouts/video.css';
|
|||||||
import { VidstackPlayer, VidstackPlayerLayout } from 'vidstack/global/player';
|
import { VidstackPlayer, VidstackPlayerLayout } from 'vidstack/global/player';
|
||||||
|
|
||||||
// Dash Support
|
// Dash Support
|
||||||
import dashjs from 'dashjs';
|
import * as dashjs from 'dashjs';
|
||||||
|
|
||||||
// Subtitle Support
|
// Subtitle Support
|
||||||
import SubtitlesOctopus from '@jellyfin/libass-wasm';
|
import SubtitlesOctopus from '@jellyfin/libass-wasm';
|
||||||
|
73
resources/js/stats.js
Normal file
73
resources/js/stats.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import Chart from 'chart.js/auto';
|
||||||
|
|
||||||
|
// Theming
|
||||||
|
if (localStorage.theme !== 'light') {
|
||||||
|
Chart.defaults.color = "#ADBABD";
|
||||||
|
Chart.defaults.borderColor = "rgba(255,255,255,0.1)";
|
||||||
|
Chart.defaults.backgroundColor = "rgba(255,255,0,0.1)";
|
||||||
|
Chart.defaults.elements.line.borderColor = "rgba(255,255,0,0.4)";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Tags from API
|
||||||
|
window.axios.get('/v1/monthly-views').then(function (response) {
|
||||||
|
if (response.status != 200) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
labels: response.data.map((entry) => { return entry.date }),
|
||||||
|
datasets: [{
|
||||||
|
label: 'Views',
|
||||||
|
fill: false,
|
||||||
|
backgroundColor: 'rgba(190, 18, 60, 0.3)',
|
||||||
|
borderColor: 'rgba(190, 18, 60, 1.0)',
|
||||||
|
cubicInterpolationMode: 'monotone',
|
||||||
|
data: response.data.map((entry) => { return entry.count }),
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
type: 'line',
|
||||||
|
data: data,
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
plugins: {
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: 'Views the last 30 days',
|
||||||
|
font: {
|
||||||
|
size: 18
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
interaction: {
|
||||||
|
intersect: false,
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
display: true,
|
||||||
|
title: {
|
||||||
|
display: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
display: true,
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: 'Views'
|
||||||
|
},
|
||||||
|
suggestedMin: 0,
|
||||||
|
suggestedMax: 40000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const monthlyViewChart = new Chart(
|
||||||
|
document.getElementById('monthlyChart'),
|
||||||
|
config
|
||||||
|
);
|
||||||
|
}).catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
|
@@ -1,32 +0,0 @@
|
|||||||
<x-app-layout>
|
|
||||||
<div class="p-5">
|
|
||||||
<div class="w-[50%] mx-auto sm:px-6 lg:px-8 text-gray-800 dark:text-gray-200 bg-white dark:bg-neutral-950 rounded-lg">
|
|
||||||
<div class="relative p-4">
|
|
||||||
<form method="POST" action="{{ route('admin.add.torrent') }}">
|
|
||||||
@csrf
|
|
||||||
|
|
||||||
<div class="p-4">
|
|
||||||
<label class="mb-2 leading-tight text-gray-800 dark:text-gray-200 w-full" for="name">Hentai ID:</label>
|
|
||||||
<input id="hentai_id" name="hentai_id" class="block w-full p-4 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-rose-800 focus:border-rose-900 dark:bg-neutral-900 dark:border-neutral-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-rose-800 dark:focus:border-rose-900" value="{{ $hentai_id }}" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-4">
|
|
||||||
<label class="mb-2 leading-tight text-gray-800 dark:text-gray-200 w-full" for="name">Torrent URL:</label>
|
|
||||||
<input id="torrent_url" name="torrent_url" class="block w-full p-4 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-rose-800 focus:border-rose-900 dark:bg-neutral-900 dark:border-neutral-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-rose-800 dark:focus:border-rose-900" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="p-4">
|
|
||||||
<label class="mb-2 leading-tight text-gray-800 dark:text-gray-200 w-full" for="name">Episodes (e.g. "01-02" or "01"):</label>
|
|
||||||
<input id="torrent_episodes" name="torrent_episodes" class="block w-full p-4 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-rose-800 focus:border-rose-900 dark:bg-neutral-900 dark:border-neutral-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-rose-800 dark:focus:border-rose-900" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
|
||||||
<button type="submit" class="ml-1 inline-block rounded bg-rose-600 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600" data-te-ripple-init data-te-ripple-color="light">
|
|
||||||
Create
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</x-app-layout>
|
|
@@ -97,6 +97,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap flex-shrink-0 justify-end items-center p-4 rounded-b-md">
|
<div class="flex flex-wrap flex-shrink-0 justify-end items-center p-4 rounded-b-md">
|
||||||
|
<div class="inline-block mr-2">
|
||||||
|
<input class="w-4 h-4 text-rose-600 bg-gray-100 border-gray-300 rounded focus:ring-rose-500 dark:focus:ring-rose-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
|
||||||
|
type="checkbox" value="true" id="v2" name="v2" />
|
||||||
|
<label class="inline-block hover:cursor-pointer dark:text-white" for="v2">
|
||||||
|
v2 Re-Release Notification
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<button type="button" class="inline-block px-6 pt-2.5 pb-2 text-xs font-medium leading-normal uppercase rounded transition duration-150 ease-in-out bg-primary-100 text-primary-700 hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200" data-te-modal-dismiss data-te-ripple-init data-te-ripple-color="light">
|
<button type="button" class="inline-block px-6 pt-2.5 pb-2 text-xs font-medium leading-normal uppercase rounded transition duration-150 ease-in-out bg-primary-100 text-primary-700 hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200" data-te-modal-dismiss data-te-ripple-init data-te-ripple-color="light">
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
|
@@ -56,6 +56,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
||||||
|
<div class="inline-block mr-2">
|
||||||
|
<input class="w-4 h-4 text-rose-600 bg-gray-100 border-gray-300 rounded focus:ring-rose-500 dark:focus:ring-rose-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
|
||||||
|
type="checkbox" value="true" id="censored" name="censored" />
|
||||||
|
<label class="inline-block hover:cursor-pointer dark:text-white" for="censored">
|
||||||
|
Censored Notification
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<button type="button" class="inline-block rounded bg-primary-100 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-primary-700 transition duration-150 ease-in-out hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200" data-te-modal-dismiss data-te-ripple-init data-te-ripple-color="light">
|
<button type="button" class="inline-block rounded bg-primary-100 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-primary-700 transition duration-150 ease-in-out hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200" data-te-modal-dismiss data-te-ripple-init data-te-ripple-color="light">
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
|
@@ -62,13 +62,12 @@
|
|||||||
|
|
||||||
<div class="p-4 pt-0">
|
<div class="p-4 pt-0">
|
||||||
<label class="leading-tight text-gray-800 dark:text-gray-200 w-full" for="description1">Description 1:</label>
|
<label class="leading-tight text-gray-800 dark:text-gray-200 w-full" for="description1">Description 1:</label>
|
||||||
<textarea rows="4" cols="50" id="description1" name="description1" class="mt-1 block w-full border-gray-300 dark:border-gray-700 dark:bg-neutral-900 dark:text-gray-300 focus:border-rose-500 dark:focus:border-rose-600 focus:ring-rose-500 dark:focus:ring-rose-600 rounded-md shadow-sm" required>
|
<textarea rows="4" cols="50" id="description1" name="description1" class="mt-1 block w-full border-gray-300 dark:border-gray-700 dark:bg-neutral-900 dark:text-gray-300 focus:border-rose-500 dark:focus:border-rose-600 focus:ring-rose-500 dark:focus:ring-rose-600 rounded-md shadow-sm" required></textarea>
|
||||||
</textarea>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-4 pt-0">
|
<div class="p-4 pt-0">
|
||||||
<label class="leading-tight text-gray-800 dark:text-gray-200 w-full" for="episodedlurl1">Download 1080p 1:</label>
|
<label class="leading-tight text-gray-800 dark:text-gray-200 w-full" for="episodedlurl1">Download 1080p 1:</label>
|
||||||
<x-text-input id="episodedlurl1" class="block w-full" type="text" name="episodedlurl1" required />
|
<x-text-input id="episodedlurl1" class="block w-full" type="text" name="episodedlurl1" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-4 pt-0">
|
<div class="p-4 pt-0">
|
||||||
@@ -78,7 +77,7 @@
|
|||||||
|
|
||||||
<div class="p-4 pt-0">
|
<div class="p-4 pt-0">
|
||||||
<label class="leading-tight text-gray-800 dark:text-gray-200 w-full" for="episodedlurl4k1">Download 4k 1:</label>
|
<label class="leading-tight text-gray-800 dark:text-gray-200 w-full" for="episodedlurl4k1">Download 4k 1:</label>
|
||||||
<x-text-input id="episodedlurl4k1" class="block w-full" type="text" name="episodedlurl4k1" required />
|
<x-text-input id="episodedlurl4k1" class="block w-full" type="text" name="episodedlurl4k1" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-4 pt-0">
|
<div class="p-4 pt-0">
|
||||||
@@ -90,6 +89,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
||||||
|
<div class="inline-block mr-2">
|
||||||
|
<input class="w-4 h-4 text-rose-600 bg-gray-100 border-gray-300 rounded focus:ring-rose-500 dark:focus:ring-rose-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
|
||||||
|
type="checkbox" value="true" id="censored" name="censored" />
|
||||||
|
<label class="inline-block hover:cursor-pointer dark:text-white" for="censored">
|
||||||
|
Censored Notification
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<button type="button" class="inline-block rounded bg-primary-100 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-primary-700 transition duration-150 ease-in-out hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200" data-te-modal-dismiss data-te-ripple-init data-te-ripple-color="light">
|
<button type="button" class="inline-block rounded bg-primary-100 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-primary-700 transition duration-150 ease-in-out hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200" data-te-modal-dismiss data-te-ripple-init data-te-ripple-color="light">
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
|
@@ -1,7 +1,11 @@
|
|||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
<div class="container my-24 mx-auto md:px-6 z-10 relative">
|
<div class="container my-24 mx-auto md:px-6 z-10 relative">
|
||||||
<p class="leading-normal font-bold text-lg text-rose-600 text-center">
|
<p class="leading-normal font-bold text-2xl text-rose-600 text-center">
|
||||||
(╥﹏╥)
|
(╥﹏╥)
|
||||||
</p>
|
</p>
|
||||||
|
<br>
|
||||||
|
<p class="leading-normal font-bold text-lg text-rose-600 text-center">
|
||||||
|
Please login to view this hentai!
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</x-app-layout>
|
</x-app-layout>
|
@@ -1,6 +1,6 @@
|
|||||||
@props(['episode'])
|
@props(['episode'])
|
||||||
|
|
||||||
<div class="relative p-1 mb-8 w-full transition duration-300 ease-in-out md:p-2 hover:-translate-y-1 hover:scale-110">
|
<div class="relative p-1 mb-8 w-full transition duration-300 ease-in-out md:p-2 md:hover:-translate-y-1 md:hover:scale-110">
|
||||||
<a class="hover:text-blue-600" href="{{ route('hentai.index', ['title' => $episode->slug]) }}">
|
<a class="hover:text-blue-600" href="{{ route('hentai.index', ['title' => $episode->slug]) }}">
|
||||||
<img alt="{{ $episode->title }} - {{ $episode->episode }}" loading="lazy" width="1000"
|
<img alt="{{ $episode->title }} - {{ $episode->episode }}" loading="lazy" width="1000"
|
||||||
class="block object-cover object-center relative z-20 rounded-lg aspect-video"
|
class="block object-cover object-center relative z-20 rounded-lg aspect-video"
|
||||||
@@ -8,10 +8,10 @@
|
|||||||
|
|
||||||
@guest
|
@guest
|
||||||
<p
|
<p
|
||||||
class="absolute right-2 top-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute right-1 md:right-2 top-1 md:top-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
{{ $episode->getResolution() }}</p>
|
{{ $episode->getResolution() }}</p>
|
||||||
<p
|
<p
|
||||||
class="absolute left-4 bottom-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute left-1 md:left-4 bottom-1 md:bottom-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i class="fa-regular fa-heart"></i>
|
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i class="fa-regular fa-heart"></i>
|
||||||
{{ $episode->likeCount() }} <i class="fa-regular fa-comment"></i>
|
{{ $episode->likeCount() }} <i class="fa-regular fa-comment"></i>
|
||||||
{{ $episode->commentCount() }}
|
{{ $episode->commentCount() }}
|
||||||
@@ -29,20 +29,20 @@
|
|||||||
@auth
|
@auth
|
||||||
@if ($episode->userWatched(auth()->user()->id))
|
@if ($episode->userWatched(auth()->user()->id))
|
||||||
<p
|
<p
|
||||||
class="absolute right-2 top-2 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute right-1 md:right-2 top-1 md:top-2 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
{{ $episode->getResolution() }}</p>
|
{{ $episode->getResolution() }}</p>
|
||||||
<p
|
<p
|
||||||
class="absolute left-2 bottom-2 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute left-1 md:left-2 bottom-1 md:bottom-2 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
|
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
|
||||||
class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i class="fa-regular fa-comment"></i>
|
class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i class="fa-regular fa-comment"></i>
|
||||||
{{ $episode->commentCount() }}
|
{{ $episode->commentCount() }}
|
||||||
</p>
|
</p>
|
||||||
@else
|
@else
|
||||||
<p
|
<p
|
||||||
class="absolute right-2 top-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute right-1 md:right-2 top-1 md:top-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
{{ $episode->getResolution() }}</p>
|
{{ $episode->getResolution() }}</p>
|
||||||
<p
|
<p
|
||||||
class="absolute left-2 bottom-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute left-1 md:left-2 bottom-1 md:bottom-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
|
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
|
||||||
class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i class="fa-regular fa-comment"></i>
|
class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i class="fa-regular fa-comment"></i>
|
||||||
{{ $episode->commentCount() }}
|
{{ $episode->commentCount() }}
|
||||||
|
@@ -24,9 +24,8 @@
|
|||||||
@include('home.partials.random')
|
@include('home.partials.random')
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- Comments -->
|
<!-- Comments -->
|
||||||
<div class="mx-auto pt-6 sm:px-6 lg:px-8 space-y-6 max-w-[100%] xl:max-w-[95%] 2xl:max-w-[85%]">
|
<div class="mx-auto pt-6 sm:px-6 lg:px-8 space-y-6 max-w-[100%] xl:max-w-[95%] 2xl:max-w-[85%] pb-2">
|
||||||
@include('home.partials.comments')
|
@include('home.partials.comments')
|
||||||
</div>
|
</div>
|
||||||
</x-app-layout>
|
</x-app-layout>
|
@@ -1,8 +1,12 @@
|
|||||||
<p class="leading-normal font-bold text-lg text-neutral-800 dark:text-white">
|
<p class="leading-normal font-bold text-lg text-neutral-800 dark:text-white">
|
||||||
Random
|
Random <span class="font-light text-xs text-neutral-800/60 dark:text-white/40">(Cached for 5 minutes)</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@php $random = \App\Models\Episode::inRandomOrder()->limit(8)->get(); @endphp
|
@php
|
||||||
|
$random = \cache()->remember('random_home', 300, function () {
|
||||||
|
return \App\Models\Episode::inRandomOrder()->limit(8)->get(); ;
|
||||||
|
});
|
||||||
|
@endphp
|
||||||
|
|
||||||
<div class="mb-6">
|
<div class="mb-6">
|
||||||
@include('home.partials.tab.template', ['episodes' => $random, 'showThumbnails' => false])
|
@include('home.partials.tab.template', ['episodes' => $random, 'showThumbnails' => false])
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
<div class="flex justify-center pb-10">
|
<div class="flex justify-center pb-10">
|
||||||
<img src="/images/cropped-HS-1-270x270.webp" class="max-w-[150px]" alt="hstream.moe Logo" />
|
<img src="/images/cropped-HS-1-270x270.webp" class="max-w-[150px]" alt="hstream.moe Logo" />
|
||||||
</div>
|
</div>
|
||||||
<div class="grid md:grid-cols-5 lg:gap-x-12">
|
<div class="grid md:grid-cols-2 lg:grid-cols-4 lg:gap-x-12">
|
||||||
<div class="mb-12 md:mb-0">
|
<div class="mb-12 md:mb-0">
|
||||||
<div class="mb-6 inline-block rounded-md bg-white dark:bg-neutral-950 p-4 text-sky-500">
|
<div class="mb-6 inline-block rounded-md bg-white dark:bg-neutral-950 p-4 text-sky-500">
|
||||||
<i class="fa-solid fa-eye text-3xl"> {{ number_format($viewCount) }}</i>
|
<i class="fa-solid fa-eye text-3xl"> {{ number_format($viewCount) }}</i>
|
||||||
@@ -14,15 +14,7 @@
|
|||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-12 md:mb-0">
|
<div class="mb-12 md:mb-0">
|
||||||
<div class="mb-6 inline-block rounded-md bg-white dark:bg-neutral-950 p-4 text-sky-500">
|
<div class="b-6 inline-block rounded-md bg-white dark:bg-neutral-950 p-4 text-sky-500">
|
||||||
<i class="fa-solid fa-calendar-days text-3xl"> {{ number_format($monthlyCount) }}</i>
|
|
||||||
</div>
|
|
||||||
<h5 class="text-lg font-medium dark:text-neutral-300">
|
|
||||||
views the last 30 days
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
<div class="mb-12 md:mb-0">
|
|
||||||
<div class="mb-6 inline-block rounded-md bg-white dark:bg-neutral-950 p-4 text-rose-600">
|
|
||||||
<i class="fa-solid fa-video text-3xl"> {{ $episodeCount }}</i>
|
<i class="fa-solid fa-video text-3xl"> {{ $episodeCount }}</i>
|
||||||
</div>
|
</div>
|
||||||
<h5 class="text-lg font-medium dark:text-neutral-300">
|
<h5 class="text-lg font-medium dark:text-neutral-300">
|
||||||
@@ -46,7 +38,10 @@
|
|||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
<div class="flex justify-center dark:bg-neutral-950 bg-gray-50 rounded-xl md:m-11 hidden md:block">
|
||||||
<p class="text-center text-black/40 dark:text-white/40">Cached for 60 Minutes</p>
|
<canvas id="monthlyChart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
@vite(['resources/js/stats.js'])
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<footer class="mt-auto bg-white z-10 rounded-lg shadow dark:bg-neutral-950 m-4">
|
<footer class="bg-white z-10 rounded-lg shadow dark:bg-neutral-950 m-4 mb-0 mt-auto">
|
||||||
<div class="w-full xl:max-w-[95%] 2xl:max-w-[84%] mx-auto p-4">
|
<div class="w-full xl:max-w-[95%] 2xl:max-w-[84%] mx-auto p-4">
|
||||||
<div class="sm:flex sm:items-center sm:justify-between">
|
<div class="sm:flex sm:items-center sm:justify-between">
|
||||||
<a href="https://hstream.moe/" class="flex items-center mb-4 sm:mb-0">
|
<a href="https://hstream.moe/" class="flex items-center mb-4 sm:mb-0">
|
||||||
@@ -65,3 +65,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
@include('modals.language-selector')
|
@include('modals.language-selector')
|
||||||
|
|
||||||
|
<div class="m-2 w-full mx-auto">
|
||||||
|
<div class="text-sm text-gray-500 text-center">
|
||||||
|
<p>Render time: {{ number_format(microtime(true) - (defined('LARAVEL_START') ? LARAVEL_START : request()->server('REQUEST_TIME_FLOAT')), 3) }} seconds | Memory usage: {{ number_format(memory_get_peak_usage(true) / 1048576, 2) }} MB | Git: <a href="https://gitea.hstream.moe/w33b/hstream/commits/branch/main" target="_blank">{{ \App\Helpers\GitHelper::shortCommit() }}</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -67,8 +67,7 @@
|
|||||||
@livewire('nav-live-search')
|
@livewire('nav-live-search')
|
||||||
<div class="hidden lg:block pl-4">
|
<div class="hidden lg:block pl-4">
|
||||||
<div class="flex flex-col items-center bg-gray-50/20 dark:bg-neutral-900/40 rounded-md">
|
<div class="flex flex-col items-center bg-gray-50/20 dark:bg-neutral-900/40 rounded-md">
|
||||||
@php $random = App\Models\Episode::inRandomOrder()->limit(1)->pluck('slug')->first(); @endphp
|
<a href="{{ route('hentai.random') }}"
|
||||||
<a href="{{ route('hentai.index', ['title' => $random]) }}"
|
|
||||||
class="cursor-pointer px-4 py-2 text-sm font-medium dark:hover:text-white text-gray-500 dark:text-white/90 focus:outline-none flex flex-col items-center md:flex-row">
|
class="cursor-pointer px-4 py-2 text-sm font-medium dark:hover:text-white text-gray-500 dark:text-white/90 focus:outline-none flex flex-col items-center md:flex-row">
|
||||||
<i class="fa-solid fa-shuffle"></i>
|
<i class="fa-solid fa-shuffle"></i>
|
||||||
<p class="md:pl-1 pl-0">Random</p>
|
<p class="md:pl-1 pl-0">Random</p>
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
<div wire:key="episode-{{ $episode->id }}">
|
<div wire:key="episode-{{ $episode->id }}">
|
||||||
@if ($searchIsJpn)
|
@if ($searchIsJpn)
|
||||||
<div class="relative p-1 mb-14 w-full transition duration-300 ease-in-out md:p-2 hover:-translate-y-1 hover:scale-110"
|
<div class="relative p-1 mb-14 w-full transition duration-300 ease-in-out md:p-2 md:hover:-translate-y-1 md:hover:scale-110"
|
||||||
data-thumbs="{{ optional($episode->gallery)->pluck('thumbnail_url') }}">
|
data-thumbs="{{ optional($episode->gallery)->pluck('thumbnail_url') }}">
|
||||||
@else
|
@else
|
||||||
<div class="relative p-1 mb-8 w-full transition duration-300 ease-in-out md:p-2 hover:-translate-y-1 hover:scale-110"
|
<div class="relative p-1 mb-8 w-full transition duration-300 ease-in-out md:p-2 md:hover:-translate-y-1 md:hover:scale-110"
|
||||||
data-thumbs="{{ optional($episode->gallery)->pluck('thumbnail_url') }}">
|
data-thumbs="{{ optional($episode->gallery)->pluck('thumbnail_url') }}">
|
||||||
@endif
|
@endif
|
||||||
<a class="hover:text-blue-600" href="{{ route('hentai.index', ['title' => $episode->slug]) }}">
|
<a class="hover:text-blue-600" href="{{ route('hentai.index', ['title' => $episode->slug]) }}">
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
src="{{ optional($episode->gallery->first())->thumbnail_url }}">
|
src="{{ optional($episode->gallery->first())->thumbnail_url }}">
|
||||||
@if ($episode->hasAutoTrans())
|
@if ($episode->hasAutoTrans())
|
||||||
<p
|
<p
|
||||||
class="absolute right-2 bottom-2 bg-blue-600/80 !text-white rounded-tl-lg rounded-br-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute right-1 md:right-2 bottom-1 md:bottom-2 bg-blue-600/80 !text-white rounded-tl-lg rounded-br-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
<i class="fa-regular fa-closed-captioning"></i> Multi-Subs
|
<i class="fa-regular fa-closed-captioning"></i> Multi-Subs
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
@@ -44,27 +44,27 @@
|
|||||||
@php $problematic = cache()->rememberForever('episodeProblematic'.$episode->id, fn () => $episode->getProblematicTags()); @endphp
|
@php $problematic = cache()->rememberForever('episodeProblematic'.$episode->id, fn () => $episode->getProblematicTags()); @endphp
|
||||||
@if (!empty($problematic))
|
@if (!empty($problematic))
|
||||||
<p
|
<p
|
||||||
class="absolute left-2 top-2 bg-red-700/70 !text-white rounded-br-lg rounded-tl-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute left-1 md:left-2 top-1 md:top-2 bg-red-700/70 !text-white rounded-br-lg rounded-tl-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
<i class="fa-solid fa-triangle-exclamation"></i> {{ $problematic }}
|
<i class="fa-solid fa-triangle-exclamation"></i> {{ $problematic }}
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (auth()->check() && $episode->userWatched(auth()->user()->id))
|
@if (auth()->check() && $episode->userWatched(auth()->user()->id))
|
||||||
<p
|
<p
|
||||||
class="absolute right-2 top-2 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute right-1 md:right-2 top-1 md:top-2 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
{{ $episode->getResolution() }}</p>
|
{{ $episode->getResolution() }}</p>
|
||||||
<p
|
<p
|
||||||
class="absolute left-2 bottom-2 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute left-1 md:left-2 bottom-1 md:bottom-2 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
|
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
|
||||||
class="fa-regular fa-heart"></i>
|
class="fa-regular fa-heart"></i>
|
||||||
{{ $episode->likeCount() }} <i class="fa-regular fa-comment"></i> {{ $episode->commentCount() }}
|
{{ $episode->likeCount() }} <i class="fa-regular fa-comment"></i> {{ $episode->commentCount() }}
|
||||||
</p>
|
</p>
|
||||||
@else
|
@else
|
||||||
<p
|
<p
|
||||||
class="absolute right-2 top-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute right-1 md:right-2 top-1 md:top-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
{{ $episode->getResolution() }}</p>
|
{{ $episode->getResolution() }}</p>
|
||||||
<p
|
<p
|
||||||
class="absolute left-2 bottom-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute left-1 md:left-2 bottom-1 md:bottom-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
<i class="fa-regular fa-eye"></i>
|
<i class="fa-regular fa-eye"></i>
|
||||||
{{ $episode->viewCountFormatted() }}
|
{{ $episode->viewCountFormatted() }}
|
||||||
<i class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i class="fa-regular fa-comment"></i>
|
<i class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i class="fa-regular fa-comment"></i>
|
||||||
|
@@ -1,25 +0,0 @@
|
|||||||
@forelse ($hentai->torrents as $torrent)
|
|
||||||
<a href="{{ $torrent->torrent_url }}" target="_blank">
|
|
||||||
<button class="group rounded-md shadow bg-primary-600 text-white cursor-pointer flex justify-between items-center overflow-hidden transition-all hover:glow m-1 w-[150px]">
|
|
||||||
<div class="relative w-12 h-12 bg-white bg-opacity-20 text-white flex justify-center items-center transition-all">
|
|
||||||
<i id="arrow" class="fa-solid fa-magnet transition-all group-hover:-translate-y-1"></i>
|
|
||||||
<div id="progress" class="absolute w-full h-0 bg-white bg-opacity-20 top-0 duration-200"></div>
|
|
||||||
</div>
|
|
||||||
<div class="w-32 text-center">
|
|
||||||
<p class="text-sm">Episode {{ $torrent->episodes }}</p>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
@empty
|
|
||||||
<a>
|
|
||||||
<button class="group rounded-md shadow bg-gray-600 text-white cursor-pointer flex justify-between items-center overflow-hidden transition-all hover:glow m-1 w-[150px]">
|
|
||||||
<div class="relative w-12 h-12 bg-white bg-opacity-20 text-white flex justify-center items-center transition-all">
|
|
||||||
<i id="arrow" class="fa-solid fa-magnet transition-all group-hover:-translate-y-1"></i>
|
|
||||||
<div id="progress" class="absolute w-full h-0 bg-white bg-opacity-20 top-0 duration-200"></div>
|
|
||||||
</div>
|
|
||||||
<div class="w-32 text-center">
|
|
||||||
<p class="text-sm">Torrent not available</p>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
@endforelse
|
|
@@ -1,4 +1,6 @@
|
|||||||
@auth
|
@auth
|
||||||
|
@php $download = $episode->getDownloadByType('FHD'); @endphp
|
||||||
|
@isset($download)
|
||||||
<p class="font-bold text-gray-800 dark:text-gray-200">
|
<p class="font-bold text-gray-800 dark:text-gray-200">
|
||||||
<i class="fa-solid fa-lock-open pr-[4px] text-green-400"></i> 1080p
|
<i class="fa-solid fa-lock-open pr-[4px] text-green-400"></i> 1080p
|
||||||
</p>
|
</p>
|
||||||
@@ -13,13 +15,21 @@
|
|||||||
@foreach ($dlList as $hdl)
|
@foreach ($dlList as $hdl)
|
||||||
@include('modals.partials.download-button')
|
@include('modals.partials.download-button')
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
@include('livewire.partials.torrent-button', ['hentai' => $episode->hentai])
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@include('modals.partials.download-backup')
|
@include('modals.partials.download-backup')
|
||||||
|
@else
|
||||||
|
<p class="text-gray-800 dark:text-gray-200 font-bold">
|
||||||
|
<i class="fa-solid fa-lock pr-[4px] text-red-600"></i> 1080p
|
||||||
|
</p>
|
||||||
|
<p class="text-gray-800 dark:text-gray-200">
|
||||||
|
Unavailable.
|
||||||
|
</p>
|
||||||
|
@endisset
|
||||||
|
|
||||||
@if ($episode->interpolated)
|
@if ($episode->interpolated)
|
||||||
|
@php $download = $episode->getDownloadByType('FHDi'); @endphp
|
||||||
|
@isset($download)
|
||||||
<p class="font-bold text-gray-800 dark:text-gray-200">
|
<p class="font-bold text-gray-800 dark:text-gray-200">
|
||||||
<i class="fa-solid fa-lock-open pr-[4px] text-green-400"></i> 1080p 48fps
|
<i class="fa-solid fa-lock-open pr-[4px] text-green-400"></i> 1080p 48fps
|
||||||
</p>
|
</p>
|
||||||
@@ -29,10 +39,19 @@
|
|||||||
@include('modals.partials.download-button-interpolated')
|
@include('modals.partials.download-button-interpolated')
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
@else
|
||||||
|
<p class="text-gray-800 dark:text-gray-200 font-bold">
|
||||||
|
<i class="fa-solid fa-lock pr-[4px] text-red-600"></i> 1080p 48fps
|
||||||
|
</p>
|
||||||
|
<p class="text-gray-800 dark:text-gray-200">
|
||||||
|
Unavailable.
|
||||||
|
</p>
|
||||||
|
@endisset
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
@php $download = $episode->getDownloadByType('UHD'); @endphp
|
||||||
|
@isset($download)
|
||||||
@if (!Auth::user()->is_patreon)
|
@if (!Auth::user()->is_patreon)
|
||||||
@if (config('hstream.free_downloads'))
|
@if (config('hstream.free_downloads'))
|
||||||
<p class="font-bold text-gray-800 dark:text-gray-200">
|
<p class="font-bold text-gray-800 dark:text-gray-200">
|
||||||
@@ -61,6 +80,14 @@
|
|||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
@else
|
||||||
|
<p class="text-gray-800 dark:text-gray-200 font-bold">
|
||||||
|
<i class="fa-solid fa-lock pr-[4px] text-red-600"></i> 4k
|
||||||
|
</p>
|
||||||
|
<p class="text-gray-800 dark:text-gray-200">
|
||||||
|
Unavailable.
|
||||||
|
</p>
|
||||||
|
@endisset
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
@if ($episode->interpolated_uhd)
|
@if ($episode->interpolated_uhd)
|
||||||
|
@@ -8,6 +8,9 @@
|
|||||||
@foreach ($dlList as $hdl)
|
@foreach ($dlList as $hdl)
|
||||||
@php
|
@php
|
||||||
$download = $hdl->getDownloadByType('FHD');
|
$download = $hdl->getDownloadByType('FHD');
|
||||||
|
@endphp
|
||||||
|
@isset($download)
|
||||||
|
@php
|
||||||
$downloadURL = $dlDomainsBackup[array_rand($dlDomainsBackup)].'/'.$download->url;
|
$downloadURL = $dlDomainsBackup[array_rand($dlDomainsBackup)].'/'.$download->url;
|
||||||
$background = 'bg-green-600';
|
$background = 'bg-green-600';
|
||||||
@endphp
|
@endphp
|
||||||
@@ -20,6 +23,11 @@
|
|||||||
:fill-numbers="$fillNumbers"
|
:fill-numbers="$fillNumbers"
|
||||||
:file-size="$download->getFileSize()"
|
:file-size="$download->getFileSize()"
|
||||||
:background="$background">
|
:background="$background">
|
||||||
|
@else
|
||||||
|
<a class="inline-flex items-center ml-4 px-4 p-4 mt-4 cursor-not-allowed bg-gray-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-rose-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150" id="downloadEpisode" alt="Kekw">
|
||||||
|
<i class="fa-solid fa-download mr-2"></i> Episode {{ $hdl->episode }} (Unavailable)
|
||||||
|
</a>
|
||||||
|
@endisset
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,5 +1,9 @@
|
|||||||
@php
|
@php
|
||||||
$download = $hdl->getDownloadByType('FHD');
|
$download = $hdl->getDownloadByType('FHD');
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
@isset($download)
|
||||||
|
@php
|
||||||
$downloadURL = $dldomains[array_rand($dldomains)].'/'.$download->url;
|
$downloadURL = $dldomains[array_rand($dldomains)].'/'.$download->url;
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
@@ -10,3 +14,8 @@
|
|||||||
:episode-number="$hdl->episode"
|
:episode-number="$hdl->episode"
|
||||||
:fill-numbers="$fillNumbers"
|
:fill-numbers="$fillNumbers"
|
||||||
:file-size="$download->getFileSize()">
|
:file-size="$download->getFileSize()">
|
||||||
|
@else
|
||||||
|
<a class="inline-flex items-center ml-4 px-4 p-4 mt-4 cursor-not-allowed bg-gray-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-rose-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150" id="downloadEpisode" alt="Kekw">
|
||||||
|
<i class="fa-solid fa-download mr-2"></i> Episode {{ $hdl->episode }} (Unavailable)
|
||||||
|
</a>
|
||||||
|
@endisset
|
@@ -1,5 +1,16 @@
|
|||||||
@guest
|
@guest
|
||||||
|
|
||||||
|
@php $download = $episode->getDownloadByType('FHD'); @endphp
|
||||||
|
@isset($download)
|
||||||
@include('modals.partials.download-captcha')
|
@include('modals.partials.download-captcha')
|
||||||
|
@else
|
||||||
|
<p class="text-gray-800 dark:text-gray-200 font-bold">
|
||||||
|
<i class="fa-solid fa-lock pr-[4px] text-red-600"></i> FHD
|
||||||
|
</p>
|
||||||
|
<p class="text-gray-800 dark:text-gray-200">
|
||||||
|
Unavailable.
|
||||||
|
</p>
|
||||||
|
@endisset
|
||||||
|
|
||||||
@if ($episode->interpolated)
|
@if ($episode->interpolated)
|
||||||
<br>
|
<br>
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
<br>
|
<br>
|
||||||
|
@php $download = $episode->getDownloadByType('FHD'); @endphp
|
||||||
|
@isset($download)
|
||||||
<p class="font-bold text-gray-800 dark:text-gray-200">
|
<p class="font-bold text-gray-800 dark:text-gray-200">
|
||||||
<i class="fa-solid fa-lock-open pr-[4px] text-green-400"></i> Subtitles
|
<i class="fa-solid fa-lock-open pr-[4px] text-green-400"></i> Subtitles
|
||||||
</p>
|
</p>
|
||||||
@@ -32,3 +34,11 @@
|
|||||||
@endforeach
|
@endforeach
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
@else
|
||||||
|
<p class="text-gray-800 dark:text-gray-200 font-bold">
|
||||||
|
<i class="fa-solid fa-lock pr-[4px] text-red-600"></i> Subtitles
|
||||||
|
</p>
|
||||||
|
<p class="text-gray-800 dark:text-gray-200">
|
||||||
|
Unavailable.
|
||||||
|
</p>
|
||||||
|
@endisset
|
@@ -12,7 +12,7 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="relative p-1 mb-8 w-full transition duration-300 ease-in-out md:p-2 hover:-translate-y-1 hover:scale-110">
|
class="relative p-1 mb-8 w-full transition duration-300 ease-in-out md:p-2 md:hover:-translate-y-1 md:hover:scale-110">
|
||||||
<a class="hover:text-blue-600" href="{{ route('hentai.index', ['title' => $episode->slug]) }}">
|
<a class="hover:text-blue-600" href="{{ route('hentai.index', ['title' => $episode->slug]) }}">
|
||||||
<img alt="{{ $episode->title }} - {{ $episode->episode }}" loading="lazy" width="400"
|
<img alt="{{ $episode->title }} - {{ $episode->episode }}" loading="lazy" width="400"
|
||||||
class="block relative rounded-lg object-cover object-center aspect-[11/16] z-20 "
|
class="block relative rounded-lg object-cover object-center aspect-[11/16] z-20 "
|
||||||
@@ -20,10 +20,10 @@
|
|||||||
|
|
||||||
@guest
|
@guest
|
||||||
<p
|
<p
|
||||||
class="absolute right-2 top-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute right-1 md:right-2 top-1 md:top-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
{{ $episode->getResolution() }}</p>
|
{{ $episode->getResolution() }}</p>
|
||||||
<p
|
<p
|
||||||
class="absolute left-2 bottom-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute left-1 md:left-2 bottom-1 md:bottom-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
|
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
|
||||||
class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i class="fa-regular fa-comment"></i>
|
class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i class="fa-regular fa-comment"></i>
|
||||||
{{ $episode->commentCount() }}
|
{{ $episode->commentCount() }}
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
@php $problematic = cache()->rememberForever('episodeProblematic'.$episode->id, fn () => $episode->getProblematicTags()); @endphp
|
@php $problematic = cache()->rememberForever('episodeProblematic'.$episode->id, fn () => $episode->getProblematicTags()); @endphp
|
||||||
@if (!empty($problematic))
|
@if (!empty($problematic))
|
||||||
<p
|
<p
|
||||||
class="absolute left-2 top-2 bg-red-700/70 !text-white rounded-br-lg rounded-tl-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute left-1 md:left-2 top-1 md:top-2 bg-red-700/70 !text-white rounded-br-lg rounded-tl-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
<i class="fa-solid fa-triangle-exclamation"></i> {{ $problematic }}
|
<i class="fa-solid fa-triangle-exclamation"></i> {{ $problematic }}
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
@@ -41,20 +41,20 @@
|
|||||||
@auth
|
@auth
|
||||||
@if ($episode->userWatched(auth()->user()->id))
|
@if ($episode->userWatched(auth()->user()->id))
|
||||||
<p
|
<p
|
||||||
class="absolute right-2 top-2 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute right-1 md:right-2 top-1 md:top-2 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
{{ $episode->getResolution() }}</p>
|
{{ $episode->getResolution() }}</p>
|
||||||
<p
|
<p
|
||||||
class="absolute left-2 bottom-2 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute left-1 md:left-2 bottom-1 md:bottom-2 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
|
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
|
||||||
class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i
|
class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i
|
||||||
class="fa-regular fa-comment"></i> {{ $episode->commentCount() }}
|
class="fa-regular fa-comment"></i> {{ $episode->commentCount() }}
|
||||||
</p>
|
</p>
|
||||||
@else
|
@else
|
||||||
<p
|
<p
|
||||||
class="absolute right-2 top-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute right-1 md:right-2 top-1 md:top-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
{{ $episode->getResolution() }}</p>
|
{{ $episode->getResolution() }}</p>
|
||||||
<p
|
<p
|
||||||
class="absolute left-2 bottom-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
class="absolute left-1 md:left-2 bottom-1 md:bottom-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||||
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
|
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
|
||||||
class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i
|
class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i
|
||||||
class="fa-regular fa-comment"></i> {{ $episode->commentCount() }}
|
class="fa-regular fa-comment"></i> {{ $episode->commentCount() }}
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Http\Controllers\ContactController;
|
use App\Http\Controllers\ContactController;
|
||||||
use App\Http\Controllers\DownloadsController;
|
|
||||||
use App\Http\Controllers\HomeController;
|
use App\Http\Controllers\HomeController;
|
||||||
use App\Http\Controllers\PlaylistController;
|
use App\Http\Controllers\PlaylistController;
|
||||||
use App\Http\Controllers\ProfileController;
|
use App\Http\Controllers\ProfileController;
|
||||||
@@ -9,6 +8,7 @@ use App\Http\Controllers\StreamController;
|
|||||||
use App\Http\Controllers\UserController;
|
use App\Http\Controllers\UserController;
|
||||||
use App\Http\Controllers\Api\AdminApiController;
|
use App\Http\Controllers\Api\AdminApiController;
|
||||||
use App\Http\Controllers\Api\DownloadApiController;
|
use App\Http\Controllers\Api\DownloadApiController;
|
||||||
|
use App\Http\Controllers\Api\HentaiApiController;
|
||||||
use App\Http\Controllers\Api\StreamApiController;
|
use App\Http\Controllers\Api\StreamApiController;
|
||||||
use App\Http\Controllers\Api\UserApiController;
|
use App\Http\Controllers\Api\UserApiController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
@@ -22,6 +22,11 @@ use Illuminate\Support\Facades\Route;
|
|||||||
Route::get('/', [HomeController::class, 'index'])->name('home.index');
|
Route::get('/', [HomeController::class, 'index'])->name('home.index');
|
||||||
Route::get('/stats', [HomeController::class, 'stats'])->name('home.stats');
|
Route::get('/stats', [HomeController::class, 'stats'])->name('home.stats');
|
||||||
Route::get('/banned', [HomeController::class, 'banned'])->name('home.banned');
|
Route::get('/banned', [HomeController::class, 'banned'])->name('home.banned');
|
||||||
|
Route::get('/random', [HomeController::class, 'random'])->name('hentai.random');
|
||||||
|
|
||||||
|
// API Endpoint
|
||||||
|
Route::get('/v1/hentai-list', [HentaiApiController::class, 'index'])->name('api.hentai.index');
|
||||||
|
Route::get('/v1/monthly-views', [HentaiApiController::class, 'getMonthlyViews'])->name('api.hentai.monthly');
|
||||||
|
|
||||||
// Stream Page
|
// Stream Page
|
||||||
Route::get('/hentai/{title}', [StreamController::class, 'index'])->name('hentai.index');
|
Route::get('/hentai/{title}', [StreamController::class, 'index'])->name('hentai.index');
|
||||||
@@ -123,10 +128,6 @@ Route::group(['middleware' => ['auth', 'auth.admin']], function () {
|
|||||||
Route::get('/admin/tags/{episode_id}', [AdminApiController::class, 'getEpisodeTags'])->name('admin.tags.episode');
|
Route::get('/admin/tags/{episode_id}', [AdminApiController::class, 'getEpisodeTags'])->name('admin.tags.episode');
|
||||||
Route::get('/admin/studio/{episode_id}', [AdminApiController::class, 'getEpisodeStudio'])->name('admin.studio.episode');
|
Route::get('/admin/studio/{episode_id}', [AdminApiController::class, 'getEpisodeStudio'])->name('admin.studio.episode');
|
||||||
|
|
||||||
// Torrents
|
|
||||||
Route::get('/admin/add-torrent/{hentai_id}', [App\Http\Controllers\Admin\TorrentController::class, 'index'])->name('admin.add.torrentpage');
|
|
||||||
Route::post('/admin/add-torrent', [App\Http\Controllers\Admin\TorrentController::class, 'store'])->name('admin.add.torrent');
|
|
||||||
|
|
||||||
// Subtitles
|
// Subtitles
|
||||||
Route::get('/admin/subtitles/{episode_id}', [AdminApiController::class, 'getSubtitles'])->name('admin.subtitles');
|
Route::get('/admin/subtitles/{episode_id}', [AdminApiController::class, 'getSubtitles'])->name('admin.subtitles');
|
||||||
Route::post('/admin/add-new-subtitle', [App\Http\Controllers\Admin\SubtitleController::class, 'store'])->name('admin.add.new.subtitle');
|
Route::post('/admin/add-new-subtitle', [App\Http\Controllers\Admin\SubtitleController::class, 'store'])->name('admin.add.new.subtitle');
|
||||||
|
@@ -20,7 +20,8 @@ export default defineConfig({
|
|||||||
'resources/js/user-blacklist.js',
|
'resources/js/user-blacklist.js',
|
||||||
'resources/js/admin-edit.js',
|
'resources/js/admin-edit.js',
|
||||||
'resources/js/admin-subtitles.js',
|
'resources/js/admin-subtitles.js',
|
||||||
'resources/js/preview.js'
|
'resources/js/preview.js',
|
||||||
|
'resources/js/stats.js'
|
||||||
],
|
],
|
||||||
refresh: true,
|
refresh: true,
|
||||||
}),
|
}),
|
||||||
|
Reference in New Issue
Block a user