ombi.php 18 KB

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