main.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <?
  2. # Config
  3. $MEDIA_PATH = '/mnt/media';
  4. $TV_PATH = $MEDIA_PATH . '/TV';
  5. $EXISTS_FILES = array('no_quality_checks', 'more_number_formats', 'skip');
  6. $CONTENT_FILES = array('must_match', 'search_name');
  7. $TVDB_URL = 'http://thetvdb.com/?tab=series';
  8. function writeWebloc($url, $path) {
  9. $encoded_url = htmlspecialchars($url, ENT_XML1, 'UTF-8');
  10. $str = '<?xml version="1.0" encoding="UTF-8"?>';
  11. $str .= '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">';
  12. $str .= '<plist version="1.0">';
  13. $str .= '<dict>';
  14. $str .= '<key>URL</key>';
  15. $str .= '<string>' . $encoded_url . '</string>';
  16. $str .= '</dict>';
  17. $str .= '</plist>';
  18. file_put_contents($path, $str);
  19. }
  20. # True if the input path is junk -- self-links, OS X noise, etc.
  21. function isJunk($path) {
  22. $path = basename($path);
  23. # Ignore certain fixed paths
  24. foreach (array('.', '..', '.DS_Store') as $value) {
  25. if ($path == $value) {
  26. return true;
  27. }
  28. }
  29. # Ignore ._ paths
  30. if (preg_match('/^\.\_/', $path)) {
  31. return true;
  32. }
  33. # Otherwise the path is good
  34. return false;
  35. }
  36. # True if the provided season folder is being monitored
  37. function isMonitored($season_path) {
  38. if (file_exists(dirname($season_path) . '/skip')) {
  39. return false;
  40. }
  41. if (file_exists($season_path . '/season_done')) {
  42. return false;
  43. }
  44. $season = 0;
  45. if (preg_match('/^Season\s+(\d+)$/i', basename($season_path), $matches)) {
  46. $season = $matches[1];
  47. }
  48. if (!$season) {
  49. return false;
  50. }
  51. return true;
  52. }
  53. # Get the season search status, including the URL (if any) for the provided path
  54. function seasonSearch($season_path) {
  55. $retval = isMonitored($season_path);
  56. if ($retval) {
  57. $file = $season_path . '/url';
  58. if (is_readable($file)) {
  59. $retval = trim(file_get_contents($file));
  60. }
  61. }
  62. return $retval;
  63. }
  64. # Find all the season in a provided series folder and determine which are being monitored
  65. function findSeasons($path) {
  66. $retval = array();
  67. # Check for the skip file
  68. $skip = false;
  69. if (file_exists($path . '/skip')) {
  70. $skip = true;
  71. }
  72. $dir = opendir($path);
  73. if ($dir === FALSE) {
  74. die('Unable to opendir(): ' . htmlspecialchars($path) . "\n");
  75. }
  76. while (false !== ($season = readdir($dir))) {
  77. # Skip junk
  78. if (isJunk($show)) {
  79. continue;
  80. }
  81. # We only care about directories
  82. $season_path = $path . '/' . $season;
  83. if (!is_dir($season_path)) {
  84. continue;
  85. }
  86. # Record the season number and search status
  87. if (preg_match('/Season\s+(\d+)/i', $season, $matches)) {
  88. $retval[ $matches[1] ] = seasonSearch($season_path);
  89. }
  90. }
  91. closedir($dir);
  92. # Sort numerically; the directory listing typically returns a lexicographic order
  93. ksort($retval, SORT_NUMERIC);
  94. return $retval;
  95. }
  96. # Find all shows under the given path
  97. function allShows($base) {
  98. $retval = array();
  99. # Look for series folders
  100. $tv_dir = opendir($base);
  101. if ($tv_dir === FALSE) {
  102. die('Unable to opendir(): ' . htmlspecialchars($path) . "\n");
  103. }
  104. while (false !== ($show = readdir($tv_dir))) {
  105. # Skip junk
  106. if (isJunk($show)) {
  107. continue;
  108. }
  109. # We only care about directories
  110. $show_path = $base . '/' . $show;
  111. if (!is_dir($show_path)) {
  112. continue;
  113. }
  114. # Record the show title and look for season folders
  115. $retval[ $show ] = findSeasons($show_path);
  116. }
  117. closedir($tv_dir);
  118. return $retval;
  119. }
  120. # Find the *.webloc file, if in, in the provided folder
  121. function findWebloc($path) {
  122. $retval = false;
  123. $dir = opendir($path);
  124. if ($dir === FALSE) {
  125. die('Unable to opendir(): ' . htmlspecialchars($path) . "\n");
  126. }
  127. while (false !== ($name = readdir($dir))) {
  128. # Skip junk
  129. if (isJunk($name)) {
  130. continue;
  131. }
  132. # We only care about *.webloc files
  133. if (!preg_match('/\.webloc$/', $name)) {
  134. continue;
  135. }
  136. # The file must be readable to be useful
  137. $file = $path . '/' . $name;
  138. if (is_readable($file)) {
  139. $retval = $file;
  140. last;
  141. }
  142. }
  143. closedir($dir);
  144. return $retval;
  145. }
  146. # Read and parse the provided *.webloc file
  147. function readWebloc($file) {
  148. global $TVDB_URL;
  149. $retval = array(
  150. 'tvdb-id' => false,
  151. 'tvdb-lid' => false,
  152. 'url' => false,
  153. );
  154. # Read and parse the file
  155. # Accept both the resource-fork and data-fork (i.e. plist) verisons of the file
  156. $str = trim(file_get_contents($file));
  157. if (preg_match('/(?:\?|\&(?:amp;)?)id=(\d+)/', $str, $matches)) {
  158. $retval['tvdb-id'] = $matches[1];
  159. }
  160. if (preg_match('/(?:\?|\&(?:amp;)?)lid=(\d+)/', $str, $matches)) {
  161. $retval['tvdb-lid'] = $matches[1];
  162. }
  163. # Construct a URL
  164. if ($retval['tvdb-id'] !== false) {
  165. $retval['url'] = $TVDB_URL . '&id=' . $retval['tvdb-id'];
  166. if ($retval['tvdb-lid'] !== false) {
  167. $retval['url'] .= '&lid=' . $retval['tvdb-lid'];
  168. }
  169. }
  170. return $retval;
  171. }
  172. # Read and parse all of the series-level exists, content, and *.webloc files
  173. function readFlags($path) {
  174. global $EXISTS_FILES;
  175. global $CONTENT_FILES;
  176. $flags = array();
  177. # Look for all the exists files
  178. foreach ($EXISTS_FILES as $name) {
  179. $flags[ $name ] = false;
  180. if (file_exists($path . '/' . $name)) {
  181. $flags[ $name ] = true;
  182. }
  183. }
  184. # Read all the content files
  185. foreach ($CONTENT_FILES as $name) {
  186. $flags[ $name ] = false;
  187. $file = $path . '/' . $name;
  188. if (is_readable($file)) {
  189. $flags[ $name ] = trim(file_get_contents($file));
  190. }
  191. }
  192. # Read the TVDB IDs from the *.webloc file
  193. $webloc = findWebloc($path);
  194. if ($webloc !== false) {
  195. $flags = array_merge($flags, readWebloc($webloc));
  196. }
  197. return $flags;
  198. }
  199. function printShow($show) {
  200. global $TV_PATH;
  201. global $EXISTS_FILES;
  202. global $CONTENT_FILES;
  203. # Construct our show path and make sure it's reasonable
  204. $path = $TV_PATH . '/' . $show;
  205. if (!is_dir($path)) {
  206. die('Unknown show: ' . htmlspecialchars($show));
  207. }
  208. # Check the flags
  209. $flags = readFlags($path);
  210. # Check the seasons
  211. $seasons = findSeasons($path);
  212. # Header
  213. echo '<h1>' . htmlspecialchars($show) . '</h1>';
  214. echo '<form action="' . $SERVER['PHP_SELF'] . '" method="post">';
  215. # Exists and content flags
  216. echo '<h2>Series Parameters</h2>';
  217. echo '<p>';
  218. foreach ($EXISTS_FILES as $file) {
  219. $file_html = htmlspecialchars($file);
  220. echo '<label><input value="1" type="checkbox" name="' . $file_html . '" ';
  221. if ($flags[ $file ]) {
  222. echo 'checked="checked"';
  223. }
  224. echo '/> ' . $file_html . '</label><br/>';
  225. }
  226. foreach ($CONTENT_FILES as $file) {
  227. $file_html = htmlspecialchars($file);
  228. echo '<label><input type="text" size="40" name="' . $file_html . '" ';
  229. if ($flags[ $file ]) {
  230. echo 'value="' . htmlspecialchars($flags[ $file ]) . '"';
  231. }
  232. echo '/> ' . $file_html . '</label><br/>';
  233. }
  234. echo '</p>';
  235. # TVDB URL
  236. echo '<h2>The TVDB URL</h2>';
  237. echo '<p><a href="' . htmlspecialchars($flags['url']) . '">' . htmlspecialchars($flags['url']) . '</a></p>';
  238. # Seasons
  239. echo '<h2>Season Parameters</h2>';
  240. echo '<p>';
  241. foreach ($seasons as $season => $monitored) {
  242. $season_html = htmlspecialchars($season);
  243. echo '<label>Season ' . $season_html . ' ';
  244. echo '<input type="checkbox" value="1" name="season_' . $season_html . '" ';
  245. if ($monitored !== false) {
  246. echo 'checked="checked"';
  247. }
  248. echo '/></label>';
  249. echo '<input type="text" size="150" name="url_' . $season_html . '" value="';
  250. if ($monitored !== false && $monitored !== true) {
  251. echo htmlspecialchars($monitored);
  252. }
  253. echo '"/><br/>';
  254. }
  255. echo '</p>';
  256. # Footer
  257. echo '<p><input type="submit" name="submit" value="Save"/></p>';
  258. echo '</form>';
  259. }
  260. # Print a DL of all shows and note the available and monitored seasons
  261. function printAllShows() {
  262. global $TV_PATH;
  263. global $MEDIA_PATH;
  264. $shows = allShows($TV_PATH);
  265. echo "<dl>\n";
  266. foreach ($shows as $show => $seasons) {
  267. echo '<dt><a href="?show=' . urlencode($show) . '">' . htmlspecialchars($show) . "</a></dt>\n";
  268. foreach ($seasons as $season => $monitored) {
  269. echo '<dd>Season ' . htmlspecialchars($season);
  270. if ($monitored) {
  271. echo ' (monitored)';
  272. }
  273. echo "</dd>\n";
  274. }
  275. }
  276. echo "</dl>\n";
  277. }
  278. ?>