support tvdb lookup by imdb

This commit is contained in:
Luke Pulverenti 2015-11-24 13:45:52 -05:00
parent c7ad584792
commit c7c1ff7874
8 changed files with 143 additions and 90 deletions

View File

@ -65,7 +65,7 @@ namespace MediaBrowser.Providers.People
Person = itemName
}).Items.Cast<Series>()
.Where(i => !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb)))
.Where(i => TvdbSeriesProvider.IsValidSeries(i.ProviderIds))
.ToList();
var infos = seriesWithPerson.Select(i => GetImageFromSeriesData(i, item.Name, cancellationToken))
@ -77,7 +77,7 @@ namespace MediaBrowser.Providers.People
private RemoteImageInfo GetImageFromSeriesData(Series series, string personName, CancellationToken cancellationToken)
{
var tvdbPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, series.GetProviderId(MetadataProviders.Tvdb));
var tvdbPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, series.ProviderIds);
var actorXmlPath = Path.Combine(tvdbPath, "actors.xml");

View File

@ -66,7 +66,11 @@ namespace MediaBrowser.Providers.TV
{
var tvdbId = group.Key;
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, tvdbId);
// Todo: Support series by imdb id
var seriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
seriesProviderIds[MetadataProviders.Tvdb.ToString()] = tvdbId;
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
var episodeFiles = Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.TopDirectoryOnly)
.Select(Path.GetFileNameWithoutExtension)

View File

@ -57,12 +57,10 @@ namespace MediaBrowser.Providers.TV
var episode = (Episode)item;
var series = episode.Series;
var seriesId = series != null ? series.GetProviderId(MetadataProviders.Tvdb) : null;
if (!string.IsNullOrEmpty(seriesId))
if (series != null && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
{
// Process images
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId);
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, series.ProviderIds);
var indexOffset = TvdbSeriesProvider.GetSeriesOffset(series.ProviderIds) ?? 0;
var files = TvdbEpisodeProvider.Current.GetEpisodeXmlFiles(episode.ParentIndexNumber + indexOffset, episode.IndexNumber, episode.IndexNumberEnd, seriesDataPath);
@ -204,12 +202,10 @@ namespace MediaBrowser.Providers.TV
{
var series = episode.Series;
var seriesId = series != null ? series.GetProviderId(MetadataProviders.Tvdb) : null;
if (!string.IsNullOrEmpty(seriesId))
if (series != null && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
{
// Process images
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId);
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, series.ProviderIds);
var files = TvdbEpisodeProvider.Current.GetEpisodeXmlFiles(episode.ParentIndexNumber, episode.IndexNumber, episode.IndexNumberEnd, seriesDataPath);

View File

@ -1,5 +1,4 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
@ -27,7 +26,6 @@ namespace MediaBrowser.Providers.TV
/// </summary>
class TvdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IItemIdentityProvider<EpisodeInfo>, IHasChangeMonitor
{
private const string FullIdFormat = "{0}:{1}:{2}"; // seriesId:seasonIndex:episodeNumbers
private static readonly string FullIdKey = MetadataProviders.Tvdb + "-Full";
internal static TvdbEpisodeProvider Current;
@ -47,31 +45,20 @@ 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));
if (identity == null)
if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds) && searchInfo.IndexNumber.HasValue)
{
await Identify(searchInfo).ConfigureAwait(false);
identity = Identity.ParseIdentity(searchInfo.GetProviderId(FullIdKey));
}
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, searchInfo.SeriesProviderIds);
if (identity != null)
{
seriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
seriesProviderIds[MetadataProviders.Tvdb.ToString()] = identity.Value.SeriesId;
}
if (TvdbSeriesProvider.IsValidSeries(seriesProviderIds))
{
var seriesDataPath = await TvdbSeriesProvider.Current.EnsureSeriesInfo(seriesProviderIds, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false);
var searchNumbers = new EpisodeNumbers();
searchNumbers.EpisodeNumber = searchInfo.IndexNumber.Value;
searchNumbers.SeasonNumber = searchInfo.ParentIndexNumber;
searchNumbers.EpisodeNumberEnd = searchInfo.IndexNumberEnd ?? searchNumbers.EpisodeNumber;
try
{
var metadataResult = FetchEpisodeData(searchInfo, identity, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
var metadataResult = FetchEpisodeData(searchInfo, searchNumbers, seriesDataPath, cancellationToken);
if (metadataResult.HasMetadata)
{
@ -122,11 +109,41 @@ namespace MediaBrowser.Providers.TV
if (identity != null)
{
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, identity.Value.SeriesId);
var seriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
seriesProviderIds[MetadataProviders.Tvdb.ToString()] = identity.Value.SeriesId;
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
var searchNumbers = new EpisodeNumbers();
searchNumbers.EpisodeNumber = identity.Value.EpisodeNumber;
var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(searchInfo.SeriesProviderIds) ?? 0;
searchNumbers.SeasonNumber = identity.Value.SeasonIndex + seasonOffset;
searchNumbers.EpisodeNumberEnd = identity.Value.EpisodeNumberEnd ?? searchNumbers.EpisodeNumber;
try
{
result = FetchEpisodeData(searchInfo, identity.Value, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
result = FetchEpisodeData(searchInfo, searchNumbers, seriesDataPath, cancellationToken);
}
catch (FileNotFoundException)
{
// Don't fail the provider because this will just keep on going and going.
}
catch (DirectoryNotFoundException)
{
// Don't fail the provider because this will just keep on going and going.
}
}
else if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds) && searchInfo.IndexNumber.HasValue)
{
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, searchInfo.SeriesProviderIds);
var searchNumbers = new EpisodeNumbers();
searchNumbers.EpisodeNumber = searchInfo.IndexNumber.Value;
searchNumbers.SeasonNumber = searchInfo.ParentIndexNumber;
searchNumbers.EpisodeNumberEnd = searchInfo.IndexNumberEnd ?? searchNumbers.EpisodeNumber;
try
{
result = FetchEpisodeData(searchInfo, searchNumbers, seriesDataPath, cancellationToken);
}
catch (FileNotFoundException)
{
@ -156,12 +173,10 @@ namespace MediaBrowser.Providers.TV
var episode = (Episode)item;
var series = episode.Series;
var seriesId = series != null ? series.GetProviderId(MetadataProviders.Tvdb) : null;
if (!string.IsNullOrEmpty(seriesId))
if (series != null && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
{
// Process images
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId);
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, series.ProviderIds);
var files = GetEpisodeXmlFiles(episode.ParentIndexNumber, episode.IndexNumber, episode.IndexNumberEnd, seriesDataPath);
@ -243,20 +258,25 @@ namespace MediaBrowser.Providers.TV
return files;
}
private class EpisodeNumbers
{
public int EpisodeNumber;
public int? SeasonNumber;
public int EpisodeNumberEnd;
}
/// <summary>
/// Fetches the episode data.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="identity">The identity.</param>
/// <param name="searchNumbers">The search numbers.</param>
/// <param name="seriesDataPath">The series data path.</param>
/// <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, EpisodeNumbers searchNumbers, string seriesDataPath, CancellationToken cancellationToken)
{
var episodeNumber = identity.HasValue ? (identity.Value.EpisodeNumber) : id.IndexNumber.Value;
var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(seriesProviderIds) ?? 0;
var seasonNumber = identity.HasValue ? (identity.Value.SeasonIndex + seasonOffset) : id.ParentIndexNumber;
var episodeNumber = searchNumbers.EpisodeNumber;
var seasonNumber = searchNumbers.SeasonNumber;
string file;
var usingAbsoluteData = false;
@ -299,7 +319,7 @@ namespace MediaBrowser.Providers.TV
usingAbsoluteData = true;
}
var end = identity.HasValue ? (identity.Value.EpisodeNumberEnd ?? episodeNumber) : (id.IndexNumberEnd ?? episodeNumber);
var end = searchNumbers.EpisodeNumberEnd;
episodeNumber++;
while (episodeNumber <= end)

View File

@ -360,7 +360,7 @@ namespace MediaBrowser.Providers.TV
_fileSystem.CreateDirectory(seriesDataPath);
return TvdbSeriesProvider.Current.DownloadSeriesZip(id, seriesDataPath, lastTvDbUpdateTime, preferredMetadataLanguage, cancellationToken);
return TvdbSeriesProvider.Current.DownloadSeriesZip(id, MetadataProviders.Tvdb.ToString(), seriesDataPath, lastTvDbUpdateTime, preferredMetadataLanguage, cancellationToken);
}
}
}

View File

@ -375,17 +375,10 @@ namespace MediaBrowser.Providers.TV
var season = (Season)item;
var series = season.Series;
if (series == null)
{
return false;
}
var tvdbId = series.GetProviderId(MetadataProviders.Tvdb);
if (!String.IsNullOrEmpty(tvdbId))
if (series != null && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
{
// Process images
var imagesXmlPath = Path.Combine(TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, tvdbId), "banners.xml");
var imagesXmlPath = Path.Combine(TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, series.ProviderIds), "banners.xml");
var fileInfo = _fileSystem.GetFileInfo(imagesXmlPath);

View File

@ -340,12 +340,10 @@ namespace MediaBrowser.Providers.TV
return false;
}
var tvdbId = item.GetProviderId(MetadataProviders.Tvdb);
if (!String.IsNullOrEmpty(tvdbId))
if (TvdbSeriesProvider.IsValidSeries(item.ProviderIds))
{
// Process images
var imagesXmlPath = Path.Combine(TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, tvdbId), "banners.xml");
var imagesXmlPath = Path.Combine(TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, item.ProviderIds), "banners.xml");
var fileInfo = _fileSystem.GetFileInfo(imagesXmlPath);

View File

@ -56,6 +56,7 @@ namespace MediaBrowser.Providers.TV
private const string SeriesSearchUrl = "http://www.thetvdb.com/api/GetSeries.php?seriesname={0}&language={1}";
private const string SeriesGetZip = "http://www.thetvdb.com/api/{0}/series/{1}/all/{2}.zip";
private const string SeriesGetZipByImdbId = "http://www.thetvdb.com/api/{0}/GetSeriesByRemoteID.php?imdbid={1}&language={2}";
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
{
@ -100,7 +101,7 @@ namespace MediaBrowser.Providers.TV
result.Item = new Series();
result.HasMetadata = true;
FetchSeriesData(result, itemId.GetProviderId(MetadataProviders.Tvdb), cancellationToken);
FetchSeriesData(result, itemId.ProviderIds, cancellationToken);
await FindAnimeSeriesIndex(result.Item, itemId).ConfigureAwait(false);
}
@ -139,16 +140,25 @@ namespace MediaBrowser.Providers.TV
/// Fetches the series data.
/// </summary>
/// <param name="result">The result.</param>
/// <param name="seriesId">The series id.</param>
/// <param name="seriesProviderIds">The series provider ids.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.Boolean}.</returns>
private void FetchSeriesData(MetadataResult<Series> result, string seriesId, CancellationToken cancellationToken)
private void FetchSeriesData(MetadataResult<Series> result, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken)
{
var series = result.Item;
series.SetProviderId(MetadataProviders.Tvdb, seriesId);
string id;
if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out id))
{
series.SetProviderId(MetadataProviders.Tvdb, id);
}
var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesId);
if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id))
{
series.SetProviderId(MetadataProviders.Imdb, id);
}
var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
var seriesXmlFilename = series.GetPreferredMetadataLanguage().ToLower() + ".xml";
@ -168,12 +178,14 @@ namespace MediaBrowser.Providers.TV
/// Downloads the series zip.
/// </summary>
/// <param name="seriesId">The series id.</param>
/// <param name="idType">Type of the identifier.</param>
/// <param name="seriesDataPath">The series data path.</param>
/// <param name="lastTvDbUpdateTime">The last tv database update time.</param>
/// <param name="preferredMetadataLanguage">The preferred metadata language.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
internal async Task DownloadSeriesZip(string seriesId, string seriesDataPath, long? lastTvDbUpdateTime, string preferredMetadataLanguage, CancellationToken cancellationToken)
/// <exception cref="System.ArgumentNullException">seriesId</exception>
internal async Task DownloadSeriesZip(string seriesId, string idType, string seriesDataPath, long? lastTvDbUpdateTime, string preferredMetadataLanguage, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(seriesId))
{
@ -182,7 +194,7 @@ namespace MediaBrowser.Providers.TV
try
{
await DownloadSeriesZip(seriesId, seriesDataPath, lastTvDbUpdateTime, preferredMetadataLanguage, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
await DownloadSeriesZip(seriesId, idType, seriesDataPath, lastTvDbUpdateTime, preferredMetadataLanguage, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
return;
}
catch (HttpException ex)
@ -195,18 +207,20 @@ namespace MediaBrowser.Providers.TV
if (!string.Equals(preferredMetadataLanguage, "en", StringComparison.OrdinalIgnoreCase))
{
await DownloadSeriesZip(seriesId, seriesDataPath, lastTvDbUpdateTime, "en", preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
await DownloadSeriesZip(seriesId, idType, seriesDataPath, lastTvDbUpdateTime, "en", preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
}
}
private async Task DownloadSeriesZip(string seriesId, string seriesDataPath, long? lastTvDbUpdateTime, string preferredMetadataLanguage, string saveAsMetadataLanguage, CancellationToken cancellationToken)
private async Task DownloadSeriesZip(string seriesId, string idType, string seriesDataPath, long? lastTvDbUpdateTime, string preferredMetadataLanguage, string saveAsMetadataLanguage, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(seriesId))
{
throw new ArgumentNullException("seriesId");
}
var url = string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, preferredMetadataLanguage);
var url = string.Equals(idType, "tvdb", StringComparison.OrdinalIgnoreCase) ?
string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, preferredMetadataLanguage) :
string.Format(SeriesGetZipByImdbId, TVUtils.TvdbApiKey, seriesId, preferredMetadataLanguage);
using (var zipStream = await _httpClient.Get(new HttpRequestOptions
{
@ -263,25 +277,44 @@ namespace MediaBrowser.Providers.TV
return true;
}
}
//if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id))
//{
// return true;
//}
if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id))
{
// This check should ideally never be necessary but we're seeing some cases of this and haven't tracked them down yet.
if (!string.IsNullOrWhiteSpace(id))
{
return true;
}
}
return false;
}
internal async Task<string> EnsureSeriesInfo(Dictionary<string,string> seriesProviderIds, string preferredMetadataLanguage, CancellationToken cancellationToken)
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 seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
// 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);
await DownloadSeriesZip(seriesId, MetadataProviders.Tvdb.ToString(), seriesDataPath, null, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
}
return seriesDataPath;
}
if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out seriesId))
{
var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
// 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, MetadataProviders.Imdb.ToString(), seriesDataPath, null, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
}
return seriesDataPath;
@ -838,9 +871,6 @@ namespace MediaBrowser.Providers.TV
var val = reader.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(val))
{
// Only fill this if it doesn't already have a value, since we get it from imdb which has better data
if (!item.CommunityRating.HasValue || string.IsNullOrWhiteSpace(item.GetProviderId(MetadataProviders.Imdb)))
{
float rval;
@ -850,7 +880,6 @@ namespace MediaBrowser.Providers.TV
item.CommunityRating = rval;
}
}
}
break;
}
case "RatingCount":
@ -1190,15 +1219,28 @@ namespace MediaBrowser.Providers.TV
/// Gets the series data path.
/// </summary>
/// <param name="appPaths">The app paths.</param>
/// <param name="seriesId">The series id.</param>
/// <param name="seriesProviderIds">The series provider ids.</param>
/// <returns>System.String.</returns>
internal static string GetSeriesDataPath(IApplicationPaths appPaths, string seriesId)
internal static string GetSeriesDataPath(IApplicationPaths appPaths, Dictionary<string, string> seriesProviderIds)
{
string seriesId;
if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesId))
{
var seriesDataPath = Path.Combine(GetSeriesDataPath(appPaths), seriesId);
return seriesDataPath;
}
if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out seriesId))
{
var seriesDataPath = Path.Combine(GetSeriesDataPath(appPaths), seriesId);
return seriesDataPath;
}
return null;
}
/// <summary>
/// Gets the series data path.
/// </summary>