File size: 5,148 Bytes
3cb0dc4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
"""
Path Validation Module
Validates and suggests safe alternatives for problematic file paths
"""
import re
from pathlib import Path
from typing import Tuple, List
def detect_problematic_characters(path_name: str) -> List[str]:
"""Detect problematic characters in a path name"""
problematic_chars = []
# Characters that cause FFmpeg issues
if "'" in path_name:
problematic_chars.append("apostrophe (')")
# Characters that may cause filesystem issues
if '"' in path_name:
problematic_chars.append('double quote (")')
# Other potentially problematic characters
problematic_patterns = {
r'[<>|?*]': 'invalid filesystem characters',
r'[\x00-\x1f]': 'control characters',
r'\\': 'backslashes (Windows path separators)',
}
for pattern, description in problematic_patterns.items():
if re.search(pattern, path_name):
problematic_chars.append(description)
return problematic_chars
def suggest_safe_path(path_name: str) -> str:
"""Suggest a safe alternative for a problematic path name"""
from modules.file_manager import sanitize_filename
return sanitize_filename(path_name)
def validate_book_path(book_name: str) -> Tuple[bool, str, str]:
"""
Validate a book name for path safety
Returns:
(is_safe, warning_message, suggested_name)
"""
problematic_chars = detect_problematic_characters(book_name)
if not problematic_chars:
return True, "", book_name
suggested_name = suggest_safe_path(book_name)
# Create warning message
char_list = ", ".join(problematic_chars)
warning_msg = f"⚠️ Path contains problematic characters: {char_list}\n\n"
warning_msg += f"This may cause:\n"
warning_msg += f"• FFmpeg concatenation failures\n"
warning_msg += f"• File system compatibility issues\n"
warning_msg += f"• Audio processing errors\n\n"
warning_msg += f"Suggested safe name: '{suggested_name}'"
return False, warning_msg, suggested_name
def validate_and_create_audiobook_path(book_name: str, force_safe: bool = False) -> Tuple[Path, str]:
"""
Validate book name and create safe audiobook path
Args:
book_name: Original book name from user input
force_safe: If True, automatically use safe name without asking
Returns:
(safe_audiobook_path, actual_name_used)
"""
from config.config import AUDIOBOOK_ROOT
is_safe, warning, suggested_name = validate_book_path(book_name)
if is_safe or force_safe:
final_name = suggested_name if force_safe and not is_safe else book_name
audiobook_path = AUDIOBOOK_ROOT / final_name
return audiobook_path, final_name
else:
# Return suggested path but indicate validation failed
suggested_path = AUDIOBOOK_ROOT / suggested_name
return suggested_path, suggested_name
def check_existing_audiobook_paths() -> List[Tuple[str, str, str]]:
"""
Check existing audiobook directories for problematic paths
Returns:
List of (original_name, suggested_name, issues) tuples
"""
from config.config import AUDIOBOOK_ROOT
problematic_books = []
if not AUDIOBOOK_ROOT.exists():
return problematic_books
for book_dir in AUDIOBOOK_ROOT.iterdir():
if book_dir.is_dir():
book_name = book_dir.name
problematic_chars = detect_problematic_characters(book_name)
if problematic_chars:
suggested_name = suggest_safe_path(book_name)
issues = ", ".join(problematic_chars)
problematic_books.append((book_name, suggested_name, issues))
return problematic_books
# Utility functions for GUI integration
def format_path_warning_html(book_name: str) -> str:
"""Format path validation warning as HTML for Gradio"""
is_safe, warning, suggested = validate_book_path(book_name)
if is_safe:
return f'<span style="color: green;">✅ Path is safe: "{book_name}"</span>'
else:
html = f'<div style="color: orange; background: #fff3cd; padding: 10px; border-radius: 5px; border: 1px solid #ffeaa7;">'
html += f'<strong>⚠️ Problematic Path Detected</strong><br>'
html += f'<strong>Original:</strong> "{book_name}"<br>'
html += f'<strong>Suggested:</strong> "{suggested}"<br><br>'
html += f'<strong>Issues Found:</strong><br>'
for char in detect_problematic_characters(book_name):
html += f'• {char}<br>'
html += f'<br><em>Tip: Use the suggested name to avoid audio processing errors.</em>'
html += f'</div>'
return html
def format_path_warning_text(book_name: str) -> str:
"""Format path validation warning as plain text"""
is_safe, warning, suggested = validate_book_path(book_name)
if is_safe:
return f'✅ Path is safe: "{book_name}"'
else:
return f'⚠️ PROBLEMATIC PATH: "{book_name}"\nSUGGESTED: "{suggested}"\n\n{warning}' |