filter duplicate recordings based on showId

This commit is contained in:
Luke Pulverenti 2016-11-24 11:29:23 -05:00
parent 8bc4d49c89
commit 9606a2a710
10 changed files with 79 additions and 38 deletions

View File

@ -33,8 +33,6 @@ namespace Emby.Common.Implementations.Net
_LocalPort = localPort;
_Socket.Bind(new IPEndPoint(ip, _LocalPort));
if (_LocalPort == 0)
_LocalPort = (_Socket.LocalEndPoint as IPEndPoint).Port;
}
#endregion

View File

@ -100,7 +100,8 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders = new Dictionary<string, string>();
}
if (addCachePrevention)
string expires;
if (addCachePrevention && !responseHeaders.TryGetValue("Expires", out expires))
{
responseHeaders["Expires"] = "-1";
}

View File

@ -645,6 +645,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
existingTimer.SeasonNumber = updatedTimer.SeasonNumber;
existingTimer.ShortOverview = updatedTimer.ShortOverview;
existingTimer.StartDate = updatedTimer.StartDate;
existingTimer.ShowId = updatedTimer.ShowId;
}
public Task<ImageStream> GetChannelImageAsync(string channelId, CancellationToken cancellationToken)
@ -1836,6 +1837,39 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return seriesTimer.SkipEpisodesInLibrary && IsProgramAlreadyInLibrary(timer);
}
private void HandleDuplicateShowIds(List<TimerInfo> timers)
{
foreach (var timer in timers.Skip(1))
{
// TODO: Get smarter, prefer HD, etc
timer.Status = RecordingStatus.Cancelled;
_timerProvider.Update(timer);
}
}
private void SearchForDuplicateShowIds(List<TimerInfo> timers)
{
var groups = timers.ToLookup(i => i.ShowId ?? string.Empty).ToList();
foreach (var group in groups)
{
if (string.IsNullOrWhiteSpace(group.Key))
{
continue;
}
var groupTimers = group.ToList();
if (groupTimers.Count < 2)
{
continue;
}
HandleDuplicateShowIds(groupTimers);
}
}
private async Task UpdateTimersForSeriesTimer(List<ProgramInfo> epgData, SeriesTimerInfo seriesTimer, bool deleteInvalidTimers)
{
var allTimers = GetTimersForSeries(seriesTimer, epgData)
@ -1843,6 +1877,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var registration = await _liveTvManager.GetRegistrationInfo("seriesrecordings").ConfigureAwait(false);
var enabledTimersForSeries = new List<TimerInfo>();
if (registration.IsValid)
{
foreach (var timer in allTimers)
@ -1855,6 +1891,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
timer.Status = RecordingStatus.Cancelled;
}
else
{
enabledTimersForSeries.Add(timer);
}
_timerProvider.Add(timer);
}
else
@ -1870,6 +1910,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
existingTimer.Status = RecordingStatus.Cancelled;
}
if (existingTimer.Status != RecordingStatus.Cancelled)
{
enabledTimersForSeries.Add(existingTimer);
}
existingTimer.SeriesTimerId = seriesTimer.Id;
_timerProvider.Update(existingTimer);
}
@ -1877,6 +1922,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
}
SearchForDuplicateShowIds(enabledTimersForSeries);
if (deleteInvalidTimers)
{
var allTimerIds = allTimers
@ -1901,8 +1948,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
}
private IEnumerable<TimerInfo> GetTimersForSeries(SeriesTimerInfo seriesTimer,
IEnumerable<ProgramInfo> allPrograms)
private IEnumerable<TimerInfo> GetTimersForSeries(SeriesTimerInfo seriesTimer, IEnumerable<ProgramInfo> allPrograms)
{
if (seriesTimer == null)
{

View File

@ -31,6 +31,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
timer.Name = parent.Name;
timer.Overview = parent.Overview;
timer.SeriesTimerId = seriesTimer.Id;
timer.ShowId = parent.ShowId;
CopyProgramInfoToTimerInfo(parent, timer);

View File

@ -124,12 +124,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings
private ProgramInfo GetProgramInfo(XmlTvProgram p, ListingsProviderInfo info)
{
var episodeTitle = p.Episode == null ? null : p.Episode.Title;
var programInfo = new ProgramInfo
{
ChannelId = p.ChannelId,
EndDate = GetDate(p.EndDate),
EpisodeNumber = p.Episode == null ? null : p.Episode.Episode,
EpisodeTitle = p.Episode == null ? null : p.Episode.Title,
EpisodeTitle = episodeTitle,
Genres = p.Categories,
Id = String.Format("{0}_{1:O}", p.ChannelId, p.StartDate), // Construct an id from the channel and start date,
StartDate = GetDate(p.StartDate),
@ -149,7 +151,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings
HasImage = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source),
OfficialRating = p.Rating != null && !String.IsNullOrEmpty(p.Rating.Value) ? p.Rating.Value : null,
CommunityRating = p.StarRating.HasValue ? p.StarRating.Value : (float?)null,
SeriesId = p.Episode != null ? p.Title.GetMD5().ToString("N") : null
SeriesId = p.Episode != null ? p.Title.GetMD5().ToString("N") : null,
ShowId = ((p.Title ?? string.Empty) + (episodeTitle ?? string.Empty)).GetMD5().ToString("N")
};
if (programInfo.IsMovie)

View File

@ -34,6 +34,8 @@ namespace MediaBrowser.Controller.LiveTv
/// <value>The program identifier.</value>
public string ProgramId { get; set; }
public string ShowId { get; set; }
/// <summary>
/// Name of the recording.
/// </summary>

View File

@ -154,7 +154,6 @@ namespace MediaBrowser.Model.Configuration
/// </summary>
/// <value><c>true</c> if [enable dashboard response caching]; otherwise, <c>false</c>.</value>
public bool EnableDashboardResponseCaching { get; set; }
public bool EnableDashboardResourceMinification { get; set; }
/// <summary>
/// Allows the dashboard to be served from a custom path.
@ -230,7 +229,6 @@ namespace MediaBrowser.Model.Configuration
HttpsPortNumber = DefaultHttpsPort;
EnableHttps = false;
EnableDashboardResponseCaching = true;
EnableDashboardResourceMinification = true;
EnableAnonymousUsageReporting = true;
EnableAutomaticRestart = true;

View File

@ -45,6 +45,8 @@
/// </summary>
Chapters,
ChildCount,
/// <summary>
/// The critic rating summary
/// </summary>

View File

@ -113,6 +113,7 @@ namespace MediaBrowser.WebDashboard.Api
private readonly ILocalizationManager _localization;
private readonly IJsonSerializer _jsonSerializer;
private readonly IAssemblyInfo _assemblyInfo;
private readonly IMemoryStreamFactory _memoryStreamFactory;
/// <summary>
/// Initializes a new instance of the <see cref="DashboardService" /> class.
@ -120,7 +121,7 @@ namespace MediaBrowser.WebDashboard.Api
/// <param name="appHost">The app host.</param>
/// <param name="serverConfigurationManager">The server configuration manager.</param>
/// <param name="fileSystem">The file system.</param>
public DashboardService(IServerApplicationHost appHost, IServerConfigurationManager serverConfigurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, IAssemblyInfo assemblyInfo, ILogger logger, IHttpResultFactory resultFactory)
public DashboardService(IServerApplicationHost appHost, IServerConfigurationManager serverConfigurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, IAssemblyInfo assemblyInfo, ILogger logger, IHttpResultFactory resultFactory, IMemoryStreamFactory memoryStreamFactory)
{
_appHost = appHost;
_serverConfigurationManager = serverConfigurationManager;
@ -130,6 +131,7 @@ namespace MediaBrowser.WebDashboard.Api
_assemblyInfo = assemblyInfo;
_logger = logger;
_resultFactory = resultFactory;
_memoryStreamFactory = memoryStreamFactory;
}
/// <summary>
@ -161,7 +163,7 @@ namespace MediaBrowser.WebDashboard.Api
if (plugin != null && stream != null)
{
return _resultFactory.GetStaticResult(Request, plugin.Version.ToString().GetMD5(), null, null, MimeTypes.GetMimeType("page.html"), () => GetPackageCreator().ModifyHtml("dummy.html", stream, null, _appHost.ApplicationVersion.ToString(), null, false));
return _resultFactory.GetStaticResult(Request, plugin.Version.ToString().GetMD5(), null, null, MimeTypes.GetMimeType("page.html"), () => GetPackageCreator().ModifyHtml("dummy.html", stream, null, _appHost.ApplicationVersion.ToString(), null));
}
throw new ResourceNotFoundException();
@ -294,7 +296,7 @@ namespace MediaBrowser.WebDashboard.Api
cacheDuration = TimeSpan.FromDays(365);
}
var cacheKey = (_appHost.ApplicationVersion.ToString() + (localizationCulture ?? string.Empty) + path).GetMD5();
var cacheKey = (_appHost.ApplicationVersion + (localizationCulture ?? string.Empty) + path).GetMD5();
return await _resultFactory.GetStaticResult(Request, cacheKey, null, cacheDuration, contentType, () => GetResourceStream(path, localizationCulture)).ConfigureAwait(false);
}
@ -312,15 +314,13 @@ namespace MediaBrowser.WebDashboard.Api
/// <returns>Task{Stream}.</returns>
private Task<Stream> GetResourceStream(string path, string localizationCulture)
{
var minify = _serverConfigurationManager.Configuration.EnableDashboardResourceMinification;
return GetPackageCreator()
.GetResource(path, null, localizationCulture, _appHost.ApplicationVersion.ToString(), minify);
.GetResource(path, null, localizationCulture, _appHost.ApplicationVersion.ToString());
}
private PackageCreator GetPackageCreator()
{
return new PackageCreator(_fileSystem, _localization, _logger, _serverConfigurationManager, _jsonSerializer);
return new PackageCreator(_fileSystem, _logger, _serverConfigurationManager, _memoryStreamFactory);
}
private List<string> GetDeployIgnoreExtensions()
@ -507,7 +507,7 @@ namespace MediaBrowser.WebDashboard.Api
private async Task DumpFile(string resourceVirtualPath, string destinationFilePath, string mode, string culture, string appVersion)
{
using (var stream = await GetPackageCreator().GetResource(resourceVirtualPath, mode, culture, appVersion, false).ConfigureAwait(false))
using (var stream = await GetPackageCreator().GetResource(resourceVirtualPath, mode, culture, appVersion).ConfigureAwait(false))
{
using (var fs = _fileSystem.GetFileStream(destinationFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
{

View File

@ -16,32 +16,28 @@ namespace MediaBrowser.WebDashboard.Api
public class PackageCreator
{
private readonly IFileSystem _fileSystem;
private readonly ILocalizationManager _localization;
private readonly ILogger _logger;
private readonly IServerConfigurationManager _config;
private readonly IJsonSerializer _jsonSerializer;
private readonly IMemoryStreamFactory _memoryStreamFactory;
public PackageCreator(IFileSystem fileSystem, ILocalizationManager localization, ILogger logger, IServerConfigurationManager config, IJsonSerializer jsonSerializer)
public PackageCreator(IFileSystem fileSystem, ILogger logger, IServerConfigurationManager config, IMemoryStreamFactory memoryStreamFactory)
{
_fileSystem = fileSystem;
_localization = localization;
_logger = logger;
_config = config;
_jsonSerializer = jsonSerializer;
_memoryStreamFactory = memoryStreamFactory;
}
public async Task<Stream> GetResource(string path,
string mode,
string localizationCulture,
string appVersion,
bool enableMinification)
string appVersion)
{
Stream resourceStream;
if (path.Equals("css/all.css", StringComparison.OrdinalIgnoreCase))
{
resourceStream = await GetAllCss(enableMinification).ConfigureAwait(false);
enableMinification = false;
resourceStream = await GetAllCss().ConfigureAwait(false);
}
else
{
@ -56,7 +52,7 @@ namespace MediaBrowser.WebDashboard.Api
{
if (IsCoreHtml(path))
{
resourceStream = await ModifyHtml(path, resourceStream, mode, appVersion, localizationCulture, enableMinification).ConfigureAwait(false);
resourceStream = await ModifyHtml(path, resourceStream, mode, appVersion, localizationCulture).ConfigureAwait(false);
}
}
}
@ -140,20 +136,14 @@ namespace MediaBrowser.WebDashboard.Api
/// <summary>
/// Modifies the HTML by adding common meta tags, css and js.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="sourceStream">The source stream.</param>
/// <param name="mode">The mode.</param>
/// <param name="appVersion">The application version.</param>
/// <param name="localizationCulture">The localization culture.</param>
/// <param name="enableMinification">if set to <c>true</c> [enable minification].</param>
/// <returns>Task{Stream}.</returns>
public async Task<Stream> ModifyHtml(string path, Stream sourceStream, string mode, string appVersion, string localizationCulture, bool enableMinification)
public async Task<Stream> ModifyHtml(string path, Stream sourceStream, string mode, string appVersion, string localizationCulture)
{
using (sourceStream)
{
string html;
using (var memoryStream = new MemoryStream())
using (var memoryStream = _memoryStreamFactory.CreateNew())
{
await sourceStream.CopyToAsync(memoryStream).ConfigureAwait(false);
@ -202,7 +192,7 @@ namespace MediaBrowser.WebDashboard.Api
var bytes = Encoding.UTF8.GetBytes(html);
return new MemoryStream(bytes);
return _memoryStreamFactory.CreateNew(bytes);
}
}
@ -332,9 +322,9 @@ namespace MediaBrowser.WebDashboard.Api
/// Gets all CSS.
/// </summary>
/// <returns>Task{Stream}.</returns>
private async Task<Stream> GetAllCss(bool enableMinification)
private async Task<Stream> GetAllCss()
{
var memoryStream = new MemoryStream();
var memoryStream = _memoryStreamFactory.CreateNew();
var files = new[]
{