disambiguate seasons (#1543)
This commit is contained in:
@@ -26,9 +26,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- Fix tray icon shortcut to open logs folder on Windows
|
||||
- Unlock playout when playout build fails
|
||||
- Ignore errors deleting old HLS segments; this should improve stream reliability
|
||||
- Update show year when changed within Plex
|
||||
|
||||
### Changed
|
||||
- Upgrade from .NET 7 to .NET 8
|
||||
- In schedule items, disambiguate seasons from shows with the same title by including show year
|
||||
- Old format: `Show Title (Season Number)`
|
||||
- New format: `Show Title (Show Year) - Season Number`
|
||||
|
||||
## [0.8.4-beta] - 2023-12-02
|
||||
### Fixed
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using System.Globalization;
|
||||
using ErsatzTV.Core.Domain;
|
||||
|
||||
namespace ErsatzTV.Application.MediaItems;
|
||||
|
||||
@@ -8,13 +9,27 @@ internal static class Mapper
|
||||
new(show.Id, show.ShowMetadata.HeadOrNone().Map(sm => $"{sm?.Title} ({sm?.Year})").IfNone("???"));
|
||||
|
||||
internal static NamedMediaItemViewModel ProjectToViewModel(Season season) =>
|
||||
new(season.Id, $"{ShowTitle(season)} ({SeasonDescription(season)})");
|
||||
new(season.Id, $"{ShowTitle(season)} - {SeasonDescription(season)}");
|
||||
|
||||
internal static NamedMediaItemViewModel ProjectToViewModel(Artist artist) =>
|
||||
new(artist.Id, artist.ArtistMetadata.HeadOrNone().Match(am => am.Title, () => "???"));
|
||||
|
||||
private static string ShowTitle(Season season) =>
|
||||
season.Show.ShowMetadata.HeadOrNone().Map(sm => sm.Title).IfNone("???");
|
||||
private static string ShowTitle(Season season)
|
||||
{
|
||||
var title = "???";
|
||||
var year = "???";
|
||||
|
||||
foreach (ShowMetadata show in season.Show.ShowMetadata.HeadOrNone())
|
||||
{
|
||||
title = show.Title;
|
||||
foreach (int y in Optional(show.Year))
|
||||
{
|
||||
year = y.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
return $"{title} ({year})";
|
||||
}
|
||||
|
||||
private static string SeasonDescription(Season season) =>
|
||||
season.SeasonNumber == 0 ? "Specials" : $"Season {season.SeasonNumber}";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Globalization;
|
||||
using ErsatzTV.Application.MediaItems;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Infrastructure.Data;
|
||||
@@ -25,21 +26,25 @@ public class SearchTelevisionSeasonsHandler : IRequestHandler<SearchTelevisionSe
|
||||
where EF.Functions.Like(showMetadata.Title + " " + seasonMetadata.Title, $"%{request.Query}%")
|
||||
orderby EF.Functions.Collate(showMetadata.Title, TvContext.CaseInsensitiveCollation), season
|
||||
.SeasonNumber
|
||||
select new TelevisionSeason(season.Id, showMetadata.Title, season.SeasonNumber))
|
||||
select new TelevisionSeason(season.Id, showMetadata.Title, showMetadata.Year, season.SeasonNumber))
|
||||
.Take(20)
|
||||
.ToListAsync(cancellationToken)
|
||||
.Map(list => list.Map(ToNamedMediaItem).ToList());
|
||||
}
|
||||
|
||||
private static NamedMediaItemViewModel ToNamedMediaItem(TelevisionSeason season) => new(
|
||||
season.Id,
|
||||
$"{ShowTitle(season)} ({SeasonTitle(season)})");
|
||||
private static NamedMediaItemViewModel ToNamedMediaItem(TelevisionSeason season) =>
|
||||
new(season.Id, $"{ShowTitle(season)} - {SeasonTitle(season)}");
|
||||
|
||||
private static string ShowTitle(TelevisionSeason season) => $"{season.Title ?? "???"}";
|
||||
private static string ShowTitle(TelevisionSeason season)
|
||||
{
|
||||
string title = season.Title ?? "???";
|
||||
string year = season.Year.HasValue ? season.Year.Value.ToString(CultureInfo.InvariantCulture) : "???";
|
||||
return $"{title} ({year})";
|
||||
}
|
||||
|
||||
private static string SeasonTitle(TelevisionSeason season) => season.SeasonNumber == 0
|
||||
? "Specials"
|
||||
: $"Season {season.SeasonNumber}";
|
||||
|
||||
public record TelevisionSeason(int Id, string Title, int SeasonNumber);
|
||||
public record TelevisionSeason(int Id, string Title, int? Year, int SeasonNumber);
|
||||
}
|
||||
|
||||
@@ -41,4 +41,5 @@ public interface ITelevisionRepository
|
||||
Task<bool> UpdateTitles(EpisodeMetadata metadata, string title, string sortTitle);
|
||||
Task<bool> UpdateOutline(EpisodeMetadata metadata, string outline);
|
||||
Task<bool> UpdatePlot(EpisodeMetadata metadata, string plot);
|
||||
Task<bool> UpdateYear(ShowMetadata metadata, int? year);
|
||||
}
|
||||
|
||||
@@ -525,6 +525,14 @@ public class TelevisionRepository : ITelevisionRepository
|
||||
new { Plot = plot, MetadataId = metadata.Id }).Map(result => result > 0);
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateYear(ShowMetadata metadata, int? year)
|
||||
{
|
||||
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await dbContext.Connection.ExecuteAsync(
|
||||
"UPDATE ShowMetadata SET Year = @Year WHERE Id = @MetadataId",
|
||||
new { Year = year, MetadataId = metadata.Id }).Map(result => result > 0);
|
||||
}
|
||||
|
||||
public async Task<List<Episode>> GetShowItems(int showId)
|
||||
{
|
||||
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
@@ -441,6 +441,14 @@ public class PlexTelevisionLibraryScanner :
|
||||
result.IsUpdated = true;
|
||||
}
|
||||
|
||||
if (existingMetadata.Year != fullMetadata.Year)
|
||||
{
|
||||
if (await _televisionRepository.UpdateYear(existingMetadata, fullMetadata.Year))
|
||||
{
|
||||
result.IsUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.IsUpdated)
|
||||
{
|
||||
await _metadataRepository.MarkAsUpdated(existingMetadata, fullMetadata.DateUpdated);
|
||||
|
||||
Reference in New Issue
Block a user