From 69cf9e8fc4bc7b20a3d2df15877bc214ce726579 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 30 Dec 2018 13:18:38 +0100 Subject: [PATCH 1/7] Give more info on error --- Emby.Dlna/DlnaManager.cs | 6 +++--- Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 62d1eb57ce..4c0f9415bc 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -531,7 +531,7 @@ namespace Emby.Dlna } } - class DlnaProfileEntryPoint /*: IServerEntryPoint*/ + class DlnaProfileEntryPoint : IServerEntryPoint { private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; @@ -551,7 +551,7 @@ namespace Emby.Dlna private void DumpProfiles() { - var list = new List + DeviceProfile[] list = new [] { new SamsungSmartTvProfile(), new XboxOneProfile(), @@ -597,4 +597,4 @@ namespace Emby.Dlna { } } -} \ No newline at end of file +} diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 2e96796784..4e3cfe5df7 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2392,13 +2392,16 @@ namespace Emby.Server.Implementations.LiveTv public async Task SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings) { - info = _jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(info)); + // Let's try something + //info = _jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(info)); - var provider = _listingProviders.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase)); + IListingsProvider provider = _listingProviders.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase)); if (provider == null) { - throw new ResourceNotFoundException(); + throw new ResourceNotFoundException( + string.Format("Couldn't find provider with name: '{0}' of type: '{1}'", provider.Name, provider.Type) + ); } await provider.Validate(info, validateLogin, validateListings).ConfigureAwait(false); From 76d3f60f0664529bb80a24fb225f6091619c3564 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 30 Dec 2018 15:25:08 +0100 Subject: [PATCH 2/7] Fix NullRefException --- Emby.Dlna/DlnaManager.cs | 5 +++-- Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 4c0f9415bc..042a19d650 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -530,7 +530,7 @@ namespace Emby.Dlna }; } } - + /* class DlnaProfileEntryPoint : IServerEntryPoint { private readonly IApplicationPaths _appPaths; @@ -596,5 +596,6 @@ namespace Emby.Dlna public void Dispose() { } - } + }*/ } + diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 4e3cfe5df7..d57f7e8cc3 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2400,7 +2400,7 @@ namespace Emby.Server.Implementations.LiveTv if (provider == null) { throw new ResourceNotFoundException( - string.Format("Couldn't find provider with name: '{0}' of type: '{1}'", provider.Name, provider.Type) + string.Format("Couldn't find provider of type: '{0}'", info.Type) ); } From 6ebb00549b044a55669aed1f83f0a1d84a1e5903 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 30 Dec 2018 17:42:54 +0100 Subject: [PATCH 3/7] Add missing XmlTvListingsProvider Added from https://github.com/thirunjuguna/emby/blob/e679ac4224c7ac8400f12ef95a063be4fcf3b5c0/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs --- .../LiveTv/Listings/XmlTvListingsProvider.cs | 260 ++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs new file mode 100644 index 0000000000..16252b557c --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -0,0 +1,260 @@ +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.LiveTv; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Emby.XmlTv.Classes; +using Emby.XmlTv.Entities; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Net; +using MediaBrowser.Common.Progress; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; + +namespace Emby.Server.Implementations.LiveTv.Listings +{ + public class XmlTvListingsProvider : IListingsProvider + { + private readonly IServerConfigurationManager _config; + private readonly IHttpClient _httpClient; + private readonly ILogger _logger; + private readonly IFileSystem _fileSystem; + private readonly IZipClient _zipClient; + + public XmlTvListingsProvider(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger, IFileSystem fileSystem, IZipClient zipClient) + { + _config = config; + _httpClient = httpClient; + _logger = logger; + _fileSystem = fileSystem; + _zipClient = zipClient; + } + + public string Name + { + get { return "XmlTV"; } + } + + public string Type + { + get { return "xmltv"; } + } + + private string GetLanguage(ListingsProviderInfo info) + { + if (!string.IsNullOrWhiteSpace(info.PreferredLanguage)) + { + return info.PreferredLanguage; + } + + return _config.Configuration.PreferredMetadataLanguage; + } + + private async Task GetXml(string path, CancellationToken cancellationToken) + { + _logger.Info("xmltv path: {0}", path); + + if (!path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + return UnzipIfNeeded(path, path); + } + + var cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "-" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + ".xml"; + var cacheFile = Path.Combine(_config.ApplicationPaths.CachePath, "xmltv", cacheFilename); + if (_fileSystem.FileExists(cacheFile)) + { + return UnzipIfNeeded(path, cacheFile); + } + + _logger.Info("Downloading xmltv listings from {0}", path); + + var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = path, + Progress = new SimpleProgress(), + DecompressionMethod = CompressionMethod.Gzip, + + // It's going to come back gzipped regardless of this value + // So we need to make sure the decompression method is set to gzip + EnableHttpCompression = true, + + UserAgent = "Emby/3.0" + + }).ConfigureAwait(false); + + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFile)); + + _fileSystem.CopyFile(tempFile, cacheFile, true); + + return UnzipIfNeeded(path, cacheFile); + } + + private string UnzipIfNeeded(string originalUrl, string file) + { + var ext = Path.GetExtension(originalUrl.Split('?')[0]); + + if (string.Equals(ext, ".gz", StringComparison.OrdinalIgnoreCase)) + { + using (var stream = _fileSystem.OpenRead(file)) + { + var tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); + _fileSystem.CreateDirectory(tempFolder); + + _zipClient.ExtractAllFromGz(stream, tempFolder, true); + + return _fileSystem.GetFiles(tempFolder, true) + .Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase)) + .Select(i => i.FullName) + .FirstOrDefault(); + } + } + + return file; + } + + public async Task> GetProgramsAsync(ListingsProviderInfo info, string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) + { + if (string.IsNullOrWhiteSpace(channelId)) + { + throw new ArgumentNullException("channelId"); + } + + /* + if (!await EmbyTV.EmbyTVRegistration.Instance.EnableXmlTv().ConfigureAwait(false)) + { + var length = endDateUtc - startDateUtc; + if (length.TotalDays > 1) + { + endDateUtc = startDateUtc.AddDays(1); + } + }*/ + + _logger.Debug("Getting xmltv programs for channel {0}", channelId); + + var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); + var reader = new XmlTvReader(path, GetLanguage(info)); + + var results = reader.GetProgrammes(channelId, startDateUtc, endDateUtc, cancellationToken); + return results.Select(p => GetProgramInfo(p, info)); + } + + private ProgramInfo GetProgramInfo(XmlTvProgram p, ListingsProviderInfo info) + { + var episodeTitle = p.Episode == null ? null : p.Episode.Title; + + var programInfo = new ProgramInfo + { + ChannelId = p.ChannelId, + EndDate = p.EndDate.UtcDateTime, + EpisodeNumber = p.Episode == null ? null : p.Episode.Episode, + EpisodeTitle = episodeTitle, + Genres = p.Categories, + StartDate = p.StartDate.UtcDateTime, + Name = p.Title, + Overview = p.Description, + ProductionYear = !p.CopyrightDate.HasValue ? (int?)null : p.CopyrightDate.Value.Year, + SeasonNumber = p.Episode == null ? null : p.Episode.Series, + IsSeries = p.Episode != null, + IsRepeat = p.IsPreviouslyShown && !p.IsNew, + IsPremiere = p.Premiere != null, + IsKids = p.Categories.Any(c => info.KidsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), + IsMovie = p.Categories.Any(c => info.MovieCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), + IsNews = p.Categories.Any(c => info.NewsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), + IsSports = p.Categories.Any(c => info.SportsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), + ImageUrl = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source) ? p.Icon.Source : null, + 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 + }; + + if (!string.IsNullOrWhiteSpace(p.ProgramId)) + { + programInfo.ShowId = p.ProgramId; + } + else + { + var uniqueString = (p.Title ?? string.Empty) + (episodeTitle ?? string.Empty) /*+ (p.IceTvEpisodeNumber ?? string.Empty)*/; + + if (programInfo.SeasonNumber.HasValue) + { + uniqueString = "-" + programInfo.SeasonNumber.Value.ToString(CultureInfo.InvariantCulture); + } + if (programInfo.EpisodeNumber.HasValue) + { + uniqueString = "-" + programInfo.EpisodeNumber.Value.ToString(CultureInfo.InvariantCulture); + } + + programInfo.ShowId = uniqueString.GetMD5().ToString("N"); + + // If we don't have valid episode info, assume it's a unique program, otherwise recordings might be skipped + if (programInfo.IsSeries && !programInfo.IsRepeat) + { + if ((programInfo.EpisodeNumber ?? 0) == 0) + { + programInfo.ShowId = programInfo.ShowId + programInfo.StartDate.Ticks.ToString(CultureInfo.InvariantCulture); + } + } + } + + // Construct an id from the channel and start date + programInfo.Id = String.Format("{0}_{1:O}", p.ChannelId, p.StartDate); + + if (programInfo.IsMovie) + { + programInfo.IsSeries = false; + programInfo.EpisodeNumber = null; + programInfo.EpisodeTitle = null; + } + + return programInfo; + } + + public Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings) + { + // Assume all urls are valid. check files for existence + if (!info.Path.StartsWith("http", StringComparison.OrdinalIgnoreCase) && !_fileSystem.FileExists(info.Path)) + { + throw new FileNotFoundException("Could not find the XmlTv file specified:", info.Path); + } + + return Task.FromResult(true); + } + + public async Task> GetLineups(ListingsProviderInfo info, string country, string location) + { + // In theory this should never be called because there is always only one lineup + var path = await GetXml(info.Path, CancellationToken.None).ConfigureAwait(false); + var reader = new XmlTvReader(path, GetLanguage(info)); + var results = reader.GetChannels(); + + // Should this method be async? + return results.Select(c => new NameIdPair() { Id = c.Id, Name = c.DisplayName }).ToList(); + } + + public async Task> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken) + { + // In theory this should never be called because there is always only one lineup + var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); + var reader = new XmlTvReader(path, GetLanguage(info)); + var results = reader.GetChannels(); + + // Should this method be async? + return results.Select(c => new ChannelInfo + { + Id = c.Id, + Name = c.DisplayName, + ImageUrl = c.Icon != null && !String.IsNullOrEmpty(c.Icon.Source) ? c.Icon.Source : null, + Number = string.IsNullOrWhiteSpace(c.Number) ? c.Id : c.Number + + }).ToList(); + } + } +} From baa2afb61e90e99f32b17b572d836ba0dfbc4f0f Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 30 Dec 2018 17:56:47 +0100 Subject: [PATCH 4/7] Restore latest version Source: https://github.com/jellyfin/jellyfin/blob/30baa15839d268e3f03ac46844b61ec4b2aef1bc/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs --- .../LiveTv/Listings/XmlTvListingsProvider.cs | 62 ++++++++++++++++--- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 16252b557c..08abd51e1e 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -102,23 +102,64 @@ namespace Emby.Server.Implementations.LiveTv.Listings if (string.Equals(ext, ".gz", StringComparison.OrdinalIgnoreCase)) { - using (var stream = _fileSystem.OpenRead(file)) + try { - var tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); - _fileSystem.CreateDirectory(tempFolder); - - _zipClient.ExtractAllFromGz(stream, tempFolder, true); + var tempFolder = ExtractGz(file); + return FindXmlFile(tempFolder); + } + catch (Exception ex) + { + _logger.ErrorException("Error extracting from gz file {0}", ex, file); + } - return _fileSystem.GetFiles(tempFolder, true) - .Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase)) - .Select(i => i.FullName) - .FirstOrDefault(); + try + { + var tempFolder = ExtractFirstFileFromGz(file); + return FindXmlFile(tempFolder); + } + catch (Exception ex) + { + _logger.ErrorException("Error extracting from zip file {0}", ex, file); } } return file; } + private string ExtractFirstFileFromGz(string file) + { + using (var stream = _fileSystem.OpenRead(file)) + { + var tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); + _fileSystem.CreateDirectory(tempFolder); + + _zipClient.ExtractFirstFileFromGz(stream, tempFolder, "data.xml"); + + return tempFolder; + } + } + + private string ExtractGz(string file) + { + using (var stream = _fileSystem.OpenRead(file)) + { + var tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); + _fileSystem.CreateDirectory(tempFolder); + + _zipClient.ExtractAllFromGz(stream, tempFolder, true); + + return tempFolder; + } + } + + private string FindXmlFile(string directory) + { + return _fileSystem.GetFiles(directory, true) + .Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase)) + .Select(i => i.FullName) + .FirstOrDefault(); + } + public async Task> GetProgramsAsync(ListingsProviderInfo info, string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(channelId)) @@ -139,6 +180,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings _logger.Debug("Getting xmltv programs for channel {0}", channelId); var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); + _logger.Debug("Opening XmlTvReader for {0}", path); var reader = new XmlTvReader(path, GetLanguage(info)); var results = reader.GetProgrammes(channelId, startDateUtc, endDateUtc, cancellationToken); @@ -232,6 +274,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { // In theory this should never be called because there is always only one lineup var path = await GetXml(info.Path, CancellationToken.None).ConfigureAwait(false); + _logger.Debug("Opening XmlTvReader for {0}", path); var reader = new XmlTvReader(path, GetLanguage(info)); var results = reader.GetChannels(); @@ -243,6 +286,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { // In theory this should never be called because there is always only one lineup var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); + _logger.Debug("Opening XmlTvReader for {0}", path); var reader = new XmlTvReader(path, GetLanguage(info)); var results = reader.GetChannels(); From 589aa2416aca71d6e487c46b2a464537a0c8392c Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 30 Dec 2018 18:21:49 +0100 Subject: [PATCH 5/7] Clean up XmlTvListeningProvider --- .../LiveTv/Listings/XmlTvListingsProvider.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 08abd51e1e..b8c4314a1a 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -1,6 +1,3 @@ -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.LiveTv; using System; using System.Collections.Generic; using System.Globalization; @@ -14,10 +11,13 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Common.Progress; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; +using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; -namespace Emby.Server.Implementations.LiveTv.Listings +namespace Jellyfin.Server.Implementations.LiveTv.Listings { public class XmlTvListingsProvider : IListingsProvider { @@ -189,20 +189,20 @@ namespace Emby.Server.Implementations.LiveTv.Listings private ProgramInfo GetProgramInfo(XmlTvProgram p, ListingsProviderInfo info) { - var episodeTitle = p.Episode == null ? null : p.Episode.Title; + var episodeTitle = p.Episode?.Title; var programInfo = new ProgramInfo { ChannelId = p.ChannelId, EndDate = p.EndDate.UtcDateTime, - EpisodeNumber = p.Episode == null ? null : p.Episode.Episode, + EpisodeNumber = p.Episode?.Episode, EpisodeTitle = episodeTitle, Genres = p.Categories, StartDate = p.StartDate.UtcDateTime, Name = p.Title, Overview = p.Description, - ProductionYear = !p.CopyrightDate.HasValue ? (int?)null : p.CopyrightDate.Value.Year, - SeasonNumber = p.Episode == null ? null : p.Episode.Series, + ProductionYear = p.CopyrightDate?.Year, + SeasonNumber = p.Episode?.Series, IsSeries = p.Episode != null, IsRepeat = p.IsPreviouslyShown && !p.IsNew, IsPremiere = p.Premiere != null, @@ -213,8 +213,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings ImageUrl = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source) ? p.Icon.Source : null, 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 + CommunityRating = p.StarRating, + SeriesId = p.Episode == null ? null : p.Title.GetMD5().ToString("N") }; if (!string.IsNullOrWhiteSpace(p.ProgramId)) @@ -267,7 +267,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings throw new FileNotFoundException("Could not find the XmlTv file specified:", info.Path); } - return Task.FromResult(true); + return Task.CompletedTask; } public async Task> GetLineups(ListingsProviderInfo info, string country, string location) From 9ff45cf9690621612a9f58e6abdf1c6cde3ddcda Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 30 Dec 2018 18:30:29 +0100 Subject: [PATCH 6/7] Some voodoo magic to stop a crash --- .../Channels/RefreshChannelsScheduledTask.cs | 3 ++- .../LiveTv/Listings/SchedulesDirect.cs | 2 +- Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs b/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs index 0208183614..9d1b751d75 100644 --- a/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs +++ b/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Progress; using MediaBrowser.Model.Tasks; @@ -54,7 +55,7 @@ namespace Emby.Server.Implementations.Channels get { return true; } } - public async Task Execute(System.Threading.CancellationToken cancellationToken, IProgress progress) + public async Task Execute(CancellationToken cancellationToken, IProgress progress) { var manager = (ChannelManager)_channelManager; diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 9021666a30..2d0eaf25ba 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -1298,4 +1298,4 @@ namespace Emby.Server.Implementations.LiveTv.Listings } } -} \ No newline at end of file +} diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index d57f7e8cc3..7f2a5ad295 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2392,8 +2392,8 @@ namespace Emby.Server.Implementations.LiveTv public async Task SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings) { - // Let's try something - //info = _jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(info)); + // Voodoo + info = _jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(info)); IListingsProvider provider = _listingProviders.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase)); @@ -2406,7 +2406,7 @@ namespace Emby.Server.Implementations.LiveTv await provider.Validate(info, validateLogin, validateListings).ConfigureAwait(false); - var config = GetConfiguration(); + LiveTvOptions config = GetConfiguration(); var list = config.ListingProviders.ToList(); var index = list.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase)); From f31457a457782cba0b34d409f93e051666c7a5c1 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 30 Dec 2018 20:21:48 +0100 Subject: [PATCH 7/7] Final cleanup --- .../LiveTv/Listings/XmlTvListingsProvider.cs | 99 +++++++++---------- .../LiveTv/LiveTvManager.cs | 7 +- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index b8c4314a1a..a8609ce2da 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -65,8 +65,8 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings return UnzipIfNeeded(path, path); } - var cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "-" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + ".xml"; - var cacheFile = Path.Combine(_config.ApplicationPaths.CachePath, "xmltv", cacheFilename); + string cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "-" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + ".xml"; + string cacheFile = Path.Combine(_config.ApplicationPaths.CachePath, "xmltv", cacheFilename); if (_fileSystem.FileExists(cacheFile)) { return UnzipIfNeeded(path, cacheFile); @@ -74,7 +74,7 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings _logger.Info("Downloading xmltv listings from {0}", path); - var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions + string tempFile = await _httpClient.GetTempFile(new HttpRequestOptions { CancellationToken = cancellationToken, Url = path, @@ -98,13 +98,13 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings private string UnzipIfNeeded(string originalUrl, string file) { - var ext = Path.GetExtension(originalUrl.Split('?')[0]); + string ext = Path.GetExtension(originalUrl.Split('?')[0]); if (string.Equals(ext, ".gz", StringComparison.OrdinalIgnoreCase)) { try { - var tempFolder = ExtractGz(file); + string tempFolder = ExtractGz(file); return FindXmlFile(tempFolder); } catch (Exception ex) @@ -114,7 +114,7 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings try { - var tempFolder = ExtractFirstFileFromGz(file); + string tempFolder = ExtractFirstFileFromGz(file); return FindXmlFile(tempFolder); } catch (Exception ex) @@ -130,7 +130,7 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings { using (var stream = _fileSystem.OpenRead(file)) { - var tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); + string tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); _fileSystem.CreateDirectory(tempFolder); _zipClient.ExtractFirstFileFromGz(stream, tempFolder, "data.xml"); @@ -143,7 +143,7 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings { using (var stream = _fileSystem.OpenRead(file)) { - var tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); + string tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); _fileSystem.CreateDirectory(tempFolder); _zipClient.ExtractAllFromGz(stream, tempFolder, true); @@ -179,51 +179,47 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings _logger.Debug("Getting xmltv programs for channel {0}", channelId); - var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); + string path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); _logger.Debug("Opening XmlTvReader for {0}", path); var reader = new XmlTvReader(path, GetLanguage(info)); - var results = reader.GetProgrammes(channelId, startDateUtc, endDateUtc, cancellationToken); - return results.Select(p => GetProgramInfo(p, info)); + return reader.GetProgrammes(channelId, startDateUtc, endDateUtc, cancellationToken) + .Select(p => GetProgramInfo(p, info)); } - private ProgramInfo GetProgramInfo(XmlTvProgram p, ListingsProviderInfo info) + private ProgramInfo GetProgramInfo(XmlTvProgram program, ListingsProviderInfo info) { - var episodeTitle = p.Episode?.Title; + string episodeTitle = program.Episode?.Title; var programInfo = new ProgramInfo { - ChannelId = p.ChannelId, - EndDate = p.EndDate.UtcDateTime, - EpisodeNumber = p.Episode?.Episode, + ChannelId = program.ChannelId, + EndDate = program.EndDate.UtcDateTime, + EpisodeNumber = program.Episode?.Episode, EpisodeTitle = episodeTitle, - Genres = p.Categories, - StartDate = p.StartDate.UtcDateTime, - Name = p.Title, - Overview = p.Description, - ProductionYear = p.CopyrightDate?.Year, - SeasonNumber = p.Episode?.Series, - IsSeries = p.Episode != null, - IsRepeat = p.IsPreviouslyShown && !p.IsNew, - IsPremiere = p.Premiere != null, - IsKids = p.Categories.Any(c => info.KidsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), - IsMovie = p.Categories.Any(c => info.MovieCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), - IsNews = p.Categories.Any(c => info.NewsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), - IsSports = p.Categories.Any(c => info.SportsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), - ImageUrl = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source) ? p.Icon.Source : null, - 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, - SeriesId = p.Episode == null ? null : p.Title.GetMD5().ToString("N") + Genres = program.Categories, + StartDate = program.StartDate.UtcDateTime, + Name = program.Title, + Overview = program.Description, + ProductionYear = program.CopyrightDate?.Year, + SeasonNumber = program.Episode?.Series, + IsSeries = program.Episode != null, + IsRepeat = program.IsPreviouslyShown && !program.IsNew, + IsPremiere = program.Premiere != null, + IsKids = program.Categories.Any(c => info.KidsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), + IsMovie = program.Categories.Any(c => info.MovieCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), + IsNews = program.Categories.Any(c => info.NewsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), + IsSports = program.Categories.Any(c => info.SportsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), + ImageUrl = program.Icon != null && !String.IsNullOrEmpty(program.Icon.Source) ? program.Icon.Source : null, + HasImage = program.Icon != null && !String.IsNullOrEmpty(program.Icon.Source), + OfficialRating = program.Rating != null && !String.IsNullOrEmpty(program.Rating.Value) ? program.Rating.Value : null, + CommunityRating = program.StarRating, + SeriesId = program.Episode == null ? null : program.Title.GetMD5().ToString("N") }; - if (!string.IsNullOrWhiteSpace(p.ProgramId)) + if (string.IsNullOrWhiteSpace(program.ProgramId)) { - programInfo.ShowId = p.ProgramId; - } - else - { - var uniqueString = (p.Title ?? string.Empty) + (episodeTitle ?? string.Empty) /*+ (p.IceTvEpisodeNumber ?? string.Empty)*/; + string uniqueString = (program.Title ?? string.Empty) + (episodeTitle ?? string.Empty) /*+ (p.IceTvEpisodeNumber ?? string.Empty)*/; if (programInfo.SeasonNumber.HasValue) { @@ -237,17 +233,20 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings programInfo.ShowId = uniqueString.GetMD5().ToString("N"); // If we don't have valid episode info, assume it's a unique program, otherwise recordings might be skipped - if (programInfo.IsSeries && !programInfo.IsRepeat) + if (programInfo.IsSeries + && !programInfo.IsRepeat + && (programInfo.EpisodeNumber ?? 0) == 0) { - if ((programInfo.EpisodeNumber ?? 0) == 0) - { - programInfo.ShowId = programInfo.ShowId + programInfo.StartDate.Ticks.ToString(CultureInfo.InvariantCulture); - } + programInfo.ShowId = programInfo.ShowId + programInfo.StartDate.Ticks.ToString(CultureInfo.InvariantCulture); } } + else + { + programInfo.ShowId = program.ProgramId; + } // Construct an id from the channel and start date - programInfo.Id = String.Format("{0}_{1:O}", p.ChannelId, p.StartDate); + programInfo.Id = String.Format("{0}_{1:O}", program.ChannelId, program.StartDate); if (programInfo.IsMovie) { @@ -273,10 +272,10 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings public async Task> GetLineups(ListingsProviderInfo info, string country, string location) { // In theory this should never be called because there is always only one lineup - var path = await GetXml(info.Path, CancellationToken.None).ConfigureAwait(false); + string path = await GetXml(info.Path, CancellationToken.None).ConfigureAwait(false); _logger.Debug("Opening XmlTvReader for {0}", path); var reader = new XmlTvReader(path, GetLanguage(info)); - var results = reader.GetChannels(); + IEnumerable results = reader.GetChannels(); // Should this method be async? return results.Select(c => new NameIdPair() { Id = c.Id, Name = c.DisplayName }).ToList(); @@ -285,10 +284,10 @@ namespace Jellyfin.Server.Implementations.LiveTv.Listings public async Task> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken) { // In theory this should never be called because there is always only one lineup - var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); + string path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); _logger.Debug("Opening XmlTvReader for {0}", path); var reader = new XmlTvReader(path, GetLanguage(info)); - var results = reader.GetChannels(); + IEnumerable results = reader.GetChannels(); // Should this method be async? return results.Select(c => new ChannelInfo diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 7f2a5ad295..e4400220e6 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2392,7 +2392,8 @@ namespace Emby.Server.Implementations.LiveTv public async Task SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings) { - // Voodoo + // Hack to make the object a pure ListingsProviderInfo instead of an AddListingProvider + // ServerConfiguration.SaveConfiguration crashes during xml serialization for AddListingProvider info = _jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(info)); IListingsProvider provider = _listingProviders.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase)); @@ -2408,8 +2409,8 @@ namespace Emby.Server.Implementations.LiveTv LiveTvOptions config = GetConfiguration(); - var list = config.ListingProviders.ToList(); - var index = list.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase)); + List list = config.ListingProviders.ToList(); + int index = list.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase)); if (index == -1 || string.IsNullOrWhiteSpace(info.Id)) {