seriesScraper.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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, skipping..<br><br>" . PHP_EOL;
  54. continue;
  55. }
  56. $series = json_decode(curl_download($this->apiURL . urlencode($dir) . "&language=de&include_image_language=de"), true);
  57. if($series['total_results'] == 1) {
  58. $this->outputText .= "Found 1 series, downloading...<br>" . PHP_EOL;
  59. $this->downloadSeriesByID($series['results'][0]['id'], $dir, $sourceID);
  60. } else if($series['total_results'] < 1) {
  61. $this->outputText .= "<span style=\"color: red;\">Not found!!</span><br>" . PHP_EOL;
  62. } else { // multiple search results
  63. usort($series['results'], array("MovieScraper", "sortByPopularity")); // sort results by popularity, so that you don't have to scroll like 500000x
  64. foreach($series['results'] as $result) {
  65. $this->outputText .= "<pre>" . print_r($result, true) . "</pre>" . PHP_EOL;
  66. $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
  67. }
  68. }
  69. $this->outputText .= "<br>" . PHP_EOL;
  70. /*
  71. Array
  72. (
  73. [page] => 1
  74. [results] => Array
  75. (
  76. [0] => Array
  77. (
  78. [poster_path] => /hDlezfMSw8oXIFNZ7B9fFLrV8kd.jpg
  79. [popularity] => 1.006821
  80. [id] => 15826
  81. [backdrop_path] => /meQN6iuOulLwOV8LNO6S9z3bJBY.jpg
  82. [vote_average] => 7
  83. [overview] => 1000 Ways to Die is an anthology television series that [...]
  84. [first_air_date] => 2009-02-04
  85. [origin_country] => Array
  86. (
  87. [0] => US
  88. )
  89. [genre_ids] => Array
  90. (
  91. [0] => 99
  92. )
  93. [original_language] => en
  94. [vote_count] => 1
  95. [name] => 1000 Ways to Die
  96. [original_name] => 1000 Ways to Die
  97. )
  98. )
  99. [total_results] => 1
  100. [total_pages] => 1
  101. )
  102. */
  103. }
  104. }
  105. public function downloadSeriesByID($seriesID, $path, $sourceID) {
  106. $source = $GLOBALS['db']->getAllAssoc("sources", "id", $sourceID);
  107. $series = json_decode(curl_download("http://api.themoviedb.org/3/tv/" . $seriesID . "?api_key=a39779a38e0619f8ae58b09f64522597&language=de&include_image_language=de"), true);
  108. //$this->outputText .= "<pre>" . print_r($series, true) . "</pre>";
  109. // Download poster, backdrop
  110. if(!file_exists("img/posters" . $series['poster_path'])) {
  111. file_put_contents("img/posters" . $series['poster_path'], fopen($this->bannerURL . $series['poster_path'], 'r'));
  112. }
  113. if(!file_exists("img/posters" . $series['backdrop_path'])) {
  114. file_put_contents("img/posters" . $series['backdrop_path'], fopen($this->bannerURL . $series['backdrop_path'], 'r'));
  115. }
  116. $cols = array(
  117. "moviedb-id",
  118. "name",
  119. "path",
  120. "poster",
  121. "backdrop",
  122. "overview",
  123. "source"
  124. );
  125. $vals = array(
  126. $series['id'],
  127. $series['name'],
  128. $path,
  129. ltrim($series['poster_path'], "/"),
  130. ltrim($series['backdrop_path'], "/"),
  131. $series['overview'],
  132. $sourceID
  133. );
  134. $dbSeriesID = $GLOBALS['db']->insertRow("series", $cols, $vals);
  135. $localSeasons = scandir($source[0]['path'] . "/" . $path);
  136. $localSeasons = array_diff($localSeasons, array('.', '..', 'formatting.txt', '.Trash-1000'));
  137. foreach($localSeasons as $localSeason) {
  138. $season = array_search(ltrim(ltrim($localSeason, "S"), 0), array_column($series['seasons'], 'season_number'));
  139. $cols = array(
  140. "series-id",
  141. "number",
  142. "poster"
  143. );
  144. $vals = array(
  145. $dbSeriesID,
  146. $series['seasons'][$season]['season_number'],
  147. ltrim($series['seasons'][$season]['poster_path'], "/")
  148. );
  149. $dbSeasonID = $GLOBALS['db'] -> insertRow("series-seasons", $cols, $vals);
  150. if(!file_exists("img/posters" . $series['seasons'][$season]['poster_path'])) {
  151. file_put_contents("img/posters" . $series['seasons'][$season]['poster_path'], fopen($this->bannerURL . $series['seasons'][$season]['poster_path'], 'r'));
  152. }
  153. $localEpisodes = scandir($source[0]['path'] . "/" . $path . "/" . $localSeason);
  154. $localEpisodes = array_diff($localEpisodes, array('.', '..', 'formatting.txt', '.Trash-1000'));
  155. $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")));
  156. $episodes = array();
  157. foreach($dbEpisodes['episodes'] as $episode) {
  158. $episodes[] = get_object_vars($episode);
  159. }
  160. foreach($localEpisodes as $localEpisode) {
  161. $episode = array_search($this::getEpisodeNumberByFilename($localEpisode), array_column($episodes, 'episode_number'));
  162. $cols = array(
  163. "season-id",
  164. "number",
  165. "name",
  166. "thumb",
  167. "path"
  168. );
  169. $vals = array(
  170. $dbSeasonID,
  171. $episodes[$episode]['episode_number'],
  172. $episodes[$episode]['name'],
  173. ltrim($episodes[$episode]['still_path'], "/"),
  174. $localEpisode
  175. );
  176. $GLOBALS['db'] -> insertRow("series-episodes", $cols, $vals);
  177. if(!file_exists("img/posters" . $episodes[$episode]['still_path'])) {
  178. file_put_contents("img/posters" . $episodes[$episode]['still_path'], fopen($this->bannerURL . $episodes[$episode]['still_path'], 'r'));
  179. }
  180. }
  181. }
  182. $this->outputText .= "Done.";
  183. }
  184. }