mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-29 00:01:21 +00:00
Separate Blacklight/Releases into specific services
This commit is contained in:
@@ -127,7 +127,7 @@ class Books
|
||||
%s %s %s
|
||||
GROUP BY boo.id
|
||||
ORDER BY %s %s %s",
|
||||
(new Releases)->showPasswords(),
|
||||
app(\App\Services\Releases\ReleaseBrowseService::class)->showPasswords(),
|
||||
$browseby,
|
||||
$catsrch,
|
||||
$exccatlist,
|
||||
|
||||
@@ -163,7 +163,7 @@ class Console
|
||||
%s %s %s
|
||||
GROUP BY con.id
|
||||
ORDER BY %s %s %s",
|
||||
(new Releases)->showPasswords(),
|
||||
app(\App\Services\Releases\ReleaseBrowseService::class)->showPasswords(),
|
||||
$browseBy,
|
||||
$catsrch,
|
||||
$exccatlist,
|
||||
|
||||
@@ -205,7 +205,7 @@ class Games
|
||||
$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 "
|
||||
.(new Releases)->showPasswords().
|
||||
.app(\App\Services\Releases\ReleaseBrowseService::class)->showPasswords().
|
||||
$browseBy.
|
||||
$catsrch.
|
||||
$maxAge.
|
||||
|
||||
@@ -129,7 +129,7 @@ class Movie
|
||||
|
||||
$this->imdburl = (int) Settings::settingValue('imdburl') !== 0;
|
||||
$this->movieqty = Settings::settingValue('maximdbprocessed') !== '' ? (int) Settings::settingValue('maximdbprocessed') : 100;
|
||||
$this->showPasswords = (new Releases)->showPasswords();
|
||||
$this->showPasswords = app(\App\Services\Releases\ReleaseBrowseService::class)->showPasswords();
|
||||
|
||||
$this->echooutput = config('nntmux.echocli');
|
||||
$this->imgSavePath = storage_path('covers/movies/');
|
||||
|
||||
@@ -151,7 +151,7 @@ class Music
|
||||
%s %s %s
|
||||
GROUP BY m.id
|
||||
ORDER BY %s %s %s",
|
||||
(new Releases)->showPasswords(),
|
||||
app(\App\Services\Releases\ReleaseBrowseService::class)->showPasswords(),
|
||||
$browseby,
|
||||
$catsrch,
|
||||
$exccatlist,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Blacklight;
|
||||
|
||||
use App\Models\UsenetGroup;
|
||||
use App\Services\Releases\ReleaseManagementService;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
@@ -17,7 +18,7 @@ class NZBExport
|
||||
|
||||
protected NZB $nzb;
|
||||
|
||||
protected Releases $releases;
|
||||
protected ReleaseManagementService $releaseManagement;
|
||||
|
||||
protected bool $echoCLI;
|
||||
|
||||
@@ -30,7 +31,7 @@ class NZBExport
|
||||
public function __construct()
|
||||
{
|
||||
$this->echoCLI = config('nntmux.echocli');
|
||||
$this->releases = new Releases;
|
||||
$this->releaseManagement = app(ReleaseManagementService::class);
|
||||
$this->nzb = new NZB;
|
||||
}
|
||||
|
||||
@@ -104,7 +105,7 @@ class NZBExport
|
||||
foreach ($groups as $group) {
|
||||
$currentExport = 0;
|
||||
// Get all the releases based on the parameters.
|
||||
$releases = $this->releases->getForExport($fromDate, $toDate, $group['id']);
|
||||
$releases = $this->releaseManagement->getForExport($fromDate, $toDate, $group['id']);
|
||||
$totalFound = \count($releases);
|
||||
if ($totalFound === 0) {
|
||||
if ($this->echoCLI) {
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Blacklight;
|
||||
use App\Enums\BlacklistConstants;
|
||||
use App\Models\Category;
|
||||
use App\Models\Settings;
|
||||
use App\Services\Releases\ReleaseManagementService;
|
||||
use Exception;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -41,7 +42,7 @@ class ReleaseRemover
|
||||
protected bool $ignoreUserCheck = false;
|
||||
protected string $method = '';
|
||||
protected string $query = '';
|
||||
protected Releases $releases;
|
||||
protected ReleaseManagementService $releaseManagement;
|
||||
protected array $result = [];
|
||||
private NZB $nzb;
|
||||
private ReleaseImage $releaseImage;
|
||||
@@ -54,7 +55,7 @@ class ReleaseRemover
|
||||
public function __construct()
|
||||
{
|
||||
$this->colorCLI = new ColorCLI;
|
||||
$this->releases = new Releases;
|
||||
$this->releaseManagement = app(ReleaseManagementService::class);
|
||||
$this->nzb = new NZB;
|
||||
$this->releaseImage = new ReleaseImage;
|
||||
$this->echoCLI = config('nntmux.echocli');
|
||||
@@ -844,7 +845,7 @@ class ReleaseRemover
|
||||
$deletedCount = 0;
|
||||
foreach ($this->result as $release) {
|
||||
if ($this->delete) {
|
||||
$this->releases->deleteSingle(['g' => $release->guid, 'i' => $release->id], $this->nzb, $this->releaseImage);
|
||||
$this->releaseManagement->deleteSingle(['g' => $release->guid, 'i' => $release->id], $this->nzb, $this->releaseImage);
|
||||
if ($this->echoCLI) {
|
||||
$this->colorCLI->primary('Deleting: '.$this->method.': '.$release->searchname, true);
|
||||
}
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ class XXX
|
||||
$this->colorCli = new ColorCLI;
|
||||
|
||||
$this->movieQty = Settings::settingValue('maxxxxprocessed') ?? 100;
|
||||
$this->showPasswords = (new Releases)->showPasswords();
|
||||
$this->showPasswords = app(\App\Services\Releases\ReleaseBrowseService::class)->showPasswords();
|
||||
$this->echoOutput = config('nntmux.echocli');
|
||||
$this->imgSavePath = storage_path('covers/xxx/');
|
||||
$this->cookie = resource_path('tmp/xxx.cookie');
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Release;
|
||||
use App\Services\Releases\ReleaseManagementService;
|
||||
use Blacklight\NZB;
|
||||
use Blacklight\ReleaseImage;
|
||||
use Blacklight\Releases;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\File;
|
||||
@@ -80,20 +80,20 @@ class CleanNZB extends Command
|
||||
{
|
||||
// Setup
|
||||
$nzb = new NZB;
|
||||
$rel = new Releases;
|
||||
$releaseManagement = app(ReleaseManagementService::class);
|
||||
$checked = $deleted = 0;
|
||||
|
||||
$this->info('Getting list of releases from database to check if they have a corresponding NZB on disk');
|
||||
$total = Release::count();
|
||||
$this->alert("Total releases to check: $total");
|
||||
|
||||
Release::where('nzbstatus', 1)->chunkById((int) $this->option('chunksize'), function (Collection $releases) use ($delete, &$checked, &$deleted, $nzb, $rel) {
|
||||
Release::where('nzbstatus', 1)->chunkById((int) $this->option('chunksize'), function (Collection $releases) use ($delete, &$checked, &$deleted, $nzb, $releaseManagement) {
|
||||
echo 'Total done: '.$checked."\r";
|
||||
foreach ($releases as $r) {
|
||||
|
||||
if (! $nzb->NZBPath($r->guid)) {
|
||||
if ($delete) {
|
||||
$rel->deleteSingle(['g' => $r->guid, 'i' => $r->id], $nzb, new ReleaseImage);
|
||||
$releaseManagement->deleteSingle(['g' => $r->guid, 'i' => $r->id], $nzb, new ReleaseImage);
|
||||
}
|
||||
$deleted++;
|
||||
$this->line("Deleted: $r->searchname -> $r->guid");
|
||||
|
||||
@@ -5,11 +5,19 @@ namespace App\Http\Controllers\Admin;
|
||||
use App\Http\Controllers\BasePageController;
|
||||
use App\Models\Category;
|
||||
use App\Models\Release;
|
||||
use Blacklight\Releases;
|
||||
use App\Services\Releases\ReleaseManagementService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AdminReleasesController extends BasePageController
|
||||
{
|
||||
private ReleaseManagementService $releaseManagement;
|
||||
|
||||
public function __construct(ReleaseManagementService $releaseManagement)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->releaseManagement = $releaseManagement;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
@@ -88,8 +96,7 @@ class AdminReleasesController extends BasePageController
|
||||
{
|
||||
try {
|
||||
if ($id) {
|
||||
$releases = new Releases;
|
||||
$releases->deleteMultiple($id);
|
||||
$this->releaseManagement->deleteMultiple($id);
|
||||
|
||||
// Handle AJAX requests
|
||||
if (request()->wantsJson() || request()->ajax()) {
|
||||
|
||||
@@ -12,8 +12,9 @@ use App\Models\UsenetGroup;
|
||||
use App\Models\User;
|
||||
use App\Models\UserDownload;
|
||||
use App\Models\UserRequest;
|
||||
use App\Services\Releases\ReleaseBrowseService;
|
||||
use App\Services\Releases\ReleaseSearchService;
|
||||
use Blacklight\NZB;
|
||||
use Blacklight\Releases;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -27,6 +28,17 @@ use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
class ApiController extends BasePageController
|
||||
{
|
||||
private string $type;
|
||||
private ReleaseSearchService $releaseSearchService;
|
||||
private ReleaseBrowseService $releaseBrowseService;
|
||||
|
||||
public function __construct(
|
||||
ReleaseSearchService $releaseSearchService,
|
||||
ReleaseBrowseService $releaseBrowseService
|
||||
) {
|
||||
parent::__construct();
|
||||
$this->releaseSearchService = $releaseSearchService;
|
||||
$this->releaseBrowseService = $releaseBrowseService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Application|\Illuminate\Foundation\Application|RedirectResponse|Redirector|StreamedResponse|void
|
||||
@@ -119,7 +131,6 @@ class ApiController extends BasePageController
|
||||
}
|
||||
}
|
||||
|
||||
$releases = new Releases;
|
||||
|
||||
// Set Query Parameters based on Request objects
|
||||
$outputXML = ! ($request->has('o') && $request->input('o') === 'json');
|
||||
@@ -155,7 +166,7 @@ class ApiController extends BasePageController
|
||||
];
|
||||
|
||||
if ($request->has('q')) {
|
||||
$relData = $releases->search(
|
||||
$relData = $this->releaseSearchService->search(
|
||||
$searchArr,
|
||||
$groupName,
|
||||
-1,
|
||||
@@ -172,7 +183,7 @@ class ApiController extends BasePageController
|
||||
$minSize
|
||||
);
|
||||
} else {
|
||||
$relData = $releases->getBrowseRange(
|
||||
$relData = $this->releaseBrowseService->getBrowseRange(
|
||||
1,
|
||||
$categoryID,
|
||||
$offset,
|
||||
@@ -220,7 +231,7 @@ class ApiController extends BasePageController
|
||||
$airDate = str_replace('/', '-', $year[0].'-'.$episode);
|
||||
}
|
||||
|
||||
$relData = $releases->tvSearch(
|
||||
$relData = $this->releaseSearchService->tvSearch(
|
||||
$siteIdArr,
|
||||
$series,
|
||||
$episode,
|
||||
@@ -248,7 +259,7 @@ class ApiController extends BasePageController
|
||||
$tmdbId = $request->has('tmdbid') && $request->filled('tmdbid') ? (int) $request->input('tmdbid') : -1;
|
||||
$traktId = $request->has('traktid') && $request->filled('traktid') ? (int) $request->input('traktid') : -1;
|
||||
|
||||
$relData = $releases->moviesSearch(
|
||||
$relData = $this->releaseSearchService->moviesSearch(
|
||||
$imdbId,
|
||||
$tmdbId,
|
||||
$traktId,
|
||||
|
||||
@@ -10,10 +10,11 @@ use App\Models\Settings;
|
||||
use App\Models\User;
|
||||
use App\Models\UserDownload;
|
||||
use App\Models\UserRequest;
|
||||
use App\Services\Releases\ReleaseBrowseService;
|
||||
use App\Services\Releases\ReleaseSearchService;
|
||||
use App\Transformers\ApiTransformer;
|
||||
use App\Transformers\CategoryTransformer;
|
||||
use App\Transformers\DetailsTransformer;
|
||||
use Blacklight\Releases;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -23,10 +24,17 @@ use Illuminate\Support\Facades\DB;
|
||||
class ApiV2Controller extends BasePageController
|
||||
{
|
||||
private ApiController $api;
|
||||
private ReleaseSearchService $releaseSearchService;
|
||||
private ReleaseBrowseService $releaseBrowseService;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->api = new ApiController;
|
||||
public function __construct(
|
||||
ApiController $api,
|
||||
ReleaseSearchService $releaseSearchService,
|
||||
ReleaseBrowseService $releaseBrowseService
|
||||
) {
|
||||
$this->api = $api;
|
||||
$this->releaseSearchService = $releaseSearchService;
|
||||
$this->releaseBrowseService = $releaseBrowseService;
|
||||
}
|
||||
|
||||
public function capabilities(): JsonResponse
|
||||
@@ -93,7 +101,7 @@ class ApiV2Controller extends BasePageController
|
||||
];
|
||||
|
||||
// Perform search
|
||||
$relData = (new Releases)->moviesSearch(
|
||||
$relData = $this->releaseSearchService->moviesSearch(
|
||||
$params['imdbId'],
|
||||
$params['tmdbId'],
|
||||
$params['traktId'],
|
||||
@@ -137,7 +145,6 @@ class ApiV2Controller extends BasePageController
|
||||
if ($request->missing('api_token') || $request->isNotFilled('api_token')) {
|
||||
return response()->json(['error' => 'Missing parameter (api_token)'], 403);
|
||||
}
|
||||
$releases = new Releases;
|
||||
$user = User::query()->where('api_token', $request->input('api_token'))->first();
|
||||
$offset = $this->api->offset($request);
|
||||
$catExclusions = User::getCategoryExclusionForApi($request);
|
||||
@@ -150,7 +157,7 @@ class ApiV2Controller extends BasePageController
|
||||
$limit = $this->api->limit($request);
|
||||
|
||||
if ($request->has('id')) {
|
||||
$relData = $releases->apiSearch(
|
||||
$relData = $this->releaseSearchService->apiSearch(
|
||||
$request->input('id'),
|
||||
$groupName,
|
||||
$offset,
|
||||
@@ -161,7 +168,7 @@ class ApiV2Controller extends BasePageController
|
||||
$minSize
|
||||
);
|
||||
} else {
|
||||
$relData = $releases->getBrowseRange(
|
||||
$relData = $this->releaseBrowseService->getBrowseRange(
|
||||
1,
|
||||
$categoryID,
|
||||
$offset,
|
||||
@@ -202,7 +209,6 @@ class ApiV2Controller extends BasePageController
|
||||
if ($request->missing('api_token') || $request->isNotFilled('api_token')) {
|
||||
return response()->json(['error' => 'Missing parameter (api_token)'], 403);
|
||||
}
|
||||
$releases = new Releases;
|
||||
$user = User::query()->where('api_token', $request->input('api_token'))->first();
|
||||
if ($user === null) {
|
||||
return response()->json(['error' => 'Invalid API Token'], 403);
|
||||
@@ -242,7 +248,7 @@ class ApiV2Controller extends BasePageController
|
||||
$airDate = str_replace('/', '-', $year[0].'-'.$episode);
|
||||
}
|
||||
|
||||
$relData = $releases->apiTvSearch(
|
||||
$relData = $this->releaseSearchService->apiTvSearch(
|
||||
$siteIdArr,
|
||||
$series,
|
||||
$episode,
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Models\Release;
|
||||
use Blacklight\Releases;
|
||||
use App\Services\Releases\ReleaseBrowseService;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
@@ -15,7 +15,7 @@ use Illuminate\Support\Facades\DB;
|
||||
*/
|
||||
class RSS extends ApiController
|
||||
{
|
||||
public Releases $releases;
|
||||
public ReleaseBrowseService $releaseBrowseService;
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
@@ -23,7 +23,7 @@ class RSS extends ApiController
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->releases = new Releases;
|
||||
$this->releaseBrowseService = app(ReleaseBrowseService::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,7 +72,7 @@ class RSS extends ApiController
|
||||
%s %s %s %s
|
||||
ORDER BY postdate DESC %s",
|
||||
$cartSearch,
|
||||
$this->releases->showPasswords(),
|
||||
$this->releaseBrowseService->showPasswords(),
|
||||
$catSearch,
|
||||
($videosId > 0 ? sprintf('AND r.videos_id = %d %s', $videosId, ($catSearch === '' ? $catLimit : '')) : ''),
|
||||
($aniDbID > 0 ? sprintf('AND r.anidbid = %d %s', $aniDbID, ($catSearch === '' ? $catLimit : '')) : ''),
|
||||
|
||||
@@ -4,24 +4,30 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Models\RootCategory;
|
||||
use Blacklight\Releases;
|
||||
use App\Services\Releases\ReleaseBrowseService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class BrowseController extends BasePageController
|
||||
{
|
||||
private ReleaseBrowseService $releaseBrowseService;
|
||||
|
||||
public function __construct(ReleaseBrowseService $releaseBrowseService)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->releaseBrowseService = $releaseBrowseService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$releases = new Releases;
|
||||
|
||||
$ordering = $releases->getBrowseOrdering();
|
||||
$ordering = $this->releaseBrowseService->getBrowseOrdering();
|
||||
$orderBy = $request->has('ob') && ! empty($request->input('ob')) ? $request->input('ob') : '';
|
||||
$page = $request->has('page') && is_numeric($request->input('page')) ? $request->input('page') : 1;
|
||||
$offset = ($page - 1) * config('nntmux.items_per_page');
|
||||
|
||||
$rslt = $releases->getBrowseRange($page, [-1], $offset, config('nntmux.items_per_page'), $orderBy, -1, $this->userdata->categoryexclusions, -1);
|
||||
$rslt = $this->releaseBrowseService->getBrowseRange($page, [-1], $offset, config('nntmux.items_per_page'), $orderBy, -1, $this->userdata->categoryexclusions, -1);
|
||||
$results = $this->paginate($rslt ?? [], $rslt[0]->_totalcount ?? 0, config('nntmux.items_per_page'), $page, $request->url(), $request->query());
|
||||
|
||||
// Build order by URLs
|
||||
@@ -48,7 +54,6 @@ class BrowseController extends BasePageController
|
||||
*/
|
||||
public function show(Request $request, string $parentCategory, string $id = 'All')
|
||||
{
|
||||
$releases = new Releases;
|
||||
|
||||
$parentId = RootCategory::query()->where('title', $parentCategory)->value('id');
|
||||
|
||||
@@ -65,12 +70,12 @@ class BrowseController extends BasePageController
|
||||
$catarray = [];
|
||||
$catarray[] = $category;
|
||||
|
||||
$ordering = $releases->getBrowseOrdering();
|
||||
$ordering = $this->releaseBrowseService->getBrowseOrdering();
|
||||
$orderBy = $request->has('ob') && ! empty($request->input('ob')) ? $request->input('ob') : '';
|
||||
$page = $request->has('page') && is_numeric($request->input('page')) ? $request->input('page') : 1;
|
||||
$offset = ($page - 1) * config('nntmux.items_per_page');
|
||||
|
||||
$rslt = $releases->getBrowseRange($page, $catarray, $offset, config('nntmux.items_per_page'), $orderBy, -1, $this->userdata->categoryexclusions, $grp);
|
||||
$rslt = $this->releaseBrowseService->getBrowseRange($page, $catarray, $offset, config('nntmux.items_per_page'), $orderBy, -1, $this->userdata->categoryexclusions, $grp);
|
||||
$results = $this->paginate($rslt ?? [], $rslt[0]->_totalcount ?? 0, config('nntmux.items_per_page'), $page, $request->url(), $request->query());
|
||||
|
||||
$covgroup = '';
|
||||
@@ -139,12 +144,11 @@ class BrowseController extends BasePageController
|
||||
*/
|
||||
public function group(Request $request)
|
||||
{
|
||||
$releases = new Releases;
|
||||
if ($request->has('g')) {
|
||||
$group = $request->input('g');
|
||||
$page = $request->has('page') && is_numeric($request->input('page')) ? $request->input('page') : 1;
|
||||
$offset = ($page - 1) * config('nntmux.items_per_page');
|
||||
$rslt = $releases->getBrowseRange($page, [-1], $offset, config('nntmux.items_per_page'), '', -1, $this->userdata->categoryexclusions, $group);
|
||||
$rslt = $this->releaseBrowseService->getBrowseRange($page, [-1], $offset, config('nntmux.items_per_page'), '', -1, $this->userdata->categoryexclusions, $group);
|
||||
$results = $this->paginate($rslt ?? [], $rslt[0]->_totalcount ?? 0, config('nntmux.items_per_page'), $page, $request->url(), $request->query());
|
||||
|
||||
$this->viewData = array_merge($this->viewData, [
|
||||
|
||||
@@ -12,6 +12,7 @@ use App\Models\ReleaseRegex;
|
||||
use App\Models\Settings;
|
||||
use App\Models\UserDownload;
|
||||
use App\Models\Video;
|
||||
use App\Services\Releases\ReleaseSearchService;
|
||||
use Blacklight\AniDB;
|
||||
use Blacklight\Books;
|
||||
use Blacklight\Console;
|
||||
@@ -19,16 +20,22 @@ use Blacklight\Games;
|
||||
use Blacklight\Movie;
|
||||
use Blacklight\Music;
|
||||
use Blacklight\ReleaseExtra;
|
||||
use Blacklight\Releases;
|
||||
use Blacklight\XXX;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class DetailsController extends BasePageController
|
||||
{
|
||||
private ReleaseSearchService $releaseSearchService;
|
||||
|
||||
public function __construct(ReleaseSearchService $releaseSearchService)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->releaseSearchService = $releaseSearchService;
|
||||
}
|
||||
|
||||
public function show(Request $request, string $guid)
|
||||
{
|
||||
if ($guid !== null) {
|
||||
$releases = new Releases;
|
||||
$re = new ReleaseExtra;
|
||||
$data = Release::getByGuid($guid);
|
||||
$releaseRegex = '';
|
||||
@@ -52,7 +59,7 @@ class DetailsController extends BasePageController
|
||||
$reAudio = $re->getAudio($data['id']);
|
||||
$reSubs = $re->getSubs($data['id']);
|
||||
$comments = ReleaseComment::getComments($data['id']);
|
||||
$similars = $releases->searchSimilar($data['id'], $data['searchname'], $this->userdata->categoryexclusions);
|
||||
$similars = $this->releaseSearchService->searchSimilar($data['id'], $data['searchname'], $this->userdata->categoryexclusions);
|
||||
$failed = DnzbFailure::getFailedCount($data['id']);
|
||||
$downloadedBy = UserDownload::query()->with('user')->where('releases_id', $data['id'])->get(['users_id']);
|
||||
|
||||
@@ -121,7 +128,7 @@ class DetailsController extends BasePageController
|
||||
$AniDBAPIArray = '';
|
||||
if ($data['anidbid'] > 0) {
|
||||
$AniDBAPIArray = (new AniDB)->getAnimeInfo($data['anidbid']);
|
||||
|
||||
|
||||
// If we have anilist_id but missing details, fetch from AniList
|
||||
if ($AniDBAPIArray && !empty($AniDBAPIArray->anilist_id)) {
|
||||
$anilistId = is_object($AniDBAPIArray) ? $AniDBAPIArray->anilist_id : ($AniDBAPIArray['anilist_id'] ?? null);
|
||||
|
||||
@@ -5,12 +5,20 @@ namespace App\Http\Controllers;
|
||||
use App\Models\Category;
|
||||
use App\Models\Settings;
|
||||
use App\Models\UserMovie;
|
||||
use App\Services\Releases\ReleaseBrowseService;
|
||||
use Blacklight\Movie;
|
||||
use Blacklight\Releases;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class MyMoviesController extends BasePageController
|
||||
{
|
||||
private ReleaseBrowseService $releaseBrowseService;
|
||||
|
||||
public function __construct(ReleaseBrowseService $releaseBrowseService)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->releaseBrowseService = $releaseBrowseService;
|
||||
}
|
||||
|
||||
public function show(Request $request)
|
||||
{
|
||||
$mv = new Movie;
|
||||
@@ -141,7 +149,7 @@ class MyMoviesController extends BasePageController
|
||||
}
|
||||
}
|
||||
|
||||
$ordering = (new Releases)->getBrowseOrdering();
|
||||
$ordering = $this->releaseBrowseService->getBrowseOrdering();
|
||||
|
||||
$page = $request->has('page') && is_numeric($request->input('page')) ? $request->input('page') : 1;
|
||||
|
||||
|
||||
@@ -6,11 +6,19 @@ use App\Models\Category;
|
||||
use App\Models\Settings;
|
||||
use App\Models\UserSerie;
|
||||
use App\Models\Video;
|
||||
use Blacklight\Releases;
|
||||
use App\Services\Releases\ReleaseBrowseService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class MyShowsController extends BasePageController
|
||||
{
|
||||
private ReleaseBrowseService $releaseBrowseService;
|
||||
|
||||
public function __construct(ReleaseBrowseService $releaseBrowseService)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->releaseBrowseService = $releaseBrowseService;
|
||||
}
|
||||
|
||||
public function show(Request $request)
|
||||
{
|
||||
$action = $request->input('action') ?? '';
|
||||
@@ -168,15 +176,13 @@ class MyShowsController extends BasePageController
|
||||
|
||||
$shows = UserSerie::getShows($this->userdata->id);
|
||||
|
||||
$releases = new Releases;
|
||||
|
||||
$page = $request->has('page') && is_numeric($request->input('page')) ? $request->input('page') : 1;
|
||||
$offset = ($page - 1) * config('nntmux.items_per_page');
|
||||
$ordering = $releases->getBrowseOrdering();
|
||||
$ordering = $this->releaseBrowseService->getBrowseOrdering();
|
||||
$orderby = $request->has('ob') && \in_array($request->input('ob'), $ordering, false) ? $request->input('ob') : '';
|
||||
$browseCount = $shows ? $shows->count() : 0;
|
||||
|
||||
$rslt = $releases->getShowsRange($shows ?? [], $offset, config('nntmux.items_per_page'), $orderby, -1, $this->userdata->categoryexclusions);
|
||||
$rslt = $this->releaseBrowseService->getShowsRange($shows ?? [], $offset, config('nntmux.items_per_page'), $orderby, -1, $this->userdata->categoryexclusions);
|
||||
$results = $this->paginate($rslt ?? [], $browseCount, config('nntmux.items_per_page'), $page, $request->url(), $request->query());
|
||||
|
||||
$this->viewData['covgroup'] = '';
|
||||
|
||||
@@ -4,18 +4,26 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Models\UsenetGroup;
|
||||
use App\Services\Releases\ReleaseBrowseService;
|
||||
use App\Services\Releases\ReleaseSearchService;
|
||||
use App\Services\Search\Contracts\SearchServiceInterface;
|
||||
use Blacklight\Releases;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class SearchController extends BasePageController
|
||||
{
|
||||
private SearchServiceInterface $searchService;
|
||||
private ReleaseSearchService $releaseSearchService;
|
||||
private ReleaseBrowseService $releaseBrowseService;
|
||||
|
||||
public function __construct(SearchServiceInterface $searchService)
|
||||
{
|
||||
public function __construct(
|
||||
SearchServiceInterface $searchService,
|
||||
ReleaseSearchService $releaseSearchService,
|
||||
ReleaseBrowseService $releaseBrowseService
|
||||
) {
|
||||
parent::__construct();
|
||||
$this->searchService = $searchService;
|
||||
$this->releaseSearchService = $releaseSearchService;
|
||||
$this->releaseBrowseService = $releaseBrowseService;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -23,7 +31,6 @@ class SearchController extends BasePageController
|
||||
*/
|
||||
public function search(Request $request)
|
||||
{
|
||||
$releases = new Releases;
|
||||
|
||||
$results = [];
|
||||
|
||||
@@ -32,7 +39,7 @@ class SearchController extends BasePageController
|
||||
$searchType = 'advanced';
|
||||
}
|
||||
|
||||
$ordering = $releases->getBrowseOrdering();
|
||||
$ordering = $this->releaseBrowseService->getBrowseOrdering();
|
||||
$orderBy = ($request->has('ob') && \in_array($request->input('ob'), $ordering, false) ? $request->input('ob') : '');
|
||||
$page = $request->has('page') && is_numeric($request->input('page')) ? $request->input('page') : 1;
|
||||
$offset = ($page - 1) * config('nntmux.items_per_page');
|
||||
@@ -68,11 +75,11 @@ class SearchController extends BasePageController
|
||||
}
|
||||
|
||||
$orderByUrls = [];
|
||||
foreach ($releases->getBrowseOrdering() as $orderType) {
|
||||
foreach ($this->releaseBrowseService->getBrowseOrdering() as $orderType) {
|
||||
$orderByUrls['orderby'.$orderType] = url('/search?search='.htmlentities($searchString['searchname'], ENT_QUOTES | ENT_HTML5).'&t='.implode(',', $categoryID).'&ob='.$orderType);
|
||||
}
|
||||
|
||||
$rslt = $releases->search(
|
||||
$rslt = $this->releaseSearchService->search(
|
||||
$searchString,
|
||||
-1,
|
||||
-1,
|
||||
@@ -177,7 +184,7 @@ class SearchController extends BasePageController
|
||||
'filename' => $searchVars['searchadvfilename'] === '' ? -1 : $searchVars['searchadvfilename'],
|
||||
];
|
||||
|
||||
$rslt = $releases->search(
|
||||
$rslt = $this->releaseSearchService->search(
|
||||
$searchArr,
|
||||
$searchVars['searchadvgroups'],
|
||||
$searchVars['searchadvsizefrom'],
|
||||
|
||||
@@ -5,19 +5,26 @@ namespace App\Http\Controllers;
|
||||
use App\Models\TvEpisode;
|
||||
use App\Models\UserSerie;
|
||||
use App\Models\Video;
|
||||
use Blacklight\Releases;
|
||||
use App\Services\Releases\ReleaseSearchService;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class SeriesController extends BasePageController
|
||||
{
|
||||
private ReleaseSearchService $releaseSearchService;
|
||||
|
||||
public function __construct(ReleaseSearchService $releaseSearchService)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->releaseSearchService = $releaseSearchService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function index(Request $request, string $id = '')
|
||||
{
|
||||
$releases = new Releases;
|
||||
|
||||
if ($id && ctype_digit($id)) {
|
||||
$category = -1;
|
||||
@@ -33,7 +40,7 @@ class SeriesController extends BasePageController
|
||||
$page = max($page, 1);
|
||||
$offset = $seriesLimit > 0 ? ($page - 1) * $seriesLimit : 0;
|
||||
|
||||
$rel = $releases->tvSearch(['id' => $id], '', '', '', $offset, $seriesLimit, '', $catarray, -1);
|
||||
$rel = $this->releaseSearchService->tvSearch(['id' => $id], '', '', '', $offset, $seriesLimit, '', $catarray, -1);
|
||||
|
||||
$show = Video::getByVideoID($id);
|
||||
|
||||
|
||||
@@ -400,11 +400,11 @@ class UsenetGroup extends Model
|
||||
|
||||
$res->get();
|
||||
|
||||
$releases = new Releases;
|
||||
$releaseManagement = app(\App\Services\Releases\ReleaseManagementService::class);
|
||||
$nzb = new NZB;
|
||||
$releaseImage = new ReleaseImage;
|
||||
foreach ($res as $row) {
|
||||
$releases->deleteSingle(
|
||||
$releaseManagement->deleteSingle(
|
||||
[
|
||||
'g' => $row['guid'],
|
||||
'i' => $row['id'],
|
||||
|
||||
@@ -17,7 +17,6 @@ use App\Services\AdultProcessing\Pipes\IafdPipe;
|
||||
use App\Services\AdultProcessing\Pipes\PoppornPipe;
|
||||
use Blacklight\ColorCLI;
|
||||
use Blacklight\ReleaseImage;
|
||||
use Blacklight\Releases;
|
||||
use Illuminate\Pipeline\Pipeline;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Concurrency;
|
||||
@@ -74,7 +73,7 @@ class AdultProcessingPipeline
|
||||
// Try to get settings from database, but handle failures gracefully (e.g., in child processes)
|
||||
try {
|
||||
$this->movieQty = (int) (Settings::settingValue('maxxxxprocessed') ?? 100);
|
||||
$this->showPasswords = (new Releases())->showPasswords();
|
||||
$this->showPasswords = app(\App\Services\Releases\ReleaseBrowseService::class)->showPasswords();
|
||||
} catch (\Exception $e) {
|
||||
// Fallback values for child processes where DB might not be available
|
||||
$this->movieQty = 100;
|
||||
|
||||
@@ -13,6 +13,7 @@ use App\Models\Release;
|
||||
use App\Models\Settings;
|
||||
use App\Models\UsenetGroup;
|
||||
use App\Services\Categorization\CategorizationService;
|
||||
use App\Services\Releases\ReleaseManagementService;
|
||||
use App\Support\DTOs\ProcessReleasesSettings;
|
||||
use App\Support\DTOs\ReleaseCreationResult;
|
||||
use App\Support\DTOs\ReleaseDeleteStats;
|
||||
@@ -22,7 +23,6 @@ use Blacklight\NNTP;
|
||||
use Blacklight\NZB;
|
||||
use Blacklight\ReleaseCleaning;
|
||||
use Blacklight\ReleaseImage;
|
||||
use Blacklight\Releases;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -53,7 +53,7 @@ final class ReleaseProcessingService
|
||||
private readonly ColorCLI $colorCLI;
|
||||
private readonly NZB $nzb;
|
||||
private readonly ReleaseCleaning $releaseCleaning;
|
||||
private readonly Releases $releases;
|
||||
private readonly ReleaseManagementService $releaseManagement;
|
||||
private readonly ReleaseImage $releaseImage;
|
||||
private readonly ReleaseCreationService $releaseCreationService;
|
||||
private readonly CollectionCleanupService $collectionCleanupService;
|
||||
@@ -63,7 +63,7 @@ final class ReleaseProcessingService
|
||||
?ColorCLI $colorCLI = null,
|
||||
?NZB $nzb = null,
|
||||
?ReleaseCleaning $releaseCleaning = null,
|
||||
?Releases $releases = null,
|
||||
?ReleaseManagementService $releaseManagement = null,
|
||||
?ReleaseImage $releaseImage = null,
|
||||
?ReleaseCreationService $releaseCreationService = null,
|
||||
?CollectionCleanupService $collectionCleanupService = null,
|
||||
@@ -74,7 +74,7 @@ final class ReleaseProcessingService
|
||||
$this->colorCLI = $colorCLI ?? new ColorCLI();
|
||||
$this->nzb = $nzb ?? new NZB();
|
||||
$this->releaseCleaning = $releaseCleaning ?? new ReleaseCleaning();
|
||||
$this->releases = $releases ?? new Releases();
|
||||
$this->releaseManagement = $releaseManagement ?? app(ReleaseManagementService::class);
|
||||
$this->releaseImage = $releaseImage ?? new ReleaseImage();
|
||||
|
||||
$this->releaseCreationService = $releaseCreationService
|
||||
@@ -1217,7 +1217,7 @@ final class ReleaseProcessingService
|
||||
|
||||
private function deleteSingleRelease(object $release): void
|
||||
{
|
||||
$this->releases->deleteSingle(
|
||||
$this->releaseManagement->deleteSingle(
|
||||
['g' => $release->guid, 'i' => $release->id],
|
||||
$this->nzb,
|
||||
$this->releaseImage
|
||||
|
||||
@@ -0,0 +1,411 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Releases;
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Models\Release;
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* Service for browsing and ordering releases on the frontend.
|
||||
*/
|
||||
class ReleaseBrowseService
|
||||
{
|
||||
private const CACHE_VERSION_KEY = 'releases:cache_version';
|
||||
|
||||
// RAR/ZIP Password indicator.
|
||||
public const PASSWD_NONE = 0; // No password.
|
||||
public const PASSWD_RAR = 1; // Definitely passworded.
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for Browse results.
|
||||
*
|
||||
* @return Collection|mixed
|
||||
*/
|
||||
public function getBrowseRange($page, $cat, $start, $num, $orderBy, int $maxAge = -1, array $excludedCats = [], int|string $groupName = -1, int $minSize = 0): mixed
|
||||
{
|
||||
$cacheVersion = $this->getCacheVersion();
|
||||
$page = max(1, $page);
|
||||
$start = max(0, $start);
|
||||
|
||||
$orderBy = $this->getBrowseOrder($orderBy);
|
||||
|
||||
$qry = sprintf(
|
||||
"SELECT r.id, r.searchname, r.groups_id, r.guid, r.postdate, r.categories_id, r.size, r.totalpart, r.fromname, r.passwordstatus, r.grabs, r.comments, r.adddate, r.videos_id, r.tv_episodes_id, r.haspreview, r.jpgstatus, r.nfostatus, cp.title AS parent_category, c.title AS sub_category, r.group_name,
|
||||
CONCAT(cp.title, ' > ', c.title) AS category_name,
|
||||
CONCAT(cp.id, ',', c.id) AS category_ids,
|
||||
df.failed AS failed,
|
||||
rn.releases_id AS nfoid,
|
||||
re.releases_id AS reid,
|
||||
v.tvdb, v.trakt, v.tvrage, v.tvmaze, v.imdb, v.tmdb,
|
||||
m.imdbid, m.tmdbid, m.traktid,
|
||||
tve.title, tve.firstaired
|
||||
FROM
|
||||
(
|
||||
SELECT r.id, r.searchname, r.guid, r.postdate, r.groups_id, r.categories_id, r.size, r.totalpart, r.fromname, r.passwordstatus, r.grabs, r.comments, r.adddate, r.videos_id, r.tv_episodes_id, r.haspreview, r.jpgstatus, r.nfostatus, g.name AS group_name, r.movieinfo_id
|
||||
FROM releases r
|
||||
LEFT JOIN usenet_groups g ON g.id = r.groups_id
|
||||
WHERE r.passwordstatus %s
|
||||
%s %s %s %s %s
|
||||
ORDER BY %s %s %s
|
||||
) r
|
||||
LEFT JOIN categories c ON c.id = r.categories_id
|
||||
LEFT JOIN root_categories cp ON cp.id = c.root_categories_id
|
||||
LEFT OUTER JOIN videos v ON r.videos_id = v.id
|
||||
LEFT OUTER JOIN tv_episodes tve ON r.tv_episodes_id = tve.id
|
||||
LEFT OUTER JOIN movieinfo m ON m.id = r.movieinfo_id
|
||||
LEFT OUTER JOIN video_data re ON re.releases_id = r.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
|
||||
GROUP BY r.id
|
||||
ORDER BY %7\$s %8\$s",
|
||||
$this->showPasswords(),
|
||||
Category::getCategorySearch($cat),
|
||||
($maxAge > 0 ? (' AND postdate > NOW() - INTERVAL '.$maxAge.' DAY ') : ''),
|
||||
(\count($excludedCats) ? (' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')') : ''),
|
||||
((int) $groupName !== -1 ? sprintf(' AND g.name = %s ', escapeString($groupName)) : ''),
|
||||
($minSize > 0 ? sprintf('AND r.size >= %d', $minSize) : ''),
|
||||
$orderBy[0],
|
||||
$orderBy[1],
|
||||
($start === 0 ? ' LIMIT '.$num : ' LIMIT '.$num.' OFFSET '.$start)
|
||||
);
|
||||
|
||||
$cacheKey = md5($cacheVersion.$qry.$page);
|
||||
$releases = Cache::get($cacheKey);
|
||||
if ($releases !== null) {
|
||||
return $releases;
|
||||
}
|
||||
$sql = DB::select($qry);
|
||||
if (\count($sql) > 0) {
|
||||
$possibleRows = $this->getBrowseCount($cat, $maxAge, $excludedCats, $groupName);
|
||||
$sql[0]->_totalcount = $sql[0]->_totalrows = $possibleRows;
|
||||
}
|
||||
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_medium'));
|
||||
Cache::put($cacheKey, $sql, $expiresAt);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for pager on browse page.
|
||||
*/
|
||||
public function getBrowseCount(array $cat, int $maxAge = -1, array $excludedCats = [], int|string $groupName = ''): int
|
||||
{
|
||||
return $this->getPagerCount(sprintf(
|
||||
'SELECT COUNT(r.id) AS count
|
||||
FROM releases r
|
||||
%s
|
||||
WHERE r.passwordstatus %s
|
||||
%s
|
||||
%s %s %s ',
|
||||
($groupName !== -1 ? 'LEFT JOIN usenet_groups g ON g.id = r.groups_id' : ''),
|
||||
$this->showPasswords(),
|
||||
($groupName !== -1 ? sprintf(' AND g.name = %s', escapeString($groupName)) : ''),
|
||||
Category::getCategorySearch($cat),
|
||||
($maxAge > 0 ? (' AND r.postdate > NOW() - INTERVAL '.$maxAge.' DAY ') : ''),
|
||||
(\count($excludedCats) ? (' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')') : '')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the passworded releases clause.
|
||||
*/
|
||||
public function showPasswords(): string
|
||||
{
|
||||
$show = (int) Settings::settingValue('showpasswordedrelease');
|
||||
$setting = $show ?? 0;
|
||||
|
||||
return match ($setting) {
|
||||
1 => '<= '.self::PASSWD_RAR,
|
||||
default => '= '.self::PASSWD_NONE,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Use to order releases on site.
|
||||
*/
|
||||
public function getBrowseOrder(array|string $orderBy): array
|
||||
{
|
||||
$orderArr = explode('_', ($orderBy === '' ? 'posted_desc' : $orderBy));
|
||||
$orderField = match ($orderArr[0]) {
|
||||
'cat' => 'categories_id',
|
||||
'name' => 'searchname',
|
||||
'size' => 'size',
|
||||
'files' => 'totalpart',
|
||||
'stats' => 'grabs',
|
||||
default => 'postdate',
|
||||
};
|
||||
|
||||
return [$orderField, isset($orderArr[1]) && preg_match('/^(asc|desc)$/i', $orderArr[1]) ? $orderArr[1] : 'desc'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return ordering types usable on site.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getBrowseOrdering(): array
|
||||
{
|
||||
return [
|
||||
'name_asc',
|
||||
'name_desc',
|
||||
'cat_asc',
|
||||
'cat_desc',
|
||||
'posted_asc',
|
||||
'posted_desc',
|
||||
'size_asc',
|
||||
'size_desc',
|
||||
'files_asc',
|
||||
'files_desc',
|
||||
'stats_asc',
|
||||
'stats_desc',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Cache\|\Illuminate\Database\Eloquent\Collection|mixed
|
||||
*/
|
||||
public function getShowsRange($userShows, $offset, $limit, $orderBy, int $maxAge = -1, array $excludedCats = [])
|
||||
{
|
||||
$orderBy = $this->getBrowseOrder($orderBy);
|
||||
$sql = sprintf(
|
||||
"SELECT r.id, r.searchname, r.guid, r.postdate, r.groups_id, r.categories_id, r.size, r.totalpart, r.fromname, r.passwordstatus, r.grabs, r.comments, r.adddate, r.videos_id, r.tv_episodes_id, r.haspreview, r.jpgstatus, cp.title AS parent_category, c.title AS sub_category,
|
||||
CONCAT(cp.title, '->', c.title) AS category_name
|
||||
FROM releases r
|
||||
LEFT JOIN categories c ON c.id = r.categories_id
|
||||
LEFT JOIN root_categories cp ON cp.id = c.root_categories_id
|
||||
WHERE %s %s
|
||||
AND r.categories_id BETWEEN %d AND %d
|
||||
AND r.passwordstatus %s
|
||||
%s
|
||||
GROUP BY r.id
|
||||
ORDER BY %s %s %s",
|
||||
$this->uSQL($userShows, 'videos_id'),
|
||||
(! empty($excludedCats) ? ' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')' : ''),
|
||||
Category::TV_ROOT,
|
||||
Category::TV_OTHER,
|
||||
$this->showPasswords(),
|
||||
($maxAge > 0 ? sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxAge) : ''),
|
||||
$orderBy[0],
|
||||
$orderBy[1],
|
||||
($offset === false ? '' : (' LIMIT '.$limit.' OFFSET '.$offset))
|
||||
);
|
||||
$expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
|
||||
$result = Cache::get(md5($sql));
|
||||
if ($result !== null) {
|
||||
return $result;
|
||||
}
|
||||
$result = Release::fromQuery($sql);
|
||||
Cache::put(md5($sql), $result, $expiresAt);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getShowsCount($userShows, int $maxAge = -1, array $excludedCats = []): int
|
||||
{
|
||||
return $this->getPagerCount(
|
||||
sprintf(
|
||||
'SELECT r.id
|
||||
FROM releases r
|
||||
WHERE %s %s
|
||||
AND r.categories_id BETWEEN %d AND %d
|
||||
AND r.passwordstatus %s
|
||||
%s',
|
||||
$this->uSQL($userShows, 'videos_id'),
|
||||
(\count($excludedCats) ? ' AND r.categories_id NOT IN ('.implode(',', $excludedCats).')' : ''),
|
||||
Category::TV_ROOT,
|
||||
Category::TV_OTHER,
|
||||
$this->showPasswords(),
|
||||
($maxAge > 0 ? sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxAge) : '')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates part of a query for some functions.
|
||||
*/
|
||||
public function uSQL(Collection|array $userQuery, string $type): string
|
||||
{
|
||||
$sql = '(1=2 ';
|
||||
foreach ($userQuery as $query) {
|
||||
$sql .= sprintf('OR (r.%s = %d', $type, $query->$type);
|
||||
if (! empty($query->categories)) {
|
||||
$catsArr = explode('|', $query->categories);
|
||||
if (\count($catsArr) > 1) {
|
||||
$sql .= sprintf(' AND r.categories_id IN (%s)', implode(',', $catsArr));
|
||||
} else {
|
||||
$sql .= sprintf(' AND r.categories_id = %d', $catsArr[0]);
|
||||
}
|
||||
}
|
||||
$sql .= ') ';
|
||||
}
|
||||
$sql .= ') ';
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public static function bumpCacheVersion(): void
|
||||
{
|
||||
$current = Cache::get(self::CACHE_VERSION_KEY, 1);
|
||||
Cache::forever(self::CACHE_VERSION_KEY, $current + 1);
|
||||
}
|
||||
|
||||
private function getCacheVersion(): int
|
||||
{
|
||||
return Cache::get(self::CACHE_VERSION_KEY, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of releases for pager.
|
||||
*
|
||||
* @param string $query The query to get the count from.
|
||||
*/
|
||||
private function getPagerCount(string $query): int
|
||||
{
|
||||
$maxResults = (int) config('nntmux.max_pager_results');
|
||||
$cacheExpiry = config('nntmux.cache_expiry_short');
|
||||
|
||||
// Generate cache key from original query
|
||||
$cacheKey = 'pager_count_'.md5($query);
|
||||
|
||||
// Check cache first
|
||||
$count = Cache::get($cacheKey);
|
||||
if ($count !== null) {
|
||||
return (int) $count;
|
||||
}
|
||||
|
||||
// Check if this is already a COUNT query
|
||||
if (preg_match('/SELECT\s+COUNT\s*\(/is', $query)) {
|
||||
// It's already a COUNT query, just execute it
|
||||
try {
|
||||
$result = DB::select($query);
|
||||
if (isset($result[0])) {
|
||||
// Handle different possible column names
|
||||
$count = $result[0]->count ?? $result[0]->total ?? 0;
|
||||
// Check for COUNT(*) result without alias
|
||||
if ($count === 0) {
|
||||
foreach ($result[0] as $value) {
|
||||
$count = (int) $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$count = 0;
|
||||
}
|
||||
|
||||
// Cap the count at max results if applicable
|
||||
if ($maxResults > 0 && $count > $maxResults) {
|
||||
$count = $maxResults;
|
||||
}
|
||||
|
||||
// Cache the result
|
||||
Cache::put($cacheKey, $count, now()->addMinutes($cacheExpiry));
|
||||
|
||||
return $count;
|
||||
} catch (\Exception $e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// For regular SELECT queries, optimize for counting
|
||||
$countQuery = $query;
|
||||
|
||||
// Remove ORDER BY clause (not needed for COUNT)
|
||||
$countQuery = preg_replace('/ORDER\s+BY\s+[^)]+$/is', '', $countQuery);
|
||||
|
||||
// Remove GROUP BY if it's only grouping by r.id
|
||||
$countQuery = preg_replace('/GROUP\s+BY\s+r\.id\s*$/is', '', $countQuery);
|
||||
|
||||
// Check if query has DISTINCT in SELECT
|
||||
$hasDistinct = preg_match('/SELECT\s+DISTINCT/is', $countQuery);
|
||||
|
||||
// Replace SELECT clause with COUNT
|
||||
if ($hasDistinct || preg_match('/GROUP\s+BY/is', $countQuery)) {
|
||||
// For queries with DISTINCT or GROUP BY, count distinct r.id
|
||||
$countQuery = preg_replace(
|
||||
'/SELECT\s+.+?\s+FROM/is',
|
||||
'SELECT COUNT(DISTINCT r.id) as count FROM',
|
||||
$countQuery
|
||||
);
|
||||
} else {
|
||||
// For simple queries, use COUNT(*)
|
||||
$countQuery = preg_replace(
|
||||
'/SELECT\s+.+?\s+FROM/is',
|
||||
'SELECT COUNT(*) as count FROM',
|
||||
$countQuery
|
||||
);
|
||||
}
|
||||
|
||||
// Remove LIMIT/OFFSET from the count query
|
||||
$countQuery = preg_replace('/LIMIT\s+\d+(\s+OFFSET\s+\d+)?$/is', '', $countQuery);
|
||||
|
||||
try {
|
||||
// If max results is set and query might return too many results
|
||||
if ($maxResults > 0) {
|
||||
// First check if count would exceed max
|
||||
$testQuery = sprintf('SELECT 1 FROM (%s) as test LIMIT %d',
|
||||
preg_replace('/SELECT\s+COUNT.+?\s+FROM/is', 'SELECT 1 FROM', $countQuery),
|
||||
$maxResults + 1
|
||||
);
|
||||
|
||||
$testResult = DB::select($testQuery);
|
||||
if (count($testResult) > $maxResults) {
|
||||
Cache::put($cacheKey, $maxResults, now()->addMinutes($cacheExpiry));
|
||||
|
||||
return $maxResults;
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the count query
|
||||
$result = DB::select($countQuery);
|
||||
$count = isset($result[0]) ? (int) $result[0]->count : 0;
|
||||
|
||||
// Cache the result
|
||||
Cache::put($cacheKey, $count, now()->addMinutes($cacheExpiry));
|
||||
|
||||
return $count;
|
||||
} catch (\Exception $e) {
|
||||
// If optimization fails, try a simpler approach
|
||||
try {
|
||||
// Extract the core table and WHERE conditions
|
||||
if (preg_match('/FROM\s+releases\s+r\s+(.+?)(?:ORDER\s+BY|LIMIT|$)/is', $query, $matches)) {
|
||||
$conditions = $matches[1];
|
||||
// Remove JOINs but keep WHERE
|
||||
$conditions = preg_replace('/(?:LEFT\s+|INNER\s+)?(?:OUTER\s+)?JOIN\s+.+?(?=WHERE|LEFT|INNER|JOIN|$)/is', '', $conditions);
|
||||
|
||||
$fallbackQuery = sprintf('SELECT COUNT(*) as count FROM releases r %s', trim($conditions));
|
||||
|
||||
if ($maxResults > 0) {
|
||||
$fallbackQuery = sprintf('SELECT COUNT(*) as count FROM (SELECT 1 FROM releases r %s LIMIT %d) as limited',
|
||||
trim($conditions),
|
||||
$maxResults
|
||||
);
|
||||
}
|
||||
|
||||
$result = DB::select($fallbackQuery);
|
||||
$count = isset($result[0]) ? (int) $result[0]->count : 0;
|
||||
|
||||
Cache::put($cacheKey, $count, now()->addMinutes($cacheExpiry));
|
||||
|
||||
return $count;
|
||||
}
|
||||
} catch (\Exception $fallbackException) {
|
||||
// Log the error for debugging
|
||||
\Illuminate\Support\Facades\Log::error('getPagerCount failed', [
|
||||
'query' => $query,
|
||||
'error' => $fallbackException->getMessage(),
|
||||
]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Releases;
|
||||
|
||||
use App\Models\Release;
|
||||
use App\Services\Search\ManticoreSearchService;
|
||||
use Blacklight\NZB;
|
||||
use Blacklight\ReleaseImage;
|
||||
use Elasticsearch;
|
||||
use Elasticsearch\Common\Exceptions\Missing404Exception;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
/**
|
||||
* Service for managing releases (delete, update, export).
|
||||
*/
|
||||
class ReleaseManagementService
|
||||
{
|
||||
private ManticoreSearchService $manticoreSearch;
|
||||
|
||||
public function __construct(
|
||||
ManticoreSearchService $manticoreSearch
|
||||
) {
|
||||
$this->manticoreSearch = $manticoreSearch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function deleteMultiple(int|array|string $list): void
|
||||
{
|
||||
$list = (array) $list;
|
||||
|
||||
$nzb = new NZB;
|
||||
$releaseImage = new ReleaseImage;
|
||||
|
||||
foreach ($list as $identifier) {
|
||||
$this->deleteSingle(['g' => $identifier, 'i' => false], $nzb, $releaseImage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a single release by GUID, and all the corresponding files.
|
||||
*
|
||||
* @param array $identifiers ['g' => Release GUID(mandatory), 'id => ReleaseID(optional, pass
|
||||
* false)]
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function deleteSingle(array $identifiers, NZB $nzb, ReleaseImage $releaseImage): void
|
||||
{
|
||||
// Delete NZB from disk.
|
||||
$nzbPath = $nzb->NZBPath($identifiers['g']);
|
||||
if (! empty($nzbPath)) {
|
||||
File::delete($nzbPath);
|
||||
}
|
||||
|
||||
// Delete images.
|
||||
$releaseImage->delete($identifiers['g']);
|
||||
|
||||
if (config('nntmux.elasticsearch_enabled') === true) {
|
||||
if ($identifiers['i'] === false) {
|
||||
$identifiers['i'] = Release::query()->where('guid', $identifiers['g'])->first(['id']);
|
||||
if ($identifiers['i'] !== null) {
|
||||
$identifiers['i'] = $identifiers['i']['id'];
|
||||
}
|
||||
}
|
||||
if ($identifiers['i'] !== null) {
|
||||
$params = [
|
||||
'index' => 'releases',
|
||||
'id' => $identifiers['i'],
|
||||
];
|
||||
|
||||
try {
|
||||
Elasticsearch::delete($params);
|
||||
} catch (Missing404Exception $e) {
|
||||
// we do nothing here just catch the error, we don't care if release is missing from ES, we are deleting it anyway
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Delete from Manticore
|
||||
if ($identifiers['i'] === false) {
|
||||
$release = Release::query()->where('guid', $identifiers['g'])->first(['id']);
|
||||
if ($release !== null) {
|
||||
$identifiers['i'] = $release->id;
|
||||
}
|
||||
}
|
||||
if (!empty($identifiers['i'])) {
|
||||
$this->manticoreSearch->deleteRelease((int) $identifiers['i']);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete from DB.
|
||||
Release::whereGuid($identifiers['g'])->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|int
|
||||
*/
|
||||
public function updateMulti($guids, $category, $grabs, $videoId, $episodeId, $anidbId, $imdbId)
|
||||
{
|
||||
if (! \is_array($guids) || \count($guids) < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$update = [
|
||||
'categories_id' => $category === -1 ? 'categories_id' : $category,
|
||||
'grabs' => $grabs,
|
||||
'videos_id' => $videoId,
|
||||
'tv_episodes_id' => $episodeId,
|
||||
'anidbid' => $anidbId,
|
||||
'imdbid' => $imdbId,
|
||||
];
|
||||
|
||||
return Release::query()->whereIn('guid', $guids)->update($update);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Release[]|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Query\Builder[]|\Illuminate\Support\Collection
|
||||
*/
|
||||
public function getForExport(string $postFrom = '', string $postTo = '', string $groupID = '')
|
||||
{
|
||||
$query = Release::query()
|
||||
->select(['r.searchname', 'r.guid', 'g.name as gname', DB::raw("CONCAT(cp.title,'_',c.title) AS catName")])
|
||||
->from('releases as r')
|
||||
->leftJoin('categories as c', 'c.id', '=', 'r.categories_id')
|
||||
->leftJoin('root_categories as cp', 'cp.id', '=', 'c.root_categories_id')
|
||||
->leftJoin('usenet_groups as g', 'g.id', '=', 'r.groups_id');
|
||||
|
||||
if ($groupID !== '') {
|
||||
$query->where('r.groups_id', $groupID);
|
||||
}
|
||||
|
||||
if ($postFrom !== '') {
|
||||
$dateParts = explode('/', $postFrom);
|
||||
if (\count($dateParts) === 3) {
|
||||
$query->where('r.postdate', '>', $dateParts[2].'-'.$dateParts[1].'-'.$dateParts[0].'00:00:00');
|
||||
}
|
||||
}
|
||||
|
||||
if ($postTo !== '') {
|
||||
$dateParts = explode('/', $postTo);
|
||||
if (\count($dateParts) === 3) {
|
||||
$query->where('r.postdate', '<', $dateParts[2].'-'.$dateParts[1].'-'.$dateParts[0].'23:59:59');
|
||||
}
|
||||
}
|
||||
|
||||
return $query->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function getEarliestUsenetPostDate(): mixed
|
||||
{
|
||||
$row = Release::query()->selectRaw("DATE_FORMAT(min(postdate), '%d/%m/%Y') AS postdate")->first();
|
||||
|
||||
return $row === null ? '01/01/2014' : $row['postdate'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function getLatestUsenetPostDate(): mixed
|
||||
{
|
||||
$row = Release::query()->selectRaw("DATE_FORMAT(max(postdate), '%d/%m/%Y') AS postdate")->first();
|
||||
|
||||
return $row === null ? '01/01/2014' : $row['postdate'];
|
||||
}
|
||||
|
||||
public function getReleasedGroupsForSelect(bool $blnIncludeAll = true): array
|
||||
{
|
||||
$groups = Release::query()
|
||||
->selectRaw('DISTINCT g.id, g.name')
|
||||
->leftJoin('usenet_groups as g', 'g.id', '=', 'releases.groups_id')
|
||||
->get();
|
||||
$temp_array = [];
|
||||
|
||||
if ($blnIncludeAll) {
|
||||
$temp_array[-1] = '--All Groups--';
|
||||
}
|
||||
|
||||
foreach ($groups as $group) {
|
||||
$temp_array[$group['id']] = $group['name'];
|
||||
}
|
||||
|
||||
return $temp_array;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -402,6 +402,15 @@ class ManticoreSearchService implements SearchServiceInterface
|
||||
return [];
|
||||
}
|
||||
|
||||
if (config('app.debug')) {
|
||||
Log::debug('ManticoreSearch::searchIndexes called', [
|
||||
'rt_index' => $rt_index,
|
||||
'searchString' => $searchString,
|
||||
'column' => $column,
|
||||
'searchArray' => $searchArray,
|
||||
]);
|
||||
}
|
||||
|
||||
// Create cache key for search results
|
||||
$cacheKey = md5(serialize([
|
||||
'index' => $rt_index,
|
||||
@@ -412,6 +421,12 @@ class ManticoreSearchService implements SearchServiceInterface
|
||||
|
||||
$cached = Cache::get($cacheKey);
|
||||
if ($cached !== null) {
|
||||
if (config('app.debug')) {
|
||||
Log::debug('ManticoreSearch::searchIndexes returning cached result', [
|
||||
'cacheKey' => $cacheKey,
|
||||
'cached_ids_count' => count($cached['id'] ?? []),
|
||||
]);
|
||||
}
|
||||
return $cached;
|
||||
}
|
||||
|
||||
@@ -430,11 +445,17 @@ class ManticoreSearchService implements SearchServiceInterface
|
||||
if (! empty($terms)) {
|
||||
$searchExpr = implode(' ', $terms);
|
||||
} else {
|
||||
if (config('app.debug')) {
|
||||
Log::debug('ManticoreSearch::searchIndexes no terms after escaping searchArray');
|
||||
}
|
||||
return [];
|
||||
}
|
||||
} elseif (! empty($searchString)) {
|
||||
$escapedSearch = self::escapeString($searchString);
|
||||
if (empty($escapedSearch)) {
|
||||
if (config('app.debug')) {
|
||||
Log::debug('ManticoreSearch::searchIndexes escapedSearch is empty');
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user