216 lines
5.4 KiB
PHP
216 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Models\Downloads;
|
|
use App\Models\PopularMonthly;
|
|
use App\Models\PopularWeekly;
|
|
use App\Models\PopularDaily;
|
|
|
|
use Conner\Tagging\Taggable;
|
|
use Laravelista\Comments\Commentable;
|
|
use Maize\Markable\Markable;
|
|
use Maize\Markable\Models\Like;
|
|
|
|
use Spatie\Sitemap\Contracts\Sitemapable;
|
|
use Spatie\Sitemap\Tags\Url;
|
|
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
|
|
class Episode extends Model implements Sitemapable
|
|
{
|
|
use Commentable, Markable, Taggable;
|
|
use HasFactory;
|
|
|
|
protected static $marks = [
|
|
Like::class
|
|
];
|
|
|
|
/**
|
|
* Get the studio for the Hentai.
|
|
*/
|
|
public function studio(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Studios::class, 'studios_id');
|
|
}
|
|
|
|
/**
|
|
* Get the hentai for the episode.
|
|
*/
|
|
public function hentai(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Hentai::class, 'hentai_id');
|
|
}
|
|
|
|
/**
|
|
* Get the subtitles for the episode.
|
|
*/
|
|
public function subtitles(): HasMany
|
|
{
|
|
return $this->hasMany(EpisodeSubtitle::class);
|
|
}
|
|
|
|
/**
|
|
* Has a Gallery.
|
|
*/
|
|
public function gallery(): HasMany
|
|
{
|
|
return $this->hasMany(Gallery::class);
|
|
}
|
|
|
|
/**
|
|
* Has many Downloads.
|
|
*/
|
|
public function downloads(): HasMany
|
|
{
|
|
return $this->hasMany(Downloads::class);
|
|
}
|
|
|
|
/**
|
|
* Increment View Count.
|
|
*/
|
|
public function incrementViewCount(): bool
|
|
{
|
|
$this->view_count++;
|
|
return $this->save();
|
|
}
|
|
|
|
/**
|
|
* Increment Popular Count.
|
|
*/
|
|
public function incrementPopularCount(): void
|
|
{
|
|
PopularDaily::create(['episode_id' => $this->id]);
|
|
PopularWeekly::create(['episode_id' => $this->id]);
|
|
PopularMonthly::create(['episode_id' => $this->id]);
|
|
}
|
|
|
|
/**
|
|
* Get cached view count
|
|
*/
|
|
public function viewCount(): int
|
|
{
|
|
return cache()->remember('episodeViews' . $this->id, 300, fn() => $this->view_count);
|
|
}
|
|
|
|
/**
|
|
* Get view count in a human readable way
|
|
*/
|
|
public function viewCountFormatted(): string
|
|
{
|
|
if ($this->viewCount() < 1000) {
|
|
return $this->viewCount();
|
|
}
|
|
|
|
$units = ['k', 'M'];
|
|
$index = floor(log($this->viewCount(), 1000));
|
|
$shortNumber = $this->viewCount() / pow(1000, $index);
|
|
|
|
return round($shortNumber, 0) . $units[$index - 1];
|
|
}
|
|
|
|
/**
|
|
* Get cached like count
|
|
*/
|
|
public function likeCount(): int
|
|
{
|
|
return cache()->remember('episodeLikes' . $this->id, 300, fn() => $this->likes->count());
|
|
}
|
|
|
|
/**
|
|
* Get cached comment count
|
|
*/
|
|
public function commentCount(): int
|
|
{
|
|
return cache()->remember('episodeComments' . $this->id, 300, fn() => $this->comments->count());
|
|
}
|
|
|
|
public function getProblematicTags(): string
|
|
{
|
|
$problematicTags = ['Gore', 'Scat', 'Horror'];
|
|
$problematicResults = '';
|
|
foreach ($problematicTags as $pTag) {
|
|
if (! $this->tags->contains('name', $pTag)) {
|
|
continue;
|
|
}
|
|
|
|
if (! empty($problematicResults)) {
|
|
$problematicResults .= ' + ';
|
|
}
|
|
|
|
$problematicResults .= $pTag;
|
|
}
|
|
return $problematicResults;
|
|
}
|
|
|
|
/**
|
|
* Check if episode contains loli / shota tag
|
|
*/
|
|
public function isLoliOrShota(): bool
|
|
{
|
|
$problematicTags = ['Loli', 'Shota'];
|
|
|
|
return Cache::remember(
|
|
"episode:{$this->id}:has_problematic_tags",
|
|
now()->addMinutes(1440),
|
|
fn () => $this->tags->pluck('name')->intersect($problematicTags)->isNotEmpty()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* If episode has machine translated subtitles
|
|
*/
|
|
public function hasAutoTrans(): bool
|
|
{
|
|
return cache()->remember('mt' . $this->id, 900, fn() => $this->subtitles()->exists());
|
|
}
|
|
|
|
public function is48Fps(): bool
|
|
{
|
|
return cache()->remember('48fps' . $this->id, 900, fn() => $this->interpolated);
|
|
}
|
|
|
|
public function isUHD48Fps(): bool
|
|
{
|
|
return cache()->remember('48fpsUHD' . $this->id, 900, fn() => $this->interpolated_uhd);
|
|
}
|
|
|
|
public function getResolution(): string
|
|
{
|
|
if ($this->isUHD48Fps()) {
|
|
return '4k | 4k 48fps | FHD 48fps';
|
|
}
|
|
|
|
return $this->is48Fps() ? '4k | FHD 48fps' : '4k';
|
|
}
|
|
|
|
public function userWatched(int $user_id): bool
|
|
{
|
|
return cache()->remember('user' . $user_id . 'watched' . $this->id, 300, fn() => Watched::where('user_id', $user_id)->where('episode_id', $this->id)->exists());
|
|
}
|
|
|
|
public function watched(): HasMany
|
|
{
|
|
return $this->hasMany(Watched::class);
|
|
}
|
|
|
|
public function getDownloadByType(string $type): Downloads | null
|
|
{
|
|
$cacheKey = "episode_{$this->id}_download_{$type}";
|
|
return Cache::remember($cacheKey, now()->addMinutes(10), function () use ($type) {
|
|
return $this->downloads()->where('type', $type)->first();
|
|
});
|
|
}
|
|
|
|
public function toSitemapTag(): Url | string | array
|
|
{
|
|
return Url::create(route('hentai.index', $this->slug))
|
|
->setLastModificationDate(Carbon::create($this->created_at));
|
|
}
|
|
}
|