From 1d451c24ac5b9a98daa5ba1a3c598d6630edf897 Mon Sep 17 00:00:00 2001 From: "Xql.dev" Date: Mon, 13 Oct 2025 11:29:31 +0200 Subject: [PATCH] Update BulkPowerActionCommand.php Upgrade bulkPowerActionCommand.Php Uprage Rapidity start Command --- .../Server/BulkPowerActionCommand.php | 171 +++++++++++++----- 1 file changed, 127 insertions(+), 44 deletions(-) diff --git a/app/Console/Commands/Server/BulkPowerActionCommand.php b/app/Console/Commands/Server/BulkPowerActionCommand.php index 5df31bec9..fda68bf69 100644 --- a/app/Console/Commands/Server/BulkPowerActionCommand.php +++ b/app/Console/Commands/Server/BulkPowerActionCommand.php @@ -2,28 +2,32 @@ namespace Pterodactyl\Console\Commands\Server; -use Pterodactyl\Models\Server; use Illuminate\Console\Command; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Facades\Log; use Illuminate\Validation\ValidationException; use Illuminate\Validation\Factory as ValidatorFactory; -use Pterodactyl\Repositories\Wings\DaemonPowerRepository; use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException; +use Pterodactyl\Models\Server; +use Pterodactyl\Repositories\Wings\DaemonPowerRepository; class BulkPowerActionCommand extends Command { protected $signature = 'p:server:bulk-power {action : The action to perform (start, stop, restart, kill)} - {--servers= : A comma separated list of servers.} - {--nodes= : A comma separated list of nodes.}'; + {--servers= : A comma-separated list of server IDs.} + {--nodes= : A comma-separated list of node IDs.}'; - protected $description = 'Perform bulk power management on large groupings of servers or nodes at once.'; + protected $description = 'Performs bulk power management on servers or nodes.'; /** - * BulkPowerActionCommand constructor. + * Frok by xql.dev Love Pyrodactyl <3 + * Good Docs For New Developper xp */ - public function __construct(private DaemonPowerRepository $powerRepository, private ValidatorFactory $validator) - { + public function __construct( + private DaemonPowerRepository $powerRepository, + private ValidatorFactory $validator + ) { parent::__construct(); } @@ -32,18 +36,51 @@ public function __construct(private DaemonPowerRepository $powerRepository, priv * * @throws ValidationException */ - public function handle() + public function handle(): void { $action = $this->argument('action'); - $nodes = empty($this->option('nodes')) ? [] : explode(',', $this->option('nodes')); - $servers = empty($this->option('servers')) ? [] : explode(',', $this->option('servers')); + $nodes = $this->parseOptionList($this->option('nodes')); + $servers = $this->parseOptionList($this->option('servers')); + + $this->validateInput($action, $nodes, $servers); + + $query = $this->getQueryBuilder($servers, $nodes); + $count = $query->count(); + + if ($count === 0) { + $this->output->warning('No servers found matching the specified criteria.'); + return; + } + + if (!$this->confirmAction($action, $count)) { + $this->output->info('Bulk power action cancelled.'); + return; + } + $this->processServers($query, $action); + } + + /** + * Parse comma-separated option string into an array. + */ + private function parseOptionList(?string $option): array + { + return array_filter(array_map('trim', explode(',', $option ?? ''))); + } + + /** + * Validate input parameters. + * + * @throws ValidationException + */ + private function validateInput(string $action, array $nodes, array $servers): void + { $validator = $this->validator->make([ 'action' => $action, 'nodes' => $nodes, 'servers' => $servers, ], [ - 'action' => 'string|in:start,stop,kill,restart', + 'action' => 'required|string|in:start,stop,kill,restart', 'nodes' => 'array', 'nodes.*' => 'integer|min:1', 'servers' => 'array', @@ -54,53 +91,99 @@ public function handle() foreach ($validator->getMessageBag()->all() as $message) { $this->output->error($message); } - throw new ValidationException($validator); } - $count = $this->getQueryBuilder($servers, $nodes)->count(); - if (!$this->confirm(trans('command/messages.server.power.confirm', ['action' => $action, 'count' => $count])) && $this->input->isInteractive()) { - return; + if (empty($nodes) && empty($servers)) { + throw new ValidationException($this->validator->make( + [], + ['servers' => 'required_without:nodes'] + )); } + } - $bar = $this->output->createProgressBar($count); - $powerRepository = $this->powerRepository; - $this->getQueryBuilder($servers, $nodes)->each(function (Server $server) use ($action, $powerRepository, &$bar) { - $bar->clear(); - - try { - $powerRepository->setServer($server)->send($action); - } catch (DaemonConnectionException $exception) { - $this->output->error(trans('command/messages.server.power.action_failed', [ - 'name' => $server->name, - 'id' => $server->id, - 'node' => $server->node->name, - 'message' => $exception->getMessage(), - ])); - } + /** + * Confirm the bulk action with the user. + */ + private function confirmAction(string $action, int $count): bool + { + if (!$this->input->isInteractive()) { + return true; + } + + return $this->confirm(trans('command/messages.server.power.confirm', [ + 'action' => $action, + 'count' => $count, + ])); + } - $bar->advance(); - $bar->display(); + /** + * Process servers with the specified power action. + */ + private function processServers(Builder $query, string $action): void + { + $bar = $this->output->createProgressBar($query->count()); + $bar->start(); + + $query->chunk(100, function ($servers) use ($action, $bar) { + foreach ($servers as $server) { + $this->processServer($server, $action); + $bar->advance(); + } }); + $bar->finish(); $this->line(''); + $this->output->success(sprintf('Bulk power action "%s" completed.', $action)); + } + + /** + * Process a single server's power action. + */ + private function processServer(Server $server, string $action): void + { + try { + $this->powerRepository->setServer($server)->send($action); + Log::info('Bulk power action successful', [ + 'action' => $action, + 'server_id' => $server->id, + 'server_name' => $server->name, + 'node_id' => $server->node_id, + ]); + } catch (DaemonConnectionException $exception) { + $this->output->error(trans('command/messages.server.power.action_failed', [ + 'name' => $server->name, + 'id' => $server->id, + 'node' => $server->node->name, + 'message' => $exception->getMessage(), + ])); + Log::error('Bulk power action failed', [ + 'action' => $action, + 'server_id' => $server->id, + 'server_name' => $server->name, + 'node_id' => $server->node_id, + 'error' => $exception->getMessage(), + ]); + } } /** - * Returns the query builder instance that will return the servers that should be affected. + * Returns the query builder instance for affected servers. */ - protected function getQueryBuilder(array $servers, array $nodes): Builder + private function getQueryBuilder(array $servers, array $nodes): Builder { - $instance = Server::query()->whereNull('status'); - - if (!empty($nodes) && !empty($servers)) { - $instance->whereIn('id', $servers)->orWhereIn('node_id', $nodes); - } elseif (empty($nodes) && !empty($servers)) { - $instance->whereIn('id', $servers); - } elseif (!empty($nodes) && empty($servers)) { - $instance->whereIn('node_id', $nodes); + $query = Server::query() + ->whereNull('status') + ->with('node'); + + if (!empty($servers)) { + $query->whereIn('id', $servers); + } + + if (!empty($nodes)) { + $query->orWhereIn('node_id', $nodes); } - return $instance->with('node'); + return $query; } }