diff --git a/.gitignore b/.gitignore index 13050edc..4e8cfc33 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ /.env.*.local /config/secrets/prod/prod.decrypt.private.php /public/bundles/ -/public/alternatives/ /var/ /.composer /vendor/ diff --git a/calibre/Dockerfile b/calibre/Dockerfile deleted file mode 100644 index dfbfb74f..00000000 --- a/calibre/Dockerfile +++ /dev/null @@ -1,50 +0,0 @@ -#FROM alpine:edge -#RUN apk add --no-cache \ -# build-base \ -# python3 \ -# python3-dev -#RUN apk add calibre calibre-pyc --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing/ - - -FROM ubuntu:oracular -RUN apt-get update && apt-get install -y \ - build-essential \ - libegl1 \ - libopengl0 \ - libxcb-cursor0 \ - python-is-python3 \ - python3 \ - python3-dev \ - python3-venv \ - wget \ - && rm -rf /var/lib/apt/lists/* -RUN wget -nv -O- https://download.calibre-ebook.com/linux-installer.py | python -c "import sys; main=lambda:sys.stderr.write('Download failed\n'); exec(sys.stdin.read()); main()" - -RUN apt-get update && apt-get install -y \ - libxkbcommon-x11-0 \ - xserver-xorg-core \ - libnss3-dev \ - && rm -rf /var/lib/apt/lists/* -# Set up a virtual environment -ENV VIRTUAL_ENV=/opt/venv -RUN python3 -m venv $VIRTUAL_ENV -ENV PATH="$VIRTUAL_ENV/bin:$PATH" -ENV PATH="/opt/calibre:$PATH" - -# Install python modules -RUN /opt/venv/bin/pip install --upgrade pip && \ - /opt/venv/bin/pip install \ -flask \ -flask_cors -# Copy the server script to the container -COPY --link server.py /usr/local/bin/server.py - -## Install kepubify -ENV KEPUBIFY_VER="4.0.4" -RUN sh -c 'set -vx; if [ "$(uname -m)" = "x86_64" ];then kepubify_arch=64bit;elif [ "$(uname -m)" = "aarch64" ];then kepubify_arch=arm64;elif [ "$(uname -m)" = "armv7l" ];then kepubify_arch=arm; fi && wget https://github.com/pgaskin/kepubify/releases/download/v${KEPUBIFY_VER}/kepubify-linux-${kepubify_arch} -O /usr/local/bin/kepubify && chmod 755 /usr/local/bin/kepubify' - -EXPOSE 7654 -ENTRYPOINT ["/bin/sh"] - -# Run the server -CMD ["-c", ". /opt/venv/bin/activate && exec python3 /usr/local/bin/server.py"] \ No newline at end of file diff --git a/calibre/server.py b/calibre/server.py deleted file mode 100644 index 6665d249..00000000 --- a/calibre/server.py +++ /dev/null @@ -1,98 +0,0 @@ -from flask import Flask, request, jsonify, send_file, make_response, render_template_string, redirect -from flask_cors import CORS -import os -import shutil -import subprocess -import sys -import uuid -app = Flask(__name__) -app.config['MAX_CONTENT_LENGTH'] = 4 * 1024 * 1024 * 1024 # 4GB max upload size - -CORS(app) - -# Static HTML form template -convert_form = ''' - - - - File Conversion Form - - -

File Conversion Form

-
- -

- -

- -

- -
- - -''' - -@app.route("/", methods=['GET']) -def index(): - return make_response(redirect("/convert")) - -@app.route('/convert', methods=['POST', 'GET']) -def convert(): - if request.method == 'GET': - # Render the HTML form with text/html content type - response = make_response(render_template_string(convert_form)) - response.headers['Content-Type'] = 'text/html' - return response - - data = request.files['file'] - unique_prefix = str(uuid.uuid4()) - input_format = request.form.get('input_format', 'pdf') - output_format = request.form.get('output_format', 'epub') - input_file = f"/tmp/pandoc/{unique_prefix}_input.{input_format}" - output_file = f"/tmp/pandoc/{unique_prefix}_output.{output_format}" - kobo_output_file = f"/tmp/pandoc/{unique_prefix}_kobo.epub" - - data.save(input_file) - - - # Run ebook-convert conversion - try: - if output_format != input_format and not (output_format == 'kobo.epub' and input_format == 'epub'): - # Run pandoc conversion with error handling - subprocess.run(['ebook-convert', input_file, output_file], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - else: - shutil.copy(input_file, output_file) - except subprocess.CalledProcessError as e: - # Handle pandoc conversion error - os.remove(input_file) - stderr_str = e.stderr.decode('utf-8') - return jsonify({"error": "Conversion failed", "details": str(e), "stderr": stderr_str}), 500 - - if 'kobo' in output_format.lower(): - try: - # Run pandoc conversion with error handling - subprocess.run(['kepubify', '-o', kobo_output_file, output_file ], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - os.remove(output_file) - output_file = kobo_output_file - except subprocess.CalledProcessError as e: - # Handle pandoc conversion error - os.remove(output_file) - os.remove(input_file) - stderr_str = e.stderr.decode('utf-8') - return jsonify({"error": "Kobo Conversion failed", "details": str(e), "stderr": stderr_str}), 500 - - response = send_file(output_file, as_attachment=True) - - # Remove the temporary files after sending - os.remove(input_file) - os.remove(output_file) - - return response - -@app.route('/health', methods=['GET']) -def health(): - return jsonify({"status": "healthy"}) - -if __name__ == '__main__': - port = int(sys.argv[1]) if len(sys.argv) > 1 else 7654 - app.run(host='0.0.0.0', port=port) \ No newline at end of file diff --git a/config/services.yaml b/config/services.yaml index 2a0fc9db..e22f5b7f 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -104,14 +104,6 @@ services: tags: - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 130 } - App\Service\BookFormatStorage: - arguments: - $storageDir: '%kernel.project_dir%/public/alternatives' - - App\Service\BookConverter: - bind: - $storageDir: '%kernel.project_dir%/public/alternatives' - App\EventListener\LanguageListener: tags: - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 101 } diff --git a/docker-compose.yml b/docker-compose.yml index 4b2b7d28..648713c5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,17 +33,7 @@ services: - 'traefik.http.routers.npm.entrypoints=https,http' - 'traefik.http.routers.npm.rule=Host(`biblioteca-npm.docker.test`)' - 'traefik.http.services.npm.loadbalancer.server.port=8181' - calibre: - hostname: calibre - build: - context: ./calibre - volumes: - - ./var/cache/pandoc:/tmp/pandoc - ports: - - 7654:7654 - networks: - - default - - pontsun + db: image: mariadb:10.10 diff --git a/migrations/Version20240817142454.php b/migrations/Version20240817142454.php deleted file mode 100644 index 6239e29f..00000000 --- a/migrations/Version20240817142454.php +++ /dev/null @@ -1,41 +0,0 @@ -addSql('CREATE TABLE book_format (id INT AUTO_INCREMENT NOT NULL, book_id INT NOT NULL, type VARCHAR(255) NOT NULL, INDEX IDX_F76D795216A2B381 (book_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'); - $this->addSql('ALTER TABLE book_format ADD CONSTRAINT FK_F76D795216A2B381 FOREIGN KEY (book_id) REFERENCES book (id)'); - $this->addSql('ALTER TABLE kobo_device DROP FOREIGN KEY FK_42E56EFA76ED395'); - $this->addSql('DROP INDEX idx_42e56efa76ed395 ON kobo_device'); - $this->addSql('CREATE INDEX IDX_2EB06A2BA76ED395 ON kobo_device (user_id)'); - $this->addSql('ALTER TABLE kobo_device ADD CONSTRAINT FK_42E56EFA76ED395 FOREIGN KEY (user_id) REFERENCES user (id)'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('ALTER TABLE book_format DROP FOREIGN KEY FK_F76D795216A2B381'); - $this->addSql('DROP TABLE book_format'); - $this->addSql('ALTER TABLE kobo_device DROP FOREIGN KEY FK_2EB06A2BA76ED395'); - $this->addSql('DROP INDEX idx_2eb06a2ba76ed395 ON kobo_device'); - $this->addSql('CREATE INDEX IDX_42E56EFA76ED395 ON kobo_device (user_id)'); - $this->addSql('ALTER TABLE kobo_device ADD CONSTRAINT FK_2EB06A2BA76ED395 FOREIGN KEY (user_id) REFERENCES `user` (id)'); - } -} diff --git a/src/Command/BookConvertCommand.php b/src/Command/BookConvertCommand.php deleted file mode 100644 index cecb2496..00000000 --- a/src/Command/BookConvertCommand.php +++ /dev/null @@ -1,53 +0,0 @@ -addArgument('bookId', InputArgument::REQUIRED, 'Book ID') - ->addOption('format', null, InputOption::VALUE_REQUIRED, 'Book format') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $format = $input->getOption('format'); - $format = !is_string($format) || $format === '' ? BookFormatStorage::FORMAT_EPUB_KOBO : $format; - $id = $input->getArgument('bookId'); - $book = $this->bookRepository->findOneBy(['id' => $id]); - - if ($book === null) { - $output->writeln('Book not found'); - - return 1; - } - - $this->bookConverter->convert($book, $format); - - return Command::SUCCESS; - } -} diff --git a/src/Entity/Book.php b/src/Entity/Book.php index 0bd93dc1..865e5a0d 100644 --- a/src/Entity/Book.php +++ b/src/Entity/Book.php @@ -118,12 +118,6 @@ class Book #[ORM\OneToMany(mappedBy: 'book', targetEntity: KoboSyncedBook::class, cascade: ['remove'], orphanRemoval: true)] private Collection $koboSyncedBooks; - /** - * @var Collection - */ - #[ORM\OneToMany(mappedBy: 'book', targetEntity: BookFormat::class, orphanRemoval: true)] - private Collection $bookFormats; - public function __construct() { $this->bookInteractions = new ArrayCollection(); @@ -131,7 +125,6 @@ public function __construct() $this->uuid = $this->generateUuid(); $this->koboSyncedBooks = new ArrayCollection(); $this->bookmarkUsers = new ArrayCollection(); - $this->bookFormats = new ArrayCollection(); } public function getId(): ?int @@ -596,37 +589,4 @@ public function setBookmarkUsers(Collection $bookmarkUsers): self return $this; } - - public function hasFormat(string $format): bool - { - foreach ($this->bookFormats as $bookFormat) { - if ($bookFormat->getType() === $format) { - return true; - } - } - - return false; - } - - public function addBookFormat(BookFormat $bookFormat): static - { - if (!$this->bookFormats->contains($bookFormat)) { - $this->bookFormats->add($bookFormat); - $bookFormat->setBook($this); - } - - return $this; - } - - public function removeBookFormat(BookFormat $bookFormat): static - { - if ($this->bookFormats->removeElement($bookFormat)) { - // set the owning side to null (unless already changed) - if ($bookFormat->getBook() === $this) { - $bookFormat->setBook(null); - } - } - - return $this; - } } diff --git a/src/Entity/BookFormat.php b/src/Entity/BookFormat.php deleted file mode 100644 index 100683d5..00000000 --- a/src/Entity/BookFormat.php +++ /dev/null @@ -1,64 +0,0 @@ -book = $book; - $this->type = $type; - } - - public function getId(): ?int - { - return $this->id; - } - - public function getType(): ?string - { - return $this->type; - } - - public function setType(string $type): static - { - $this->type = $type; - - return $this; - } - - public function setId(int $id): static - { - $this->id = $id; - - return $this; - } - - public function getBook(): ?Book - { - return $this->book; - } - - public function setBook(?Book $book): static - { - $this->book = $book; - - return $this; - } -} diff --git a/src/Repository/BookFormatRepository.php b/src/Repository/BookFormatRepository.php deleted file mode 100644 index a428d0c0..00000000 --- a/src/Repository/BookFormatRepository.php +++ /dev/null @@ -1,43 +0,0 @@ - - */ -class BookFormatRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, BookFormat::class); - } - - // /** - // * @return BookFormat[] Returns an array of BookFormat objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('b') - // ->andWhere('b.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('b.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?BookFormat - // { - // return $this->createQueryBuilder('b') - // ->andWhere('b.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } -} diff --git a/src/Service/BookConverter.php b/src/Service/BookConverter.php deleted file mode 100644 index 267a3f40..00000000 --- a/src/Service/BookConverter.php +++ /dev/null @@ -1,92 +0,0 @@ -doRequest($book, $format); - $file = $this->responseToFile($response); - $this->storage->store($book, $format, $file); - - if (false === $book->hasFormat($format)) { - $bookFormat = new BookFormat($book, $format); - $book->addBookFormat($bookFormat); - $this->entityManager->persist($bookFormat); - $this->entityManager->flush(); - } - } - - public function responseToFile(ResponseInterface $response): \SplFileInfo - { - $random = bin2hex(random_bytes(8)); - $tempDest = $this->cacheDir.'/'.$random.'.ebook'; - try { - if ($response->getStatusCode() !== 200) { - throw new \RuntimeException(sprintf('Invalid status code %s, %s', $response->getStatusCode(), $response->getContent(false))); - } - - $content = $response->getContent(false); - - $dirname = dirname($tempDest); - if (false === is_dir($dirname)) { - mkdir($dirname, 0777, true); - } - $status = file_put_contents($tempDest, $content); - if ($status === false) { - throw new \RuntimeException('Could not write to file'); - } - - return new \SplFileInfo($tempDest); - } catch (\Exception $e) { - if (file_exists($tempDest)) { - unlink($tempDest); - } - throw $e; - } - } - - protected function doRequest(Book $book, string $format): ResponseInterface - { - $file = $this->fileSystemManager->getBookFile($book); - $data = [ - 'input_format' => $book->getExtension(), - 'output_format' => $format, - 'file' => DataPart::fromPath($file->getPathname(), 'name.'.$format), - ]; - - $formData = new FormDataPart($data); - - $options = [ - 'headers' => $formData->getPreparedHeaders()->toArray(), - 'body' => $formData->bodyToIterable(), - ]; - - return $this->client->request('POST', $this->converterUrl, $options); - } - - public function setConverterUrl(string $converterUrl): void - { - $this->converterUrl = $converterUrl; - } -} diff --git a/src/Service/BookFormatStorage.php b/src/Service/BookFormatStorage.php deleted file mode 100644 index dc4d56c8..00000000 --- a/src/Service/BookFormatStorage.php +++ /dev/null @@ -1,45 +0,0 @@ -storageDir.'/'.substr($book->getUuid(), 0, 3).'/'.$book->getUuid().'.'.$format; - } - - public function store(Book $book, string $format, \SplFileInfo $file): void - { - $filename = $this->getLocation($book, $format); - $directory = dirname($filename); - if (false === is_dir($directory)) { - mkdir($directory, 0777, true); - } - - rename($file->getPathname(), $filename); - } - - public function has(Book $book, string $format): bool - { - return file_exists($this->getLocation($book, $format)); - } - - public function remove(Book $book, string $format): void - { - if (false === unlink($this->getLocation($book, $format))) { - throw new \RuntimeException('Could not remove the file'); - } - } - - public function get(Book $book, string $format): \SplFileInfo - { - return new \SplFileInfo($this->getLocation($book, $format)); - } -} diff --git a/src/Service/BookFormatStorageInterface.php b/src/Service/BookFormatStorageInterface.php deleted file mode 100644 index 35b0cc12..00000000 --- a/src/Service/BookFormatStorageInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -