# Changelog

## Document Purpose

This document tracks all notable changes to the Aniworld project.

### What This Document Contains

- **Version History**: All released versions with dates
- **Added Features**: New functionality in each release
- **Changed Features**: Modifications to existing features
- **Deprecated Features**: Features marked for removal
- **Removed Features**: Features removed from the codebase
- **Fixed Bugs**: Bug fixes with issue references
- **Security Fixes**: Security-related changes
- **Breaking Changes**: Changes requiring user action

### What This Document Does NOT Contain

- Internal refactoring details (unless user-facing)
- Commit-level changes
- Work-in-progress features
- Roadmap or planned features

### Target Audience

- All users and stakeholders
- Operators planning upgrades
- Developers tracking changes
- Support personnel

---

## Format

This changelog follows [Keep a Changelog](https://keepachangelog.com/) principles and adheres to [Semantic Versioning](https://semver.org/).

---

## [1.3.1] - 2026-02-22

### Added

- **Encoding detection for HTML parsing** (`src/core/providers/aniworld_provider.py`):
  Added `_decode_html_content()` function that uses `chardet` to detect the actual
  encoding of HTML content before parsing. Falls back to UTF-8 with `errors='replace'`
  to handle pages with mismatched encoding declarations. Applied to all BeautifulSoup
  parsing calls to prevent "Some characters could not be decoded" warnings.
- **chardet dependency**: Added `chardet>=5.2.0` to `requirements.txt` for encoding detection.

### Added

- **Temp file cleanup after every download** (`src/core/providers/aniworld_provider.py`,
  `src/core/providers/enhanced_provider.py`): Module-level helper
  `_cleanup_temp_file()` removes the working temp file and any yt-dlp `.part`
  fragments after each download attempt — on success, on failure, and on
  exceptions (including `BrokenPipeError` and cancellation). Ensures that no
  partial files accumulate in `./Temp/` across multiple runs.
- **Temp folder purge on server start** (`src/server/fastapi_app.py`): The
  FastAPI lifespan startup now iterates `./Temp/` and deletes every file and
  sub-directory before the rest of the initialisation sequence runs. If the
  folder does not exist it is created. Errors are caught and logged as warnings
  so that they never abort startup.

---

## [1.3.0] - 2026-02-22

### Added

- **NFO tag completeness (`nfo_mapper.py`)**: All 17 required NFO tags are now
  explicitly populated during creation: `originaltitle`, `sorttitle`, `year`,
  `plot`, `outline`, `tagline`, `runtime`, `premiered`, `status`, `imdbid`,
  `genre`, `studio`, `country`, `actor`, `watched`, `dateadded`, `mpaa`.
- **`src/core/utils/nfo_mapper.py`**: New module containing
  `tmdb_to_nfo_model()`, `_extract_rating_by_country()`, and
  `_extract_fsk_rating()`. Extracted from `NFOService` to keep files under
  500 lines and isolate pure mapping logic.
- **US MPAA rating**: `_extract_rating_by_country(ratings, "US")` now maps the
  US TMDB content rating to the `<mpaa>` NFO tag.
- **`NfoRepairService` (`src/core/services/nfo_repair_service.py`)**: New service
  that detects incomplete `tvshow.nfo` files and triggers TMDB re-fetch.
  Provides `parse_nfo_tags()`, `find_missing_tags()`, `nfo_needs_repair()`, and
  `NfoRepairService.repair_series()`. 13 required tags are checked.
- **`perform_nfo_repair_scan()`
  (`src/server/services/folder_scan_service.py`)**: New async function
  that iterates every series directory, checks whether `tvshow.nfo` is missing
  required tags using `nfo_needs_repair()`, and queues the series for background
  reload via `asyncio.create_task`. Skips gracefully when `tmdb_api_key` or
  `anime_directory` is not configured.
- **NFO repair wired into scheduled folder scan (`src/server/services/folder_scan_service.py`)**:
  `perform_nfo_repair_scan(background_loader=None)` is called during the
  scheduled daily folder scan, keeping startup fast while ensuring regular
  maintenance.

### Changed

- `NFOService._tmdb_to_nfo_model()` and `NFOService._extract_fsk_rating()` moved
  to `src/core/utils/nfo_mapper.py` as module-level functions
  `tmdb_to_nfo_model()` and `_extract_fsk_rating()`.
- `src/core/services/nfo_service.py` reduced from 640 → 471 lines.

---

## [Unreleased] - 2026-01-18

### Added

- **Cron-based Scheduler**: Replaced the asyncio sleep-loop with APScheduler's `AsyncIOScheduler + CronTrigger`
    - Schedule rescans at a specific **time of day** (`HH:MM`) on selected **days of the week**
    - New `SchedulerConfig` fields: `schedule_time` (default `"03:00"`), `schedule_days` (default all 7), `auto_download_after_rescan` (default `false`)
    - Old `interval_minutes` field retained for backward compatibility
- **Auto-download after rescan**: When `auto_download_after_rescan` is enabled, missing episodes are automatically queued for download after each scheduled rescan
- **Day-of-week UI**: New day-of-week pill toggles (Mon–Sun) in the Settings → Scheduler section
- **Live config reload**: POST `/api/scheduler/config` reschedules the APScheduler job without restarting the application
- **Enriched API response**: GET/POST `/api/scheduler/config` now returns `{"success", "config", "status"}` envelope including `next_run`, `last_run`, and `scan_in_progress`

### Changed

- Scheduler API response format: previously returned flat config; now returns `{"success": true, "config": {...}, "status": {...}}`
- `reload_config()` is now a synchronous method accepting a `SchedulerConfig` argument (previously async, no arguments)
- Dependencies: added `APScheduler>=3.10.4` to `requirements.txt`

### Fixed

- **Series Visibility**: Fixed issue where series added to the database weren't appearing in the API/UI
    - Series are now loaded from database into SeriesApp's in-memory cache on startup
    - Added `_load_series_from_db()` call after initial database sync in FastAPI lifespan
- **Episode Tracking**: Fixed missing episodes not being saved to database when adding new series
    - Missing episodes are now persisted to the `episodes` table after the targeted scan
    - Episodes are properly synced during rescan operations (added/removed based on filesystem state)
- **Database Synchronization**: Improved data consistency between database and in-memory cache
    - Rescan process properly updates episodes: adds new missing episodes, removes downloaded ones
    - All series operations now maintain database and cache synchronization

### Technical Details

- Modified `src/server/fastapi_app.py` to load series from database after sync
- Modified `src/server/api/anime.py` to save scanned episodes to database
- Episodes table properly tracks missing episodes with automatic cleanup

### Deprecated

- **Legacy Series Files (key/data)**: File-based series storage is deprecated. `key` and `data` files in anime folders will be removed in v3.0.0. Database storage is now the primary method. See [docs/MIGRATION_GUIDE.md](docs/MIGRATION_GUIDE.md) for details.

---

## Sections for Each Release

```markdown
## [Version] - YYYY-MM-DD

### Added

- New features

### Changed

- Changes to existing functionality

### Deprecated

- Features that will be removed in future versions

### Removed

- Features removed in this release

### Fixed

- Bug fixes

### Security

- Security-related fixes
```

---

## Unreleased

_Changes that are in development but not yet released._

### Added

- **Comprehensive Test Suite**: Created 1,070+ tests across 4 priority tiers
    - **TIER 1 (Critical)**: 159 tests - Scheduler, NFO batch operations, download queue, persistence
    - **TIER 2 (High Priority)**: 390 tests - JavaScript framework, dark mode, setup page, settings modal, WebSocket, queue UI
    - **TIER 3 (Medium Priority)**: 156 tests - WebSocket load, concurrent operations, retry logic, NFO performance, series parsing, TMDB integration
    - **TIER 4 (Polish)**: 426 tests - Internationalization (89), user preferences (68), accessibility (250+), media server compatibility (19)
- **Frontend Testing Infrastructure**: Vitest for unit tests, Playwright for E2E tests
- **Security Test Coverage**: Complete testing for authentication, authorization, CSRF, XSS, SQL injection
- **Performance Validation**: WebSocket load (200+ concurrent clients), batch operations, concurrent access
- **Accessibility Tests**: WCAG 2.1 AA compliance testing (keyboard navigation, ARIA labels, screen readers)
- **Media Server Compatibility**: NFO format validation for Kodi, Plex, Jellyfin, and Emby

### Changed

- Updated testing documentation (TESTING_COMPLETE.md, instructions.md) to reflect 100% completion of all test tiers

### Fixed

- **Enhanced Anime Add Flow**: Automatic database persistence, targeted episode scanning, and folder creation with sanitized names
- Filesystem utility module (`src/server/utils/filesystem.py`) with `sanitize_folder_name()`, `is_safe_path()`, and `create_safe_folder()` functions
- `Serie.sanitized_folder` property for generating filesystem-safe folder names from display names
- `SerieScanner.scan_single_series()` method for targeted scanning of individual anime without full library rescan
- Add series API response now includes `missing_episodes` list and `total_missing` count
- Database transaction support with `@transactional` decorator and `atomic()` context manager
- Transaction propagation modes (REQUIRED, REQUIRES_NEW, NESTED) for fine-grained control
- Savepoint support for nested transactions with partial rollback capability
- `TransactionManager` helper class for manual transaction control
- Bulk operations: `bulk_mark_downloaded`, `bulk_delete`, `clear_all` for batch processing
- `rotate_session` atomic operation for secure session rotation
- Transaction utilities: `is_session_in_transaction`, `get_session_transaction_depth`
- `get_transactional_session` for sessions without auto-commit

### Changed

- `QueueRepository.save_item()` now uses atomic transactions for data consistency
- `QueueRepository.clear_all()` now uses atomic transactions for all-or-nothing behavior
- Service layer documentation updated to reflect transaction-aware design

### Fixed

- Scan status indicator now correctly shows running state after page reload during active scan
- Improved reliability of process status updates in the UI header

---

## Version History

_To be documented as versions are released._
