@ -13,19 +13,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
@@ -13,19 +13,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- `Extract and use embedded (text) subtitles`
- Default value: `false`
- When enabled, embedded text subtitles will be periodically extracted, and considered for playback
- Add `sub_language` and `sub_language_tag` fields to search index
### Fixed
- Fix antiforgery error caused by reusing existing browser tabs across docker container restarts
- Data protection keys will now be persisted under ErsatzTV's config folder instead of being recreated at startup
- Fix bug updating/replacing Jellyfin movies
- A deep scan can be used to fix all movies, otherwise any future updates made to JF movies will correctly sync to ETV
- Automatically generate JWT tokens to allow channel previews of protected streams
- Automatically generate JWT tokens to allow channel previews of protected streams
### Changed
- Log search index updates under scanner category at debug level, to indicate a potential cause for the UI being out of date
- Batch search index updates to keep pace with library scans
- Previously, search index updates would slowly process over minutes/hours after library scans completed
- Search index updates should now complete at the same time as library scans
- Do not unnecessarily update the search index during media server library scans
@ -17,11 +17,18 @@ public class CachingSearchRepository : ICachingSearchRepository
@@ -17,11 +17,18 @@ public class CachingSearchRepository : ICachingSearchRepository
@ -207,6 +207,11 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -207,6 +207,11 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@ -221,7 +226,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -221,7 +226,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 0 WHERE Id = @Id",
"UPDATE MediaItem SET State = 0 WHERE Id = @Id AND State != 0",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -230,6 +235,11 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -230,6 +235,11 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@ -244,7 +254,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -244,7 +254,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 0 WHERE Id = @Id",
"UPDATE MediaItem SET State = 0 WHERE Id = @Id AND State != 0",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -253,6 +263,11 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -253,6 +263,11 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@ -267,7 +282,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -267,7 +282,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 0 WHERE Id = @Id",
"UPDATE MediaItem SET State = 0 WHERE Id = @Id AND State != 0",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -278,7 +293,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -278,7 +293,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@ -293,7 +308,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -293,7 +308,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
.Map(result=>result.ToList());
awaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids",
"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids AND State != 1",
new{Ids=ids});
returnids;
@ -303,7 +318,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -303,7 +318,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@ -318,7 +333,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -318,7 +333,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
.Map(result=>result.ToList());
awaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids",
"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids AND State != 1",
new{Ids=ids});
returnids;
@ -328,7 +343,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -328,7 +343,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@ -343,7 +358,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -343,7 +358,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
.Map(result=>result.ToList());
awaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids",
"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids AND State != 1",
new{Ids=ids});
returnids;
@ -351,6 +366,11 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -351,6 +366,11 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@ -365,7 +385,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -365,7 +385,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 2 WHERE Id = @Id",
"UPDATE MediaItem SET State = 2 WHERE Id = @Id AND State != 2",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -374,6 +394,11 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -374,6 +394,11 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@ -388,7 +413,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
@@ -388,7 +413,7 @@ public class EmbyTelevisionRepository : IEmbyTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 3 WHERE Id = @Id",
"UPDATE MediaItem SET State = 3 WHERE Id = @Id AND State != 3",
@ -39,6 +39,11 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
@@ -39,6 +39,11 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
@ -53,7 +58,7 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
@@ -53,7 +58,7 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 0 WHERE Id = @Id",
"UPDATE MediaItem SET State = 0 WHERE Id = @Id AND State != 0",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -62,6 +67,11 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
@@ -62,6 +67,11 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
@ -76,7 +86,7 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
@@ -76,7 +86,7 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 2 WHERE Id = @Id",
"UPDATE MediaItem SET State = 2 WHERE Id = @Id AND State != 2",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -85,6 +95,11 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
@@ -85,6 +95,11 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
@ -99,7 +114,7 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
@@ -99,7 +114,7 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 3 WHERE Id = @Id",
"UPDATE MediaItem SET State = 3 WHERE Id = @Id AND State != 3",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -110,7 +125,7 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
@@ -110,7 +125,7 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
@ -125,7 +140,7 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
@@ -125,7 +140,7 @@ public class JellyfinMovieRepository : IJellyfinMovieRepository
.Map(result=>result.ToList());
awaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids",
"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids AND State != 1",
@ -211,6 +211,11 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -211,6 +211,11 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@ -225,7 +230,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -225,7 +230,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 0 WHERE Id = @Id",
"UPDATE MediaItem SET State = 0 WHERE Id = @Id AND State != 0",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -234,6 +239,11 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -234,6 +239,11 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@ -248,7 +258,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -248,7 +258,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 0 WHERE Id = @Id",
"UPDATE MediaItem SET State = 0 WHERE Id = @Id AND State != 0",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -257,6 +267,11 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -257,6 +267,11 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@ -271,7 +286,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -271,7 +286,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 0 WHERE Id = @Id",
"UPDATE MediaItem SET State = 0 WHERE Id = @Id AND State != 0",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -282,7 +297,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -282,7 +297,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@ -297,7 +312,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -297,7 +312,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
.Map(result=>result.ToList());
awaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids",
"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids AND State != 1",
new{Ids=ids});
returnids;
@ -307,7 +322,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -307,7 +322,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@ -322,7 +337,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -322,7 +337,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
.Map(result=>result.ToList());
awaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids",
"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids AND State != 1",
new{Ids=ids});
returnids;
@ -332,7 +347,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -332,7 +347,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@ -347,7 +362,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -347,7 +362,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
.Map(result=>result.ToList());
awaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids",
"UPDATE MediaItem SET State = 1 WHERE Id IN @Ids AND State != 1",
new{Ids=ids});
returnids;
@ -355,6 +370,11 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -355,6 +370,11 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@ -369,7 +389,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -369,7 +389,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 2 WHERE Id = @Id",
"UPDATE MediaItem SET State = 2 WHERE Id = @Id AND State != 2",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -378,6 +398,11 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -378,6 +398,11 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@ -392,7 +417,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
@@ -392,7 +417,7 @@ public class JellyfinTelevisionRepository : IJellyfinTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 3 WHERE Id = @Id",
"UPDATE MediaItem SET State = 3 WHERE Id = @Id AND State != 3",
@ -26,6 +26,11 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -26,6 +26,11 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@ -40,7 +45,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -40,7 +45,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 0 WHERE Id = @Id",
"UPDATE MediaItem SET State = 0 WHERE Id = @Id AND State != 0",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -49,6 +54,11 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -49,6 +54,11 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@ -63,7 +73,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -63,7 +73,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 0 WHERE Id = @Id",
"UPDATE MediaItem SET State = 0 WHERE Id = @Id AND State != 0",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -72,6 +82,11 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -72,6 +82,11 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@ -86,7 +101,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -86,7 +101,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 0 WHERE Id = @Id",
"UPDATE MediaItem SET State = 0 WHERE Id = @Id AND State != 0",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -95,6 +110,11 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -95,6 +110,11 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@ -109,7 +129,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -109,7 +129,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 2 WHERE Id = @Id",
"UPDATE MediaItem SET State = 2 WHERE Id = @Id AND State != 2",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -118,6 +138,11 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -118,6 +138,11 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@ -132,7 +157,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -132,7 +157,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
foreach(intidinmaybeId)
{
returnawaitdbContext.Connection.ExecuteAsync(
@"UPDATE MediaItem SET State = 3 WHERE Id = @Id",
"UPDATE MediaItem SET State = 3 WHERE Id = @Id AND State != 3",
new{Id=id}).Map(count=>count>0?Some(id):None);
}
@ -321,7 +346,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -321,7 +346,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@ -346,7 +371,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -346,7 +371,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@ -371,7 +396,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@@ -371,7 +396,7 @@ public class PlexTelevisionRepository : IPlexTelevisionRepository
@ -31,6 +31,12 @@ public class ElasticSearchItem : MinimalElasticSearchItem
@@ -31,6 +31,12 @@ public class ElasticSearchItem : MinimalElasticSearchItem
@ -307,20 +307,26 @@ public abstract class MediaServerMovieLibraryScanner<TConnectionParameters, TLib
@@ -307,20 +307,26 @@ public abstract class MediaServerMovieLibraryScanner<TConnectionParameters, TLib
@ -584,20 +584,26 @@ public abstract class MediaServerTelevisionLibraryScanner<TConnectionParameters,
@@ -584,20 +584,26 @@ public abstract class MediaServerTelevisionLibraryScanner<TConnectionParameters,