Add chardet-based _decode_html_content() to aniworld_provider. Apply
to all BeautifulSoup parsing calls to prevent decoding warnings on
pages with mismatched encoding declarations. Falls back to utf-8
with errors='replace' when confidence < 0.7.
Also fix test_enhanced_provider HLS test signature and add HLS
pattern unit tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Iterate providers actually advertised on the episode page (ordered by
SUPPORTED_PROVIDERS preference) instead of always re-resolving VOE.
Each candidate is HEAD-probed before yt-dlp runs, so dead links are
skipped immediately; direct video URLs use a streaming fast path that
bypasses yt-dlp; total failure now logs the exhausted provider list.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add ffmpeg to Dockerfile.app for container HLS support
- Configure yt-dlp with --downloader ffmpeg --hls-use-mpegts
- Add startup health check warns if ffmpeg missing
- Update DEVELOPMENT.md with ffmpeg prerequisites and troubleshooting
- Add tests for ffmpeg HLS options and health check
- Pass app logger to yt-dlp so internal [download] progress lines
are routed through the INFO-level logger instead of stdout.
- Throttle download_progress_handler debug logging to avoid
flooding logs on every fragment tick.
- Switch key provider lifecycle messages to INFO (start/complete)
while keeping verbose details at DEBUG.
- Set debug_enabled=False in development config so dev mode
does not emit extra debug noise.
- Update config docstring example from DEBUG to INFO.
- Add year property to Serie entity with name_with_year
- Add year column to AnimeSeries database model
- Add get_year() method to AniworldLoader provider
- Extract year from folder names before fetching from API
- Update SerieScanner to populate year during rescan
- Update add_series endpoint to fetch and store year
- Optimize: check folder name for year before API call
- Replace shutil.copy2() with shutil.copyfile() in enhanced_provider.py
- Replace shutil.copy() with shutil.copyfile() in aniworld_provider.py
- copyfile() only copies content, avoiding metadata permission issues
- Remove None assignment for download_progress event in AniworldLoader
- Remove None assignments for download_status and scan_status events in SeriesApp
- Events library requires events to not be initialized to None
- Verified logging configuration is properly set to INFO level
- Replace callback system with events library in SerieScanner
- Update SeriesApp to subscribe to loader and scanner events
- Refactor ScanService to use Events instead of CallbackManager
- Remove CallbackManager imports and callback classes
- Add safe event calling with error handling in SerieScanner
- Update AniworldLoader to use Events for download progress
- Remove progress_callback parameter from download methods
- Update all affected tests for Events pattern
- Fix test_series_app.py for new event subscription model
- Comment out obsolete callback tests in test_scan_service.py
All core tests passing. Events provide cleaner event-driven architecture.
- Import and use DownloadCancelled exception which YT-DLP properly handles
- Add InterruptedError handling throughout the call chain
- Fire 'cancelled' status event when download is cancelled
- Handle InterruptedError in DownloadService to set CANCELLED status
- Add cancellation flag to AniworldLoader with request_cancel/reset_cancel/is_cancelled methods
- Update base_provider.Loader interface with cancellation abstract methods
- Integrate cancellation check in YT-DLP progress hooks
- Add request_download_cancel method to SeriesApp and AnimeService
- Update DownloadService.stop() to request cancellation before shutdown
- Clean up temp files on cancellation
- Added comprehensive module-level docstring explaining provider vs series keys
- Enhanced Loaders class docstring with purpose and attributes documentation
- Added detailed docstring to GetLoader() method with Args/Returns/Raises sections
- Added type hints: Dict[str, Loader] for self.dict and -> None for __init__
- Clarified distinction between provider keys (e.g., 'aniworld.to') and series keys
- No functional changes - existing implementation already correct
- All 34 provider tests pass
- All 16 SeriesApp tests pass
- Updated instructions.md to mark Task 1.5 as completed
- Follows PEP 8 and PEP 257 standards
- Enhanced download() method docstring in aniworld_provider.py
- Enhanced Download() method docstring in enhanced_provider.py
- Clarified that 'key' is the series unique identifier from provider
- Clarified that 'serie_folder'/'serieFolder' is filesystem folder name (metadata only)
- Added comprehensive Args, Returns, and Raises sections to docstrings
- Fixed PEP 8 line length issue in logging statement
- Verified existing code already uses 'key' for identification and logging
- All 34 provider-related tests pass successfully
- No functional changes required, documentation improvements only
- refactor src/cli/Main.py: split long logging config, user prompts, and method calls
- refactor src/config/settings.py: break long Field definitions into multiple lines
- refactor src/core/providers/enhanced_provider.py: split provider lists, headers, and long f-strings
- refactor src/core/providers/streaming/voe.py: format HTTP header setup
- update QualityTODO.md: mark all line length violations as completed
All files now comply with 88-character line limit. Code readability improved with
better-structured multi-line statements and intermediate variables for complex expressions.