mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-15 09:59:06 -07:00
encapsulate validity in tv providers
This commit is contained in:
parent
cf8b820508
commit
0c7e06648c
@ -47,6 +47,8 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
var seriesProviderIds = searchInfo.SeriesProviderIds;
|
||||
|
||||
var list = new List<RemoteSearchResult>();
|
||||
|
||||
var identity = Identity.ParseIdentity(searchInfo.GetProviderId(FullIdKey));
|
||||
@ -59,14 +61,17 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
if (identity != null)
|
||||
{
|
||||
await TvdbSeriesProvider.Current.EnsureSeriesInfo(identity.Value.SeriesId, searchInfo.MetadataLanguage,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
seriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
seriesProviderIds[MetadataProviders.Tvdb.ToString()] = identity.Value.SeriesId;
|
||||
}
|
||||
|
||||
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, identity.Value.SeriesId);
|
||||
if (TvdbSeriesProvider.IsValidSeries(seriesProviderIds))
|
||||
{
|
||||
var seriesDataPath = await TvdbSeriesProvider.Current.EnsureSeriesInfo(seriesProviderIds, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
var metadataResult = FetchEpisodeData(searchInfo, identity.Value, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
|
||||
var metadataResult = FetchEpisodeData(searchInfo, identity, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
|
||||
|
||||
if (metadataResult.HasMetadata)
|
||||
{
|
||||
@ -247,11 +252,11 @@ namespace MediaBrowser.Providers.TV
|
||||
/// <param name="seriesProviderIds">The series provider ids.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{System.Boolean}.</returns>
|
||||
private MetadataResult<Episode> FetchEpisodeData(EpisodeInfo id, Identity identity, string seriesDataPath, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken)
|
||||
private MetadataResult<Episode> FetchEpisodeData(EpisodeInfo id, Identity? identity, string seriesDataPath, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken)
|
||||
{
|
||||
var episodeNumber = identity.EpisodeNumber;
|
||||
var episodeNumber = identity.HasValue ? (identity.Value.EpisodeNumber) : id.IndexNumber.Value;
|
||||
var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(seriesProviderIds) ?? 0;
|
||||
var seasonNumber = identity.SeasonIndex + seasonOffset;
|
||||
var seasonNumber = identity.HasValue ? (identity.Value.SeasonIndex + seasonOffset) : id.ParentIndexNumber;
|
||||
|
||||
string file;
|
||||
var usingAbsoluteData = false;
|
||||
@ -294,7 +299,7 @@ namespace MediaBrowser.Providers.TV
|
||||
usingAbsoluteData = true;
|
||||
}
|
||||
|
||||
var end = identity.EpisodeNumberEnd ?? episodeNumber;
|
||||
var end = identity.HasValue ? (identity.Value.EpisodeNumberEnd ?? episodeNumber) : (id.IndexNumberEnd ?? episodeNumber);
|
||||
episodeNumber++;
|
||||
|
||||
while (episodeNumber <= end)
|
||||
|
@ -66,24 +66,30 @@ namespace MediaBrowser.Providers.TV
|
||||
var season = (Season)item;
|
||||
var series = season.Series;
|
||||
|
||||
var identity = TvdbSeasonIdentityProvider.ParseIdentity(season.GetProviderId(TvdbSeasonIdentityProvider.FullIdKey));
|
||||
if (identity == null && series != null && season.IndexNumber.HasValue)
|
||||
if (series != null && season.IndexNumber.HasValue && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
|
||||
{
|
||||
identity = new TvdbSeasonIdentity(series.GetProviderId(MetadataProviders.Tvdb), season.IndexNumber.Value);
|
||||
}
|
||||
var seriesProviderIds = series.ProviderIds;
|
||||
var seasonNumber = season.IndexNumber.Value;
|
||||
|
||||
if (identity != null && series != null)
|
||||
{
|
||||
var id = identity.Value;
|
||||
await TvdbSeriesProvider.Current.EnsureSeriesInfo(id.SeriesId, series.GetPreferredMetadataLanguage(), cancellationToken).ConfigureAwait(false);
|
||||
var identity = TvdbSeasonIdentityProvider.ParseIdentity(season.GetProviderId(TvdbSeasonIdentityProvider.FullIdKey));
|
||||
if (identity == null)
|
||||
{
|
||||
identity = new TvdbSeasonIdentity(series.GetProviderId(MetadataProviders.Tvdb), seasonNumber);
|
||||
}
|
||||
|
||||
// Process images
|
||||
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, id.SeriesId);
|
||||
if (identity != null)
|
||||
{
|
||||
var id = identity.Value;
|
||||
seasonNumber = AdjustForSeriesOffset(series, id.Index);
|
||||
|
||||
seriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
seriesProviderIds[MetadataProviders.Tvdb.ToString()] = id.SeriesId;
|
||||
}
|
||||
|
||||
var seriesDataPath = await TvdbSeriesProvider.Current.EnsureSeriesInfo(seriesProviderIds, series.GetPreferredMetadataLanguage(), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var path = Path.Combine(seriesDataPath, "banners.xml");
|
||||
|
||||
var seasonNumber = AdjustForSeriesOffset(series, id.Index);
|
||||
|
||||
try
|
||||
{
|
||||
return GetImages(path, item.GetPreferredMetadataLanguage(), seasonNumber, cancellationToken);
|
||||
|
@ -62,23 +62,17 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken)
|
||||
{
|
||||
var series = (Series)item;
|
||||
var seriesId = series.GetProviderId(MetadataProviders.Tvdb);
|
||||
|
||||
if (!string.IsNullOrEmpty(seriesId))
|
||||
if (TvdbSeriesProvider.IsValidSeries(item.ProviderIds))
|
||||
{
|
||||
var language = item.GetPreferredMetadataLanguage();
|
||||
|
||||
await TvdbSeriesProvider.Current.EnsureSeriesInfo(seriesId, language, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Process images
|
||||
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId);
|
||||
var seriesDataPath = await TvdbSeriesProvider.Current.EnsureSeriesInfo(item.ProviderIds, language, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var path = Path.Combine(seriesDataPath, "banners.xml");
|
||||
|
||||
try
|
||||
{
|
||||
var seriesOffset = TvdbSeriesProvider.GetSeriesOffset(series.ProviderIds);
|
||||
var seriesOffset = TvdbSeriesProvider.GetSeriesOffset(item.ProviderIds);
|
||||
if (seriesOffset != null && seriesOffset.Value != 0)
|
||||
return TvdbSeasonImageProvider.GetImages(path, language, seriesOffset.Value + 1, cancellationToken);
|
||||
|
||||
|
@ -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 metadata = await GetMetadata(searchInfo, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var list = new List<RemoteSearchResult>();
|
||||
|
||||
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);
|
||||
|
||||
var files = _fileSystem.GetFiles(seriesDataPath)
|
||||
.ToList();
|
||||
|
||||
var seriesXmlFilename = preferredMetadataLanguage + ".xml";
|
||||
|
||||
var download = false;
|
||||
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))
|
||||
string id;
|
||||
if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out id))
|
||||
{
|
||||
download = true;
|
||||
return true;
|
||||
}
|
||||
//if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id))
|
||||
//{
|
||||
// return true;
|
||||
//}
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
return seriesDataPath;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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))
|
||||
private bool IsCacheValid(string seriesDataPath, string preferredMetadataLanguage)
|
||||
{
|
||||
try
|
||||
{
|
||||
download = true;
|
||||
}
|
||||
var files = _fileSystem.GetFiles(seriesDataPath)
|
||||
.ToList();
|
||||
|
||||
// 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)
|
||||
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 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)
|
||||
{
|
||||
return DownloadSeriesZip(seriesId, seriesDataPath, null, preferredMetadataLanguage, cancellationToken);
|
||||
return false;
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -607,8 +607,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
||||
throw new ArgumentNullException("timer");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(timer.ProgramId))
|
||||
{
|
||||
throw new InvalidOperationException("timer.ProgramId is null. Cannot record.");
|
||||
}
|
||||
|
||||
var info = GetProgramInfoFromCache(timer.ChannelId, timer.ProgramId);
|
||||
|
||||
if (info == null)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Program with Id {0} not found", timer.ProgramId));
|
||||
}
|
||||
|
||||
var recordPath = RecordingPath;
|
||||
|
||||
if (info.IsMovie)
|
||||
|
Loading…
Reference in New Issue
Block a user