connection = $connection; $this->eggVariableRepository = $eggVariableRepository; $this->repository = $repository; $this->nestRepository = $nestRepository; } /** * Take an uploaded JSON file and parse it into a new egg. * * @deprecated use `handleFile` or `handleContent` instead * * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException * @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException * @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException * @throws \Pterodactyl\Exceptions\Service\Egg\BadYamlFormatException * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\DisplayException */ public function handle(UploadedFile $file, int $nestId): Egg { return $this->handleFile($nestId, $file); } /** * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException * @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException * @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException * @throws \Pterodactyl\Exceptions\Service\Egg\BadYamlFormatException * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\DisplayException */ public function handleFile(int $nestId, UploadedFile $file): Egg { if ($file->getError() !== UPLOAD_ERR_OK || !$file->isFile()) { throw new InvalidFileUploadException(sprintf('The selected file ["%s"] was not in a valid format to import. (is_file: %s is_valid: %s err_code: %s err: %s)', $file->getFilename(), $file->isFile() ? 'true' : 'false', $file->isValid() ? 'true' : 'false', $file->getError(), $file->getErrorMessage())); } return $this->handleContent($nestId, $file->openFile()->fread($file->getSize()), 'application/json'); } /** * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException * @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException * @throws \Pterodactyl\Exceptions\Service\Egg\BadYamlFormatException * @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException * @throws \Pterodactyl\Exceptions\DisplayException * @throws \Pterodactyl\Exceptions\Model\DataValidationException */ public function handleContent(int $nestId, string $content, string $contentType): Egg { switch (true) { case strpos($contentType, 'application/json') === 0: $parsed = json_decode($content, true); if (json_last_error() !== 0) { throw new BadJsonFormatException(trans('exceptions.nest.importer.json_error', ['error' => json_last_error_msg()])); } return $this->handleArray($nestId, $parsed); case strpos($contentType, 'application/yaml') === 0: try { $parsed = Yaml::parse($content); return $this->handleArray($nestId, $parsed); } catch (ParseException $exception) { throw new BadYamlFormatException('There was an error while attempting to parse the YAML: ' . $exception->getMessage() . '.'); } default: throw new DisplayException('unknown content type'); } } /** * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException * @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException */ private function handleArray(int $nestId, array $parsed): Egg { if (Arr::get($parsed, 'meta.version') !== 'PTDL_v1') { throw new InvalidFileUploadException(trans('exceptions.nest.importer.invalid_json_provided')); } $nest = $this->nestRepository->getWithEggs($nestId); $this->connection->beginTransaction(); /** @var \Pterodactyl\Models\Egg $egg */ $egg = $this->repository->create([ 'uuid' => Uuid::uuid4()->toString(), 'nest_id' => $nest->id, 'author' => Arr::get($parsed, 'author'), 'name' => Arr::get($parsed, 'name'), 'description' => Arr::get($parsed, 'description'), 'features' => Arr::get($parsed, 'features'), // Maintain backwards compatability for eggs that are still using the old single image // string format. New eggs can provide an array of Docker images that can be used. 'docker_images' => Arr::get($parsed, 'images') ?? [Arr::get($parsed, 'image')], 'file_denylist' => Collection::make(Arr::get($parsed, 'file_denylist'))->filter(function ($value) { return !empty($value); }), 'update_url' => Arr::get($parsed, 'meta.update_url'), 'config_files' => Arr::get($parsed, 'config.files'), 'config_startup' => Arr::get($parsed, 'config.startup'), 'config_stop' => Arr::get($parsed, 'config.stop'), 'startup' => Arr::get($parsed, 'startup'), 'script_install' => Arr::get($parsed, 'scripts.installation.script'), 'script_entry' => Arr::get($parsed, 'scripts.installation.entrypoint'), 'script_container' => Arr::get($parsed, 'scripts.installation.container'), 'copy_script_from' => null, ], true, true); Collection::make($parsed['variables'] ?? [])->each(function (array $variable) use ($egg) { $this->eggVariableRepository->create(array_merge($variable, [ 'egg_id' => $egg->id, ])); }); $this->connection->commit(); return $egg; } }