ombi.php 16 KB

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