ombi.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  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. return $this->homepageCheckKeyPermissions($key, $permissions);
  99. }
  100. public function homepageOrderombi()
  101. {
  102. if ($this->homepageItemPermissions($this->ombiHomepagePermissions('main'))) {
  103. return '
  104. <div id="' . __FUNCTION__ . '">
  105. <div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Requests...</h2></div>
  106. <script>
  107. // Ombi Requests
  108. homepageRequests("' . $this->config['ombiRefresh'] . '");
  109. // End Ombi Requests
  110. </script>
  111. </div>
  112. ';
  113. }
  114. }
  115. public function getOmbiRequests($type = "both", $limit = 50, $offset = 0)
  116. {
  117. if (!$this->homepageItemPermissions($this->ombiHomepagePermissions('main'), true)) {
  118. return false;
  119. }
  120. $api['count'] = array(
  121. 'movie' => 0,
  122. 'tv' => 0,
  123. 'limit' => (integer)$limit,
  124. 'offset' => (integer)$offset
  125. );
  126. $headers = array(
  127. "Accept" => "application/json",
  128. "Apikey" => $this->config['ombiToken'],
  129. );
  130. $requests = array();
  131. $url = $this->qualifyURL($this->config['ombiURL']);
  132. try {
  133. $options = $this->requestOptions($url, $this->config['ombiRefresh'], $this->config['ombiDisableCertCheck'], $this->config['ombiUseCustomCertificate']);
  134. switch ($type) {
  135. case 'movie':
  136. $movie = Requests::get($url . "/api/v1/Request/movie", $headers, $options);
  137. break;
  138. case 'tv':
  139. $tv = Requests::get($url . "/api/v1/Request/tv", $headers, $options);
  140. break;
  141. default:
  142. $movie = Requests::get($url . "/api/v1/Request/movie", $headers, $options);
  143. $tv = Requests::get($url . "/api/v1/Request/tv", $headers, $options);
  144. break;
  145. }
  146. if ($movie->success || $tv->success) {
  147. if (isset($movie)) {
  148. $movie = json_decode($movie->body, true);
  149. //$movie = array_reverse($movie);
  150. foreach ($movie as $key => $value) {
  151. $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);
  152. if ($proceed) {
  153. $api['count']['movie']++;
  154. $requests[] = array(
  155. 'id' => $value['theMovieDbId'],
  156. 'title' => $value['title'],
  157. 'overview' => $value['overview'],
  158. 'poster' => (isset($value['posterPath']) && $value['posterPath'] !== '') ? 'https://image.tmdb.org/t/p/w300/' . $value['posterPath'] : 'plugins/images/cache/no-list.png',
  159. 'background' => (isset($value['background']) && $value['background'] !== '') ? 'https://image.tmdb.org/t/p/w1280/' . $value['background'] : '',
  160. 'approved' => $value['approved'],
  161. 'available' => $value['available'],
  162. 'denied' => $value['denied'],
  163. 'deniedReason' => $value['deniedReason'],
  164. 'user' => $value['requestedUser']['userName'],
  165. 'userAlias' => $value['requestedUser']['userAlias'],
  166. 'request_id' => $value['id'],
  167. 'request_date' => $value['requestedDate'],
  168. 'release_date' => $value['releaseDate'],
  169. 'type' => 'movie',
  170. 'icon' => 'mdi mdi-filmstrip',
  171. 'color' => 'palette-Deep-Purple-900 bg white',
  172. );
  173. }
  174. }
  175. }
  176. if (isset($tv) && (is_array($tv) || is_object($tv))) {
  177. $tv = json_decode($tv->body, true);
  178. foreach ($tv as $key => $value) {
  179. if (count($value['childRequests']) > 0) {
  180. $proceed = (($this->config['ombiLimitUser']) && strtolower($this->user['username']) == strtolower($value['childRequests'][0]['requestedUser']['userName'])) || (!$this->config['ombiLimitUser']) || $this->qualifyRequest(1);
  181. if ($proceed) {
  182. $api['count']['tv']++;
  183. $requests[] = array(
  184. 'id' => $value['tvDbId'],
  185. 'title' => $value['title'],
  186. 'overview' => $value['overview'],
  187. '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',
  188. 'background' => (isset($value['background']) && $value['background'] !== '') ? 'https://image.tmdb.org/t/p/w1280/' . $value['background'] : '',
  189. 'approved' => $value['childRequests'][0]['approved'],
  190. 'available' => $value['childRequests'][0]['available'],
  191. 'denied' => $value['childRequests'][0]['denied'],
  192. 'deniedReason' => $value['childRequests'][0]['deniedReason'],
  193. 'user' => $value['childRequests'][0]['requestedUser']['userName'],
  194. 'userAlias' => $value['childRequests'][0]['requestedUser']['userAlias'],
  195. 'request_id' => $value['id'],
  196. 'request_date' => $value['childRequests'][0]['requestedDate'],
  197. 'release_date' => $value['releaseDate'],
  198. 'type' => 'tv',
  199. 'icon' => 'mdi mdi-television',
  200. 'color' => 'grayish-blue-bg',
  201. );
  202. }
  203. }
  204. }
  205. }
  206. //sort here
  207. usort($requests, function ($item1, $item2) {
  208. if ($item1['request_date'] == $item2['request_date']) {
  209. return 0;
  210. }
  211. return $item1['request_date'] > $item2['request_date'] ? -1 : 1;
  212. });
  213. }
  214. } catch (Requests_Exception $e) {
  215. $this->writeLog('error', 'OMBI Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
  216. $this->setAPIResponse('error', $e->getMessage(), 500);
  217. return false;
  218. };
  219. $api['content'] = isset($requests) ? array_slice($requests, $offset, $limit) : false;
  220. $this->setAPIResponse('success', null, 200, $api);
  221. return $api;
  222. }
  223. public function addOmbiRequest($id, $type)
  224. {
  225. $id = ($id) ?? null;
  226. $type = ($type) ?? null;
  227. if (!$id) {
  228. $this->setAPIResponse('error', 'Id was not supplied', 422);
  229. return false;
  230. }
  231. if (!$type) {
  232. $this->setAPIResponse('error', 'Type was not supplied', 422);
  233. return false;
  234. }
  235. if (!$this->homepageItemPermissions($this->ombiHomepagePermissions('main'), true)) {
  236. return false;
  237. }
  238. $url = $this->qualifyURL($this->config['ombiURL']);
  239. switch ($type) {
  240. case 'season':
  241. case 'tv':
  242. $type = 'tv';
  243. $add = array(
  244. 'tvDbId' => $id,
  245. 'requestAll' => $this->ombiTVDefault('all'),
  246. 'latestSeason' => $this->ombiTVDefault('last'),
  247. 'firstSeason' => $this->ombiTVDefault('first')
  248. );
  249. break;
  250. default:
  251. $type = 'movie';
  252. $add = array("theMovieDbId" => (int)$id);
  253. break;
  254. }
  255. try {
  256. $options = array('timeout' => 30);
  257. if (isset($_COOKIE['Auth'])) {
  258. $headers = array(
  259. "Accept" => "application/json",
  260. "Content-Type" => "application/json",
  261. "Authorization" => "Bearer " . $_COOKIE['Auth']
  262. );
  263. } else {
  264. $this->setAPIResponse('error', 'User does not have Auth Cookie', 500);
  265. return false;
  266. }
  267. //https://api.themoviedb.org/3/movie/157336?api_key=83cf4ee97bb728eeaf9d4a54e64356a1
  268. // Lets check if it exists inside Ombi first... but since I can't search with ID - i have to query title from id
  269. $tmdbResponse = Requests::get('https://api.themoviedb.org/3/' . $type . '/' . $id . '?api_key=83cf4ee97bb728eeaf9d4a54e64356a1', [], $options);
  270. if ($tmdbResponse->success) {
  271. $details = json_decode($tmdbResponse->body, true);
  272. if (count($details) > 0) {
  273. switch ($type) {
  274. case 'tv':
  275. $title = $details['name'];
  276. $idType = 'theTvDbId';
  277. $tmdbResponseID = Requests::get('https://api.themoviedb.org/3/tv/' . $id . '/external_ids?api_key=83cf4ee97bb728eeaf9d4a54e64356a1', [], $options);
  278. if ($tmdbResponseID->success) {
  279. $detailsID = json_decode($tmdbResponseID->body, true);
  280. if (count($detailsID) > 0) {
  281. if (isset($detailsID['tvdb_id'])) {
  282. $id = $detailsID['tvdb_id'];
  283. $add['tvDbId'] = $id;
  284. } else {
  285. $this->setAPIResponse('error', 'Could not get TVDB Id', 422);
  286. return false;
  287. }
  288. } else {
  289. $this->setAPIResponse('error', 'Could not get TVDB Id', 422);
  290. return false;
  291. }
  292. }
  293. break;
  294. case 'movie':
  295. $title = $details['title'];
  296. $idType = 'theMovieDbId';
  297. break;
  298. default:
  299. $this->setAPIResponse('error', 'Ombi Type was not found', 422);
  300. return false;
  301. }
  302. } else {
  303. $this->setAPIResponse('error', 'No data returned from TMDB', 422);
  304. return false;
  305. }
  306. } else {
  307. $this->setAPIResponse('error', 'Could not contact TMDB', 422);
  308. return false;
  309. }
  310. $options = $this->requestOptions($url, null, $this->config['ombiDisableCertCheck'], $this->config['ombiUseCustomCertificate']);
  311. $searchResponse = Requests::get($url . '/api/v1/Search/' . $type . '/' . urlencode($title), $headers, $options);
  312. if ($searchResponse->success) {
  313. $details = json_decode($searchResponse->body, true);
  314. if (count($details) > 0) {
  315. foreach ($details as $k => $v) {
  316. if ($v[$idType] == $id) {
  317. if ($v['available']) {
  318. $this->setAPIResponse('error', 'Request is already available', 409);
  319. return false;
  320. } elseif ($v['requested']) {
  321. $this->setAPIResponse('error', 'Request is already requested', 409);
  322. return false;
  323. }
  324. }
  325. }
  326. }
  327. } else {
  328. $this->setAPIResponse('error', 'Ombi Error Occurred', 500);
  329. return false;
  330. }
  331. $response = Requests::post($url . "/api/v1/Request/" . $type, $headers, json_encode($add), $options);
  332. if ($response->success) {
  333. $this->setAPIResponse('success', 'Ombi Request submitted', 200);
  334. return true;
  335. } else {
  336. $this->setAPIResponse('error', 'Ombi Error Occurred', 500);
  337. return false;
  338. }
  339. } catch (Requests_Exception $e) {
  340. $this->writeLog('error', 'OMBI Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
  341. $this->setAPIResponse('error', $e->getMessage(), 500);
  342. return false;
  343. }
  344. }
  345. public function actionOmbiRequest($id, $type, $action)
  346. {
  347. $id = ($id) ?? null;
  348. $type = ($type) ?? null;
  349. $action = ($action) ?? null;
  350. if (!$id) {
  351. $this->setAPIResponse('error', 'Id was not supplied', 422);
  352. return false;
  353. }
  354. if (!$type) {
  355. $this->setAPIResponse('error', 'Type was not supplied', 422);
  356. return false;
  357. }
  358. if (!$action) {
  359. $this->setAPIResponse('error', 'Action was not supplied', 422);
  360. return false;
  361. }
  362. if (!$this->homepageItemPermissions($this->ombiHomepagePermissions('main'), true)) {
  363. return false;
  364. }
  365. $url = $this->qualifyURL($this->config['ombiURL']);
  366. $headers = array(
  367. "Accept" => "application/json",
  368. "Content-Type" => "application/json",
  369. "Apikey" => $this->config['ombiToken']
  370. );
  371. $data = array(
  372. 'id' => $id,
  373. );
  374. switch ($type) {
  375. case 'season':
  376. case 'tv':
  377. $type = 'tv';
  378. break;
  379. default:
  380. $type = 'movie';
  381. break;
  382. }
  383. try {
  384. $options = $this->requestOptions($url, 60, $this->config['ombiDisableCertCheck'], $this->config['ombiUseCustomCertificate']);
  385. switch ($action) {
  386. case 'approve':
  387. $response = Requests::post($url . "/api/v1/Request/" . $type . "/approve", $headers, json_encode($data), $options);
  388. $message = 'Ombi Request has been approved';
  389. break;
  390. case 'available':
  391. $response = Requests::post($url . "/api/v1/Request/" . $type . "/available", $headers, json_encode($data), $options);
  392. $message = 'Ombi Request has been marked available';
  393. break;
  394. case 'unavailable':
  395. $response = Requests::post($url . "/api/v1/Request/" . $type . "/unavailable", $headers, json_encode($data), $options);
  396. $message = 'Ombi Request has been marked unavailable';
  397. break;
  398. case 'deny':
  399. $response = Requests::put($url . "/api/v1/Request/" . $type . "/deny", $headers, json_encode($data), $options);
  400. $message = 'Ombi Request has been denied';
  401. break;
  402. case 'delete':
  403. $response = Requests::delete($url . "/api/v1/Request/" . $type . "/" . $id, $headers, $options);
  404. $message = 'Ombi Request has been deleted';
  405. break;
  406. default:
  407. return false;
  408. }
  409. if ($response->success) {
  410. $this->setAPIResponse('success', $message, 200);
  411. return true;
  412. } else {
  413. $this->setAPIResponse('error', 'Ombi Error Occurred', 500);
  414. return false;
  415. }
  416. } catch (Requests_Exception $e) {
  417. $this->writeLog('error', 'OMBI Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
  418. $this->setAPIResponse('error', $e->getMessage(), 500);
  419. return false;
  420. };
  421. }
  422. public function ombiTVDefault($type)
  423. {
  424. return $type == $this->config['ombiTvDefault'];
  425. }
  426. }