From 6a36179136bf147ca01d872775003391a5ae1af7 Mon Sep 17 00:00:00 2001
From: Yuvi9587 <114073886+Yuvi9587@users.noreply.github.com>
Date: Sun, 28 Dec 2025 09:34:49 +0530
Subject: [PATCH] Commit
---
src/core/api_client.py | 9 +++------
src/core/hentaifox_client.py | 9 ++++-----
src/core/workers.py | 4 +---
src/ui/dialogs/SinglePDF.py | 10 ++--------
src/ui/main_window.py | 24 ++++++------------------
5 files changed, 16 insertions(+), 40 deletions(-)
diff --git a/src/core/api_client.py b/src/core/api_client.py
index 271824a..789a2d5 100644
--- a/src/core/api_client.py
+++ b/src/core/api_client.py
@@ -15,7 +15,6 @@ from ..config.constants import (
STYLE_POST_TITLE_GLOBAL_NUMBERING
)
-# --- NEW: Custom Adapter to fix SSL errors ---
class CustomSSLAdapter(HTTPAdapter):
"""
A custom HTTPAdapter that forces check_hostname=False when using SSL.
@@ -130,13 +129,13 @@ def fetch_single_post_data(api_domain, service, user_id, post_id, headers, logge
response = scraper.get(post_api_url, headers=headers, timeout=request_timeout, cookies=cookies_dict, proxies=proxies, verify=False)
- # --- FIX: Handle 429 Rate Limit explicitly ---
+
if response.status_code == 429:
wait_time = 20 + (attempt * 10) # 20s, 30s, 40s...
logger(f" ⚠️ Rate Limited (429) on post {post_id}. Waiting {wait_time} seconds before retrying...")
time.sleep(wait_time)
continue # Try loop again
- # ---------------------------------------------
+
response.raise_for_status()
@@ -266,11 +265,9 @@ def download_from_api(
if target_post_id and (start_page or end_page):
logger("⚠️ Page range (start/end page) is ignored when a specific post URL is provided (searching all pages for the post).")
- # --- FIXED LOGIC HERE ---
- # Define which styles require fetching ALL posts first (Sequential Mode)
+
styles_requiring_fetch_all = [STYLE_DATE_BASED, STYLE_POST_TITLE_GLOBAL_NUMBERING]
- # Only enable "fetch all and sort" if the current style is explicitly in the list above
is_manga_mode_fetch_all_and_sort_oldest_first = (
manga_mode and
(manga_filename_style_for_sort_check in styles_requiring_fetch_all) and
diff --git a/src/core/hentaifox_client.py b/src/core/hentaifox_client.py
index 0d6766b..5943667 100644
--- a/src/core/hentaifox_client.py
+++ b/src/core/hentaifox_client.py
@@ -1,8 +1,8 @@
import requests
import re
-from bs4 import BeautifulSoup # Optional, but regex is faster for this specific site
+from bs4 import BeautifulSoup
+
-# Logic derived from NHdownloader.sh 'hentaifox' function
BASE_URL = "https://hentaifox.com"
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
@@ -25,11 +25,10 @@ def get_gallery_metadata(gallery_id):
response.raise_for_status()
html = response.text
- # Extract Title (Bash: grep -o '
.*')
+
title_match = re.search(r'(.*?)', html)
title = title_match.group(1).replace(" - HentaiFox", "").strip() if title_match else f"Gallery {gallery_id}"
-
- # Extract Total Pages (Bash: grep -Eo 'Pages: [0-9]*')
+
pages_match = re.search(r'Pages: (\d+)', html)
if not pages_match:
raise ValueError("Could not find total pages count.")
diff --git a/src/core/workers.py b/src/core/workers.py
index 171f732..6d0f434 100644
--- a/src/core/workers.py
+++ b/src/core/workers.py
@@ -686,7 +686,6 @@ class PostProcessorWorker:
response = requests.get(new_url, headers=file_download_headers, timeout=(30, 300), stream=True, cookies=cookies_to_use_for_file, proxies=self.proxies, verify=False)
response.raise_for_status()
- # --- REVISED AND MOVED SIZE CHECK LOGIC ---
total_size_bytes = int(response.headers.get('Content-Length', 0))
if self.skip_file_size_mb is not None:
@@ -695,8 +694,7 @@ class PostProcessorWorker:
if file_size_mb < self.skip_file_size_mb:
self.logger(f" -> Skip File (Size): '{api_original_filename}' is {file_size_mb:.2f} MB, which is smaller than the {self.skip_file_size_mb} MB limit.")
return 0, 1, api_original_filename, False, FILE_DOWNLOAD_STATUS_SKIPPED, None
- # If Content-Length is missing, we can't check, so we no longer log a warning here and just proceed.
- # --- END OF REVISED LOGIC ---
+
num_parts_for_file = min(self.multipart_parts_count, MAX_PARTS_FOR_MULTIPART_DOWNLOAD)
diff --git a/src/ui/dialogs/SinglePDF.py b/src/ui/dialogs/SinglePDF.py
index d8ff49a..c1043fb 100644
--- a/src/ui/dialogs/SinglePDF.py
+++ b/src/ui/dialogs/SinglePDF.py
@@ -75,11 +75,6 @@ def add_metadata_page(pdf, post, font_family):
if link_url:
# Styling for clickable link: Blue + Underline
pdf.set_text_color(0, 0, 255)
- # Check if font supports underline style directly or just use 'U'
- # FPDF standard allows 'U' in style string.
- # We use 'U' combined with the font family.
- # Note: DejaVu implementation in fpdf2 might handle 'U' automatically or ignore it depending on version,
- # but setting text color indicates link clearly enough usually.
pdf.set_font(font_family, 'U', 11)
# Pass the URL to the 'link' parameter
@@ -131,9 +126,9 @@ def create_individual_pdf(post_data, output_filename, font_path, add_info_page=F
font_family = _setup_pdf_fonts(pdf, font_path, logger)
if add_info_page:
- # add_metadata_page adds the page start itself
+f
add_metadata_page(pdf, post_data, font_family)
- # REMOVED: pdf.add_page() <-- This ensures content starts right below the line
+
else:
pdf.add_page()
@@ -210,7 +205,6 @@ def create_single_pdf_from_content(posts_data, output_filename, font_path, add_i
for i, post in enumerate(posts_data):
if add_info_page:
add_metadata_page(pdf, post, font_family)
- # REMOVED: pdf.add_page() <-- This ensures content starts right below the line
else:
pdf.add_page()
diff --git a/src/ui/main_window.py b/src/ui/main_window.py
index a9b1ff5..8c5511f 100644
--- a/src/ui/main_window.py
+++ b/src/ui/main_window.py
@@ -6636,11 +6636,11 @@ class DownloaderApp (QWidget ):
# Look up the name in the cache, falling back to the ID if not found.
creator_name = self.creator_name_cache.get((service, user_id), user_id)
- # Add the new 'creator_name' key to the format_values dictionary.
+ .
format_values = {
'id': str(job_details.get('original_post_id_for_log', '')),
'user': user_id,
- 'creator_name': creator_name, # <-- ADDED
+ 'creator_name': creator_name,
'service': str(job_details.get('service', '')),
'title': post_title,
'name': base,
@@ -7075,7 +7075,6 @@ class DownloaderApp (QWidget ):
self.log_signal.emit(f" Fetched a total of {len(all_posts_from_api)} posts from the server.")
- # CORRECTED LINE: Assign the list directly without re-filtering
self.new_posts_for_update = all_posts_from_api
if not self.new_posts_for_update:
@@ -7103,7 +7102,6 @@ class DownloaderApp (QWidget ):
self.log_signal.emit(f" Update session will save to base folder: {base_download_dir_from_ui}")
raw_character_filters_text = self.character_input.text().strip()
- # FIX: Parse both filters and commands from the input string
parsed_character_filter_objects, download_commands = self._parse_character_filters(raw_character_filters_text)
try:
@@ -7181,11 +7179,7 @@ class DownloaderApp (QWidget ):
'single_pdf_mode': self.single_pdf_setting,
'project_root_dir': self.app_base_dir,
'processed_post_ids': list(self.active_update_profile['processed_post_ids']),
-
- # FIX: Use the parsed commands dictionary to get the sfp_threshold
'sfp_threshold': download_commands.get('sfp_threshold'),
-
- # FIX: Add all the missing keys
'date_prefix_format': self.date_prefix_format,
'domain_override': download_commands.get('domain_override'),
'archive_only_mode': download_commands.get('archive_only', False),
@@ -7218,11 +7212,9 @@ class DownloaderApp (QWidget ):
dialog = EmptyPopupDialog(self.user_data_path, self)
if dialog.exec_() == QDialog.Accepted:
-# --- START OF MODIFICATION ---
+
if hasattr(dialog, 'update_profiles_list') and dialog.update_profiles_list:
self.active_update_profiles_list = dialog.update_profiles_list
-
- # --- NEW LOGIC: Check if user wants to load settings into UI ---
load_settings_requested = getattr(dialog, 'load_settings_into_ui_requested', False)
self.override_update_profile_settings = load_settings_requested
@@ -7239,7 +7231,7 @@ class DownloaderApp (QWidget ):
self.link_input.setText(f"{len(self.active_update_profiles_list)} profiles loaded for update check...")
self._start_batch_update_check(self.active_update_profiles_list)
- # --- END OF MODIFICATION ---
+
elif hasattr(dialog, 'selected_creators_for_queue') and dialog.selected_creators_for_queue:
self.active_update_profile = None # Ensure single update mode is off
@@ -7488,17 +7480,13 @@ class DownloaderApp (QWidget ):
should_create_artist_folder = False
-# --- Check for popup selection scope ---
+
if item_type == 'creator_popup_selection' and item_scope == EmptyPopupDialog.SCOPE_CREATORS:
- should_create_artist_folder = True
- # --- Check for global "Artist Folders" scope ---
+ should_create_artist_folder = True
elif item_type != 'creator_popup_selection' and self.favorite_download_scope == FAVORITE_SCOPE_ARTIST_FOLDERS:
should_create_artist_folder = True
-
- # --- NEW: Check for forced folder flag from batch ---
if self.current_processing_favorite_item_info.get('force_artist_folder'):
should_create_artist_folder = True
- # ---------------------------------------------------
if should_create_artist_folder and main_download_dir:
folder_name_key = self.current_processing_favorite_item_info.get('name_for_folder', 'Unknown_Folder')