Browse Source

initial commit

Claus Vium 6 years ago
parent
commit
9729ae52a3

+ 2 - 1
MediaBrowser.Providers/MediaBrowser.Providers.csproj

@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
 
   <ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
     <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
@@ -12,6 +12,7 @@
 
 
   <ItemGroup>
   <ItemGroup>
     <PackageReference Include="PlaylistsNET" Version="1.0.2" />
     <PackageReference Include="PlaylistsNET" Version="1.0.2" />
+    <PackageReference Include="TvDbSharper" Version="2.0.0" />
   </ItemGroup>
   </ItemGroup>
 
 
   <PropertyGroup>
   <PropertyGroup>

+ 178 - 697
MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs

@@ -12,7 +12,6 @@ using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
@@ -22,6 +21,9 @@ using MediaBrowser.Model.Net;
 using MediaBrowser.Model.Providers;
 using MediaBrowser.Model.Providers;
 using MediaBrowser.Model.Xml;
 using MediaBrowser.Model.Xml;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging;
+using TvDbSharper;
+using TvDbSharper.Dto;
+using Series = MediaBrowser.Controller.Entities.TV.Series;
 
 
 namespace MediaBrowser.Providers.TV.TheTVDB
 namespace MediaBrowser.Providers.TV.TheTVDB
 {
 {
@@ -37,6 +39,7 @@ namespace MediaBrowser.Providers.TV.TheTVDB
         private readonly ILogger _logger;
         private readonly ILogger _logger;
         private readonly ILibraryManager _libraryManager;
         private readonly ILibraryManager _libraryManager;
         private readonly ILocalizationManager _localizationManager;
         private readonly ILocalizationManager _localizationManager;
+        private readonly TvDbClient _tvDbClient;
 
 
         public TvdbSeriesProvider(IZipClient zipClient, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config, ILogger logger, ILibraryManager libraryManager, IXmlReaderSettingsFactory xmlSettings, ILocalizationManager localizationManager)
         public TvdbSeriesProvider(IZipClient zipClient, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config, ILogger logger, ILibraryManager libraryManager, IXmlReaderSettingsFactory xmlSettings, ILocalizationManager localizationManager)
         {
         {
@@ -49,15 +52,9 @@ namespace MediaBrowser.Providers.TV.TheTVDB
             _xmlSettings = xmlSettings;
             _xmlSettings = xmlSettings;
             _localizationManager = localizationManager;
             _localizationManager = localizationManager;
             Current = this;
             Current = this;
+            _tvDbClient = new TvDbClient();
         }
         }
 
 
-        public const string TvdbBaseUrl = "https://www.thetvdb.com/";
-
-        private const string SeriesSearchUrl = TvdbBaseUrl + "api/GetSeries.php?seriesname={0}&language={1}";
-        private const string SeriesGetZip = TvdbBaseUrl + "api/{0}/series/{1}/all/{2}.zip";
-        private const string GetSeriesByImdbId = TvdbBaseUrl + "api/GetSeriesByRemoteID.php?imdbid={0}&language={1}";
-        private const string GetSeriesByZap2ItId = TvdbBaseUrl + "api/GetSeriesByRemoteID.php?zap2it={0}&language={1}";
-
         private string NormalizeLanguage(string language)
         private string NormalizeLanguage(string language)
         {
         {
             if (string.IsNullOrWhiteSpace(language))
             if (string.IsNullOrWhiteSpace(language))
@@ -135,29 +132,34 @@ namespace MediaBrowser.Providers.TV.TheTVDB
         /// <returns>Task{System.Boolean}.</returns>
         /// <returns>Task{System.Boolean}.</returns>
         private void FetchSeriesData(MetadataResult<Series> result, string metadataLanguage, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken)
         private void FetchSeriesData(MetadataResult<Series> result, string metadataLanguage, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken)
         {
         {
+            _tvDbClient.AcceptedLanguage = NormalizeLanguage(metadataLanguage);
             var series = result.Item;
             var series = result.Item;
+            TvDbResponse<SeriesSearchResult[]> searchResult;
 
 
-            if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out string id) && !string.IsNullOrEmpty(id))
+            if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out var tvdbId) && !string.IsNullOrEmpty(id))
             {
             {
-                series.SetProviderId(MetadataProviders.Tvdb, id);
+                series.SetProviderId(MetadataProviders.Tvdb, tvdbId);
             }
             }
 
 
-            if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id) && !string.IsNullOrEmpty(id))
+            if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out var imdbId) && !string.IsNullOrEmpty(id))
             {
             {
-                series.SetProviderId(MetadataProviders.Imdb, id);
+                series.SetProviderId(MetadataProviders.Imdb, imdbId);
+                tvdbId = GetSeriesByRemoteId(imdbId, MetadataProviders.Imdb.ToString(), metadataLanguage, cancellationToken).Result.ToString();
             }
             }
 
 
-            if (seriesProviderIds.TryGetValue(MetadataProviders.Zap2It.ToString(), out id) && !string.IsNullOrEmpty(id))
+            if (seriesProviderIds.TryGetValue(MetadataProviders.Zap2It.ToString(), out var zap2It) && !string.IsNullOrEmpty(id))
             {
             {
-                series.SetProviderId(MetadataProviders.Zap2It, id);
+                series.SetProviderId(MetadataProviders.Zap2It, zap2It);
+                tvdbId = GetSeriesByRemoteId(zap2It, MetadataProviders.Zap2It.ToString(), metadataLanguage, cancellationToken).Result.ToString();
             }
             }
 
 
-            var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
-
-            var seriesXmlPath = GetSeriesXmlPath(seriesProviderIds, metadataLanguage);
-            var actorsXmlPath = Path.Combine(seriesDataPath, "actors.xml");
+            var seriesResult = _tvDbClient.Series.GetAsync(Convert.ToInt32(tvdbId), cancellationToken).Result;
+//            var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
+//
+//            var seriesXmlPath = GetSeriesXmlPath(seriesProviderIds, metadataLanguage);
+//            var actorsXmlPath = Path.Combine(seriesDataPath, "actors.xml");
 
 
-            FetchSeriesInfo(result, seriesXmlPath, cancellationToken);
+            FetchSeriesInfo(result, searchResult, cancellationToken);
 
 
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
@@ -199,7 +201,7 @@ namespace MediaBrowser.Providers.TV.TheTVDB
 
 
             if (!string.Equals(idType, "tvdb", StringComparison.OrdinalIgnoreCase))
             if (!string.Equals(idType, "tvdb", StringComparison.OrdinalIgnoreCase))
             {
             {
-                seriesId = await GetSeriesByRemoteId(seriesId, idType, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
+                seriesId = (await GetSeriesByRemoteId(seriesId, idType, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false)).ToString();
             }
             }
 
 
             // If searching by remote id came up empty, then do a regular search
             // If searching by remote id came up empty, then do a regular search
@@ -269,227 +271,31 @@ namespace MediaBrowser.Providers.TV.TheTVDB
             await ExtractEpisodes(seriesDataPath, downloadLangaugeXmlFile, lastTvDbUpdateTime).ConfigureAwait(false);
             await ExtractEpisodes(seriesDataPath, downloadLangaugeXmlFile, lastTvDbUpdateTime).ConfigureAwait(false);
         }
         }
 
 
-        private async Task<string> GetSeriesByRemoteId(string id, string idType, string language, CancellationToken cancellationToken)
+        private async Task<int> GetSeriesByRemoteId(string id, string idType, string language, CancellationToken cancellationToken)
         {
         {
-            string url;
+            _tvDbClient.AcceptedLanguage = NormalizeLanguage(language);
+            TvDbResponse<SeriesSearchResult[]> result;
+
             if (string.Equals(idType, MetadataProviders.Zap2It.ToString(), StringComparison.OrdinalIgnoreCase))
             if (string.Equals(idType, MetadataProviders.Zap2It.ToString(), StringComparison.OrdinalIgnoreCase))
             {
             {
-                url = string.Format(GetSeriesByZap2ItId, id, NormalizeLanguage(language));
+                result = await _tvDbClient.Search.SearchSeriesByZap2ItIdAsync(id, cancellationToken);
             }
             }
             else
             else
             {
             {
-                url = string.Format(GetSeriesByImdbId, id, NormalizeLanguage(language));
-            }
-
-            using (var response = await _httpClient.SendAsync(new HttpRequestOptions
-            {
-                Url = url,
-                CancellationToken = cancellationToken,
-                BufferContent = false
-
-            }, "GET").ConfigureAwait(false))
-            {
-                using (var result = response.Content)
-                {
-                    return FindSeriesId(result);
-                }
-            }
-        }
-
-        private string FindSeriesId(Stream stream)
-        {
-            using (var streamReader = new StreamReader(stream, Encoding.UTF8))
-            {
-                var settings = _xmlSettings.Create(false);
-
-                settings.CheckCharacters = false;
-                settings.IgnoreProcessingInstructions = true;
-                settings.IgnoreComments = true;
-
-                // Use XmlReader for best performance
-                using (var reader = XmlReader.Create(streamReader, settings))
-                {
-                    reader.MoveToContent();
-                    reader.Read();
-
-                    // Loop through each element
-                    while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-                    {
-                        if (reader.NodeType == XmlNodeType.Element)
-                        {
-                            switch (reader.Name)
-                            {
-                                case "Series":
-                                    {
-                                        if (reader.IsEmptyElement)
-                                        {
-                                            reader.Read();
-                                            continue;
-                                        }
-                                        using (var subtree = reader.ReadSubtree())
-                                        {
-                                            return FindSeriesId(subtree);
-                                        }
-                                    }
-
-                                default:
-                                    reader.Skip();
-                                    break;
-                            }
-                        }
-                        else
-                        {
-                            reader.Read();
-                        }
-                    }
-                }
-            }
-
-            return null;
-        }
-
-        private string FindSeriesId(XmlReader reader)
-        {
-            reader.MoveToContent();
-            reader.Read();
-
-            // Loop through each element
-            while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-            {
-                if (reader.NodeType == XmlNodeType.Element)
-                {
-                    switch (reader.Name)
-                    {
-                        case "seriesid":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    return val;
-                                }
-
-                                return null;
-                            }
-
-                        default:
-                            reader.Skip();
-                            break;
-                    }
-                }
-                else
-                {
-                    reader.Read();
-                }
+                result = await _tvDbClient.Search.SearchSeriesByImdbIdAsync(id, cancellationToken);
             }
             }
 
 
-            return null;
+            return result.Data.First().Id;
         }
         }
 
 
         internal static bool IsValidSeries(Dictionary<string, string> seriesProviderIds)
         internal static bool IsValidSeries(Dictionary<string, string> seriesProviderIds)
         {
         {
-            if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out string id))
-            {
-                // This check should ideally never be necessary but we're seeing some cases of this and haven't tracked them down yet.
-                if (!string.IsNullOrWhiteSpace(id))
-                {
-                    return true;
-                }
-            }
-
-            if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id))
-            {
-                // This check should ideally never be necessary but we're seeing some cases of this and haven't tracked them down yet.
-                if (!string.IsNullOrWhiteSpace(id))
-                {
-                    return true;
-                }
-            }
-
-            if (seriesProviderIds.TryGetValue(MetadataProviders.Zap2It.ToString(), out id))
-            {
-                // This check should ideally never be necessary but we're seeing some cases of this and haven't tracked them down yet.
-                if (!string.IsNullOrWhiteSpace(id))
-                {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private SemaphoreSlim _ensureSemaphore = new SemaphoreSlim(1, 1);
-        internal async Task<string> EnsureSeriesInfo(Dictionary<string, string> seriesProviderIds, string seriesName, int? seriesYear, string preferredMetadataLanguage, CancellationToken cancellationToken)
-        {
-            await _ensureSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
-
-            try
-            {
-                if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out string seriesId) && !string.IsNullOrWhiteSpace(seriesId))
-                {
-                    var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
-
-                    // Only download if not already there
-                    // The post-scan task will take care of updates so we don't need to re-download here
-                    if (!IsCacheValid(seriesDataPath, preferredMetadataLanguage))
-                    {
-                        await DownloadSeriesZip(seriesId, MetadataProviders.Tvdb.ToString(), seriesName, seriesYear, seriesDataPath, null, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
-                    }
-
-                    return seriesDataPath;
-                }
-
-                if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out seriesId) && !string.IsNullOrWhiteSpace(seriesId))
-                {
-                    var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
-
-                    // Only download if not already there
-                    // The post-scan task will take care of updates so we don't need to re-download here
-                    if (!IsCacheValid(seriesDataPath, preferredMetadataLanguage))
-                    {
-                        try
-                        {
-                            await DownloadSeriesZip(seriesId, MetadataProviders.Imdb.ToString(), seriesName, seriesYear, seriesDataPath, null, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
-                        }
-                        catch (ArgumentNullException)
-                        {
-                            // Unable to determine tvdb id based on imdb id
-                            return null;
-                        }
-                    }
-
-                    return seriesDataPath;
-                }
-
-                if (seriesProviderIds.TryGetValue(MetadataProviders.Zap2It.ToString(), out seriesId) && !string.IsNullOrWhiteSpace(seriesId))
-                {
-                    var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
-
-                    // Only download if not already there
-                    // The post-scan task will take care of updates so we don't need to re-download here
-                    if (!IsCacheValid(seriesDataPath, preferredMetadataLanguage))
-                    {
-                        try
-                        {
-                            await DownloadSeriesZip(seriesId, MetadataProviders.Zap2It.ToString(), seriesName, seriesYear, seriesDataPath, null, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
-                        }
-                        catch (ArgumentNullException)
-                        {
-                            // Unable to determine tvdb id based on Zap2It id
-                            return null;
-                        }
-                    }
-
-                    return seriesDataPath;
-                }
-
-                return null;
-            }
-            finally
-            {
-                _ensureSemaphore.Release();
-            }
+            return seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out _) ||
+                   seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out _) ||
+                   seriesProviderIds.TryGetValue(MetadataProviders.Zap2It.ToString(), out _);
         }
         }
 
 
+        // TODO caching
         private bool IsCacheValid(string seriesDataPath, string preferredMetadataLanguage)
         private bool IsCacheValid(string seriesDataPath, string preferredMetadataLanguage)
         {
         {
             try
             try
@@ -543,7 +349,7 @@ namespace MediaBrowser.Providers.TV.TheTVDB
         /// <returns>Task{System.String}.</returns>
         /// <returns>Task{System.String}.</returns>
         private async Task<IEnumerable<RemoteSearchResult>> FindSeries(string name, int? year, string language, CancellationToken cancellationToken)
         private async Task<IEnumerable<RemoteSearchResult>> FindSeries(string name, int? year, string language, CancellationToken cancellationToken)
         {
         {
-            var results = (await FindSeriesInternal(name, language, cancellationToken).ConfigureAwait(false));
+            var results = await FindSeriesInternal(name, language, cancellationToken).ConfigureAwait(false);
 
 
             if (results.Count == 0)
             if (results.Count == 0)
             {
             {
@@ -552,7 +358,7 @@ namespace MediaBrowser.Providers.TV.TheTVDB
 
 
                 if (!string.IsNullOrWhiteSpace(nameWithoutYear) && !string.Equals(nameWithoutYear, name, StringComparison.OrdinalIgnoreCase))
                 if (!string.IsNullOrWhiteSpace(nameWithoutYear) && !string.Equals(nameWithoutYear, name, StringComparison.OrdinalIgnoreCase))
                 {
                 {
-                    results = (await FindSeriesInternal(nameWithoutYear, language, cancellationToken).ConfigureAwait(false));
+                    results = await FindSeriesInternal(nameWithoutYear, language, cancellationToken).ConfigureAwait(false);
                 }
                 }
             }
             }
 
 
@@ -570,77 +376,32 @@ namespace MediaBrowser.Providers.TV.TheTVDB
 
 
         private async Task<List<RemoteSearchResult>> FindSeriesInternal(string name, string language, CancellationToken cancellationToken)
         private async Task<List<RemoteSearchResult>> FindSeriesInternal(string name, string language, CancellationToken cancellationToken)
         {
         {
-            var url = string.Format(SeriesSearchUrl, WebUtility.UrlEncode(name), NormalizeLanguage(language));
-
+            _tvDbClient.AcceptedLanguage = NormalizeLanguage(language);
             var comparableName = GetComparableName(name);
             var comparableName = GetComparableName(name);
-
             var list = new List<Tuple<List<string>, RemoteSearchResult>>();
             var list = new List<Tuple<List<string>, RemoteSearchResult>>();
+            TvDbResponse<SeriesSearchResult[]> result = await _tvDbClient.Search.SearchSeriesByNameAsync(comparableName, cancellationToken);
 
 
-            using (var response = await _httpClient.SendAsync(new HttpRequestOptions
-            {
-                Url = url,
-                CancellationToken = cancellationToken,
-                BufferContent = false
-
-            }, "GET").ConfigureAwait(false))
+            foreach (var seriesSearchResult in result.Data)
             {
             {
-                using (var stream = response.Content)
+                var tvdbTitles = new List<string>
                 {
                 {
-                    var settings = _xmlSettings.Create(false);
-
-                    settings.CheckCharacters = false;
-                    settings.IgnoreProcessingInstructions = true;
-                    settings.IgnoreComments = true;
-
-                    using (var streamReader = new StreamReader(stream, Encoding.UTF8))
-                    {
-                        // Use XmlReader for best performance
-                        using (var reader = XmlReader.Create(streamReader, settings))
-                        {
-                            reader.MoveToContent();
-                            reader.Read();
-
-                            // Loop through each element
-                            while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-                            {
-                                cancellationToken.ThrowIfCancellationRequested();
+                    GetComparableName(seriesSearchResult.SeriesName)
+                };
+                tvdbTitles.AddRange(seriesSearchResult.Aliases.Select(GetComparableName));
 
 
-                                if (reader.NodeType == XmlNodeType.Element)
-                                {
-                                    switch (reader.Name)
-                                    {
-                                        case "Series":
-                                            {
-                                                if (reader.IsEmptyElement)
-                                                {
-                                                    reader.Read();
-                                                    continue;
-                                                }
-                                                using (var subtree = reader.ReadSubtree())
-                                                {
-                                                    var searchResultInfo = GetSeriesSearchResultFromSubTree(subtree);
-                                                    if (searchResultInfo != null)
-                                                    {
-                                                        searchResultInfo.Item2.SearchProviderName = Name;
-                                                        list.Add(searchResultInfo);
-                                                    }
-                                                }
-                                                break;
-                                            }
+                DateTime.TryParse(seriesSearchResult.FirstAired, out var firstAired);
+                var remoteSearchResult = new RemoteSearchResult
+                {
+                    Name = tvdbTitles.FirstOrDefault(),
+                    ProductionYear = firstAired.Year,
+                    SearchProviderName = Name,
+                    ImageUrl = seriesSearchResult.Banner
 
 
-                                        default:
-                                            reader.Skip();
-                                            break;
-                                    }
-                                }
-                                else
-                                {
-                                    reader.Read();
-                                }
-                            }
-                        }
-                    }
-                }
+                };
+                // TODO requires another query
+                // remoteSearchResult.SetProviderId(MetadataProviders.Imdb, seriesSearchResult.Id);
+                remoteSearchResult.SetProviderId(MetadataProviders.Tvdb, seriesSearchResult.Id.ToString());
+                list.Add(new Tuple<List<string>, RemoteSearchResult>(tvdbTitles, remoteSearchResult));
             }
             }
 
 
             return list
             return list
@@ -650,116 +411,6 @@ namespace MediaBrowser.Providers.TV.TheTVDB
                 .ToList();
                 .ToList();
         }
         }
 
 
-        private Tuple<List<string>, RemoteSearchResult> GetSeriesSearchResultFromSubTree(XmlReader reader)
-        {
-            var searchResult = new RemoteSearchResult
-            {
-                SearchProviderName = Name
-            };
-
-            var tvdbTitles = new List<string>();
-            string seriesId = null;
-
-            reader.MoveToContent();
-            reader.Read();
-
-            // Loop through each element
-            while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-            {
-                if (reader.NodeType == XmlNodeType.Element)
-                {
-                    switch (reader.Name)
-                    {
-                        case "SeriesName":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    tvdbTitles.Add(GetComparableName(val));
-                                }
-                                break;
-                            }
-
-                        case "AliasNames":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                var alias = (val ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).Select(GetComparableName);
-                                tvdbTitles.AddRange(alias);
-                                break;
-                            }
-
-                        case "IMDB_ID":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    searchResult.SetProviderId(MetadataProviders.Imdb, val);
-                                }
-                                break;
-                            }
-
-                        case "banner":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    searchResult.ImageUrl = TVUtils.BannerUrl + val;
-                                }
-                                break;
-                            }
-
-                        case "FirstAired":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    if (DateTime.TryParse(val, out var date))
-                                    {
-                                        searchResult.ProductionYear = date.Year;
-                                    }
-                                }
-                                break;
-                            }
-
-                        case "id":
-                        case "seriesid":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    seriesId = val;
-                                }
-                                break;
-                            }
-
-                        default:
-                            reader.Skip();
-                            break;
-                    }
-                }
-                else
-                {
-                    reader.Read();
-                }
-            }
-
-            if (tvdbTitles.Count == 0)
-            {
-                return null;
-            }
-
-            searchResult.Name = tvdbTitles.FirstOrDefault();
-            searchResult.SetProviderId(MetadataProviders.Tvdb, seriesId);
-
-            return new Tuple<List<string>, RemoteSearchResult>(tvdbTitles, searchResult);
-        }
-
         /// <summary>
         /// <summary>
         /// The remove
         /// The remove
         /// </summary>
         /// </summary>
@@ -817,85 +468,141 @@ namespace MediaBrowser.Providers.TV.TheTVDB
             return name.Trim();
             return name.Trim();
         }
         }
 
 
-        private void FetchSeriesInfo(MetadataResult<Series> result, string seriesXmlPath, CancellationToken cancellationToken)
+        private void FetchSeriesInfo(MetadataResult<Series> result, TvDbResponse<TvDbSharper.Dto.Series> seriesResponse, CancellationToken cancellationToken)
         {
         {
-            var settings = _xmlSettings.Create(false);
-
-            settings.CheckCharacters = false;
-            settings.IgnoreProcessingInstructions = true;
-            settings.IgnoreComments = true;
-
-            var episiodeAirDates = new List<DateTime>();
+            var episodeAirDates = new List<DateTime>();
+            var series = result.Item;
+            Series item = result.Item;
+            series.SetProviderId(MetadataProviders.Tvdb, seriesResponse.Data.Id.ToString());
+            series.Name = seriesResponse.Data.SeriesName;
+            series.Overview = (seriesResponse.Data.Overview ?? string.Empty).Trim();
+            // TODO result.ResultLanguage = (seriesResponse.Data. ?? string.Empty).Trim();
+            series.AirDays = TVUtils.GetAirDays(seriesResponse.Data.AirsDayOfWeek);
+            series.AirTime = seriesResponse.Data.AirsTime;
+
+            series.CommunityRating = (float?)seriesResponse.Data.SiteRating;
+            series.SetProviderId(MetadataProviders.Imdb, seriesResponse.Data.ImdbId);
+            series.SetProviderId(MetadataProviders.Zap2It, seriesResponse.Data.Zap2itId);
+            if (Enum.TryParse(seriesResponse.Data.Status, true, out SeriesStatus seriesStatus))
+            {
+                series.Status = seriesStatus;
+            }
 
 
-            using (var fileStream = _fileSystem.GetFileStream(seriesXmlPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
+            if (DateTime.TryParse(seriesResponse.Data.FirstAired, out var date))
             {
             {
-                using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
-                {
-                    // Use XmlReader for best performance
-                    using (var reader = XmlReader.Create(streamReader, settings))
-                    {
-                        reader.MoveToContent();
-                        reader.Read();
+                date = date.ToUniversalTime();
 
 
-                        // Loop through each element
-                        while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-                        {
-                            cancellationToken.ThrowIfCancellationRequested();
+                series.PremiereDate = date;
+                series.ProductionYear = date.Year;
+            }
 
 
-                            if (reader.NodeType == XmlNodeType.Element)
-                            {
-                                switch (reader.Name)
-                                {
-                                    case "Series":
-                                        {
-                                            if (reader.IsEmptyElement)
-                                            {
-                                                reader.Read();
-                                                continue;
-                                            }
-                                            using (var subtree = reader.ReadSubtree())
-                                            {
-                                                FetchDataFromSeriesNode(result, subtree, cancellationToken);
-                                            }
-                                            break;
-                                        }
+            series.RunTimeTicks = TimeSpan.FromMinutes(Convert.ToDouble(seriesResponse.Data.Runtime)).Ticks;
 
 
-                                    case "Episode":
-                                        {
-                                            if (reader.IsEmptyElement)
-                                            {
-                                                reader.Read();
-                                                continue;
-                                            }
-                                            using (var subtree = reader.ReadSubtree())
-                                            {
-                                                var date = GetFirstAiredDateFromEpisodeNode(subtree, cancellationToken);
 
 
-                                                if (date.HasValue)
-                                                {
-                                                    episiodeAirDates.Add(date.Value);
-                                                }
-                                            }
-                                            break;
-                                        }
+            if (!string.IsNullOrWhiteSpace(val))
+            {
+                var vals = val
+                    .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
+                    .Select(i => i.Trim())
+                    .Where(i => !string.IsNullOrWhiteSpace(i))
+                    .ToList();
 
 
-                                    default:
-                                        reader.Skip();
-                                        break;
-                                }
-                            }
-                            else
-                            {
-                                reader.Read();
-                            }
-                        }
+                if (vals.Count > 0)
+                {
+                    item.Genres = Array.Empty<string>();
+
+                    foreach (var genre in vals)
+                    {
+                        item.AddGenre(genre);
                     }
                     }
                 }
                 }
             }
             }
 
 
-            if (result.Item.Status.HasValue && result.Item.Status.Value == SeriesStatus.Ended && episiodeAirDates.Count > 0)
+            var val = reader.ReadElementContentAsString();
+
+            if (!string.IsNullOrWhiteSpace(val))
             {
             {
-                result.Item.EndDate = episiodeAirDates.Max();
+                var vals = val
+                    .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
+                    .Select(i => i.Trim())
+                    .Where(i => !string.IsNullOrWhiteSpace(i))
+                    .ToList();
+
+                if (vals.Count > 0)
+                {
+                    item.SetStudios(vals);
+                }
+            }
+
+//            using (var fileStream = _fileSystem.GetFileStream(seriesXmlPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
+//            {
+//                using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
+//                {
+//                    // Use XmlReader for best performance
+//                    using (var reader = XmlReader.Create(streamReader, settings))
+//                    {
+//                        reader.MoveToContent();
+//                        reader.Read();
+//
+//                        // Loop through each element
+//                        while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+//                        {
+//                            cancellationToken.ThrowIfCancellationRequested();
+//
+//                            if (reader.NodeType == XmlNodeType.Element)
+//                            {
+//                                switch (reader.Name)
+//                                {
+//                                    case "Series":
+//                                        {
+//                                            if (reader.IsEmptyElement)
+//                                            {
+//                                                reader.Read();
+//                                                continue;
+//                                            }
+//                                            using (var subtree = reader.ReadSubtree())
+//                                            {
+//                                                FetchDataFromSeriesNode(result, subtree, cancellationToken);
+//                                            }
+//                                            break;
+//                                        }
+//
+//                                    case "Episode":
+//                                        {
+//                                            if (reader.IsEmptyElement)
+//                                            {
+//                                                reader.Read();
+//                                                continue;
+//                                            }
+//                                            using (var subtree = reader.ReadSubtree())
+//                                            {
+//                                                var date = GetFirstAiredDateFromEpisodeNode(subtree, cancellationToken);
+//
+//                                                if (date.HasValue)
+//                                                {
+//                                                    episiodeAirDates.Add(date.Value);
+//                                                }
+//                                            }
+//                                            break;
+//                                        }
+//
+//                                    default:
+//                                        reader.Skip();
+//                                        break;
+//                                }
+//                            }
+//                            else
+//                            {
+//                                reader.Read();
+//                            }
+//                        }
+//                    }
+//                }
+//            }
+
+            if (result.Item.Status.HasValue && result.Item.Status.Value == SeriesStatus.Ended && episodeAirDates.Count > 0)
+            {
+                result.Item.EndDate = episodeAirDates.Max();
             }
             }
         }
         }
 
 
@@ -1107,237 +814,11 @@ namespace MediaBrowser.Providers.TV.TheTVDB
             }
             }
         }
         }
 
 
-        private void FetchDataFromSeriesNode(MetadataResult<Series> result, XmlReader reader, CancellationToken cancellationToken)
+        private void FetchDataFromSeriesNode(MetadataResult<Series> result, CancellationToken cancellationToken)
         {
         {
-            Series item = result.Item;
-
-            reader.MoveToContent();
-            reader.Read();
-
-            // Loop through each element
-            while (!reader.EOF && reader.ReadState == ReadState.Interactive)
-            {
-                cancellationToken.ThrowIfCancellationRequested();
-
-                if (reader.NodeType == XmlNodeType.Element)
-                {
-                    switch (reader.Name)
-                    {
-                        case "id":
-                            {
-                                item.SetProviderId(MetadataProviders.Tvdb.ToString(), (reader.ReadElementContentAsString() ?? string.Empty).Trim());
-                                break;
-                            }
-
-                        case "SeriesName":
-                            {
-                                item.Name = (reader.ReadElementContentAsString() ?? string.Empty).Trim();
-                                break;
-                            }
-
-                        case "Overview":
-                            {
-                                item.Overview = (reader.ReadElementContentAsString() ?? string.Empty).Trim();
-                                break;
-                            }
-
-                        case "Language":
-                            {
-                                result.ResultLanguage = (reader.ReadElementContentAsString() ?? string.Empty).Trim();
-                                break;
-                            }
-
-                        case "Airs_DayOfWeek":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    item.AirDays = TVUtils.GetAirDays(val);
-                                }
-                                break;
-                            }
-
-                        case "Airs_Time":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    item.AirTime = val;
-                                }
-                                break;
-                            }
-
-                        case "ContentRating":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    item.OfficialRating = val;
-                                }
-                                break;
-                            }
-
-                        case "Rating":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    // float.TryParse is local aware, so it can be probamatic, force us culture
-                                    if (float.TryParse(val, NumberStyles.AllowDecimalPoint, _usCulture, out var rval))
-                                    {
-                                        item.CommunityRating = rval;
-                                    }
-                                }
-                                break;
-                            }
-                        case "RatingCount":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    // int.TryParse is local aware, so it can be probamatic, force us culture
-                                    if (int.TryParse(val, NumberStyles.Integer, _usCulture, out var rval))
-                                    {
-                                        //item.VoteCount = rval;
-                                    }
-                                }
-
-                                break;
-                            }
-
-                        case "IMDB_ID":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    item.SetProviderId(MetadataProviders.Imdb, val);
-                                }
-
-                                break;
-                            }
-
-                        case "zap2it_id":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    item.SetProviderId(MetadataProviders.Zap2It, val);
-                                }
-
-                                break;
-                            }
-
-                        case "Status":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    if (Enum.TryParse(val, true, out SeriesStatus seriesStatus))
-                                        item.Status = seriesStatus;
-                                }
-
-                                break;
-                            }
-
-                        case "FirstAired":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    if (DateTime.TryParse(val, out var date))
-                                    {
-                                        date = date.ToUniversalTime();
-
-                                        item.PremiereDate = date;
-                                        item.ProductionYear = date.Year;
-                                    }
-                                }
-
-                                break;
-                            }
-
-                        case "Runtime":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    // int.TryParse is local aware, so it can be probamatic, force us culture
-                                    if (int.TryParse(val, NumberStyles.Integer, _usCulture, out var rval))
-                                    {
-                                        item.RunTimeTicks = TimeSpan.FromMinutes(rval).Ticks;
-                                    }
-                                }
-
-                                break;
-                            }
-
-                        case "Genre":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    var vals = val
-                                        .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
-                                        .Select(i => i.Trim())
-                                        .Where(i => !string.IsNullOrWhiteSpace(i))
-                                        .ToList();
-
-                                    if (vals.Count > 0)
-                                    {
-                                        item.Genres = Array.Empty<string>();
-
-                                        foreach (var genre in vals)
-                                        {
-                                            item.AddGenre(genre);
-                                        }
-                                    }
-                                }
-
-                                break;
-                            }
-
-                        case "Network":
-                            {
-                                var val = reader.ReadElementContentAsString();
-
-                                if (!string.IsNullOrWhiteSpace(val))
-                                {
-                                    var vals = val
-                                        .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
-                                        .Select(i => i.Trim())
-                                        .Where(i => !string.IsNullOrWhiteSpace(i))
-                                        .ToList();
-
-                                    if (vals.Count > 0)
-                                    {
-                                        item.SetStudios(vals);
-                                    }
-                                }
+            cancellationToken.ThrowIfCancellationRequested();
 
 
-                                break;
-                            }
 
 
-                        default:
-                            reader.Skip();
-                            break;
-                    }
-                }
-                else
-                {
-                    reader.Read();
-                }
-            }
         }
         }
 
 
         /// <summary>
         /// <summary>