ombi.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. <?php
  2. trait OmbiHomepageItem
  3. {
  4. public function ombiSettingsArray($infoOnly = false)
  5. {
  6. $homepageInformation = [
  7. 'name' => 'Ombi',
  8. 'enabled' => strpos('personal', $this->config['license']) !== false,
  9. 'image' => 'plugins/images/tabs/ombi.png',
  10. 'category' => 'Requests',
  11. 'settingsArray' => __FUNCTION__
  12. ];
  13. if ($infoOnly) {
  14. return $homepageInformation;
  15. }
  16. $homepageSettings = array(
  17. 'debug' => true,
  18. 'settings' => array(
  19. 'Enable' => array(
  20. array(
  21. 'type' => 'switch',
  22. 'name' => 'homepageOmbiEnabled',
  23. 'label' => 'Enable',
  24. 'value' => $this->config['homepageOmbiEnabled']
  25. ),
  26. array(
  27. 'type' => 'select',
  28. 'name' => 'homepageOmbiAuth',
  29. 'label' => 'Minimum Authentication',
  30. 'value' => $this->config['homepageOmbiAuth'],
  31. 'options' => $this->groupOptions
  32. )
  33. ),
  34. 'Connection' => array(
  35. array(
  36. 'type' => 'input',
  37. 'name' => 'ombiURL',
  38. 'label' => 'URL',
  39. 'value' => $this->config['ombiURL'],
  40. 'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
  41. 'placeholder' => 'http(s)://hostname:port'
  42. ),
  43. array(
  44. 'type' => 'password-alt',
  45. 'name' => 'ombiToken',
  46. 'label' => 'Token',
  47. 'value' => $this->config['ombiToken']
  48. ),
  49. array(
  50. 'type' => 'input',
  51. 'name' => 'ombiFallbackUser',
  52. 'label' => 'Ombi Fallback User',
  53. 'value' => $this->config['ombiFallbackUser'],
  54. 'help' => 'Organizr will request an Ombi User Token based off of this user credentials'
  55. ),
  56. array(
  57. 'type' => 'password-alt',
  58. 'name' => 'ombiFallbackPassword',
  59. 'label' => 'Ombi Fallback Password',
  60. 'value' => $this->config['ombiFallbackPassword']
  61. ),
  62. ),
  63. 'Misc Options' => array(
  64. array(
  65. 'type' => 'select',
  66. 'name' => 'homepageOmbiRequestAuth',
  67. 'label' => 'Minimum Group to Request',
  68. 'value' => $this->config['homepageOmbiRequestAuth'],
  69. 'options' => $this->groupOptions
  70. ),
  71. array(
  72. 'type' => 'select',
  73. 'name' => 'ombiTvDefault',
  74. 'label' => 'TV Show Default Request',
  75. 'value' => $this->config['ombiTvDefault'],
  76. 'options' => $this->ombiTvOptions()
  77. ),
  78. array(
  79. 'type' => 'switch',
  80. 'name' => 'ombiLimitUser',
  81. 'label' => 'Limit to User',
  82. 'value' => $this->config['ombiLimitUser']
  83. ),
  84. array(
  85. 'type' => 'number',
  86. 'name' => 'ombiLimit',
  87. 'label' => 'Item Limit',
  88. 'value' => $this->config['ombiLimit'],
  89. ),
  90. array(
  91. 'type' => 'select',
  92. 'name' => 'ombiRefresh',
  93. 'label' => 'Refresh Seconds',
  94. 'value' => $this->config['ombiRefresh'],
  95. 'options' => $this->timeOptions()
  96. ),
  97. array(
  98. 'type' => 'switch',
  99. 'name' => 'ombiAlias',
  100. 'label' => 'Use Ombi Alias Names',
  101. 'value' => $this->config['ombiAlias'],
  102. 'help' => 'Use Ombi Alias Names instead of Usernames - If Alias is blank, Alias will fallback to Username'
  103. )
  104. ),
  105. 'Default Filter' => array(
  106. array(
  107. 'type' => 'switch',
  108. 'name' => 'ombiDefaultFilterAvailable',
  109. 'label' => 'Show Available',
  110. 'value' => $this->config['ombiDefaultFilterAvailable'],
  111. 'help' => 'Show All Available Ombi Requests'
  112. ),
  113. array(
  114. 'type' => 'switch',
  115. 'name' => 'ombiDefaultFilterUnavailable',
  116. 'label' => 'Show Unavailable',
  117. 'value' => $this->config['ombiDefaultFilterUnavailable'],
  118. 'help' => 'Show All Unavailable Ombi Requests'
  119. ),
  120. array(
  121. 'type' => 'switch',
  122. 'name' => 'ombiDefaultFilterApproved',
  123. 'label' => 'Show Approved',
  124. 'value' => $this->config['ombiDefaultFilterApproved'],
  125. 'help' => 'Show All Approved Ombi Requests'
  126. ),
  127. array(
  128. 'type' => 'switch',
  129. 'name' => 'ombiDefaultFilterUnapproved',
  130. 'label' => 'Show Unapproved',
  131. 'value' => $this->config['ombiDefaultFilterUnapproved'],
  132. 'help' => 'Show All Unapproved Ombi Requests'
  133. ),
  134. array(
  135. 'type' => 'switch',
  136. 'name' => 'ombiDefaultFilterDenied',
  137. 'label' => 'Show Denied',
  138. 'value' => $this->config['ombiDefaultFilterDenied'],
  139. 'help' => 'Show All Denied Ombi Requests'
  140. )
  141. ),
  142. 'Test Connection' => array(
  143. array(
  144. 'type' => 'blank',
  145. 'label' => 'Please Save before Testing'
  146. ),
  147. array(
  148. 'type' => 'button',
  149. 'label' => '',
  150. 'icon' => 'fa fa-flask',
  151. 'class' => 'pull-right',
  152. 'text' => 'Test Connection',
  153. 'attr' => 'onclick="testAPIConnection(\'ombi\')"'
  154. ),
  155. )
  156. )
  157. );
  158. return array_merge($homepageInformation, $homepageSettings);
  159. }
  160. public function testConnectionOmbi()
  161. {
  162. if (empty($this->config['ombiURL'])) {
  163. $this->setAPIResponse('error', 'Ombi URL is not defined', 422);
  164. return false;
  165. }
  166. if (empty($this->config['ombiToken'])) {
  167. $this->setAPIResponse('error', 'Ombi Token is not defined', 422);
  168. return false;
  169. }
  170. $headers = array(
  171. "Accept" => "application/json",
  172. "Apikey" => $this->config['ombiToken'],
  173. );
  174. $url = $this->qualifyURL($this->config['ombiURL']);
  175. try {
  176. $options = ($this->localURL($url)) ? array('verify' => false) : array();
  177. $test = Requests::get($url . "/api/v1/Settings/about", $headers, $options);
  178. if ($test->success) {
  179. $this->setAPIResponse('success', 'API Connection succeeded', 200);
  180. return true;
  181. }
  182. } catch (Requests_Exception $e) {
  183. $this->writeLog('error', 'OMBI Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
  184. $this->setAPIResponse('error', $e->getMessage(), 500);
  185. return false;
  186. };
  187. }
  188. public function ombiHomepagePermissions($key = null)
  189. {
  190. $permissions = [
  191. 'main' => [
  192. 'enabled' => [
  193. 'homepageOmbiEnabled'
  194. ],
  195. 'auth' => [
  196. 'homepageOmbiAuth'
  197. ],
  198. 'not_empty' => [
  199. 'ombiURL',
  200. 'ombiToken'
  201. ]
  202. ]
  203. ];
  204. if (array_key_exists($key, $permissions)) {
  205. return $permissions[$key];
  206. } elseif ($key == 'all') {
  207. return $permissions;
  208. } else {
  209. return [];
  210. }
  211. }
  212. public function homepageOrderombi()
  213. {
  214. if ($this->homepageItemPermissions($this->ombiHomepagePermissions('main'))) {
  215. return '
  216. <div id="' . __FUNCTION__ . '">
  217. <div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Requests...</h2></div>
  218. <script>
  219. // Ombi Requests
  220. homepageRequests("' . $this->config['ombiRefresh'] . '");
  221. // End Ombi Requests
  222. </script>
  223. </div>
  224. ';
  225. }
  226. }
  227. public function getOmbiRequests($type = "both", $limit = 50, $offset = 0)
  228. {
  229. if (!$this->homepageItemPermissions($this->ombiHomepagePermissions('main'), true)) {
  230. return false;
  231. }
  232. $api['count'] = array(
  233. 'movie' => 0,
  234. 'tv' => 0,
  235. 'limit' => (integer)$limit,
  236. 'offset' => (integer)$offset
  237. );
  238. $headers = array(
  239. "Accept" => "application/json",
  240. "Apikey" => $this->config['ombiToken'],
  241. );
  242. $requests = array();
  243. $url = $this->qualifyURL($this->config['ombiURL']);
  244. try {
  245. $options = ($this->localURL($url)) ? array('verify' => false) : array();
  246. switch ($type) {
  247. case 'movie':
  248. $movie = Requests::get($url . "/api/v1/Request/movie", $headers, $options);
  249. break;
  250. case 'tv':
  251. $tv = Requests::get($url . "/api/v1/Request/tv", $headers, $options);
  252. break;
  253. default:
  254. $movie = Requests::get($url . "/api/v1/Request/movie", $headers, $options);
  255. $tv = Requests::get($url . "/api/v1/Request/tv", $headers, $options);
  256. break;
  257. }
  258. if ($movie->success || $tv->success) {
  259. if (isset($movie)) {
  260. $movie = json_decode($movie->body, true);
  261. //$movie = array_reverse($movie);
  262. foreach ($movie as $key => $value) {
  263. $proceed = (($this->config['ombiLimitUser']) && strtolower($this->user['username']) == strtolower($value['requestedUser']['userName'])) || (strtolower($value['requestedUser']['userName']) == strtolower($this->config['ombiFallbackUser'])) || (!$this->config['ombiLimitUser']) || $this->qualifyRequest(1);
  264. if ($proceed) {
  265. $api['count']['movie']++;
  266. $requests[] = array(
  267. 'id' => $value['theMovieDbId'],
  268. 'title' => $value['title'],
  269. 'overview' => $value['overview'],
  270. 'poster' => (isset($value['posterPath']) && $value['posterPath'] !== '') ? 'https://image.tmdb.org/t/p/w300/' . $value['posterPath'] : 'plugins/images/cache/no-list.png',
  271. 'background' => (isset($value['background']) && $value['background'] !== '') ? 'https://image.tmdb.org/t/p/w1280/' . $value['background'] : '',
  272. 'approved' => $value['approved'],
  273. 'available' => $value['available'],
  274. 'denied' => $value['denied'],
  275. 'deniedReason' => $value['deniedReason'],
  276. 'user' => $value['requestedUser']['userName'],
  277. 'userAlias' => $value['requestedUser']['userAlias'],
  278. 'request_id' => $value['id'],
  279. 'request_date' => $value['requestedDate'],
  280. 'release_date' => $value['releaseDate'],
  281. 'type' => 'movie',
  282. 'icon' => 'mdi mdi-filmstrip',
  283. 'color' => 'palette-Deep-Purple-900 bg white',
  284. );
  285. }
  286. }
  287. }
  288. if (isset($tv) && (is_array($tv) || is_object($tv))) {
  289. $tv = json_decode($tv->body, true);
  290. foreach ($tv as $key => $value) {
  291. if (count($value['childRequests']) > 0) {
  292. $proceed = (($this->config['ombiLimitUser']) && strtolower($this->user['username']) == strtolower($value['childRequests'][0]['requestedUser']['userName'])) || (!$this->config['ombiLimitUser']) || $this->qualifyRequest(1);
  293. if ($proceed) {
  294. $api['count']['tv']++;
  295. $requests[] = array(
  296. 'id' => $value['tvDbId'],
  297. 'title' => $value['title'],
  298. 'overview' => $value['overview'],
  299. 'poster' => (isset($value['posterPath']) && $value['posterPath'] !== '') ? (str_starts_with($value['posterPath'], '/') ? 'https://image.tmdb.org/t/p/w300/' . $value['posterPath'] : $value['posterPath']) : 'plugins/images/cache/no-list.png',
  300. 'background' => (isset($value['background']) && $value['background'] !== '') ? 'https://image.tmdb.org/t/p/w1280/' . $value['background'] : '',
  301. 'approved' => $value['childRequests'][0]['approved'],
  302. 'available' => $value['childRequests'][0]['available'],
  303. 'denied' => $value['childRequests'][0]['denied'],
  304. 'deniedReason' => $value['childRequests'][0]['deniedReason'],
  305. 'user' => $value['childRequests'][0]['requestedUser']['userName'],
  306. 'userAlias' => $value['childRequests'][0]['requestedUser']['userAlias'],
  307. 'request_id' => $value['id'],
  308. 'request_date' => $value['childRequests'][0]['requestedDate'],
  309. 'release_date' => $value['releaseDate'],
  310. 'type' => 'tv',
  311. 'icon' => 'mdi mdi-television',
  312. 'color' => 'grayish-blue-bg',
  313. );
  314. }
  315. }
  316. }
  317. }
  318. //sort here
  319. usort($requests, function ($item1, $item2) {
  320. if ($item1['request_date'] == $item2['request_date']) {
  321. return 0;
  322. }
  323. return $item1['request_date'] > $item2['request_date'] ? -1 : 1;
  324. });
  325. }
  326. } catch (Requests_Exception $e) {
  327. $this->writeLog('error', 'OMBI Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
  328. $this->setAPIResponse('error', $e->getMessage(), 500);
  329. return false;
  330. };
  331. $api['content'] = isset($requests) ? array_slice($requests, $offset, $limit) : false;
  332. $this->setAPIResponse('success', null, 200, $api);
  333. return $api;
  334. }
  335. public function addOmbiRequest($id, $type)
  336. {
  337. $id = ($id) ?? null;
  338. $type = ($type) ?? null;
  339. if (!$id) {
  340. $this->setAPIResponse('error', 'Id was not supplied', 422);
  341. return false;
  342. }
  343. if (!$type) {
  344. $this->setAPIResponse('error', 'Type was not supplied', 422);
  345. return false;
  346. }
  347. if (!$this->homepageItemPermissions($this->ombiHomepagePermissions('main'), true)) {
  348. return false;
  349. }
  350. $url = $this->qualifyURL($this->config['ombiURL']);
  351. switch ($type) {
  352. case 'season':
  353. case 'tv':
  354. $type = 'tv';
  355. $add = array(
  356. 'tvDbId' => $id,
  357. 'requestAll' => $this->ombiTVDefault('all'),
  358. 'latestSeason' => $this->ombiTVDefault('last'),
  359. 'firstSeason' => $this->ombiTVDefault('first')
  360. );
  361. break;
  362. default:
  363. $type = 'movie';
  364. $add = array("theMovieDbId" => (int)$id);
  365. break;
  366. }
  367. try {
  368. $options = ($this->localURL($url)) ? array('verify' => false, 'timeout' => 30) : array('timeout' => 30);
  369. if (isset($_COOKIE['Auth'])) {
  370. $headers = array(
  371. "Accept" => "application/json",
  372. "Content-Type" => "application/json",
  373. "Authorization" => "Bearer " . $_COOKIE['Auth']
  374. );
  375. } else {
  376. $this->setAPIResponse('error', 'User does not have Auth Cookie', 500);
  377. return false;
  378. }
  379. //https://api.themoviedb.org/3/movie/157336?api_key=83cf4ee97bb728eeaf9d4a54e64356a1
  380. // Lets check if it exists inside Ombi first... but since I can't search with ID - i have to query title from id
  381. $tmdbResponse = Requests::get('https://api.themoviedb.org/3/' . $type . '/' . $id . '?api_key=83cf4ee97bb728eeaf9d4a54e64356a1', [], $options);
  382. if ($tmdbResponse->success) {
  383. $details = json_decode($tmdbResponse->body, true);
  384. if (count($details) > 0) {
  385. switch ($type) {
  386. case 'tv':
  387. $title = $details['name'];
  388. $idType = 'theTvDbId';
  389. $tmdbResponseID = Requests::get('https://api.themoviedb.org/3/tv/' . $id . '/external_ids?api_key=83cf4ee97bb728eeaf9d4a54e64356a1', [], $options);
  390. if ($tmdbResponseID->success) {
  391. $detailsID = json_decode($tmdbResponseID->body, true);
  392. if (count($detailsID) > 0) {
  393. if (isset($detailsID['tvdb_id'])) {
  394. $id = $detailsID['tvdb_id'];
  395. $add['tvDbId'] = $id;
  396. } else {
  397. $this->setAPIResponse('error', 'Could not get TVDB Id', 422);
  398. return false;
  399. }
  400. } else {
  401. $this->setAPIResponse('error', 'Could not get TVDB Id', 422);
  402. return false;
  403. }
  404. }
  405. break;
  406. case 'movie':
  407. $title = $details['title'];
  408. $idType = 'theMovieDbId';
  409. break;
  410. default:
  411. $this->setAPIResponse('error', 'Ombi Type was not found', 422);
  412. return false;
  413. }
  414. } else {
  415. $this->setAPIResponse('error', 'No data returned from TMDB', 422);
  416. return false;
  417. }
  418. } else {
  419. $this->setAPIResponse('error', 'Could not contact TMDB', 422);
  420. return false;
  421. }
  422. $searchResponse = Requests::get($url . '/api/v1/Search/' . $type . '/' . urlencode($title), $headers, $options);
  423. if ($searchResponse->success) {
  424. $details = json_decode($searchResponse->body, true);
  425. if (count($details) > 0) {
  426. foreach ($details as $k => $v) {
  427. if ($v[$idType] == $id) {
  428. if ($v['available']) {
  429. $this->setAPIResponse('error', 'Request is already available', 409);
  430. return false;
  431. } elseif ($v['requested']) {
  432. $this->setAPIResponse('error', 'Request is already requested', 409);
  433. return false;
  434. }
  435. }
  436. }
  437. }
  438. } else {
  439. $this->setAPIResponse('error', 'Ombi Error Occurred', 500);
  440. return false;
  441. }
  442. $response = Requests::post($url . "/api/v1/Request/" . $type, $headers, json_encode($add), $options);
  443. if ($response->success) {
  444. $this->setAPIResponse('success', 'Ombi Request submitted', 200);
  445. return true;
  446. } else {
  447. $this->setAPIResponse('error', 'Ombi Error Occurred', 500);
  448. return false;
  449. }
  450. } catch (Requests_Exception $e) {
  451. $this->writeLog('error', 'OMBI Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
  452. $this->setAPIResponse('error', $e->getMessage(), 500);
  453. return false;
  454. }
  455. }
  456. public function actionOmbiRequest($id, $type, $action)
  457. {
  458. $id = ($id) ?? null;
  459. $type = ($type) ?? null;
  460. $action = ($action) ?? null;
  461. if (!$id) {
  462. $this->setAPIResponse('error', 'Id was not supplied', 422);
  463. return false;
  464. }
  465. if (!$type) {
  466. $this->setAPIResponse('error', 'Type was not supplied', 422);
  467. return false;
  468. }
  469. if (!$action) {
  470. $this->setAPIResponse('error', 'Action was not supplied', 422);
  471. return false;
  472. }
  473. if (!$this->homepageItemPermissions($this->ombiHomepagePermissions('main'), true)) {
  474. return false;
  475. }
  476. $url = $this->qualifyURL($this->config['ombiURL']);
  477. $headers = array(
  478. "Accept" => "application/json",
  479. "Content-Type" => "application/json",
  480. "Apikey" => $this->config['ombiToken']
  481. );
  482. $data = array(
  483. 'id' => $id,
  484. );
  485. switch ($type) {
  486. case 'season':
  487. case 'tv':
  488. $type = 'tv';
  489. break;
  490. default:
  491. $type = 'movie';
  492. break;
  493. }
  494. try {
  495. $options = ($this->localURL($url)) ? array('verify' => false, 'timeout' => 30) : array('timeout' => 30);
  496. switch ($action) {
  497. case 'approve':
  498. $response = Requests::post($url . "/api/v1/Request/" . $type . "/approve", $headers, json_encode($data), $options);
  499. $message = 'Ombi Request has been approved';
  500. break;
  501. case 'available':
  502. $response = Requests::post($url . "/api/v1/Request/" . $type . "/available", $headers, json_encode($data), $options);
  503. $message = 'Ombi Request has been marked available';
  504. break;
  505. case 'unavailable':
  506. $response = Requests::post($url . "/api/v1/Request/" . $type . "/unavailable", $headers, json_encode($data), $options);
  507. $message = 'Ombi Request has been marked unavailable';
  508. break;
  509. case 'deny':
  510. $response = Requests::put($url . "/api/v1/Request/" . $type . "/deny", $headers, json_encode($data), $options);
  511. $message = 'Ombi Request has been denied';
  512. break;
  513. case 'delete':
  514. $response = Requests::delete($url . "/api/v1/Request/" . $type . "/" . $id, $headers, $options);
  515. $message = 'Ombi Request has been deleted';
  516. break;
  517. default:
  518. return false;
  519. }
  520. if ($response->success) {
  521. $this->setAPIResponse('success', $message, 200);
  522. return true;
  523. } else {
  524. $this->setAPIResponse('error', 'Ombi Error Occurred', 500);
  525. return false;
  526. }
  527. } catch (Requests_Exception $e) {
  528. $this->writeLog('error', 'OMBI Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
  529. $this->setAPIResponse('error', $e->getMessage(), 500);
  530. return false;
  531. };
  532. }
  533. public function ombiTVDefault($type)
  534. {
  535. return $type == $this->config['ombiTvDefault'];
  536. }
  537. }