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/). @@ -14,6 +14,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Fixed
- Fix playback of transcoded 10-bit media items (pixel format `yuv420p10le`) on Nvidia hardware
- 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
### Added

6
ErsatzTV.Core/Emby/EmbyTelevisionLibraryScanner.cs

@ -231,7 +231,6 @@ namespace ErsatzTV.Core.Emby @@ -231,7 +231,6 @@ namespace ErsatzTV.Core.Emby
},
async () =>
{
incoming.ShowId = show.Id;
incoming.LibraryPathId = library.Paths.Head().Id;
_logger.LogDebug(
@ -239,7 +238,7 @@ namespace ErsatzTV.Core.Emby @@ -239,7 +238,7 @@ namespace ErsatzTV.Core.Emby
show.ShowMetadata.Head().Title,
incoming.SeasonMetadata.Head().Title);
await _televisionRepository.AddSeason(incoming);
await _televisionRepository.AddSeason(show, incoming);
});
List<EmbyItemEtag> existingEpisodes =
@ -364,7 +363,6 @@ namespace ErsatzTV.Core.Emby @@ -364,7 +363,6 @@ namespace ErsatzTV.Core.Emby
try
{
updateStatistics = true;
incoming.SeasonId = season.Id;
incoming.LibraryPathId = library.Paths.Head().Id;
_logger.LogDebug(
@ -373,7 +371,7 @@ namespace ErsatzTV.Core.Emby @@ -373,7 +371,7 @@ namespace ErsatzTV.Core.Emby
seasonName,
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 });
}

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

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

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

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

6
ErsatzTV.Core/Jellyfin/JellyfinTelevisionLibraryScanner.cs

@ -231,7 +231,6 @@ namespace ErsatzTV.Core.Jellyfin @@ -231,7 +231,6 @@ namespace ErsatzTV.Core.Jellyfin
},
async () =>
{
incoming.ShowId = show.Id;
incoming.LibraryPathId = library.Paths.Head().Id;
_logger.LogDebug(
@ -239,7 +238,7 @@ namespace ErsatzTV.Core.Jellyfin @@ -239,7 +238,7 @@ namespace ErsatzTV.Core.Jellyfin
show.ShowMetadata.Head().Title,
incoming.SeasonMetadata.Head().Title);
await _televisionRepository.AddSeason(incoming);
await _televisionRepository.AddSeason(show, incoming);
});
List<JellyfinItemEtag> existingEpisodes =
@ -365,7 +364,6 @@ namespace ErsatzTV.Core.Jellyfin @@ -365,7 +364,6 @@ namespace ErsatzTV.Core.Jellyfin
try
{
updateStatistics = true;
incoming.SeasonId = season.Id;
incoming.LibraryPathId = library.Paths.Head().Id;
_logger.LogDebug(
@ -374,7 +372,7 @@ namespace ErsatzTV.Core.Jellyfin @@ -374,7 +372,7 @@ namespace ErsatzTV.Core.Jellyfin
seasonName,
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 });
}

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

@ -242,18 +242,29 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -242,18 +242,29 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
return maybeExisting;
}
public async Task<bool> AddSeason(EmbySeason season)
public async Task<bool> AddSeason(EmbyShow show, EmbySeason season)
{
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
await dbContext.AddAsync(season);
if (await dbContext.SaveChangesAsync() <= 0)
try
{
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;
}
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)
@ -368,19 +379,30 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -368,19 +379,30 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
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();
await dbContext.AddAsync(episode);
if (await dbContext.SaveChangesAsync() <= 0)
try
{
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;
}
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)

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

@ -259,18 +259,29 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -259,18 +259,29 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
return maybeExisting;
}
public async Task<bool> AddSeason(JellyfinSeason season)
public async Task<bool> AddSeason(JellyfinShow show, JellyfinSeason season)
{
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
await dbContext.AddAsync(season);
if (await dbContext.SaveChangesAsync() <= 0)
try
{
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;
}
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)
@ -368,19 +379,30 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -368,19 +379,30 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
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();
await dbContext.AddAsync(episode);
if (await dbContext.SaveChangesAsync() <= 0)
try
{
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;
}
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)

6
ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj

@ -16,12 +16,12 @@ @@ -16,12 +16,12 @@
<PackageReference Include="Lucene.Net" 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="Microsoft.EntityFrameworkCore" Version="5.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.6">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</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">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

6
ErsatzTV/ErsatzTV.csproj

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

Loading…
Cancel
Save