Browse Source

fix: update plex movie and other video titles

pull/2947/head
Jason Dove 2 weeks ago
parent
commit
ae1756e436
No known key found for this signature in database
  1. 4
      CHANGELOG.md
  2. 2
      ErsatzTV.Core/Interfaces/Repositories/IMovieRepository.cs
  3. 1
      ErsatzTV.Core/Interfaces/Repositories/IOtherVideoRepository.cs
  4. 6
      ErsatzTV.Infrastructure/Data/Repositories/MovieRepository.cs
  5. 8
      ErsatzTV.Infrastructure/Data/Repositories/OtherVideoRepository.cs
  6. 5
      ErsatzTV.Infrastructure/Plex/PlexEtag.cs
  7. 5
      ErsatzTV.Scanner/Core/Plex/PlexMovieLibraryScanner.cs
  8. 8
      ErsatzTV.Scanner/Core/Plex/PlexOtherVideoLibraryScanner.cs

4
CHANGELOG.md

@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased] ## [Unreleased]
### Fixed
- Update Plex movie and other video titles when changed from Plex
- The first library scan after updating will act like a deep scan due to adding title to the Plex etag calculation
- Future periodic scans will update titles in ETV automatically (deep scans will not be required to update titles)
## [26.6.0] - 2026-07-09 ## [26.6.0] - 2026-07-09
### Added ### Added

2
ErsatzTV.Core/Interfaces/Repositories/IMovieRepository.cs

@ -20,7 +20,7 @@ public interface IMovieRepository
Task<bool> AddTag(MovieMetadata metadata, Tag tag); Task<bool> AddTag(MovieMetadata metadata, Tag tag);
Task<bool> AddStudio(MovieMetadata metadata, Studio studio); Task<bool> AddStudio(MovieMetadata metadata, Studio studio);
Task<bool> AddActor(MovieMetadata metadata, Actor actor); Task<bool> AddActor(MovieMetadata metadata, Actor actor);
Task<bool> UpdateSortTitle(MovieMetadata movieMetadata); Task<bool> UpdateTitles(MovieMetadata movieMetadata, string title, string sortTitle);
Task<bool> AddDirector(MovieMetadata metadata, Director director); Task<bool> AddDirector(MovieMetadata metadata, Director director);
Task<bool> AddWriter(MovieMetadata metadata, Writer writer); Task<bool> AddWriter(MovieMetadata metadata, Writer writer);
} }

1
ErsatzTV.Core/Interfaces/Repositories/IOtherVideoRepository.cs

@ -19,4 +19,5 @@ public interface IOtherVideoRepository
Task<bool> AddActor(OtherVideoMetadata metadata, Actor actor); Task<bool> AddActor(OtherVideoMetadata metadata, Actor actor);
Task<bool> AddDirector(OtherVideoMetadata metadata, Director director); Task<bool> AddDirector(OtherVideoMetadata metadata, Director director);
Task<bool> AddWriter(OtherVideoMetadata metadata, Writer writer); Task<bool> AddWriter(OtherVideoMetadata metadata, Writer writer);
Task<bool> UpdateTitles(OtherVideoMetadata metadata, string title, string sortTitle);
} }

6
ErsatzTV.Infrastructure/Data/Repositories/MovieRepository.cs

@ -195,12 +195,12 @@ public class MovieRepository : IMovieRepository
.Map(result => result > 0); .Map(result => result > 0);
} }
public async Task<bool> UpdateSortTitle(MovieMetadata movieMetadata) public async Task<bool> UpdateTitles(MovieMetadata movieMetadata, string title, string sortTitle)
{ {
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.Connection.ExecuteAsync( return await dbContext.Connection.ExecuteAsync(
@"UPDATE MovieMetadata SET SortTitle = @SortTitle WHERE Id = @Id", @"UPDATE MovieMetadata SET Title = @Title, SortTitle = @SortTitle WHERE Id = @Id",
new { movieMetadata.SortTitle, movieMetadata.Id }).Map(result => result > 0); new { Title = title, SortTitle = sortTitle, movieMetadata.Id }).Map(result => result > 0);
} }
public async Task<bool> AddDirector(MovieMetadata metadata, Director director) public async Task<bool> AddDirector(MovieMetadata metadata, Director director)

8
ErsatzTV.Infrastructure/Data/Repositories/OtherVideoRepository.cs

@ -175,6 +175,14 @@ public class OtherVideoRepository : IOtherVideoRepository
new { writer.Name, MetadataId = metadata.Id }).Map(result => result > 0); new { writer.Name, MetadataId = metadata.Id }).Map(result => result > 0);
} }
public async Task<bool> UpdateTitles(OtherVideoMetadata metadata, string title, string sortTitle)
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.Connection.ExecuteAsync(
"UPDATE OtherVideoMetadata SET Title = @Title, SortTitle = @SortTitle WHERE Id = @Id",
new { Title = title, SortTitle = sortTitle, metadata.Id }).Map(result => result > 0);
}
private async Task<Either<BaseError, MediaItemScanResult<OtherVideo>>> AddOtherVideo( private async Task<Either<BaseError, MediaItemScanResult<OtherVideo>>> AddOtherVideo(
TvContext dbContext, TvContext dbContext,
int libraryPathId, int libraryPathId,

5
ErsatzTV.Infrastructure/Plex/PlexEtag.cs

@ -27,6 +27,10 @@ public class PlexEtag
// video updated at // video updated at
bw.Write(response.UpdatedAt); bw.Write(response.UpdatedAt);
// video title
bw.Write((byte)FieldKey.Title);
bw.Write(response.Title ?? string.Empty);
foreach (PlexMediaResponse<PlexPartResponse> media in response.Media) foreach (PlexMediaResponse<PlexPartResponse> media in response.Media)
{ {
// media id // media id
@ -330,6 +334,7 @@ public class PlexEtag
Thumb = 20, Thumb = 20,
Art = 21, Art = 21,
Title = 22,
File = 30, File = 30,
Key = 31, Key = 31,

5
ErsatzTV.Scanner/Core/Plex/PlexMovieLibraryScanner.cs

@ -350,10 +350,11 @@ public class PlexMovieLibraryScanner :
result.IsUpdated = true; result.IsUpdated = true;
} }
if (fullMetadata.SortTitle != existingMetadata.SortTitle) if (fullMetadata.SortTitle != existingMetadata.SortTitle || fullMetadata.Title != existingMetadata.Title)
{ {
existingMetadata.Title = fullMetadata.Title;
existingMetadata.SortTitle = fullMetadata.SortTitle; existingMetadata.SortTitle = fullMetadata.SortTitle;
if (await _movieRepository.UpdateSortTitle(existingMetadata)) if (await _movieRepository.UpdateTitles(existingMetadata, fullMetadata.Title, fullMetadata.SortTitle))
{ {
result.IsUpdated = true; result.IsUpdated = true;
} }

8
ErsatzTV.Scanner/Core/Plex/PlexOtherVideoLibraryScanner.cs

@ -352,17 +352,15 @@ public class PlexOtherVideoLibraryScanner :
result.IsUpdated = true; result.IsUpdated = true;
} }
/* if (fullMetadata.SortTitle != existingMetadata.SortTitle || fullMetadata.Title != existingMetadata.Title)
if (fullMetadata.SortTitle != existingMetadata.SortTitle)
{ {
existingMetadata.Title = fullMetadata.Title;
existingMetadata.SortTitle = fullMetadata.SortTitle; existingMetadata.SortTitle = fullMetadata.SortTitle;
// Not existing on IOtherVideoRepository if (await _otherVideoRepository.UpdateTitles(existingMetadata, fullMetadata.Title, fullMetadata.SortTitle))
if (await _otherVideoRepository.UpdateSortTitle(existingMetadata))
{ {
result.IsUpdated = true; result.IsUpdated = true;
} }
} }
*/
bool poster = await UpdateArtworkIfNeeded(existingMetadata, fullMetadata, ArtworkKind.Poster); bool poster = await UpdateArtworkIfNeeded(existingMetadata, fullMetadata, ArtworkKind.Poster);
bool fanArt = await UpdateArtworkIfNeeded(existingMetadata, fullMetadata, ArtworkKind.FanArt); bool fanArt = await UpdateArtworkIfNeeded(existingMetadata, fullMetadata, ArtworkKind.FanArt);

Loading…
Cancel
Save