浏览代码

Merge pull request #1850 from MediaBrowser/dev

Dev
Luke 9 年之前
父节点
当前提交
74b57185f6

+ 6 - 4
MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs

@@ -143,7 +143,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
             };
         }
 
-        private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression)
+        private WebRequest GetRequest(HttpRequestOptions options, string method)
         {
             var request = CreateWebRequest(options.Url);
             var httpWebRequest = request as HttpWebRequest;
@@ -154,7 +154,9 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
 
                 AddRequestHeaders(httpWebRequest, options);
 
-                httpWebRequest.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None;
+                httpWebRequest.AutomaticDecompression = options.EnableHttpCompression ? 
+                    (options.DecompressionMethod ?? DecompressionMethods.Deflate) : 
+                    DecompressionMethods.None;
             }
 
             request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
@@ -366,7 +368,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
                 };
             }
 
-            var httpWebRequest = GetRequest(options, httpMethod, options.EnableHttpCompression);
+            var httpWebRequest = GetRequest(options, httpMethod);
 
             if (options.RequestContentBytes != null ||
                 !string.IsNullOrEmpty(options.RequestContent) ||
@@ -556,7 +558,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
 
             options.CancellationToken.ThrowIfCancellationRequested();
 
-            var httpWebRequest = GetRequest(options, "GET", options.EnableHttpCompression);
+            var httpWebRequest = GetRequest(options, "GET");
 
             if (options.ResourcePool != null)
             {

+ 3 - 0
MediaBrowser.Common/Net/HttpRequestOptions.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Net;
 using System.Threading;
 
 namespace MediaBrowser.Common.Net
@@ -16,6 +17,8 @@ namespace MediaBrowser.Common.Net
         /// <value>The URL.</value>
         public string Url { get; set; }
 
+        public DecompressionMethods? DecompressionMethod { get; set; }
+
         /// <summary>
         /// Gets or sets the accept header.
         /// </summary>

+ 4 - 4
MediaBrowser.Controller/Providers/ItemInfo.cs

@@ -1,3 +1,4 @@
+using System;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Entities;
 
@@ -5,10 +6,6 @@ namespace MediaBrowser.Controller.Providers
 {
     public class ItemInfo
     {
-        public ItemInfo()
-        {
-        }
-
         public ItemInfo(IHasMetadata item)
         {
             Path = item.Path;
@@ -21,8 +18,11 @@ namespace MediaBrowser.Controller.Providers
                 VideoType = video.VideoType;
                 IsPlaceHolder = video.IsPlaceHolder;
             }
+
+            ItemType = item.GetType();
         }
 
+        public Type ItemType { get; set; }
         public string Path { get; set; }
         public string ContainingFolderPath { get; set; }
         public VideoType VideoType { get; set; }

+ 141 - 35
MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs

@@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.Music
         private readonly IApplicationHost _appHost;
         private readonly ILogger _logger;
 
-        public static string MusicBrainzBaseUrl = "http://musicbrainz.fercasas.com:5000";
+        public static string MusicBrainzBaseUrl = "https://www.musicbrainz.org";
 
         public MusicBrainzAlbumProvider(IHttpClient httpClient, IApplicationHost appHost, ILogger logger)
         {
@@ -44,7 +44,7 @@ namespace MediaBrowser.Providers.Music
 
             if (!string.IsNullOrEmpty(releaseId))
             {
-                url = string.Format(MusicBrainzBaseUrl + "/ws/2/release/?query=reid:{0}", releaseId);
+                url = string.Format("/ws/2/release/?query=reid:{0}", releaseId);
             }
             else
             {
@@ -52,7 +52,7 @@ namespace MediaBrowser.Providers.Music
 
                 if (!string.IsNullOrWhiteSpace(artistMusicBrainzId))
                 {
-                    url = string.Format(MusicBrainzBaseUrl + "/ws/2/release/?query=\"{0}\" AND arid:{1}",
+                    url = string.Format("/ws/2/release/?query=\"{0}\" AND arid:{1}",
                         WebUtility.UrlEncode(searchInfo.Name),
                         artistMusicBrainzId);
                 }
@@ -60,7 +60,7 @@ namespace MediaBrowser.Providers.Music
                 {
                     isNameSearch = true;
 
-                    url = string.Format(MusicBrainzBaseUrl + "/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"",
+                    url = string.Format("/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"",
                        WebUtility.UrlEncode(searchInfo.Name),
                        WebUtility.UrlEncode(searchInfo.GetAlbumArtist()));
                 }
@@ -199,57 +199,86 @@ namespace MediaBrowser.Providers.Music
 
         private async Task<ReleaseResult> GetReleaseResult(string albumName, string artistId, CancellationToken cancellationToken)
         {
-            var url = string.Format(MusicBrainzBaseUrl + "/ws/2/release/?query=\"{0}\" AND arid:{1}",
+            var url = string.Format("/ws/2/release/?query=\"{0}\" AND arid:{1}",
                 WebUtility.UrlEncode(albumName),
                 artistId);
 
             var doc = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false);
 
-            return GetReleaseResult(doc);
+            return ReleaseResult.Parse(doc);
         }
 
         private async Task<ReleaseResult> GetReleaseResultByArtistName(string albumName, string artistName, CancellationToken cancellationToken)
         {
-            var url = string.Format(MusicBrainzBaseUrl + "/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"",
+            var url = string.Format("/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"",
                 WebUtility.UrlEncode(albumName),
                 WebUtility.UrlEncode(artistName));
 
             var doc = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false);
 
-            return GetReleaseResult(doc);
+            return ReleaseResult.Parse(doc);
         }
 
-        private ReleaseResult GetReleaseResult(XmlDocument doc)
+        private class ReleaseResult
         {
-            var ns = new XmlNamespaceManager(doc.NameTable);
-            ns.AddNamespace("mb", MusicBrainzBaseUrl + "/ns/mmd-2.0#");
+            public string ReleaseId;
+            public string ReleaseGroupId;
 
-            var result = new ReleaseResult
+            public static ReleaseResult Parse(XmlDocument doc)
             {
+                var docElem = doc.DocumentElement;
 
-            };
+                if (docElem == null)
+                {
+                    return new ReleaseResult();
+                }
 
-            var releaseIdNode = doc.SelectSingleNode("//mb:release-list/mb:release/@id", ns);
+                var releaseList = docElem.FirstChild;
+                if (releaseList == null)
+                {
+                    return new ReleaseResult();
+                }
 
-            if (releaseIdNode != null)
-            {
-                result.ReleaseId = releaseIdNode.Value;
-            }
+                var nodes = releaseList.ChildNodes;
+                string releaseId = null;
+                string releaseGroupId = null;
 
-            var releaseGroupIdNode = doc.SelectSingleNode("//mb:release-list/mb:release/mb:release-group/@id", ns);
+                if (nodes != null)
+                {
+                    foreach (var node in nodes.Cast<XmlNode>())
+                    {
+                        if (string.Equals(node.Name, "release", StringComparison.OrdinalIgnoreCase))
+                        {
+                            releaseId = node.Attributes["id"].Value;
+                            releaseGroupId = GetReleaseGroupIdFromReleaseNode(node);
+                            break;
+                        }
+                    }
+                }
 
-            if (releaseGroupIdNode != null)
-            {
-                result.ReleaseGroupId = releaseGroupIdNode.Value;
+                return new ReleaseResult
+                {
+                    ReleaseId = releaseId,
+                    ReleaseGroupId = releaseGroupId
+                };
             }
 
-            return result;
-        }
+            private static string GetReleaseGroupIdFromReleaseNode(XmlNode node)
+            {
+                var subNodes = node.ChildNodes;
+                if (subNodes != null)
+                {
+                    foreach (var subNode in subNodes.Cast<XmlNode>())
+                    {
+                        if (string.Equals(subNode.Name, "release-group", StringComparison.OrdinalIgnoreCase))
+                        {
+                            return subNode.Attributes["id"].Value;
+                        }
+                    }
+                }
 
-        private class ReleaseResult
-        {
-            public string ReleaseId;
-            public string ReleaseGroupId;
+                return null;
+            }
         }
 
         /// <summary>
@@ -260,15 +289,37 @@ namespace MediaBrowser.Providers.Music
         /// <returns>Task{System.String}.</returns>
         private async Task<string> GetReleaseGroupId(string releaseEntryId, CancellationToken cancellationToken)
         {
-            var url = string.Format(MusicBrainzBaseUrl + "/ws/2/release-group/?query=reid:{0}", releaseEntryId);
+            var url = string.Format("/ws/2/release-group/?query=reid:{0}", releaseEntryId);
 
             var doc = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false);
 
-            var ns = new XmlNamespaceManager(doc.NameTable);
-            ns.AddNamespace("mb", MusicBrainzBaseUrl + "/ns/mmd-2.0#");
-            var node = doc.SelectSingleNode("//mb:release-group-list/mb:release-group/@id", ns);
+            var docElem = doc.DocumentElement;
+
+            if (docElem == null)
+            {
+                return null;
+            }
 
-            return node != null ? node.Value : null;
+            var releaseList = docElem.FirstChild;
+            if (releaseList == null)
+            {
+                return null;
+            }
+
+            var nodes = releaseList.ChildNodes;
+            string releaseGroupId = null;
+
+            if (nodes != null)
+            {
+                foreach (var node in nodes.Cast<XmlNode>())
+                {
+                    if (string.Equals(node.Name, "release-group", StringComparison.OrdinalIgnoreCase))
+                    {
+                        return node.Attributes["id"].Value;
+                    }
+                }
+            }
+            return null;
         }
 
         /// <summary>
@@ -276,6 +327,49 @@ namespace MediaBrowser.Providers.Music
         /// </summary>
         private readonly SemaphoreSlim _musicBrainzResourcePool = new SemaphoreSlim(1, 1);
 
+        private long _lastMbzUrlQueryTicks = 0;
+        private List<MbzUrl> _mbzUrls = null;
+        private MbzUrl _chosenUrl;
+
+        private async Task<MbzUrl> GetMbzUrl()
+        {
+            if (_mbzUrls == null || (DateTime.UtcNow.Ticks - _lastMbzUrlQueryTicks) > TimeSpan.FromHours(12).Ticks)
+            {
+                await RefreshMzbUrls().ConfigureAwait(false);
+
+                var urls = _mbzUrls.ToList();
+                _chosenUrl = urls[new Random().Next(0, urls.Count - 1)];
+            }
+
+            return _chosenUrl;
+        }
+
+        private async Task RefreshMzbUrls()
+        {
+            try
+            {
+                _mbzUrls = new List<MbzUrl>
+                {
+                    new MbzUrl
+                    {
+                        url = MusicBrainzBaseUrl,
+                        throttleMs = 1000
+                    }
+                };
+            }
+            catch
+            {
+                _mbzUrls = new List<MbzUrl>
+                {
+                    new MbzUrl
+                    {
+                        url = MusicBrainzBaseUrl,
+                        throttleMs = 1000
+                    }
+                };
+            }
+        }
+
         /// <summary>
         /// Gets the music brainz response.
         /// </summary>
@@ -285,9 +379,15 @@ namespace MediaBrowser.Providers.Music
         /// <returns>Task{XmlDocument}.</returns>
         internal async Task<XmlDocument> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
         {
-            // MusicBrainz is extremely adamant about limiting to one request per second
+            var urlInfo = await GetMbzUrl().ConfigureAwait(false);
 
-            await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
+            if (urlInfo.throttleMs > 0)
+            {
+                // MusicBrainz is extremely adamant about limiting to one request per second
+                await Task.Delay(urlInfo.throttleMs, cancellationToken).ConfigureAwait(false);
+            }
+
+            url = urlInfo.url.TrimEnd('/') + url;
 
             var doc = new XmlDocument();
 
@@ -319,5 +419,11 @@ namespace MediaBrowser.Providers.Music
         {
             throw new NotImplementedException();
         }
+
+        internal class MbzUrl
+        {
+            public string url { get; set; }
+            public int throttleMs { get; set; }
+        }
     }
 }

+ 3 - 6
MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs

@@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.Music
 
             if (!string.IsNullOrWhiteSpace(musicBrainzId))
             {
-                var url = string.Format(MusicBrainzAlbumProvider.MusicBrainzBaseUrl + "/ws/2/artist/?query=arid:{0}", musicBrainzId);
+                var url = string.Format("/ws/2/artist/?query=arid:{0}", musicBrainzId);
 
                 var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken)
                             .ConfigureAwait(false);
@@ -35,7 +35,7 @@ namespace MediaBrowser.Providers.Music
                 // They seem to throw bad request failures on any term with a slash
                 var nameToSearch = searchInfo.Name.Replace('/', ' ');
 
-                var url = String.Format(MusicBrainzAlbumProvider.MusicBrainzBaseUrl + "/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch));
+                var url = String.Format("/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch));
 
                 var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false);
 
@@ -49,7 +49,7 @@ namespace MediaBrowser.Providers.Music
                 if (HasDiacritics(searchInfo.Name))
                 {
                     // Try again using the search with accent characters url
-                    url = String.Format(MusicBrainzAlbumProvider.MusicBrainzBaseUrl + "/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
+                    url = String.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
 
                     doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false);
 
@@ -62,9 +62,6 @@ namespace MediaBrowser.Providers.Music
 
         private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlDocument doc)
         {
-            //var ns = new XmlNamespaceManager(doc.NameTable);
-            //ns.AddNamespace("mb", "https://musicbrainz.org/ns/mmd-2.0#");
-
             var list = new List<RemoteSearchResult>();
 
             var docElem = doc.DocumentElement;

+ 6 - 1
MediaBrowser.Server.Implementations/Dto/DtoService.cs

@@ -486,10 +486,15 @@ namespace MediaBrowser.Server.Implementations.Dto
 
                     dto.UserData.Played = dto.UserData.PlayedPercentage.HasValue && dto.UserData.PlayedPercentage.Value >= 100;
                 }
-                else
+                else if (item.SourceType == SourceType.Library)
                 {
                     dto.UserData = _userDataRepository.GetUserDataDto(item, user);
                 }
+                else
+                {
+                    var userData = _userDataRepository.GetUserData(user, item);
+                    dto.UserData = GetUserItemDataDto(userData);
+                }
 
                 if (item.SourceType == SourceType.Library)
                 {

+ 26 - 3
MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs

@@ -6,6 +6,8 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using System.Linq;
+using System.Net;
+using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using Emby.XmlTv.Classes;
@@ -53,7 +55,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
                 return path;
             }
 
-            var cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "_" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + ".xml";
+            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 (File.Exists(cacheFile))
             {
@@ -67,13 +69,34 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
                 CancellationToken = cancellationToken,
                 Url = path,
                 Progress = new Progress<Double>(),
-                EnableHttpCompression = false
+                DecompressionMethod = DecompressionMethods.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
 
             }).ConfigureAwait(false);
 
             Directory.CreateDirectory(Path.GetDirectoryName(cacheFile));
-            File.Copy(tempFile, cacheFile, true);
 
+            using (var stream = File.OpenRead(tempFile))
+            {
+                using (var reader = new StreamReader(stream, Encoding.UTF8))
+                {
+                    using (var fileStream = File.OpenWrite(cacheFile))
+                    {
+                        using (var writer = new StreamWriter(fileStream))
+                        {
+                            while (!reader.EndOfStream)
+                            {
+                                writer.WriteLine(reader.ReadLine());
+                            }
+                        }
+                    }
+                }
+            }
+
+            _logger.Debug("Returning xmltv path {0}", cacheFile);
             return cacheFile;
         }
 

+ 7 - 0
MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs

@@ -44,6 +44,13 @@ namespace MediaBrowser.XbmcMetadata.Savers
             }
             else
             {
+                // http://kodi.wiki/view/NFO_files/Movies
+                // movie.nfo will override all and any .nfo files in the same folder as the media files if you use the "Use foldernames for lookups" setting. If you don't, then moviename.nfo is used
+                //if (!item.IsInMixedFolder && item.ItemType == typeof(Movie))
+                //{
+                //    list.Add(Path.Combine(item.ContainingFolderPath, "movie.nfo"));
+                //}
+
                 list.Add(Path.ChangeExtension(item.Path, ".nfo"));
             }