Skip to content

Commit

Permalink
sanitize filename on Windows (#62)
Browse files Browse the repository at this point in the history
Co-authored-by: Zehina <[email protected]>
  • Loading branch information
Zehina and Zehina authored Oct 20, 2024
1 parent 0758b3c commit 71c1f9a
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 5 deletions.
13 changes: 10 additions & 3 deletions webtoon_downloader/core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class DownloadError(Exception):

url: str
cause: Exception
base_message: str = "Failed to download from"
message: str | None = field(default=None)

def __str__(self) -> str:
Expand All @@ -20,27 +21,33 @@ def __str__(self) -> str:
if self.cause:
cause_msg = str(self.cause)
if cause_msg:
return f"Failed to download from {self.url} => {cause_msg}"
return f"{self.base_message} {self.url} => {cause_msg}"

return f"Failed to download from {self.url} due to: {self.cause.__class__.__name__}"
return f"{self.base_message} {self.url} due to: {self.cause.__class__.__name__}"

return f"Failed to download from {self.url}"
return f"{self.base_message} {self.url}"


@dataclass
class WebtoonDownloadError(DownloadError):
"""Exception raised for Webtoon download errors"""

base_message: str = "Failed to download Webtoon"


@dataclass
class ImageDownloadError(DownloadError):
"""Exception raised for image download errors"""

base_message: str = "downloading image"


@dataclass
class ChapterDownloadError(DownloadError):
"""Exception raised for chapter download errors"""

base_message: str = "downloading chapter"

chapter_info: ChapterInfo | None = None


Expand Down
19 changes: 17 additions & 2 deletions webtoon_downloader/core/webtoon/namer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os
import re
from dataclasses import dataclass
from pathlib import Path
from typing import Protocol, runtime_checkable
Expand All @@ -7,6 +9,18 @@
from webtoon_downloader.core.webtoon.models import ChapterInfo, PageInfo


def sanitize_filename(filename: str) -> str:
"""
Sanitizes a filename by replacing all non-alphanumeric characters with underscores on Windows.
"""
if os.name == "nt":
filename = re.sub(r"[^\w\.-]", "_", filename)
if filename[-1] == "_":
filename = filename[:-1]

return filename


@runtime_checkable
class FileNameGenerator(Protocol):
"""
Expand Down Expand Up @@ -47,7 +61,8 @@ def get_chapter_directory(self, chapter_info: ChapterInfo) -> Path:
Returns the directory path for storing the given chapter's data.
"""
if self.use_chapter_title_directories:
return Path(chapter_info.title)
return Path(sanitize_filename(chapter_info.title))

return Path(f"{chapter_info.number:0{len(str(chapter_info.total_chapters))}d}")

def get_page_filename(self, page_info: PageInfo) -> str:
Expand Down Expand Up @@ -77,7 +92,7 @@ class NonSeparateFileNameGenerator(FileNameGenerator):
are stored in the same directory.
"""

def get_chapter_directory(self, chapter_info: ChapterInfo) -> Path: # type ignore
def get_chapter_directory(self, _: ChapterInfo) -> Path: # type ignore
"""
Returns the root directory for storing pages when they are not separated by chapters.
"""
Expand Down

0 comments on commit 71c1f9a

Please sign in to comment.