From d7cf8f4b9fdda66425cf12a5c1c2f55c0c954c5e Mon Sep 17 00:00:00 2001 From: DariusIII Date: Mon, 4 Jun 2018 11:15:09 +0200 Subject: [PATCH] Complete v2 api, add related transformers and routes --- Blacklight/http/API.php | 26 +-- Changelog | 1 + app/Http/Controllers/Api/ApiV2Controller.php | 183 ++++++++++++++++++- app/Models/Category.php | 28 +++ app/Transformers/ApiTransformer.php | 89 +++++++++ app/Transformers/DetailsTransformer.php | 92 ++++++++++ app/Transformers/MoviesTransformer.php | 34 ---- routes/api.php | 19 +- 8 files changed, 416 insertions(+), 56 deletions(-) create mode 100644 app/Transformers/ApiTransformer.php create mode 100644 app/Transformers/DetailsTransformer.php delete mode 100644 app/Transformers/MoviesTransformer.php diff --git a/Blacklight/http/API.php b/Blacklight/http/API.php index e2a58b481..7598c78e0 100755 --- a/Blacklight/http/API.php +++ b/Blacklight/http/API.php @@ -78,13 +78,13 @@ class API extends Capabilities public function maxAge(): int { $maxAge = -1; - if (isset($this->getRequest['maxage'])) { - if ($this->getRequest['maxage'] === '') { + if (request()->has('maxage')) { + if (empty(request()->input('maxage'))) { Utility::showApiError(201, 'Incorrect parameter (maxage must not be empty)'); - } elseif (! is_numeric($this->getRequest['maxage'])) { + } elseif (! is_numeric(request()->input('maxage'))) { Utility::showApiError(201, 'Incorrect parameter (maxage must be numeric)'); } else { - $maxAge = (int) $this->getRequest['maxage']; + $maxAge = (int) request()->input('maxage'); } } @@ -98,8 +98,8 @@ class API extends Capabilities public function categoryID(): array { $categoryID[] = -1; - if (isset($this->getRequest['cat'])) { - $categoryIDs = urldecode($this->getRequest['cat']); + if (request()->has('cat')) { + $categoryIDs = urldecode(request()->input('cat')); // Append Web-DL category ID if HD present for SickBeard / Sonarr compatibility. if (strpos($categoryIDs, Category::TV_HD) !== false && strpos($categoryIDs, Category::TV_WEBDL) === false) { @@ -120,8 +120,8 @@ class API extends Capabilities public function group() { $groupName = -1; - if (isset($this->getRequest['group'])) { - $group = Group::isValidGroup($this->getRequest['group']); + if (request()->has('group')) { + $group = Group::isValidGroup(request()->input('group')); if ($group !== false) { $groupName = $group; } @@ -137,8 +137,8 @@ class API extends Capabilities public function limit(): int { $limit = 100; - if (isset($this->getRequest['limit']) && is_numeric($this->getRequest['limit']) && $this->getRequest['limit'] < 100) { - $limit = (int) $this->getRequest['limit']; + if (request()->has('limit') && is_numeric(request()->input('limit'))) { + $limit = (int) request()->input('limit'); } return $limit; @@ -151,8 +151,8 @@ class API extends Capabilities public function offset(): int { $offset = 0; - if (isset($this->getRequest['offset']) && is_numeric($this->getRequest['offset'])) { - $offset = (int) $this->getRequest['offset']; + if (request()->has('offset') && is_numeric(request()->input('offset'))) { + $offset = (int) request()->input('offset'); } return $offset; @@ -164,7 +164,7 @@ class API extends Capabilities */ public function verifyEmptyParameter($parameter): void { - if (isset($this->getRequest[$parameter]) && $this->getRequest[$parameter] === '') { + if (request()->has($parameter) && empty(request()->input($parameter))) { Utility::showApiError(201, 'Incorrect parameter ('.$parameter.' must not be empty)'); } } diff --git a/Changelog b/Changelog index b136ac35c..4f49093f2 100755 --- a/Changelog +++ b/Changelog @@ -1,4 +1,5 @@ 2018-06-04 DariusIII + * Chg: Complete v2 api, add related transformers and routes * Chg: Update phpunit, whoops and php-parser packages * Fix: Fix links in XML 2018-06-03 DariusIII diff --git a/app/Http/Controllers/Api/ApiV2Controller.php b/app/Http/Controllers/Api/ApiV2Controller.php index f44593cab..66a764096 100644 --- a/app/Http/Controllers/Api/ApiV2Controller.php +++ b/app/Http/Controllers/Api/ApiV2Controller.php @@ -3,22 +3,32 @@ namespace App\Http\Controllers\Api; use App\Models\Category; +use App\Models\Release; use App\Models\Settings; +use App\Models\User; +use App\Transformers\ApiTransformer; +use App\Transformers\DetailsTransformer; use Blacklight\http\API; use Blacklight\Releases; use App\Models\UserRequest; +use Blacklight\utility\Utility; use Illuminate\Http\Request; use App\Extensions\util\Versions; use App\Http\Controllers\Controller; -use App\Transformers\MoviesTransformer; use App\Transformers\CategoryTransformer; +use Illuminate\Support\Facades\Auth; class ApiV2Controller extends Controller { + public function __construct() + { + + } + /** - * @throws \Exception + * @return \Illuminate\Http\JsonResponse */ - public function capabilities() + public function capabilities(): \Illuminate\Http\JsonResponse { $serverroot = url('/'); $category = Category::getForApi(); @@ -57,13 +67,14 @@ class ApiV2Controller extends Controller * @return \Illuminate\Http\JsonResponse * @throws \Exception */ - public function movie(Request $request) + public function movie(Request $request): \Illuminate\Http\JsonResponse { + $user = Auth::user(); $api = new API(); $releases = new Releases(); $minSize = $request->has('minsize') && $request->input('minsize') > 0 ? $request->input('minsize') : 0; $maxAge = $api->maxAge(); - UserRequest::addApiRequest(\Auth::id(), $request->getRequestUri()); + UserRequest::addApiRequest($user->id, $request->getRequestUri()); $imdbId = $request->input('imdbid') ?? -1; @@ -77,7 +88,167 @@ class ApiV2Controller extends Controller $minSize ); - $relData = fractal($relData, new MoviesTransformer()); + $relData = fractal($relData, new ApiTransformer($user)); + + return response()->json($relData); + } + + /** + * @param \Illuminate\Http\Request $request + * + * @return \Illuminate\Http\JsonResponse + * @throws \Exception + */ + public function search(Request $request): \Illuminate\Http\JsonResponse + { + $user = Auth::user(); + $api = new API(); + $releases = new Releases(); + $offset = $api->offset(); + $catExclusions = User::getCategoryExclusion($user->id); + $minSize = $request->has('minsize') && $request->input('minsize') > 0 ? $request->input('minsize') : 0; + $maxAge = $api->maxAge(); + $groupName = $api->group(); + UserRequest::addApiRequest($user->id, $request->getRequestUri()); + $categoryID = $api->categoryID(); + $limit = $api->limit(); + + if ($request->has('id')) { + $relData = $releases->search( + $request->input('id'), + -1, + -1, + -1, + $groupName, + -1, + -1, + 0, + 0, + -1, + -1, + $offset, + $limit, + '', + $maxAge, + $catExclusions, + 'basic', + $categoryID, + $minSize + ); + } else { + $relData = $releases->getBrowseRange( + 1, + $categoryID, + $offset, + $limit, + '', + $maxAge, + $catExclusions, + $groupName, + $minSize + ); + } + + $relData = fractal($relData, new ApiTransformer($user)); + + return response()->json($relData); + } + + /** + * @param \Illuminate\Http\Request $request + * + * @return \Illuminate\Http\JsonResponse + * @throws \Exception + */ + public function tv(Request $request): \Illuminate\Http\JsonResponse + { + $user = Auth::user(); + $api = new API(); + $releases = new Releases(); + $minSize = $request->has('minsize') && $request->input('minsize') > 0 ? $request->input('minsize') : 0; + $api->verifyEmptyParameter('id'); + $api->verifyEmptyParameter('vid'); + $api->verifyEmptyParameter('tvdbid'); + $api->verifyEmptyParameter('traktid'); + $api->verifyEmptyParameter('rid'); + $api->verifyEmptyParameter('tvmazeid'); + $api->verifyEmptyParameter('imdbid'); + $api->verifyEmptyParameter('tmdbid'); + $api->verifyEmptyParameter('season'); + $api->verifyEmptyParameter('ep'); + $maxAge = $api->maxAge(); + UserRequest::addApiRequest($user->id, $request->getRequestUri()); + + $siteIdArr = [ + 'id' => $request->input('vid') ?? '0', + 'tvdb' => $request->input('tvdbid') ?? '0', + 'trakt' => $request->input('traktid') ?? '0', + 'tvrage' => $request->input('rid') ?? '0', + 'tvmaze' => $request->input('tvmazeid') ?? '0', + 'imdb' => $request->input('imdbid') ?? '0', + 'tmdb' => $request->input('tmdbid') ?? '0', + ]; + + // Process season only queries or Season and Episode/Airdate queries + + $series = $request->input('season') ?? ''; + $episode = $request->input('ep') ?? ''; + + if (preg_match('#^(19|20)\d{2}$#', $series, $year) && strpos($episode, '/') !== false) { + $airdate = str_replace('/', '-', $year[0].'-'.$episode); + } + + $relData = $releases->tvSearch( + $siteIdArr, + $series, + $episode, + $airdate ?? '', + $api->offset(), + $api->limit(), + $request->input('id') ?? '', + $api->categoryID(), + $maxAge, + $minSize + ); + + $relData = fractal($relData, new ApiTransformer($user)); + + return response()->json($relData); + } + + /** + * @param \Illuminate\Http\Request $request + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + */ + public function getNzb(Request $request) + { + $user = Auth::user(); + UserRequest::addApiRequest($user->id, $request->getRequestUri()); + $relData = Release::checkGuidForApi($request->input('id')); + if ($relData !== false) { + return redirect('/getnzb?i='.$user->id.'&r='.$user->api_token.'&id='.$request->input('id').(($request->has('del') && $request->input('del') === '1') ? '&del=1' : '')); + } + + Utility::showApiError(300, 'No such item (the guid you provided has no release in our database)'); + } + + /** + * @param \Illuminate\Http\Request $request + * + * @return \Illuminate\Http\JsonResponse + */ + public function details(Request $request): \Illuminate\Http\JsonResponse + { + $user = Auth::user(); + if (! $request->has('id')) { + Utility::showApiError(200, 'Missing parameter (guid is required for single release details)'); + } + + UserRequest::addApiRequest($user->id, $request->getRequestUri()); + $relData = Release::getByGuid($request->input('id')); + + $relData = fractal($relData, new DetailsTransformer($user)); return response()->json($relData); } diff --git a/app/Models/Category.php b/app/Models/Category.php index 3b83c53f1..7c0aba374 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -129,6 +129,34 @@ class Category extends Model self::OTHER_MISC, ]; + public const MOVIES_GROUP = + [ + self::MOVIE_FOREIGN, + self::MOVIE_ROOT, + self::MOVIE_OTHER, + self::MOVIE_SD, + self::MOVIE_HD, + self::MOVIE_UHD, + self::MOVIE_3D, + self::MOVIE_BLURAY, + self::MOVIE_DVD, + self::MOVIE_WEBDL, + ]; + + public const TV_GROUP = + [ + self::TV_FOREIGN, + self::TV_ROOT, + self::TV_OTHER, + self::TV_SD, + self::TV_HD, + self::TV_UHD, + self::TV_ANIME, + self::TV_DOCU, + self::TV_SPORT, + self::TV_WEBDL, + ]; + /** * Temporary category while we sort through the name. * @var int diff --git a/app/Transformers/ApiTransformer.php b/app/Transformers/ApiTransformer.php new file mode 100644 index 000000000..44d0725d3 --- /dev/null +++ b/app/Transformers/ApiTransformer.php @@ -0,0 +1,89 @@ +user = $user; + } + + /** + * @param \stdClass $releases + * + * @return array + */ + public function transform(\stdClass $releases): array + { + if (\in_array($releases->categories_id, Category::MOVIES_GROUP, false)) { + return [ + 'title' => $releases->searchname, + 'details' => url('/').'/details/'.$releases->guid, + 'link' => url('/').'/getnzb?id='.$releases->guid.'.nzb'.'&i='.$this->user->id.'&r='.$this->user->api_token, + 'category' => $releases->categories_id, + 'category name' => $releases->category_name, + 'size' => $releases->size, + 'files' => $releases->totalpart, + 'poster' => $releases->fromname, + 'imdbid' => $releases->imdbid, + 'grabs' => $releases->grabs, + 'comments' => $releases->comments, + 'password' => $releases->passwordstatus, + 'usenetdate' => Carbon::parse($releases->postdate)->format('D, d M Y H:i:s O'), + 'group' => $releases->group_name, + ]; + } + + if (\in_array($releases->categories_id, Category::TV_GROUP, false)) { + return [ + 'title' => $releases->searchname, + 'details' => url('/').'/details/'.$releases->guid, + 'link' => url('/').'/getnzb?id='.$releases->guid.'.nzb'.'&i='.$this->user->id.'&r='.$this->user->api_token, + 'category' => $releases->categories_id, + 'category name' => $releases->category_name, + 'size' => $releases->size, + 'files' => $releases->totalpart, + 'poster' => $releases->fromname, + 'tvairdate' => $releases->firstaired, + 'tvdbid' => $releases->tvdb, + 'traktid' => $releases->trakt, + 'tvrageid' => $releases->tvrage, + 'tvmazeid' => $releases->tvmaze, + 'imdbid' => $releases->imdb, + 'tmdbid' => $releases->tmdb, + 'grabs' => $releases->grabs, + 'comments' => $releases->comments, + 'password' => $releases->passwordstatus, + 'usenetdate' => Carbon::parse($releases->postdate)->format('D, d M Y H:i:s O'), + 'group' => $releases->group_name, + ]; + } + + return [ + 'title' => $releases->searchname, + 'details' => url('/').'/details/'.$releases->guid, + 'link' => url('/').'/getnzb?id='.$releases->guid.'.nzb'.'&i='.$this->user->id.'&r='.$this->user->api_token, + 'category' => $releases->categories_id, + 'category name' => $releases->category_name, + 'size' => $releases->size, + 'files' => $releases->totalpart, + 'poster' => $releases->fromname, + 'grabs' => $releases->grabs, + 'comments' => $releases->comments, + 'password' => $releases->passwordstatus, + 'usenetdate' => Carbon::parse($releases->postdate)->format('D, d M Y H:i:s O'), + 'group' => $releases->group_name, + ]; + } +} diff --git a/app/Transformers/DetailsTransformer.php b/app/Transformers/DetailsTransformer.php new file mode 100644 index 000000000..dcf9d8dd6 --- /dev/null +++ b/app/Transformers/DetailsTransformer.php @@ -0,0 +1,92 @@ +user = $user; + } + + /** + * A Fractal transformer. + * + * @param \App\Models\Release $releases + * + * @return array + */ + public function transform(Release $releases): array + { + if (\in_array($releases->categories_id, Category::MOVIES_GROUP, false)) { + return [ + 'title' => $releases->searchname, + 'details' => url('/').'/details/'.$releases->guid, + 'link' => url('/').'/getnzb?id='.$releases->guid.'.nzb'.'&i='.$this->user->id.'&r='.$this->user->api_token, + 'category' => $releases->categories_id, + 'category name' => $releases->category_name, + 'size' => $releases->size, + 'files' => $releases->totalpart, + 'poster' => $releases->fromname, + 'imdbid' => $releases->imdbid, + 'grabs' => $releases->grabs, + 'comments' => $releases->comments, + 'password' => $releases->passwordstatus, + 'usenetdate' => Carbon::parse($releases->postdate)->format('D, d M Y H:i:s O'), + 'group' => $releases->group_name, + ]; + } + + if (\in_array($releases->categories_id, Category::TV_GROUP, false)) { + return [ + 'title' => $releases->searchname, + 'details' => url('/').'/details/'.$releases->guid, + 'link' => url('/').'/getnzb?id='.$releases->guid.'.nzb'.'&i='.$this->user->id.'&r='.$this->user->api_token, + 'category' => $releases->categories_id, + 'category name' => $releases->category_name, + 'size' => $releases->size, + 'files' => $releases->totalpart, + 'poster' => $releases->fromname, + 'tvairdate' => $releases->firstaired, + 'tvdbid' => $releases->tvdb, + 'traktid' => $releases->trakt, + 'tvrageid' => $releases->tvrage, + 'tvmazeid' => $releases->tvmaze, + 'imdbid' => $releases->imdb, + 'tmdbid' => $releases->tmdb, + 'grabs' => $releases->grabs, + 'comments' => $releases->comments, + 'password' => $releases->passwordstatus, + 'usenetdate' => Carbon::parse($releases->postdate)->format('D, d M Y H:i:s O'), + 'group' => $releases->group_name, + ]; + } + + return [ + 'title' => $releases->searchname, + 'details' => url('/').'/details/'.$releases->guid, + 'link' => url('/').'/getnzb?id='.$releases->guid.'.nzb'.'&i='.$this->user->id.'&r='.$this->user->api_token, + 'category' => $releases->categories_id, + 'category name' => $releases->category_name, + 'size' => $releases->size, + 'files' => $releases->totalpart, + 'poster' => $releases->fromname, + 'grabs' => $releases->grabs, + 'comments' => $releases->comments, + 'password' => $releases->passwordstatus, + 'usenetdate' => Carbon::parse($releases->postdate)->format('D, d M Y H:i:s O'), + 'group' => $releases->group_name, + ]; + } +} diff --git a/app/Transformers/MoviesTransformer.php b/app/Transformers/MoviesTransformer.php deleted file mode 100644 index a8305fd9a..000000000 --- a/app/Transformers/MoviesTransformer.php +++ /dev/null @@ -1,34 +0,0 @@ - $releases->searchname, - 'details' => url('/').'/details/'.$releases->guid, - 'link' => url('/').'/getnzb?id='.$releases->guid.'.nzb', - 'category' => $releases->categories_id, - 'category name' => $releases->category_name, - 'size' => $releases->size, - 'files' => $releases->totalpart, - 'poster' => $releases->fromname, - 'imdbid' => $releases->imdbid, - 'grabs' => $releases->grabs, - 'comments' => $releases->comments, - 'password' => $releases->passwordstatus, - 'usenetdate' => Carbon::parse($releases->postdate)->format('D, d M Y H:i:s O'), - 'group' => $releases->group_name, - ]; - } -} diff --git a/routes/api.php b/routes/api.php index 6bc51fac3..a5c6a6f55 100644 --- a/routes/api.php +++ b/routes/api.php @@ -19,11 +19,24 @@ Route::prefix('v1')->group(function () { }); }); -Route::prefix('v2')->middleware('auth:api')->group(function () { +Route::prefix('v2')->group(function () { Route::namespace('Api')->group(function () { Route::get('capabilities', 'ApiV2Controller@capabilities'); Route::post('capabilities', 'ApiV2Controller@capabilities'); - Route::get('movies', 'ApiV2Controller@movie'); - Route::post('movies', 'ApiV2Controller@movie'); + }); +}); + +Route::prefix('v2')->middleware('auth:api')->group(function () { + Route::namespace('Api')->group(function () { + Route::get('movies', 'ApiV2Controller@movie'); + Route::post('movies', 'ApiV2Controller@movie'); + Route::get('search', 'ApiV2Controller@search'); + Route::post('search', 'ApiV2Controller@search'); + Route::get('tv', 'ApiV2Controller@tv'); + Route::post('tv', 'ApiV2Controller@tv'); + Route::get('getnzb', 'ApiV2Controller@getNzb'); + Route::post('getnzb', 'ApiV2Controller@getNzb'); + Route::get('details', 'ApiV2Controller@details'); + Route::post('details', 'ApiV2Controller@details'); }); });