mirror of
https://github.com/Yuvi9587/Kemono-Downloader.git
synced 2025-12-17 23:47:15 +00:00
Commit
This commit is contained in:
parent
b744e83f09
commit
0940bdb8dd
@ -13,14 +13,13 @@ from PyQt5 .QtCore import QObject ,pyqtSignal ,QThread ,QMutex ,QMutexLocker
|
|||||||
from urllib .parse import urlparse
|
from urllib .parse import urlparse
|
||||||
try :
|
try :
|
||||||
from mega import Mega
|
from mega import Mega
|
||||||
# Import download functions from drive.py
|
|
||||||
# Assuming drive.py is in the same directory
|
|
||||||
try :
|
try :
|
||||||
from drive import download_mega_file as drive_download_mega_file, \
|
from drive import download_mega_file as drive_download_mega_file ,download_gdrive_file ,download_dropbox_file
|
||||||
download_gdrive_file, download_dropbox_file
|
|
||||||
# To avoid confusion, we'll use drive_download_mega_file internally when calling from main
|
|
||||||
# and ensure this module exports it as download_mega_file for compatibility if needed,
|
|
||||||
# or main.py can be updated to call drive_download_mega_file.
|
|
||||||
except ImportError as drive_import_err :
|
except ImportError as drive_import_err :
|
||||||
print (f"ERROR importing from drive.py: {drive_import_err }. External drive downloads will fail.")
|
print (f"ERROR importing from drive.py: {drive_import_err }. External drive downloads will fail.")
|
||||||
except ImportError :
|
except ImportError :
|
||||||
@ -57,6 +56,7 @@ FILE_DOWNLOAD_STATUS_FAILED_PERMANENTLY_THIS_SESSION ="failed_permanent_session"
|
|||||||
fastapi_app =None
|
fastapi_app =None
|
||||||
KNOWN_NAMES =[]
|
KNOWN_NAMES =[]
|
||||||
MIN_SIZE_FOR_MULTIPART_DOWNLOAD =10 *1024 *1024
|
MIN_SIZE_FOR_MULTIPART_DOWNLOAD =10 *1024 *1024
|
||||||
|
GOFILE_GUEST_TOKEN =None
|
||||||
MAX_PARTS_FOR_MULTIPART_DOWNLOAD =15
|
MAX_PARTS_FOR_MULTIPART_DOWNLOAD =15
|
||||||
MAX_FILENAME_COMPONENT_LENGTH =150
|
MAX_FILENAME_COMPONENT_LENGTH =150
|
||||||
IMAGE_EXTENSIONS ={
|
IMAGE_EXTENSIONS ={
|
||||||
@ -704,6 +704,7 @@ def get_link_platform (url ):
|
|||||||
if 'mega.nz'in domain or 'mega.io'in domain :return 'mega'
|
if 'mega.nz'in domain or 'mega.io'in domain :return 'mega'
|
||||||
if 'dropbox.com'in domain :return 'dropbox'
|
if 'dropbox.com'in domain :return 'dropbox'
|
||||||
if 'patreon.com'in domain :return 'patreon'
|
if 'patreon.com'in domain :return 'patreon'
|
||||||
|
if 'gofile.io'in domain :return 'gofile'
|
||||||
if 'instagram.com'in domain :return 'instagram'
|
if 'instagram.com'in domain :return 'instagram'
|
||||||
if 'twitter.com'in domain or 'x.com'in domain :return 'twitter/x'
|
if 'twitter.com'in domain or 'x.com'in domain :return 'twitter/x'
|
||||||
if 'discord.gg'in domain or 'discord.com/invite'in domain :return 'discord invite'
|
if 'discord.gg'in domain or 'discord.com/invite'in domain :return 'discord invite'
|
||||||
@ -2133,7 +2134,7 @@ def download_mega_file (mega_link ,download_path =".",logger_func =print ):
|
|||||||
|
|
||||||
try :
|
try :
|
||||||
|
|
||||||
# Pre-flight check for link validity and attributes
|
|
||||||
logger_func (f" Verifying Mega link and fetching attributes: {mega_link }")
|
logger_func (f" Verifying Mega link and fetching attributes: {mega_link }")
|
||||||
file_attributes =m .get_public_url_info (mega_link )
|
file_attributes =m .get_public_url_info (mega_link )
|
||||||
|
|
||||||
@ -2141,12 +2142,12 @@ def download_mega_file (mega_link ,download_path =".",logger_func =print ):
|
|||||||
logger_func (f"❌ Error: Could not retrieve valid file information for the Mega link. Link might be invalid, expired, or a folder. Info received: {file_attributes }")
|
logger_func (f"❌ Error: Could not retrieve valid file information for the Mega link. Link might be invalid, expired, or a folder. Info received: {file_attributes }")
|
||||||
raise ValueError (f"Invalid or inaccessible Mega link. get_public_url_info returned: {file_attributes }")
|
raise ValueError (f"Invalid or inaccessible Mega link. get_public_url_info returned: {file_attributes }")
|
||||||
|
|
||||||
expected_filename = file_attributes.get('name') # Changed from 'n'
|
expected_filename =file_attributes .get ('name')
|
||||||
file_size = file_attributes.get('size') # Changed from 's'
|
file_size =file_attributes .get ('size')
|
||||||
|
|
||||||
if not expected_filename :
|
if not expected_filename :
|
||||||
logger_func(f"⚠️ Critical: File name ('name') not found in Mega link attributes. Attributes: {file_attributes}") # Updated log
|
logger_func (f"⚠️ Critical: File name ('name') not found in Mega link attributes. Attributes: {file_attributes }")
|
||||||
raise ValueError(f"File name ('name') not found in Mega link attributes: {file_attributes}") # Updated ValueError
|
raise ValueError (f"File name ('name') not found in Mega link attributes: {file_attributes }")
|
||||||
|
|
||||||
logger_func (f" Link verified. Expected filename: '{expected_filename }'. Size: {file_size if file_size is not None else 'Unknown'} bytes.")
|
logger_func (f" Link verified. Expected filename: '{expected_filename }'. Size: {file_size if file_size is not None else 'Unknown'} bytes.")
|
||||||
|
|
||||||
@ -2156,19 +2157,19 @@ def download_mega_file (mega_link ,download_path =".",logger_func =print ):
|
|||||||
|
|
||||||
logger_func (f"Starting download of '{expected_filename }' to '{download_path }'...")
|
logger_func (f"Starting download of '{expected_filename }' to '{download_path }'...")
|
||||||
|
|
||||||
# m.download_url returns a tuple (filepath, filename) on success for mega.py 1.0.8
|
|
||||||
download_result =m .download_url (mega_link ,dest_path =download_path ,dest_filename =None )
|
download_result =m .download_url (mega_link ,dest_path =download_path ,dest_filename =None )
|
||||||
|
|
||||||
if download_result and isinstance (download_result ,tuple )and len (download_result )==2 :
|
if download_result and isinstance (download_result ,tuple )and len (download_result )==2 :
|
||||||
saved_filepath ,saved_filename =download_result
|
saved_filepath ,saved_filename =download_result
|
||||||
# Ensure saved_filepath is an absolute path if dest_path was relative
|
|
||||||
if not os .path .isabs (saved_filepath )and dest_path :
|
if not os .path .isabs (saved_filepath )and dest_path :
|
||||||
saved_filepath =os .path .join (os .path .abspath (dest_path ),saved_filename )
|
saved_filepath =os .path .join (os .path .abspath (dest_path ),saved_filename )
|
||||||
|
|
||||||
logger_func (f"File downloaded successfully! Saved as: {saved_filepath }")
|
logger_func (f"File downloaded successfully! Saved as: {saved_filepath }")
|
||||||
if not os .path .exists (saved_filepath ):
|
if not os .path .exists (saved_filepath ):
|
||||||
logger_func (f"⚠️ Warning: mega.py reported success but file '{saved_filepath }' not found on disk.")
|
logger_func (f"⚠️ Warning: mega.py reported success but file '{saved_filepath }' not found on disk.")
|
||||||
# Optionally, verify filename if needed, though saved_filename should be correct
|
|
||||||
if saved_filename !=expected_filename :
|
if saved_filename !=expected_filename :
|
||||||
logger_func (f" Note: Saved filename '{saved_filename }' differs from initially expected '{expected_filename }'. This is usually fine.")
|
logger_func (f" Note: Saved filename '{saved_filename }' differs from initially expected '{expected_filename }'. This is usually fine.")
|
||||||
else :
|
else :
|
||||||
@ -2184,7 +2185,7 @@ def download_mega_file (mega_link ,download_path =".",logger_func =print ):
|
|||||||
except requests .exceptions .RequestException as e :
|
except requests .exceptions .RequestException as e :
|
||||||
logger_func (f"Error during request to Mega (network issue, etc.): {e }")
|
logger_func (f"Error during request to Mega (network issue, etc.): {e }")
|
||||||
raise
|
raise
|
||||||
except ValueError as ve: # Catch our custom ValueError from pre-flight
|
except ValueError as ve :
|
||||||
logger_func (f"ValueError during Mega processing (likely invalid link): {ve }")
|
logger_func (f"ValueError during Mega processing (likely invalid link): {ve }")
|
||||||
raise
|
raise
|
||||||
except Exception as e :
|
except Exception as e :
|
||||||
|
|||||||
147
main.py
147
main.py
@ -157,16 +157,16 @@ class DownloadExtractedLinksDialog(QDialog):
|
|||||||
self .links_data =links_data
|
self .links_data =links_data
|
||||||
self .setWindowTitle ("Download Selected External Links")
|
self .setWindowTitle ("Download Selected External Links")
|
||||||
|
|
||||||
# Adjust dialog size relative to parent
|
|
||||||
if parent :
|
if parent :
|
||||||
parent_width =parent .width ()
|
parent_width =parent .width ()
|
||||||
parent_height =parent .height ()
|
parent_height =parent .height ()
|
||||||
dialog_width = int(parent_width * 0.6) # 60% of parent width
|
dialog_width =int (parent_width *0.6 )
|
||||||
dialog_height = int(parent_height * 0.7) # 70% of parent height
|
dialog_height =int (parent_height *0.7 )
|
||||||
min_w, min_h = 500, 400 # Keep a reasonable minimum
|
min_w ,min_h =500 ,400
|
||||||
self .resize (max (dialog_width ,min_w ),max (dialog_height ,min_h ))
|
self .resize (max (dialog_width ,min_w ),max (dialog_height ,min_h ))
|
||||||
else :
|
else :
|
||||||
self.setMinimumSize(500, 400) # Fallback if no parent
|
self .setMinimumSize (500 ,400 )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -184,20 +184,20 @@ class DownloadExtractedLinksDialog(QDialog):
|
|||||||
post_title_for_group =link_info_item .get ('title','Untitled Post')
|
post_title_for_group =link_info_item .get ('title','Untitled Post')
|
||||||
grouped_links [post_title_for_group ].append (link_info_item )
|
grouped_links [post_title_for_group ].append (link_info_item )
|
||||||
|
|
||||||
# Sort by post title for consistent order
|
|
||||||
sorted_post_titles =sorted (grouped_links .keys (),key =lambda x :x .lower ())
|
sorted_post_titles =sorted (grouped_links .keys (),key =lambda x :x .lower ())
|
||||||
|
|
||||||
for post_title_key in sorted_post_titles :
|
for post_title_key in sorted_post_titles :
|
||||||
# Add header for post_title
|
|
||||||
header_item =QListWidgetItem (f"{post_title_key }")
|
header_item =QListWidgetItem (f"{post_title_key }")
|
||||||
header_item.setFlags(Qt.NoItemFlags) # Not selectable, not checkable
|
header_item .setFlags (Qt .NoItemFlags )
|
||||||
font =header_item .font ()
|
font =header_item .font ()
|
||||||
font .setBold (True )
|
font .setBold (True )
|
||||||
font.setPointSize(font.pointSize() + 1) # Slightly larger
|
font .setPointSize (font .pointSize ()+1 )
|
||||||
header_item .setFont (font )
|
header_item .setFont (font )
|
||||||
if parent and hasattr (parent ,'current_theme')and parent .current_theme =="dark":
|
if parent and hasattr (parent ,'current_theme')and parent .current_theme =="dark":
|
||||||
header_item .setForeground (Qt .cyan )
|
header_item .setForeground (Qt .cyan )
|
||||||
else: # Light theme or no theme info
|
else :
|
||||||
header_item .setForeground (Qt .blue )
|
header_item .setForeground (Qt .blue )
|
||||||
self .links_list_widget .addItem (header_item )
|
self .links_list_widget .addItem (header_item )
|
||||||
|
|
||||||
@ -210,8 +210,8 @@ class DownloadExtractedLinksDialog(QDialog):
|
|||||||
item .setCheckState (Qt .Checked )
|
item .setCheckState (Qt .Checked )
|
||||||
self .links_list_widget .addItem (item )
|
self .links_list_widget .addItem (item )
|
||||||
|
|
||||||
# Add a little space after each group, or a separator item if preferred
|
|
||||||
# self.links_list_widget.addItem(QListWidgetItem("")) # Simple spacer
|
|
||||||
|
|
||||||
layout .addWidget (self .links_list_widget )
|
layout .addWidget (self .links_list_widget )
|
||||||
|
|
||||||
@ -241,17 +241,15 @@ class DownloadExtractedLinksDialog(QDialog):
|
|||||||
def _set_all_items_checked (self ,check_state ):
|
def _set_all_items_checked (self ,check_state ):
|
||||||
for i in range (self .links_list_widget .count ()):
|
for i in range (self .links_list_widget .count ()):
|
||||||
item =self .links_list_widget .item (i )
|
item =self .links_list_widget .item (i )
|
||||||
if item.flags() & Qt.ItemIsUserCheckable: # Only operate on checkable items
|
if item .flags ()&Qt .ItemIsUserCheckable :
|
||||||
item .setCheckState (check_state )
|
item .setCheckState (check_state )
|
||||||
|
|
||||||
def _handle_download_selected (self ):
|
def _handle_download_selected (self ):
|
||||||
selected_links =[]
|
selected_links =[]
|
||||||
for i in range (self .links_list_widget .count ()):
|
for i in range (self .links_list_widget .count ()):
|
||||||
item =self .links_list_widget .item (i )
|
item =self .links_list_widget .item (i )
|
||||||
# Ensure item is checkable, actually checked, and has data (is a link item)
|
|
||||||
if item.flags() & Qt.ItemIsUserCheckable and \
|
if item .flags ()&Qt .ItemIsUserCheckable and item .checkState ()==Qt .Checked and item .data (Qt .UserRole )is not None :
|
||||||
item.checkState() == Qt.Checked and \
|
|
||||||
item.data(Qt.UserRole) is not None:
|
|
||||||
selected_links .append (item .data (Qt .UserRole ))
|
selected_links .append (item .data (Qt .UserRole ))
|
||||||
if selected_links :
|
if selected_links :
|
||||||
self .download_requested .emit (selected_links )
|
self .download_requested .emit (selected_links )
|
||||||
@ -2351,13 +2349,13 @@ class ExternalLinkDownloadThread(QThread):
|
|||||||
platform =task_info .get ('platform','unknown').lower ()
|
platform =task_info .get ('platform','unknown').lower ()
|
||||||
full_mega_url =task_info ['url']
|
full_mega_url =task_info ['url']
|
||||||
post_title =task_info ['title']
|
post_title =task_info ['title']
|
||||||
key = task_info.get('key', '') # Primarily for Mega
|
key =task_info .get ('key','')
|
||||||
|
|
||||||
self .progress_signal .emit (f"Download ({i +1 }/{len (self .tasks )}): Starting '{post_title }' ({platform .upper ()}) from {full_mega_url }")
|
self .progress_signal .emit (f"Download ({i +1 }/{len (self .tasks )}): Starting '{post_title }' ({platform .upper ()}) from {full_mega_url }")
|
||||||
|
|
||||||
try :
|
try :
|
||||||
if platform =='mega':
|
if platform =='mega':
|
||||||
# Ensure key is part of the URL for mega.py
|
|
||||||
if key :
|
if key :
|
||||||
parsed_original_url =urlparse (full_mega_url )
|
parsed_original_url =urlparse (full_mega_url )
|
||||||
if key not in parsed_original_url .fragment :
|
if key not in parsed_original_url .fragment :
|
||||||
@ -2366,7 +2364,7 @@ class ExternalLinkDownloadThread(QThread):
|
|||||||
self .progress_signal .emit (f" Adjusted Mega URL with key: {full_mega_url_with_key }")
|
self .progress_signal .emit (f" Adjusted Mega URL with key: {full_mega_url_with_key }")
|
||||||
else :
|
else :
|
||||||
full_mega_url_with_key =full_mega_url
|
full_mega_url_with_key =full_mega_url
|
||||||
else: # No key provided, use URL as is (might fail if key is required and not in fragment)
|
else :
|
||||||
full_mega_url_with_key =full_mega_url
|
full_mega_url_with_key =full_mega_url
|
||||||
drive_download_mega_file (full_mega_url_with_key ,self .download_base_path ,logger_func =self .parent_logger_func )
|
drive_download_mega_file (full_mega_url_with_key ,self .download_base_path ,logger_func =self .parent_logger_func )
|
||||||
elif platform =='google drive':
|
elif platform =='google drive':
|
||||||
@ -2507,7 +2505,7 @@ class DownloaderApp (QWidget ):
|
|||||||
self .char_filter_scope =CHAR_SCOPE_TITLE
|
self .char_filter_scope =CHAR_SCOPE_TITLE
|
||||||
self .manga_filename_style =self .settings .value (MANGA_FILENAME_STYLE_KEY ,STYLE_POST_TITLE ,type =str )
|
self .manga_filename_style =self .settings .value (MANGA_FILENAME_STYLE_KEY ,STYLE_POST_TITLE ,type =str )
|
||||||
self .current_theme =self .settings .value (THEME_KEY ,"dark",type =str )
|
self .current_theme =self .settings .value (THEME_KEY ,"dark",type =str )
|
||||||
self .only_links_log_display_mode = LOG_DISPLAY_LINKS # New state variable
|
self .only_links_log_display_mode =LOG_DISPLAY_LINKS
|
||||||
self .mega_download_log_preserved_once =False
|
self .mega_download_log_preserved_once =False
|
||||||
self .allow_multipart_download_setting =False
|
self .allow_multipart_download_setting =False
|
||||||
self .use_cookie_setting =False
|
self .use_cookie_setting =False
|
||||||
@ -3445,7 +3443,7 @@ class DownloaderApp (QWidget ):
|
|||||||
self .log_display_mode_toggle_button .setToolTip ("Toggle log display mode for 'Only Links'")
|
self .log_display_mode_toggle_button .setToolTip ("Toggle log display mode for 'Only Links'")
|
||||||
self .log_display_mode_toggle_button .setFixedWidth (120 )
|
self .log_display_mode_toggle_button .setFixedWidth (120 )
|
||||||
self .log_display_mode_toggle_button .setStyleSheet ("padding: 4px 8px; margin-top: 5px;")
|
self .log_display_mode_toggle_button .setStyleSheet ("padding: 4px 8px; margin-top: 5px;")
|
||||||
self.log_display_mode_toggle_button.setVisible(False) # Initially hidden
|
self .log_display_mode_toggle_button .setVisible (False )
|
||||||
export_button_layout .addWidget (self .log_display_mode_toggle_button )
|
export_button_layout .addWidget (self .log_display_mode_toggle_button )
|
||||||
right_layout .addLayout (export_button_layout )
|
right_layout .addLayout (export_button_layout )
|
||||||
|
|
||||||
@ -3545,12 +3543,11 @@ class DownloaderApp (QWidget ):
|
|||||||
self .log_signal .emit ("ℹ️ No links selected for download from dialog.")
|
self .log_signal .emit ("ℹ️ No links selected for download from dialog.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Preserve log logic (might need adjustment if GDrive/Dropbox have different log styles)
|
|
||||||
if self.radio_only_links and self.radio_only_links.isChecked() and \
|
if self .radio_only_links and self .radio_only_links .isChecked ()and self .only_links_log_display_mode ==LOG_DISPLAY_DOWNLOAD_PROGRESS :
|
||||||
self.only_links_log_display_mode == LOG_DISPLAY_DOWNLOAD_PROGRESS:
|
|
||||||
self .main_log_output .clear ()
|
self .main_log_output .clear ()
|
||||||
self .log_signal .emit ("ℹ️ Displaying Mega download progress (extracted links hidden)...")
|
self .log_signal .emit ("ℹ️ Displaying Mega download progress (extracted links hidden)...")
|
||||||
self.mega_download_log_preserved_once = False # Ensure no append logic triggers
|
self .mega_download_log_preserved_once =False
|
||||||
|
|
||||||
current_main_dir =self .dir_input .text ().strip ()
|
current_main_dir =self .dir_input .text ().strip ()
|
||||||
download_dir_for_mega =""
|
download_dir_for_mega =""
|
||||||
@ -3572,7 +3569,7 @@ class DownloaderApp (QWidget ):
|
|||||||
self ,
|
self ,
|
||||||
"Select Download Folder for Mega Links",
|
"Select Download Folder for Mega Links",
|
||||||
suggestion_path ,
|
suggestion_path ,
|
||||||
options=QFileDialog.ShowDirsOnly | QFileDialog.DontUseNativeDialog # Added DontUseNativeDialog for consistency
|
options =QFileDialog .ShowDirsOnly |QFileDialog .DontUseNativeDialog
|
||||||
)
|
)
|
||||||
|
|
||||||
if not chosen_dir :
|
if not chosen_dir :
|
||||||
@ -3586,7 +3583,7 @@ class DownloaderApp (QWidget ):
|
|||||||
self .log_signal .emit (f"❌ Critical Error: Selected download directory '{download_dir_for_mega }' does not exist.")
|
self .log_signal .emit (f"❌ Critical Error: Selected download directory '{download_dir_for_mega }' does not exist.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# selected_links_info already contains dicts with 'url', 'title', 'platform', 'key'
|
|
||||||
tasks_for_thread =selected_links_info
|
tasks_for_thread =selected_links_info
|
||||||
|
|
||||||
if self .external_link_download_thread and self .external_link_download_thread .isRunning ():
|
if self .external_link_download_thread and self .external_link_download_thread .isRunning ():
|
||||||
@ -3600,7 +3597,7 @@ class DownloaderApp (QWidget ):
|
|||||||
self
|
self
|
||||||
)
|
)
|
||||||
self .external_link_download_thread .finished .connect (self ._on_external_link_download_thread_finished )
|
self .external_link_download_thread .finished .connect (self ._on_external_link_download_thread_finished )
|
||||||
# Connect progress_signal if ExternalLinkDownloadThread has it (it does)
|
|
||||||
self .external_link_download_thread .progress_signal .connect (self .handle_main_log )
|
self .external_link_download_thread .progress_signal .connect (self .handle_main_log )
|
||||||
self .external_link_download_thread .file_complete_signal .connect (self ._on_single_external_file_complete )
|
self .external_link_download_thread .file_complete_signal .connect (self ._on_single_external_file_complete )
|
||||||
|
|
||||||
@ -3614,29 +3611,29 @@ class DownloaderApp (QWidget ):
|
|||||||
self .log_signal .emit ("✅ External link download thread finished.")
|
self .log_signal .emit ("✅ External link download thread finished.")
|
||||||
self .progress_label .setText ("External link downloads complete. Ready for new task.")
|
self .progress_label .setText ("External link downloads complete. Ready for new task.")
|
||||||
|
|
||||||
self.mega_download_log_preserved_once = True # Mark that a mega download just finished
|
self .mega_download_log_preserved_once =True
|
||||||
self.log_signal.emit("INTERNAL: mega_download_log_preserved_once SET to True.") # Debug
|
self .log_signal .emit ("INTERNAL: mega_download_log_preserved_once SET to True.")
|
||||||
|
|
||||||
if self .radio_only_links and self .radio_only_links .isChecked ():
|
if self .radio_only_links and self .radio_only_links .isChecked ():
|
||||||
self .log_signal .emit (HTML_PREFIX +"<br><hr>--- End of Mega Download Log ---<br>")
|
self .log_signal .emit (HTML_PREFIX +"<br><hr>--- End of Mega Download Log ---<br>")
|
||||||
# The _filter_links_log will be called by set_ui_enabled -> _handle_filter_mode_change
|
|
||||||
# No need to call it directly here as it might interfere with the flag.
|
|
||||||
|
|
||||||
self .set_ui_enabled (True ) # Enable UI after potential log update
|
|
||||||
|
|
||||||
# Reset the flag AFTER the UI update cycle (triggered by set_ui_enabled) is complete.
|
|
||||||
# This ensures the flag protects the log content throughout the entire UI update.
|
self .set_ui_enabled (True )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if self .mega_download_log_preserved_once :
|
if self .mega_download_log_preserved_once :
|
||||||
self .mega_download_log_preserved_once =False
|
self .mega_download_log_preserved_once =False
|
||||||
self.log_signal.emit("INTERNAL: mega_download_log_preserved_once RESET to False.") # Debug
|
self .log_signal .emit ("INTERNAL: mega_download_log_preserved_once RESET to False.")
|
||||||
|
|
||||||
if self .external_link_download_thread :
|
if self .external_link_download_thread :
|
||||||
self .external_link_download_thread .deleteLater ()
|
self .external_link_download_thread .deleteLater ()
|
||||||
self .external_link_download_thread =None
|
self .external_link_download_thread =None
|
||||||
|
|
||||||
def _on_single_external_file_complete (self ,url ,success ):
|
def _on_single_external_file_complete (self ,url ,success ):
|
||||||
# This is a new slot to potentially update progress if needed per file
|
|
||||||
# For now, the thread's own progress_signal handles detailed logging.
|
|
||||||
pass
|
pass
|
||||||
def _show_future_settings_dialog (self ):
|
def _show_future_settings_dialog (self ):
|
||||||
"""Shows the placeholder dialog for future settings."""
|
"""Shows the placeholder dialog for future settings."""
|
||||||
@ -3871,8 +3868,8 @@ class DownloaderApp (QWidget ):
|
|||||||
link_data =(post_title ,link_text ,link_url ,platform ,decryption_key )
|
link_data =(post_title ,link_text ,link_url ,platform ,decryption_key )
|
||||||
self .external_link_queue .append (link_data )
|
self .external_link_queue .append (link_data )
|
||||||
if self .radio_only_links and self .radio_only_links .isChecked ():
|
if self .radio_only_links and self .radio_only_links .isChecked ():
|
||||||
self .extracted_links_cache .append (link_data ) # Keep for now, might be redundant with below
|
self .extracted_links_cache .append (link_data )
|
||||||
self ._update_download_extracted_links_button_state() # Update button if in mode
|
self ._update_download_extracted_links_button_state ()
|
||||||
|
|
||||||
is_only_links_mode =self .radio_only_links and self .radio_only_links .isChecked ()
|
is_only_links_mode =self .radio_only_links and self .radio_only_links .isChecked ()
|
||||||
should_display_in_external_log =self .show_external_links and not is_only_links_mode
|
should_display_in_external_log =self .show_external_links and not is_only_links_mode
|
||||||
@ -3883,8 +3880,8 @@ class DownloaderApp (QWidget ):
|
|||||||
QTimer .singleShot (0 ,self ._try_process_next_external_link )
|
QTimer .singleShot (0 ,self ._try_process_next_external_link )
|
||||||
return
|
return
|
||||||
|
|
||||||
# Always add to extracted_links_cache so it's available if user switches mode later
|
|
||||||
if link_data not in self.extracted_links_cache: # Avoid duplicates if already added above
|
if link_data not in self .extracted_links_cache :
|
||||||
self .extracted_links_cache .append (link_data )
|
self .extracted_links_cache .append (link_data )
|
||||||
|
|
||||||
def _try_process_next_external_link (self ):
|
def _try_process_next_external_link (self ):
|
||||||
@ -3916,7 +3913,7 @@ class DownloaderApp (QWidget ):
|
|||||||
post_title ,link_text ,link_url ,platform ,decryption_key =link_data
|
post_title ,link_text ,link_url ,platform ,decryption_key =link_data
|
||||||
is_only_links_mode =self .radio_only_links and self .radio_only_links .isChecked ()
|
is_only_links_mode =self .radio_only_links and self .radio_only_links .isChecked ()
|
||||||
|
|
||||||
max_link_text_len =50 # Consistent with _filter_links_log
|
max_link_text_len =50
|
||||||
display_text =(link_text [:max_link_text_len ].strip ()+"..."
|
display_text =(link_text [:max_link_text_len ].strip ()+"..."
|
||||||
if len (link_text )>max_link_text_len else link_text .strip ())
|
if len (link_text )>max_link_text_len else link_text .strip ())
|
||||||
formatted_link_info =f"{display_text } - {link_url } - {platform }"
|
formatted_link_info =f"{display_text } - {link_url } - {platform }"
|
||||||
@ -3932,10 +3929,10 @@ class DownloaderApp (QWidget ):
|
|||||||
title_html =f'<b style="color: #87CEEB;">{html .escape (post_title )}</b><br>'
|
title_html =f'<b style="color: #87CEEB;">{html .escape (post_title )}</b><br>'
|
||||||
self .log_signal .emit (HTML_PREFIX +title_html )
|
self .log_signal .emit (HTML_PREFIX +title_html )
|
||||||
self ._current_link_post_title =post_title
|
self ._current_link_post_title =post_title
|
||||||
# Emit plain text link info; handle_main_log will .append() it
|
|
||||||
self .log_signal .emit (formatted_link_info )
|
self .log_signal .emit (formatted_link_info )
|
||||||
elif self .show_external_links :
|
elif self .show_external_links :
|
||||||
separator ="-"*45 # This separator is for _append_to_external_log's internal use if it were to use it, not for HTML
|
separator ="-"*45
|
||||||
self ._append_to_external_log (formatted_link_info ,separator )
|
self ._append_to_external_log (formatted_link_info ,separator )
|
||||||
|
|
||||||
self ._is_processing_external_link_queue =False
|
self ._is_processing_external_link_queue =False
|
||||||
@ -4105,18 +4102,17 @@ class DownloaderApp (QWidget ):
|
|||||||
if is_only_links :
|
if is_only_links :
|
||||||
self .progress_log_label .setText ("📜 Extracted Links Log:")
|
self .progress_log_label .setText ("📜 Extracted Links Log:")
|
||||||
if self .external_log_output :self .external_log_output .hide ()
|
if self .external_log_output :self .external_log_output .hide ()
|
||||||
if self .log_splitter :self .log_splitter .setSizes ([self .height (),0 ]) # type: ignore
|
if self .log_splitter :self .log_splitter .setSizes ([self .height (),0 ])
|
||||||
|
|
||||||
|
|
||||||
# Conditional clear to preserve Mega download log in progress view
|
|
||||||
do_clear_log_in_filter_change =True
|
do_clear_log_in_filter_change =True
|
||||||
if self.mega_download_log_preserved_once and \
|
if self .mega_download_log_preserved_once and self .only_links_log_display_mode ==LOG_DISPLAY_DOWNLOAD_PROGRESS :
|
||||||
self.only_links_log_display_mode == LOG_DISPLAY_DOWNLOAD_PROGRESS:
|
|
||||||
do_clear_log_in_filter_change =False
|
do_clear_log_in_filter_change =False
|
||||||
|
|
||||||
if self .main_log_output and do_clear_log_in_filter_change :
|
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.") # Debug
|
self .log_signal .emit ("INTERNAL: _handle_filter_mode_change - About to clear log.")
|
||||||
self .main_log_output .clear ()
|
self .main_log_output .clear ()
|
||||||
self.log_signal.emit("INTERNAL: _handle_filter_mode_change - Log cleared by _handle_filter_mode_change.") # Debug
|
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 )
|
if self .main_log_output :self .main_log_output .setMinimumHeight (0 )
|
||||||
self .log_signal .emit ("="*20 +" Mode changed to: Only Links "+"="*20 )
|
self .log_signal .emit ("="*20 +" Mode changed to: Only Links "+"="*20 )
|
||||||
@ -4138,7 +4134,7 @@ class DownloaderApp (QWidget ):
|
|||||||
self .update_external_links_setting (self .external_links_checkbox .isChecked ()if self .external_links_checkbox else False )
|
self .update_external_links_setting (self .external_links_checkbox .isChecked ()if self .external_links_checkbox else False )
|
||||||
self .log_signal .emit (f"="*20 +f" Mode changed to: {filter_mode_text } "+"="*20 )
|
self .log_signal .emit (f"="*20 +f" Mode changed to: {filter_mode_text } "+"="*20 )
|
||||||
|
|
||||||
# Call _filter_links_log AFTER potential clear and other UI updates for "Only Links"
|
|
||||||
if is_only_links :
|
if is_only_links :
|
||||||
self ._filter_links_log ()
|
self ._filter_links_log ()
|
||||||
|
|
||||||
@ -4174,15 +4170,14 @@ class DownloaderApp (QWidget ):
|
|||||||
|
|
||||||
search_term =self .link_search_input .text ().lower ().strip ()if self .link_search_input else ""
|
search_term =self .link_search_input .text ().lower ().strip ()if self .link_search_input else ""
|
||||||
|
|
||||||
if self.mega_download_log_preserved_once and \
|
if self .mega_download_log_preserved_once and self .only_links_log_display_mode ==LOG_DISPLAY_DOWNLOAD_PROGRESS :
|
||||||
self.only_links_log_display_mode == LOG_DISPLAY_DOWNLOAD_PROGRESS:
|
|
||||||
# Mega download just finished, in progress view. Preserve the log.
|
|
||||||
# Do nothing to the log content itself.
|
|
||||||
self .log_signal .emit ("INTERNAL: _filter_links_log - Preserving Mega log (due to mega_download_log_preserved_once).")
|
self .log_signal .emit ("INTERNAL: _filter_links_log - Preserving Mega log (due to mega_download_log_preserved_once).")
|
||||||
elif self .only_links_log_display_mode ==LOG_DISPLAY_DOWNLOAD_PROGRESS :
|
elif self .only_links_log_display_mode ==LOG_DISPLAY_DOWNLOAD_PROGRESS :
|
||||||
# This is when 'Progress View' is selected for the 'Only Links' log scope,
|
|
||||||
# AND a Mega download hasn't *just* finished (mega_download_log_preserved_once is False).
|
|
||||||
# We should clear the log and show the placeholder message.
|
|
||||||
self .log_signal .emit ("INTERNAL: _filter_links_log - In Progress View. Clearing for placeholder.")
|
self .log_signal .emit ("INTERNAL: _filter_links_log - In Progress View. Clearing for placeholder.")
|
||||||
if self .main_log_output :self .main_log_output .clear ()
|
if self .main_log_output :self .main_log_output .clear ()
|
||||||
self .log_signal .emit ("INTERNAL: _filter_links_log - Cleared for progress placeholder.")
|
self .log_signal .emit ("INTERNAL: _filter_links_log - Cleared for progress placeholder.")
|
||||||
@ -4190,11 +4185,11 @@ class DownloaderApp (QWidget ):
|
|||||||
" Perform a Mega download to see its progress here, or switch back to 🔗 view.")
|
" Perform a Mega download to see its progress here, or switch back to 🔗 view.")
|
||||||
self .log_signal .emit ("INTERNAL: _filter_links_log - Placeholder message emitted.")
|
self .log_signal .emit ("INTERNAL: _filter_links_log - Placeholder message emitted.")
|
||||||
|
|
||||||
else: # self.only_links_log_display_mode == LOG_DISPLAY_LINKS
|
else :
|
||||||
# In links view. Clear and show the (filtered) links.
|
|
||||||
self.log_signal.emit("INTERNAL: _filter_links_log - In links view branch. About to clear.") # Debug
|
self .log_signal .emit ("INTERNAL: _filter_links_log - In links view branch. About to clear.")
|
||||||
if self .main_log_output :self .main_log_output .clear ()
|
if self .main_log_output :self .main_log_output .clear ()
|
||||||
self.log_signal.emit("INTERNAL: _filter_links_log - Cleared for links view.") # Debug
|
self .log_signal .emit ("INTERNAL: _filter_links_log - Cleared for links view.")
|
||||||
|
|
||||||
current_title_for_display =None
|
current_title_for_display =None
|
||||||
any_links_displayed_this_call =False
|
any_links_displayed_this_call =False
|
||||||
@ -4205,13 +4200,13 @@ class DownloaderApp (QWidget ):
|
|||||||
search_term in link_text .lower ()or
|
search_term in link_text .lower ()or
|
||||||
search_term in link_url .lower ()or
|
search_term in link_url .lower ()or
|
||||||
search_term in platform .lower ()or
|
search_term in platform .lower ()or
|
||||||
(decryption_key and search_term in decryption_key.lower())) # type: ignore
|
(decryption_key and search_term in decryption_key .lower ()))
|
||||||
if not matches_search :
|
if not matches_search :
|
||||||
continue
|
continue
|
||||||
|
|
||||||
any_links_displayed_this_call =True
|
any_links_displayed_this_call =True
|
||||||
if post_title !=current_title_for_display :
|
if post_title !=current_title_for_display :
|
||||||
if current_title_for_display is not None : # Add separator only if it's not the very first title
|
if current_title_for_display is not None :
|
||||||
if self .main_log_output :self .main_log_output .insertHtml (separator_html )
|
if self .main_log_output :self .main_log_output .insertHtml (separator_html )
|
||||||
|
|
||||||
title_html =f'<b style="color: #87CEEB;">{html .escape (post_title )}</b><br>'
|
title_html =f'<b style="color: #87CEEB;">{html .escape (post_title )}</b><br>'
|
||||||
@ -4220,19 +4215,19 @@ class DownloaderApp (QWidget ):
|
|||||||
|
|
||||||
max_link_text_len =50
|
max_link_text_len =50
|
||||||
display_text =(link_text [:max_link_text_len ].strip ()+"..."if len (link_text )>max_link_text_len else link_text .strip ())
|
display_text =(link_text [:max_link_text_len ].strip ()+"..."if len (link_text )>max_link_text_len else link_text .strip ())
|
||||||
# Construct plain text link line
|
|
||||||
plain_link_info_line =f"{display_text } - {link_url } - {platform }"
|
plain_link_info_line =f"{display_text } - {link_url } - {platform }"
|
||||||
if decryption_key :
|
if decryption_key :
|
||||||
plain_link_info_line +=f" (Decryption Key: {decryption_key })"
|
plain_link_info_line +=f" (Decryption Key: {decryption_key })"
|
||||||
if self .main_log_output :
|
if self .main_log_output :
|
||||||
self.main_log_output.append(plain_link_info_line) # Appending plain text for default styling & spacing
|
self .main_log_output .append (plain_link_info_line )
|
||||||
|
|
||||||
if any_links_displayed_this_call :
|
if any_links_displayed_this_call :
|
||||||
if self.main_log_output: self.main_log_output.append("") # Extra blank line at the end
|
if self .main_log_output :self .main_log_output .append ("")
|
||||||
elif not search_term and self.main_log_output: # No links in cache at all
|
elif not search_term and self .main_log_output :
|
||||||
self .log_signal .emit (" (No links extracted yet or all filtered out in links view)")
|
self .log_signal .emit (" (No links extracted yet or all filtered out in links view)")
|
||||||
|
|
||||||
# self.mega_download_log_preserved_once is now reset in _on_mega_download_thread_finished
|
|
||||||
if self .main_log_output :self .main_log_output .verticalScrollBar ().setValue (self .main_log_output .verticalScrollBar ().maximum ())
|
if self .main_log_output :self .main_log_output .verticalScrollBar ().setValue (self .main_log_output .verticalScrollBar ().maximum ())
|
||||||
|
|
||||||
|
|
||||||
@ -5982,7 +5977,7 @@ class DownloaderApp (QWidget ):
|
|||||||
self .favorite_download_queue .clear ()
|
self .favorite_download_queue .clear ()
|
||||||
self .is_processing_favorites_queue =False
|
self .is_processing_favorites_queue =False
|
||||||
|
|
||||||
self.only_links_log_display_mode = LOG_DISPLAY_LINKS # Reset on soft reset too
|
self .only_links_log_display_mode =LOG_DISPLAY_LINKS
|
||||||
|
|
||||||
if hasattr (self ,'link_input'):
|
if hasattr (self ,'link_input'):
|
||||||
if self .download_extracted_links_button :
|
if self .download_extracted_links_button :
|
||||||
@ -6012,7 +6007,7 @@ class DownloaderApp (QWidget ):
|
|||||||
"After Mega download, Mega log is shown THEN links are appended.\n"
|
"After Mega download, Mega log is shown THEN links are appended.\n"
|
||||||
"Click to switch to 'Download Progress View'."
|
"Click to switch to 'Download Progress View'."
|
||||||
)
|
)
|
||||||
else: # LOG_DISPLAY_DOWNLOAD_PROGRESS
|
else :
|
||||||
self .log_display_mode_toggle_button .setText ("⬇️ Progress View")
|
self .log_display_mode_toggle_button .setText ("⬇️ Progress View")
|
||||||
self .log_display_mode_toggle_button .setToolTip (
|
self .log_display_mode_toggle_button .setToolTip (
|
||||||
"Current View: Mega Download Progress.\n"
|
"Current View: Mega Download Progress.\n"
|
||||||
@ -6023,13 +6018,13 @@ class DownloaderApp (QWidget ):
|
|||||||
def _toggle_log_display_mode (self ):
|
def _toggle_log_display_mode (self ):
|
||||||
self .only_links_log_display_mode =LOG_DISPLAY_DOWNLOAD_PROGRESS if self .only_links_log_display_mode ==LOG_DISPLAY_LINKS else LOG_DISPLAY_LINKS
|
self .only_links_log_display_mode =LOG_DISPLAY_DOWNLOAD_PROGRESS if self .only_links_log_display_mode ==LOG_DISPLAY_LINKS else LOG_DISPLAY_LINKS
|
||||||
self ._update_log_display_mode_button_text ()
|
self ._update_log_display_mode_button_text ()
|
||||||
self._filter_links_log() # Refresh the log based on the new mode
|
self ._filter_links_log ()
|
||||||
|
|
||||||
def cancel_download_button_action (self ):
|
def cancel_download_button_action (self ):
|
||||||
if not self .cancel_btn .isEnabled ()and not self .cancellation_event .is_set ():self .log_signal .emit ("ℹ️ No active download to cancel or already cancelling.");return
|
if not self .cancel_btn .isEnabled ()and not self .cancellation_event .is_set ():self .log_signal .emit ("ℹ️ No active download to cancel or already cancelling.");return
|
||||||
self .log_signal .emit ("⚠️ Requesting cancellation of download process (soft reset)...")
|
self .log_signal .emit ("⚠️ Requesting cancellation of download process (soft reset)...")
|
||||||
|
|
||||||
if self .mega_download_thread and self .mega_download_thread .isRunning ():
|
if self .external_link_download_thread and self .external_link_download_thread .isRunning ():
|
||||||
self .log_signal .emit (" Cancelling active External Link download thread...")
|
self .log_signal .emit (" Cancelling active External Link download thread...")
|
||||||
self .external_link_download_thread .cancel ()
|
self .external_link_download_thread .cancel ()
|
||||||
|
|
||||||
@ -6369,7 +6364,7 @@ class DownloaderApp (QWidget ):
|
|||||||
self .already_logged_bold_key_terms .clear ()
|
self .already_logged_bold_key_terms .clear ()
|
||||||
self .missed_key_terms_buffer .clear ()
|
self .missed_key_terms_buffer .clear ()
|
||||||
self .favorite_download_queue .clear ()
|
self .favorite_download_queue .clear ()
|
||||||
self .only_links_log_display_mode = LOG_DISPLAY_LINKS # Reset on full reset
|
self .only_links_log_display_mode =LOG_DISPLAY_LINKS
|
||||||
self .mega_download_log_preserved_once =False
|
self .mega_download_log_preserved_once =False
|
||||||
self .permanently_failed_files_for_dialog .clear ()
|
self .permanently_failed_files_for_dialog .clear ()
|
||||||
self .favorite_download_scope =FAVORITE_SCOPE_SELECTED_LOCATION
|
self .favorite_download_scope =FAVORITE_SCOPE_SELECTED_LOCATION
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user