From 3b010b8eeb13171485d4db570bde357cd85e8d52 Mon Sep 17 00:00:00 2001 From: Yuvi9587 <114073886+Yuvi9587@users.noreply.github.com> Date: Thu, 5 Jun 2025 18:23:08 +0100 Subject: [PATCH] Commit --- downloader_utils.py | 52 ++++++++++++++++++++++++++++++++++++++------- main.py | 27 ++++++++++++++++++----- 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/downloader_utils.py b/downloader_utils.py index dded447..7239a13 100644 --- a/downloader_utils.py +++ b/downloader_utils.py @@ -767,30 +767,47 @@ class PostProcessorWorker: manga_global_file_counter_ref=None): # New for global numbering was_original_name_kept_flag = False final_filename_saved_for_return = "" - retry_later_details = None # For storing info if retryable failure + retry_later_details = None + + # self.logger(f" [DSF_DEBUG] Entered _download_single_file for: {file_info.get('name', 'unknown file') if file_info else 'NO_FILE_INFO'}") + if self._check_pause(f"File download prep for '{file_info.get('name', 'unknown file')}'"): return 0, 1, "", False if self.check_cancel() or (skip_event and skip_event.is_set()): return 0, 1, "", False + + # self.logger(f" [DSF_DEBUG] Passed pause/cancel checks.") + file_url = file_info.get('url') cookies_to_use_for_file = None if self.use_cookie: # This flag comes from the checkbox + # self.logger(f" [DSF_DEBUG] Preparing cookies...") cookies_to_use_for_file = prepare_cookies_for_request(self.use_cookie, self.cookie_text, self.selected_cookie_file, self.app_base_dir, self.logger) + # self.logger(f" [DSF_DEBUG] Cookies prepared.") + api_original_filename = file_info.get('_original_name_for_log', file_info.get('name')) + # self.logger(f" [DSF_DEBUG] API original filename: '{api_original_filename}'") + filename_to_save_in_main_path = "" if forced_filename_override: filename_to_save_in_main_path = forced_filename_override self.logger(f" Retrying with forced filename: '{filename_to_save_in_main_path}'") else: + # self.logger(f" [DSF_DEBUG] Starting filename generation logic...") if self.skip_words_list and (self.skip_words_scope == SKIP_SCOPE_FILES or self.skip_words_scope == SKIP_SCOPE_BOTH): filename_to_check_for_skip_words = api_original_filename.lower() for skip_word in self.skip_words_list: if skip_word.lower() in filename_to_check_for_skip_words: self.logger(f" -> Skip File (Keyword in Original Name '{skip_word}'): '{api_original_filename}'. Scope: {self.skip_words_scope}") return 0, 1, api_original_filename, False, FILE_DOWNLOAD_STATUS_SKIPPED, None - original_filename_cleaned_base, original_ext = os.path.splitext(clean_filename(api_original_filename)) + # self.logger(f" [DSF_DEBUG] About to call clean_filename for: '{api_original_filename}'") + cleaned_original_api_filename = clean_filename(api_original_filename) + # self.logger(f" [DSF_DEBUG] clean_filename returned: '{cleaned_original_api_filename}'") + original_filename_cleaned_base, original_ext = os.path.splitext(cleaned_original_api_filename) + if not original_ext.startswith('.'): original_ext = '.' + original_ext if original_ext else '' if self.manga_mode_active: # Note: duplicate_file_mode is overridden to "Delete" in main.py if manga_mode is on + # self.logger(f" [DSF_DEBUG] Manga mode active. Style: {self.manga_filename_style}") if self.manga_filename_style == STYLE_ORIGINAL_NAME: - filename_to_save_in_main_path = clean_filename(api_original_filename) + filename_to_save_in_main_path = cleaned_original_api_filename # Use already cleaned if self.manga_date_prefix and self.manga_date_prefix.strip(): cleaned_prefix = clean_filename(self.manga_date_prefix.strip()) if cleaned_prefix: @@ -810,16 +827,18 @@ class PostProcessorWorker: else: filename_to_save_in_main_path = f"{cleaned_post_title_base}{original_ext}" else: - filename_to_save_in_main_path = clean_filename(api_original_filename) # Fallback to original if no title + filename_to_save_in_main_path = cleaned_original_api_filename # Fallback to cleaned original self.logger(f"⚠️ Manga mode (Post Title Style): Post title missing for post {original_post_id_for_log}. Using cleaned original filename '{filename_to_save_in_main_path}'.") elif self.manga_filename_style == STYLE_DATE_BASED: current_thread_name = threading.current_thread().name if manga_date_file_counter_ref is not None and len(manga_date_file_counter_ref) == 2: counter_val_for_filename = -1 counter_lock = manga_date_file_counter_ref[1] + # self.logger(f" [DSF_DEBUG] Manga Date Mode: Acquiring counter lock...") with counter_lock: counter_val_for_filename = manga_date_file_counter_ref[0] manga_date_file_counter_ref[0] += 1 # type: ignore + # self.logger(f" [DSF_DEBUG] Manga Date Mode: Counter lock released. Value: {counter_val_for_filename}") base_numbered_name = f"{counter_val_for_filename:03d}" # type: ignore if self.manga_date_prefix and self.manga_date_prefix.strip(): cleaned_prefix = clean_filename(self.manga_date_prefix.strip()) @@ -831,31 +850,38 @@ class PostProcessorWorker: filename_to_save_in_main_path = f"{base_numbered_name}{original_ext}" else: self.logger(f"⚠️ Manga Date Mode: Counter ref not provided or malformed for '{api_original_filename}'. Using original. Ref: {manga_date_file_counter_ref}") - filename_to_save_in_main_path = clean_filename(api_original_filename) + filename_to_save_in_main_path = cleaned_original_api_filename elif self.manga_filename_style == STYLE_POST_TITLE_GLOBAL_NUMBERING: if manga_global_file_counter_ref is not None and len(manga_global_file_counter_ref) == 2: counter_val_for_filename = -1 counter_lock = manga_global_file_counter_ref[1] + # self.logger(f" [DSF_DEBUG] Manga Title+GlobalNum Mode: Acquiring counter lock...") with counter_lock: counter_val_for_filename = manga_global_file_counter_ref[0] manga_global_file_counter_ref[0] += 1 + # self.logger(f" [DSF_DEBUG] Manga Title+GlobalNum Mode: Counter lock released. Value: {counter_val_for_filename}") cleaned_post_title_base_for_global = clean_filename(post_title.strip() if post_title and post_title.strip() else "post") filename_to_save_in_main_path = f"{cleaned_post_title_base_for_global}_{counter_val_for_filename:03d}{original_ext}" else: # Counter ref not provided or malformed self.logger(f"⚠️ Manga Title+GlobalNum Mode: Counter ref not provided or malformed for '{api_original_filename}'. Using original. Ref: {manga_global_file_counter_ref}") - filename_to_save_in_main_path = clean_filename(api_original_filename) # Fallback to original + filename_to_save_in_main_path = cleaned_original_api_filename # Fallback to cleaned original self.logger(f"⚠️ Manga mode (Title+GlobalNum Style Fallback): Using cleaned original filename '{filename_to_save_in_main_path}' for post {original_post_id_for_log}.") else: self.logger(f"⚠️ Manga mode: Unknown filename style '{self.manga_filename_style}'. Defaulting to original filename for '{api_original_filename}'.") - filename_to_save_in_main_path = clean_filename(api_original_filename) + filename_to_save_in_main_path = cleaned_original_api_filename if not filename_to_save_in_main_path: filename_to_save_in_main_path = f"manga_file_{original_post_id_for_log}_{file_index_in_post + 1}{original_ext}" self.logger(f"⚠️ Manga mode: Generated filename was empty. Using generic fallback: '{filename_to_save_in_main_path}'.") was_original_name_kept_flag = False else: - filename_to_save_in_main_path = clean_filename(api_original_filename) + # self.logger(f" [DSF_DEBUG] Non-manga mode. Setting filename_to_save_in_main_path to cleaned original: '{cleaned_original_api_filename}'") + filename_to_save_in_main_path = cleaned_original_api_filename was_original_name_kept_flag = False + + # self.logger(f" [DSF_DEBUG] Filename after initial/manga logic: '{filename_to_save_in_main_path}'") + if self.remove_from_filename_words_list and filename_to_save_in_main_path: + # self.logger(f" [DSF_DEBUG] Starting 'remove_from_filename_words_list' logic for: '{filename_to_save_in_main_path}'") base_name_for_removal, ext_for_removal = os.path.splitext(filename_to_save_in_main_path) modified_base_name = base_name_for_removal for word_to_remove in self.remove_from_filename_words_list: @@ -869,7 +895,11 @@ class PostProcessorWorker: filename_to_save_in_main_path = modified_base_name + ext_for_removal else: filename_to_save_in_main_path = base_name_for_removal + ext_for_removal + # self.logger(f" [DSF_DEBUG] Filename after 'remove_from_filename_words_list': '{filename_to_save_in_main_path}'") + # self.logger(f" [DSF_DEBUG] Filename generation logic complete. Final base name for download: '{filename_to_save_in_main_path}'") + if not self.download_thumbnails: + # self.logger(f" [DSF_DEBUG] Starting filter mode checks (thumbnails not downloaded)...") is_img_type = is_image(api_original_filename) is_vid_type = is_video(api_original_filename) is_archive_type = is_archive(api_original_filename) @@ -896,8 +926,12 @@ class PostProcessorWorker: if self.skip_rar and is_rar(api_original_filename): self.logger(f" -> Pref Skip: '{api_original_filename}' (RAR).") return 0, 1, api_original_filename, False, FILE_DOWNLOAD_STATUS_SKIPPED, None + # self.logger(f" [DSF_DEBUG] Filter mode checks complete.") + + # self.logger(f" [DSF_DEBUG] Attempting to create target folder: '{target_folder_path}'") try: os.makedirs(target_folder_path, exist_ok=True) # For .part file + # self.logger(f" [DSF_DEBUG] Target folder ensured/created.") except OSError as e: self.logger(f" ❌ Critical error creating directory '{target_folder_path}': {e}. Skipping file '{api_original_filename}'.") return 0, 1, api_original_filename, False, FILE_DOWNLOAD_STATUS_SKIPPED, None # Treat as skip @@ -910,6 +944,8 @@ class PostProcessorWorker: total_size_bytes = 0 download_successful_flag = False last_exception_for_retry_later = None + + # self.logger(f" [DSF_DEBUG] Entering download retry loop for '{api_original_filename}'...") for attempt_num_single_stream in range(max_retries + 1): if self._check_pause(f"File download attempt for '{api_original_filename}'"): break if self.check_cancel() or (skip_event and skip_event.is_set()): break diff --git a/main.py b/main.py index 9bb2cad..8a7391c 100644 --- a/main.py +++ b/main.py @@ -4186,6 +4186,12 @@ class DownloaderApp(QWidget): if hasattr(self, 'use_cookie_checkbox'): # Update visibility based on forced True state self._update_cookie_input_visibility(True) self.update_ui_for_manga_mode(False) # Refresh manga UI elements + # Explicitly enable favorite buttons when favorite mode is ON + if hasattr(self, 'favorite_mode_artists_button'): + self.favorite_mode_artists_button.setEnabled(True) + if hasattr(self, 'favorite_mode_posts_button'): + self.favorite_mode_posts_button.setEnabled(True) + else: # Favorite Mode OFF (URL input visible) if self.link_input: self.link_input.setEnabled(True) self.update_page_range_enabled_state() # Re-evaluate based on current link_input text @@ -4196,6 +4202,11 @@ class DownloaderApp(QWidget): self.use_cookie_checkbox.setEnabled(True) # Unlock it if hasattr(self, 'use_cookie_checkbox'): # Update visibility based on current state self._update_cookie_input_visibility(self.use_cookie_checkbox.isChecked()) + # Explicitly disable favorite buttons when favorite mode is OFF + if hasattr(self, 'favorite_mode_artists_button'): + self.favorite_mode_artists_button.setEnabled(False) + if hasattr(self, 'favorite_mode_posts_button'): + self.favorite_mode_posts_button.setEnabled(False) def update_ui_for_manga_mode(self, checked): is_only_links_mode = self.radio_only_links and self.radio_only_links.isChecked() @@ -5264,10 +5275,13 @@ class DownloaderApp(QWidget): else: # UI is idle or download finished pass + # General UI element enabling/disabling for widget in all_potentially_toggleable_widgets: if not widget: continue - if self.is_paused and widget in widgets_to_enable_on_pause: + # Skip favorite mode buttons here, they are handled by _handle_favorite_mode_toggle + if widget is self.favorite_mode_artists_button or widget is self.favorite_mode_posts_button: continue + elif self.is_paused and widget in widgets_to_enable_on_pause: widget.setEnabled(True) # Re-enable specific widgets if paused elif widget is self.favorite_mode_checkbox: # Favorite mode checkbox can only be changed when idle widget.setEnabled(enabled) @@ -5281,10 +5295,13 @@ class DownloaderApp(QWidget): if self.link_input: self.link_input.setEnabled(enabled and not is_fav_mode_active) - if self.favorite_mode_artists_button: - self.favorite_mode_artists_button.setEnabled(enabled and is_fav_mode_active) - if self.favorite_mode_posts_button: - self.favorite_mode_posts_button.setEnabled(enabled and is_fav_mode_active) # Enable/disable this button + # If UI is being disabled (download active), ensure favorite buttons are also disabled. + # If UI is being enabled, _handle_favorite_mode_toggle will manage their state. + if not enabled: + if self.favorite_mode_artists_button: + self.favorite_mode_artists_button.setEnabled(False) + if self.favorite_mode_posts_button: + self.favorite_mode_posts_button.setEnabled(False) if self.download_btn: self.download_btn.setEnabled(enabled and not is_fav_mode_active) # Only if UI enabled AND not in fav mode