diff --git a/downloader_utils.py b/downloader_utils.py
index f5fe8ca..10bbfb4 100644
--- a/downloader_utils.py
+++ b/downloader_utils.py
@@ -1347,6 +1347,7 @@ class PostProcessorWorker:
unique_links_data = {}
for match in link_pattern.finditer(post_content_html):
link_url = match.group(1).strip()
+ link_url = html.unescape(link_url) # Decode HTML entities in the URL
link_inner_text = match.group(2)
if not any(ext in link_url.lower() for ext in ['.css', '.js', '.ico', '.xml', '.svg']) \
diff --git a/main.py b/main.py
index b9ec5c8..1e35a71 100644
--- a/main.py
+++ b/main.py
@@ -236,10 +236,11 @@ class TourDialog(QDialog):
# --- Define Tour Steps with Updated Content ---
step1_content = (
- "Hello! This quick tour will walk you through the main features of the Kemono Downloader, including recent updates."
+ "Hello! This quick tour will walk you through the main features of the Kemono Downloader, including recent updates like enhanced filtering, manga mode improvements, and cookie management."
"
"
"- My goal is to help you easily download content from Kemono and Coomer.
"
"- Use the Next and Back buttons to navigate.
"
+ "- Many options have tooltips if you hover over them for more details.
"
"- Click Skip Tour to close this guide at any time.
"
"- Check 'Never show this tour again' if you don't want to see this on future startups.
"
"
"
@@ -256,7 +257,7 @@ class TourDialog(QDialog):
" Click 'Browse...' to choose a folder on your computer where all downloaded files will be saved. "
"This is required unless you are using 'Only Links' mode.
"
"π Page Range (Creator URLs only):
"
- " If downloading from a creator's page, you can specify a range of pages (e.g., pages 2 to 5). "
+ " If downloading from a creator's page, you can specify a range of pages to fetch (e.g., pages 2 to 5). "
"Leave blank for all pages. This is disabled for single post URLs or when Manga/Comic Mode is active."
""
)
@@ -268,11 +269,11 @@ class TourDialog(QDialog):
"π― Filter by Character(s):
"
" Enter character names, comma-separated (e.g., Tifa, Aerith). Group aliases for a combined folder name: (alias1, alias2) becomes folder 'alias1 alias2'.
"
" The 'Filter: [Scope]' button next to this input controls how this filter is applied:"
- " - Filter: Files: Checks individual filenames. A post is kept if any file matches; only matching files are downloaded.
"
- " - Filter: Title: Checks post titles. All files from a matching post are downloaded.
"
- " - Filter: Both: Checks post title first. If it matches, all files are downloaded. If not, it then checks filenames, and only matching files are downloaded.
"
- " - Filter: Comments (Beta): Checks filenames first. If a match, all files are downloaded. If no file match, it then checks post comments. If a comment matches, all files are downloaded. (Uses more API requests).
"
- " This filter also influences folder naming if 'Separate Folders' is enabled.
"
+ " - Filter: Files: Checks individual filenames. A post is kept if any file matches; only matching files are downloaded. Folder naming uses the character from the matching filename.
"
+ " - Filter: Title: Checks post titles. All files from a matching post are downloaded. Folder naming uses the character from the matching post title.
"
+ " - Filter: Both: Checks post title first. If it matches, all files are downloaded. If not, it then checks filenames, and only matching files are downloaded. Folder naming prioritizes title match, then file match.
"
+ " - Filter: Comments (Beta): Checks filenames first. If a file matches, all files from the post are downloaded. If no file match, it then checks post comments. If a comment matches, all files are downloaded. (Uses more API requests). Folder naming prioritizes file match, then comment match.
"
+ " This filter also influences folder naming if 'Separate Folders by Name/Title' is enabled.
"
"π« Skip with Words:
"
" Enter words, comma-separated (e.g., WIP, sketch, preview). "
" The 'Scope: [Type]' button (next to this input) cycles how this filter applies:"
@@ -295,14 +296,18 @@ class TourDialog(QDialog):
"More options to customize your downloads:"
""
"- Skip .zip / Skip .rar: Check these to avoid downloading these archive file types. "
- " (Note: These are disabled and ignored if 'π¦ Only Archives' mode is selected).
"
+ " (Note: These are disabled and ignored if 'π¦ Only Archives' filter mode is selected).
"
"βοΈ Remove Words from name:
"
" Enter words, comma-separated (e.g., patreon, [HD]), to remove from downloaded filenames (case-insensitive).
"
"Download Thumbnails Only: Downloads small preview images instead of full-sized files (if available).
"
"Compress Large Images: If the 'Pillow' library is installed, images larger than 1.5MB will be converted to WebP format if the WebP version is significantly smaller.
"
"ποΈ Custom Folder Name (Single Post Only):
"
" If you are downloading a single specific post URL AND 'Separate Folders by Name/Title' is enabled, "
- "you can enter a custom name here for that post's download folder."
+ "you can enter a custom name here for that post's download folder.
"
+ "πͺ Use Cookie: Check this to use cookies for requests. You can either:"
+ " - Enter a cookie string directly into the text field (e.g., name1=value1; name2=value2).
"
+ " - Click 'Browse...' to select a cookies.txt file (Netscape format). The path will appear in the text field.
"
+ " This is useful for accessing content that requires login. The text field takes precedence if filled."
""
)
self.step4 = TourStepWidget("β’ Fine-Tuning Downloads", step4_content)
@@ -312,25 +317,36 @@ class TourDialog(QDialog):
""
"- βοΈ Separate Folders by Name/Title: Creates subfolders based on the 'Filter by Character(s)' input or post titles (can use the 'Known Shows/Characters' list as a fallback for folder names).
"
"- Subfolder per Post: If 'Separate Folders' is on, this creates an additional subfolder for each individual post inside the main character/title folder.
"
- "- π Use Multithreading (Threads): Enables faster downloads for creator pages by processing multiple posts or files concurrently. The number of threads can be adjusted. Single post URLs are processed using a single thread for post data but can use multiple threads for file downloads within that post.
"
+ "- π Use Multithreading (Threads): Enables faster operations. The number in 'Threads' input means:"
+ "
- For Creator Feeds: Number of posts to process simultaneously. Files within each post are downloaded sequentially by its worker (unless 'Date Based' manga naming is on, which forces 1 post worker).
"
+ " - For Single Post URLs: Number of files to download concurrently from that single post.
"
+ " If unchecked, 1 thread is used. High thread counts (e.g., >40) may show an advisory.
"
"- Multi-part Download Toggle (Top-right of log area):
"
" The 'Multi-part: [ON/OFF]' button allows enabling/disabling multi-segment downloads for individual large files. "
- " - ON: Can speed up large file downloads (e.g., videos) but may increase UI choppiness or log spam with many small files. An advisory will appear when enabling.
"
+ " - ON: Can speed up large file downloads (e.g., videos) but may increase UI choppiness or log spam with many small files. An advisory will appear when enabling. If a multi-part download fails, it retries as single-stream.
"
" - OFF (Default): Files are downloaded in a single stream.
"
" This is disabled if 'Only Links' or 'Only Archives' mode is active.
"
"- π Manga/Comic Mode (Creator URLs only): Tailored for sequential content."
"
"
" - Downloads posts from oldest to newest.
"
" - The 'Page Range' input is disabled as all posts are fetched.
"
- " - A filename style toggle button (e.g., 'Name: Post Title' or 'Name: Original File') appears in the top-right of the log area when this mode is active for a creator feed. Click it to change naming:"
+ "
- A filename style toggle button (e.g., 'Name: Post Title') appears in the top-right of the log area when this mode is active for a creator feed. Click it to cycle through naming styles:"
"
"
- " - Name: Post Title (Default): The first file in a post is named after the post's title (e.g., MyMangaChapter1.jpg). Subsequent files in the same post (if any) will retain their original filenames.
"
- " - Name: Original File: All files will attempt to keep their original filenames as provided by the site (e.g., 001.jpg, page_02.png). You'll see a recommendation to use 'Post Title' style if you choose this.
"
+ " - Name: Post Title (Default): The first file in a post is named after the post's title. Subsequent files in the same post keep original names.
"
+ " - Name: Original File: All files attempt to keep their original filenames.
"
+ " - Name: Date Based: Files are named sequentially (001.ext, 002.ext, ...) based on post publication order. Multithreading for post processing is automatically disabled for this style.
"
"
"
" "
- " - For best results with 'Name: Post Title' style, use the 'Filter by Character(s)' field with the manga/series title.
"
+ " - For best results with 'Name: Post Title' or 'Name: Date Based' styles, use the 'Filter by Character(s)' field with the manga/series title for folder organization.
"
"
"
- "- π Known Shows/Characters: Add names here (e.g., Game Title, Series Name, Character Full Name). These are used for automatic folder creation when 'Separate Folders' is on and no specific 'Filter by Character(s)' is provided for a post.
"
+ "- π Known.txt for Smart Folder Organization:
"
+ " Fine-grained control over automatic folder organization using a personalized list in Known.txt."
+ " "
+ " - Primary Names & Aliases: Define a main folder name and link multiple aliases. For example, an entry like
([Power], powwr, pwr, Blood devil) ensures any post matching \"Power\", \"powwr\", etc. (based on your filter scope) gets saved into a \"Power\" folder. Simple entries like My Series are also supported. The primary name for the folder is the one in [] brackets, or the first one if no brackets. "
+ " - Intelligent Fallback: When 'Separate Folders by Name/Title' is active, and if a post doesn't match any specific 'Filter by Character(s)' input, the downloader consults
Known.txt to find a matching primary name for folder creation. "
+ " - User-Friendly Management: Add or remove primary names directly through the UI list below. For advanced editing (like setting up aliases or defining the primary name for a group), click 'Open Known.txt' to edit the file directly.
"
+ "
"
+ " "
"
"
)
self.step5 = TourStepWidget("β£ Organization & Performance", step5_content)
@@ -345,7 +361,8 @@ class TourDialog(QDialog):
" - ποΈ Progress Log (Default): Shows all download activity, errors, and summaries.
"
" - π Missed Character Log: Displays a summarized list of key terms from post titles that were skipped due to your 'Filter by Character(s)' settings. Useful for identifying content you might be unintentionally missing.
"
"π Reset: Clears all input fields, logs, and resets temporary settings to their defaults. Can only be used when no download is active.
"
- "β¬οΈ Start Download / π Extract Links / β Cancel: These buttons initiate or stop the current download/extraction process. The 'Cancel' button also performs a soft UI reset, preserving your URL and Directory inputs."
+ "β¬οΈ Start Download / π Extract Links / βΈοΈ Pause / β Cancel: These buttons control the process. 'Cancel & Reset UI' stops the current operation and performs a soft UI reset, preserving your URL and Directory inputs. 'Pause/Resume' allows temporarily halting and continuing.
"
+ "If some files fail with recoverable errors (like 'IncompleteRead'), you might be prompted to retry them at the end of a session."
""
"
You're all set! Click 'Finish' to close the tour and start using the downloader."
)
@@ -358,7 +375,7 @@ class TourDialog(QDialog):
bottom_controls_layout = QVBoxLayout()
bottom_controls_layout.setContentsMargins(15, 10, 15, 15) # Adjusted margins
- bottom_controls_layout.setSpacing(10)
+ bottom_controls_layout.setSpacing(12) # Slightly more spacing
self.never_show_again_checkbox = QCheckBox("Never show this tour again")
bottom_controls_layout.addWidget(self.never_show_again_checkbox, 0, Qt.AlignLeft)