mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-29 02:01:33 +00:00
Update browse and API queries
This commit is contained in:
@@ -178,11 +178,10 @@ class GamesService
|
||||
*
|
||||
* @param array<string, mixed> $excludedCats
|
||||
* @param array<string, mixed> $orderBy
|
||||
* @return array<string, mixed>
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getGamesRange(mixed $page, mixed $cat, mixed $start, mixed $num, array|string $orderBy = '', string $maxAge = '', array $excludedCats = []): array
|
||||
public function getGamesRange(mixed $page, mixed $cat, mixed $start, mixed $num, array|string $orderBy = '', string $maxAge = '', array $excludedCats = []): mixed
|
||||
{
|
||||
$page = max(1, $page);
|
||||
$start = max(0, $start);
|
||||
@@ -192,91 +191,110 @@ class GamesService
|
||||
if (count($cat) > 0 && $cat[0] !== -1) {
|
||||
$catsrch = Category::getCategorySearch($cat);
|
||||
}
|
||||
$whereAge = '';
|
||||
if ($maxAge > 0) {
|
||||
$maxAge = sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxAge);
|
||||
$whereAge = sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxAge);
|
||||
}
|
||||
$exccatlist = '';
|
||||
if (count($excludedCats) > 0) {
|
||||
$exccatlist = ' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')';
|
||||
}
|
||||
$order = $this->getGamesOrder($orderBy);
|
||||
$gamesSql =
|
||||
"SELECT SQL_CALC_FOUND_ROWS gi.id, GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_id FROM gamesinfo gi LEFT JOIN releases r ON gi.id = r.gamesinfo_id WHERE gi.title != '' AND gi.cover = 1 AND r.passwordstatus "
|
||||
.app(\App\Services\Releases\ReleaseBrowseService::class)->showPasswords().
|
||||
$browseBy.
|
||||
$catsrch.
|
||||
$maxAge.
|
||||
$exccatlist.
|
||||
' GROUP BY gi.id ORDER BY '.($order[0]).' '.($order[1]). // @phpstan-ignore offsetAccess.notFound
|
||||
($start === false ? '' : ' LIMIT '.$num.' OFFSET '.$start);
|
||||
|
||||
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium'));
|
||||
$gamesCache = Cache::get(md5($gamesSql.$page));
|
||||
if ($gamesCache !== null) {
|
||||
$games = $gamesCache;
|
||||
} else {
|
||||
$data = DB::select($gamesSql);
|
||||
$games = ['total' => DB::select('SELECT FOUND_ROWS() AS total'), 'result' => $data];
|
||||
Cache::put(md5($gamesSql.$page), $games, $expiresAt);
|
||||
$showPasswords = app(\App\Services\Releases\ReleaseBrowseService::class)->showPasswords();
|
||||
|
||||
$baseWhere = "gi.title != '' AND gi.cover = 1 "
|
||||
."AND r.passwordstatus {$showPasswords} "
|
||||
.$browseBy.' '
|
||||
.$catsrch.' '
|
||||
.$whereAge
|
||||
.$exccatlist;
|
||||
|
||||
$cacheKey = md5('games_range_'.$baseWhere.$order[0].$order[1].$start.$num.$page); // @phpstan-ignore offsetAccess.notFound
|
||||
|
||||
$cached = Cache::get($cacheKey);
|
||||
if ($cached !== null) {
|
||||
return $cached;
|
||||
}
|
||||
|
||||
$gameIDs = $releaseIDs = [];
|
||||
if (is_array($games['result'])) {
|
||||
foreach ($games['result'] as $game => $id) {
|
||||
$gameIDs[] = $id->id;
|
||||
$releaseIDs[] = $id->grp_release_id;
|
||||
}
|
||||
// Step 1: Count total distinct games matching filters
|
||||
$countSql = 'SELECT COUNT(DISTINCT gi.id) AS total '
|
||||
.'FROM gamesinfo gi '
|
||||
.'INNER JOIN releases r ON gi.id = r.gamesinfo_id '
|
||||
.'WHERE '.$baseWhere;
|
||||
|
||||
$totalResult = DB::select($countSql);
|
||||
$totalCount = $totalResult[0]->total ?? 0;
|
||||
|
||||
if ($totalCount === 0) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
$returnSql = sprintf(
|
||||
"SELECT
|
||||
GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_id,
|
||||
GROUP_CONCAT(r.rarinnerfilecount ORDER BY r.postdate DESC SEPARATOR ',') AS grp_rarinnerfilecount,
|
||||
GROUP_CONCAT(r.haspreview ORDER BY r.postdate DESC SEPARATOR ',') AS grp_haspreview,
|
||||
GROUP_CONCAT(r.passwordstatus ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_password,
|
||||
GROUP_CONCAT(r.guid ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_guid,
|
||||
GROUP_CONCAT(rn.releases_id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_nfoid,
|
||||
GROUP_CONCAT(g.name ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_grpname,
|
||||
GROUP_CONCAT(r.searchname ORDER BY r.postdate DESC SEPARATOR '#') AS grp_release_name,
|
||||
GROUP_CONCAT(r.postdate ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_postdate,
|
||||
GROUP_CONCAT(r.adddate ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_adddate,
|
||||
GROUP_CONCAT(r.size ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_size,
|
||||
GROUP_CONCAT(r.totalpart ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_totalparts,
|
||||
GROUP_CONCAT(r.comments ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_comments,
|
||||
GROUP_CONCAT(r.grabs ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_grabs,
|
||||
GROUP_CONCAT(df.failed ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_failed,
|
||||
GROUP_CONCAT(cp.title, ' > ', c.title ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_catname,
|
||||
gi.*, YEAR(gi.releasedate) as year, r.gamesinfo_id, rn.releases_id AS nfoid, g.name AS group_name
|
||||
FROM releases r
|
||||
LEFT OUTER JOIN usenet_groups g ON g.id = r.groups_id
|
||||
LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id
|
||||
LEFT OUTER JOIN dnzb_failures df ON df.release_id = r.id
|
||||
LEFT OUTER JOIN categories c ON c.id = r.categories_id
|
||||
LEFT OUTER JOIN root_categories cp ON cp.id = c.root_categories_id
|
||||
INNER JOIN gamesinfo gi ON gi.id = r.gamesinfo_id
|
||||
WHERE gi.id IN (%s)
|
||||
AND r.id IN (%s)
|
||||
%s
|
||||
GROUP BY gi.id
|
||||
ORDER BY %s %s",
|
||||
(! empty($gameIDs) ? implode(',', $gameIDs) : -1),
|
||||
(! empty($releaseIDs) ? implode(',', $releaseIDs) : -1),
|
||||
$catsrch,
|
||||
$order[0], // @phpstan-ignore offsetAccess.notFound
|
||||
$order[1] // @phpstan-ignore offsetAccess.notFound
|
||||
);
|
||||
// Step 2: Get paginated games entity list with only needed columns
|
||||
$gamesSql = 'SELECT gi.id, gi.title, gi.cover, gi.publisher, gi.releasedate, gi.review, gi.url, '
|
||||
.'YEAR(gi.releasedate) AS year, '
|
||||
.'MAX(r.postdate) AS latest_postdate, '
|
||||
.'COUNT(r.id) AS total_releases '
|
||||
.'FROM gamesinfo gi '
|
||||
.'INNER JOIN releases r ON gi.id = r.gamesinfo_id '
|
||||
.'WHERE '.$baseWhere.' '
|
||||
.'GROUP BY gi.id, gi.title, gi.cover, gi.publisher, gi.releasedate, gi.review, gi.url '
|
||||
."ORDER BY {$order[0]} {$order[1]} " // @phpstan-ignore offsetAccess.notFound
|
||||
."LIMIT {$num} OFFSET {$start}";
|
||||
|
||||
$return = Cache::get(md5($returnSql.$page));
|
||||
if ($return !== null) {
|
||||
return $return;
|
||||
}
|
||||
$return = DB::select($returnSql);
|
||||
if (count($return) > 0) {
|
||||
$return[0]->_totalcount = $games['total'][0]->total ?? 0;
|
||||
}
|
||||
Cache::put(md5($returnSql.$page), $return, $expiresAt);
|
||||
$games = GamesInfo::fromQuery($gamesSql);
|
||||
|
||||
return $return;
|
||||
if ($games->isEmpty()) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
// Build list of game IDs for release query
|
||||
$gameIds = $games->pluck('id')->toArray();
|
||||
$inGameIds = implode(',', array_map('intval', $gameIds));
|
||||
|
||||
// Step 3: Get top 2 releases per game using ROW_NUMBER()
|
||||
$releasesSql = 'SELECT ranked.id, ranked.gamesinfo_id, ranked.guid, ranked.searchname, '
|
||||
.'ranked.size, ranked.postdate, ranked.adddate, ranked.haspreview, ranked.grabs, '
|
||||
.'ranked.comments, ranked.totalpart, ranked.group_name, ranked.nfoid, ranked.failed_count '
|
||||
.'FROM ( '
|
||||
.'SELECT r.id, r.gamesinfo_id, r.guid, r.searchname, r.size, r.postdate, r.adddate, '
|
||||
.'r.haspreview, r.grabs, r.comments, r.totalpart, g.name AS group_name, '
|
||||
.'rn.releases_id AS nfoid, df.failed AS failed_count, '
|
||||
.'ROW_NUMBER() OVER (PARTITION BY r.gamesinfo_id ORDER BY r.postdate DESC) AS rn '
|
||||
.'FROM releases r '
|
||||
.'LEFT JOIN usenet_groups g ON g.id = r.groups_id '
|
||||
.'LEFT JOIN release_nfos rn ON rn.releases_id = r.id '
|
||||
.'LEFT JOIN dnzb_failures df ON df.release_id = r.id '
|
||||
."WHERE r.gamesinfo_id IN ({$inGameIds}) "
|
||||
."AND r.passwordstatus {$showPasswords} "
|
||||
.$catsrch.' '
|
||||
.$whereAge
|
||||
.$exccatlist
|
||||
.') ranked '
|
||||
.'WHERE ranked.rn <= 2 '
|
||||
.'ORDER BY ranked.gamesinfo_id, ranked.postdate DESC';
|
||||
|
||||
$releases = DB::select($releasesSql);
|
||||
|
||||
// Group releases by gamesinfo_id for fast lookup
|
||||
$releasesByGame = [];
|
||||
foreach ($releases as $release) {
|
||||
$releasesByGame[$release->gamesinfo_id][] = $release;
|
||||
}
|
||||
|
||||
// Attach releases to each game entity
|
||||
foreach ($games as $game) {
|
||||
$game->releases = $releasesByGame[$game->id] ?? []; // @phpstan-ignore assign.propertyReadOnly
|
||||
}
|
||||
|
||||
// Set total count on first item
|
||||
if ($games->isNotEmpty()) {
|
||||
$games[0]->_totalcount = $totalCount; // @phpstan-ignore property.notFound
|
||||
}
|
||||
|
||||
Cache::put($cacheKey, $games, $expiresAt);
|
||||
|
||||
return $games;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user