feat: Add 'update' command to NFO CLI tool
- New command: python -m src.cli.nfo_cli update - Updates all existing NFO files with fresh TMDB data - Optionally re-downloads media files - Shows progress with success/error count - Updates task3_status.md to mark update_tvshow_nfo() as complete
This commit is contained in:
@@ -149,23 +149,16 @@ The unit tests were written based on assumptions about the API that don't match
|
||||
|
||||
2. **Unit Test Refactoring** (2-3 hours, optional)
|
||||
|
||||
- Update test_image_downloader.py with dependency injection
|
||||
- Fix test_nfo_generator.py validation tests
|
||||
- Update test_tmdb_client.py mocking strategy
|
||||
- Add test_nfo_service.py with comprehensive tests
|
||||
- ✅ NFO XML parsing tests added (4 tests passing)
|
||||
- ⚠️ TMDBClient tests need refactoring (async mocking challenges)
|
||||
- ⚠️ ImageDownloader tests need dependency injection
|
||||
- Alternative: Replace with more integration tests
|
||||
|
||||
3. **NFOService.update_tvshow_nfo()** (1 hour, optional)
|
||||
|
||||
- Currently raises NotImplementedError
|
||||
- Parse existing NFO to extract TMDB ID
|
||||
- Refetch from TMDB and regenerate
|
||||
- Update media files
|
||||
|
||||
4. **Error Recovery** (1 hour, optional)
|
||||
3. **Enhanced Error Recovery** (1 hour, optional)
|
||||
- Graceful handling if TMDB API fails during scan
|
||||
- Don't block scan if NFO creation fails
|
||||
- Retry queue for failed NFO creations
|
||||
- Enhanced logging for debugging
|
||||
- Background job for bulk operations
|
||||
|
||||
### Future API Integration (Separate Tasks)
|
||||
|
||||
@@ -176,11 +169,13 @@ The unit tests were written based on assumptions about the API that don't match
|
||||
|
||||
## 🐛 Known Issues / Future Enhancements
|
||||
|
||||
1. **NFOService.update_tvshow_nfo()** - Not implemented (optional)
|
||||
1. **NFOService.update_tvshow_nfo()** - ✅ **IMPLEMENTED**
|
||||
|
||||
- Currently raises `NotImplementedError`
|
||||
- Would need to parse existing NFO to extract TMDB ID
|
||||
- Then refetch and regenerate
|
||||
- Parses existing NFO to extract TMDB ID from uniqueid or tmdbid elements
|
||||
- Fetches fresh metadata from TMDB API
|
||||
- Regenerates NFO with updated data
|
||||
- Optionally re-downloads media files
|
||||
- Comprehensive error handling for edge cases
|
||||
|
||||
2. **Unit Tests** - Need refactoring (optional)
|
||||
|
||||
@@ -263,9 +258,9 @@ Task 3 is **95% Complete** and **Production Ready**.
|
||||
|
||||
**Optional Future Work (Not blocking):**
|
||||
|
||||
- Unit test refactoring (mocking strategy needs redesign)
|
||||
- update_tvshow_nfo() implementation
|
||||
- Advanced error recovery features
|
||||
- Unit test refactoring (mocking strategy needs redesign for async code)
|
||||
- ~~update_tvshow_nfo() implementation~~ ✅ **DONE**
|
||||
- Advanced error recovery features (retry queue, background jobs)
|
||||
|
||||
## ⏱️ Time Investment Summary
|
||||
|
||||
|
||||
@@ -165,17 +165,102 @@ async def check_nfo_status():
|
||||
return 0
|
||||
|
||||
|
||||
async def update_nfo_files():
|
||||
"""Update existing NFO files with fresh data from TMDB."""
|
||||
print("=" * 70)
|
||||
print("NFO Update Tool")
|
||||
print("=" * 70)
|
||||
|
||||
if not settings.tmdb_api_key:
|
||||
print("\n❌ Error: TMDB_API_KEY not configured")
|
||||
print(" Set TMDB_API_KEY in .env file or environment")
|
||||
print(" Get API key from: https://www.themoviedb.org/settings/api")
|
||||
return 1
|
||||
|
||||
if not settings.anime_directory:
|
||||
print("\n❌ Error: ANIME_DIRECTORY not configured")
|
||||
return 1
|
||||
|
||||
print(f"\nAnime Directory: {settings.anime_directory}")
|
||||
print(f"Download media: {settings.nfo_download_poster or settings.nfo_download_logo or settings.nfo_download_fanart}")
|
||||
|
||||
# Get series with NFO
|
||||
from src.core.entities.SerieList import SerieList
|
||||
serie_list = SerieList(settings.anime_directory)
|
||||
all_series = serie_list.get_all()
|
||||
series_with_nfo = [s for s in all_series if s.has_nfo()]
|
||||
|
||||
if not series_with_nfo:
|
||||
print("\n⚠️ No series with NFO files found")
|
||||
print(" Run 'scan' command first to create NFO files")
|
||||
return 0
|
||||
|
||||
print(f"\nFound {len(series_with_nfo)} series with NFO files")
|
||||
print("Updating NFO files with fresh data from TMDB...")
|
||||
print("(This may take a while)")
|
||||
|
||||
# Initialize NFO service
|
||||
from src.core.services.nfo_service import NFOService
|
||||
nfo_service = NFOService(
|
||||
tmdb_api_key=settings.tmdb_api_key,
|
||||
anime_directory=settings.anime_directory,
|
||||
image_size=settings.nfo_image_size
|
||||
)
|
||||
|
||||
success_count = 0
|
||||
error_count = 0
|
||||
|
||||
try:
|
||||
for i, serie in enumerate(series_with_nfo, 1):
|
||||
print(f"\n[{i}/{len(series_with_nfo)}] Updating: {serie.name}")
|
||||
|
||||
try:
|
||||
await nfo_service.update_tvshow_nfo(
|
||||
serie_folder=serie.folder,
|
||||
download_media=(
|
||||
settings.nfo_download_poster or
|
||||
settings.nfo_download_logo or
|
||||
settings.nfo_download_fanart
|
||||
)
|
||||
)
|
||||
print(f" ✅ Updated successfully")
|
||||
success_count += 1
|
||||
|
||||
# Small delay to respect API rate limits
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Error: {e}")
|
||||
error_count += 1
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print(f"✅ Update complete!")
|
||||
print(f" Success: {success_count}")
|
||||
print(f" Errors: {error_count}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ Fatal error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return 1
|
||||
finally:
|
||||
await nfo_service.close()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def main():
|
||||
"""Main CLI entry point."""
|
||||
if len(sys.argv) < 2:
|
||||
print("NFO Management Tool")
|
||||
print("\nUsage:")
|
||||
print(" python -m src.cli.nfo_cli scan # Scan and create/update NFO files")
|
||||
print(" python -m src.cli.nfo_cli scan # Scan and create missing NFO files")
|
||||
print(" python -m src.cli.nfo_cli status # Check NFO status for all series")
|
||||
print(" python -m src.cli.nfo_cli update # Update existing NFO files with fresh data")
|
||||
print("\nConfiguration:")
|
||||
print(" Set TMDB_API_KEY in .env file")
|
||||
print(" Set NFO_AUTO_CREATE=true to enable auto-creation")
|
||||
print(" Set NFO_UPDATE_ON_SCAN=true to update existing NFOs")
|
||||
print(" Set NFO_UPDATE_ON_SCAN=true to update existing NFOs during scan")
|
||||
return 1
|
||||
|
||||
command = sys.argv[1].lower()
|
||||
@@ -184,9 +269,11 @@ def main():
|
||||
return asyncio.run(scan_and_create_nfo())
|
||||
elif command == "status":
|
||||
return asyncio.run(check_nfo_status())
|
||||
elif command == "update":
|
||||
return asyncio.run(update_nfo_files())
|
||||
else:
|
||||
print(f"Unknown command: {command}")
|
||||
print("Use 'scan' or 'status'")
|
||||
print("Use 'scan', 'status', or 'update'")
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user