From 53ef248cb5042543dee54b765fee06b343f038cc Mon Sep 17 00:00:00 2001
From: sevi-kun <dev@sevi-kun.me>
Date: Mon, 17 Mar 2025 00:24:05 +0100
Subject: [PATCH] Swap docker version with pip version

---
 requirements.txt | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/main.py      | 45 ++++++++++++++++++--------------------
 2 files changed, 77 insertions(+), 24 deletions(-)
 create mode 100644 requirements.txt

diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..5946f1b
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,56 @@
+aiofiles==24.1.0
+aiohappyeyeballs==2.6.1
+aiohttp==3.11.13
+aiosignal==1.3.2
+annotated-types==0.7.0
+anyio==4.8.0
+attrs==25.3.0
+beautifulsoup4==4.13.3
+bidict==0.23.1
+certifi==2025.1.31
+chardet==5.2.0
+charset-normalizer==3.4.1
+click==8.1.8
+docutils==0.21.2
+fastapi==0.115.11
+frozenlist==1.5.0
+h11==0.14.0
+httpcore==1.0.7
+httptools==0.6.4
+httpx==0.28.1
+idna==3.10
+ifaddr==0.2.0
+iso8601==1.1.0
+itsdangerous==2.2.0
+Jinja2==3.1.6
+markdown2==2.5.3
+MarkupSafe==3.0.2
+multidict==6.1.0
+nhentai==0.5.25
+nicegui==2.12.1
+orjson==3.10.15
+propcache==0.3.0
+pscript==0.7.7
+pydantic==2.10.6
+pydantic_core==2.27.2
+Pygments==2.19.1
+python-dotenv==1.0.1
+python-engineio==4.11.2
+python-multipart==0.0.20
+python-socketio==5.12.1
+PyYAML==6.0.2
+requests==2.32.3
+simple-websocket==1.1.0
+sniffio==1.3.1
+soupsieve==2.6
+starlette==0.46.1
+tabulate==0.9.0
+typing_extensions==4.12.2
+urllib3==1.26.20
+uvicorn==0.34.0
+uvloop==0.21.0
+vbuild==0.8.2
+watchfiles==1.0.4
+websockets==15.0.1
+wsproto==1.2.0
+yarl==1.18.3
diff --git a/src/main.py b/src/main.py
index 4c13c2c..4ec3327 100644
--- a/src/main.py
+++ b/src/main.py
@@ -9,12 +9,11 @@ ui.dark_mode().enable()
 
 # Configuration
 DOWNLOAD_DIR = os.path.expanduser("~/Downloads/doujinshi")
-DOCKER_IMAGE = "ricterz/nhentai"  # Official Docker image from DockerHub
 OUTPUT_FORMAT = "[%i]%s"  # Default format for folder naming
 COOKIE = ""  # For bypassing Cloudflare captcha
 USER_AGENT = ""  # For bypassing Cloudflare captcha
-HTML_VIEWER = True  # Generate HTML viewer
-GENERATE_CBZ = False  # Generate Comic Book Archive
+HTML_VIEWER = False  # Generate HTML viewer
+GENERATE_CBZ = True  # Generate Comic Book Archive
 GENERATE_PDF = False  # Generate PDF file
 THREAD_COUNT = 5  # Thread count for downloading
 TIMEOUT = 30  # Timeout in seconds
@@ -48,15 +47,10 @@ def add_nhentai_id():
                                     on_click=lambda: start_download(id_value, status),
                                     color='primary').classes('ml-2').props('size=sm')
 
-            complete_btn = ui.button('Mark Complete',
-                                    on_click=lambda: update_status(status, id_value, True),
-                                    color='green').classes('ml-2').props('size=sm')
-
 def update_status(status_icon, id_value, success=True):
     if success:
         status_icon.name = 'check_circle'
         status_icon.classes('text-green-500', remove='text-yellow-500 text-red-500 text-blue-500')
-        ui.notify(f'ID {id_value} marked as complete', color='positive')
     else:
         status_icon.name = 'error'
         status_icon.classes('text-red-500', remove='text-yellow-500 text-green-500 text-blue-500')
@@ -64,23 +58,30 @@ def update_status(status_icon, id_value, success=True):
 
 def download_doujinshi(id_value, status_icon):
     # This function runs in a background thread
+    global download_statuses
+
     try:
+        # Try to check if nhentai CLI is installed
+        try:
+            subprocess.run(["nhentai", "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
+        except (subprocess.SubprocessError, FileNotFoundError):
+            download_statuses[id_value] = {
+                'status': 'error',
+                'message': 'nhentai CLI tool is not installed'
+            }
+            return
+
         # Create download directory if it doesn't exist
         os.makedirs(DOWNLOAD_DIR, exist_ok=True)
 
-        # Build Docker command with all options
-        cmd = [
-            "docker", "run", "--rm",
-            "-v", f"{DOWNLOAD_DIR}:/output",
-            "-v", f"{os.path.expanduser('~/.nhentai')}:/root/.nhentai",
-            DOCKER_IMAGE
-        ]
+        # Build command with all options
+        cmd = ["nhentai"]
 
         # Add the ID
         cmd.extend(["--id", str(id_value)])
 
         # Add output directory
-        cmd.extend(["--output", "/output"])
+        cmd.extend(["--output", DOWNLOAD_DIR])
 
         # Add format option
         cmd.extend(["--format", OUTPUT_FORMAT])
@@ -148,7 +149,6 @@ def download_doujinshi(id_value, status_icon):
         stdout, stderr = process.communicate()
 
         # Use the global dict to track status
-        global download_statuses
         if process.returncode == 0:
             # Success
             download_statuses[id_value] = {
@@ -217,12 +217,11 @@ def show_settings():
     with ui.dialog() as dialog, ui.card().classes('w-96'):
         ui.label('Download Settings').classes('text-xl font-bold')
 
-        global DOWNLOAD_DIR, DOCKER_IMAGE, OUTPUT_FORMAT, COOKIE, USER_AGENT, HTML_VIEWER, GENERATE_CBZ, GENERATE_PDF, THREAD_COUNT, TIMEOUT, RETRY_COUNT
+        global DOWNLOAD_DIR, OUTPUT_FORMAT, COOKIE, USER_AGENT, HTML_VIEWER, GENERATE_CBZ, GENERATE_PDF, THREAD_COUNT, TIMEOUT, RETRY_COUNT
 
         # Basic Settings
         ui.label('Basic Settings').classes('text-lg font-semibold mt-4')
         download_dir_input = ui.input('Download Directory', value=DOWNLOAD_DIR).classes('w-full')
-        docker_image_input = ui.input('Docker Image', value=DOCKER_IMAGE).classes('w-full')
         output_format_input = ui.input('Output Format', value=OUTPUT_FORMAT,
                                      placeholder='e.g. [%i]%s').classes('w-full')
         ui.label('Supported: %i (ID), %s (subtitle), %t (title), %a (authors), %g (groups), %p (pretty name)').classes('text-xs text-gray-500')
@@ -250,7 +249,6 @@ def show_settings():
             ui.button('Cancel', on_click=dialog.close).props('outline')
             ui.button('Save', on_click=lambda: save_settings(
                 download_dir_input.value,
-                docker_image_input.value,
                 output_format_input.value,
                 cookie_input.value,
                 useragent_input.value,
@@ -264,12 +262,11 @@ def show_settings():
             ))
     dialog.open()
 
-def save_settings(download_dir, docker_image, output_format, cookie, useragent,
+def save_settings(download_dir, output_format, cookie, useragent,
                 html_viewer, generate_cbz, generate_pdf, thread_count, timeout, retry_count, dialog):
-    global DOWNLOAD_DIR, DOCKER_IMAGE, OUTPUT_FORMAT, COOKIE, USER_AGENT, HTML_VIEWER, GENERATE_CBZ, GENERATE_PDF, THREAD_COUNT, TIMEOUT, RETRY_COUNT
+    global DOWNLOAD_DIR, OUTPUT_FORMAT, COOKIE, USER_AGENT, HTML_VIEWER, GENERATE_CBZ, GENERATE_PDF, THREAD_COUNT, TIMEOUT, RETRY_COUNT
 
     DOWNLOAD_DIR = download_dir
-    DOCKER_IMAGE = docker_image
     OUTPUT_FORMAT = output_format
     COOKIE = cookie
     USER_AGENT = useragent
@@ -304,7 +301,7 @@ with history_container:
 
 # Add footer with help info
 with ui.footer().classes('bg-gray-100 dark:bg-gray-800 text-sm'):
-    ui.label('Using ricterz/nhentai Docker image. Need help? Check the GitHub page:')
+    ui.label('Using nhentai CLI tool. Need help? Check the GitHub page:')
     ui.link('https://github.com/RicterZ/nhentai', 'https://github.com/RicterZ/nhentai').classes('ml-1')
 
 ui.run()