Files
hstream/app/Models/Episode.php
2025-09-18 15:31:27 +02:00

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