trakt.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. <?php
  2. trait TraktHomepageItem
  3. {
  4. public function traktSettingsArray()
  5. {
  6. return array(
  7. 'name' => 'Trakt',
  8. 'enabled' => strpos('personal', $this->config['license']) !== false,
  9. 'image' => 'plugins/images/tabs/trakt.png',
  10. 'category' => 'Calendar',
  11. 'docs' => 'https://docs.organizr.app/books/setup-features/page/trakt',
  12. 'settings' => array(
  13. 'About' => array(
  14. array(
  15. 'type' => 'html',
  16. 'override' => 12,
  17. 'label' => '',
  18. 'html' => '
  19. <div class="panel panel-default">
  20. <div class="panel-wrapper collapse in">
  21. <div class="panel-body">
  22. <h3 lang="en">Trakt Homepage Item</h3>
  23. <p lang="en">This homepage item enables the calendar on the homepage and displays your movies and/or tv shows from Trakt\'s API.</p>
  24. <p lang="en">In order for this item to be setup, you need to goto the following URL to create a new API app.</p>
  25. <p><a href="https://trakt.tv/oauth/applications/new" target="_blank">New API App</a></p>
  26. <p lang="en">Enter anything for Name and Description. You can leave Javascript and Permissions blank. The only info you have to enter is for Redirect URI. Enter the following URL:</p>
  27. <code>' . $this->getServerPath() . 'api/v2/oauth/trakt</code>
  28. </div>
  29. </div>
  30. </div>'
  31. ),
  32. ),
  33. 'Enable' => array(
  34. array(
  35. 'type' => 'switch',
  36. 'name' => 'homepageTraktEnabled',
  37. 'label' => 'Enable',
  38. 'value' => $this->config['homepageTraktEnabled']
  39. ),
  40. array(
  41. 'type' => 'select',
  42. 'name' => 'homepageTraktAuth',
  43. 'label' => 'Minimum Authentication',
  44. 'value' => $this->config['homepageTraktAuth'],
  45. 'options' => $this->groupOptions
  46. )
  47. ),
  48. 'Connection' => array(
  49. array(
  50. 'type' => 'input',
  51. 'name' => 'traktClientId',
  52. 'label' => 'Client Id',
  53. 'value' => $this->config['traktClientId'],
  54. 'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.'
  55. ),
  56. array(
  57. 'type' => 'password-alt',
  58. 'name' => 'traktClientSecret',
  59. 'label' => 'Client Secret',
  60. 'value' => $this->config['traktClientSecret']
  61. ),
  62. array(
  63. 'type' => 'blank',
  64. 'label' => 'Please Save before clicking button'
  65. ),
  66. array(
  67. 'type' => 'button',
  68. 'label' => '',
  69. 'icon' => 'fa fa-user',
  70. 'class' => 'pull-right',
  71. 'text' => 'Connect Account',
  72. 'attr' => 'onclick="openOAuth(\'trakt\')"'
  73. ),
  74. ),
  75. 'Calendar' => array(
  76. array(
  77. 'type' => 'number',
  78. 'name' => 'calendarStartTrakt',
  79. 'label' => '# of Days Before',
  80. 'value' => $this->config['calendarStartTrakt'],
  81. 'placeholder' => '',
  82. 'help' => 'Total Days (Adding start and end days) has a maximum of 33 Days from Trakt API'
  83. ),
  84. array(
  85. 'type' => 'number',
  86. 'name' => 'calendarEndTrakt',
  87. 'label' => '# of Days After',
  88. 'value' => $this->config['calendarEndTrakt'],
  89. 'placeholder' => '',
  90. 'help' => 'Total Days (Adding start and end days) has a maximum of 33 Days from Trakt API'
  91. ),
  92. array(
  93. 'type' => 'select',
  94. 'name' => 'calendarFirstDay',
  95. 'label' => 'Start Day',
  96. 'value' => $this->config['calendarFirstDay'],
  97. 'options' => $this->daysOptions()
  98. ),
  99. array(
  100. 'type' => 'select',
  101. 'name' => 'calendarDefault',
  102. 'label' => 'Default View',
  103. 'value' => $this->config['calendarDefault'],
  104. 'options' => $this->calendarDefaultOptions()
  105. ),
  106. array(
  107. 'type' => 'select',
  108. 'name' => 'calendarTimeFormat',
  109. 'label' => 'Time Format',
  110. 'value' => $this->config['calendarTimeFormat'],
  111. 'options' => $this->timeFormatOptions()
  112. ),
  113. array(
  114. 'type' => 'select',
  115. 'name' => 'calendarLocale',
  116. 'label' => 'Locale',
  117. 'value' => $this->config['calendarLocale'],
  118. 'options' => $this->calendarLocaleOptions()
  119. ),
  120. array(
  121. 'type' => 'select',
  122. 'name' => 'calendarLimit',
  123. 'label' => 'Items Per Day',
  124. 'value' => $this->config['calendarLimit'],
  125. 'options' => $this->limitOptions()
  126. ),
  127. array(
  128. 'type' => 'select',
  129. 'name' => 'calendarRefresh',
  130. 'label' => 'Refresh Seconds',
  131. 'value' => $this->config['calendarRefresh'],
  132. 'options' => $this->timeOptions()
  133. )
  134. )
  135. )
  136. );
  137. }
  138. public function traktHomepagePermissions($key = null)
  139. {
  140. $permissions = [
  141. 'calendar' => [
  142. 'enabled' => [
  143. 'homepageTraktEnabled'
  144. ],
  145. 'auth' => [
  146. 'homepageTraktAuth'
  147. ],
  148. 'not_empty' => [
  149. 'traktClientId',
  150. 'traktAccessToken'
  151. ]
  152. ]
  153. ];
  154. if (array_key_exists($key, $permissions)) {
  155. return $permissions[$key];
  156. } elseif ($key == 'all') {
  157. return $permissions;
  158. } else {
  159. return [];
  160. }
  161. }
  162. public function getTraktCalendar($startDate = null)
  163. {
  164. $startDate = date('Y-m-d', strtotime('-' . $this->config['calendarStartTrakt'] . ' days'));
  165. $calendarItems = array();
  166. $errors = null;
  167. $totalDays = (int)$this->config['calendarStartTrakt'] + (int)$this->config['calendarEndTrakt'];
  168. if (!$this->homepageItemPermissions($this->traktHomepagePermissions('calendar'), true)) {
  169. return false;
  170. }
  171. $headers = [
  172. 'Content-Type' => 'application/json',
  173. 'Authorization' => 'Bearer ' . $this->config['traktAccessToken'],
  174. 'trakt-api-version' => 2,
  175. 'trakt-api-key' => $this->config['traktClientId']
  176. ];
  177. $url = $this->qualifyURL('https://api.trakt.tv/calendars/my/shows/' . $startDate . '/' . $totalDays . '?extended=full');
  178. $options = $this->requestOptions($url, false, $this->config['calendarRefresh']);
  179. try {
  180. $response = Requests::get($url, $headers, $options);
  181. if ($response->success) {
  182. $data = json_decode($response->body, true);
  183. $traktTv = $this->formatTraktCalendarTv($data);
  184. if (!empty($traktTv)) {
  185. $calendarItems = array_merge($calendarItems, $traktTv);
  186. }
  187. }
  188. } catch (Requests_Exception $e) {
  189. $this->writeLog('error', 'Trakt Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
  190. $this->setAPIResponse('error', $e->getMessage(), 500);
  191. $errors = true;
  192. }
  193. $url = $this->qualifyURL('https://api.trakt.tv/calendars/my/movies/' . $startDate . '/' . $totalDays . '?extended=full');
  194. try {
  195. $response = Requests::get($url, $headers, $options);
  196. if ($response->success) {
  197. $data = json_decode($response->body, true);
  198. $traktMovies = $this->formatTraktCalendarMovies($data);
  199. if (!empty($traktTv)) {
  200. $calendarItems = array_merge($calendarItems, $traktMovies);
  201. }
  202. }
  203. } catch (Requests_Exception $e) {
  204. $this->writeLog('error', 'Trakt Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
  205. $this->setAPIResponse('error', $e->getMessage(), 500);
  206. $errors = true;
  207. }
  208. if ($errors) {
  209. $this->setAPIResponse('error', 'An error Occurred', 500, null);
  210. return false;
  211. }
  212. $this->setAPIResponse('success', null, 200, $calendarItems);
  213. $this->traktOAuthRefresh();
  214. return $calendarItems;
  215. }
  216. public function formatTraktCalendarTv($array)
  217. {
  218. $gotCalendar = array();
  219. $i = 0;
  220. foreach ($array as $child) {
  221. $i++;
  222. $seriesName = $child['show']['title'];
  223. $seriesID = $child['show']['ids']['tmdb'];
  224. $episodeID = $child['show']['ids']['tmdb'];
  225. if (!isset($episodeID)) {
  226. $episodeID = "";
  227. }
  228. //$episodeName = htmlentities($child['title'], ENT_QUOTES);
  229. $episodeAirDate = $child['first_aired'];
  230. $episodeAirDate = strtotime($episodeAirDate);
  231. $episodeAirDate = date("Y-m-d H:i:s", $episodeAirDate);
  232. if (new DateTime() < new DateTime($episodeAirDate)) {
  233. $unaired = true;
  234. }
  235. if ($child['episode']['number'] == 1) {
  236. $episodePremier = "true";
  237. } else {
  238. $episodePremier = "false";
  239. $date = new DateTime($episodeAirDate);
  240. $date->add(new DateInterval("PT1S"));
  241. $date->format(DateTime::ATOM);
  242. $child['first_aired'] = gmdate('Y-m-d\TH:i:s\Z', strtotime($date->format(DateTime::ATOM)));
  243. }
  244. $downloaded = 0;
  245. $monitored = 0;
  246. if ($downloaded == "0" && isset($unaired) && $episodePremier == "true") {
  247. $downloaded = "text-primary animated flash";
  248. } elseif ($downloaded == "0" && isset($unaired) && $monitored == "0") {
  249. $downloaded = "text-dark";
  250. } elseif ($downloaded == "0" && isset($unaired)) {
  251. $downloaded = "text-info";
  252. } elseif ($downloaded == "1") {
  253. $downloaded = "text-success";
  254. } else {
  255. $downloaded = "text-danger";
  256. }
  257. $fanart = "/plugins/images/cache/no-np.png";
  258. $bottomTitle = 'S' . sprintf("%02d", $child['episode']['season']) . 'E' . sprintf("%02d", $child['episode']['number']) . ' - ' . $child['episode']['title'];
  259. $details = array(
  260. "seasonCount" => $child['episode']['season'],
  261. "status" => 'dunno',
  262. "topTitle" => $seriesName,
  263. "bottomTitle" => $bottomTitle,
  264. "overview" => isset($child['episode']['overview']) ? $child['episode']['overview'] : '',
  265. "runtime" => isset($child['episode']['runtime']) ? $child['episode']['runtime'] : '',
  266. "image" => $fanart,
  267. "ratings" => isset($child['show']['rating']) ? $child['show']['rating'] : '',
  268. "videoQuality" => "unknown",
  269. "audioChannels" => "unknown",
  270. "audioCodec" => "unknown",
  271. "videoCodec" => "unknown",
  272. "size" => "unknown",
  273. "genres" => isset($child['show']['genres']) ? $child['show']['genres'] : '',
  274. );
  275. array_push($gotCalendar, array(
  276. "id" => "Trakt-Tv-" . $i,
  277. "title" => $seriesName,
  278. "start" => $child['first_aired'],
  279. "className" => "inline-popups bg-calendar calendar-item get-tmdb-image tmdb-tv tmdbID--" . $seriesID,
  280. "imagetype" => "tv " . $downloaded,
  281. "imagetypeFilter" => "tv",
  282. "downloadFilter" => $downloaded,
  283. "bgColor" => str_replace('text', 'bg', $downloaded),
  284. "details" => $details
  285. ));
  286. }
  287. if ($i != 0) {
  288. return $gotCalendar;
  289. }
  290. return false;
  291. }
  292. public function formatTraktCalendarMovies($array)
  293. {
  294. $gotCalendar = array();
  295. $i = 0;
  296. foreach ($array as $child) {
  297. $i++;
  298. $movieName = $child['movie']['title'];
  299. $movieID = $child['movie']['ids']['tmdb'];
  300. if (!isset($movieID)) {
  301. $movieID = '';
  302. }
  303. $physicalRelease = (isset($child['movie']['released']) ? $child['movie']['released'] : null);
  304. //$backupRelease = (isset($child['info']['release_date']['theater']) ? $child['info']['release_date']['theater'] : null);
  305. //$physicalRelease = (isset($physicalRelease) ? $physicalRelease : $backupRelease);
  306. $physicalRelease = strtotime($physicalRelease);
  307. $physicalRelease = date('Y-m-d', $physicalRelease);
  308. $oldestDay = new DateTime ($this->currentTime);
  309. $oldestDay->modify('-' . $this->config['calendarStart'] . ' days');
  310. $newestDay = new DateTime ($this->currentTime);
  311. $newestDay->modify('+' . $this->config['calendarEnd'] . ' days');
  312. $startDt = new DateTime ($physicalRelease);
  313. if (new DateTime() < $startDt) {
  314. $notReleased = 'true';
  315. } else {
  316. $notReleased = 'false';
  317. }
  318. $downloaded = 'text-dark';
  319. $banner = '/plugins/images/cache/no-np.png';
  320. $details = array(
  321. 'topTitle' => $movieName,
  322. 'bottomTitle' => $child['movie']['tagline'],
  323. 'status' => $child['movie']['status'],
  324. 'overview' => $child['movie']['overview'],
  325. 'runtime' => $child['movie']['runtime'],
  326. 'image' => $banner,
  327. 'ratings' => isset($child['movie']['rating']) ? $child['movie']['rating'] : '',
  328. 'videoQuality' => 'unknown',
  329. 'audioChannels' => '',
  330. 'audioCodec' => '',
  331. 'videoCodec' => '',
  332. 'genres' => $child['movie']['genres'],
  333. 'year' => isset($child['movie']['year']) ? $child['movie']['year'] : '',
  334. 'studio' => isset($child['movie']['year']) ? $child['movie']['year'] : '',
  335. );
  336. array_push($gotCalendar, array(
  337. 'id' => 'Trakt-Movie-' . $i,
  338. 'title' => $movieName,
  339. 'start' => $physicalRelease,
  340. 'className' => 'inline-popups bg-calendar calendar-item get-tmdb-image tmdb-movie tmdbID--' . $movieID,
  341. 'imagetype' => 'film ' . $downloaded,
  342. 'imagetypeFilter' => 'film',
  343. 'downloadFilter' => $downloaded,
  344. 'bgColor' => str_replace('text', 'bg', $downloaded),
  345. 'details' => $details
  346. ));
  347. }
  348. if ($i != 0) {
  349. return $gotCalendar;
  350. }
  351. return false;
  352. }
  353. }