mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-28 17:01:16 +00:00
Update APIv2 speed
This commit is contained in:
@@ -44,14 +44,31 @@ final class DetailsData extends Data
|
|||||||
|
|
||||||
public static function fromRelease(Release|\stdClass $release, User $user): self
|
public static function fromRelease(Release|\stdClass $release, User $user): self
|
||||||
{
|
{
|
||||||
|
return new self(...self::toArrayFromRelease($release, $user));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the API array directly for hot details response paths.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public static function toArrayFromRelease(
|
||||||
|
Release|\stdClass $release,
|
||||||
|
User $user,
|
||||||
|
?string $detailsBaseUrl = null,
|
||||||
|
?string $getNzbBaseUrl = null
|
||||||
|
): array {
|
||||||
$get = static fn (string $key, mixed $default = null): mixed => $release->{$key} ?? $default;
|
$get = static fn (string $key, mixed $default = null): mixed => $release->{$key} ?? $default;
|
||||||
|
|
||||||
$categoriesId = (int) $get('categories_id', 0);
|
$categoriesId = (int) $get('categories_id', 0);
|
||||||
$guid = (string) $get('guid', '');
|
$guid = (string) $get('guid', '');
|
||||||
|
$detailsBaseUrl ??= url('/details').'/';
|
||||||
|
$getNzbBaseUrl ??= url('/getnzb');
|
||||||
|
|
||||||
$base = [
|
$base = [
|
||||||
'title' => (string) $get('searchname', ''),
|
'title' => (string) $get('searchname', ''),
|
||||||
'details' => url('/').'/details/'.$guid,
|
'details' => $detailsBaseUrl.$guid,
|
||||||
'link' => url('/').'/getnzb?id='.$guid.'.nzb&r='.$user->api_token,
|
'link' => $getNzbBaseUrl.'?id='.$guid.'.nzb&r='.$user->api_token,
|
||||||
'category' => $categoriesId,
|
'category' => $categoriesId,
|
||||||
'category_name' => $get('category_name'),
|
'category_name' => $get('category_name'),
|
||||||
'added' => Carbon::parse($get('adddate'))->toRssString(),
|
'added' => Carbon::parse($get('adddate'))->toRssString(),
|
||||||
@@ -64,25 +81,23 @@ final class DetailsData extends Data
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (in_array($categoriesId, Category::MOVIES_GROUP, true)) {
|
if (in_array($categoriesId, Category::MOVIES_GROUP, true)) {
|
||||||
return new self(
|
return $base + [
|
||||||
...$base,
|
'imdbid' => $get('imdbid'),
|
||||||
imdbid: $get('imdbid'),
|
];
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array($categoriesId, Category::TV_GROUP, true)) {
|
if (in_array($categoriesId, Category::TV_GROUP, true)) {
|
||||||
return new self(
|
return $base + [
|
||||||
...$base,
|
'imdbid' => $get('imdb'),
|
||||||
imdbid: $get('imdb'),
|
'tmdbid' => $get('tmdb'),
|
||||||
tmdbid: $get('tmdb'),
|
'traktid' => $get('trakt'),
|
||||||
traktid: $get('trakt'),
|
'tvairdate' => $get('firstaired'),
|
||||||
tvairdate: $get('firstaired'),
|
'tvdbid' => $get('tvdb'),
|
||||||
tvdbid: $get('tvdb'),
|
'tvrageid' => $get('tvrage'),
|
||||||
tvrageid: $get('tvrage'),
|
'tvmazeid' => $get('tvmaze'),
|
||||||
tvmazeid: $get('tvmaze'),
|
];
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new self(...$base);
|
return $base;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,17 +64,23 @@ final class ReleaseData extends Data
|
|||||||
*
|
*
|
||||||
* @return array<string, mixed>
|
* @return array<string, mixed>
|
||||||
*/
|
*/
|
||||||
public static function toArrayFromRelease(Release|\stdClass $release, User $user): array
|
public static function toArrayFromRelease(
|
||||||
{
|
Release|\stdClass $release,
|
||||||
|
User $user,
|
||||||
|
?string $detailsBaseUrl = null,
|
||||||
|
?string $getNzbBaseUrl = null
|
||||||
|
): array {
|
||||||
$get = static fn (string $key, mixed $default = null): mixed => $release->{$key} ?? $default;
|
$get = static fn (string $key, mixed $default = null): mixed => $release->{$key} ?? $default;
|
||||||
|
|
||||||
$categoriesId = (int) $get('categories_id', 0);
|
$categoriesId = (int) $get('categories_id', 0);
|
||||||
$guid = (string) $get('guid', '');
|
$guid = (string) $get('guid', '');
|
||||||
|
$detailsBaseUrl ??= url('/details').'/';
|
||||||
|
$getNzbBaseUrl ??= url('/getnzb');
|
||||||
|
|
||||||
$base = [
|
$base = [
|
||||||
'title' => (string) $get('searchname', ''),
|
'title' => (string) $get('searchname', ''),
|
||||||
'details' => url('/details/'.$guid),
|
'details' => $detailsBaseUrl.$guid,
|
||||||
'url' => url('/getnzb').'?id='.$guid.'.nzb&r='.$user->api_token,
|
'url' => $getNzbBaseUrl.'?id='.$guid.'.nzb&r='.$user->api_token,
|
||||||
'category' => $categoriesId,
|
'category' => $categoriesId,
|
||||||
'category_name' => $get('category_name'),
|
'category_name' => $get('category_name'),
|
||||||
'added' => Carbon::parse($get('adddate'))->toRssString(),
|
'added' => Carbon::parse($get('adddate'))->toRssString(),
|
||||||
|
|||||||
@@ -126,6 +126,12 @@ class ApiV2Controller extends BasePageController
|
|||||||
return $this->resolvedUserStats[$user->id] ??= $this->api->getCachedUserStats($user->id);
|
return $this->resolvedUserStats[$user->id] ??= $this->api->getCachedUserStats($user->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function recordApiRequest(User $user, Request $request): void
|
||||||
|
{
|
||||||
|
UserRequest::addApiRequest($user->id, $request->getRequestUri());
|
||||||
|
event(new UserAccessedApi($user, $request->ip()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the standard search-results JSON response.
|
* Build the standard search-results JSON response.
|
||||||
*
|
*
|
||||||
@@ -141,11 +147,13 @@ class ApiV2Controller extends BasePageController
|
|||||||
{
|
{
|
||||||
$rowsArray = is_array($rows) ? $rows : iterator_to_array($rows, false);
|
$rowsArray = is_array($rows) ? $rows : iterator_to_array($rows, false);
|
||||||
$total = (int) ($rowsArray[0]->_totalrows ?? 0);
|
$total = (int) ($rowsArray[0]->_totalrows ?? 0);
|
||||||
|
$detailsBaseUrl = url('/details').'/';
|
||||||
|
$getNzbBaseUrl = url('/getnzb');
|
||||||
|
|
||||||
$results = array_map(
|
$results = [];
|
||||||
static fn ($row): array => ReleaseData::toArrayFromRelease($row, $user),
|
foreach ($rowsArray as $row) {
|
||||||
$rowsArray,
|
$results[] = ReleaseData::toArrayFromRelease($row, $user, $detailsBaseUrl, $getNzbBaseUrl);
|
||||||
);
|
}
|
||||||
|
|
||||||
return response()->json(array_merge(
|
return response()->json(array_merge(
|
||||||
['Total' => $total],
|
['Total' => $total],
|
||||||
@@ -211,7 +219,10 @@ class ApiV2Controller extends BasePageController
|
|||||||
'book-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'],
|
'anime-search' => ['available' => 'yes', 'supportedParams' => 'id,anidbid,anilistid,cat,minsize,maxsize,maxage,limit,offset,sort'],
|
||||||
],
|
],
|
||||||
'categories' => $category->map(static fn (RootCategory $rootCategory): CategoryData => CategoryData::fromCategory($rootCategory))->values(),
|
'categories' => $category
|
||||||
|
->map(static fn (RootCategory $rootCategory): array => CategoryData::fromCategory($rootCategory)->toArray())
|
||||||
|
->values()
|
||||||
|
->all(),
|
||||||
'groups' => Schema::hasTable('usenet_groups')
|
'groups' => Schema::hasTable('usenet_groups')
|
||||||
? UsenetGroup::query()
|
? UsenetGroup::query()
|
||||||
->where('active', 1)
|
->where('active', 1)
|
||||||
@@ -223,7 +234,8 @@ class ApiV2Controller extends BasePageController
|
|||||||
'lastupdate' => $group->last_updated ? Carbon::parse($group->last_updated)->toRfc2822String() : '',
|
'lastupdate' => $group->last_updated ? Carbon::parse($group->last_updated)->toRfc2822String() : '',
|
||||||
])
|
])
|
||||||
->values()
|
->values()
|
||||||
: collect(),
|
->all()
|
||||||
|
: [],
|
||||||
'genres' => Schema::hasTable('genres')
|
'genres' => Schema::hasTable('genres')
|
||||||
? Genre::query()
|
? Genre::query()
|
||||||
->enabled()
|
->enabled()
|
||||||
@@ -235,7 +247,8 @@ class ApiV2Controller extends BasePageController
|
|||||||
'categoryid' => (int) ($genre->type ?? 0),
|
'categoryid' => (int) ($genre->type ?? 0),
|
||||||
])
|
])
|
||||||
->values()
|
->values()
|
||||||
: collect(),
|
->all()
|
||||||
|
: [],
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -258,8 +271,7 @@ class ApiV2Controller extends BasePageController
|
|||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserRequest::addApiRequest($user->id, $request->getRequestUri());
|
$this->recordApiRequest($user, $request);
|
||||||
event(new UserAccessedApi($user, $request->ip()));
|
|
||||||
|
|
||||||
// Get request parameters efficiently
|
// Get request parameters efficiently
|
||||||
$imdbId = (string) Str::replace('tt', '', (string) $request->input('imdbid', ''));
|
$imdbId = (string) Str::replace('tt', '', (string) $request->input('imdbid', ''));
|
||||||
@@ -324,8 +336,7 @@ class ApiV2Controller extends BasePageController
|
|||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserRequest::addApiRequest($user->id, $request->getRequestUri());
|
$this->recordApiRequest($user, $request);
|
||||||
event(new UserAccessedApi($user, $request->ip()));
|
|
||||||
|
|
||||||
if ($request->has('id') && $request->isNotFilled('id')) {
|
if ($request->has('id') && $request->isNotFilled('id')) {
|
||||||
return response()->json(['error' => 'Incorrect parameter (id must not be empty)'], 400);
|
return response()->json(['error' => 'Incorrect parameter (id must not be empty)'], 400);
|
||||||
@@ -402,8 +413,7 @@ class ApiV2Controller extends BasePageController
|
|||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserRequest::addApiRequest($user->id, $request->getRequestUri());
|
$this->recordApiRequest($user, $request);
|
||||||
event(new UserAccessedApi($user, $request->ip()));
|
|
||||||
|
|
||||||
if ($request->has('id') && $request->isNotFilled('id')) {
|
if ($request->has('id') && $request->isNotFilled('id')) {
|
||||||
return response()->json(['error' => 'Incorrect parameter (id must not be empty)'], 400);
|
return response()->json(['error' => 'Incorrect parameter (id must not be empty)'], 400);
|
||||||
@@ -480,8 +490,7 @@ class ApiV2Controller extends BasePageController
|
|||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserRequest::addApiRequest($user->id, $request->getRequestUri());
|
$this->recordApiRequest($user, $request);
|
||||||
event(new UserAccessedApi($user, $request->ip()));
|
|
||||||
|
|
||||||
$q = (string) $request->input('id', '');
|
$q = (string) $request->input('id', '');
|
||||||
$anidb = (int) $request->input('anidbid', -1);
|
$anidb = (int) $request->input('anidbid', -1);
|
||||||
@@ -540,8 +549,7 @@ class ApiV2Controller extends BasePageController
|
|||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserRequest::addApiRequest($user->id, $request->getRequestUri());
|
$this->recordApiRequest($user, $request);
|
||||||
event(new UserAccessedApi($user, $request->ip()));
|
|
||||||
|
|
||||||
$offset = $this->api->offset($request);
|
$offset = $this->api->offset($request);
|
||||||
$catExclusions = User::getCachedCategoryExclusionById($user->id);
|
$catExclusions = User::getCachedCategoryExclusionById($user->id);
|
||||||
@@ -637,8 +645,7 @@ class ApiV2Controller extends BasePageController
|
|||||||
if (! is_string($sort)) {
|
if (! is_string($sort)) {
|
||||||
return $sort;
|
return $sort;
|
||||||
}
|
}
|
||||||
UserRequest::addApiRequest($user->id, $request->getRequestUri());
|
$this->recordApiRequest($user, $request);
|
||||||
event(new UserAccessedApi($user, $request->ip()));
|
|
||||||
|
|
||||||
$siteIdArr = [
|
$siteIdArr = [
|
||||||
'id' => $request->input('vid') ?? null,
|
'id' => $request->input('vid') ?? null,
|
||||||
@@ -703,8 +710,7 @@ class ApiV2Controller extends BasePageController
|
|||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
event(new UserAccessedApi($user, $request->ip()));
|
$this->recordApiRequest($user, $request);
|
||||||
UserRequest::addApiRequest($user->id, $request->getRequestUri());
|
|
||||||
$relData = Release::checkGuidForApi($request->input('id'));
|
$relData = Release::checkGuidForApi($request->input('id'));
|
||||||
if ($relData) {
|
if ($relData) {
|
||||||
$request->attributes->set(GetNzbController::REQUEST_USER_ATTRIBUTE, $user);
|
$request->attributes->set(GetNzbController::REQUEST_USER_ATTRIBUTE, $user);
|
||||||
@@ -725,8 +731,7 @@ class ApiV2Controller extends BasePageController
|
|||||||
return response()->json(['error' => 'Missing parameter (guid is required for single release details)'], 400);
|
return response()->json(['error' => 'Missing parameter (guid is required for single release details)'], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
UserRequest::addApiRequest($user->id, $request->getRequestUri());
|
$this->recordApiRequest($user, $request);
|
||||||
event(new UserAccessedApi($user, $request->ip()));
|
|
||||||
$guid = $request->input('id');
|
$guid = $request->input('id');
|
||||||
$relData = $this->releaseRowCache->remember('v2', 'details', [
|
$relData = $this->releaseRowCache->remember('v2', 'details', [
|
||||||
'guid' => $guid,
|
'guid' => $guid,
|
||||||
@@ -736,7 +741,12 @@ class ApiV2Controller extends BasePageController
|
|||||||
return response()->json(['error' => 'No such item'], 404);
|
return response()->json(['error' => 'No such item'], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(DetailsData::fromRelease($relData, $user)->toArray());
|
return response()->json(DetailsData::toArrayFromRelease(
|
||||||
|
$relData,
|
||||||
|
$user,
|
||||||
|
url('/details').'/',
|
||||||
|
url('/getnzb')
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function hasTvSearchParameters(Request $request): bool
|
private function hasTvSearchParameters(Request $request): bool
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace App\Listeners;
|
namespace App\Listeners;
|
||||||
|
|
||||||
use App\Events\UserAccessedApi;
|
use App\Events\UserAccessedApi;
|
||||||
use App\Models\User;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class UpdateUserAccessedApi
|
class UpdateUserAccessedApi
|
||||||
{
|
{
|
||||||
@@ -30,6 +30,8 @@ class UpdateUserAccessedApi
|
|||||||
$updateData['host'] = $event->ip;
|
$updateData['host'] = $event->ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
User::find($event->user->id)->update($updateData);
|
DB::table('users')
|
||||||
|
->where('id', $event->user->id)
|
||||||
|
->update($updateData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -568,6 +568,24 @@ class ApiRequestMatrixTest extends TestCase
|
|||||||
->assertJsonPath('genres.0.name', 'Test Genre');
|
->assertJsonPath('genres.0.name', 'Test Genre');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_v2_details_response_shape_is_unchanged(): void
|
||||||
|
{
|
||||||
|
$token = (string) DB::table('users')->value('api_token');
|
||||||
|
|
||||||
|
$this->getJson('/api/v2/details?api_token='.$token.'&id=release-guid')
|
||||||
|
->assertOk()
|
||||||
|
->assertJsonPath('title', 'Ubuntu.Release')
|
||||||
|
->assertJsonPath('details', 'http://localhost/details/release-guid')
|
||||||
|
->assertJsonPath('link', 'http://localhost/getnzb?id=release-guid.nzb&r='.$token)
|
||||||
|
->assertJsonPath('category', 5030)
|
||||||
|
->assertJsonPath('category_name', 'TV > SD')
|
||||||
|
->assertJsonPath('size', 123456)
|
||||||
|
->assertJsonPath('files', 10)
|
||||||
|
->assertJsonPath('grabs', 2)
|
||||||
|
->assertJsonPath('comments', 1)
|
||||||
|
->assertJsonPath('password', 0);
|
||||||
|
}
|
||||||
|
|
||||||
private function createSchema(): void
|
private function createSchema(): void
|
||||||
{
|
{
|
||||||
Schema::create('roles', function (Blueprint $table): void {
|
Schema::create('roles', function (Blueprint $table): void {
|
||||||
@@ -662,6 +680,54 @@ class ApiRequestMatrixTest extends TestCase
|
|||||||
$table->timestamp('timestamp')->nullable();
|
$table->timestamp('timestamp')->nullable();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Schema::create('videos', function (Blueprint $table): void {
|
||||||
|
$table->unsignedInteger('id')->primary();
|
||||||
|
$table->unsignedInteger('tvdb')->nullable();
|
||||||
|
$table->unsignedInteger('trakt')->nullable();
|
||||||
|
$table->unsignedInteger('tvrage')->nullable();
|
||||||
|
$table->unsignedInteger('tvmaze')->nullable();
|
||||||
|
$table->string('imdb')->nullable();
|
||||||
|
$table->unsignedInteger('tmdb')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create('tv_episodes', function (Blueprint $table): void {
|
||||||
|
$table->unsignedInteger('id')->primary();
|
||||||
|
$table->string('title')->nullable();
|
||||||
|
$table->string('series')->nullable();
|
||||||
|
$table->string('episode')->nullable();
|
||||||
|
$table->date('firstaired')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create('movieinfo', function (Blueprint $table): void {
|
||||||
|
$table->unsignedInteger('id')->primary();
|
||||||
|
$table->string('imdbid')->nullable();
|
||||||
|
$table->unsignedInteger('tmdbid')->nullable();
|
||||||
|
$table->unsignedInteger('traktid')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create('releases', function (Blueprint $table): void {
|
||||||
|
$table->unsignedInteger('id')->primary();
|
||||||
|
$table->string('searchname');
|
||||||
|
$table->string('guid')->index();
|
||||||
|
$table->dateTime('postdate');
|
||||||
|
$table->unsignedInteger('categories_id');
|
||||||
|
$table->unsignedBigInteger('size');
|
||||||
|
$table->unsignedInteger('totalpart');
|
||||||
|
$table->string('fromname')->nullable();
|
||||||
|
$table->integer('passwordstatus')->default(0);
|
||||||
|
$table->unsignedInteger('grabs')->default(0);
|
||||||
|
$table->unsignedInteger('comments')->default(0);
|
||||||
|
$table->dateTime('adddate');
|
||||||
|
$table->unsignedInteger('videos_id')->default(0);
|
||||||
|
$table->unsignedInteger('tv_episodes_id')->default(0);
|
||||||
|
$table->integer('haspreview')->default(0);
|
||||||
|
$table->integer('nfostatus')->default(0);
|
||||||
|
$table->unsignedInteger('movieinfo_id')->default(0);
|
||||||
|
$table->unsignedInteger('musicinfo_id')->default(0);
|
||||||
|
$table->unsignedInteger('consoleinfo_id')->default(0);
|
||||||
|
$table->unsignedInteger('groups_id')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
Schema::create('usenet_groups', function (Blueprint $table): void {
|
Schema::create('usenet_groups', function (Blueprint $table): void {
|
||||||
$table->increments('id');
|
$table->increments('id');
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
@@ -754,12 +820,36 @@ class ApiRequestMatrixTest extends TestCase
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
DB::table('usenet_groups')->insert([
|
DB::table('usenet_groups')->insert([
|
||||||
|
'id' => 1,
|
||||||
'name' => 'alt.binaries.test',
|
'name' => 'alt.binaries.test',
|
||||||
'active' => 1,
|
'active' => 1,
|
||||||
'description' => 'Test usenet group',
|
'description' => 'Test usenet group',
|
||||||
'last_updated' => now(),
|
'last_updated' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
DB::table('releases')->insert([
|
||||||
|
'id' => 1,
|
||||||
|
'searchname' => 'Ubuntu.Release',
|
||||||
|
'guid' => 'release-guid',
|
||||||
|
'postdate' => '2026-01-02 00:00:00',
|
||||||
|
'categories_id' => 5030,
|
||||||
|
'size' => 123456,
|
||||||
|
'totalpart' => 10,
|
||||||
|
'fromname' => 'poster',
|
||||||
|
'passwordstatus' => 0,
|
||||||
|
'grabs' => 2,
|
||||||
|
'comments' => 1,
|
||||||
|
'adddate' => '2026-01-03 00:00:00',
|
||||||
|
'videos_id' => 0,
|
||||||
|
'tv_episodes_id' => 0,
|
||||||
|
'haspreview' => 0,
|
||||||
|
'nfostatus' => 0,
|
||||||
|
'movieinfo_id' => 0,
|
||||||
|
'musicinfo_id' => 0,
|
||||||
|
'consoleinfo_id' => 0,
|
||||||
|
'groups_id' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
DB::table('genres')->insert([
|
DB::table('genres')->insert([
|
||||||
'id' => 1,
|
'id' => 1,
|
||||||
'title' => 'Test Genre',
|
'title' => 'Test Genre',
|
||||||
|
|||||||
@@ -4,11 +4,28 @@ namespace Tests\Feature;
|
|||||||
|
|
||||||
use App\Events\UserAccessedApi;
|
use App\Events\UserAccessedApi;
|
||||||
use App\Listeners\UpdateUserAccessedApi;
|
use App\Listeners\UpdateUserAccessedApi;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
use stdClass;
|
use stdClass;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
final class UpdateUserAccessedApiTest extends TestCase
|
final class UpdateUserAccessedApiTest extends TestCase
|
||||||
{
|
{
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
config([
|
||||||
|
'database.default' => 'sqlite',
|
||||||
|
'database.connections.sqlite.database' => ':memory:',
|
||||||
|
'app.key' => 'base64:'.base64_encode(random_bytes(32)),
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::purge();
|
||||||
|
DB::reconnect();
|
||||||
|
}
|
||||||
|
|
||||||
public function test_event_has_ip_property(): void
|
public function test_event_has_ip_property(): void
|
||||||
{
|
{
|
||||||
// Use a simple stdClass as the event just stores the user reference
|
// Use a simple stdClass as the event just stores the user reference
|
||||||
@@ -43,4 +60,57 @@ final class UpdateUserAccessedApiTest extends TestCase
|
|||||||
$this->assertEquals(999, $event->user->id);
|
$this->assertEquals(999, $event->user->id);
|
||||||
$this->assertEquals('10.0.0.1', $event->ip);
|
$this->assertEquals('10.0.0.1', $event->ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_listener_updates_api_access_and_host(): void
|
||||||
|
{
|
||||||
|
$this->createUsersTable();
|
||||||
|
|
||||||
|
DB::table('users')->insert([
|
||||||
|
'id' => 1,
|
||||||
|
'host' => null,
|
||||||
|
'apiaccess' => null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = new stdClass;
|
||||||
|
$user->id = 1;
|
||||||
|
|
||||||
|
(new UpdateUserAccessedApi)->handle(new UserAccessedApi($user, '192.168.1.100'));
|
||||||
|
|
||||||
|
$row = DB::table('users')->where('id', 1)->first();
|
||||||
|
|
||||||
|
$this->assertSame('192.168.1.100', $row->host);
|
||||||
|
$this->assertNotNull($row->apiaccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_listener_updates_with_a_single_query_without_loading_user_model(): void
|
||||||
|
{
|
||||||
|
$this->createUsersTable();
|
||||||
|
|
||||||
|
DB::table('users')->insert([
|
||||||
|
'id' => 1,
|
||||||
|
'host' => null,
|
||||||
|
'apiaccess' => null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = new stdClass;
|
||||||
|
$user->id = 1;
|
||||||
|
|
||||||
|
DB::flushQueryLog();
|
||||||
|
DB::enableQueryLog();
|
||||||
|
|
||||||
|
(new UpdateUserAccessedApi)->handle(new UserAccessedApi($user, '10.0.0.1'));
|
||||||
|
|
||||||
|
$queries = DB::getQueryLog();
|
||||||
|
$this->assertCount(1, $queries);
|
||||||
|
$this->assertStringStartsWith('update ', strtolower((string) $queries[0]['query']));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createUsersTable(): void
|
||||||
|
{
|
||||||
|
Schema::create('users', function (Blueprint $table): void {
|
||||||
|
$table->increments('id');
|
||||||
|
$table->string('host')->nullable();
|
||||||
|
$table->timestamp('apiaccess')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Tests\Unit;
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\Data\Api\DetailsData;
|
||||||
use App\Data\Api\ReleaseData;
|
use App\Data\Api\ReleaseData;
|
||||||
use App\Facades\Search;
|
use App\Facades\Search;
|
||||||
use App\Models\Release;
|
use App\Models\Release;
|
||||||
@@ -133,7 +134,38 @@ class ApiPerformanceHelpersTest extends TestCase
|
|||||||
|
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
ReleaseData::fromRelease($release, $user)->toArray(),
|
ReleaseData::fromRelease($release, $user)->toArray(),
|
||||||
ReleaseData::toArrayFromRelease($release, $user)
|
ReleaseData::toArrayFromRelease($release, $user, url('/details').'/', url('/getnzb'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_details_data_fast_array_matches_existing_data_output(): void
|
||||||
|
{
|
||||||
|
$release = (object) [
|
||||||
|
'searchname' => 'Ubuntu.Release',
|
||||||
|
'guid' => 'release-guid',
|
||||||
|
'categories_id' => 5030,
|
||||||
|
'category_name' => 'TV > SD',
|
||||||
|
'adddate' => '2026-01-03 00:00:00',
|
||||||
|
'size' => 123456,
|
||||||
|
'totalpart' => 10,
|
||||||
|
'grabs' => 2,
|
||||||
|
'comments' => 1,
|
||||||
|
'passwordstatus' => 0,
|
||||||
|
'postdate' => '2026-01-02 00:00:00',
|
||||||
|
'imdb' => '1234567',
|
||||||
|
'tmdb' => 234,
|
||||||
|
'trakt' => 345,
|
||||||
|
'firstaired' => '2026-01-01',
|
||||||
|
'tvdb' => 456,
|
||||||
|
'tvrage' => 567,
|
||||||
|
'tvmaze' => 678,
|
||||||
|
];
|
||||||
|
$user = new User;
|
||||||
|
$user->api_token = 'api-token';
|
||||||
|
|
||||||
|
$this->assertSame(
|
||||||
|
DetailsData::fromRelease($release, $user)->toArray(),
|
||||||
|
DetailsData::toArrayFromRelease($release, $user, url('/details').'/', url('/getnzb'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user