diff --git a/fuel/app/classes/controller/home.php b/fuel/app/classes/controller/home.php index 5479587..ba3d383 100755 --- a/fuel/app/classes/controller/home.php +++ b/fuel/app/classes/controller/home.php @@ -17,10 +17,14 @@ class Controller_Home extends Controller_Template $user = Session::get('user'); $sessionServer = Session::get('server'); - if(!$user) + if(is_null($user)) Response::redirect('/login'); - $server = $sessionServer ? Model_Server::find_by_pk($sessionServer->id) : Model_Server::find_one_by('user_id', $user->id); + $server = $sessionServer ? Model_Server::find_by_pk($sessionServer->id) : (Model_Server::find_one_by('user_id', $user->id) ?: Model_Server::find_by([ + ['online', '=', 1], + ['disable', '=', 0], + ], null, null, 10)[0] + ); if(!$server) Response::redirect('/login'); diff --git a/fuel/app/classes/controller/rest/browse.php b/fuel/app/classes/controller/rest/browse.php index 8658571..675a8db 100644 --- a/fuel/app/classes/controller/rest/browse.php +++ b/fuel/app/classes/controller/rest/browse.php @@ -117,7 +117,7 @@ class Controller_Rest_Browse extends Controller_Rest if(!$library) return $this->response(array('error' => true, 'message' => 'No library found!')); - return Model_Library::getSectionsContent($server, $library); + return Model_Library::getLibraryContents($server, $library); } public function get_seasons() diff --git a/fuel/app/classes/controller/rest/movie.php b/fuel/app/classes/controller/rest/movie.php index 8a84d32..fb788c0 100644 --- a/fuel/app/classes/controller/rest/movie.php +++ b/fuel/app/classes/controller/rest/movie.php @@ -26,7 +26,7 @@ class Controller_Rest_Movie extends Controller_Rest else $episodes = [$movie]; - $view = View::forge('stream/index'); + $view = View::forge('player/index'); $view->set('user_settings', $user_settings); $view->set('movie', $movie); diff --git a/fuel/app/classes/model/library.php b/fuel/app/classes/model/library.php index 4ec58ba..c83b109 100644 --- a/fuel/app/classes/model/library.php +++ b/fuel/app/classes/model/library.php @@ -95,7 +95,7 @@ class Model_Library extends Model_Overwrite 'server_id' => $server->id, 'name' => $library['@attributes']['title'], 'type' => $library['@attributes']['type'], - 'updatedAt' => $library['@attributes']['updatedAt'], + 'updatedAt' => time(), 'createdAt' => $library['@attributes']['createdAt'], 'scannedAt' => $library['@attributes']['scannedAt'] )); @@ -120,7 +120,7 @@ class Model_Library extends Model_Overwrite * @return bool * @throws FuelException */ - public static function getSectionsContent($server, $library) + public static function getLibraryContents($server, $library) { $curl = Request::forge(($server->https ? 'https' : 'http').'://' . $server->url . ($server->port? ':' . $server->port : '') . '/library/sections/' . $library->plex_key . '/all?X-Plex-Token=' . $server->token, 'curl'); diff --git a/fuel/app/classes/model/movie.php b/fuel/app/classes/model/movie.php index 255d9e3..22473ed 100644 --- a/fuel/app/classes/model/movie.php +++ b/fuel/app/classes/model/movie.php @@ -44,6 +44,7 @@ class Model_Movie extends Model_Overwrite private $_season = null; private $_tv_show = null; private $_library = null; + /** @var Model_Server */ private $_server = null; public $trailer = null; @@ -82,6 +83,9 @@ class Model_Movie extends Model_Overwrite return $this->_library; } + /** + * @return Model_Server + */ public function getServer() { if(!$this->_server) { @@ -463,20 +467,6 @@ class Model_Movie extends Model_Overwrite return $movies_id_array; } - public static function getMovieMetadata($server, $movie) - { - /*$curl = Request::forge('http://' . $server->url . ($server->port ? ':' . $server->port : '') . $movie->plex_key . '?X-Plex-Token=' . $server->token, 'curl'); - $curl->execute(); - - if ($curl->response()->status !== 200) - return false; - - $media = Format::forge($curl->response()->body, 'xml')->to_array(); - - if(isset($movies['Video'])) - $this->getMovies($server, $movies['Video']);*/ - } - public static function getThirtyLastedTvShows($server) { return self::find(function ($query) use ($server) { @@ -492,6 +482,12 @@ class Model_Movie extends Model_Overwrite ->join('server', 'LEFT') ->on('library.server_id', '=', 'server.id') ->where('server.id', $server->id) + ->and_where('server.online', 1) + ->and_where('server.disable', 0) + ->and_where('library.disable', 0) + ->and_where('tvshow.disable', 0) + ->and_where('season.disable', 0) + ->and_where('movie.disable', 0) ->and_where('movie.type', 'episode') ->order_by('movie.addedAt', 'DESC') ->order_by(DB::expr('MAX(' . DB::table_prefix('movie') .'.addedAt)'), 'DESC ')//'movie.addedAt', 'DESC') @@ -512,6 +508,7 @@ class Model_Movie extends Model_Overwrite ->join('server', 'LEFT') ->on('library.server_id', '=', 'server.id') ->where('server.id', $server->id) + ->and_where('movie.disable', 0) ->and_where('movie.type', 'movie') ->order_by('movie.addedAt', 'DESC') ->limit(30) @@ -526,6 +523,7 @@ class Model_Movie extends Model_Overwrite return $query ->select('*') ->where('type', 'movie') + ->group_by('originalTitle', 'title', 'year', 'studio') ->order_by('title', 'ASC') ; }); @@ -534,6 +532,6 @@ class Model_Movie extends Model_Overwrite public function getTrailer() { $trailer = new Model_Trailer($this->originalTitle ?: $this->title, $this->year, $this->type); - $this->trailer = $trailer->trailer; + $this->trailer = $trailer->getTrailer(); } } diff --git a/fuel/app/classes/model/overwrite.php b/fuel/app/classes/model/overwrite.php index cb2cbe5..919deb6 100755 --- a/fuel/app/classes/model/overwrite.php +++ b/fuel/app/classes/model/overwrite.php @@ -1,36 +1,44 @@ -value('disable', 1) - ->where(static::primary_key(), '=', $this->{static::primary_key()}) : null; - - $this->pre_delete($query); - $result = $query ? $query->execute(static::get_connection(true)) : null; - - return $this->post_delete($result); - } - - protected function pre_save(&$query) - { - if($this->is_new()) { - if(!isset($this->{static::primary_key()}) || !$this->{static::primary_key()} || $this->{static::primary_key()} === null) { - $this->{static::primary_key()} = Str::random('uuid'); - $query->set([static::primary_key() => $this->{static::primary_key()}]); - } - } - } - -} \ No newline at end of file +value('disable', 1) + ->where(static::primary_key(), '=', $this->{static::primary_key()}) : null; + + $this->pre_delete($query); + $result = $query ? $query->execute(static::get_connection(true)) : null; + + return $this->post_delete($result); + } + + /** + * Use it to force to use UUID to primary key + * @param \Fuel\Core\Database_Query $query + */ + protected function pre_save(&$query) + { + if($this->is_new()) { + if(!isset($this->{static::primary_key()}) || !$this->{static::primary_key()} || $this->{static::primary_key()} === null) { + $this->{static::primary_key()} = Str::random('uuid'); + $query->set([static::primary_key() => $this->{static::primary_key()}]); + } + } + } + +} diff --git a/fuel/app/classes/model/season.php b/fuel/app/classes/model/season.php index f3424ec..6dc6380 100644 --- a/fuel/app/classes/model/season.php +++ b/fuel/app/classes/model/season.php @@ -129,16 +129,15 @@ class Model_Season extends Model_Overwrite $tvshow_id = $tvshow->id; $season = Model_Season::find(function ($query) use ($XMLseason, $tvshow_id) { - /** @var Database_Query_Builder_Select $query */ return $query ->select('*') - ->where('plex_key', $XMLseason['@attributes']['key']) + ->where('plex_key', $XMLseason['@attributes']['ratingKey']) ->and_where('tv_show_id', $tvshow_id); })[0] ?: Model_Season::forge(); $season->set([ 'tv_show_id' => $tvshow->id, - 'plex_key' => $XMLseason['@attributes']['key'], + 'plex_key' => $XMLseason['@attributes']['ratingKey'], 'number' => $XMLseason['@attributes']['index'], 'title' => $XMLseason['@attributes']['title'], 'thumb' => isset($XMLseason['@attributes']['thumb']) ? $XMLseason['@attributes']['thumb'] : null, @@ -171,7 +170,7 @@ class Model_Season extends Model_Overwrite public static function getMovies($server, $season) { try { - $curl = Request::forge(($server->https ? 'https' : 'http').'://' . $server->url . ($server->port ? ':' . $server->port : '') . $season->plex_key . '?X-Plex-Token=' . $server->token, 'curl'); + $curl = Request::forge(($server->https ? 'https' : 'http').'://' . $server->url . ($server->port ? ':' . $server->port : '') . '/library/metadata/' . $season->plex_key . '/children?X-Plex-Token=' . $server->token, 'curl'); if($server->https) { $curl->set_options([ diff --git a/fuel/app/classes/model/trailer.php b/fuel/app/classes/model/trailer.php index a37dd0e..db3a730 100644 --- a/fuel/app/classes/model/trailer.php +++ b/fuel/app/classes/model/trailer.php @@ -10,7 +10,7 @@ class Model_Trailer private $_url; - public $trailer; + private $_trailer; public function __construct($title, $year, $type) { @@ -26,16 +26,24 @@ class Model_Trailer $this->getMovieTrailer(); - if(!$this->trailer) + if(!$this->_trailer) $this->getMovieTeaser(); - - return $this->trailer; } } + /** + * @return mixed + */ + public function getTrailer() + { + return $this->_trailer; + } + private function getUrl() { $html = Request::forge('https://www.themoviedb.org/search/movie?query=' . urlencode($this->_title) . '+y%3A' . $this->_year . '&language=us', 'curl'); + $html->set_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0'); + $html->execute(); if ($html->response()->status !== 200) @@ -56,6 +64,7 @@ class Model_Trailer private function getMovieTrailer() { $html = Request::forge('https://www.themoviedb.org' . $this->_url . '/videos?active_nav_item=Trailers&video_language=en-US&language=en-US', 'curl'); + $html->set_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0'); $html->set_options(array( CURLOPT_FOLLOWLOCATION => true, ) @@ -76,12 +85,13 @@ class Model_Trailer $youtube = '//www.youtube.com/embed/'.$youtube[1].'?enablejsapi=1&autoplay=0&hl=en-US&modestbranding=1&fs=1'; - $this->trailer = $youtube; + $this->_trailer = $youtube; } private function getMovieTeaser() { $html = Request::forge('https://www.themoviedb.org' . $this->_url . '/videos?active_nav_item=Teasers&video_language=en-US&language=en-US', 'curl'); + $html->set_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0'); $html->set_options(array( CURLOPT_FOLLOWLOCATION => true, ) @@ -102,6 +112,6 @@ class Model_Trailer $youtube = preg_replace('/\&origin\=https%3A%2F%2Fwww\.themoviedb\.org/i', '', $youtube[1]); - $this->trailer = $youtube; + $this->_trailer = $youtube; } } \ No newline at end of file diff --git a/fuel/app/classes/model/tvshow.php b/fuel/app/classes/model/tvshow.php index e5123bf..73c699e 100644 --- a/fuel/app/classes/model/tvshow.php +++ b/fuel/app/classes/model/tvshow.php @@ -117,9 +117,7 @@ class Model_Tvshow extends Model_Overwrite if(!$this->_server) $this->getServer(); - $plex_key = preg_split('/\/children/', $this->plex_key)[0]; - - $curl = Request::forge(($this->_server->https ? 'https' : 'http').'://' . $this->_server->url . ($this->_server->port ? ':' . $this->_server->port : '') . $plex_key . '?X-Plex-Token=' . $this->_server->token, 'curl'); + $curl = Request::forge(($this->_server->https ? 'https' : 'http').'://' . $this->_server->url . ($this->_server->port ? ':' . $this->_server->port : '') . '/library/metadata/' . $this->plex_key . '?X-Plex-Token=' . $this->_server->token, 'curl'); if($this->_server->https) { $curl->set_options([ @@ -161,16 +159,15 @@ class Model_Tvshow extends Model_Overwrite $library_id = $library->id; $tvshow = Model_Tvshow::find(function ($query) use ($subsection, $library_id) { - /** @var Database_Query_Builder_Select $query */ return $query ->select('*') - ->where('plex_key', $subsection['@attributes']['key']) + ->where('plex_key', $subsection['@attributes']['ratingKey']) ->and_where('library_id', $library_id); })[0] ?: Model_Tvshow::forge(); $tvshow->set([ 'library_id' => $library->id, - 'plex_key' => $subsection['@attributes']['key'], + 'plex_key' => $subsection['@attributes']['ratingKey'], 'studio' => isset($subsection['@attributes']['studio']) ? $subsection['@attributes']['studio'] : null, 'title' => $subsection['@attributes']['title'], 'contentRating' => isset($subsection['@attributes']['contentRating']) ? $subsection['@attributes']['contentRating'] : null, @@ -212,7 +209,7 @@ class Model_Tvshow extends Model_Overwrite public static function getTvShowSeasons($server, $tvshow) { try { - $curl = Request::forge(($server->https ? 'https' : 'http').'://' . $server->url . ($server->port ? ':' . $server->port : '') . $tvshow->plex_key . '?X-Plex-Token=' . $server->token, 'curl'); + $curl = Request::forge(($server->https ? 'https' : 'http').'://' . $server->url . ($server->port ? ':' . $server->port : '') . '/library/metadata/' . $tvshow->plex_key . '/children?X-Plex-Token=' . $server->token, 'curl'); if($server->https) { $curl->set_options([ diff --git a/fuel/app/classes/model/user.php b/fuel/app/classes/model/user.php index be7a253..304b102 100755 --- a/fuel/app/classes/model/user.php +++ b/fuel/app/classes/model/user.php @@ -47,7 +47,7 @@ class Model_User extends Model_Overwrite ; }); - if(count($result) > 0) + if($result !== null) return $result[0]; else return false; diff --git a/fuel/app/tasks/clean.php b/fuel/app/tasks/clean.php new file mode 100644 index 0000000..f85af05 --- /dev/null +++ b/fuel/app/tasks/clean.php @@ -0,0 +1,50 @@ +getServer(); + + try { + $curl = Request::forge(($server->https === '1' ? 'https' : 'http').'://' . $server->url . ($server->port ? ':' . $server->port : '') . $movie->plex_key . '?X-Plex-Token=' . $server->token, 'curl'); + + $curl->set_options([ + CURLOPT_CONNECTTIMEOUT => 1 + ]); + + if($server->https === '1') { + $curl->set_options([ + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_SSL_VERIFYHOST => false + ]); + } + + $curl->execute(); + + if ($curl->response()->status !== 200) + throw new FuelException('No session found!'); + + } catch (Exception $exception) { + $movie->set([ + 'updatedAt' => time(), + 'disable' => 1 + ]); + + $movie->save(); + } + } + } +} diff --git a/fuel/app/tasks/server.php b/fuel/app/tasks/server.php index 1d374e4..b45694b 100644 --- a/fuel/app/tasks/server.php +++ b/fuel/app/tasks/server.php @@ -4,7 +4,9 @@ namespace Fuel\Tasks; use Exception; use Fuel\Core\FuelException; +use Fuel\Core\RequestStatusException; use Model_Library; +use Model_Movie; use Model_Season; use Model_Server; use Model_Tvshow; @@ -19,7 +21,7 @@ class Server foreach ($servers as $server) { try { - $curl = Request::forge(($this->_server->https === '1' ? 'https' : 'http').'://' . $server->url . ($server->port ? ':' . $server->port : '') . '?X-Plex-Token=' . $server->token, 'curl'); + $curl = Request::forge(($server->https === '1' ? 'https' : 'http').'://' . $server->url . ($server->port ? ':' . $server->port : '') . '?X-Plex-Token=' . $server->token, 'curl'); $curl->set_options([ CURLOPT_CONNECTTIMEOUT => 1 @@ -54,14 +56,134 @@ class Server } } + public function checkNotFound() + { + $this->_checkMovies(); + $this->_checkSeasons(); + $this->_checkTvShows(); + } + + private function _checkMovies() + { + $movies = Model_Movie::find_all(); + + /** @var Model_Movie $movie */ + foreach ($movies as $movie) { + $movie->plex_key; + $server = $movie->getServer(); + + try { + $curl = Request::forge(($server->https === '1' ? 'https' : 'http') . '://' . $server->url . ($server->port ? ':' . $server->port : '') . $movie->plex_key . '?X-Plex-Token=' . $server->token, 'curl'); + + $curl->set_options([ + CURLOPT_CONNECTTIMEOUT => 1 + ]); + + if ($server->https === '1') { + $curl->set_options([ + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_SSL_VERIFYHOST => false + ]); + } + + $curl->execute(); + } catch (RequestStatusException $exception) { + $movie->set([ + 'disable' => 1 + ]); + + $movie->save(); + } catch (Exception $exception) { + + } + } + } + + private function _checkSeasons() + { + $seasons = Model_Season::find_all(); + + /** @var Model_Season $season */ + foreach ($seasons as $season) { + $season->plex_key; + $server = $season->getServer(); + + try { + $curl = Request::forge(($server->https === '1' ? 'https' : 'http') . '://' . $server->url . ($server->port ? ':' . $server->port : '') . $season->plex_key . '?X-Plex-Token=' . $server->token, 'curl'); + + $curl->set_options([ + CURLOPT_CONNECTTIMEOUT => 1 + ]); + + if ($server->https === '1') { + $curl->set_options([ + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_SSL_VERIFYHOST => false + ]); + } + + $curl->execute(); + } catch (RequestStatusException $exception) { + $season->set([ + 'disable' => 1 + ]); + + $season->save(); + } catch (Exception $exception) { + + } + } + } + + private function _checkTvShows() + { + $tv_shows = Model_Tvshow::find_all(); + + /** @var Model_Tvshow $tv_show */ + foreach ($tv_shows as $tv_show) { + $tv_show->plex_key; + $server = $tv_show->getServer(); + + try { + $curl = Request::forge(($server->https === '1' ? 'https' : 'http') . '://' . $server->url . ($server->port ? ':' . $server->port : '') . $tv_show->plex_key . '?X-Plex-Token=' . $server->token, 'curl'); + + $curl->set_options([ + CURLOPT_CONNECTTIMEOUT => 1 + ]); + + if ($server->https === '1') { + $curl->set_options([ + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_SSL_VERIFYHOST => false + ]); + } + + $curl->execute(); + } catch (RequestStatusException $exception) { + $tv_show->set([ + 'disable' => 1 + ]); + + $tv_show->save(); + } catch (Exception $exception) { + + } + } + } + public function browseServers() { $time = ini_get('max_execution_time'); - $servers = Model_Server::find_all(); + $servers = Model_Server::find([ + 'where' => [ + 'online' => 1, + 'disable' => 0 + ] + ]); - if($time > 0 && $time < ($servers * 5 * 60)) { - ini_set('max_execution_time', 5 * $servers); + if($time > 0 && $time < ($servers * 10 * 60)) { + ini_set('max_execution_time', 10 * $servers); } foreach ($servers as $server) { @@ -90,7 +212,7 @@ class Server $libraries = Model_Library::find_by('server_id',$server->id); foreach ($libraries as $library) { - Model_Library::getSectionsContent($server, $library); + Model_Library::getLibraryContents($server, $library); } $this->browseTvShows($server); diff --git a/fuel/app/views/home/index.php b/fuel/app/views/home/index.php index 430c02a..97f338a 100755 --- a/fuel/app/views/home/index.php +++ b/fuel/app/views/home/index.php @@ -16,7 +16,7 @@
- +
- +
diff --git a/fuel/app/views/movie/index.php b/fuel/app/views/movie/index.php index 0368793..3e25ba8 100644 --- a/fuel/app/views/movie/index.php +++ b/fuel/app/views/movie/index.php @@ -306,7 +306,7 @@
-
+
@@ -403,6 +403,10 @@ event.target.remove(); }); /** LOAD IMG **/ + $('.actor_img').each(function (index, element) { + var actor_img = $(element).data('background'); + $(element).css('background-image', 'url("' + actor_img + '")'); + }); $('.PosterCardImg-imageContainer-1Ar4M[data-movie-id]').each(function (index, element) { var movie_id = $(element).data('movie-id'); $('[data-movie-id="' + movie_id + '"] > div').css('background-image', 'url("/cover/movie?movie_id='+ movie_id +'&width='+ 325 +'&height='+ 488 +'")'); diff --git a/fuel/app/views/movie/list.php b/fuel/app/views/movie/list.php index dcc36db..fa1ad89 100644 --- a/fuel/app/views/movie/list.php +++ b/fuel/app/views/movie/list.php @@ -59,7 +59,7 @@
-
@@ -330,12 +330,36 @@ }); }); /** LOAD IMAGES **/ - $('.PosterCardImg-imageContainer-1Ar4M[data-movie-id]').each(function (index, element) { - /** IF USING CLOUDFLARE TOO MANY REQUEST **/ - setTimeout(function(){ - var movie_id = $(element).data('movie-id'); - $('[data-movie-id="' + movie_id + '"] > div').css('background-image', 'url("/cover/movie?movie_id='+ movie_id +'&width='+ 160 +'&height='+ 236 +'")'); - }, 10 * index); + $('.MetadataListPageContent-metadataListScroller-1uFgY.MetadataListPageContent-hasGutter-1EfyE.Scroller-scroller-d5-b-.Scroller-vertical-1bgGS').scroll(function() { + + let number = 1; + + $('.PosterCardImg-imageContainer-1Ar4M[data-movie-id]').each(function (index, element) { + + let movie_id = $(element).data('movie-id'); + let position = element.getBoundingClientRect(); + let movie = document.querySelector('[data-movie-id="' + movie_id + '"] > div'); + + if( position.top > 0 && position.top <= (window.innerHeight || document.documentElement.clientHeight) && !movie.classList.contains('hasBackground') ) { + console.log(movie, position.top, window.innerHeight, !movie.classList.contains('hasBackground')); + movie.classList.add('hasBackground'); + console.log(movie, position.top, window.innerHeight, !movie.classList.contains('hasBackground')); + /** IF USING CLOUDFLARE TOO MANY REQUEST **/ + setTimeout(function () { + $('[data-movie-id="' + movie_id + '"] > div') + .css('opacity', 0) + .css('background-image', 'url("/cover/movie?movie_id=' + movie_id + '&width=' + 160 + '&height=' + 236 + '")') + .animate({opacity: 1}, 500); + }, 50 +( 50 * number)); + number++; + } else if( ( position.top < 0 || position.top > (window.innerHeight || document.documentElement.clientHeight) ) && movie.classList.contains('hasBackground') ) { + $('[data-movie-id="' + movie_id + '"] > div').css('background-image', '') + .removeClass('hasBackground') + .animate({opacity: 0}, 500); + } + }); }); + + $('.MetadataListPageContent-metadataListScroller-1uFgY.MetadataListPageContent-hasGutter-1EfyE.Scroller-scroller-d5-b-.Scroller-vertical-1bgGS').scroll(); }); \ No newline at end of file diff --git a/fuel/app/views/player/index.php b/fuel/app/views/player/index.php new file mode 100644 index 0000000..311ef16 --- /dev/null +++ b/fuel/app/views/player/index.php @@ -0,0 +1,293 @@ + + + +
+
+
+ +
+
+ + +
+
+
+