ombi.php 18 KB

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