Compare commits

..

23 Commits

Author SHA1 Message Date
444feac1e0 Use redirect for random button to save database queries 2025-10-09 12:55:24 +02:00
c034c94db5 Add padding to comments on home page 2025-10-09 12:38:54 +02:00
ca52584da9 Cache random hentai row for 5 minutes 2025-10-09 12:38:17 +02:00
dca4924e9a Add v2 re-release discord webhook 2025-10-08 20:01:06 +02:00
9ad7c7afc2 Fix incorrect cache key 2025-10-08 19:50:55 +02:00
6c8d34b030 Fix vite build 2025-10-08 19:38:54 +02:00
35a0d61437 Add censored discord notification 2025-10-08 18:32:08 +02:00
725a441d9e Add discord notification for v2 releases 2025-10-08 17:41:10 +02:00
96a9019eba Temp fix call on null for removed downloads (dmca) 2025-10-08 17:24:14 +02:00
e2497867f0 Display login message 2025-10-08 17:05:31 +02:00
a6c47cf2e6 Remove unused Controller 2025-10-08 16:53:51 +02:00
fffa320c08 Add monthly views chart 2025-10-08 16:52:40 +02:00
2880547f3e Fix mobile offset episode thumbnail / cover 2025-10-08 13:00:16 +02:00
b5dbf24e91 Update node packages 2025-10-08 12:42:35 +02:00
43cf5db6c9 Update composer packages 2025-10-08 12:04:12 +02:00
9e0042b09f Add stats and current git commit to footer 2025-10-08 11:44:40 +02:00
e717b2bd07 Temp fix call on null for removed downloads (dmca) 2025-10-07 23:46:17 +02:00
bbbc4ac329 Add domain 2025-10-07 22:38:20 +02:00
55739a21b5 Add hentai list api endoint 2025-10-02 21:26:09 +02:00
bc193c7141 Remove torrents system 2025-09-22 13:34:52 +02:00
c0a22e875c Fix duplicate download entries and add constraint 2025-09-22 00:18:22 +02:00
4697073e9f Replace old download search with new patreon file search 2025-09-21 23:49:58 +02:00
9be33db14f Improve patreon filebrowser 2025-09-21 23:10:53 +02:00
49 changed files with 3265 additions and 2108 deletions

View File

@@ -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

View File

@@ -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
View 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';
}
});
}
}

View File

@@ -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', [

View File

@@ -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();

View File

@@ -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');
}
}

View 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);
}
}

View File

@@ -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');
}
}

View File

@@ -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()
]); ]);
} }

View File

@@ -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;
} }
} }
} }

View File

@@ -1,60 +0,0 @@
<?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

@@ -6,7 +6,7 @@ use App\Models\Downloads;
use Livewire\Component; use Livewire\Component;
use Livewire\WithPagination; use Livewire\WithPagination;
class DownloadsPatreon extends Component class DownloadsSearch extends Component
{ {
use WithPagination; use WithPagination;
@@ -24,6 +24,18 @@ class DownloadsPatreon extends Component
$this->resetPage(); $this->resetPage();
} }
public function clicked($downloadId)
{
$download = Downloads::find($downloadId);
if (!$download) {
return;
}
$download->count++;
$download->save();
cache()->forget("episode_{$download->episode->id}_download_{$download->type}");
}
public function render() public function render()
{ {
$orderby = 'created_at'; $orderby = 'created_at';
@@ -60,12 +72,12 @@ class DownloadsPatreon extends Component
} }
$downloads = Downloads::when($this->fileSearch != '', fn ($query) => $query->where('url', 'like', '%'.$this->fileSearch.'%')) $downloads = Downloads::when($this->fileSearch != '', fn ($query) => $query->where('url', 'like', '%'.$this->fileSearch.'%'))
->where('size', '>', 0) ->when(!auth()->user()->is_patreon, fn ($query) => $query->whereIn('type', ['FHD', 'FHDi']))
->where(fn ($q) => $q->where('type', '=', 'UHD')->orWhere('type', '=', 'UHDi')) ->whereNotNull('size')
->orderBy($orderby, $orderdirection) ->orderBy($orderby, $orderdirection)
->paginate(20); ->paginate(20);
return view('livewire.downloads-patreon', [ return view('livewire.downloads-search', [
'downloads' => $downloads, 'downloads' => $downloads,
'query' => $this->fileSearch, 'query' => $this->fileSearch,
]); ]);

View File

@@ -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;

View File

@@ -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',
];
}

View File

@@ -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",

2567
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -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'),
], ],
/* /*

View File

@@ -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)

View File

@@ -0,0 +1,54 @@
<?php
use App\Models\Downloads;
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
{
# Delete entries with "#" as URL
Downloads::where('url', '#')->forceDelete();
# Remove duplicate entries
$duplicates = DB::table('downloads')
->select('episode_id', 'type', DB::raw('COUNT(*) as count'))
->groupBy('episode_id', 'type')
->having('count', '>', 1)
->get();
foreach ($duplicates as $duplicate) {
// Find all rows for this episode_id and type
$rows = DB::table('downloads')
->where('episode_id', $duplicate->episode_id)
->where('type', $duplicate->type)
->orderBy('count', 'desc') // Order by count to delete the ones with the lower count
->get();
// Delete the rows with lower counts, keeping the one with the highest count
$rows->skip(1)->each(function ($row) {
DB::table('downloads')->where('id', $row->id)->delete();
});
}
Schema::table('downloads', function (Blueprint $table) {
$table->unique(['episode_id', 'type']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('downloads', function (Blueprint $table) {
$table->dropUnique(['episode_id', 'type']);
});
}
};

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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",

View File

@@ -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
View 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);
});

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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() }}

View File

@@ -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>

View File

@@ -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])

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -67,53 +67,61 @@
<!-- Header --> <!-- Header -->
<div <div
class="flex bg-white/30 dark:bg-neutral-950/40 backdrop-blur font-medium dark:border-neutral-500 border-b rounded-tl-lg rounded-tr-lg"> class="flex bg-white/30 dark:bg-neutral-950/40 backdrop-blur font-medium dark:border-neutral-500 border-b rounded-tl-lg rounded-tr-lg">
<div class="flex-1 px-6 py-4">Title</div> <div class="flex-1 px-6 py-4 hidden sm:block">Title</div>
<div class="w-28 px-6 py-4">Size</div> <div class="w-28 px-6 py-4 hidden sm:block">Size</div>
<div class="w-32 px-6 py-4">Date</div> <div class="w-32 px-6 py-4 hidden sm:block">Date</div>
<div class="w-32 px-6 py-4">Download</div> <div class="w-32 px-6 py-4">Download</div>
</div> </div>
@php
$dldomains = config('hstream.download_domain');
$dlpdomains = config('hstream.download_domain_4k');
@endphp
<!-- Rows --> <!-- Rows -->
@foreach ($downloads as $download) @foreach ($downloads as $download)
@php @php
$title = explode('/', $download->url)[2]; $title = explode('/', $download->url)[2];
$bytes = $download->size;
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$power = $bytes > 0 ? floor(log($bytes, 1024)) : 0;
$fileSize = round($bytes / pow(1024, $power), 2) . ' ' . $units[$power];
@endphp @endphp
<div <div
class="flex items-center border-b bg-white/70 dark:bg-neutral-950/80 dark:border-zinc-700 hover:bg-white/80 dark:hover:bg-neutral-950/90"> class="flex flex-col sm:flex-row items-center border-b bg-white dark:bg-neutral-950 dark:border-zinc-700 hover:bg-zinc-100 dark:hover:bg-neutral-800">
<!-- Title --> <!-- Title -->
<div class="flex flex-1 items-center space-x-2 px-3 py-2"> <div class="flex flex-1 items-center space-x-2 px-3 py-2">
<span class="cursor-default">
{{ $title }} {{ $title }}
</span>
</div> </div>
<!-- Size --> <!-- Size -->
<div class="w-28 whitespace-nowrap"> <div class="w-28 whitespace-nowrap flex">
{{ $fileSize }} <span class="block sm:hidden">
Size:
</span>
{{ $download->getFileSize() }}
</div> </div>
<!-- Date --> <!-- Date -->
<div class="w-32 whitespace-nowrap"> <div class="w-32 whitespace-nowrap flex">
<span class="block sm:hidden">
Date:
</span>
{{ $download->created_at->format('Y-m-d') }} {{ $download->created_at->format('Y-m-d') }}
</div> </div>
<!-- Download --> <!-- Download -->
<div class="w-32 whitespace-nowrap"> <div class="w-32 whitespace-nowrap">
@php @php
$dlpdomains = config('hstream.download_domain_4k'); if (in_array($download->type, ['FHD', 'FHDi'])) {
$downloadURL = $dldomains[array_rand($dldomains)].'/'.$download->url;
} else {
$now = \Illuminate\Support\Carbon::now(); $now = \Illuminate\Support\Carbon::now();
$expire = \Illuminate\Support\Facades\Crypt::encryptString($now->addHours(6)); $expire = \Illuminate\Support\Facades\Crypt::encryptString($now->addHours(6));
$file = \Illuminate\Support\Facades\Crypt::encryptString('hentai/'.$download->url); $file = \Illuminate\Support\Facades\Crypt::encryptString('hentai/'.$download->url);
$downloadURL = $dlpdomains[array_rand($dlpdomains)].'/download/'.$file.'/'.$expire; $downloadURL = $dlpdomains[array_rand($dlpdomains)].'/download/'.$file.'/'.$expire;
}
@endphp @endphp
<a href="{{ $downloadURL }}" download> <a href="{{ $downloadURL }}" wire:click="clicked({{ $download->id }})" download>
<button id="dl-{{ $download->id }}" <button id="dl-{{ $download->id }}"
class="group rounded-md bg-transparent border-[1px] border-white/20 shadow dark:text-white text-blac cursor-pointer flex justify-between items-center overflow-hidden transition-all w-[110px] h-[35px]"> class="group rounded-md bg-transparent border-[1px] border-white/20 shadow dark:text-white text-blac cursor-pointer flex justify-between items-center overflow-hidden transition-all w-[110px] h-[32px] mt-1 mb-1">
<div <div
class="relative w-12 h-[40px] bg-transparent dark:text-white text-black flex justify-center items-center transition-all"> class="relative w-12 h-[40px] bg-transparent dark:text-white text-black flex justify-center items-center transition-all">
<svg class="w-4 h-4 transition-all group-hover:-translate-y-1" <svg class="w-4 h-4 transition-all group-hover:-translate-y-1"

View File

@@ -1,146 +0,0 @@
<div class="py-3">
<div class="mx-auto sm:px-6 lg:px-8 space-y-6 max-w-[100%] xl:max-w-[80%] 2xl:max-w-[50%]">
<!-- Search Filter -->
<div class="p-4 sm:p-8 bg-white dark:bg-neutral-800 shadow sm:rounded-lg">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<!-- Title -->
<div>
<label for="live-search"
class="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white">Search</label>
<div class="relative right-2 left-0 sm:left-2 transition-all">
<div class="absolute inset-y-0 left-2 flex items-center pl-3 pointer-events-none">
<svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true"
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
</svg>
</div>
<input wire:model.live.debounce.600ms="search" type="search" id="live-search"
class="block w-full p-4 pl-10 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"
placeholder="{{ __('search.search-hentai') }}" required>
<div class="absolute right-0 top-[11px]" wire:loading>
<svg aria-hidden="true"
class="inline w-8 h-8 mr-2 text-gray-200 animate-spin dark:text-gray-600 fill-pink-600"
viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
fill="currentColor" />
<path
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
fill="currentFill" />
</svg>
</div>
</div>
</div>
<!-- Ordering -->
<div>
<div class="relative right-2 left-0 sm:left-2 transition-all">
<div class="absolute inset-y-0 left-2 flex items-center pl-3 pointer-events-none">
<i class="fa-solid fa-sort text-gray-500 dark:text-gray-400"></i>
</div>
<select wire:model.live="order"
class="block w-full p-4 pl-10 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">
<option value="az">A-Z</option>
<option value="za">Z-A</option>
</select>
</div>
</div>
</div>
<div class="float-right text-gray-900 dark:text-white">
<input type="checkbox" wire:model.live="withTorrents">
Show only with Torrent
</div>
</div>
</div>
@php $dldomains = config('hstream.download_domain'); @endphp
<div class="relative pt-5 mx-auto sm:px-6 lg:px-8 space-y-6 text-gray-900 dark:text-white xl:max-w-[95%] 2xl:max-w-[60%]" wire:keydown.right.window="nextPage" wire:keydown.left.window="previousPage">
<div class="flex flex-col">
<div class="overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="inline-block min-w-full py-2 sm:px-6 lg:px-8">
<div class="overflow-hidden">
<!-- Desktop -->
<table class="min-w-full text-left text-sm font-light collapse md:visible">
<thead class="border-b font-medium dark:border-neutral-500 bg-white dark:bg-neutral-800 shadow sm:rounded-lg">
<tr>
<th scope="col" class="px-6 py-4">Title</th>
<th scope="col" class="px-6 py-4">Download</th>
<th scope="col" class="px-6 py-4">Torrent</th>
</tr>
</thead>
<tbody>
@foreach($hentai as $h)
@php $episode = $h->episodes->first(); @endphp
<tr class="border-b dark:border-neutral-500">
<td class="whitespace-nowrap px-6 py-4">
{{ $episode->title }}
@if ($episode->title != $episode->title_jpn)
<br>
{{ $episode->title_jpn }}
@endif
@auth
@if(Auth::user()->is_admin)
<br>
<a href="{{ route('admin.add.torrentpage', ['hentai_id' => $h->id]) }}" target="_blank">Add Torrent</a>
@endif
@endauth
</td>
<td class="whitespace-nowrap px-6 py-4">
@foreach($h->episodes as $episode)
@include('livewire.partials.download-button', ['hdl' => $episode])
@endforeach
</td>
<td class="whitespace-nowrap px-6 py-4">
@include('livewire.partials.torrent-button', ['hentai' => $h])
</td>
</tr>
@endforeach
</tbody>
</table>
<!-- Mobile -->
<table class="min-w-full text-left text-sm font-light visible md:collapse">
<thead class="font-medium">
<tr>
<th scope="col" class="px-6 py-4"></th>
</tr>
</thead>
<tbody>
@foreach($hentai as $h)
@php $episode = $h->episodes->first(); @endphp
<tr class="border-b dark:border-neutral-500">
<td class="px-2 py-4 grid grid-flow-row">
{{ $episode->title }}
@if ($episode->title != $episode->title_jpn)
<br>
{{ $episode->title_jpn }}
@endif
<br>
<div class="flex flex-row flex-wrap">
@foreach($h->episodes as $episode)
@include('livewire.partials.download-button', ['hdl' => $episode])
@endforeach
@include('livewire.partials.torrent-button', ['hentai' => $h])
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
{{ $hentai->links('pagination::tailwind') }}
</div>
</div>

View File

@@ -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>

View File

@@ -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

View File

@@ -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)

View File

@@ -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>

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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() }}

View File

@@ -1,4 +0,0 @@
<x-app-layout>
@include('user.partials.background')
@livewire('downloads-patreon')
</x-app-layout>

View File

@@ -1,3 +1,4 @@
<x-app-layout> <x-app-layout>
@livewire('downloads') @include('user.partials.background')
@livewire('downloads-search')
</x-app-layout> </x-app-layout>

View File

@@ -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');
@@ -78,9 +83,6 @@ Route::middleware('auth')->group(function () {
// Download Page // Download Page
Route::get('/download-search', [HomeController::class, 'downloadSearch'])->name('download.search'); Route::get('/download-search', [HomeController::class, 'downloadSearch'])->name('download.search');
// Download Page for Patreon Subscribers
Route::get('/files', [DownloadsController::class, 'index'])->name('files.index');
}); });
Route::get('/user/{username}', [UserController::class, 'index'])->name('user.index'); Route::get('/user/{username}', [UserController::class, 'index'])->name('user.index');
@@ -126,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');

View File

@@ -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,
}), }),