Browse Source

clean up old show artwork; properly update season artwork

pull/2778/head
Jason Dove 7 months ago
parent
commit
1837fb7c56
No known key found for this signature in database
  1. 2
      CHANGELOG.md
  2. 34
      ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs
  3. 9
      ErsatzTV.Scanner/Core/Metadata/LocalMetadataProvider.cs
  4. 66
      ErsatzTV.Scanner/Core/Metadata/TelevisionFolderScanner.cs

2
CHANGELOG.md

@ -25,7 +25,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -25,7 +25,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix 500 errors when serving XMLTV due to concurrent file reads and writes
- Fix playback of AC3 audio when targeting stereo output and input layout changes mid-stream
- Use other video artwork in XMLTV template
- Remove artwork from other videos when artwork has been removed from disk
- Properly update (add or remove) artwork for all local media libraries when files have changed
## [26.1.1] - 2026-01-08
### Fixed

34
ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs

@ -271,17 +271,18 @@ public class TelevisionRepository : ITelevisionRepository @@ -271,17 +271,18 @@ public class TelevisionRepository : ITelevisionRepository
try
{
metadata.DateAdded = DateTime.UtcNow;
metadata.Genres ??= new List<Genre>();
metadata.Tags ??= new List<Tag>();
metadata.Studios ??= new List<Studio>();
metadata.Actors ??= new List<Actor>();
metadata.Guids ??= new List<MetadataGuid>();
metadata.Genres ??= [];
metadata.Tags ??= [];
metadata.Studios ??= [];
metadata.Actors ??= [];
metadata.Guids ??= [];
metadata.Artwork ??= [];
var show = new Show
{
LibraryPathId = libraryPathId,
ShowMetadata = new List<ShowMetadata> { metadata },
Seasons = new List<Season>(),
TraktListItems = new List<TraktListItem>()
ShowMetadata = [metadata],
Seasons = [],
TraktListItems = []
};
await dbContext.Shows.AddAsync(show);
@ -670,17 +671,18 @@ public class TelevisionRepository : ITelevisionRepository @@ -670,17 +671,18 @@ public class TelevisionRepository : ITelevisionRepository
LibraryPathId = libraryPathId,
ShowId = show.Id,
SeasonNumber = seasonNumber,
Episodes = new List<Episode>(),
SeasonMetadata = new List<SeasonMetadata>
{
new()
Episodes = [],
SeasonMetadata =
[
new SeasonMetadata
{
DateAdded = DateTime.UtcNow,
Guids = new List<MetadataGuid>(),
Tags = new List<Tag>()
Guids = [],
Tags = [],
Artwork = []
}
},
TraktListItems = new List<TraktListItem>()
],
TraktListItems = []
};
await dbContext.Seasons.AddAsync(season);
await dbContext.SaveChangesAsync();

9
ErsatzTV.Scanner/Core/Metadata/LocalMetadataProvider.cs

@ -563,7 +563,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider @@ -563,7 +563,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider
{
var updated = false;
episode.EpisodeMetadata ??= new List<EpisodeMetadata>();
episode.EpisodeMetadata ??= [];
var toUpdate = episode.EpisodeMetadata
.Where(em => episodeMetadata.Any(em2 => em2.EpisodeNumber == em.EpisodeNumber))
@ -1317,7 +1317,8 @@ public class LocalMetadataProvider : ILocalMetadataProvider @@ -1317,7 +1317,8 @@ public class LocalMetadataProvider : ILocalMetadataProvider
Actors = Actors(nfo.Actors, dateAdded, dateUpdated),
Guids = nfo.UniqueIds
.Map(id => new MetadataGuid { Guid = $"{id.Type}://{id.Guid}" })
.ToList()
.ToList(),
Artwork = []
};
}
@ -1409,8 +1410,8 @@ public class LocalMetadataProvider : ILocalMetadataProvider @@ -1409,8 +1410,8 @@ public class LocalMetadataProvider : ILocalMetadataProvider
Writers = nfo.Writers.Map(w => new Writer { Name = w }).ToList(),
Genres = nfo.Genres.Map(g => new Genre { Name = g }).ToList(),
Tags = nfo.Tags.Map(t => new Tag { Name = t }).ToList(),
Studios = new List<Studio>(),
Artwork = new List<Artwork>()
Studios = [],
Artwork = []
};
result.Add(metadata);

66
ErsatzTV.Scanner/Core/Metadata/TelevisionFolderScanner.cs

@ -248,17 +248,15 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan @@ -248,17 +248,15 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan
maybeParentFolder,
seasonFolder);
// skip folder if etag matches
if (knownFolder.Etag == etag)
// cache etag match for later checking
// we still need to scan the season folder in case season artwork has changed
bool etagMatch = knownFolder.Etag == etag;
if (etagMatch)
{
if (allTrashedItems.Any(f => f.StartsWith(seasonFolder, StringComparison.OrdinalIgnoreCase)))
{
_logger.LogDebug("Previously trashed items are now present in folder {Folder}", seasonFolder);
}
else
{
// etag matches and no trashed items are now present, continue to next folder
continue;
etagMatch = false;
}
}
@ -280,6 +278,12 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan @@ -280,6 +278,12 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan
foreach (Season season in maybeSeason.RightToSeq())
{
// skip scanning episodes when season folder etag matches
if (etagMatch)
{
continue;
}
Either<BaseError, Unit> scanResult = await ScanEpisodes(
libraryPath,
knownFolder,
@ -410,7 +414,7 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan @@ -410,7 +414,7 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan
private async Task<Either<BaseError, Season>> EnsureMetadataExists(Season season)
{
season.SeasonMetadata ??= new List<SeasonMetadata>();
season.SeasonMetadata ??= [];
if (season.SeasonMetadata.Count == 0)
{
@ -419,8 +423,9 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan @@ -419,8 +423,9 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan
SeasonId = season.Id,
Season = season,
DateAdded = DateTime.UtcNow,
Guids = new List<MetadataGuid>(),
Tags = new List<Tag>()
Guids = [],
Tags = [],
Artwork = []
};
season.SeasonMetadata.Add(metadata);
@ -492,11 +497,18 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan @@ -492,11 +497,18 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan
try
{
Show show = result.Item;
Option<string> maybeArtwork = LocateArtworkForShow(showFolder, artworkKind);
foreach (string artworkFile in maybeArtwork)
foreach (ShowMetadata metadata in show.ShowMetadata.HeadOrNone())
{
ShowMetadata metadata = show.ShowMetadata.Head();
await RefreshArtwork(artworkFile, metadata, artworkKind, None, None, cancellationToken);
Option<string> maybeArtwork = LocateArtworkForShow(showFolder, artworkKind);
foreach (string artworkFile in maybeArtwork)
{
await RefreshArtwork(artworkFile, metadata, artworkKind, None, None, cancellationToken);
}
if (maybeArtwork.IsNone && metadata.Artwork.Any(a => a.ArtworkKind == artworkKind))
{
await _metadataRepository.RemoveArtworkWithKind(metadata, artworkKind);
}
}
return result;
@ -515,11 +527,18 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan @@ -515,11 +527,18 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan
{
try
{
Option<string> maybePoster = LocatePoster(season, seasonFolder);
foreach (string posterFile in maybePoster)
foreach (SeasonMetadata metadata in season.SeasonMetadata.HeadOrNone())
{
SeasonMetadata metadata = season.SeasonMetadata.Head();
await RefreshArtwork(posterFile, metadata, ArtworkKind.Poster, None, None, cancellationToken);
Option<string> maybePoster = LocatePoster(season, seasonFolder);
foreach (string posterFile in maybePoster)
{
await RefreshArtwork(posterFile, metadata, ArtworkKind.Poster, None, None, cancellationToken);
}
if (maybePoster.IsNone && metadata.Artwork.Any(a => a.ArtworkKind is ArtworkKind.Poster))
{
await _metadataRepository.RemoveArtworkWithKind(metadata, ArtworkKind.Poster);
}
}
return season;
@ -535,10 +554,10 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan @@ -535,10 +554,10 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan
{
try
{
Option<string> maybeThumbnail = LocateThumbnail(episode);
foreach (string thumbnailFile in maybeThumbnail)
foreach (EpisodeMetadata metadata in episode.EpisodeMetadata)
{
foreach (EpisodeMetadata metadata in episode.EpisodeMetadata)
Option<string> maybeThumbnail = LocateThumbnail(episode);
foreach (string thumbnailFile in maybeThumbnail)
{
await RefreshArtwork(
thumbnailFile,
@ -548,6 +567,11 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan @@ -548,6 +567,11 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan
None,
cancellationToken);
}
if (maybeThumbnail.IsNone && metadata.Artwork.Any(a => a.ArtworkKind is ArtworkKind.Thumbnail))
{
await _metadataRepository.RemoveArtworkWithKind(metadata, ArtworkKind.Thumbnail);
}
}
return episode;

Loading…
Cancel
Save