ombi.php 18 KB

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