Moves perform_nfo_repair_scan and its helpers (_repair_one_series, _NFO_REPAIR_SEMAPHORE) into folder_scan_service.py so NFO repair runs during the scheduled folder scan instead of on startup. - Removes NFO repair code from initialization_service.py - Updates all test imports and patch targets - Updates docs/NFO_GUIDE.md and docs/CHANGELOG.md references All 174 related tests pass.
839 lines
23 KiB
Markdown
839 lines
23 KiB
Markdown
# NFO Metadata Guide
|
|
|
|
## Document Purpose
|
|
|
|
This guide explains how to use the NFO metadata feature to enrich your anime library with TMDB metadata and artwork for Plex, Jellyfin, Emby, and Kodi.
|
|
|
|
---
|
|
|
|
## 1. Overview
|
|
|
|
### What are NFO Files?
|
|
|
|
NFO files are XML documents that contain metadata about TV shows and episodes. Media servers like Plex, Jellyfin, Emby, and Kodi use these files to display information about your library without needing to scrape external sources.
|
|
|
|
### Features
|
|
|
|
- **Automatic NFO Creation**: Generate NFO files during downloads
|
|
- **TMDB Integration**: Fetch metadata from The Movie Database
|
|
- **Image Downloads**: Poster, fanart, and logo images
|
|
- **Batch Operations**: Create/update NFO files for multiple anime
|
|
- **Web UI**: Manage NFO settings and operations
|
|
- **API Access**: Programmatic NFO management
|
|
|
|
---
|
|
|
|
## 2. Getting Started
|
|
|
|
### 2.1 Obtain TMDB API Key
|
|
|
|
1. Create a free account at https://www.themoviedb.org
|
|
2. Navigate to https://www.themoviedb.org/settings/api
|
|
3. Request an API key (select "Developer" option)
|
|
4. Copy your API key (v3 auth)
|
|
|
|
### 2.2 Configure NFO Settings
|
|
|
|
#### Via Web Interface
|
|
|
|
1. Open http://127.0.0.1:8000
|
|
2. Click **Configuration** button
|
|
3. Scroll to **NFO Settings** section
|
|
4. Enter your TMDB API key
|
|
5. Click **Test Connection** to verify
|
|
6. Configure options:
|
|
- **Auto-create during downloads**: Enable to create NFO files automatically
|
|
- **Update on library scan**: Enable to refresh existing NFO files
|
|
- **Download poster**: Episode and show poster images (poster.jpg)
|
|
- **Download logo**: Show logo images (logo.png)
|
|
- **Download fanart**: Background artwork (fanart.jpg)
|
|
- **Image size**: Select w500 (recommended), w780, or original
|
|
7. Click **Save**
|
|
|
|
#### Via Environment Variables
|
|
|
|
Add to your `.env` file:
|
|
|
|
```bash
|
|
TMDB_API_KEY=your_api_key_here
|
|
NFO_AUTO_CREATE=true
|
|
NFO_UPDATE_ON_SCAN=false
|
|
NFO_DOWNLOAD_POSTER=true
|
|
NFO_DOWNLOAD_LOGO=false
|
|
NFO_DOWNLOAD_FANART=false
|
|
NFO_IMAGE_SIZE=w500
|
|
```
|
|
|
|
#### Via config.json
|
|
|
|
Edit `data/config.json`:
|
|
|
|
```json
|
|
{
|
|
"nfo": {
|
|
"tmdb_api_key": "your_api_key_here",
|
|
"auto_create": true,
|
|
"update_on_scan": false,
|
|
"download_poster": true,
|
|
"download_logo": false,
|
|
"download_fanart": false,
|
|
"image_size": "w500"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Using NFO Features
|
|
|
|
### 3.1 Automatic NFO Creation
|
|
|
|
With `auto_create` enabled, NFO files are created automatically when downloading episodes:
|
|
|
|
1. Add episodes to download queue
|
|
2. Start queue processing
|
|
3. NFO files are created after successful downloads
|
|
4. Images are downloaded based on configuration
|
|
|
|
### 3.2 Manual NFO Creation
|
|
|
|
#### Via Web Interface
|
|
|
|
1. Navigate to the main page
|
|
2. Click **Create NFO** button next to an anime
|
|
3. Wait for completion notification
|
|
|
|
#### Via API
|
|
|
|
```bash
|
|
curl -X POST "http://127.0.0.1:8000/api/nfo/create" \
|
|
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"anime_id": 123,
|
|
"folder_path": "/path/to/anime/Attack on Titan"
|
|
}'
|
|
```
|
|
|
|
### 3.3 Batch NFO Creation
|
|
|
|
Create NFO files for multiple anime at once:
|
|
|
|
```bash
|
|
curl -X POST "http://127.0.0.1:8000/api/nfo/batch/create" \
|
|
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"anime_ids": [123, 456, 789]
|
|
}'
|
|
```
|
|
|
|
### 3.4 Update Existing NFO Files
|
|
|
|
Update NFO files with latest TMDB metadata:
|
|
|
|
```bash
|
|
curl -X POST "http://127.0.0.1:8000/api/nfo/update" \
|
|
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"anime_id": 123,
|
|
"folder_path": "/path/to/anime/Attack on Titan",
|
|
"force": true
|
|
}'
|
|
```
|
|
|
|
### 3.5 Check NFO Status
|
|
|
|
Check which anime have NFO files:
|
|
|
|
```bash
|
|
curl -X GET "http://127.0.0.1:8000/api/nfo/check?folder_path=/path/to/anime" \
|
|
-H "Authorization: Bearer YOUR_JWT_TOKEN"
|
|
```
|
|
|
|
Response:
|
|
|
|
```json
|
|
{
|
|
"has_tvshow_nfo": true,
|
|
"episode_nfos": [
|
|
{
|
|
"season": 1,
|
|
"episode": 1,
|
|
"has_nfo": true,
|
|
"file_path": "/path/to/anime/Season 1/S01E01.nfo"
|
|
}
|
|
],
|
|
"missing_episodes": [],
|
|
"total_episodes": 25,
|
|
"nfo_count": 25
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 4. File Structure
|
|
|
|
### 4.1 NFO File Locations
|
|
|
|
NFO files are created in the anime directory:
|
|
|
|
```
|
|
/path/to/anime/Attack on Titan/
|
|
├── tvshow.nfo # Show metadata
|
|
├── poster.jpg # Show poster (optional)
|
|
├── logo.png # Show logo (optional)
|
|
├── fanart.jpg # Show fanart (optional)
|
|
├── Season 1/
|
|
│ ├── S01E01.mkv
|
|
│ ├── S01E01.nfo # Episode metadata
|
|
│ ├── S01E01-thumb.jpg # Episode thumbnail (optional)
|
|
│ ├── S01E02.mkv
|
|
│ └── S01E02.nfo
|
|
└── Season 2/
|
|
├── S02E01.mkv
|
|
└── S02E01.nfo
|
|
```
|
|
|
|
### 4.2 tvshow.nfo Format
|
|
|
|
```xml
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<tvshow>
|
|
<title>Attack on Titan</title>
|
|
<originaltitle>進撃の巨人</originaltitle>
|
|
<showtitle>Attack on Titan</showtitle>
|
|
<sorttitle>Attack on Titan</sorttitle>
|
|
<rating>8.5</rating>
|
|
<year>2013</year>
|
|
<plot>Humans are nearly exterminated by giant creatures...</plot>
|
|
<runtime>24</runtime>
|
|
<mpaa>TV-MA</mpaa>
|
|
<premiered>2013-04-07</premiered>
|
|
<status>Ended</status>
|
|
<studio>Wit Studio</studio>
|
|
<genre>Animation</genre>
|
|
<genre>Action</genre>
|
|
<genre>Sci-Fi & Fantasy</genre>
|
|
<uniqueid type="tmdb">1429</uniqueid>
|
|
<thumb aspect="poster">https://image.tmdb.org/t/p/w500/...</thumb>
|
|
<fanart>
|
|
<thumb>https://image.tmdb.org/t/p/original/...</thumb>
|
|
</fanart>
|
|
</tvshow>
|
|
```
|
|
|
|
### 4.3 Episode NFO Format
|
|
|
|
```xml
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<episodedetails>
|
|
<title>To You, in 2000 Years: The Fall of Shiganshina, Part 1</title>
|
|
<showtitle>Attack on Titan</showtitle>
|
|
<season>1</season>
|
|
<episode>1</episode>
|
|
<displayseason>1</displayseason>
|
|
<displayepisode>1</displayepisode>
|
|
<plot>After a hundred years of peace...</plot>
|
|
<runtime>24</runtime>
|
|
<aired>2013-04-07</aired>
|
|
<rating>8.2</rating>
|
|
<uniqueid type="tmdb">63056</uniqueid>
|
|
<thumb>https://image.tmdb.org/t/p/w500/...</thumb>
|
|
</episodedetails>
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Folder Naming Convention
|
|
|
|
### 5.1 Expected Format
|
|
|
|
After the daily folder scan (when **Update on library scan** is enabled), Aniworld validates every series folder against its `tvshow.nfo` metadata. If the folder name does not match the expected convention, it is automatically renamed.
|
|
|
|
**Format:**
|
|
|
|
```
|
|
{title} ({year})
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
| NFO `<title>` | NFO `<year>` | Expected Folder Name |
|
|
|---------------|--------------|----------------------|
|
|
| `Attack on Titan` | `2013` | `Attack on Titan (2013)` |
|
|
| `One Piece` | `1999` | `One Piece (1999)` |
|
|
| `Demon Slayer: Kimetsu no Yaiba` | `2019` | `Demon Slayer Kimetsu no Yaiba (2019)` |
|
|
|
|
### 5.2 Sanitization Rules
|
|
|
|
Illegal filesystem characters are removed or replaced to ensure cross-platform compatibility:
|
|
|
|
- Removed: `< > : " / \ | ? *` and null bytes
|
|
- Control characters stripped
|
|
- Multiple spaces collapsed to one
|
|
- Leading/trailing dots and whitespace trimmed
|
|
- Maximum length: 200 characters (truncated at word boundary if possible)
|
|
|
|
### 5.3 Skip Conditions
|
|
|
|
A folder is **not** renamed when any of the following apply:
|
|
|
|
- `tvshow.nfo` is missing `<title>` or `<year>` (or they are empty)
|
|
- The series has an **active or pending download**
|
|
- The target folder name already exists (duplicate)
|
|
- The resulting path would exceed the OS path-length limit
|
|
- The app lacks write permission to the anime directory
|
|
|
|
All skipped and renamed actions are logged.
|
|
|
|
---
|
|
|
|
## 6. Poster Check
|
|
|
|
### 6.1 Overview
|
|
|
|
During the daily folder scan, Aniworld checks every series folder for a valid `poster.jpg`. If the file is missing or smaller than 1 KB, the application attempts to re-download it from the URL stored in the series' `tvshow.nfo` file.
|
|
|
|
### 6.2 How It Works
|
|
|
|
1. **Scan** — After folder renaming, the scan iterates over all series folders that contain a `tvshow.nfo`.
|
|
2. **Validate** — For each folder, it checks whether `poster.jpg` exists and is at least 1 KB.
|
|
3. **Parse NFO** — If the poster is missing or too small, the scan reads `tvshow.nfo` and looks for a `<thumb aspect="poster">` (or any `<thumb>`) URL.
|
|
4. **Download** — If a URL is found, the poster is downloaded using `ImageDownloader` with a concurrency limit of 3 simultaneous downloads.
|
|
5. **Validate Download** — The downloaded image is validated with PIL to ensure it is not corrupted.
|
|
|
|
### 6.3 Skip Conditions
|
|
|
|
A folder is **not** processed for poster download when any of the following apply:
|
|
|
|
- `tvshow.nfo` does not exist in the folder.
|
|
- `poster.jpg` already exists and is ≥ 1 KB.
|
|
- No `<thumb>` URL is found in the NFO (the NFO may have been created before thumb tags were added).
|
|
- The `nfo.download_poster` setting is `false` (poster checks are still performed, but downloads are skipped if the setting is disabled; see [CONFIGURATION.md](CONFIGURATION.md)).
|
|
|
|
### 6.4 Logging
|
|
|
|
Every poster check action is logged:
|
|
|
|
- **INFO** — When a poster is successfully downloaded.
|
|
- **WARNING** — When a download fails or no URL is found.
|
|
- **ERROR** — When an unexpected exception occurs during download.
|
|
|
|
---
|
|
|
|
## 7. API Reference
|
|
|
|
### 5.1 Check NFO Status
|
|
|
|
**Endpoint**: `GET /api/nfo/check`
|
|
|
|
**Query Parameters**:
|
|
|
|
- `folder_path` (required): Absolute path to anime directory
|
|
|
|
**Response**:
|
|
|
|
```json
|
|
{
|
|
"has_tvshow_nfo": true,
|
|
"episode_nfos": [
|
|
{
|
|
"season": 1,
|
|
"episode": 1,
|
|
"has_nfo": true,
|
|
"file_path": "/path/to/S01E01.nfo"
|
|
}
|
|
],
|
|
"missing_episodes": [],
|
|
"total_episodes": 25,
|
|
"nfo_count": 25
|
|
}
|
|
```
|
|
|
|
### 5.2 Create NFO Files
|
|
|
|
**Endpoint**: `POST /api/nfo/create`
|
|
|
|
**Request Body**:
|
|
|
|
```json
|
|
{
|
|
"anime_id": 123,
|
|
"folder_path": "/path/to/anime/Attack on Titan"
|
|
}
|
|
```
|
|
|
|
**Response**:
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "NFO files created successfully",
|
|
"files_created": ["tvshow.nfo", "S01E01.nfo", "S01E02.nfo"],
|
|
"images_downloaded": ["poster.jpg", "S01E01-thumb.jpg"]
|
|
}
|
|
```
|
|
|
|
### 5.3 Update NFO Files
|
|
|
|
**Endpoint**: `POST /api/nfo/update`
|
|
|
|
**Request Body**:
|
|
|
|
```json
|
|
{
|
|
"anime_id": 123,
|
|
"folder_path": "/path/to/anime",
|
|
"force": false
|
|
}
|
|
```
|
|
|
|
**Response**:
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "NFO files updated successfully",
|
|
"files_updated": ["tvshow.nfo", "S01E01.nfo"]
|
|
}
|
|
```
|
|
|
|
### 5.4 View NFO Content
|
|
|
|
**Endpoint**: `GET /api/nfo/view`
|
|
|
|
**Query Parameters**:
|
|
|
|
- `file_path` (required): Absolute path to NFO file
|
|
|
|
**Response**:
|
|
|
|
```json
|
|
{
|
|
"content": "<?xml version=\"1.0\"...?>",
|
|
"file_path": "/path/to/tvshow.nfo",
|
|
"exists": true
|
|
}
|
|
```
|
|
|
|
### 5.5 Get Media Status
|
|
|
|
**Endpoint**: `GET /api/nfo/media/status`
|
|
|
|
**Query Parameters**:
|
|
|
|
- `folder_path` (required): Absolute path to anime directory
|
|
|
|
**Response**:
|
|
|
|
```json
|
|
{
|
|
"poster_exists": true,
|
|
"poster_path": "/path/to/poster.jpg",
|
|
"logo_exists": false,
|
|
"logo_path": null,
|
|
"fanart_exists": true,
|
|
"fanart_path": "/path/to/fanart.jpg",
|
|
"episode_thumbs": [
|
|
{
|
|
"season": 1,
|
|
"episode": 1,
|
|
"exists": true,
|
|
"path": "/path/to/S01E01-thumb.jpg"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 5.6 Download Media
|
|
|
|
**Endpoint**: `POST /api/nfo/media/download`
|
|
|
|
**Request Body**:
|
|
|
|
```json
|
|
{
|
|
"folder_path": "/path/to/anime",
|
|
"anime_id": 123,
|
|
"download_poster": true,
|
|
"download_logo": false,
|
|
"download_fanart": false,
|
|
"image_size": "w500"
|
|
}
|
|
```
|
|
|
|
**Response**:
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Media downloaded successfully",
|
|
"downloaded": ["poster.jpg", "S01E01-thumb.jpg"]
|
|
}
|
|
```
|
|
|
|
### 5.7 Batch Create NFO
|
|
|
|
**Endpoint**: `POST /api/nfo/batch/create`
|
|
|
|
**Request Body**:
|
|
|
|
```json
|
|
{
|
|
"anime_ids": [123, 456, 789]
|
|
}
|
|
```
|
|
|
|
**Response**:
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"results": [
|
|
{
|
|
"anime_id": 123,
|
|
"success": true,
|
|
"message": "Created successfully"
|
|
},
|
|
{
|
|
"anime_id": 456,
|
|
"success": false,
|
|
"error": "Folder not found"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 5.8 Find Missing NFOs
|
|
|
|
**Endpoint**: `GET /api/nfo/missing`
|
|
|
|
**Response**:
|
|
|
|
```json
|
|
{
|
|
"anime_list": [
|
|
{
|
|
"anime_id": 123,
|
|
"title": "Attack on Titan",
|
|
"folder_path": "/path/to/anime/Attack on Titan",
|
|
"missing_tvshow_nfo": false,
|
|
"missing_episode_count": 3,
|
|
"total_episodes": 25
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Troubleshooting
|
|
|
|
### 6.1 NFO Files Not Created
|
|
|
|
**Problem**: NFO files are not being created during downloads.
|
|
|
|
**Solutions**:
|
|
|
|
1. Verify TMDB API key is configured correctly
|
|
2. Check `auto_create` is enabled in settings
|
|
3. Ensure anime directory has write permissions
|
|
4. Check logs for error messages
|
|
5. Test TMDB connection using "Test Connection" button
|
|
|
|
### 6.2 Invalid TMDB API Key
|
|
|
|
**Problem**: TMDB validation fails with "Invalid API key".
|
|
|
|
**Solutions**:
|
|
|
|
1. Verify API key is copied correctly (no extra spaces)
|
|
2. Ensure you're using the v3 API key (not v4)
|
|
3. Check API key is active on TMDB website
|
|
4. Try regenerating API key on TMDB
|
|
|
|
### 6.3 Images Not Downloading
|
|
|
|
**Problem**: NFO files are created but images are missing.
|
|
|
|
**Solutions**:
|
|
|
|
1. Enable image downloads in settings (poster/logo/fanart)
|
|
2. Verify TMDB API key is valid
|
|
3. Check network connectivity to TMDB servers
|
|
4. Ensure sufficient disk space
|
|
5. Check file permissions in anime directory
|
|
|
|
### 6.4 Incorrect Metadata
|
|
|
|
**Problem**: NFO contains wrong show information.
|
|
|
|
**Solutions**:
|
|
|
|
1. Verify anime title matches TMDB exactly
|
|
2. Use TMDB ID if available for accurate matching
|
|
3. Update NFO files with `force=true` to refresh metadata
|
|
4. Check TMDB website for correct show information
|
|
|
|
### 6.5 Permission Errors
|
|
|
|
**Problem**: "Permission denied" when creating NFO files.
|
|
|
|
**Solutions**:
|
|
|
|
1. Check anime directory permissions: `chmod 755 /path/to/anime`
|
|
2. Ensure application user has write access
|
|
3. Verify directory ownership: `chown -R user:group /path/to/anime`
|
|
4. Check parent directories are accessible
|
|
|
|
### 6.6 Slow NFO Creation
|
|
|
|
**Problem**: NFO creation takes a long time.
|
|
|
|
**Solutions**:
|
|
|
|
1. Reduce image size (use w500 instead of original)
|
|
2. Disable unnecessary images (logo, fanart)
|
|
3. Create NFOs in batches during off-peak hours
|
|
4. Check network speed to TMDB servers
|
|
5. Verify disk I/O performance
|
|
|
|
---
|
|
|
|
## 7. Best Practices
|
|
|
|
### 7.1 Configuration Recommendations
|
|
|
|
- **Image Size**: Use `w500` for optimal balance of quality and storage
|
|
- **Auto-create**: Enable for new downloads
|
|
- **Update on scan**: Disable to avoid unnecessary TMDB API calls
|
|
- **Poster**: Always enable for show and episode thumbnails
|
|
- **Logo/Fanart**: Enable only if your media server supports them
|
|
|
|
### 7.2 Maintenance
|
|
|
|
- **Regular Updates**: Update NFO files quarterly to get latest metadata
|
|
- **Backup**: Include NFO files in your backup strategy
|
|
- **Validation**: Periodically check missing NFOs using `/api/nfo/missing`
|
|
- **API Rate Limits**: Be mindful of TMDB API rate limits when batch processing
|
|
|
|
### 7.3 Performance
|
|
|
|
- **Batch Operations**: Use batch endpoints for multiple anime
|
|
- **Off-Peak Processing**: Create NFOs during low-activity periods
|
|
- **Image Optimization**: Use smaller image sizes for large libraries
|
|
- **Selective Updates**: Only update NFOs when metadata changes
|
|
|
|
### 7.4 Media Server Integration
|
|
|
|
#### Plex
|
|
|
|
- Use "Personal Media Shows" agent
|
|
- Enable "Local Media Assets" scanner
|
|
- Place NFO files in anime directories
|
|
- Refresh metadata after creating NFOs
|
|
|
|
#### Jellyfin
|
|
|
|
- Use "NFO" metadata provider
|
|
- Enable in Library settings
|
|
- Order providers: NFO first, then online sources
|
|
- Scan library after NFO creation
|
|
|
|
#### Emby
|
|
|
|
- Enable "NFO" metadata reader
|
|
- Configure in Library advanced settings
|
|
- Use "Prefer embedded metadata" option
|
|
- Refresh metadata after updates
|
|
|
|
#### Kodi
|
|
|
|
- NFO files are automatically detected
|
|
- No additional configuration needed
|
|
- Update library to see changes
|
|
|
|
---
|
|
|
|
## 8. Advanced Usage
|
|
|
|
### 8.1 Custom NFO Templates
|
|
|
|
You can customize NFO generation by modifying the NFO service:
|
|
|
|
```python
|
|
# src/core/services/nfo_creator.py
|
|
def generate_tvshow_nfo(self, metadata: dict) -> str:
|
|
# Add custom fields or modify structure
|
|
pass
|
|
```
|
|
|
|
### 8.2 Bulk Operations
|
|
|
|
Create NFOs for entire library:
|
|
|
|
```bash
|
|
# Get all anime without NFOs
|
|
curl -X GET "http://127.0.0.1:8000/api/nfo/missing" \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
| jq -r '.anime_list[].anime_id' \
|
|
| xargs -I{} curl -X POST "http://127.0.0.1:8000/api/nfo/batch/create" \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"anime_ids": [{}]}'
|
|
```
|
|
|
|
### 8.3 Scheduled Updates
|
|
|
|
Use the scheduler API to refresh NFOs automatically:
|
|
|
|
```bash
|
|
# Schedule weekly NFO updates (rescan runs Sunday at 03:00)
|
|
curl -X POST "http://127.0.0.1:8000/api/scheduler/config" \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"enabled": true,
|
|
"schedule_time": "03:00",
|
|
"schedule_days": ["sun"],
|
|
"auto_download_after_rescan": false
|
|
}'
|
|
```
|
|
|
|
---
|
|
|
|
## 9. Related Documentation
|
|
|
|
- [API.md](API.md) - Complete API reference
|
|
- [CONFIGURATION.md](CONFIGURATION.md) - All configuration options
|
|
- [ARCHITECTURE.md](ARCHITECTURE.md) - System architecture
|
|
- [DEVELOPMENT.md](DEVELOPMENT.md) - Development guide
|
|
|
|
---
|
|
|
|
## 10. Tag Reference
|
|
|
|
The table below lists every XML tag written to `tvshow.nfo` and its source in
|
|
the TMDB API response. All tags are written whenever the NFO is created or
|
|
updated via `create_tvshow_nfo()` / `update_tvshow_nfo()`.
|
|
|
|
| NFO tag | TMDB source field | Required |
|
|
| --------------- | ----------------------------------------------------- | -------- |
|
|
| `title` | `name` | ✅ |
|
|
| `originaltitle` | `original_name` | ✅ |
|
|
| `showtitle` | `name` (same as `title`) | ✅ |
|
|
| `sorttitle` | `name` (same as `title`) | ✅ |
|
|
| `year` | First 4 chars of `first_air_date` | ✅ |
|
|
| `plot` | `overview` | ✅ |
|
|
| `outline` | `overview` (same as `plot`) | ✅ |
|
|
| `tagline` | `tagline` | optional |
|
|
| `runtime` | `episode_run_time[0]` | ✅ |
|
|
| `premiered` | `first_air_date` | ✅ |
|
|
| `status` | `status` | ✅ |
|
|
| `mpaa` | US content rating from `content_ratings.results` | optional |
|
|
| `fsk` | DE content rating (written as `mpaa` when preferred) | optional |
|
|
| `imdbid` | `external_ids.imdb_id` | ✅ |
|
|
| `tmdbid` | `id` | ✅ |
|
|
| `tvdbid` | `external_ids.tvdb_id` | optional |
|
|
| `genre` | `genres[].name` (one element per genre) | ✅ |
|
|
| `studio` | `networks[].name` (one element per network) | ✅ |
|
|
| `country` | `origin_country[]` or `production_countries[].name` | ✅ |
|
|
| `actor` | `credits.cast[]` (top 10, with name/role/thumb) | ✅ |
|
|
| `watched` | Always `false` on creation | ✅ |
|
|
| `dateadded` | System clock at creation time (`YYYY-MM-DD HH:MM:SS`) | ✅ |
|
|
|
|
The mapping logic lives in `src/core/utils/nfo_mapper.py` (`tmdb_to_nfo_model`).
|
|
The XML serialisation lives in `src/core/utils/nfo_generator.py`
|
|
(`generate_tvshow_nfo`).
|
|
|
|
---
|
|
|
|
## 11. Automatic NFO Repair
|
|
|
|
NFO repair now runs as part of the scheduled daily folder scan rather than on every
|
|
startup. When the scheduler triggers `FolderScanService.run_folder_scan()`, the first
|
|
step is `perform_nfo_repair_scan(background_loader=None)`. Each incomplete NFO is
|
|
queued as a background `asyncio` task, so the scan returns quickly while repairs
|
|
continue asynchronously.
|
|
|
|
### How It Works
|
|
|
|
1. **Scan** — `perform_nfo_repair_scan()` in
|
|
`src/server/services/initialization_service.py` is called from
|
|
`FolderScanService.run_folder_scan()` (`src/server/services/folder_scan_service.py`).
|
|
2. **Detect** — `nfo_needs_repair(nfo_path)` from
|
|
`src/core/services/nfo_repair_service.py` parses each `tvshow.nfo` with
|
|
`lxml` and checks for the 13 required tags listed below.
|
|
3. **Repair** — Series whose NFO is incomplete are queued for background reload
|
|
via `asyncio.create_task`. Each task creates its own isolated
|
|
:class:`NFOService` / :class:`TMDBClient` so concurrent tasks never share an
|
|
``aiohttp`` session — this prevents "Connector is closed" errors when many repairs
|
|
run in parallel. A semaphore caps TMDB concurrency at 3 to stay within rate limits.
|
|
|
|
### Tags Checked (13 required)
|
|
|
|
| XPath | Tag name |
|
|
| ----------------- | --------------- |
|
|
| `./title` | `title` |
|
|
| `./originaltitle` | `originaltitle` |
|
|
| `./year` | `year` |
|
|
| `./plot` | `plot` |
|
|
| `./runtime` | `runtime` |
|
|
| `./premiered` | `premiered` |
|
|
| `./status` | `status` |
|
|
| `./imdbid` | `imdbid` |
|
|
| `./genre` | `genre` |
|
|
| `./studio` | `studio` |
|
|
| `./country` | `country` |
|
|
| `./actor/name` | `actor/name` |
|
|
| `./watched` | `watched` |
|
|
|
|
### Log Messages
|
|
|
|
| Message | Meaning |
|
|
| ----------------------------------------------------------- | ------------------------------------------------- |
|
|
| `NFO repair scan complete: 0 of N series queued for repair` | All NFOs are complete — no action needed |
|
|
| `NFO repair scan complete: X of N series queued for repair` | X series had incomplete NFOs and have been queued |
|
|
| `NFO repair scan skipped: TMDB API key not configured` | Set `tmdb_api_key` in `data/config.json` |
|
|
| `NFO repair scan skipped: anime directory not configured` | Set `anime_directory` in `data/config.json` |
|
|
|
|
### Triggering a Manual Repair
|
|
|
|
You can also repair a single series on demand via the API:
|
|
|
|
```http
|
|
POST /api/nfo/update/{series_key}
|
|
```
|
|
|
|
This calls `NFOService.update_tvshow_nfo()` directly and overwrites the existing
|
|
`tvshow.nfo` with fresh data from TMDB.
|
|
|
|
### Source Files
|
|
|
|
| File | Purpose |
|
|
| ----------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
| `src/core/services/nfo_repair_service.py` | `REQUIRED_TAGS`, `parse_nfo_tags`, `find_missing_tags`, `nfo_needs_repair`, `NfoRepairService` |
|
|
| `src/server/services/folder_scan_service.py` | `perform_nfo_repair_scan` — invoked during the scheduled daily folder scan |
|
|
|
|
---
|
|
|
|
## 12. Support
|
|
|
|
### Getting Help
|
|
|
|
- Check logs in `logs/` directory for error details
|
|
- Review [TESTING.md](TESTING.md) for test coverage
|
|
- Consult [DATABASE.md](DATABASE.md) for NFO status schema
|
|
|
|
### Common Issues
|
|
|
|
See section 6 (Troubleshooting) for solutions to common problems.
|
|
|
|
### TMDB Resources
|
|
|
|
- TMDB API Documentation: https://developers.themoviedb.org/3
|
|
- TMDB Support: https://www.themoviedb.org/talk
|
|
- TMDB API Status: https://status.themoviedb.org/
|