Browse Source

fix adding jellyfin emby seasons episodes (#281)

* fix adding new seasons and episodes with emby and jellyfin

* update changelog

* update dependencies
pull/279/head
Jason Dove 5 years ago committed by GitHub
parent
commit
e2f3e86fd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      CHANGELOG.md
  2. 6
      ErsatzTV.Core/Emby/EmbyTelevisionLibraryScanner.cs
  3. 4
      ErsatzTV.Core/Interfaces/Repositories/IEmbyTelevisionRepository.cs
  4. 4
      ErsatzTV.Core/Interfaces/Repositories/IJellyfinTelevisionRepository.cs
  5. 6
      ErsatzTV.Core/Jellyfin/JellyfinTelevisionLibraryScanner.cs
  6. 56
      ErsatzTV.Infrastructure/Data/Repositories/EmbyTelevisionRepository.cs
  7. 56
      ErsatzTV.Infrastructure/Data/Repositories/JellyfinTelevisionRepository.cs
  8. 6
      ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj
  9. 6
      ErsatzTV/ErsatzTV.csproj

2
CHANGELOG.md

@ -14,6 +14,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Fixed ### Fixed
- Fix playback of transcoded 10-bit media items (pixel format `yuv420p10le`) on Nvidia hardware - Fix playback of transcoded 10-bit media items (pixel format `yuv420p10le`) on Nvidia hardware
- Emby and Jellyfin scanners now respect library refresh interval setting - Emby and Jellyfin scanners now respect library refresh interval setting
- Fix adding new seasons to existing Emby and Jellyfin shows
- Fix adding new episodes to existing Emby and Jellyfin seasons
## [0.0.47-prealpha] - 2021-06-15 ## [0.0.47-prealpha] - 2021-06-15
### Added ### Added

6
ErsatzTV.Core/Emby/EmbyTelevisionLibraryScanner.cs

@ -231,7 +231,6 @@ namespace ErsatzTV.Core.Emby
}, },
async () => async () =>
{ {
incoming.ShowId = show.Id;
incoming.LibraryPathId = library.Paths.Head().Id; incoming.LibraryPathId = library.Paths.Head().Id;
_logger.LogDebug( _logger.LogDebug(
@ -239,7 +238,7 @@ namespace ErsatzTV.Core.Emby
show.ShowMetadata.Head().Title, show.ShowMetadata.Head().Title,
incoming.SeasonMetadata.Head().Title); incoming.SeasonMetadata.Head().Title);
await _televisionRepository.AddSeason(incoming); await _televisionRepository.AddSeason(show, incoming);
}); });
List<EmbyItemEtag> existingEpisodes = List<EmbyItemEtag> existingEpisodes =
@ -364,7 +363,6 @@ namespace ErsatzTV.Core.Emby
try try
{ {
updateStatistics = true; updateStatistics = true;
incoming.SeasonId = season.Id;
incoming.LibraryPathId = library.Paths.Head().Id; incoming.LibraryPathId = library.Paths.Head().Id;
_logger.LogDebug( _logger.LogDebug(
@ -373,7 +371,7 @@ namespace ErsatzTV.Core.Emby
seasonName, seasonName,
incoming.EpisodeMetadata.HeadOrNone().Map(em => em.EpisodeNumber)); incoming.EpisodeMetadata.HeadOrNone().Map(em => em.EpisodeNumber));
if (await _televisionRepository.AddEpisode(incoming)) if (await _televisionRepository.AddEpisode(season, incoming))
{ {
await _searchIndex.AddItems(_searchRepository, new List<MediaItem> { incoming }); await _searchIndex.AddItems(_searchRepository, new List<MediaItem> { incoming });
} }

4
ErsatzTV.Core/Interfaces/Repositories/IEmbyTelevisionRepository.cs

@ -13,9 +13,9 @@ namespace ErsatzTV.Core.Interfaces.Repositories
Task<List<EmbyItemEtag>> GetExistingEpisodes(EmbyLibrary library, string seasonItemId); Task<List<EmbyItemEtag>> GetExistingEpisodes(EmbyLibrary library, string seasonItemId);
Task<bool> AddShow(EmbyShow show); Task<bool> AddShow(EmbyShow show);
Task<Option<EmbyShow>> Update(EmbyShow show); Task<Option<EmbyShow>> Update(EmbyShow show);
Task<bool> AddSeason(EmbySeason season); Task<bool> AddSeason(EmbyShow show, EmbySeason season);
Task<Unit> Update(EmbySeason season); Task<Unit> Update(EmbySeason season);
Task<bool> AddEpisode(EmbyEpisode episode); Task<bool> AddEpisode(EmbySeason season, EmbyEpisode episode);
Task<Option<EmbyEpisode>> Update(EmbyEpisode episode); Task<Option<EmbyEpisode>> Update(EmbyEpisode episode);
Task<List<int>> RemoveMissingShows(EmbyLibrary library, List<string> showIds); Task<List<int>> RemoveMissingShows(EmbyLibrary library, List<string> showIds);
Task<Unit> RemoveMissingSeasons(EmbyLibrary library, List<string> seasonIds); Task<Unit> RemoveMissingSeasons(EmbyLibrary library, List<string> seasonIds);

4
ErsatzTV.Core/Interfaces/Repositories/IJellyfinTelevisionRepository.cs

@ -13,9 +13,9 @@ namespace ErsatzTV.Core.Interfaces.Repositories
Task<List<JellyfinItemEtag>> GetExistingEpisodes(JellyfinLibrary library, string seasonItemId); Task<List<JellyfinItemEtag>> GetExistingEpisodes(JellyfinLibrary library, string seasonItemId);
Task<bool> AddShow(JellyfinShow show); Task<bool> AddShow(JellyfinShow show);
Task<Option<JellyfinShow>> Update(JellyfinShow show); Task<Option<JellyfinShow>> Update(JellyfinShow show);
Task<bool> AddSeason(JellyfinSeason season); Task<bool> AddSeason(JellyfinShow show, JellyfinSeason season);
Task<Unit> Update(JellyfinSeason season); Task<Unit> Update(JellyfinSeason season);
Task<bool> AddEpisode(JellyfinEpisode episode); Task<bool> AddEpisode(JellyfinSeason season, JellyfinEpisode episode);
Task<Option<JellyfinEpisode>> Update(JellyfinEpisode episode); Task<Option<JellyfinEpisode>> Update(JellyfinEpisode episode);
Task<List<int>> RemoveMissingShows(JellyfinLibrary library, List<string> showIds); Task<List<int>> RemoveMissingShows(JellyfinLibrary library, List<string> showIds);
Task<Unit> RemoveMissingSeasons(JellyfinLibrary library, List<string> seasonIds); Task<Unit> RemoveMissingSeasons(JellyfinLibrary library, List<string> seasonIds);

6
ErsatzTV.Core/Jellyfin/JellyfinTelevisionLibraryScanner.cs

@ -231,7 +231,6 @@ namespace ErsatzTV.Core.Jellyfin
}, },
async () => async () =>
{ {
incoming.ShowId = show.Id;
incoming.LibraryPathId = library.Paths.Head().Id; incoming.LibraryPathId = library.Paths.Head().Id;
_logger.LogDebug( _logger.LogDebug(
@ -239,7 +238,7 @@ namespace ErsatzTV.Core.Jellyfin
show.ShowMetadata.Head().Title, show.ShowMetadata.Head().Title,
incoming.SeasonMetadata.Head().Title); incoming.SeasonMetadata.Head().Title);
await _televisionRepository.AddSeason(incoming); await _televisionRepository.AddSeason(show, incoming);
}); });
List<JellyfinItemEtag> existingEpisodes = List<JellyfinItemEtag> existingEpisodes =
@ -365,7 +364,6 @@ namespace ErsatzTV.Core.Jellyfin
try try
{ {
updateStatistics = true; updateStatistics = true;
incoming.SeasonId = season.Id;
incoming.LibraryPathId = library.Paths.Head().Id; incoming.LibraryPathId = library.Paths.Head().Id;
_logger.LogDebug( _logger.LogDebug(
@ -374,7 +372,7 @@ namespace ErsatzTV.Core.Jellyfin
seasonName, seasonName,
incoming.EpisodeMetadata.HeadOrNone().Map(em => em.EpisodeNumber)); incoming.EpisodeMetadata.HeadOrNone().Map(em => em.EpisodeNumber));
if (await _televisionRepository.AddEpisode(incoming)) if (await _televisionRepository.AddEpisode(season, incoming))
{ {
await _searchIndex.AddItems(_searchRepository, new List<MediaItem> { incoming }); await _searchIndex.AddItems(_searchRepository, new List<MediaItem> { incoming });
} }

56
ErsatzTV.Infrastructure/Data/Repositories/EmbyTelevisionRepository.cs

@ -242,18 +242,29 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
return maybeExisting; return maybeExisting;
} }
public async Task<bool> AddSeason(EmbySeason season) public async Task<bool> AddSeason(EmbyShow show, EmbySeason season)
{ {
await using TvContext dbContext = _dbContextFactory.CreateDbContext(); try
await dbContext.AddAsync(season); {
if (await dbContext.SaveChangesAsync() <= 0) season.ShowId = await _dbConnection.ExecuteScalarAsync<int>(
@"SELECT Id FROM EmbyShow WHERE ItemId = @ItemId",
new { show.ItemId });
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
await dbContext.AddAsync(season);
if (await dbContext.SaveChangesAsync() <= 0)
{
return false;
}
await dbContext.Entry(season).Reference(m => m.LibraryPath).LoadAsync();
await dbContext.Entry(season.LibraryPath).Reference(lp => lp.Library).LoadAsync();
return true;
}
catch (Exception)
{ {
return false; return false;
} }
await dbContext.Entry(season).Reference(m => m.LibraryPath).LoadAsync();
await dbContext.Entry(season.LibraryPath).Reference(lp => lp.Library).LoadAsync();
return true;
} }
public async Task<Unit> Update(EmbySeason season) public async Task<Unit> Update(EmbySeason season)
@ -368,19 +379,30 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
return Unit.Default; return Unit.Default;
} }
public async Task<bool> AddEpisode(EmbyEpisode episode) public async Task<bool> AddEpisode(EmbySeason season, EmbyEpisode episode)
{ {
await using TvContext dbContext = _dbContextFactory.CreateDbContext(); try
await dbContext.AddAsync(episode); {
if (await dbContext.SaveChangesAsync() <= 0) episode.SeasonId = await _dbConnection.ExecuteScalarAsync<int>(
@"SELECT Id FROM EmbySeason WHERE ItemId = @ItemId",
new { season.ItemId });
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
await dbContext.AddAsync(episode);
if (await dbContext.SaveChangesAsync() <= 0)
{
return false;
}
await dbContext.Entry(episode).Reference(m => m.LibraryPath).LoadAsync();
await dbContext.Entry(episode.LibraryPath).Reference(lp => lp.Library).LoadAsync();
await dbContext.Entry(episode).Reference(e => e.Season).LoadAsync();
return true;
}
catch (Exception)
{ {
return false; return false;
} }
await dbContext.Entry(episode).Reference(m => m.LibraryPath).LoadAsync();
await dbContext.Entry(episode.LibraryPath).Reference(lp => lp.Library).LoadAsync();
await dbContext.Entry(episode).Reference(e => e.Season).LoadAsync();
return true;
} }
public async Task<Option<EmbyEpisode>> Update(EmbyEpisode episode) public async Task<Option<EmbyEpisode>> Update(EmbyEpisode episode)

56
ErsatzTV.Infrastructure/Data/Repositories/JellyfinTelevisionRepository.cs

@ -259,18 +259,29 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
return maybeExisting; return maybeExisting;
} }
public async Task<bool> AddSeason(JellyfinSeason season) public async Task<bool> AddSeason(JellyfinShow show, JellyfinSeason season)
{ {
await using TvContext dbContext = _dbContextFactory.CreateDbContext(); try
await dbContext.AddAsync(season); {
if (await dbContext.SaveChangesAsync() <= 0) season.ShowId = await _dbConnection.ExecuteScalarAsync<int>(
@"SELECT Id FROM JellyfinShow WHERE ItemId = @ItemId",
new { show.ItemId });
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
await dbContext.AddAsync(season);
if (await dbContext.SaveChangesAsync() <= 0)
{
return false;
}
await dbContext.Entry(season).Reference(m => m.LibraryPath).LoadAsync();
await dbContext.Entry(season.LibraryPath).Reference(lp => lp.Library).LoadAsync();
return true;
}
catch (Exception)
{ {
return false; return false;
} }
await dbContext.Entry(season).Reference(m => m.LibraryPath).LoadAsync();
await dbContext.Entry(season.LibraryPath).Reference(lp => lp.Library).LoadAsync();
return true;
} }
public async Task<Unit> Update(JellyfinSeason season) public async Task<Unit> Update(JellyfinSeason season)
@ -368,19 +379,30 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
return Unit.Default; return Unit.Default;
} }
public async Task<bool> AddEpisode(JellyfinEpisode episode) public async Task<bool> AddEpisode(JellyfinSeason season, JellyfinEpisode episode)
{ {
await using TvContext dbContext = _dbContextFactory.CreateDbContext(); try
await dbContext.AddAsync(episode); {
if (await dbContext.SaveChangesAsync() <= 0) episode.SeasonId = await _dbConnection.ExecuteScalarAsync<int>(
@"SELECT Id FROM JellyfinSeason WHERE ItemId = @ItemId",
new { season.ItemId });
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
await dbContext.AddAsync(episode);
if (await dbContext.SaveChangesAsync() <= 0)
{
return false;
}
await dbContext.Entry(episode).Reference(m => m.LibraryPath).LoadAsync();
await dbContext.Entry(episode.LibraryPath).Reference(lp => lp.Library).LoadAsync();
await dbContext.Entry(episode).Reference(e => e.Season).LoadAsync();
return true;
}
catch (Exception)
{ {
return false; return false;
} }
await dbContext.Entry(episode).Reference(m => m.LibraryPath).LoadAsync();
await dbContext.Entry(episode.LibraryPath).Reference(lp => lp.Library).LoadAsync();
await dbContext.Entry(episode).Reference(e => e.Season).LoadAsync();
return true;
} }
public async Task<Option<JellyfinEpisode>> Update(JellyfinEpisode episode) public async Task<Option<JellyfinEpisode>> Update(JellyfinEpisode episode)

6
ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj

@ -16,12 +16,12 @@
<PackageReference Include="Lucene.Net" Version="4.8.0-beta00013" /> <PackageReference Include="Lucene.Net" Version="4.8.0-beta00013" />
<PackageReference Include="Lucene.Net.Analysis.Common" Version="4.8.0-beta00013" /> <PackageReference Include="Lucene.Net.Analysis.Common" Version="4.8.0-beta00013" />
<PackageReference Include="Lucene.Net.QueryParser" Version="4.8.0-beta00013" /> <PackageReference Include="Lucene.Net.QueryParser" Version="4.8.0-beta00013" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.6"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.7">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.7" />
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="16.9.60"> <PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="16.9.60">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

6
ErsatzTV/ErsatzTV.csproj

@ -19,14 +19,14 @@
</PackageReference> </PackageReference>
<PackageReference Include="Blazored.LocalStorage" Version="4.1.1" /> <PackageReference Include="Blazored.LocalStorage" Version="4.1.1" />
<PackageReference Include="FluentValidation" Version="10.2.3" /> <PackageReference Include="FluentValidation" Version="10.2.3" />
<PackageReference Include="FluentValidation.AspNetCore" Version="10.1.0" /> <PackageReference Include="FluentValidation.AspNetCore" Version="10.2.3" />
<PackageReference Include="HtmlSanitizer" Version="5.0.404" /> <PackageReference Include="HtmlSanitizer" Version="5.0.404" />
<PackageReference Include="LanguageExt.Core" Version="3.4.15" /> <PackageReference Include="LanguageExt.Core" Version="3.4.15" />
<PackageReference Include="Markdig" Version="0.24.0" /> <PackageReference Include="Markdig" Version="0.24.0" />
<PackageReference Include="MediatR.Courier.DependencyInjection" Version="3.0.1" /> <PackageReference Include="MediatR.Courier.DependencyInjection" Version="3.0.1" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" /> <PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.6" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.6"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.7">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>

Loading…
Cancel
Save