seriesScraper.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. <?php
  2. ignore_user_abort(true);
  3. class SeriesScraper {
  4. private $apiURL = "http://api.themoviedb.org/3/search/tv?api_key=a39779a38e0619f8ae58b09f64522597&query=";
  5. private $bannerURL = "https://image.tmdb.org/t/p/original";
  6. private $outputText = "";
  7. public function __construct() {
  8. }
  9. public function getOutputText() {
  10. return $this->outputText;
  11. }
  12. public static function getEpisodeNumberByFilename($filename) {
  13. preg_match("/([a-zA-Z0-9äöüÄÖÜß\-\.\,\w]+)-[S|s]([0-9]+)[E|e]([0-9]+)-([a-zA-Z0-9äöüÄÖÜß\-\.\,\w\:]+)\.([a-zA-Z0-9\(\).*\w\,]+)/", $filename, $output);
  14. return ltrim($output[3], 0);
  15. }
  16. public static function remove($seriesID) {
  17. $series = Model::getSeriesBySeriesID($seriesID);
  18. $seasons = Model::getSeasonsBySeriesID($seriesID);
  19. foreach($seasons as $season) {
  20. $episodes = $GLOBALS['db']->getAllAssoc("series-episodes", "season-id", $season['id']);
  21. foreach($episodes as $episode) {
  22. unlink("img/posters/" . $episode['thumb']);
  23. }
  24. $GLOBALS['db']->deleteRows("series-episodes", "season-id", $season['id']);
  25. }
  26. $seasons = $GLOBALS['db']->getAllAssoc("series-seasons", "series-id", $seriesID);
  27. foreach($seasons as $season) {
  28. unlink("img/posters/" . $season['poster']);
  29. }
  30. $GLOBALS['db']->deleteRows("series-seasons", "series-id", $seriesID);
  31. $series = $GLOBALS['db']->getAllAssoc("series", "id", $seriesID);
  32. unlink("img/posters/" . $series[0]['poster']);
  33. unlink("img/posters/" . $series[0]['backdrop']);
  34. $GLOBALS['db']->deleteRows("series", "id", $seriesID);
  35. header("Location: " . $GLOBALS['conf']['baseURL'] . "?view=admin");
  36. }
  37. public function update($seriesID) {
  38. $series = Model::getSeriesBySeriesID($seriesID);
  39. self::remove($seriesID);
  40. $this->downloadSeriesByID($series[0]['moviedb-id'], $series[0]['path'], $series[0]['source']);
  41. header("Location: " . $GLOBALS['conf']['baseURL'] . "?view=admin");
  42. }
  43. public function scrapeFolder($sourceID) {
  44. if(!file_exists("img/posters")) {
  45. mkdir("img/posters");
  46. }
  47. $source = $GLOBALS['db']->getAllAssoc("sources", "id", $sourceID);
  48. $dirList = scandir($source[0]['path']);
  49. $dirList = array_diff($dirList, array('.', '..', 'formatting.txt', '.Trash-1000', 'queue.hbq'));
  50. foreach($dirList as $dir) {
  51. $this->outputText .= "<b>" . $dir . "</b><br>" . PHP_EOL;
  52. if($GLOBALS['db']->countRows("series", "path", $dir) > 0) {
  53. $this->outputText .= "Exists, updating..<br><br>" . PHP_EOL;
  54. self::updateByID($GLOBALS['db']->getString("id", "series", "path", $dir));
  55. continue;
  56. }
  57. $series = json_decode(curl_download($this->apiURL . urlencode($dir) . "&language=de&include_image_language=de"), true);
  58. if($series['total_results'] == 1) {
  59. $this->outputText .= "Found 1 series, downloading...<br>" . PHP_EOL;
  60. $this->downloadSeriesByID($series['results'][0]['id'], $dir, $sourceID);
  61. } else if($series['total_results'] < 1) {
  62. $this->outputText .= "<span style=\"color: red;\">Not found!!</span><br>" . PHP_EOL;
  63. } else { // multiple search results
  64. usort($series['results'], array("MovieScraper", "sortByPopularity")); // sort results by popularity, so that you don't have to scroll 500000x
  65. foreach($series['results'] as $result) {
  66. $this->outputText .= "<pre>" . print_r($result, true) . "</pre>" . PHP_EOL;
  67. $this->outputText .= "<a href=\"?view=scrape&action=scrapeSingleTV&moviedbID=" . $result['id'] . "&path=" . urlencode($dir) . "&sourceID=" . $sourceID . "\" target=\"_blank\">Load</a><br /><br />" . PHP_EOL; // TODO: this
  68. }
  69. }
  70. $this->outputText .= "<br>" . PHP_EOL;
  71. }
  72. }
  73. public function downloadSeriesByID($seriesID, $path, $sourceID) {
  74. $source = $GLOBALS['db']->getAllAssoc("sources", "id", $sourceID);
  75. $series = json_decode(curl_download("http://api.themoviedb.org/3/tv/" . $seriesID . "?api_key=a39779a38e0619f8ae58b09f64522597&language=de&include_image_language=de"), true);
  76. //$this->outputText .= "<pre>" . print_r($series, true) . "</pre>";
  77. // Download poster, backdrop
  78. if(!file_exists("img/posters" . $series['poster_path'])) {
  79. file_put_contents("img/posters" . $series['poster_path'], fopen($this->bannerURL . $series['poster_path'], 'r'));
  80. }
  81. if(!file_exists("img/posters" . $series['backdrop_path'])) {
  82. file_put_contents("img/posters" . $series['backdrop_path'], fopen($this->bannerURL . $series['backdrop_path'], 'r'));
  83. }
  84. $cols = array(
  85. "moviedb-id",
  86. "name",
  87. "path",
  88. "poster",
  89. "backdrop",
  90. "overview",
  91. "source"
  92. );
  93. $vals = array(
  94. $series['id'],
  95. $series['name'],
  96. $path,
  97. ltrim($series['poster_path'], "/"),
  98. ltrim($series['backdrop_path'], "/"),
  99. $series['overview'],
  100. $sourceID
  101. );
  102. $dbSeriesID = $GLOBALS['db']->insertRow("series", $cols, $vals);
  103. $localSeasons = scandir($source[0]['path'] . "/" . $path);
  104. $localSeasons = array_diff($localSeasons, array('.', '..', 'formatting.txt', '.Trash-1000'));
  105. foreach($localSeasons as $localSeason) {
  106. $season = array_search(ltrim(ltrim($localSeason, "S"), 0), array_column($series['seasons'], 'season_number'));
  107. $cols = array(
  108. "series-id",
  109. "number",
  110. "poster"
  111. );
  112. $vals = array(
  113. $dbSeriesID,
  114. $series['seasons'][$season]['season_number'],
  115. ltrim($series['seasons'][$season]['poster_path'], "/")
  116. );
  117. $dbSeasonID = $GLOBALS['db'] -> insertRow("series-seasons", $cols, $vals);
  118. if(!file_exists("img/posters" . $series['seasons'][$season]['poster_path'])) {
  119. file_put_contents("img/posters" . $series['seasons'][$season]['poster_path'], fopen($this->bannerURL . $series['seasons'][$season]['poster_path'], 'r'));
  120. }
  121. $localEpisodes = scandir($source[0]['path'] . "/" . $path . "/" . $localSeason);
  122. $localEpisodes = array_diff($localEpisodes, array('.', '..', 'formatting.txt', '.Trash-1000'));
  123. $dbEpisodes = get_object_vars(json_decode(curl_download("http://api.themoviedb.org/3/tv/" . $seriesID . "/season/" . ltrim(ltrim($localSeason, "S"), 0) . "?api_key=a39779a38e0619f8ae58b09f64522597&language=de&include_image_language=de")));
  124. $episodes = array();
  125. foreach($dbEpisodes['episodes'] as $episode) {
  126. $episodes[] = get_object_vars($episode);
  127. }
  128. foreach($localEpisodes as $localEpisode) {
  129. $episode = array_search($this::getEpisodeNumberByFilename($localEpisode), array_column($episodes, 'episode_number'));
  130. $cols = array(
  131. "season-id",
  132. "number",
  133. "name",
  134. "thumb",
  135. "path"
  136. );
  137. $vals = array(
  138. $dbSeasonID,
  139. $episodes[$episode]['episode_number'],
  140. $episodes[$episode]['name'],
  141. ltrim($episodes[$episode]['still_path'], "/"),
  142. $localEpisode
  143. );
  144. $GLOBALS['db'] -> insertRow("series-episodes", $cols, $vals);
  145. if(!file_exists("img/posters" . $episodes[$episode]['still_path'])) {
  146. file_put_contents("img/posters" . $episodes[$episode]['still_path'], fopen($this->bannerURL . $episodes[$episode]['still_path'], 'r'));
  147. }
  148. }
  149. }
  150. $this->outputText .= "Done.";
  151. }
  152. public function updateByID($seriesID) {
  153. /*if($seriesID != 208) {
  154. return;
  155. }*/
  156. error_log($seriesID);
  157. $series = $GLOBALS['db']->getAllAssoc("series", "id", $seriesID);
  158. $seriesDB = json_decode(curl_download("http://api.themoviedb.org/3/tv/" . $series[0]['moviedb-id'] . "?api_key=a39779a38e0619f8ae58b09f64522597&language=de&include_image_language=de"), true);
  159. if($series[0]['poster'] != ltrim($seriesDB['poster_path'], "/")) { // poster
  160. error_log("New Poster, old: " . $series[0]['poster'] . " new: " . ltrim($seriesDB['poster_path'], "/"));
  161. unlink("img/posters/" . $series[0]['poster']);
  162. file_put_contents("img/posters" . $seriesDB['poster_path'], fopen($this->bannerURL . $seriesDB['poster_path'], 'r'));
  163. $GLOBALS['db']->updateRow("series", "poster", '"' . ltrim($seriesDB['poster_path'], "/") . '"', "id", $seriesID);
  164. }
  165. if($series[0]['backdrop'] != ltrim($seriesDB['backdrop_path'], "/")) { // backdrop
  166. error_log("New Backdrop, old: " . $series[0]['backdrop'] . " new: " . ltrim($seriesDB['backdrop_path'], "/"));
  167. unlink("img/posters/" . $series[0]['backdrop']);
  168. file_put_contents("img/posters" . $seriesDB['backdrop_path'], fopen($this->bannerURL . $seriesDB['backdrop_path'], 'r'));
  169. $GLOBALS['db']->updateRow("series", "backdrop", '"' . ltrim($seriesDB['backdrop_path'], "/") . '"', "id", $seriesID);
  170. }
  171. $seasons = $GLOBALS['db']->getAllAssoc("series-seasons", "series-id", $seriesID);
  172. foreach($seasons as $season) { // TODO: check for new seasons
  173. $seasonDB = array_search(ltrim($season['number'], 0), array_column($seriesDB['seasons'], 'season_number'));
  174. $seasonDB = $seriesDB['seasons'][$seasonDB];
  175. if($season['poster'] != ltrim($seasonDB['poster_path'], "/")) {
  176. error_log("New Season-Poster, old: " . $season['poster'] . " new: " . ltrim($seasonDB['poster_path'], "/"));
  177. unlink("img/posters/" . $season['poster']);
  178. file_put_contents("img/posters" . $seasonDB['poster_path'], fopen($this->bannerURL . $seasonDB['poster_path'], 'r'));
  179. $GLOBALS['db']->updateRow("series-seasons", "poster", '"' . ltrim($seasonDB['poster_path'], "/") . '"', "id", $season['id']);
  180. }
  181. $episodesDB = json_decode(curl_download("http://api.themoviedb.org/3/tv/" . $series[0]['moviedb-id'] . "/season/" . $season['number'] . "?api_key=a39779a38e0619f8ae58b09f64522597&language=de&include_image_language=de"), true);
  182. $episodes = $GLOBALS['db']->getAllAssoc("series-episodes", "season-id", $season['id']);
  183. foreach($episodes as $episode) {
  184. $episodeDB = array_search($episode['number'], array_column($episodesDB['episodes'], 'episode_number'));
  185. $episodeDB = $episodesDB['episodes'][$episodeDB];
  186. if($episode['thumb'] != ltrim($episodeDB['still_path'], "/")) {
  187. error_log("New Episode-Poster, old: " . $episode['thumb'] . " new: " . ltrim($episodeDB['still_path'], "/"));
  188. unlink("img/posters/" . $episode['thumb']);
  189. file_put_contents("img/posters" . $episodeDB['still_path'], fopen($this->bannerURL . $episodeDB['still_path'], 'r'));
  190. $GLOBALS['db']->updateRow("series-episodes", "thumb", '"' . ltrim($episodeDB['still_path'], "/") . '"', "id", $episode['id']);
  191. }
  192. }
  193. }
  194. }
  195. }