96 'Content-Type' => 'application/json;charset=utf-8',
97 'Authorization' => sprintf('Bearer %s', Configurator::$instance->get('tmdb'))
100 // Append language preference to headers to avoid adult content
101 $headers['Accept-Language'] = 'en-US'; // Example: Set language preference to English
103 // Make the GET request with headers
104 $resp = EasyCurl::setHeaders($headers)->get(...$args);
106 // Check if response status is not 200 OK
107 if ($resp->getStatus() != 200) {
108 throw new TmdbClientException('Tmdb Client Error: ' . $resp->getBody(), $resp->getStatus());
111 // Check for adult content in response (assuming TMDB API supports such filtering)
112 $jsonResponse = json_decode($resp->getBody(), true);
119 public function getGenre(): array
121 return $this->request('genre/' . $this->getType() . '/list')['genres'] ?? [];
338 $perPage = 20; // Number of items per page
339 $seenVideos = []; // Array to track seen video ids
341 // Function to check if the video has a poster or backdrop and is not adult
342 $isValidVideo = function($video) {
343 return (isset($video['poster_path']) || isset($video['backdrop_path'])) && (!isset($video['adult']) || $video['adult'] === false);
346 // Loop until we have at least 20 videos or no more results are returned
347 while (count($videos) < $perPage) {
348 $relatedVideos = $this->request($this->getType() . '/' . $id . '/recommendations', ['page' => $page])['results'] ?? [];
350 if (empty($relatedVideos)) {
351 break; // No more results
354 foreach ($relatedVideos as $video) {
355 if (count($videos) >= $perPage) {
358 if ($isValidVideo($video) && !in_array($video['id'], $seenVideos)) {
360 $seenVideos[] = $video['id'];
88 $tmdb = TmdbClient::create('tv');
89 $cache = cache('tmdb.tv');
91 $viewModel = new TmdbCollection(
93 $cache->load('genres', fn () => $tmdb->getGenre())
98 $id = substr($slug, strrpos($slug, '-') + 1);
100 $viewModel->addToCollection('similar', TmdbClient::create('tv')->getRelatedVideos($id));
102 return view('video', [
103 'video' => $this->findOrFail($id, 'tv'),
104 'similar' => $viewModel->cut('similar')
109 ->addToCollection('airing-today', $cache->load('airingtoday', fn () => $tmdb->getAiringToday(), '12 hours'))
110 ->addToCollection('popular', $cache->load('popular', fn () => $tmdb->getPopular(), '12 hours'))
111 ->addToCollection('this-week', $cache->load('ontheair', fn () => $tmdb->getOnTheAir(), '12 hours'))
112 ->addToCollection('toprated', $cache->load('toprated', fn () => $tmdb->getTopRated(), '12 hours'));
68 (is_string($callback) && function_exists($callback))
69 || (is_object($callback) && ($callback instanceof Closure))
71 || (is_array($callback) && method_exists($callback[0], $callback[1]));
74 public static function load($callback, ...$params)
76 if (!self::exists($callback)) {
77 throw new UndefinedMethod((is_array($callback) ? (!is_string($callback[0]) ? get_class($callback[0]) : (string) $callback[0]) . '->' . $callback[1] : $callback) . '() does not exists');
80 return call_user_func($callback, ...array_values($params));
83 public static function create(string $class, ...$args)
85 if (!class_exists($class)) {
86 throw new UndefinedClass('Class: ' . $class . ' does not exists');
89 return new $class(...array_values($args));
92 public static function name($callback): string
107 // set new callback method
108 $route->setCallback([$route->getCallback()[0], $call_method]);
111 // escape grouped/nested named parameter
112 $route->setParameters($this->escapeNestedParameters($route->getParameters()));
114 // trigger route middleware event
115 $this->triggerEvent(IRoute::EVENTS['callback'], $route);
117 // load router callback
118 return CallbackHandler::load(
119 $route->getCallback(),
120 ...CallbackHandler::reflect(
121 $route->getParameters(),
122 $route->getCallback(),
123 array_merge($this->getReflectionParameters(), [$route])
128 public function callMiddlewares($middlewares): void
130 foreach ((array) $middlewares as $middleware) {
131 $class = CallbackHandler::create($middleware);
90 // utilize method required paramiters
91 $route->setParameters(
92 $this->applyFilters(self::FILTER['parameters'], $this->utilizeRouteParam($matches, $route))
98 // create route dispatcher
99 $dispatcher = new RouteDispatcher($this);
101 // dispatch route callback
102 return $dispatcher->dispatch($route);
107 if (isset($this->fallback) && CallbackHandler::exists($this->fallback)) {
108 CallbackHandler::load($this->fallback);
111 // not found any route for this path
112 throw new NotFoundException('the route does not matched..');
97 public static function run(): void
99 // load application initial kernels
100 self::$app->loadKernels('boot');
102 // render router result
103 echo self::$app->router->resolve();
105 // load application initial kernels
106 self::$app->loadKernels('shutdown');
110 * Check Anu Component added to the Application
114 public static function hasComponent(string $key): bool
116 return isset(self::$app->components[$key]);
14 'tmp_dir' => config('app.tmp_dir'),
15 'except' => ['/admin/*', '/embed/*', '/search/*'],
18 // serve from cache if production mode
23 // create a new application instance for this http request
24 Application::create(__DIR__)
25 ->registerKernel(App\Http\Kernels\AppKernel::class)
28 // stop the application execution process