|
@@ -59,56 +59,48 @@ namespace MediaBrowser.Providers.TV
|
|
|
|
|
|
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
|
|
|
{
|
|
|
- var seriesId = searchInfo.GetProviderId(MetadataProviders.Tvdb);
|
|
|
-
|
|
|
- if (string.IsNullOrWhiteSpace(seriesId))
|
|
|
+ if (IsValidSeries(searchInfo.ProviderIds))
|
|
|
{
|
|
|
- return await FindSeries(searchInfo.Name, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false);
|
|
|
- }
|
|
|
-
|
|
|
- var metadata = await GetMetadata(searchInfo, cancellationToken).ConfigureAwait(false);
|
|
|
-
|
|
|
- var list = new List<RemoteSearchResult>();
|
|
|
+ var metadata = await GetMetadata(searchInfo, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
- if (metadata.HasMetadata)
|
|
|
- {
|
|
|
- var res = new RemoteSearchResult
|
|
|
+ if (metadata.HasMetadata)
|
|
|
{
|
|
|
- Name = metadata.Item.Name,
|
|
|
- PremiereDate = metadata.Item.PremiereDate,
|
|
|
- ProductionYear = metadata.Item.ProductionYear,
|
|
|
- ProviderIds = metadata.Item.ProviderIds,
|
|
|
- SearchProviderName = Name
|
|
|
- };
|
|
|
-
|
|
|
- list.Add(res);
|
|
|
+ return new List<RemoteSearchResult>
|
|
|
+ {
|
|
|
+ new RemoteSearchResult
|
|
|
+ {
|
|
|
+ Name = metadata.Item.Name,
|
|
|
+ PremiereDate = metadata.Item.PremiereDate,
|
|
|
+ ProductionYear = metadata.Item.ProductionYear,
|
|
|
+ ProviderIds = metadata.Item.ProviderIds,
|
|
|
+ SearchProviderName = Name
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- return list;
|
|
|
+ return await FindSeries(searchInfo.Name, searchInfo.Year, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
|
public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo itemId, CancellationToken cancellationToken)
|
|
|
{
|
|
|
var result = new MetadataResult<Series>();
|
|
|
|
|
|
- var seriesId = itemId.GetProviderId(MetadataProviders.Tvdb);
|
|
|
-
|
|
|
- if (string.IsNullOrWhiteSpace(seriesId))
|
|
|
+ if (!IsValidSeries(itemId.ProviderIds))
|
|
|
{
|
|
|
await Identify(itemId).ConfigureAwait(false);
|
|
|
- seriesId = itemId.GetProviderId(MetadataProviders.Tvdb);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
|
- if (!string.IsNullOrWhiteSpace(seriesId))
|
|
|
+ if (IsValidSeries(itemId.ProviderIds))
|
|
|
{
|
|
|
- await EnsureSeriesInfo(seriesId, itemId.MetadataLanguage, cancellationToken).ConfigureAwait(false);
|
|
|
+ await EnsureSeriesInfo(itemId.ProviderIds, itemId.MetadataLanguage, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
result.Item = new Series();
|
|
|
result.HasMetadata = true;
|
|
|
|
|
|
- FetchSeriesData(result, seriesId, cancellationToken);
|
|
|
+ FetchSeriesData(result, itemId.GetProviderId(MetadataProviders.Tvdb), cancellationToken);
|
|
|
await FindAnimeSeriesIndex(result.Item, itemId).ConfigureAwait(false);
|
|
|
}
|
|
|
|
|
@@ -168,7 +160,7 @@ namespace MediaBrowser.Providers.TV
|
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
|
result.ResetPeople();
|
|
|
-
|
|
|
+
|
|
|
FetchActors(result, actorsXmlPath);
|
|
|
}
|
|
|
|
|
@@ -239,7 +231,7 @@ namespace MediaBrowser.Providers.TV
|
|
|
|
|
|
if (!string.Equals(downloadLangaugeXmlFile, saveAsLanguageXmlFile, StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
- _fileSystem.CopyFile(downloadLangaugeXmlFile, saveAsLanguageXmlFile, true);
|
|
|
+ _fileSystem.CopyFile(downloadLangaugeXmlFile, saveAsLanguageXmlFile, true);
|
|
|
}
|
|
|
|
|
|
await ExtractEpisodes(seriesDataPath, downloadLangaugeXmlFile, lastTvDbUpdateTime).ConfigureAwait(false);
|
|
@@ -250,62 +242,94 @@ namespace MediaBrowser.Providers.TV
|
|
|
return _config.GetConfiguration<TvdbOptions>("tvdb");
|
|
|
}
|
|
|
|
|
|
- private readonly Task _cachedTask = Task.FromResult(true);
|
|
|
- internal Task EnsureSeriesInfo(string seriesId, string preferredMetadataLanguage, CancellationToken cancellationToken)
|
|
|
+ internal static bool IsValidSeries(Dictionary<string, string> seriesProviderIds)
|
|
|
{
|
|
|
- var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesId);
|
|
|
-
|
|
|
- _fileSystem.CreateDirectory(seriesDataPath);
|
|
|
+ string id;
|
|
|
+ if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out id))
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ //if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id))
|
|
|
+ //{
|
|
|
+ // return true;
|
|
|
+ //}
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- var files = _fileSystem.GetFiles(seriesDataPath)
|
|
|
- .ToList();
|
|
|
+ internal async Task<string> EnsureSeriesInfo(Dictionary<string,string> seriesProviderIds, string preferredMetadataLanguage, CancellationToken cancellationToken)
|
|
|
+ {
|
|
|
+ string seriesId;
|
|
|
+ if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesId))
|
|
|
+ {
|
|
|
+ var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesId);
|
|
|
|
|
|
- var seriesXmlFilename = preferredMetadataLanguage + ".xml";
|
|
|
+ // Only download if not already there
|
|
|
+ // The post-scan task will take care of updates so we don't need to re-download here
|
|
|
+ if (!IsCacheValid(seriesDataPath, preferredMetadataLanguage))
|
|
|
+ {
|
|
|
+ await DownloadSeriesZip(seriesId, seriesDataPath, null, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
|
|
|
+ }
|
|
|
|
|
|
- var download = false;
|
|
|
- var automaticUpdatesEnabled = GetTvDbOptions().EnableAutomaticUpdates;
|
|
|
+ return seriesDataPath;
|
|
|
+ }
|
|
|
|
|
|
- const int cacheDays = 2;
|
|
|
+ return null;
|
|
|
+ }
|
|
|
|
|
|
- var seriesFile = files.FirstOrDefault(i => string.Equals(seriesXmlFilename, i.Name, StringComparison.OrdinalIgnoreCase));
|
|
|
- // No need to check age if automatic updates are enabled
|
|
|
- if (seriesFile == null || !seriesFile.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(seriesFile)).TotalDays > cacheDays))
|
|
|
+ private bool IsCacheValid(string seriesDataPath, string preferredMetadataLanguage)
|
|
|
+ {
|
|
|
+ try
|
|
|
{
|
|
|
- download = true;
|
|
|
- }
|
|
|
+ var files = _fileSystem.GetFiles(seriesDataPath)
|
|
|
+ .ToList();
|
|
|
|
|
|
- var actorsXml = files.FirstOrDefault(i => string.Equals("actors.xml", i.Name, StringComparison.OrdinalIgnoreCase));
|
|
|
- // No need to check age if automatic updates are enabled
|
|
|
- if (actorsXml == null || !actorsXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(actorsXml)).TotalDays > cacheDays))
|
|
|
- {
|
|
|
- download = true;
|
|
|
- }
|
|
|
+ var seriesXmlFilename = preferredMetadataLanguage + ".xml";
|
|
|
+
|
|
|
+ var automaticUpdatesEnabled = GetTvDbOptions().EnableAutomaticUpdates;
|
|
|
+
|
|
|
+ const int cacheDays = 2;
|
|
|
+
|
|
|
+ var seriesFile = files.FirstOrDefault(i => string.Equals(seriesXmlFilename, i.Name, StringComparison.OrdinalIgnoreCase));
|
|
|
+ // No need to check age if automatic updates are enabled
|
|
|
+ if (seriesFile == null || !seriesFile.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(seriesFile)).TotalDays > cacheDays))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- var bannersXml = files.FirstOrDefault(i => string.Equals("banners.xml", i.Name, StringComparison.OrdinalIgnoreCase));
|
|
|
- // No need to check age if automatic updates are enabled
|
|
|
- if (bannersXml == null || !bannersXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(bannersXml)).TotalDays > cacheDays))
|
|
|
+ var actorsXml = files.FirstOrDefault(i => string.Equals("actors.xml", i.Name, StringComparison.OrdinalIgnoreCase));
|
|
|
+ // No need to check age if automatic updates are enabled
|
|
|
+ if (actorsXml == null || !actorsXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(actorsXml)).TotalDays > cacheDays))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ var bannersXml = files.FirstOrDefault(i => string.Equals("banners.xml", i.Name, StringComparison.OrdinalIgnoreCase));
|
|
|
+ // No need to check age if automatic updates are enabled
|
|
|
+ if (bannersXml == null || !bannersXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(bannersXml)).TotalDays > cacheDays))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (DirectoryNotFoundException)
|
|
|
{
|
|
|
- download = true;
|
|
|
+ return false;
|
|
|
}
|
|
|
-
|
|
|
- // Only download if not already there
|
|
|
- // The post-scan task will take care of updates so we don't need to re-download here
|
|
|
- if (download)
|
|
|
+ catch (FileNotFoundException)
|
|
|
{
|
|
|
- return DownloadSeriesZip(seriesId, seriesDataPath, null, preferredMetadataLanguage, cancellationToken);
|
|
|
+ return false;
|
|
|
}
|
|
|
-
|
|
|
- return _cachedTask;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// Finds the series.
|
|
|
/// </summary>
|
|
|
/// <param name="name">The name.</param>
|
|
|
+ /// <param name="year">The year.</param>
|
|
|
/// <param name="language">The language.</param>
|
|
|
/// <param name="cancellationToken">The cancellation token.</param>
|
|
|
/// <returns>Task{System.String}.</returns>
|
|
|
- private async Task<IEnumerable<RemoteSearchResult>> FindSeries(string name, string language, CancellationToken cancellationToken)
|
|
|
+ private async Task<IEnumerable<RemoteSearchResult>> FindSeries(string name, int? year, string language, CancellationToken cancellationToken)
|
|
|
{
|
|
|
var results = (await FindSeriesInternal(name, language, cancellationToken).ConfigureAwait(false)).ToList();
|
|
|
|
|
@@ -320,7 +344,16 @@ namespace MediaBrowser.Providers.TV
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return results;
|
|
|
+ return results.Where(i =>
|
|
|
+ {
|
|
|
+ if (year.HasValue && i.ProductionYear.HasValue)
|
|
|
+ {
|
|
|
+ // Allow one year tolerance
|
|
|
+ return Math.Abs(year.Value - i.ProductionYear.Value) <= 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
private async Task<IEnumerable<RemoteSearchResult>> FindSeriesInternal(string name, string language, CancellationToken cancellationToken)
|
|
@@ -1108,7 +1141,7 @@ namespace MediaBrowser.Providers.TV
|
|
|
var file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber, episodeNumber));
|
|
|
|
|
|
// 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
|
|
|
{
|
|
@@ -1125,7 +1158,7 @@ namespace MediaBrowser.Providers.TV
|
|
|
file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", absoluteNumber));
|
|
|
|
|
|
// 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
|
|
|
{
|
|
@@ -1242,17 +1275,19 @@ namespace MediaBrowser.Providers.TV
|
|
|
|
|
|
public async Task Identify(SeriesInfo info)
|
|
|
{
|
|
|
- if (string.IsNullOrEmpty(info.GetProviderId(MetadataProviders.Tvdb)))
|
|
|
+ if (!string.IsNullOrWhiteSpace(info.GetProviderId(MetadataProviders.Tvdb)))
|
|
|
{
|
|
|
- var srch = await FindSeries(info.Name, info.MetadataLanguage, CancellationToken.None).ConfigureAwait(false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- var entry = srch.FirstOrDefault();
|
|
|
+ var srch = await FindSeries(info.Name, info.Year, info.MetadataLanguage, CancellationToken.None).ConfigureAwait(false);
|
|
|
|
|
|
- if (entry != null)
|
|
|
- {
|
|
|
- var id = entry.GetProviderId(MetadataProviders.Tvdb);
|
|
|
- info.SetProviderId(MetadataProviders.Tvdb, id);
|
|
|
- }
|
|
|
+ var entry = srch.FirstOrDefault();
|
|
|
+
|
|
|
+ if (entry != null)
|
|
|
+ {
|
|
|
+ var id = entry.GetProviderId(MetadataProviders.Tvdb);
|
|
|
+ info.SetProviderId(MetadataProviders.Tvdb, id);
|
|
|
}
|
|
|
}
|
|
|
|