mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-06-03 13:44:22 -04:00
make provider project portabl
This commit is contained in:
parent
7130d8a78f
commit
e12f27d8ed
@ -30,6 +30,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BDInfo", "BDInfo\BDInfo.csp
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Common.Implementations", "MediaBrowser.Common.Implementations\MediaBrowser.Common.Implementations.csproj", "{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Providers", "MediaBrowser.Providers\MediaBrowser.Providers.csproj", "{442B5058-DCAF-4263-BB6A-F21E31120A1B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -97,6 +99,12 @@ Global
|
||||
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU
|
||||
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU
|
||||
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU
|
||||
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -112,5 +120,6 @@ Global
|
||||
{713F42B5-878E-499D-A878-E4C652B1D5E8} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
|
||||
{88AE38DF-19D7-406F-A6A9-09527719A21E} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
|
||||
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
|
||||
{442B5058-DCAF-4263-BB6A-F21E31120A1B} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -13,8 +13,9 @@
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<ProductVersion>10.0.0</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@ -41,13 +42,6 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\SharedVersion.cs">
|
||||
<Link>Properties\SharedVersion.cs</Link>
|
||||
@ -171,7 +165,7 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Target Name="EmitMSBuildWarning" BeforeTargets="Build">
|
||||
<Warning Text="Packages containing MSBuild targets and props files cannot be fully installed in projects targeting multiple frameworks. The MSBuild targets and props files have been ignored." />
|
||||
</Target>
|
||||
</Project>
|
@ -15,6 +15,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Xml;
|
||||
|
||||
namespace MediaBrowser.Providers.Music
|
||||
{
|
||||
@ -26,15 +27,17 @@ namespace MediaBrowser.Providers.Music
|
||||
private readonly IApplicationHost _appHost;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IJsonSerializer _json;
|
||||
private readonly IXmlReaderSettingsFactory _xmlSettings;
|
||||
|
||||
public static string MusicBrainzBaseUrl = "https://www.musicbrainz.org";
|
||||
|
||||
public MusicBrainzAlbumProvider(IHttpClient httpClient, IApplicationHost appHost, ILogger logger, IJsonSerializer json)
|
||||
public MusicBrainzAlbumProvider(IHttpClient httpClient, IApplicationHost appHost, ILogger logger, IJsonSerializer json, IXmlReaderSettingsFactory xmlSettings)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_appHost = appHost;
|
||||
_logger = logger;
|
||||
_json = json;
|
||||
_xmlSettings = xmlSettings;
|
||||
Current = this;
|
||||
}
|
||||
|
||||
@ -71,17 +74,18 @@ namespace MediaBrowser.Providers.Music
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
var doc = await GetMusicBrainzResponse(url, isNameSearch, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return GetResultsFromResponse(doc);
|
||||
using (var reader = await GetMusicBrainzResponse(url, isNameSearch, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
return GetResultsFromResponse(reader);
|
||||
}
|
||||
}
|
||||
|
||||
return new List<RemoteSearchResult>();
|
||||
}
|
||||
|
||||
private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlDocument doc)
|
||||
private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlReader reader)
|
||||
{
|
||||
return ReleaseResult.Parse(doc).Select(i =>
|
||||
return ReleaseResult.Parse(reader).Select(i =>
|
||||
{
|
||||
var result = new RemoteSearchResult
|
||||
{
|
||||
@ -191,9 +195,10 @@ namespace MediaBrowser.Providers.Music
|
||||
WebUtility.UrlEncode(albumName),
|
||||
artistId);
|
||||
|
||||
var doc = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return ReleaseResult.Parse(doc, 1).FirstOrDefault();
|
||||
using (var reader = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
return ReleaseResult.Parse(reader, 1).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<ReleaseResult> GetReleaseResultByArtistName(string albumName, string artistName, CancellationToken cancellationToken)
|
||||
@ -202,9 +207,10 @@ namespace MediaBrowser.Providers.Music
|
||||
WebUtility.UrlEncode(albumName),
|
||||
WebUtility.UrlEncode(artistName));
|
||||
|
||||
var doc = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return ReleaseResult.Parse(doc, 1).FirstOrDefault();
|
||||
using (var reader = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
return ReleaseResult.Parse(reader, 1).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private class ReleaseResult
|
||||
@ -215,108 +221,114 @@ namespace MediaBrowser.Providers.Music
|
||||
public string Overview;
|
||||
public int? Year;
|
||||
|
||||
public static List<ReleaseResult> Parse(XmlDocument doc, int? limit = null)
|
||||
public static List<ReleaseResult> Parse(XmlReader reader, int? limit = null)
|
||||
{
|
||||
var docElem = doc.DocumentElement;
|
||||
var list = new List<ReleaseResult>();
|
||||
reader.MoveToContent();
|
||||
|
||||
if (docElem == null)
|
||||
// Loop through each element
|
||||
while (reader.Read())
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
var releaseList = docElem.FirstChild;
|
||||
if (releaseList == null)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
var nodes = releaseList.ChildNodes;
|
||||
|
||||
if (nodes != null)
|
||||
{
|
||||
foreach (var node in nodes.Cast<XmlNode>())
|
||||
switch (reader.Name)
|
||||
{
|
||||
if (string.Equals(node.Name, "release", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var releaseId = node.Attributes["id"].Value;
|
||||
var releaseGroupId = GetReleaseGroupIdFromReleaseNode(node);
|
||||
|
||||
list.Add(new ReleaseResult
|
||||
case "release-list":
|
||||
{
|
||||
ReleaseId = releaseId,
|
||||
ReleaseGroupId = releaseGroupId,
|
||||
Title = GetValueFromReleaseNode(node, "title"),
|
||||
Overview = GetValueFromReleaseNode(node, "annotation"),
|
||||
Year = GetYearFromReleaseNode(node, "date")
|
||||
});
|
||||
|
||||
if (limit.HasValue && list.Count >= limit.Value)
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
return ParseReleaseList(subReader);
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new List<ReleaseResult>();
|
||||
}
|
||||
|
||||
private static List<ReleaseResult> ParseReleaseList(XmlReader reader)
|
||||
{
|
||||
var list = new List<ReleaseResult>();
|
||||
|
||||
reader.MoveToContent();
|
||||
|
||||
// Loop through each element
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "release":
|
||||
{
|
||||
var releaseId = reader.GetAttribute("id");
|
||||
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
var artist = ParseRelease(subReader, releaseId);
|
||||
list.Add(artist);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static int? GetYearFromReleaseNode(XmlNode node, string name)
|
||||
private static ReleaseResult ParseRelease(XmlReader reader, string releaseId)
|
||||
{
|
||||
var subNodes = node.ChildNodes;
|
||||
if (subNodes != null)
|
||||
var result = new ReleaseResult
|
||||
{
|
||||
foreach (var subNode in subNodes.Cast<XmlNode>())
|
||||
ReleaseId = releaseId
|
||||
};
|
||||
|
||||
reader.MoveToContent();
|
||||
|
||||
// Loop through each element
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
if (string.Equals(subNode.Name, name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
DateTime date;
|
||||
if (DateTime.TryParse(subNode.InnerText, out date))
|
||||
case "title":
|
||||
{
|
||||
return date.Year;
|
||||
result.Title = reader.ReadElementContentAsString();
|
||||
break;
|
||||
}
|
||||
case "date":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
DateTime date;
|
||||
if (DateTime.TryParse(val, out date))
|
||||
{
|
||||
result.Year = date.Year;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "annotation":
|
||||
{
|
||||
result.Overview = reader.ReadElementContentAsString();
|
||||
break;
|
||||
}
|
||||
case "release-group":
|
||||
{
|
||||
result.ReleaseGroupId = reader.GetAttribute("id");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetValueFromReleaseNode(XmlNode node, string name)
|
||||
{
|
||||
var subNodes = node.ChildNodes;
|
||||
if (subNodes != null)
|
||||
{
|
||||
foreach (var subNode in subNodes.Cast<XmlNode>())
|
||||
{
|
||||
if (string.Equals(subNode.Name, name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return subNode.InnerText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,33 +342,54 @@ namespace MediaBrowser.Providers.Music
|
||||
{
|
||||
var url = string.Format("/ws/2/release-group/?query=reid:{0}", releaseEntryId);
|
||||
|
||||
var doc = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var docElem = doc.DocumentElement;
|
||||
|
||||
if (docElem == null)
|
||||
using (var reader = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
reader.MoveToContent();
|
||||
|
||||
var releaseList = docElem.FirstChild;
|
||||
if (releaseList == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var nodes = releaseList.ChildNodes;
|
||||
|
||||
if (nodes != null)
|
||||
{
|
||||
foreach (var node in nodes.Cast<XmlNode>())
|
||||
// Loop through each element
|
||||
while (reader.Read())
|
||||
{
|
||||
if (string.Equals(node.Name, "release-group", StringComparison.OrdinalIgnoreCase))
|
||||
switch (reader.Name)
|
||||
{
|
||||
return node.Attributes["id"].Value;
|
||||
case "release-group-list":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
return GetFirstReleaseGroupId(subReader);
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetFirstReleaseGroupId(XmlReader reader)
|
||||
{
|
||||
reader.MoveToContent();
|
||||
|
||||
// Loop through each element
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "release-group":
|
||||
{
|
||||
return reader.GetAttribute("id");
|
||||
}
|
||||
default:
|
||||
{
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -432,7 +465,7 @@ namespace MediaBrowser.Providers.Music
|
||||
/// <param name="isSearch">if set to <c>true</c> [is search].</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{XmlDocument}.</returns>
|
||||
internal async Task<XmlDocument> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
|
||||
internal async Task<XmlReader> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
|
||||
{
|
||||
var urlInfo = await GetMbzUrl().ConfigureAwait(false);
|
||||
|
||||
@ -444,8 +477,6 @@ namespace MediaBrowser.Providers.Music
|
||||
|
||||
url = urlInfo.url.TrimEnd('/') + url;
|
||||
|
||||
var doc = new XmlDocument();
|
||||
|
||||
var options = new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
@ -458,11 +489,15 @@ namespace MediaBrowser.Providers.Music
|
||||
{
|
||||
using (var oReader = new StreamReader(xml, Encoding.UTF8))
|
||||
{
|
||||
doc.Load(oReader);
|
||||
var settings = _xmlSettings.Create(false);
|
||||
|
||||
settings.CheckCharacters = false;
|
||||
settings.IgnoreProcessingInstructions = true;
|
||||
settings.IgnoreComments = true;
|
||||
|
||||
return XmlReader.Create(oReader, settings);
|
||||
}
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
public int Order
|
||||
|
@ -26,10 +26,11 @@ namespace MediaBrowser.Providers.Music
|
||||
{
|
||||
var url = string.Format("/ws/2/artist/?query=arid:{0}", musicBrainzId);
|
||||
|
||||
var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return GetResultsFromResponse(doc);
|
||||
using (var reader = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken)
|
||||
.ConfigureAwait(false))
|
||||
{
|
||||
return GetResultsFromResponse(reader);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -38,13 +39,14 @@ namespace MediaBrowser.Providers.Music
|
||||
|
||||
var url = String.Format("/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch));
|
||||
|
||||
var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var results = GetResultsFromResponse(doc).ToList();
|
||||
|
||||
if (results.Count > 0)
|
||||
using (var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
return results;
|
||||
var results = GetResultsFromResponse(doc).ToList();
|
||||
|
||||
if (results.Count > 0)
|
||||
{
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
if (HasDiacritics(searchInfo.Name))
|
||||
@ -52,75 +54,123 @@ namespace MediaBrowser.Providers.Music
|
||||
// Try again using the search with accent characters url
|
||||
url = String.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
|
||||
|
||||
doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return GetResultsFromResponse(doc);
|
||||
using (var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
return GetResultsFromResponse(doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new List<RemoteSearchResult>();
|
||||
}
|
||||
|
||||
private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlDocument doc)
|
||||
private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlReader reader)
|
||||
{
|
||||
reader.MoveToContent();
|
||||
|
||||
// Loop through each element
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "artist-list":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
return ParseArtistList(subReader);
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new List<RemoteSearchResult>();
|
||||
}
|
||||
|
||||
private IEnumerable<RemoteSearchResult> ParseArtistList(XmlReader reader)
|
||||
{
|
||||
var list = new List<RemoteSearchResult>();
|
||||
|
||||
var docElem = doc.DocumentElement;
|
||||
reader.MoveToContent();
|
||||
|
||||
if (docElem == null)
|
||||
// Loop through each element
|
||||
while (reader.Read())
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
var artistList = docElem.FirstChild;
|
||||
if (artistList == null)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
var nodes = artistList.ChildNodes;
|
||||
|
||||
if (nodes != null)
|
||||
{
|
||||
foreach (var node in nodes.Cast<XmlNode>())
|
||||
switch (reader.Name)
|
||||
{
|
||||
if (node.Attributes != null)
|
||||
{
|
||||
string name = null;
|
||||
string overview = null;
|
||||
string mbzId = node.Attributes["id"].Value;
|
||||
|
||||
foreach (var child in node.ChildNodes.Cast<XmlNode>())
|
||||
case "artist":
|
||||
{
|
||||
if (string.Equals(child.Name, "name", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
name = child.InnerText;
|
||||
}
|
||||
if (string.Equals(child.Name, "annotation", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
overview = child.InnerText;
|
||||
}
|
||||
}
|
||||
var mbzId = reader.GetAttribute("id");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(mbzId) && !string.IsNullOrWhiteSpace(name))
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
var artist = ParseArtist(subReader, mbzId);
|
||||
list.Add(artist);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
var result = new RemoteSearchResult
|
||||
{
|
||||
Name = name,
|
||||
Overview = overview
|
||||
};
|
||||
|
||||
result.SetProviderId(MetadataProviders.MusicBrainzArtist, mbzId);
|
||||
|
||||
list.Add(result);
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private RemoteSearchResult ParseArtist(XmlReader reader, string artistId)
|
||||
{
|
||||
var result = new RemoteSearchResult();
|
||||
|
||||
reader.MoveToContent();
|
||||
|
||||
// Loop through each element
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "name":
|
||||
{
|
||||
result.Name = reader.ReadElementContentAsString();
|
||||
break;
|
||||
}
|
||||
//case "sort-name":
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
//case "tag-list":
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
case "annotation":
|
||||
{
|
||||
result.Overview = reader.ReadElementContentAsString();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.SetProviderId(MetadataProviders.MusicBrainzArtist, artistId);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(artistId) || string.IsNullOrWhiteSpace(result.Name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo id, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = new MetadataResult<MusicArtist>
|
||||
|
@ -103,7 +103,7 @@ namespace MediaBrowser.Providers.TV
|
||||
{
|
||||
// No biggie. Don't blow up
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
catch (IOException)
|
||||
{
|
||||
// No biggie. Don't blow up
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ namespace MediaBrowser.Providers.TV
|
||||
{
|
||||
// No biggie. Don't blow up
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
catch (IOException)
|
||||
{
|
||||
// No biggie. Don't blow up
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.Xml;
|
||||
|
||||
namespace MediaBrowser.Providers.TV
|
||||
{
|
||||
@ -31,14 +32,16 @@ namespace MediaBrowser.Providers.TV
|
||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||
private static readonly SemaphoreSlim _resourceLock = new SemaphoreSlim(1, 1);
|
||||
public static bool IsRunning = false;
|
||||
private readonly IXmlReaderSettingsFactory _xmlSettings;
|
||||
|
||||
public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, IFileSystem fileSystem)
|
||||
public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, IFileSystem fileSystem, IXmlReaderSettingsFactory xmlSettings)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_libraryManager = libraryManager;
|
||||
_localization = localization;
|
||||
_fileSystem = fileSystem;
|
||||
_xmlSettings = xmlSettings;
|
||||
}
|
||||
|
||||
public async Task Run(List<IGrouping<string, Series>> series, bool addNewItems, CancellationToken cancellationToken)
|
||||
@ -495,56 +498,59 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
DateTime? airDate = null;
|
||||
|
||||
// It appears the best way to filter out invalid entries is to only include those with valid air dates
|
||||
using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
|
||||
using (var fileStream = _fileSystem.GetFileStream(xmlPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
|
||||
{
|
||||
// Use XmlReader for best performance
|
||||
using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
|
||||
// It appears the best way to filter out invalid entries is to only include those with valid air dates
|
||||
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
|
||||
{
|
||||
CheckCharacters = false,
|
||||
IgnoreProcessingInstructions = true,
|
||||
IgnoreComments = true,
|
||||
ValidationType = ValidationType.None
|
||||
}))
|
||||
{
|
||||
reader.MoveToContent();
|
||||
var settings = _xmlSettings.Create(false);
|
||||
|
||||
// Loop through each element
|
||||
while (reader.Read())
|
||||
settings.CheckCharacters = false;
|
||||
settings.IgnoreProcessingInstructions = true;
|
||||
settings.IgnoreComments = true;
|
||||
|
||||
// Use XmlReader for best performance
|
||||
using (var reader = XmlReader.Create(streamReader, settings))
|
||||
{
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
reader.MoveToContent();
|
||||
|
||||
// Loop through each element
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.Name)
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
case "EpisodeName":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
if (string.IsNullOrWhiteSpace(val))
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "EpisodeName":
|
||||
{
|
||||
// Not valid, ignore these
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "FirstAired":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
DateTime date;
|
||||
if (DateTime.TryParse(val, out date))
|
||||
var val = reader.ReadElementContentAsString();
|
||||
if (string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
airDate = date.ToUniversalTime();
|
||||
// Not valid, ignore these
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "FirstAired":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
DateTime date;
|
||||
if (DateTime.TryParse(val, out date))
|
||||
{
|
||||
airDate = date.ToUniversalTime();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.IO;
|
||||
|
||||
namespace MediaBrowser.Providers.TV
|
||||
{
|
||||
@ -20,11 +21,13 @@ namespace MediaBrowser.Providers.TV
|
||||
{
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
public MovieDbSeriesImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient)
|
||||
public MovieDbSeriesImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem)
|
||||
{
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_httpClient = httpClient;
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
public string Name
|
||||
@ -166,7 +169,7 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
var fileInfo = new FileInfo(path);
|
||||
var fileInfo = _fileSystem.GetFileInfo(path);
|
||||
|
||||
if (fileInfo.Exists)
|
||||
{
|
||||
|
@ -18,6 +18,7 @@ using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.Xml;
|
||||
|
||||
namespace MediaBrowser.Providers.TV
|
||||
{
|
||||
@ -50,6 +51,7 @@ namespace MediaBrowser.Providers.TV
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IXmlReaderSettingsFactory _xmlSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TvdbPrescanTask"/> class.
|
||||
@ -57,13 +59,14 @@ namespace MediaBrowser.Providers.TV
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="httpClient">The HTTP client.</param>
|
||||
/// <param name="config">The config.</param>
|
||||
public TvdbPrescanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IFileSystem fileSystem, ILibraryManager libraryManager)
|
||||
public TvdbPrescanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IFileSystem fileSystem, ILibraryManager libraryManager, IXmlReaderSettingsFactory xmlSettings)
|
||||
{
|
||||
_logger = logger;
|
||||
_httpClient = httpClient;
|
||||
_config = config;
|
||||
_fileSystem = fileSystem;
|
||||
_libraryManager = libraryManager;
|
||||
_xmlSettings = xmlSettings;
|
||||
}
|
||||
|
||||
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||
@ -103,7 +106,7 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
string newUpdateTime;
|
||||
|
||||
var existingDirectories = Directory.EnumerateDirectories(path)
|
||||
var existingDirectories = _fileSystem.GetDirectoryPaths(path)
|
||||
.Select(Path.GetFileName)
|
||||
.ToList();
|
||||
|
||||
@ -180,13 +183,11 @@ namespace MediaBrowser.Providers.TV
|
||||
/// <returns>System.String.</returns>
|
||||
private string GetUpdateTime(Stream response)
|
||||
{
|
||||
var settings = new XmlReaderSettings
|
||||
{
|
||||
CheckCharacters = false,
|
||||
IgnoreProcessingInstructions = true,
|
||||
IgnoreComments = true,
|
||||
ValidationType = ValidationType.None
|
||||
};
|
||||
var settings = _xmlSettings.Create(false);
|
||||
|
||||
settings.CheckCharacters = false;
|
||||
settings.IgnoreProcessingInstructions = true;
|
||||
settings.IgnoreComments = true;
|
||||
|
||||
using (var streamReader = new StreamReader(response, Encoding.UTF8))
|
||||
{
|
||||
@ -253,13 +254,11 @@ namespace MediaBrowser.Providers.TV
|
||||
string updateTime = null;
|
||||
var idList = new List<string>();
|
||||
|
||||
var settings = new XmlReaderSettings
|
||||
{
|
||||
CheckCharacters = false,
|
||||
IgnoreProcessingInstructions = true,
|
||||
IgnoreComments = true,
|
||||
ValidationType = ValidationType.None
|
||||
};
|
||||
var settings = _xmlSettings.Create(false);
|
||||
|
||||
settings.CheckCharacters = false;
|
||||
settings.IgnoreProcessingInstructions = true;
|
||||
settings.IgnoreComments = true;
|
||||
|
||||
using (var streamReader = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
|
17
MediaBrowser.Providers/project.json
Normal file
17
MediaBrowser.Providers/project.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"frameworks":{
|
||||
"netstandard1.6":{
|
||||
"dependencies":{
|
||||
"NETStandard.Library":"1.6.0",
|
||||
}
|
||||
},
|
||||
".NETPortable,Version=v4.5,Profile=Profile7":{
|
||||
"buildOptions": {
|
||||
"define": [ ]
|
||||
},
|
||||
"frameworkAssemblies":{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3965
MediaBrowser.Providers/project.lock.json
Normal file
3965
MediaBrowser.Providers/project.lock.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@ using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using MediaBrowser.Model.Xml;
|
||||
using MediaBrowser.Providers.TV;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.TV
|
||||
@ -33,14 +34,16 @@ namespace MediaBrowser.Server.Implementations.TV
|
||||
private readonly ILogger _logger;
|
||||
private readonly ILocalizationManager _localization;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IXmlReaderSettingsFactory _xmlSettings;
|
||||
|
||||
public SeriesPostScanTask(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, ILocalizationManager localization, IFileSystem fileSystem)
|
||||
public SeriesPostScanTask(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, ILocalizationManager localization, IFileSystem fileSystem, IXmlReaderSettingsFactory xmlSettings)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_localization = localization;
|
||||
_fileSystem = fileSystem;
|
||||
_xmlSettings = xmlSettings;
|
||||
}
|
||||
|
||||
public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
@ -60,7 +63,7 @@ namespace MediaBrowser.Server.Implementations.TV
|
||||
|
||||
var seriesGroups = FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList();
|
||||
|
||||
return new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem).Run(seriesGroups, true, cancellationToken);
|
||||
return new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem, _xmlSettings).Run(seriesGroups, true, cancellationToken);
|
||||
}
|
||||
|
||||
internal static IEnumerable<IGrouping<string, Series>> FindSeriesGroups(List<Series> seriesList)
|
||||
@ -128,8 +131,9 @@ namespace MediaBrowser.Server.Implementations.TV
|
||||
private readonly object _libraryChangedSyncLock = new object();
|
||||
private const int LibraryUpdateDuration = 180000;
|
||||
private readonly ITaskManager _taskManager;
|
||||
private readonly IXmlReaderSettingsFactory _xmlSettings;
|
||||
|
||||
public CleanMissingEpisodesEntryPoint(ILibraryManager libraryManager, IServerConfigurationManager config, ILogger logger, ILocalizationManager localization, IFileSystem fileSystem, ITaskManager taskManager)
|
||||
public CleanMissingEpisodesEntryPoint(ILibraryManager libraryManager, IServerConfigurationManager config, ILogger logger, ILocalizationManager localization, IFileSystem fileSystem, ITaskManager taskManager, IXmlReaderSettingsFactory xmlSettings)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_config = config;
|
||||
@ -137,6 +141,7 @@ namespace MediaBrowser.Server.Implementations.TV
|
||||
_localization = localization;
|
||||
_fileSystem = fileSystem;
|
||||
_taskManager = taskManager;
|
||||
_xmlSettings = xmlSettings;
|
||||
}
|
||||
|
||||
private Timer LibraryUpdateTimer { get; set; }
|
||||
@ -190,7 +195,7 @@ namespace MediaBrowser.Server.Implementations.TV
|
||||
|
||||
var seriesGroups = SeriesPostScanTask.FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList();
|
||||
|
||||
await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem)
|
||||
await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem, _xmlSettings)
|
||||
.Run(seriesGroups, false, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -21,6 +21,7 @@
|
||||
<ProjectReference Include="..\..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
|
||||
<ProjectReference Include="..\..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
|
||||
<ProjectReference Include="..\..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
|
||||
<ProjectReference Include="..\..\MediaBrowser.Providers\MediaBrowser.Providers.csproj" />
|
||||
<ProjectReference Include="..\..\MediaBrowser.WebDashboard\MediaBrowser.WebDashboard.csproj" />
|
||||
<ProjectReference Include="..\..\MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj" />
|
||||
</ItemGroup>
|
||||
|
@ -88,6 +88,23 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"MediaBrowser.Providers/1.0.0": {
|
||||
"type": "project",
|
||||
"framework": ".NETPortable,Version=v4.5,Profile=Profile7",
|
||||
"compile": {
|
||||
"bin/Debug/MediaBrowser.Providers.dll": {}
|
||||
},
|
||||
"runtime": {
|
||||
"bin/Debug/MediaBrowser.Providers.dll": {}
|
||||
},
|
||||
"contentFiles": {
|
||||
"bin/Debug/MediaBrowser.Providers.pdb": {
|
||||
"buildAction": "None",
|
||||
"codeLanguage": "any",
|
||||
"copyToOutput": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"MediaBrowser.WebDashboard/1.0.0": {
|
||||
"type": "project",
|
||||
"framework": ".NETPortable,Version=v4.5,Profile=Profile7",
|
||||
|
@ -30,6 +30,9 @@
|
||||
"MediaBrowser.Model": {
|
||||
"target": "project"
|
||||
},
|
||||
"MediaBrowser.Providers": {
|
||||
"target": "project"
|
||||
},
|
||||
"MediaBrowser.WebDashboard": {
|
||||
"target": "project"
|
||||
},
|
||||
|
@ -2175,6 +2175,17 @@
|
||||
"NETStandard.Library": "1.6.0"
|
||||
}
|
||||
},
|
||||
"MediaBrowser.Providers/1.0.0": {
|
||||
"type": "project",
|
||||
"framework": ".NETStandard,Version=v1.6",
|
||||
"dependencies": {
|
||||
"DvdLib": "1.0.0",
|
||||
"MediaBrowser.Common": "1.0.0",
|
||||
"MediaBrowser.Controller": "1.0.0",
|
||||
"MediaBrowser.Model": "1.0.0",
|
||||
"NETStandard.Library": "1.6.0"
|
||||
}
|
||||
},
|
||||
"MediaBrowser.WebDashboard/1.0.0": {
|
||||
"type": "project",
|
||||
"framework": ".NETStandard,Version=v1.6",
|
||||
@ -6953,6 +6964,11 @@
|
||||
"path": "../../MediaBrowser.Model/project.json",
|
||||
"msbuildProject": "../../MediaBrowser.Model/MediaBrowser.Model.csproj"
|
||||
},
|
||||
"MediaBrowser.Providers/1.0.0": {
|
||||
"type": "project",
|
||||
"path": "../../MediaBrowser.Providers/project.json",
|
||||
"msbuildProject": "../../MediaBrowser.Providers/MediaBrowser.Providers.csproj"
|
||||
},
|
||||
"MediaBrowser.WebDashboard/1.0.0": {
|
||||
"type": "project",
|
||||
"path": "../../MediaBrowser.WebDashboard/project.json",
|
||||
@ -6974,6 +6990,7 @@
|
||||
"MediaBrowser.Common",
|
||||
"MediaBrowser.Controller",
|
||||
"MediaBrowser.Model",
|
||||
"MediaBrowser.Providers",
|
||||
"MediaBrowser.WebDashboard",
|
||||
"MediaBrowser.XbmcMetadata"
|
||||
]
|
||||
|
Loading…
x
Reference in New Issue
Block a user