mirror of https://github.com/jellyfin/jellyfin.git
continue reworking provider project
This commit is contained in:
parent
823e558ade
commit
872aec9352
|
@ -98,18 +98,6 @@ namespace MediaBrowser.Controller.Library
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this instance is hidden.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
|
|
||||||
public bool IsHidden
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return FileInfo.IsHidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this instance is vf.
|
/// Gets a value indicating whether this instance is vf.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -52,5 +52,7 @@ namespace MediaBrowser.Model.Globalization
|
||||||
IEnumerable<LocalizatonOption> GetLocalizationOptions();
|
IEnumerable<LocalizatonOption> GetLocalizationOptions();
|
||||||
|
|
||||||
string RemoveDiacritics(string text);
|
string RemoveDiacritics(string text);
|
||||||
|
|
||||||
|
string NormalizeFormKD(string text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -863,8 +863,8 @@ namespace MediaBrowser.Providers.Manager
|
||||||
private readonly ConcurrentQueue<Tuple<Guid, MetadataRefreshOptions>> _refreshQueue =
|
private readonly ConcurrentQueue<Tuple<Guid, MetadataRefreshOptions>> _refreshQueue =
|
||||||
new ConcurrentQueue<Tuple<Guid, MetadataRefreshOptions>>();
|
new ConcurrentQueue<Tuple<Guid, MetadataRefreshOptions>>();
|
||||||
|
|
||||||
private readonly object _refreshTimerLock = new object();
|
private readonly object _refreshQueueLock = new object();
|
||||||
private Timer _refreshTimer;
|
private bool _isProcessingRefreshQueue;
|
||||||
|
|
||||||
public void QueueRefresh(Guid id, MetadataRefreshOptions options)
|
public void QueueRefresh(Guid id, MetadataRefreshOptions options)
|
||||||
{
|
{
|
||||||
|
@ -874,38 +874,18 @@ namespace MediaBrowser.Providers.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
_refreshQueue.Enqueue(new Tuple<Guid, MetadataRefreshOptions>(id, options));
|
_refreshQueue.Enqueue(new Tuple<Guid, MetadataRefreshOptions>(id, options));
|
||||||
StartRefreshTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StartRefreshTimer()
|
lock (_refreshQueueLock)
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
{
|
{
|
||||||
return;
|
if (!_isProcessingRefreshQueue)
|
||||||
}
|
|
||||||
|
|
||||||
lock (_refreshTimerLock)
|
|
||||||
{
|
|
||||||
if (_refreshTimer == null)
|
|
||||||
{
|
{
|
||||||
_refreshTimer = new Timer(RefreshTimerCallback, null, 100, Timeout.Infinite);
|
_isProcessingRefreshQueue = true;
|
||||||
|
Task.Run(() => StartProcessingRefreshQueue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopRefreshTimer()
|
private async Task StartProcessingRefreshQueue()
|
||||||
{
|
|
||||||
lock (_refreshTimerLock)
|
|
||||||
{
|
|
||||||
if (_refreshTimer != null)
|
|
||||||
{
|
|
||||||
_refreshTimer.Dispose();
|
|
||||||
_refreshTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void RefreshTimerCallback(object state)
|
|
||||||
{
|
{
|
||||||
Tuple<Guid, MetadataRefreshOptions> refreshItem;
|
Tuple<Guid, MetadataRefreshOptions> refreshItem;
|
||||||
var libraryManager = _libraryManagerFactory();
|
var libraryManager = _libraryManagerFactory();
|
||||||
|
@ -939,7 +919,10 @@ namespace MediaBrowser.Providers.Manager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StopRefreshTimer();
|
lock (_refreshQueueLock)
|
||||||
|
{
|
||||||
|
_isProcessingRefreshQueue = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RefreshItem(BaseItem item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
private async Task RefreshItem(BaseItem item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
||||||
|
@ -1018,7 +1001,6 @@ namespace MediaBrowser.Providers.Manager
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
StopRefreshTimer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -131,7 +131,6 @@
|
||||||
<Compile Include="TV\FanArt\FanArtSeasonProvider.cs" />
|
<Compile Include="TV\FanArt\FanArtSeasonProvider.cs" />
|
||||||
<Compile Include="TV\FanArt\FanartSeriesProvider.cs" />
|
<Compile Include="TV\FanArt\FanartSeriesProvider.cs" />
|
||||||
<Compile Include="TV\MissingEpisodeProvider.cs" />
|
<Compile Include="TV\MissingEpisodeProvider.cs" />
|
||||||
<Compile Include="TV\SeriesPostScanTask.cs" />
|
|
||||||
<Compile Include="TV\TheMovieDb\MovieDbProviderBase.cs" />
|
<Compile Include="TV\TheMovieDb\MovieDbProviderBase.cs" />
|
||||||
<Compile Include="TV\TheMovieDb\MovieDbEpisodeImageProvider.cs" />
|
<Compile Include="TV\TheMovieDb\MovieDbEpisodeImageProvider.cs" />
|
||||||
<Compile Include="TV\TheMovieDb\MovieDbSeasonProvider.cs" />
|
<Compile Include="TV\TheMovieDb\MovieDbSeasonProvider.cs" />
|
||||||
|
|
|
@ -134,23 +134,6 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
//var idString = item.Id.ToString("N");
|
|
||||||
//var cachePath = Path.Combine(_appPaths.CachePath,
|
|
||||||
// "ffprobe-video",
|
|
||||||
// idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//return _json.DeserializeFromFile<Model.MediaInfo.MediaInfo>(cachePath);
|
|
||||||
}
|
|
||||||
catch (FileNotFoundException)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (DirectoryNotFoundException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
var protocol = item.LocationType == LocationType.Remote
|
var protocol = item.LocationType == LocationType.Remote
|
||||||
? MediaProtocol.Http
|
? MediaProtocol.Http
|
||||||
: MediaProtocol.File;
|
: MediaProtocol.File;
|
||||||
|
@ -655,7 +638,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
/// <returns>System.Nullable{IsoType}.</returns>
|
/// <returns>System.Nullable{IsoType}.</returns>
|
||||||
private IsoType? DetermineIsoType(IIsoMount isoMount)
|
private IsoType? DetermineIsoType(IIsoMount isoMount)
|
||||||
{
|
{
|
||||||
var fileSystemEntries = Directory.EnumerateFileSystemEntries(isoMount.MountedPath).Select(Path.GetFileName).ToList();
|
var fileSystemEntries = _fileSystem.GetFileSystemEntryPaths(isoMount.MountedPath).Select(Path.GetFileName).ToList();
|
||||||
|
|
||||||
if (fileSystemEntries.Contains("video_ts", StringComparer.OrdinalIgnoreCase) ||
|
if (fileSystemEntries.Contains("video_ts", StringComparer.OrdinalIgnoreCase) ||
|
||||||
fileSystemEntries.Contains("VIDEO_TS.IFO", StringComparer.OrdinalIgnoreCase))
|
fileSystemEntries.Contains("VIDEO_TS.IFO", StringComparer.OrdinalIgnoreCase))
|
||||||
|
|
|
@ -12,6 +12,7 @@ using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using MediaBrowser.Controller.Extensions;
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.Music
|
namespace MediaBrowser.Providers.Music
|
||||||
{
|
{
|
||||||
|
@ -159,21 +160,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
/// <returns><c>true</c> if the specified text has diacritics; otherwise, <c>false</c>.</returns>
|
/// <returns><c>true</c> if the specified text has diacritics; otherwise, <c>false</c>.</returns>
|
||||||
private bool HasDiacritics(string text)
|
private bool HasDiacritics(string text)
|
||||||
{
|
{
|
||||||
return !String.Equals(text, RemoveDiacritics(text), StringComparison.Ordinal);
|
return !String.Equals(text, text.RemoveDiacritics(), StringComparison.Ordinal);
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the diacritics.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The text.</param>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
private string RemoveDiacritics(string text)
|
|
||||||
{
|
|
||||||
return String.Concat(
|
|
||||||
text.Normalize(NormalizationForm.FormD)
|
|
||||||
.Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) !=
|
|
||||||
UnicodeCategory.NonSpacingMark)
|
|
||||||
).Normalize(NormalizationForm.FormC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -20,7 +20,7 @@ using MediaBrowser.Model.Globalization;
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.TV
|
namespace MediaBrowser.Providers.TV
|
||||||
{
|
{
|
||||||
class MissingEpisodeProvider
|
public class MissingEpisodeProvider
|
||||||
{
|
{
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
@ -56,7 +56,7 @@ namespace MediaBrowser.Providers.TV
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
//_logger.Warn("Series files missing for series id {0}", seriesGroup.Key);
|
//_logger.Warn("Series files missing for series id {0}", seriesGroup.Key);
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,8 @@ namespace MediaBrowser.Providers.TV
|
||||||
|
|
||||||
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
|
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
|
||||||
|
|
||||||
var episodeFiles = Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.TopDirectoryOnly)
|
var episodeFiles = _fileSystem.GetFilePaths(seriesDataPath)
|
||||||
|
.Where(i => string.Equals(Path.GetExtension(i), ".xml", StringComparison.OrdinalIgnoreCase))
|
||||||
.Select(Path.GetFileNameWithoutExtension)
|
.Select(Path.GetFileNameWithoutExtension)
|
||||||
.Where(i => i.StartsWith("episode-", StringComparison.OrdinalIgnoreCase))
|
.Where(i => i.StartsWith("episode-", StringComparison.OrdinalIgnoreCase))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -19,6 +19,7 @@ using System.Xml;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Controller.IO;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
|
using MediaBrowser.Model.Xml;
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.TV
|
namespace MediaBrowser.Providers.TV
|
||||||
{
|
{
|
||||||
|
@ -29,12 +30,14 @@ namespace MediaBrowser.Providers.TV
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
private readonly IXmlReaderSettingsFactory _xmlSettings;
|
||||||
|
|
||||||
public TvdbSeasonImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
|
public TvdbSeasonImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IXmlReaderSettingsFactory xmlSettings)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
|
_xmlSettings = xmlSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
|
@ -80,13 +83,13 @@ namespace MediaBrowser.Providers.TV
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return GetImages(path, item.GetPreferredMetadataLanguage(), seasonNumber, cancellationToken);
|
return GetImages(path, item.GetPreferredMetadataLanguage(), seasonNumber, _xmlSettings, _fileSystem, cancellationToken);
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException)
|
catch (FileNotFoundException)
|
||||||
{
|
{
|
||||||
// No tvdb data yet. Don't blow up
|
// No tvdb data yet. Don't blow up
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
// No tvdb data yet. Don't blow up
|
// No tvdb data yet. Don't blow up
|
||||||
}
|
}
|
||||||
|
@ -105,45 +108,46 @@ namespace MediaBrowser.Providers.TV
|
||||||
return seasonNumber;
|
return seasonNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static IEnumerable<RemoteImageInfo> GetImages(string xmlPath, string preferredLanguage, int seasonNumber, CancellationToken cancellationToken)
|
internal static IEnumerable<RemoteImageInfo> GetImages(string xmlPath, string preferredLanguage, int seasonNumber, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var settings = new XmlReaderSettings
|
var settings = xmlReaderSettingsFactory.Create(false);
|
||||||
{
|
|
||||||
CheckCharacters = false,
|
settings.CheckCharacters = false;
|
||||||
IgnoreProcessingInstructions = true,
|
settings.IgnoreProcessingInstructions = true;
|
||||||
IgnoreComments = true,
|
settings.IgnoreComments = true;
|
||||||
ValidationType = ValidationType.None
|
|
||||||
};
|
|
||||||
|
|
||||||
var list = new List<RemoteImageInfo>();
|
var list = new List<RemoteImageInfo>();
|
||||||
|
|
||||||
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 streamReader = new StreamReader(fileStream, Encoding.UTF8))
|
||||||
using (var reader = XmlReader.Create(streamReader, settings))
|
|
||||||
{
|
{
|
||||||
reader.MoveToContent();
|
// Use XmlReader for best performance
|
||||||
|
using (var reader = XmlReader.Create(streamReader, settings))
|
||||||
// Loop through each element
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
reader.MoveToContent();
|
||||||
|
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
// Loop through each element
|
||||||
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
switch (reader.Name)
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
case "Banner":
|
switch (reader.Name)
|
||||||
{
|
{
|
||||||
using (var subtree = reader.ReadSubtree())
|
case "Banner":
|
||||||
{
|
{
|
||||||
AddImage(subtree, list, seasonNumber);
|
using (var subtree = reader.ReadSubtree())
|
||||||
|
{
|
||||||
|
AddImage(subtree, list, seasonNumber);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
reader.Skip();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
reader.Skip();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ using System.Xml;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Controller.IO;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
|
using MediaBrowser.Model.Xml;
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.TV
|
namespace MediaBrowser.Providers.TV
|
||||||
{
|
{
|
||||||
|
@ -28,12 +29,14 @@ namespace MediaBrowser.Providers.TV
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
private readonly IXmlReaderSettingsFactory _xmlReaderSettingsFactory;
|
||||||
|
|
||||||
public TvdbSeriesImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
|
public TvdbSeriesImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
|
_xmlReaderSettingsFactory = xmlReaderSettingsFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
|
@ -75,7 +78,7 @@ namespace MediaBrowser.Providers.TV
|
||||||
{
|
{
|
||||||
var seriesOffset = TvdbSeriesProvider.GetSeriesOffset(item.ProviderIds);
|
var seriesOffset = TvdbSeriesProvider.GetSeriesOffset(item.ProviderIds);
|
||||||
if (seriesOffset != null && seriesOffset.Value != 0)
|
if (seriesOffset != null && seriesOffset.Value != 0)
|
||||||
return TvdbSeasonImageProvider.GetImages(path, language, seriesOffset.Value + 1, cancellationToken);
|
return TvdbSeasonImageProvider.GetImages(path, language, seriesOffset.Value + 1, _xmlReaderSettingsFactory, _fileSystem, cancellationToken);
|
||||||
|
|
||||||
return GetImages(path, language, cancellationToken);
|
return GetImages(path, language, cancellationToken);
|
||||||
}
|
}
|
||||||
|
@ -83,7 +86,7 @@ namespace MediaBrowser.Providers.TV
|
||||||
{
|
{
|
||||||
// No tvdb data yet. Don't blow up
|
// No tvdb data yet. Don't blow up
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
// No tvdb data yet. Don't blow up
|
// No tvdb data yet. Don't blow up
|
||||||
}
|
}
|
||||||
|
@ -94,43 +97,44 @@ namespace MediaBrowser.Providers.TV
|
||||||
|
|
||||||
private IEnumerable<RemoteImageInfo> GetImages(string xmlPath, string preferredLanguage, CancellationToken cancellationToken)
|
private IEnumerable<RemoteImageInfo> GetImages(string xmlPath, string preferredLanguage, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var settings = new XmlReaderSettings
|
var settings = _xmlReaderSettingsFactory.Create(false);
|
||||||
{
|
|
||||||
CheckCharacters = false,
|
settings.CheckCharacters = false;
|
||||||
IgnoreProcessingInstructions = true,
|
settings.IgnoreProcessingInstructions = true;
|
||||||
IgnoreComments = true,
|
settings.IgnoreComments = true;
|
||||||
ValidationType = ValidationType.None
|
|
||||||
};
|
|
||||||
|
|
||||||
var list = new List<RemoteImageInfo>();
|
var list = new List<RemoteImageInfo>();
|
||||||
|
|
||||||
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 streamReader = new StreamReader(fileStream, Encoding.UTF8))
|
||||||
using (var reader = XmlReader.Create(streamReader, settings))
|
|
||||||
{
|
{
|
||||||
reader.MoveToContent();
|
// Use XmlReader for best performance
|
||||||
|
using (var reader = XmlReader.Create(streamReader, settings))
|
||||||
// Loop through each element
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
reader.MoveToContent();
|
||||||
|
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
// Loop through each element
|
||||||
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
switch (reader.Name)
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
case "Banner":
|
switch (reader.Name)
|
||||||
{
|
{
|
||||||
using (var subtree = reader.ReadSubtree())
|
case "Banner":
|
||||||
{
|
{
|
||||||
AddImage(subtree, list);
|
using (var subtree = reader.ReadSubtree())
|
||||||
|
{
|
||||||
|
AddImage(subtree, list);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
reader.Skip();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
reader.Skip();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,8 @@ using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Model.Xml;
|
||||||
using MediaBrowser.Controller.IO;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.TV
|
namespace MediaBrowser.Providers.TV
|
||||||
{
|
{
|
||||||
|
@ -41,8 +40,10 @@ namespace MediaBrowser.Providers.TV
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IMemoryStreamProvider _memoryStreamProvider;
|
private readonly IMemoryStreamProvider _memoryStreamProvider;
|
||||||
|
private readonly IXmlReaderSettingsFactory _xmlSettings;
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
|
||||||
public TvdbSeriesProvider(IZipClient zipClient, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config, ILogger logger, ILibraryManager libraryManager, IMemoryStreamProvider memoryStreamProvider)
|
public TvdbSeriesProvider(IZipClient zipClient, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config, ILogger logger, ILibraryManager libraryManager, IMemoryStreamProvider memoryStreamProvider, IXmlReaderSettingsFactory xmlSettings, ILocalizationManager localizationManager)
|
||||||
{
|
{
|
||||||
_zipClient = zipClient;
|
_zipClient = zipClient;
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
|
@ -51,6 +52,8 @@ namespace MediaBrowser.Providers.TV
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_memoryStreamProvider = memoryStreamProvider;
|
_memoryStreamProvider = memoryStreamProvider;
|
||||||
|
_xmlSettings = xmlSettings;
|
||||||
|
_localizationManager = localizationManager;
|
||||||
Current = this;
|
Current = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +255,8 @@ namespace MediaBrowser.Providers.TV
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanitize all files, except for extracted episode files
|
// Sanitize all files, except for extracted episode files
|
||||||
foreach (var file in Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.AllDirectories).ToList()
|
foreach (var file in _fileSystem.GetFilePaths(seriesDataPath, true).ToList()
|
||||||
|
.Where(i => string.Equals(Path.GetExtension(i), ".xml", StringComparison.OrdinalIgnoreCase))
|
||||||
.Where(i => !Path.GetFileName(i).StartsWith("episode-", StringComparison.OrdinalIgnoreCase)))
|
.Where(i => !Path.GetFileName(i).StartsWith("episode-", StringComparison.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
await SanitizeXmlFile(file).ConfigureAwait(false);
|
await SanitizeXmlFile(file).ConfigureAwait(false);
|
||||||
|
@ -281,20 +285,78 @@ namespace MediaBrowser.Providers.TV
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
var doc = new XmlDocument();
|
return FindSeriesId(result);
|
||||||
doc.Load(result);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (doc.HasChildNodes)
|
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))
|
||||||
{
|
{
|
||||||
var node = doc.SelectSingleNode("//Series/seriesid");
|
reader.MoveToContent();
|
||||||
|
|
||||||
if (node != null)
|
// Loop through each element
|
||||||
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
var idResult = node.InnerText;
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
|
{
|
||||||
|
switch (reader.Name)
|
||||||
|
{
|
||||||
|
case "Series":
|
||||||
|
{
|
||||||
|
using (var subtree = reader.ReadSubtree())
|
||||||
|
{
|
||||||
|
return FindSeriesId(subtree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_logger.Info("Tvdb GetSeriesByRemoteId produced id of {0}", idResult ?? string.Empty);
|
default:
|
||||||
|
reader.Skip();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return idResult;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FindSeriesId(XmlReader reader)
|
||||||
|
{
|
||||||
|
reader.MoveToContent();
|
||||||
|
|
||||||
|
// Loop through each element
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,11 +464,11 @@ namespace MediaBrowser.Providers.TV
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (FileNotFoundException)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -570,10 +632,10 @@ namespace MediaBrowser.Providers.TV
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The name.</param>
|
/// <param name="name">The name.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
internal static string GetComparableName(string name)
|
private string GetComparableName(string name)
|
||||||
{
|
{
|
||||||
name = name.ToLower();
|
name = name.ToLower();
|
||||||
name = name.Normalize(NormalizationForm.FormKD);
|
name = _localizationManager.NormalizeFormKD(name);
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
foreach (var c in name)
|
foreach (var c in name)
|
||||||
{
|
{
|
||||||
|
@ -615,58 +677,59 @@ namespace MediaBrowser.Providers.TV
|
||||||
|
|
||||||
private void FetchSeriesInfo(MetadataResult<Series> result, string seriesXmlPath, CancellationToken cancellationToken)
|
private void FetchSeriesInfo(MetadataResult<Series> result, string seriesXmlPath, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var settings = new XmlReaderSettings
|
var settings = _xmlSettings.Create(false);
|
||||||
{
|
|
||||||
CheckCharacters = false,
|
settings.CheckCharacters = false;
|
||||||
IgnoreProcessingInstructions = true,
|
settings.IgnoreProcessingInstructions = true;
|
||||||
IgnoreComments = true,
|
settings.IgnoreComments = true;
|
||||||
ValidationType = ValidationType.None
|
|
||||||
};
|
|
||||||
|
|
||||||
var episiodeAirDates = new List<DateTime>();
|
var episiodeAirDates = new List<DateTime>();
|
||||||
|
|
||||||
using (var streamReader = new StreamReader(seriesXmlPath, Encoding.UTF8))
|
using (var fileStream = _fileSystem.GetFileStream(seriesXmlPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
|
||||||
{
|
{
|
||||||
// Use XmlReader for best performance
|
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
|
||||||
using (var reader = XmlReader.Create(streamReader, settings))
|
|
||||||
{
|
{
|
||||||
reader.MoveToContent();
|
// Use XmlReader for best performance
|
||||||
|
using (var reader = XmlReader.Create(streamReader, settings))
|
||||||
// Loop through each element
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
reader.MoveToContent();
|
||||||
|
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
// Loop through each element
|
||||||
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
switch (reader.Name)
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
case "Series":
|
switch (reader.Name)
|
||||||
{
|
{
|
||||||
using (var subtree = reader.ReadSubtree())
|
case "Series":
|
||||||
{
|
{
|
||||||
FetchDataFromSeriesNode(result, subtree, cancellationToken);
|
using (var subtree = reader.ReadSubtree())
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "Episode":
|
|
||||||
{
|
|
||||||
using (var subtree = reader.ReadSubtree())
|
|
||||||
{
|
|
||||||
var date = GetFirstAiredDateFromEpisodeNode(subtree, cancellationToken);
|
|
||||||
|
|
||||||
if (date.HasValue)
|
|
||||||
{
|
{
|
||||||
episiodeAirDates.Add(date.Value);
|
FetchDataFromSeriesNode(result, subtree, cancellationToken);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
case "Episode":
|
||||||
reader.Skip();
|
{
|
||||||
break;
|
using (var subtree = reader.ReadSubtree())
|
||||||
|
{
|
||||||
|
var date = GetFirstAiredDateFromEpisodeNode(subtree, cancellationToken);
|
||||||
|
|
||||||
|
if (date.HasValue)
|
||||||
|
{
|
||||||
|
episiodeAirDates.Add(date.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
reader.Skip();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -751,39 +814,40 @@ namespace MediaBrowser.Providers.TV
|
||||||
/// <param name="actorsXmlPath">The actors XML path.</param>
|
/// <param name="actorsXmlPath">The actors XML path.</param>
|
||||||
private void FetchActors(MetadataResult<Series> result, string actorsXmlPath)
|
private void FetchActors(MetadataResult<Series> result, string actorsXmlPath)
|
||||||
{
|
{
|
||||||
var settings = new XmlReaderSettings
|
var settings = _xmlSettings.Create(false);
|
||||||
{
|
|
||||||
CheckCharacters = false,
|
|
||||||
IgnoreProcessingInstructions = true,
|
|
||||||
IgnoreComments = true,
|
|
||||||
ValidationType = ValidationType.None
|
|
||||||
};
|
|
||||||
|
|
||||||
using (var streamReader = new StreamReader(actorsXmlPath, Encoding.UTF8))
|
settings.CheckCharacters = false;
|
||||||
|
settings.IgnoreProcessingInstructions = true;
|
||||||
|
settings.IgnoreComments = true;
|
||||||
|
|
||||||
|
using (var fileStream = _fileSystem.GetFileStream(actorsXmlPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
|
||||||
{
|
{
|
||||||
// Use XmlReader for best performance
|
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
|
||||||
using (var reader = XmlReader.Create(streamReader, settings))
|
|
||||||
{
|
{
|
||||||
reader.MoveToContent();
|
// Use XmlReader for best performance
|
||||||
|
using (var reader = XmlReader.Create(streamReader, settings))
|
||||||
// Loop through each element
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
{
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
reader.MoveToContent();
|
||||||
|
|
||||||
|
// Loop through each element
|
||||||
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
switch (reader.Name)
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
case "Actor":
|
switch (reader.Name)
|
||||||
{
|
{
|
||||||
using (var subtree = reader.ReadSubtree())
|
case "Actor":
|
||||||
{
|
{
|
||||||
FetchDataFromActorNode(result, subtree);
|
using (var subtree = reader.ReadSubtree())
|
||||||
|
{
|
||||||
|
FetchDataFromActorNode(result, subtree);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
reader.Skip();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
reader.Skip();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1112,39 +1176,40 @@ namespace MediaBrowser.Providers.TV
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
private async Task ExtractEpisodes(string seriesDataPath, string xmlFile, long? lastTvDbUpdateTime)
|
private async Task ExtractEpisodes(string seriesDataPath, string xmlFile, long? lastTvDbUpdateTime)
|
||||||
{
|
{
|
||||||
var settings = new XmlReaderSettings
|
var settings = _xmlSettings.Create(false);
|
||||||
{
|
|
||||||
CheckCharacters = false,
|
|
||||||
IgnoreProcessingInstructions = true,
|
|
||||||
IgnoreComments = true,
|
|
||||||
ValidationType = ValidationType.None
|
|
||||||
};
|
|
||||||
|
|
||||||
using (var streamReader = new StreamReader(xmlFile, Encoding.UTF8))
|
settings.CheckCharacters = false;
|
||||||
|
settings.IgnoreProcessingInstructions = true;
|
||||||
|
settings.IgnoreComments = true;
|
||||||
|
|
||||||
|
using (var fileStream = _fileSystem.GetFileStream(xmlFile, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
|
||||||
{
|
{
|
||||||
// Use XmlReader for best performance
|
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
|
||||||
using (var reader = XmlReader.Create(streamReader, settings))
|
|
||||||
{
|
{
|
||||||
reader.MoveToContent();
|
// Use XmlReader for best performance
|
||||||
|
using (var reader = XmlReader.Create(streamReader, settings))
|
||||||
// Loop through each element
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
{
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
reader.MoveToContent();
|
||||||
|
|
||||||
|
// Loop through each element
|
||||||
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
switch (reader.Name)
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
case "Episode":
|
switch (reader.Name)
|
||||||
{
|
{
|
||||||
var outerXml = reader.ReadOuterXml();
|
case "Episode":
|
||||||
|
{
|
||||||
|
var outerXml = reader.ReadOuterXml();
|
||||||
|
|
||||||
await SaveEpsiodeXml(seriesDataPath, outerXml, lastTvDbUpdateTime).ConfigureAwait(false);
|
await SaveEpsiodeXml(seriesDataPath, outerXml, lastTvDbUpdateTime).ConfigureAwait(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
reader.Skip();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
reader.Skip();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1154,13 +1219,11 @@ namespace MediaBrowser.Providers.TV
|
||||||
|
|
||||||
private async Task SaveEpsiodeXml(string seriesDataPath, string xml, long? lastTvDbUpdateTime)
|
private async Task SaveEpsiodeXml(string seriesDataPath, string xml, long? lastTvDbUpdateTime)
|
||||||
{
|
{
|
||||||
var settings = new XmlReaderSettings
|
var settings = _xmlSettings.Create(false);
|
||||||
{
|
|
||||||
CheckCharacters = false,
|
settings.CheckCharacters = false;
|
||||||
IgnoreProcessingInstructions = true,
|
settings.IgnoreProcessingInstructions = true;
|
||||||
IgnoreComments = true,
|
settings.IgnoreComments = true;
|
||||||
ValidationType = ValidationType.None
|
|
||||||
};
|
|
||||||
|
|
||||||
var seasonNumber = -1;
|
var seasonNumber = -1;
|
||||||
var episodeNumber = -1;
|
var episodeNumber = -1;
|
||||||
|
@ -1253,13 +1316,16 @@ namespace MediaBrowser.Providers.TV
|
||||||
// Only save the file if not already there, or if the episode has changed
|
// Only save the file if not already there, or if the episode has changed
|
||||||
if (hasEpisodeChanged || !_fileSystem.FileExists(file))
|
if (hasEpisodeChanged || !_fileSystem.FileExists(file))
|
||||||
{
|
{
|
||||||
using (var writer = XmlWriter.Create(file, new XmlWriterSettings
|
using (var fileStream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None, true))
|
||||||
{
|
{
|
||||||
Encoding = Encoding.UTF8,
|
using (var writer = XmlWriter.Create(fileStream, new XmlWriterSettings
|
||||||
Async = true
|
{
|
||||||
}))
|
Encoding = Encoding.UTF8,
|
||||||
{
|
Async = true
|
||||||
await writer.WriteRawAsync(xml).ConfigureAwait(false);
|
}))
|
||||||
|
{
|
||||||
|
await writer.WriteRawAsync(xml).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1270,13 +1336,16 @@ namespace MediaBrowser.Providers.TV
|
||||||
// Only save the file if not already there, or if the episode has changed
|
// Only save the file if not already there, or if the episode has changed
|
||||||
if (hasEpisodeChanged || !_fileSystem.FileExists(file))
|
if (hasEpisodeChanged || !_fileSystem.FileExists(file))
|
||||||
{
|
{
|
||||||
using (var writer = XmlWriter.Create(file, new XmlWriterSettings
|
using (var fileStream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None, true))
|
||||||
{
|
{
|
||||||
Encoding = Encoding.UTF8,
|
using (var writer = XmlWriter.Create(fileStream, new XmlWriterSettings
|
||||||
Async = true
|
{
|
||||||
}))
|
Encoding = Encoding.UTF8,
|
||||||
{
|
Async = true
|
||||||
await writer.WriteRawAsync(xml).ConfigureAwait(false);
|
}))
|
||||||
|
{
|
||||||
|
await writer.WriteRawAsync(xml).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1339,7 +1408,7 @@ namespace MediaBrowser.Providers.TV
|
||||||
_fileSystem.DeleteFile(file);
|
_fileSystem.DeleteFile(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
// No biggie
|
// No biggie
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,11 @@ namespace MediaBrowser.Server.Implementations.Localization
|
||||||
).Normalize(NormalizationForm.FormC);
|
).Normalize(NormalizationForm.FormC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string NormalizeFormKD(string text)
|
||||||
|
{
|
||||||
|
return text.Normalize(NormalizationForm.FormKD);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the cultures.
|
/// Gets the cultures.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -278,6 +278,7 @@
|
||||||
<Compile Include="Sync\SyncJobOptions.cs" />
|
<Compile Include="Sync\SyncJobOptions.cs" />
|
||||||
<Compile Include="Sync\SyncNotificationEntryPoint.cs" />
|
<Compile Include="Sync\SyncNotificationEntryPoint.cs" />
|
||||||
<Compile Include="Threading\PeriodicTimer.cs" />
|
<Compile Include="Threading\PeriodicTimer.cs" />
|
||||||
|
<Compile Include="TV\SeriesPostScanTask.cs" />
|
||||||
<Compile Include="UserViews\CollectionFolderImageProvider.cs" />
|
<Compile Include="UserViews\CollectionFolderImageProvider.cs" />
|
||||||
<Compile Include="UserViews\DynamicImageProvider.cs" />
|
<Compile Include="UserViews\DynamicImageProvider.cs" />
|
||||||
<Compile Include="News\NewsEntryPoint.cs" />
|
<Compile Include="News\NewsEntryPoint.cs" />
|
||||||
|
@ -383,6 +384,10 @@
|
||||||
<Project>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</Project>
|
<Project>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</Project>
|
||||||
<Name>MediaBrowser.Model</Name>
|
<Name>MediaBrowser.Model</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\MediaBrowser.Providers\MediaBrowser.Providers.csproj">
|
||||||
|
<Project>{442b5058-dcaf-4263-bb6a-f21e31120a1b}</Project>
|
||||||
|
<Name>MediaBrowser.Providers</Name>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\Mono.Nat\Mono.Nat.csproj">
|
<ProjectReference Include="..\Mono.Nat\Mono.Nat.csproj">
|
||||||
<Project>{d7453b88-2266-4805-b39b-2b5a2a33e1ba}</Project>
|
<Project>{d7453b88-2266-4805-b39b-2b5a2a33e1ba}</Project>
|
||||||
<Name>Mono.Nat</Name>
|
<Name>Mono.Nat</Name>
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
using MediaBrowser.Controller.Configuration;
|
using System;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
|
||||||
using MediaBrowser.Controller.Library;
|
|
||||||
using MediaBrowser.Controller.Providers;
|
|
||||||
using MediaBrowser.Model.Entities;
|
|
||||||
using MediaBrowser.Model.Logging;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Plugins;
|
using MediaBrowser.Controller.Plugins;
|
||||||
|
using MediaBrowser.Controller.Providers;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
|
using MediaBrowser.Providers.TV;
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.TV
|
namespace MediaBrowser.Server.Implementations.TV
|
||||||
{
|
{
|
||||||
class SeriesGroup : List<Series>, IGrouping<string, Series>
|
class SeriesGroup : List<Series>, IGrouping<string, Series>
|
||||||
{
|
{
|
Loading…
Reference in New Issue