'hentai-1080p/', 'FHDi' => 'hentai-1080p/', 'UHD' => 'hentai/', 'UHDi' => 'hentai/', ]; private const STREAM_PREFIX = 'hentai-stream/'; private const CACHE_TTL = 300; public function validateDownload(string $type, string $url, bool $fresh = false): array { $path = self::DOWNLOAD_PREFIX[$type].ltrim($url, '/'); $domains = config('hstream.download_domain_4k'); return $this->checkMirrors($domains, [$path], $fresh); } public function validateStream(string $baseurl, int $episodeCount, bool $fresh = false, int $episodeNumber = 1): array { $domains = config('hstream.download_domain_4k'); // Validate the base directory, plus the episode manifest as a sanity check. $paths = [self::STREAM_PREFIX.rtrim($baseurl, '/')]; if ($episodeCount >= 1) { $paths[] = self::STREAM_PREFIX.rtrim($baseurl, '/').'/E'.str_pad($episodeNumber, 2, '0', STR_PAD_LEFT).'/720/manifest.mpd'; } return $this->checkMirrors($domains, $paths, $fresh); } private function checkMirrors(array $domains, array $paths, bool $fresh = false): array { $cacheKey = 'cdncheck:'.sha1(serialize([$domains, $paths])); if ($fresh) { Cache::forget($cacheKey); } return Cache::remember($cacheKey, self::CACHE_TTL, fn () => $this->runChecks($domains, $paths)); } private function runChecks(array $domains, array $paths): array { $entries = []; foreach ($domains as $domain) { foreach ($paths as $path) { $entries[] = ['domain' => $domain, 'path' => $path]; } } try { $responses = Http::pool(function ($pool) use ($entries) { foreach ($entries as $entry) { $pool->timeout(4) ->withHeaders(['Accept' => 'application/json']) ->get($entry['domain'].'/check/'.$this->tokenize($entry['path']).'/'.$this->tokenize(now()->addHours(6))); } }); } catch (\Throwable $e) { $mirrors = []; foreach ($entries as $entry) { $mirrors[$entry['domain']][$entry['path']] = false; } return [ 'valid' => false, 'mirrors' => $mirrors, 'size' => null, ]; } $mirrors = []; $allValid = true; $firstSize = null; foreach ($entries as $index => $entry) { $response = $responses[$index]; $ok = $response instanceof Response && $response->ok() && $response->json('valid') === true; $mirrors[$entry['domain']][$entry['path']] = $ok; if (! $ok) { $allValid = false; } elseif ($firstSize === null) { $firstSize = $response->json('size'); } } return [ 'valid' => $allValid, 'mirrors' => $mirrors, 'size' => $allValid ? $firstSize : null, ]; } private function tokenize(string $value): string { return urlencode(Crypt::encryptString($value)); } }