mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-17 02:49:05 -07:00
commit
74b57185f6
@ -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)
|
||||
{
|
||||
|
@ -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>
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
private ReleaseResult GetReleaseResult(XmlDocument doc)
|
||||
{
|
||||
var ns = new XmlNamespaceManager(doc.NameTable);
|
||||
ns.AddNamespace("mb", MusicBrainzBaseUrl + "/ns/mmd-2.0#");
|
||||
|
||||
var result = new ReleaseResult
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
var releaseIdNode = doc.SelectSingleNode("//mb:release-list/mb:release/@id", ns);
|
||||
|
||||
if (releaseIdNode != null)
|
||||
{
|
||||
result.ReleaseId = releaseIdNode.Value;
|
||||
}
|
||||
|
||||
var releaseGroupIdNode = doc.SelectSingleNode("//mb:release-list/mb:release/mb:release-group/@id", ns);
|
||||
|
||||
if (releaseGroupIdNode != null)
|
||||
{
|
||||
result.ReleaseGroupId = releaseGroupIdNode.Value;
|
||||
}
|
||||
|
||||
return result;
|
||||
return ReleaseResult.Parse(doc);
|
||||
}
|
||||
|
||||
private class ReleaseResult
|
||||
{
|
||||
public string ReleaseId;
|
||||
public string ReleaseGroupId;
|
||||
|
||||
public static ReleaseResult Parse(XmlDocument doc)
|
||||
{
|
||||
var docElem = doc.DocumentElement;
|
||||
|
||||
if (docElem == null)
|
||||
{
|
||||
return new ReleaseResult();
|
||||
}
|
||||
|
||||
var releaseList = docElem.FirstChild;
|
||||
if (releaseList == null)
|
||||
{
|
||||
return new ReleaseResult();
|
||||
}
|
||||
|
||||
var nodes = releaseList.ChildNodes;
|
||||
string releaseId = null;
|
||||
string releaseGroupId = null;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ReleaseResult
|
||||
{
|
||||
ReleaseId = releaseId,
|
||||
ReleaseGroupId = releaseGroupId
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return node != null ? node.Value : null;
|
||||
if (docElem == null)
|
||||
{
|
||||
return 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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user