This commit is contained in:
Yuvi9587 2025-09-07 08:16:43 -07:00
parent ec94417569
commit a9b210b2ba
6 changed files with 47 additions and 91 deletions

View File

@ -60,7 +60,6 @@ RESOLUTION_KEY = "window_resolution"
UI_SCALE_KEY = "ui_scale_factor"
SAVE_CREATOR_JSON_KEY = "saveCreatorJsonProfile"
FETCH_FIRST_KEY = "fetchAllPostsFirst"
# --- FIX: Add the missing key for the Discord token ---
DISCORD_TOKEN_KEY = "discord/token"
POST_DOWNLOAD_ACTION_KEY = "postDownloadAction"

View File

@ -43,9 +43,7 @@ def fetch_channel_messages(channel_id, logger=print, cancellation_event=None, pa
}
offset = 0
# --- FIX: Corrected the page size for Discord API pagination ---
page_size = 150
# --- END FIX ---
while True:
if cancellation_event and cancellation_event.is_set():

View File

@ -875,25 +875,22 @@ class PostProcessorWorker:
def process(self):
if self.service == 'discord':
# For Discord, self.post is a MESSAGE object from the API.
post_title = self.post.get('content', '') or f"Message {self.post.get('id', 'N/A')}"
post_id = self.post.get('id', 'unknown_id')
post_main_file_info = {} # Discord messages don't have a single main file
post_main_file_info = {}
post_attachments = self.post.get('attachments', [])
post_content_html = self.post.get('content', '')
post_data = self.post # Keep a reference to the original message object
post_data = self.post
log_prefix = "Message"
else:
# Existing logic for standard creator posts
post_title = self.post.get('title', '') or 'untitled_post'
post_id = self.post.get('id', 'unknown_id')
post_main_file_info = self.post.get('file')
post_attachments = self.post.get('attachments', [])
post_content_html = self.post.get('content', '')
post_data = self.post # Reference to the post object
post_data = self.post
log_prefix = "Post"
# --- FIX: FETCH FULL POST DATA IF CONTENT IS MISSING BUT NEEDED ---
content_is_needed = (
self.show_external_links or
self.extract_links_only or

View File

@ -271,4 +271,4 @@ def download_dropbox_file(dropbox_link, download_path=".", logger_func=print):
except Exception as e:
logger_func(f" [Dropbox] ❌ An error occurred during Dropbox download: {e}")
traceback.print_exc(limit=2)
traceback.print_exc(limit=2)

View File

@ -42,17 +42,12 @@ class ErrorFilesDialog(QDialog):
if app_icon and not app_icon.isNull():
self.setWindowIcon(app_icon)
# --- START OF FIX ---
# Get the user-defined scale factor from the parent application.
scale_factor = getattr(self.parent_app, 'scale_factor', 1.0)
# Define base dimensions and apply the correct scale factor.
base_width, base_height = 550, 400
self.setMinimumSize(int(base_width * scale_factor), int(base_height * scale_factor))
self.resize(int(base_width * scale_factor * 1.1), int(base_height * scale_factor * 1.1))
# --- END OF FIX ---
# --- Initialize UI and Apply Theming ---
self._init_ui()
self._retranslate_ui()
self._apply_theme()

View File

@ -260,6 +260,8 @@ class DownloaderApp (QWidget ):
self.is_fetching_only = False
self.fetched_posts_for_download = []
self.is_ready_to_download_fetched = False
self.last_logged_filter_mode = None
self.last_logged_external_link_status = None
print(f" Known.txt will be loaded/saved at: {self.config_file}")
@ -406,7 +408,6 @@ class DownloaderApp (QWidget ):
try:
queue_logger(f" Downloading ({download_count+1}/{total_attachments}): '{filename_to_use}'...")
# --- FIX: Stream the download in chunks for responsive controls ---
response = requests.get(file_url, stream=True, timeout=60)
response.raise_for_status()
@ -2340,49 +2341,60 @@ class DownloaderApp (QWidget ):
self.log_signal.emit(f" ⚠️ Could not delete temp file '{filepath}': {e}")
self.session_temp_files = []
def update_external_links_setting (self ,checked ):
is_only_links_mode =self .radio_only_links and self .radio_only_links .isChecked ()
is_only_archives_mode =self .radio_only_archives and self .radio_only_archives .isChecked ()
def update_external_links_setting(self, checked, log_change=True):
is_only_links_mode = self.radio_only_links and self.radio_only_links.isChecked()
is_only_archives_mode = self.radio_only_archives and self.radio_only_archives.isChecked()
is_only_audio_mode = hasattr(self, 'radio_only_audio') and self.radio_only_audio.isChecked()
if is_only_links_mode or is_only_archives_mode :
if self .external_log_output :self .external_log_output .hide ()
if self .log_splitter :self .log_splitter .setSizes ([self .height (),0 ])
return
if is_only_links_mode or is_only_archives_mode or is_only_audio_mode:
if self.external_log_output: self.external_log_output.hide()
if self.log_splitter: self.log_splitter.setSizes([self.height(), 0])
return
self .show_external_links =checked
if checked :
if self .external_log_output :self .external_log_output .show ()
if self .log_splitter :self .log_splitter .setSizes ([self .height ()//2 ,self .height ()//2 ])
if self .main_log_output :self .main_log_output .setMinimumHeight (50 )
if self .external_log_output :self .external_log_output .setMinimumHeight (50 )
self.log_signal.emit(" External Links Log Enabled")
if self .external_log_output :
self .external_log_output .clear ()
self .external_log_output .append ("🔗 External Links Found:")
self ._try_process_next_external_link ()
else :
if self .external_log_output :self .external_log_output .hide ()
if self .log_splitter :self .log_splitter .setSizes ([self .height (),0 ])
if self .main_log_output :self .main_log_output .setMinimumHeight (0 )
if self .external_log_output :self .external_log_output .setMinimumHeight (0 )
if self .external_log_output :self .external_log_output .clear ()
self.log_signal.emit(" External Links Log Disabled")
self.show_external_links = checked
if log_change and self.last_logged_external_link_status != checked:
if checked:
self.log_signal.emit(" External Links Log Enabled")
else:
self.log_signal.emit(" External Links Log Disabled")
self.last_logged_external_link_status = checked
if checked:
if self.external_log_output: self.external_log_output.show()
if self.log_splitter: self.log_splitter.setSizes([self.height() // 2, self.height() // 2])
if self.main_log_output: self.main_log_output.setMinimumHeight(50)
if self.external_log_output: self.external_log_output.setMinimumHeight(50)
if self.external_log_output:
self.external_log_output.clear()
self.external_log_output.append("🔗 External Links Found:")
self._try_process_next_external_link()
else:
if self.external_log_output: self.external_log_output.hide()
if self.log_splitter: self.log_splitter.setSizes([self.height(), 0])
if self.main_log_output: self.main_log_output.setMinimumHeight(0)
if self.external_log_output: self.external_log_output.setMinimumHeight(0)
if self.external_log_output: self.external_log_output.clear()
def _handle_filter_mode_change(self, button, checked):
if not button or not checked:
return
new_mode_text = button.text()
if self.last_logged_filter_mode != new_mode_text:
self.log_signal.emit(f" Filter mode changed to: {new_mode_text}")
self.last_logged_filter_mode = new_mode_text
is_only_links = (button == self.radio_only_links)
if hasattr(self, 'use_multithreading_checkbox') and hasattr(self, 'thread_count_input'):
if is_only_links:
# When "Only Links" is selected, enable multithreading, set threads to 20, and lock the input.
self.use_multithreading_checkbox.setChecked(True)
self.thread_count_input.setText("20")
self.thread_count_input.setEnabled(False)
self.thread_count_label.setEnabled(False)
self.update_multithreading_label("20")
else:
# When another mode is selected, re-enable the input for user control.
is_multithreading_checked = self.use_multithreading_checkbox.isChecked()
self.thread_count_input.setEnabled(is_multithreading_checked)
self.thread_count_label.setEnabled(is_multithreading_checked)
@ -2448,38 +2460,11 @@ class DownloaderApp (QWidget ):
if is_only_links:
self.progress_log_label.setText("📜 Extracted Links Log:")
if self.external_log_output: self.external_log_output.hide()
if self.log_splitter: self.log_splitter.setSizes([self.height(), 0])
do_clear_log_in_filter_change = True
if self.mega_download_log_preserved_once and self.only_links_log_display_mode == LOG_DISPLAY_DOWNLOAD_PROGRESS:
do_clear_log_in_filter_change = False
if self.main_log_output and do_clear_log_in_filter_change:
self.log_signal.emit("INTERNAL: _handle_filter_mode_change - About to clear log.")
self.main_log_output.clear()
self.log_signal.emit("INTERNAL: _handle_filter_mode_change - Log cleared by _handle_filter_mode_change.")
if self.main_log_output: self.main_log_output.setMinimumHeight(0)
self.log_signal.emit(f" Filter mode changed to: {button.text()}")
self._try_process_next_external_link()
elif is_only_archives:
self.progress_log_label.setText("📜 Progress Log (Archives Only):")
if self.external_log_output: self.external_log_output.hide()
if self.log_splitter: self.log_splitter.setSizes([self.height(), 0])
if self.main_log_output: self.main_log_output.clear()
self.log_signal.emit(f" Filter mode changed to: {button.text()}")
elif is_only_audio:
self.progress_log_label.setText(self._tr("progress_log_label_text", "📜 Progress Log:") + f" ({self._tr('filter_audio_radio', '🎧 Only Audio')})")
if self.external_log_output: self.external_log_output.hide()
if self.log_splitter: self.log_splitter.setSizes([self.height(), 0])
if self.main_log_output: self.main_log_output.clear()
self.log_signal.emit(f" Filter mode changed to: {button.text()}")
else:
self.progress_log_label.setText(self._tr("progress_log_label_text", "📜 Progress Log:"))
self.update_external_links_setting(self.external_links_checkbox.isChecked() if self.external_links_checkbox else False)
self.log_signal.emit(f" Filter mode changed to: {button.text()}")
self.update_external_links_setting(self.external_links_checkbox.isChecked() if self.external_links_checkbox else False)
if is_only_links:
self._filter_links_log()
@ -2509,13 +2494,11 @@ class DownloaderApp (QWidget ):
self.update_custom_folder_visibility()
self.update_ui_for_manga_mode(self.manga_mode_checkbox.isChecked() if self.manga_mode_checkbox else False)
def _filter_links_log (self ):
if not (self .radio_only_links and self .radio_only_links .isChecked ()):return
search_term =self .link_search_input .text ().lower ().strip ()if self .link_search_input else ""
# This block handles the "Download Progress" view for Mega/Drive links and should be kept
if self .mega_download_log_preserved_once and self .only_links_log_display_mode ==LOG_DISPLAY_DOWNLOAD_PROGRESS :
self .log_signal .emit ("INTERNAL: _filter_links_log - Preserving Mega log.")
return
@ -3294,7 +3277,6 @@ class DownloaderApp (QWidget ):
self.manga_rename_toggle_button, self.manga_date_prefix_input,
self.multipart_toggle_button, self.custom_folder_input, self.custom_folder_label,
self.discord_scope_toggle_button
# --- FIX: REMOVED self.save_discord_as_pdf_btn from this list ---
]
enable_state = not is_specialized
@ -3335,14 +3317,10 @@ class DownloaderApp (QWidget ):
url_text = self.link_input.text().strip()
service, _, _ = extract_post_info(url_text)
# --- FIX: Use two separate flags for better control ---
# This is true for BOTH kemono.cr/discord and discord.com
is_any_discord_url = (service == 'discord')
# This is ONLY true for official discord.com
is_official_discord_url = 'discord.com' in url_text and is_any_discord_url
if is_official_discord_url:
# Show the token input only for the official site
self.remove_from_filename_label_widget.setText("🔑 Discord Token:")
self.remove_from_filename_input.setPlaceholderText("Enter your Discord Authorization Token here")
self.remove_from_filename_input.setEchoMode(QLineEdit.Password)
@ -3355,16 +3333,13 @@ class DownloaderApp (QWidget ):
self.remove_from_filename_input.setPlaceholderText(self._tr("remove_from_filename_input_placeholder_text", "e.g., patreon, HD"))
self.remove_from_filename_input.setEchoMode(QLineEdit.Normal)
# Handle other specialized downloaders (Bunkr, nhentai, etc.)
is_saint2 = 'saint2.su' in url_text or 'saint2.pk' in url_text
is_erome = 'erome.com' in url_text
is_specialized = service in ['bunkr', 'nhentai', 'hentai2read'] or is_saint2 or is_erome
self._set_ui_for_specialized_downloader(is_specialized)
# --- FIX: Show the Scope button for ANY Discord URL (Kemono or official) ---
self.discord_scope_toggle_button.setVisible(is_any_discord_url)
if hasattr(self, 'discord_message_limit_input'):
# Only show the message limit for the official site, as it's an API feature
self.discord_message_limit_input.setVisible(is_official_discord_url)
if is_any_discord_url:
@ -3705,16 +3680,12 @@ class DownloaderApp (QWidget ):
server_id=server_id, channel_id=channel_id, url=api_url, limit=message_limit, parent=self
)
# 2. Connect its signals to the main window's functions
self.download_thread.progress_signal.connect(self.handle_main_log)
self.download_thread.progress_label_signal.connect(self.progress_label.setText)
self.download_thread.finished_signal.connect(self.download_finished)
# --- FIX: Start the thread BEFORE updating the UI ---
# 3. Start the download process in the background
self.download_thread.start()
# 4. NOW, update the UI. The app knows a download is active.
self.set_ui_enabled(False)
self._update_button_states_and_connections()
@ -5185,14 +5156,11 @@ class DownloaderApp (QWidget ):
self ._handle_favorite_mode_toggle (is_fav_mode_active )
def _handle_pause_resume_action(self):
# --- FIX: Simplified and corrected the pause/resume logic ---
if not self._is_download_active():
return
# Toggle the main app's pause state tracker
self.is_paused = not self.is_paused
# Call the correct method on the thread based on the new state
if isinstance(self.download_thread, DiscordDownloadThread):
if self.is_paused:
self.download_thread.pause()
@ -5518,7 +5486,6 @@ class DownloaderApp (QWidget ):
self.log_signal.emit("✅ Download complete! Notification sound played.")
return
# --- FIX: Ensure confirm_title is defined before it is used ---
confirm_title = self._tr("action_confirmation_title", "Action After Download")
confirm_text = ""