mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-09-01 18:58:56 +00:00
Update API spec and adjust the code accordingly
This commit is contained in:
@@ -7,6 +7,7 @@ namespace App\Http\Controllers\Api;
|
||||
use App\Events\UserAccessedApi;
|
||||
use App\Http\Controllers\BasePageController;
|
||||
use App\Models\Category;
|
||||
use App\Models\Genre;
|
||||
use App\Models\Release;
|
||||
use App\Models\ReleaseNfo;
|
||||
use App\Models\Settings;
|
||||
@@ -27,6 +28,7 @@ use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
@@ -181,6 +183,13 @@ class ApiController extends BasePageController
|
||||
case 's':
|
||||
$this->verifyEmptyParameter($request, 'q');
|
||||
$maxAge = $this->maxAge($request);
|
||||
if (! is_int($maxAge)) {
|
||||
return $maxAge;
|
||||
}
|
||||
$sort = $this->sort($request);
|
||||
if (! is_string($sort)) {
|
||||
return $sort;
|
||||
}
|
||||
$groupName = $this->group($request);
|
||||
UserRequest::addApiRequest($uid, $request->getRequestUri());
|
||||
$categoryID = $this->categoryID($request);
|
||||
@@ -195,7 +204,8 @@ class ApiController extends BasePageController
|
||||
$maxAge,
|
||||
$catExclusions,
|
||||
$categoryID,
|
||||
$minSize
|
||||
$minSize,
|
||||
$sort
|
||||
);
|
||||
} else {
|
||||
$relData = $this->releaseBrowseService->getBrowseRangeForApi(
|
||||
@@ -203,7 +213,7 @@ class ApiController extends BasePageController
|
||||
$categoryID,
|
||||
$offset,
|
||||
$limit,
|
||||
'',
|
||||
$sort,
|
||||
$maxAge,
|
||||
$catExclusions,
|
||||
$groupName,
|
||||
@@ -225,6 +235,13 @@ class ApiController extends BasePageController
|
||||
$this->verifyEmptyParameter($request, 'season');
|
||||
$this->verifyEmptyParameter($request, 'ep');
|
||||
$maxAge = $this->maxAge($request);
|
||||
if (! is_int($maxAge)) {
|
||||
return $maxAge;
|
||||
}
|
||||
$sort = $this->sort($request);
|
||||
if (! is_string($sort)) {
|
||||
return $sort;
|
||||
}
|
||||
UserRequest::addApiRequest($uid, $request->getRequestUri());
|
||||
|
||||
$siteIdArr = [
|
||||
@@ -258,7 +275,8 @@ class ApiController extends BasePageController
|
||||
$this->categoryID($request),
|
||||
$maxAge,
|
||||
$minSize,
|
||||
$catExclusions
|
||||
$catExclusions,
|
||||
$sort
|
||||
);
|
||||
|
||||
$this->output($relData, $params, $outputXML, $offset, 'api');
|
||||
@@ -269,6 +287,13 @@ class ApiController extends BasePageController
|
||||
$this->verifyEmptyParameter($request, 'q');
|
||||
$this->verifyEmptyParameter($request, 'imdbid');
|
||||
$maxAge = $this->maxAge($request);
|
||||
if (! is_int($maxAge)) {
|
||||
return $maxAge;
|
||||
}
|
||||
$sort = $this->sort($request);
|
||||
if (! is_string($sort)) {
|
||||
return $sort;
|
||||
}
|
||||
UserRequest::addApiRequest($uid, $request->getRequestUri());
|
||||
|
||||
$imdbId = $request->has('imdbid') && $request->filled('imdbid')
|
||||
@@ -287,7 +312,8 @@ class ApiController extends BasePageController
|
||||
$this->categoryID($request),
|
||||
$maxAge,
|
||||
$minSize,
|
||||
$catExclusions
|
||||
$catExclusions,
|
||||
$sort
|
||||
);
|
||||
|
||||
$this->addCoverURL(
|
||||
@@ -308,6 +334,10 @@ class ApiController extends BasePageController
|
||||
if (! is_int($maxAge)) {
|
||||
return $maxAge;
|
||||
}
|
||||
$sort = $this->sort($request);
|
||||
if (! is_string($sort)) {
|
||||
return $sort;
|
||||
}
|
||||
$groupName = $this->group($request);
|
||||
UserRequest::addApiRequest($uid, $request->getRequestUri());
|
||||
$relData = $this->releaseSearchService->apiMusicSearch(
|
||||
@@ -318,7 +348,8 @@ class ApiController extends BasePageController
|
||||
$maxAge,
|
||||
$catExclusions,
|
||||
$this->categoryID($request),
|
||||
$minSize
|
||||
$minSize,
|
||||
$sort
|
||||
);
|
||||
$this->output($relData, $params, $outputXML, $offset, 'api');
|
||||
break;
|
||||
@@ -331,6 +362,10 @@ class ApiController extends BasePageController
|
||||
if (! is_int($maxAge)) {
|
||||
return $maxAge;
|
||||
}
|
||||
$sort = $this->sort($request);
|
||||
if (! is_string($sort)) {
|
||||
return $sort;
|
||||
}
|
||||
$groupName = $this->group($request);
|
||||
UserRequest::addApiRequest($uid, $request->getRequestUri());
|
||||
$relData = $this->releaseSearchService->apiBookSearch(
|
||||
@@ -341,7 +376,8 @@ class ApiController extends BasePageController
|
||||
$maxAge,
|
||||
$catExclusions,
|
||||
$this->categoryID($request),
|
||||
$minSize
|
||||
$minSize,
|
||||
$sort
|
||||
);
|
||||
$this->output($relData, $params, $outputXML, $offset, 'api');
|
||||
break;
|
||||
@@ -357,6 +393,10 @@ class ApiController extends BasePageController
|
||||
if (! is_int($maxAge)) {
|
||||
return $maxAge;
|
||||
}
|
||||
$sort = $this->sort($request);
|
||||
if (! is_string($sort)) {
|
||||
return $sort;
|
||||
}
|
||||
UserRequest::addApiRequest($uid, $request->getRequestUri());
|
||||
$relData = $this->releaseSearchService->animeSearch(
|
||||
$anidb,
|
||||
@@ -366,7 +406,8 @@ class ApiController extends BasePageController
|
||||
$this->categoryID($request),
|
||||
$maxAge,
|
||||
$catExclusions,
|
||||
$anilist
|
||||
$anilist,
|
||||
$sort
|
||||
);
|
||||
$this->output($relData, $params, $outputXML, $offset, 'api');
|
||||
break;
|
||||
@@ -426,18 +467,18 @@ class ApiController extends BasePageController
|
||||
//
|
||||
case 'nzbAdd':
|
||||
if (! User::canPost($uid)) {
|
||||
return response('User does not have permission to post', 403);
|
||||
return showApiError(102, 'Insufficient privileges/not authorized');
|
||||
}
|
||||
|
||||
if ($request->missing('file')) {
|
||||
return response('Missing parameter (file is required for adding an NZB)', 400);
|
||||
return showApiError(200, 'Missing parameter (file is required for adding an NZB)');
|
||||
}
|
||||
if ($request->missing('apikey')) {
|
||||
return response('Missing parameter (apikey is required for adding an NZB)', 400);
|
||||
return showApiError(200, 'Missing parameter (apikey is required for adding an NZB)');
|
||||
}
|
||||
|
||||
if (! $request->hasFile('file')) {
|
||||
return response('Missing parameter (file is required for adding an NZB)', 400);
|
||||
return showApiError(600, 'Failed to load NZB');
|
||||
}
|
||||
|
||||
UserRequest::addApiRequest($uid, $request->getRequestUri());
|
||||
@@ -448,11 +489,11 @@ class ApiController extends BasePageController
|
||||
if ($nzbFile !== null) {
|
||||
// We need to check if file is an actual nzb file.
|
||||
if ($nzbFile->getClientOriginalExtension() !== 'nzb') {
|
||||
return response('File is not an NZB file', 400);
|
||||
return showApiError(600, 'Failed to load NZB (file is not an NZB file)');
|
||||
}
|
||||
// Check if the file is proper xml nzb file.
|
||||
if (! isValidNewznabNzb($nzbFile->getContent())) {
|
||||
return response('File is not a valid Newznab NZB file', 400);
|
||||
return showApiError(600, 'Failed to load NZB (invalid NZB payload)');
|
||||
}
|
||||
if (! File::isDirectory(config('nntmux.nzb_upload_folder'))) {
|
||||
@File::makeDirectory(config('nntmux.nzb_upload_folder'), 0775, true);
|
||||
@@ -461,16 +502,24 @@ class ApiController extends BasePageController
|
||||
if (File::put(config('nntmux.nzb_upload_folder').$nzbFile->getClientOriginalName(), $nzbFile->getContent())) {
|
||||
Log::channel('nzb_upload')->info('NZB file uploaded by API: '.$nzbFile->getClientOriginalName());
|
||||
|
||||
return response('NZB file uploaded successfully', 200);
|
||||
$successXml = sprintf(
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<success id=\"0\" guid=\"\" categoryid=\"%s\" name=\"%s\" />\n",
|
||||
(string) $request->input('cat', ''),
|
||||
htmlspecialchars(pathinfo($nzbFile->getClientOriginalName(), PATHINFO_FILENAME), ENT_QUOTES, 'UTF-8')
|
||||
);
|
||||
|
||||
return response($successXml, 200)->header('Content-type', 'text/xml');
|
||||
}
|
||||
|
||||
Log::channel('nzb_upload')->warning('NZB file uploaded by API failed: '.$nzbFile->getClientOriginalName());
|
||||
} else {
|
||||
Log::channel('nzb_upload')->warning('NZB file uploaded by API failed: no file provided');
|
||||
|
||||
return response('NZB file upload failed', 500);
|
||||
return showApiError(603, 'NZB failed to write to disk');
|
||||
}
|
||||
|
||||
return showApiError(603, 'NZB failed to write to disk');
|
||||
|
||||
break;
|
||||
|
||||
// Capabilities request.
|
||||
@@ -551,12 +600,12 @@ class ApiController extends BasePageController
|
||||
'default' => 100,
|
||||
],
|
||||
'searching' => [
|
||||
'search' => ['available' => 'yes', 'supportedParams' => 'q'],
|
||||
'tv-search' => ['available' => 'yes', 'supportedParams' => 'q,vid,tvdbid,traktid,rid,tvmazeid,imdbid,tmdbid,season,ep'],
|
||||
'movie-search' => ['available' => 'yes', 'supportedParams' => 'q,imdbid, tmdbid, traktid'],
|
||||
'audio-search' => ['available' => 'yes', 'supportedParams' => 'q,cat,minsize,maxage,group'],
|
||||
'book-search' => ['available' => 'yes', 'supportedParams' => 'q,cat,minsize,maxage,group'],
|
||||
'anime-search' => ['available' => 'yes', 'supportedParams' => 'q,anidbid,anilistid,cat,maxage'],
|
||||
'search' => ['available' => 'yes', 'supportedParams' => 'q,group,minsize,maxsize,maxage,cat,limit,offset,attrs,extended,del,sort'],
|
||||
'tv-search' => ['available' => 'yes', 'supportedParams' => 'q,vid,tvdbid,traktid,rid,tvmazeid,imdbid,tmdbid,season,ep,cat,minsize,maxsize,maxage,limit,offset,attrs,extended,del,sort'],
|
||||
'movie-search' => ['available' => 'yes', 'supportedParams' => 'q,imdbid,tmdbid,traktid,genre,cat,minsize,maxsize,maxage,limit,offset,attrs,extended,del,sort'],
|
||||
'audio-search' => ['available' => 'yes', 'supportedParams' => 'q,cat,minsize,maxsize,maxage,group,limit,offset,attrs,extended,del,sort'],
|
||||
'book-search' => ['available' => 'yes', 'supportedParams' => 'q,title,author,cat,minsize,maxsize,maxage,group,limit,offset,attrs,extended,del,sort'],
|
||||
'anime-search' => ['available' => 'yes', 'supportedParams' => 'q,anidbid,anilistid,cat,minsize,maxsize,maxage,limit,offset,attrs,extended,del,sort'],
|
||||
],
|
||||
];
|
||||
});
|
||||
@@ -569,6 +618,34 @@ class ApiController extends BasePageController
|
||||
|
||||
// Only load categories for caps requests (also cached via Category::getForMenu)
|
||||
$serverInfo['categories'] = $includeCats ? Category::getForMenu() : null;
|
||||
$serverInfo['groups'] = $includeCats
|
||||
? (Schema::hasTable('usenet_groups')
|
||||
? UsenetGroup::query()
|
||||
->where('active', 1)
|
||||
->orderBy('name')
|
||||
->get(['name', 'description', 'last_updated'])
|
||||
->map(static fn (UsenetGroup $group): array => [
|
||||
'name' => $group->name,
|
||||
'description' => (string) ($group->description ?? ''),
|
||||
'lastupdate' => $group->last_updated ? Carbon::parse($group->last_updated)->toRfc2822String() : '',
|
||||
])
|
||||
->all()
|
||||
: [])
|
||||
: null;
|
||||
$serverInfo['genres'] = $includeCats
|
||||
? (Schema::hasTable('genres')
|
||||
? Genre::query()
|
||||
->enabled()
|
||||
->orderBy('title')
|
||||
->get(['id', 'title', 'type'])
|
||||
->map(static fn (Genre $genre): array => [
|
||||
'id' => $genre->id,
|
||||
'name' => $genre->title,
|
||||
'categoryid' => (int) ($genre->type ?? 0),
|
||||
])
|
||||
->all()
|
||||
: [])
|
||||
: null;
|
||||
|
||||
return $serverInfo;
|
||||
}
|
||||
@@ -674,6 +751,30 @@ class ApiController extends BasePageController
|
||||
return $offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and normalize the API sort parameter.
|
||||
*
|
||||
* @return Application|ResponseFactory|\Illuminate\Foundation\Application|Response|string
|
||||
*/
|
||||
public function sort(Request $request)
|
||||
{
|
||||
$defaultSort = 'posted_desc';
|
||||
if (! $request->has('sort')) {
|
||||
return $defaultSort;
|
||||
}
|
||||
|
||||
$sort = strtolower(trim((string) $request->input('sort')));
|
||||
if ($sort === '') {
|
||||
return showApiError(201, 'Incorrect parameter (sort must not be empty)');
|
||||
}
|
||||
|
||||
if (! preg_match('/^(cat|name|size|files|stats|posted)_(asc|desc)$/', $sort)) {
|
||||
return showApiError(201, 'Incorrect parameter (sort must be one of: cat_asc/desc, name_asc/desc, size_asc/desc, files_asc/desc, stats_asc/desc, posted_asc/desc)');
|
||||
}
|
||||
|
||||
return $sort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a parameter is empty.
|
||||
*
|
||||
|
||||
@@ -7,8 +7,10 @@ namespace App\Http\Controllers\Api;
|
||||
use App\Events\UserAccessedApi;
|
||||
use App\Http\Controllers\BasePageController;
|
||||
use App\Models\Category;
|
||||
use App\Models\Genre;
|
||||
use App\Models\Release;
|
||||
use App\Models\Settings;
|
||||
use App\Models\UsenetGroup;
|
||||
use App\Models\User;
|
||||
use App\Models\UserRequest;
|
||||
use App\Services\RegistrationStatusService;
|
||||
@@ -17,11 +19,16 @@ use App\Services\Releases\ReleaseSearchService;
|
||||
use App\Transformers\ApiTransformer;
|
||||
use App\Transformers\CategoryTransformer;
|
||||
use App\Transformers\DetailsTransformer;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ApiV2Controller extends BasePageController
|
||||
@@ -82,6 +89,38 @@ class ApiV2Controller extends BasePageController
|
||||
];
|
||||
}
|
||||
|
||||
private function parseMaxAge(Request $request): int|JsonResponse
|
||||
{
|
||||
if (! $request->has('maxage')) {
|
||||
return -1;
|
||||
}
|
||||
if ($request->isNotFilled('maxage')) {
|
||||
return response()->json(['error' => 'Incorrect parameter (maxage must not be empty)'], 400);
|
||||
}
|
||||
if (! is_numeric($request->input('maxage'))) {
|
||||
return response()->json(['error' => 'Incorrect parameter (maxage must be numeric)'], 400);
|
||||
}
|
||||
|
||||
return (int) $request->input('maxage');
|
||||
}
|
||||
|
||||
private function parseSort(Request $request): string|JsonResponse
|
||||
{
|
||||
if (! $request->has('sort')) {
|
||||
return 'posted_desc';
|
||||
}
|
||||
|
||||
$sort = strtolower(trim((string) $request->input('sort')));
|
||||
if ($sort === '') {
|
||||
return response()->json(['error' => 'Incorrect parameter (sort must not be empty)'], 400);
|
||||
}
|
||||
if (! preg_match('/^(cat|name|size|files|stats|posted)_(asc|desc)$/', $sort)) {
|
||||
return response()->json(['error' => 'Incorrect parameter (sort must be one of: cat_asc/desc, name_asc/desc, size_asc/desc, files_asc/desc, stats_asc/desc, posted_asc/desc)'], 400);
|
||||
}
|
||||
|
||||
return $sort;
|
||||
}
|
||||
|
||||
public function capabilities(): JsonResponse
|
||||
{
|
||||
// Cache the full capabilities response for 10 minutes
|
||||
@@ -100,14 +139,38 @@ class ApiV2Controller extends BasePageController
|
||||
'default' => 100,
|
||||
],
|
||||
'searching' => [
|
||||
'search' => ['available' => 'yes', 'supportedParams' => 'id'],
|
||||
'tv-search' => ['available' => 'yes', 'supportedParams' => 'id,vid,tvdbid,traktid,rid,tvmazeid,imdbid,tmdbid,season,ep'],
|
||||
'movie-search' => ['available' => 'yes', 'supportedParams' => 'id, imdbid, tmdbid, traktid'],
|
||||
'audio-search' => ['available' => 'yes', 'supportedParams' => 'id,cat,minsize,maxage,group'],
|
||||
'book-search' => ['available' => 'yes', 'supportedParams' => 'id,cat,minsize,maxage,group'],
|
||||
'anime-search' => ['available' => 'yes', 'supportedParams' => 'id,anidbid,anilistid,cat,maxage'],
|
||||
'search' => ['available' => 'yes', 'supportedParams' => 'id,group,minsize,maxsize,maxage,cat,limit,offset,sort'],
|
||||
'tv-search' => ['available' => 'yes', 'supportedParams' => 'id,vid,tvdbid,traktid,rid,tvmazeid,imdbid,tmdbid,season,ep,cat,minsize,maxsize,maxage,limit,offset,sort'],
|
||||
'movie-search' => ['available' => 'yes', 'supportedParams' => 'id,imdbid,tmdbid,traktid,genre,cat,minsize,maxsize,maxage,limit,offset,sort'],
|
||||
'audio-search' => ['available' => 'yes', 'supportedParams' => 'id,cat,minsize,maxsize,maxage,group,limit,offset,sort'],
|
||||
'book-search' => ['available' => 'yes', 'supportedParams' => 'id,cat,minsize,maxsize,maxage,group,limit,offset,sort'],
|
||||
'anime-search' => ['available' => 'yes', 'supportedParams' => 'id,anidbid,anilistid,cat,minsize,maxsize,maxage,limit,offset,sort'],
|
||||
],
|
||||
'categories' => fractal($category, new CategoryTransformer),
|
||||
'groups' => Schema::hasTable('usenet_groups')
|
||||
? UsenetGroup::query()
|
||||
->where('active', 1)
|
||||
->orderBy('name')
|
||||
->get(['name', 'description', 'last_updated'])
|
||||
->map(static fn (UsenetGroup $group): array => [
|
||||
'name' => $group->name,
|
||||
'description' => (string) ($group->description ?? ''),
|
||||
'lastupdate' => $group->last_updated ? Carbon::parse($group->last_updated)->toRfc2822String() : '',
|
||||
])
|
||||
->values()
|
||||
: collect(),
|
||||
'genres' => Schema::hasTable('genres')
|
||||
? Genre::query()
|
||||
->enabled()
|
||||
->orderBy('title')
|
||||
->get(['id', 'title', 'type'])
|
||||
->map(static fn (Genre $genre): array => [
|
||||
'id' => $genre->id,
|
||||
'name' => $genre->title,
|
||||
'categoryid' => (int) ($genre->type ?? 0),
|
||||
])
|
||||
->values()
|
||||
: collect(),
|
||||
];
|
||||
});
|
||||
|
||||
@@ -142,18 +205,25 @@ class ApiV2Controller extends BasePageController
|
||||
$offset = $this->api->offset($request);
|
||||
$limit = $this->api->limit($request);
|
||||
$categoryID = $this->api->categoryID($request);
|
||||
$maxAge = $this->api->maxAge($request);
|
||||
$maxAge = $this->parseMaxAge($request);
|
||||
if (! is_int($maxAge)) {
|
||||
return $maxAge;
|
||||
}
|
||||
$sort = $this->parseSort($request);
|
||||
if (! is_string($sort)) {
|
||||
return $sort;
|
||||
}
|
||||
$catExclusions = User::getCategoryExclusionById($user->id);
|
||||
|
||||
// Create cache key for movie search results
|
||||
$searchCacheKey = 'api_movie_search:'.md5(serialize([
|
||||
$imdbId, $tmdbId, $traktId, $offset, $limit, $searchName,
|
||||
$imdbId, $tmdbId, $traktId, $offset, $limit, $searchName, $sort,
|
||||
$categoryID, $maxAge, $minSize, $catExclusions,
|
||||
]));
|
||||
|
||||
// Cache search results for 10 minutes
|
||||
$relData = Cache::remember($searchCacheKey, 600, function () use (
|
||||
$imdbId, $tmdbId, $traktId, $offset, $limit, $searchName,
|
||||
$imdbId, $tmdbId, $traktId, $offset, $limit, $searchName, $sort,
|
||||
$categoryID, $maxAge, $minSize, $catExclusions
|
||||
) {
|
||||
return $this->releaseSearchService->moviesSearch(
|
||||
@@ -166,7 +236,8 @@ class ApiV2Controller extends BasePageController
|
||||
$categoryID,
|
||||
$maxAge,
|
||||
$minSize,
|
||||
$catExclusions
|
||||
$catExclusions,
|
||||
$sort
|
||||
);
|
||||
});
|
||||
|
||||
@@ -197,10 +268,14 @@ class ApiV2Controller extends BasePageController
|
||||
$offset = $this->api->offset($request);
|
||||
$limit = $this->api->limit($request);
|
||||
$categoryID = $this->api->categoryID($request);
|
||||
$maxAge = $this->api->maxAge($request);
|
||||
$maxAge = $this->parseMaxAge($request);
|
||||
if (! is_int($maxAge)) {
|
||||
return $maxAge;
|
||||
}
|
||||
$sort = $this->parseSort($request);
|
||||
if (! is_string($sort)) {
|
||||
return $sort;
|
||||
}
|
||||
|
||||
$minSize = max(0, (int) $request->input('minsize', 0));
|
||||
$catExclusions = User::getCategoryExclusionById($user->id);
|
||||
@@ -214,7 +289,8 @@ class ApiV2Controller extends BasePageController
|
||||
$maxAge,
|
||||
$catExclusions,
|
||||
$categoryID,
|
||||
$minSize
|
||||
$minSize,
|
||||
$sort
|
||||
);
|
||||
|
||||
$response = array_merge(
|
||||
@@ -244,10 +320,14 @@ class ApiV2Controller extends BasePageController
|
||||
$offset = $this->api->offset($request);
|
||||
$limit = $this->api->limit($request);
|
||||
$categoryID = $this->api->categoryID($request);
|
||||
$maxAge = $this->api->maxAge($request);
|
||||
$maxAge = $this->parseMaxAge($request);
|
||||
if (! is_int($maxAge)) {
|
||||
return $maxAge;
|
||||
}
|
||||
$sort = $this->parseSort($request);
|
||||
if (! is_string($sort)) {
|
||||
return $sort;
|
||||
}
|
||||
|
||||
$minSize = max(0, (int) $request->input('minsize', 0));
|
||||
$catExclusions = User::getCategoryExclusionById($user->id);
|
||||
@@ -261,7 +341,8 @@ class ApiV2Controller extends BasePageController
|
||||
$maxAge,
|
||||
$catExclusions,
|
||||
$categoryID,
|
||||
$minSize
|
||||
$minSize,
|
||||
$sort
|
||||
);
|
||||
|
||||
$response = array_merge(
|
||||
@@ -293,10 +374,14 @@ class ApiV2Controller extends BasePageController
|
||||
$offset = $this->api->offset($request);
|
||||
$limit = $this->api->limit($request);
|
||||
$categoryID = $this->api->categoryID($request);
|
||||
$maxAge = $this->api->maxAge($request);
|
||||
$maxAge = $this->parseMaxAge($request);
|
||||
if (! is_int($maxAge)) {
|
||||
return $maxAge;
|
||||
}
|
||||
$sort = $this->parseSort($request);
|
||||
if (! is_string($sort)) {
|
||||
return $sort;
|
||||
}
|
||||
|
||||
$catExclusions = User::getCategoryExclusionById($user->id);
|
||||
|
||||
@@ -308,7 +393,8 @@ class ApiV2Controller extends BasePageController
|
||||
$categoryID,
|
||||
$maxAge,
|
||||
$catExclusions,
|
||||
$anilist
|
||||
$anilist,
|
||||
$sort
|
||||
);
|
||||
|
||||
$response = array_merge(
|
||||
@@ -337,7 +423,14 @@ class ApiV2Controller extends BasePageController
|
||||
$offset = $this->api->offset($request);
|
||||
$catExclusions = User::getCategoryExclusionById($user->id);
|
||||
$minSize = $request->has('minsize') && $request->input('minsize') > 0 ? $request->input('minsize') : 0;
|
||||
$maxAge = $this->api->maxAge($request);
|
||||
$maxAge = $this->parseMaxAge($request);
|
||||
if (! is_int($maxAge)) {
|
||||
return $maxAge;
|
||||
}
|
||||
$sort = $this->parseSort($request);
|
||||
if (! is_string($sort)) {
|
||||
return $sort;
|
||||
}
|
||||
$groupName = $this->api->group($request);
|
||||
if (is_array($groupName)) {
|
||||
$groupName = $groupName[0] ?? -1;
|
||||
@@ -354,7 +447,8 @@ class ApiV2Controller extends BasePageController
|
||||
$maxAge,
|
||||
$catExclusions,
|
||||
$categoryID,
|
||||
$minSize
|
||||
$minSize,
|
||||
$sort
|
||||
);
|
||||
} else {
|
||||
$relData = $this->releaseBrowseService->getBrowseRangeForApi(
|
||||
@@ -362,7 +456,7 @@ class ApiV2Controller extends BasePageController
|
||||
$categoryID,
|
||||
$offset,
|
||||
$limit,
|
||||
'',
|
||||
$sort,
|
||||
$maxAge,
|
||||
$catExclusions,
|
||||
$groupName,
|
||||
@@ -402,7 +496,14 @@ class ApiV2Controller extends BasePageController
|
||||
$this->api->verifyEmptyParameter($request, 'tmdbid');
|
||||
$this->api->verifyEmptyParameter($request, 'season');
|
||||
$this->api->verifyEmptyParameter($request, 'ep');
|
||||
$maxAge = $this->api->maxAge($request);
|
||||
$maxAge = $this->parseMaxAge($request);
|
||||
if (! is_int($maxAge)) {
|
||||
return $maxAge;
|
||||
}
|
||||
$sort = $this->parseSort($request);
|
||||
if (! is_string($sort)) {
|
||||
return $sort;
|
||||
}
|
||||
UserRequest::addApiRequest($user->id, $request->getRequestUri());
|
||||
event(new UserAccessedApi($user, $request->ip()));
|
||||
|
||||
@@ -436,7 +537,8 @@ class ApiV2Controller extends BasePageController
|
||||
$this->api->categoryID($request),
|
||||
$maxAge,
|
||||
$minSize,
|
||||
$catExclusions
|
||||
$catExclusions,
|
||||
$sort
|
||||
);
|
||||
|
||||
$response = array_merge(
|
||||
@@ -448,7 +550,7 @@ class ApiV2Controller extends BasePageController
|
||||
return response()->json($response);
|
||||
}
|
||||
|
||||
public function getNzb(Request $request): Application|JsonResponse|Redirector|RedirectResponse|\Illuminate\Contracts\Foundation\Application
|
||||
public function getNzb(Request $request): Application|ResponseFactory|JsonResponse|Redirector|RedirectResponse
|
||||
{
|
||||
$user = $this->resolveUser($request);
|
||||
if (! $user) {
|
||||
|
||||
@@ -154,6 +154,8 @@ class XML_Response
|
||||
'registration' => $this->server['registration'],
|
||||
'searching' => $this->server['searching'],
|
||||
'categories' => $this->server['categories'] ?? [],
|
||||
'groups' => $this->server['groups'] ?? [],
|
||||
'genres' => $this->server['genres'] ?? [],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -340,6 +342,8 @@ class XML_Response
|
||||
$this->addNode(['name' => 'registration', 'data' => $this->server['registration']]);
|
||||
$this->addNodes(['name' => 'searching', 'data' => $this->server['searching']]);
|
||||
$this->writeCategoryListing();
|
||||
$this->writeGroupListing();
|
||||
$this->writeGenreListing();
|
||||
$this->xml->endElement();
|
||||
$this->xml->endDocument();
|
||||
|
||||
@@ -461,6 +465,35 @@ class XML_Response
|
||||
}
|
||||
$this->xml->endElement();
|
||||
}
|
||||
$this->xml->endElement();
|
||||
}
|
||||
|
||||
protected function writeGroupListing(): void
|
||||
{
|
||||
$this->xml->startElement('groups');
|
||||
foreach (($this->server['groups'] ?? []) as $group) {
|
||||
$this->xml->startElement('group');
|
||||
$this->xml->writeAttribute('name', (string) ($group['name'] ?? ''));
|
||||
$this->xml->writeAttribute('description', (string) ($group['description'] ?? ''));
|
||||
if (! empty($group['lastupdate'])) {
|
||||
$this->xml->writeAttribute('lastupdate', (string) $group['lastupdate']);
|
||||
}
|
||||
$this->xml->endElement();
|
||||
}
|
||||
$this->xml->endElement();
|
||||
}
|
||||
|
||||
protected function writeGenreListing(): void
|
||||
{
|
||||
$this->xml->startElement('genres');
|
||||
foreach (($this->server['genres'] ?? []) as $genre) {
|
||||
$this->xml->startElement('genre');
|
||||
$this->xml->writeAttribute('id', (string) ($genre['id'] ?? ''));
|
||||
$this->xml->writeAttribute('name', (string) ($genre['name'] ?? ''));
|
||||
$this->xml->writeAttribute('categoryid', (string) ($genre['categoryid'] ?? '0'));
|
||||
$this->xml->endElement();
|
||||
}
|
||||
$this->xml->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user