- Move phase/plan docs into docs/ - Move legacy node:test files into tests/legacy/ with README - Remove .backup file, test audit artifacts, and unused AI prompt/skill files - Remove broken iOS GitHub workflows (reference missing MovieMapper-iOS/)
12 KiB
12 KiB
MovieMapper Rust Implementation Plan
Overview
This document outlines the implementation plan for a Rust-based version of MovieMapper. The Rust implementation will focus on the business logic layer while maintaining compatibility with the existing Electron frontend.
Project Structure
Rust/
├── src/
│ ├── lib.rs
│ ├── main.rs
│ ├── model/
│ │ ├── mod.rs
│ │ ├── file.rs
│ │ ├── show.rs
│ │ └── episode.rs
│ ├── service/
│ │ ├── mod.rs
│ │ ├── file_scanner.rs
│ │ ├── file_metadata.rs
│ │ ├── tvdb_api.rs
│ │ ├── file_mapper.rs
│ │ ├── audit_logger.rs
│ │ └── tag_manager.rs
│ ├── utils/
│ │ ├── mod.rs
│ │ ├── ffmpeg.rs
│ │ ├── path.rs
│ │ └── error.rs
│ └── config/
│ ├── mod.rs
│ └── settings.rs
├── tests/
│ ├── unit/
│ │ ├── file_scanner_tests.rs
│ │ ├── file_metadata_tests.rs
│ │ ├── tvdb_api_tests.rs
│ │ ├── file_mapper_tests.rs
│ │ ├── audit_logger_tests.rs
│ │ └── tag_manager_tests.rs
│ ├── integration/
│ │ ├── integration_tests.rs
│ │ └── end_to_end_tests.rs
│ └── fixtures/
│ ├── test_files/
│ └── test_data.json
├── Cargo.toml
├── Cargo.lock
├── FEATURES.md (copied from root)
└── README.md
Phase 1: Project Setup and Core Model (Week 1)
Tasks
- Initialize Rust project with
cargo new - Configure
Cargo.tomlwith dependencies - Create model structs
- Implement basic error handling
- Set up testing framework
Dependencies
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1.0", features = ["full"] }
reqwest = { version = "0.11", features = ["json"] }
thiserror = "1.0"
anyhow = "1.0"
chrono = { version = "0.4", features = ["serde"] }
notify = "6.1"
tracing = "0.1"
tracing-subscriber = "0.3"
ffmpeg-next = "5.0"
dirs = "5.0"
dotenv = "0.15"
[dev-dependencies]
tempfile = "3.10"
tokio-test = "0.4"
Model Structs
// src/model/file.rs
pub struct MediaFile {
pub path: PathBuf,
pub name: String,
pub size: u64,
pub modified: DateTime<Utc>,
pub duration: String,
pub quality: String,
pub fps: String,
pub is_folder: bool,
pub is_problematic: bool,
pub tags: Vec<String>,
}
// src/model/show.rs
pub struct Show {
pub id: i64,
pub series_name: String,
pub status: String,
pub first_aired: Option<String>,
pub overview: String,
pub image: String,
pub slug: String,
}
// src/model/episode.rs
pub struct Episode {
pub id: i64,
pub name: String,
pub number: i32,
pub season_number: i32,
pub aired: Option<String>,
pub runtime: Option<i32>,
}
Implementation Checklist
- Initialize Rust project
- Configure Cargo.toml
- Create model structs (File, Show, Episode, Season)
- Implement custom error types with
thiserror - Set up basic logging with
tracing - Create unit test structure
Phase 2: File Scanning and Metadata Extraction (Week 2)
Tasks
- Implement directory scanning
- Integrate FFmpeg for metadata extraction
- Implement progress reporting
- Handle problematic files gracefully
- Write unit tests for scanning logic
Key Functions
// src/service/file_scanner.rs
pub struct FileScanner {
extensions: Vec<String>,
}
impl FileScanner {
pub fn new() -> Self;
pub async fn scan_directory(
&self,
path: &Path,
progress_callback: Option<&mut dyn FnMut(usize, usize, &str)>,
) -> Result<Vec<MediaFile>, ScannerError>;
pub fn is_media_file(&self, path: &Path) -> bool;
}
// src/service/file_metadata.rs
pub struct MetadataExtractor;
impl MetadataExtractor {
pub async fn extract_duration(&self, path: &Path) -> Result<String, MetadataError>;
pub async fn extract_quality(&self, path: &Path) -> Result<QualityInfo, MetadataError>;
pub async fn extract_metadata(&self, path: &Path) -> Result<MediaFileMetadata, MetadataError>;
}
Implementation Checklist
- Implement directory scanning (non-recursive)
- Integrate FFmpeg for metadata extraction
- Handle permission errors gracefully
- Implement progress callback support
- Add tests for file scanning
- Add tests for metadata extraction
- Test with problematic files
Phase 3: TVDB API Integration (Week 3)
Tasks
- Implement authentication flow
- Implement search functionality
- Implement show details fetch
- Implement season/episode fetch
- Handle API errors and edge cases
- Write API integration tests
Key Functions
// src/service/tvdb_api.rs
pub struct TVDBClient {
base_url: String,
api_key: String,
token: Option<String>,
}
impl TVDBClient {
pub async fn new(api_key: &str) -> Result<Self, TVDBError>;
pub async fn authenticate(&mut self) -> Result<(), TVDBError>;
pub async fn search(&self, query: &str) -> Result<Vec<Show>, TVDBError>;
pub async fn get_show_details(&self, show_id: i64) -> Result<ShowDetails, TVDBError>;
pub async fn get_season_episodes(
&self,
show_id: i64,
season_number: i32,
) -> Result<Vec<Episode>, TVDBError>;
}
Implementation Checklist
- Implement authentication with token caching
- Implement search endpoint
- Implement show details endpoint
- Implement episodes endpoint
- Handle API rate limiting
- Add tests for all API endpoints
- Test with real API calls
Phase 4: File Mapping and Renaming (Week 4)
Tasks
- Implement file mapping logic
- Implement Jellyfin naming convention
- Implement episode range handling
- Implement folder renaming with TVDB ID
- Handle file conflicts
- Write comprehensive mapping tests
Key Functions
// src/service/file_mapper.rs
pub struct FileMapper;
impl FileMapper {
pub async fn map_files(
&self,
files: &[MediaFile],
show_name: &str,
season_number: i32,
tvdb_id: Option<i64>,
) -> Result<MappingResult, MappingError>;
pub fn generate_jellyfin_filename(
&self,
show_name: &str,
season: i32,
episode_start: i32,
episode_end: i32,
quality: &str,
extension: &str,
) -> String;
}
Implementation Checklist
- Implement Jellyfin filename generation
- Handle episode ranges
- Implement folder renaming
- Handle file conflicts
- Add tests for mapping logic
- Test with various file patterns
Phase 5: Audit Logging and File Operations (Week 5)
Tasks
- Implement audit logging
- Implement file movement
- Implement folder creation
- Handle file operations safely
- Write tests for file operations
Key Functions
// src/service/audit_logger.rs
pub struct AuditLogger;
impl AuditLogger {
pub fn new(directory: &Path);
pub fn log_event(&self, action: &str, details: serde_json::Value) -> Result<(), AuditError>;
}
// src/service/file_operations.rs
pub struct FileOperations;
impl FileOperations {
pub fn move_file(&self, source: &Path, destination: &Path) -> Result<(), FileError>;
pub fn create_folder(&self, path: &Path) -> Result<(), FileError>;
pub fn rename_file(&self, old_path: &Path, new_name: &str) -> Result<(), FileError>;
}
Implementation Checklist
- Implement audit logging to
.auditfiles - Implement safe file movement
- Implement folder creation
- Implement file renaming
- Add tests for audit logging
- Add tests for file operations
Phase 6: Tag Management (Week 6)
Tasks
- Implement tag data structures
- Implement tag application/removal
- Implement bulk tag operations
- Implement tag-based file movement
- Write tag management tests
Key Functions
// src/service/tag_manager.rs
pub struct TagManager;
impl TagManager {
pub fn add_tag(&mut self, file_path: &Path, tag: &str) -> Result<(), TagError>;
pub fn remove_tag(&mut self, file_path: &Path, tag: &str) -> Result<(), TagError>;
pub fn get_tags(&self, file_path: &Path) -> Vec<&str>;
pub fn get_tagged_files(&self, tag: &str) -> Vec<&Path>;
pub fn move_tagged_files(&self, tag: &str, target_folder: &Path) -> Result<usize, TagError>;
}
Implementation Checklist
- Implement tag data structures
- Implement tag application logic
- Implement tag removal logic
- Implement bulk operations
- Add tests for tag management
- Test with multiple tags
Phase 7: Integration and End-to-End Testing (Week 7)
Tasks
- Write integration tests
- Write end-to-end tests
- Test with real file system
- Test with TVDB API
- Test error handling
- Performance testing
Test Scenarios
// tests/integration/file_scanner_tests.rs
#[tokio::test]
async fn test_scan_directory_with_media_files() {
// Create test directory structure
// Scan directory
// Verify results
}
// tests/integration/tvdb_api_tests.rs
#[tokio::test]
async fn test_search_and_fetch_details() {
// Search for a show
// Fetch details
// Verify results
}
// tests/integration/file_mapping_tests.rs
#[tokio::test]
async fn test_map_files_to_jellyfin_format() {
// Create test files
// Map files
// Verify renamed files
}
Implementation Checklist
- Write integration tests for all modules
- Write end-to-end tests
- Test with real file system
- Test with TVDB API
- Add error handling tests
- Performance testing
Phase 8: Documentation and Examples (Week 8)
Tasks
- Write comprehensive documentation
- Create example usage
- Write migration guide
- Create troubleshooting guide
- Write benchmark tests
Documentation Checklist
- API documentation with
cargo doc - User guide
- Developer guide
- Migration guide from JavaScript version
- Troubleshooting guide
- Performance benchmarks
Testing Strategy
Unit Tests
- Test individual functions in isolation
- Mock external dependencies (FFmpeg, TVDB API)
- Aim for 90%+ code coverage
Integration Tests
- Test module interactions
- Test with real file system
- Test with TVDB API
End-to-End Tests
- Test complete workflows
- Test error scenarios
- Test edge cases
Test Commands
# Run all tests
cargo test
# Run unit tests only
cargo test --lib
# Run integration tests
cargo test --test integration
# Run with coverage
cargo tarpaulin
# Run benchmarks
cargo bench
Known Challenges and Solutions
Challenge 1: FFmpeg Integration
Solution: Use ffmpeg-next crate for FFmpeg bindings. Handle errors gracefully and provide fallback values.
Challenge 2: TVDB API Authentication
Solution: Implement token caching with expiration. Handle token refresh automatically.
Challenge 3: File System Operations
Solution: Use notify crate for file system events. Implement atomic file operations.
Challenge 4: Progress Reporting
Solution: Use callback functions for progress updates. Implement async/await for non-blocking operations.
Challenge 5: Cross-Platform Path Handling
Solution: Use PathBuf and Path for all path operations. Handle platform-specific path separators.
Success Criteria
- All features from JavaScript version implemented
- 90%+ test coverage
- All tests passing
- Documentation complete
- Performance meets or exceeds JavaScript version
- No memory leaks
- Clean error handling
Future Enhancements
- Caching Layer: Implement caching for TVDB API responses
- Database Integration: Store show and file information
- Advanced File Matching: Better episode identification algorithms
- Export Functionality: Export organized collections
- Drag and Drop UI: Native drag and drop support
- Batch Operations: Support for batch file operations