converted season providers

This commit is contained in:
Luke Pulverenti 2014-02-03 00:35:43 -05:00
parent 6261f157f3
commit 30ebfab8e0
37 changed files with 526 additions and 893 deletions

View File

@ -784,11 +784,19 @@ namespace MediaBrowser.Controller.Entities
ResetResolveArgs();
}
await BeforeRefreshMetadata(options, cancellationToken).ConfigureAwait(false);
await ProviderManager.RefreshMetadata(this, options, cancellationToken).ConfigureAwait(false);
return false;
}
private readonly Task _cachedTask = Task.FromResult(true);
protected virtual Task BeforeRefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken)
{
return _cachedTask;
}
[Obsolete]
public virtual async Task<bool> RefreshMetadataDirect(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false)
{

View File

@ -914,11 +914,14 @@ namespace MediaBrowser.Controller.Entities
return item;
}
public override async Task<bool> RefreshMetadataDirect(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false)
protected override Task BeforeRefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken)
{
var changed = await base.RefreshMetadataDirect(cancellationToken, forceSave, forceRefresh).ConfigureAwait(false);
if (SupportsShortcutChildren && LocationType == LocationType.FileSystem)
{
RefreshLinkedChildren();
}
return (SupportsShortcutChildren && LocationType == LocationType.FileSystem && RefreshLinkedChildren()) || changed;
return base.BeforeRefreshMetadata(options, cancellationToken);
}
/// <summary>

View File

@ -274,33 +274,6 @@ namespace MediaBrowser.Controller.Entities
serializer.SerializeToFile(Configuration, xmlPath);
}
/// <summary>
/// Refresh metadata on us by execution our provider chain
/// The item will be persisted if a change is made by a provider, or if it's new or changed.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="forceSave">if set to <c>true</c> [is new item].</param>
/// <param name="forceRefresh">if set to <c>true</c> [force].</param>
/// <returns>true if a provider reports we changed</returns>
public override async Task<bool> RefreshMetadataDirect(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false)
{
// Reload this
ResetResolveArgs();
var updateReason = await ProviderManager.ExecuteMetadataProviders(this, cancellationToken, forceRefresh).ConfigureAwait(false);
var changed = updateReason.HasValue;
if (changed || forceSave)
{
cancellationToken.ThrowIfCancellationRequested();
await UserManager.UpdateUser(this).ConfigureAwait(false);
}
return changed;
}
/// <summary>
/// Updates the configuration.
/// </summary>

View File

@ -51,7 +51,7 @@ namespace MediaBrowser.Providers.BoxSets
public string Name
{
get { return "Media Browser xml"; }
get { return "Media Browser Xml"; }
}
protected override FileInfo GetXmlFile(string path)

View File

@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Games
public string Name
{
get { return "Media Browser xml"; }
get { return "Media Browser Xml"; }
}
protected override FileInfo GetXmlFile(string path)

View File

@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Games
public string Name
{
get { return "Media Browser xml"; }
get { return "Media Browser Xml"; }
}
protected override FileInfo GetXmlFile(string path)

View File

@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.LiveTv
public string Name
{
get { return "Media Browser xml"; }
get { return "Media Browser Xml"; }
}
protected override FileInfo GetXmlFile(string path)

View File

@ -89,6 +89,8 @@ namespace MediaBrowser.Providers.Manager
// Next run metadata providers
if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
{
updateType = updateType | BeforeMetadataRefresh(itemOfType);
var providers = GetProviders(item, lastResult.DateLastMetadataRefresh.HasValue, refreshOptions).ToList();
if (providers.Count > 0)
@ -100,6 +102,8 @@ namespace MediaBrowser.Providers.Manager
refreshResult.SetDateLastMetadataRefresh(DateTime.UtcNow);
refreshResult.AddImageProvidersRefreshed(result.Providers);
}
updateType = updateType | AfterMetadataRefresh(itemOfType);
}
// Next run remote image providers, but only if local image providers didn't throw an exception
@ -116,8 +120,6 @@ namespace MediaBrowser.Providers.Manager
refreshResult.SetDateLastImagesRefresh(DateTime.UtcNow);
refreshResult.AddImageProvidersRefreshed(result.Providers);
}
updateType = updateType | AfterMetadataRefresh(itemOfType);
}
var providersHadChanges = updateType > ItemUpdateType.Unspecified;
@ -157,6 +159,16 @@ namespace MediaBrowser.Providers.Manager
return ItemUpdateType.Unspecified;
}
/// <summary>
/// Befores the metadata refresh.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>ItemUpdateType.</returns>
protected virtual ItemUpdateType BeforeMetadataRefresh(TItemType item)
{
return ItemUpdateType.Unspecified;
}
/// <summary>
/// Gets the providers.
/// </summary>
@ -261,12 +273,17 @@ namespace MediaBrowser.Providers.Manager
if (localItem.HasMetadata)
{
MergeData(localItem.Item, temp, new List<MetadataFields>(), !options.ReplaceAllMetadata, true);
refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport;
if (!string.IsNullOrEmpty(localItem.Item.Name))
{
MergeData(localItem.Item, temp, new List<MetadataFields>(), !options.ReplaceAllMetadata, true);
refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport;
// Only one local provider allowed per item
hasLocalMetadata = true;
break;
// Only one local provider allowed per item
hasLocalMetadata = true;
break;
}
Logger.Error("Invalid local metadata found for: " + item.Path);
}
}
catch (OperationCanceledException)

View File

@ -65,6 +65,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="All\LocalImageProvider.cs" />
<Compile Include="Books\BookMetadataService.cs" />
<Compile Include="BoxSets\BoxSetMetadataService.cs" />
<Compile Include="BoxSets\MovieDbBoxSetImageProvider.cs" />
<Compile Include="BoxSets\MovieDbBoxSetProvider.cs" />
@ -151,26 +152,24 @@
<Compile Include="TV\EpisodeIndexNumberProvider.cs" />
<Compile Include="TV\EpisodeProviderFromXml.cs" />
<Compile Include="TV\EpisodeXmlParser.cs" />
<Compile Include="TV\FanArtSeasonProvider.cs" />
<Compile Include="TV\FanArtTVProvider.cs" />
<Compile Include="TV\FanArtTvUpdatesPrescanTask.cs" />
<Compile Include="TV\ManualFanartSeasonProvider.cs" />
<Compile Include="TV\FanartSeasonProvider.cs" />
<Compile Include="TV\ManualFanartSeriesProvider.cs" />
<Compile Include="TV\ManualTvdbEpisodeImageProvider.cs" />
<Compile Include="People\TvdbPersonImageProvider.cs" />
<Compile Include="TV\ManualTvdbSeasonImageProvider.cs" />
<Compile Include="TV\TvdbSeasonImageProvider.cs" />
<Compile Include="TV\ManualTvdbSeriesImageProvider.cs" />
<Compile Include="TV\SeasonIndexNumberProvider.cs" />
<Compile Include="TV\SeasonMetadataService.cs" />
<Compile Include="TV\TvdbEpisodeProvider.cs" />
<Compile Include="TV\TvdbSeasonProvider.cs" />
<Compile Include="TV\TvdbSeriesImageProvider.cs" />
<Compile Include="TV\TvdbSeriesProvider.cs" />
<Compile Include="TV\SeasonProviderFromXml.cs" />
<Compile Include="TV\SeasonXmlProvider.cs" />
<Compile Include="TV\SeriesDynamicInfoProvider.cs" />
<Compile Include="TV\SeriesPostScanTask.cs" />
<Compile Include="TV\SeriesProviderFromXml.cs" />
<Compile Include="TV\SeriesXmlParser.cs" />
<Compile Include="TV\TvdbPrescanTask.cs" />
<Compile Include="TV\TvdbSeriesImageProvider.cs" />
<Compile Include="UserRootFolderNameProvider.cs" />
<Compile Include="Users\UserMetadataService.cs" />
<Compile Include="VirtualItemImageValidator.cs" />

View File

@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Music
public string Name
{
get { return "Media Browser xml"; }
get { return "Media Browser Xml"; }
}
protected override FileInfo GetXmlFile(string path)

View File

@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Music
public string Name
{
get { return "Media Browser xml"; }
get { return "Media Browser Xml"; }
}
protected override FileInfo GetXmlFile(string path)

View File

@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.People
public string Name
{
get { return "Media Browser xml"; }
get { return "Media Browser Xml"; }
}
protected override FileInfo GetXmlFile(string path)

View File

@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Savers
{
get
{
return "Media Browser xml";
return "Media Browser Xml";
}
}

View File

@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.Savers
{
get
{
return "Media Browser xml";
return "Media Browser Xml";
}
}

View File

@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.Savers
{
get
{
return "Media Browser xml";
return "Media Browser Xml";
}
}

View File

@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.Savers
{
get
{
return "Media Browser xml";
return "Media Browser Xml";
}
}

View File

@ -41,7 +41,7 @@ namespace MediaBrowser.Providers.Savers
{
get
{
return "Media Browser xml";
return "Media Browser Xml";
}
}

View File

@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.Savers
{
get
{
return "Media Browser xml";
return "Media Browser Xml";
}
}

View File

@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.Savers
{
get
{
return "Media Browser xml";
return "Media Browser Xml";
}
}

View File

@ -28,7 +28,7 @@ namespace MediaBrowser.Providers.Savers
{
get
{
return "Media Browser xml";
return "Media Browser Xml";
}
}

View File

@ -32,7 +32,7 @@ namespace MediaBrowser.Providers.Savers
{
get
{
return "Media Browser xml";
return "Media Browser Xml";
}
}

View File

@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Savers
{
get
{
return "Media Browser xml";
return "Media Browser Xml";
}
}

View File

@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Savers
{
get
{
return "Media Browser xml";
return "Media Browser Xml";
}
}

View File

@ -24,7 +24,7 @@ namespace MediaBrowser.Providers.Savers
{
get
{
return "Media Browser xml";
return "Media Browser Xml";
}
}

View File

@ -1,190 +1,303 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using MediaBrowser.Providers.Music;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Net;
using System.Net;
using MediaBrowser.Providers.Music;
using System.Xml;
namespace MediaBrowser.Providers.TV
{
/// <summary>
/// Class FanArtSeasonProvider
/// </summary>
class FanArtSeasonProvider : BaseMetadataProvider
public class FanartSeasonImageProvider : IRemoteImageProvider, IHasOrder, IHasChangeMonitor
{
/// <summary>
/// The _provider manager
/// </summary>
private readonly IProviderManager _providerManager;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IServerConfigurationManager _config;
private readonly IHttpClient _httpClient;
private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="FanArtSeasonProvider"/> class.
/// </summary>
/// <param name="logManager">The log manager.</param>
/// <param name="configurationManager">The configuration manager.</param>
/// <param name="providerManager">The provider manager.</param>
public FanArtSeasonProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
public FanartSeasonImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
{
_providerManager = providerManager;
_config = config;
_httpClient = httpClient;
_fileSystem = fileSystem;
}
public override ItemUpdateType ItemUpdateType
public string Name
{
get
{
return ItemUpdateType.ImageUpdate;
}
get { return ProviderName; }
}
/// <summary>
/// Supportses the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public override bool Supports(BaseItem item)
public static string ProviderName
{
get { return "FanArt"; }
}
public bool Supports(IHasImages item)
{
return item is Season;
}
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override MetadataProviderPriority Priority
public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
{
get { return MetadataProviderPriority.Third; }
return new List<ImageType>
{
ImageType.Backdrop,
ImageType.Thumb
};
}
protected override DateTime CompareDate(BaseItem item)
public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType);
}
public async Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{
var list = new List<RemoteImageInfo>();
var season = (Season)item;
var series = season.Series;
if (series != null)
{
var id = series.GetProviderId(MetadataProviders.Tvdb);
if (!string.IsNullOrEmpty(id) && season.IndexNumber.HasValue)
{
await FanArtTvProvider.Current.EnsureSeriesXml(id, cancellationToken).ConfigureAwait(false);
var xmlPath = FanArtTvProvider.Current.GetFanartXmlPath(id);
try
{
AddImages(list, season.IndexNumber.Value, xmlPath, cancellationToken);
}
catch (FileNotFoundException)
{
// No biggie. Don't blow up
}
}
}
var language = item.GetPreferredMetadataLanguage();
var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase);
// Sort first by width to prioritize HD versions
return list.OrderByDescending(i => i.Width ?? 0)
.ThenByDescending(i =>
{
if (string.Equals(language, i.Language, StringComparison.OrdinalIgnoreCase))
{
return 3;
}
if (!isLanguageEn)
{
if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase))
{
return 2;
}
}
if (string.IsNullOrEmpty(i.Language))
{
return isLanguageEn ? 3 : 2;
}
return 0;
})
.ThenByDescending(i => i.CommunityRating ?? 0)
.ThenByDescending(i => i.VoteCount ?? 0);
}
private void AddImages(List<RemoteImageInfo> list, int seasonNumber, string xmlPath, CancellationToken cancellationToken)
{
using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
{
// Use XmlReader for best performance
using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
{
CheckCharacters = false,
IgnoreProcessingInstructions = true,
IgnoreComments = true,
ValidationType = ValidationType.None
}))
{
reader.MoveToContent();
// Loop through each element
while (reader.Read())
{
cancellationToken.ThrowIfCancellationRequested();
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "series":
{
using (var subReader = reader.ReadSubtree())
{
AddImages(list, subReader, seasonNumber, cancellationToken);
}
break;
}
default:
reader.Skip();
break;
}
}
}
}
}
}
private void AddImages(List<RemoteImageInfo> list, XmlReader reader, int seasonNumber, CancellationToken cancellationToken)
{
reader.MoveToContent();
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "seasonthumbs":
{
using (var subReader = reader.ReadSubtree())
{
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Thumb, 500, 281, seasonNumber);
}
break;
}
case "showbackgrounds":
{
using (var subReader = reader.ReadSubtree())
{
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Backdrop, 1920, 1080, seasonNumber);
}
break;
}
default:
{
using (reader.ReadSubtree())
{
}
break;
}
}
}
}
}
private void PopulateImageCategory(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken, ImageType type, int width, int height, int seasonNumber)
{
reader.MoveToContent();
while (reader.Read())
{
cancellationToken.ThrowIfCancellationRequested();
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "seasonthumb":
case "showbackground":
{
var url = reader.GetAttribute("url");
var season = reader.GetAttribute("season");
int imageSeasonNumber;
if (!string.IsNullOrEmpty(url) &&
!string.IsNullOrEmpty(season) &&
int.TryParse(season, NumberStyles.Any, _usCulture, out imageSeasonNumber) &&
seasonNumber == imageSeasonNumber)
{
var likesString = reader.GetAttribute("likes");
int likes;
var info = new RemoteImageInfo
{
RatingType = RatingType.Likes,
Type = type,
Width = width,
Height = height,
ProviderName = Name,
Url = url,
Language = reader.GetAttribute("lang")
};
if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes))
{
info.CommunityRating = likes;
}
list.Add(info);
}
break;
}
default:
reader.Skip();
break;
}
}
}
}
public int Order
{
get { return 1; }
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
Url = url,
ResourcePool = FanartArtistProvider.FanArtResourcePool
});
}
public bool HasChanged(IHasMetadata item, DateTime date)
{
var season = (Season)item;
var seriesId = season.Series != null ? season.Series.GetProviderId(MetadataProviders.Tvdb) : null;
var series = season.Series;
if (!string.IsNullOrEmpty(seriesId))
if (series == null)
{
return false;
}
var tvdbId = series.GetProviderId(MetadataProviders.Tvdb);
if (!String.IsNullOrEmpty(tvdbId))
{
// Process images
var imagesXmlPath = FanArtTvProvider.Current.GetFanartXmlPath(seriesId);
var imagesXmlPath = FanArtTvProvider.Current.GetFanartXmlPath(tvdbId);
var imagesFileInfo = new FileInfo(imagesXmlPath);
var fileInfo = new FileInfo(imagesXmlPath);
if (imagesFileInfo.Exists)
{
return _fileSystem.GetLastWriteTimeUtc(imagesFileInfo);
}
return fileInfo.Exists && _fileSystem.GetLastWriteTimeUtc(fileInfo) > date;
}
return base.CompareDate(item);
}
/// <summary>
/// Fetches metadata and returns true or false indicating if any work that requires persistence was done
/// </summary>
/// <param name="item">The item.</param>
/// <param name="force">if set to <c>true</c> [force].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.Boolean}.</returns>
public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var season = (Season) item;
// Process images
var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualFanartSeasonImageProvider.ProviderName).ConfigureAwait(false);
await FetchImages(season, images.ToList(), cancellationToken).ConfigureAwait(false);
SetLastRefreshed(item, DateTime.UtcNow, providerInfo);
return true;
}
/// <summary>
/// Fetches the images.
/// </summary>
/// <param name="season">The season.</param>
/// <param name="images">The images.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private async Task FetchImages(Season season, List<RemoteImageInfo> images, CancellationToken cancellationToken)
{
var options = ConfigurationManager.Configuration.GetMetadataOptions("Season") ?? new MetadataOptions();
if (options.IsEnabled(ImageType.Thumb) && !season.HasImage(ImageType.Thumb) && !season.LockedFields.Contains(MetadataFields.Images))
{
await SaveImage(season, images, ImageType.Thumb, cancellationToken).ConfigureAwait(false);
}
}
private async Task SaveImage(BaseItem item, List<RemoteImageInfo> images, ImageType type, CancellationToken cancellationToken)
{
foreach (var image in images.Where(i => i.Type == type))
{
try
{
await _providerManager.SaveImage(item, image.Url, FanartArtistProvider.FanArtResourcePool, type, null, cancellationToken).ConfigureAwait(false);
break;
}
catch (HttpException ex)
{
// Sometimes fanart has bad url's in their xml
if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound)
{
continue;
}
break;
}
}
}
/// <summary>
/// Gets a value indicating whether [requires internet].
/// </summary>
/// <value><c>true</c> if [requires internet]; otherwise, <c>false</c>.</value>
public override bool RequiresInternet
{
get
{
return true;
}
}
/// <summary>
/// Gets a value indicating whether [refresh on version change].
/// </summary>
/// <value><c>true</c> if [refresh on version change]; otherwise, <c>false</c>.</value>
protected override bool RefreshOnVersionChange
{
get
{
return true;
}
}
/// <summary>
/// Gets the provider version.
/// </summary>
/// <value>The provider version.</value>
protected override string ProviderVersion
{
get
{
return "3";
}
return false;
}
}
}

View File

@ -72,7 +72,7 @@ namespace MediaBrowser.Providers.TV
return ItemUpdateType.ImageUpdate;
}
}
/// <summary>
/// Needses the refresh internal.
/// </summary>
@ -160,7 +160,7 @@ namespace MediaBrowser.Providers.TV
var dataPath = GetSeriesDataPath(ConfigurationManager.ApplicationPaths, tvdbId);
return Path.Combine(dataPath, "fanart.xml");
}
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken)
@ -199,7 +199,7 @@ namespace MediaBrowser.Providers.TV
private async Task FetchFromXml(BaseItem item, List<RemoteImageInfo> images, CancellationToken cancellationToken)
{
var options = ConfigurationManager.Configuration.GetMetadataOptions("Series") ?? new MetadataOptions();
if (!item.LockedFields.Contains(MetadataFields.Images))
{
cancellationToken.ThrowIfCancellationRequested();
@ -278,6 +278,23 @@ namespace MediaBrowser.Providers.TV
}
}
internal Task EnsureSeriesXml(string tvdbId, CancellationToken cancellationToken)
{
var xmlPath = GetSeriesDataPath(ConfigurationManager.ApplicationPaths, tvdbId);
var fileInfo = _fileSystem.GetFileSystemInfo(xmlPath);
if (fileInfo.Exists)
{
if (ConfigurationManager.Configuration.EnableFanArtUpdates || (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 7)
{
return Task.FromResult(true);
}
}
return DownloadSeriesXml(tvdbId, cancellationToken);
}
/// <summary>
/// Downloads the series XML.
/// </summary>

View File

@ -1,276 +0,0 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using MediaBrowser.Providers.Music;
namespace MediaBrowser.Providers.TV
{
public class ManualFanartSeasonImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IServerConfigurationManager _config;
private readonly IHttpClient _httpClient;
public ManualFanartSeasonImageProvider(IServerConfigurationManager config, IHttpClient httpClient)
{
_config = config;
_httpClient = httpClient;
}
public string Name
{
get { return ProviderName; }
}
public static string ProviderName
{
get { return "FanArt"; }
}
public bool Supports(IHasImages item)
{
return item is Season;
}
public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
{
return new List<ImageType>
{
ImageType.Backdrop,
ImageType.Thumb
};
}
public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{
var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
return images.Where(i => i.Type == imageType);
}
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{
var list = new List<RemoteImageInfo>();
var season = (Season)item;
var series = season.Series;
if (series != null)
{
var id = series.GetProviderId(MetadataProviders.Tvdb);
if (!string.IsNullOrEmpty(id) && season.IndexNumber.HasValue)
{
var xmlPath = FanArtTvProvider.Current.GetFanartXmlPath(id);
try
{
AddImages(list, season.IndexNumber.Value, xmlPath, cancellationToken);
}
catch (FileNotFoundException)
{
// No biggie. Don't blow up
}
}
}
var language = item.GetPreferredMetadataLanguage();
var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase);
// Sort first by width to prioritize HD versions
list = list.OrderByDescending(i => i.Width ?? 0)
.ThenByDescending(i =>
{
if (string.Equals(language, i.Language, StringComparison.OrdinalIgnoreCase))
{
return 3;
}
if (!isLanguageEn)
{
if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase))
{
return 2;
}
}
if (string.IsNullOrEmpty(i.Language))
{
return isLanguageEn ? 3 : 2;
}
return 0;
})
.ThenByDescending(i => i.CommunityRating ?? 0)
.ThenByDescending(i => i.VoteCount ?? 0)
.ToList();
return Task.FromResult<IEnumerable<RemoteImageInfo>>(list);
}
private void AddImages(List<RemoteImageInfo> list, int seasonNumber, string xmlPath, CancellationToken cancellationToken)
{
using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
{
// Use XmlReader for best performance
using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
{
CheckCharacters = false,
IgnoreProcessingInstructions = true,
IgnoreComments = true,
ValidationType = ValidationType.None
}))
{
reader.MoveToContent();
// Loop through each element
while (reader.Read())
{
cancellationToken.ThrowIfCancellationRequested();
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "series":
{
using (var subReader = reader.ReadSubtree())
{
AddImages(list, subReader, seasonNumber, cancellationToken);
}
break;
}
default:
reader.Skip();
break;
}
}
}
}
}
}
private void AddImages(List<RemoteImageInfo> list, XmlReader reader, int seasonNumber, CancellationToken cancellationToken)
{
reader.MoveToContent();
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "seasonthumbs":
{
using (var subReader = reader.ReadSubtree())
{
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Thumb, 500, 281, seasonNumber);
}
break;
}
case "showbackgrounds":
{
using (var subReader = reader.ReadSubtree())
{
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Backdrop, 1920, 1080, seasonNumber);
}
break;
}
default:
{
using (reader.ReadSubtree())
{
}
break;
}
}
}
}
}
private void PopulateImageCategory(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken, ImageType type, int width, int height, int seasonNumber)
{
reader.MoveToContent();
while (reader.Read())
{
cancellationToken.ThrowIfCancellationRequested();
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "seasonthumb":
case "showbackground":
{
var url = reader.GetAttribute("url");
var season = reader.GetAttribute("season");
int imageSeasonNumber;
if (!string.IsNullOrEmpty(url) &&
!string.IsNullOrEmpty(season) &&
int.TryParse(season, NumberStyles.Any, _usCulture, out imageSeasonNumber) &&
seasonNumber == imageSeasonNumber)
{
var likesString = reader.GetAttribute("likes");
int likes;
var info = new RemoteImageInfo
{
RatingType = RatingType.Likes,
Type = type,
Width = width,
Height = height,
ProviderName = Name,
Url = url,
Language = reader.GetAttribute("lang")
};
if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes))
{
info.CommunityRating = likes;
}
list.Add(info);
}
break;
}
default:
reader.Skip();
break;
}
}
}
}
public int Order
{
get { return 1; }
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
Url = url,
ResourcePool = FanartArtistProvider.FanArtResourcePool
});
}
}
}

View File

@ -1,83 +0,0 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
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.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.TV
{
class SeasonIndexNumberProvider : BaseMetadataProvider
{
/// <summary>
/// Initializes a new instance of the <see cref="BaseMetadataProvider" /> class.
/// </summary>
/// <param name="logManager">The log manager.</param>
/// <param name="configurationManager">The configuration manager.</param>
public SeasonIndexNumberProvider(ILogManager logManager, IServerConfigurationManager configurationManager)
: base(logManager, configurationManager)
{
}
protected override bool RefreshOnVersionChange
{
get
{
return true;
}
}
protected override string ProviderVersion
{
get
{
return "2";
}
}
/// <summary>
/// Supportses the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public override bool Supports(BaseItem item)
{
if (item is Season)
{
var locationType = item.LocationType;
return locationType != LocationType.Virtual && locationType != LocationType.Remote;
}
return false;
}
/// <summary>
/// Fetches metadata and returns true or false indicating if any work that requires persistence was done
/// </summary>
/// <param name="item">The item.</param>
/// <param name="force">if set to <c>true</c> [force].</param>
/// <param name="providerInfo">The provider information.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.Boolean}.</returns>
public override Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken)
{
item.IndexNumber = TVUtils.GetSeasonNumberFromPath(item.Path);
SetLastRefreshed(item, DateTime.UtcNow, providerInfo);
return TrueTaskResult;
}
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override MetadataProviderPriority Priority
{
get { return MetadataProviderPriority.First; }
}
}
}

View File

@ -0,0 +1,58 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.TV
{
public class SeasonMetadataService : MetadataService<Season, ItemId>
{
private readonly ILibraryManager _libraryManager;
public SeasonMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager)
: base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem)
{
_libraryManager = libraryManager;
}
/// <summary>
/// Merges the specified source.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="target">The target.</param>
/// <param name="lockedFields">The locked fields.</param>
/// <param name="replaceData">if set to <c>true</c> [replace data].</param>
/// <param name="mergeMetadataSettings">if set to <c>true</c> [merge metadata settings].</param>
protected override void MergeData(Season source, Season target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
{
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
}
protected override Task SaveItem(Season item, ItemUpdateType reason, CancellationToken cancellationToken)
{
return _libraryManager.UpdateItem(item, reason, cancellationToken);
}
protected override ItemUpdateType BeforeMetadataRefresh(Season item)
{
var updateType = base.BeforeMetadataRefresh(item);
var currentIndexNumber = item.IndexNumber;
item.IndexNumber = item.IndexNumber ?? TVUtils.GetSeasonNumberFromPath(item.Path);
if ((currentIndexNumber ?? -1) != (item.IndexNumber ?? -1))
{
updateType = updateType | ItemUpdateType.MetadataImport;
}
return updateType;
}
}
}

View File

@ -1,97 +0,0 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.TV
{
/// <summary>
/// Class SeriesProviderFromXml
/// </summary>
public class SeasonProviderFromXml : BaseMetadataProvider
{
private readonly IFileSystem _fileSystem;
public SeasonProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
_fileSystem = fileSystem;
}
/// <summary>
/// Supportses the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public override bool Supports(BaseItem item)
{
return item is Season && item.LocationType == LocationType.FileSystem;
}
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override MetadataProviderPriority Priority
{
get { return MetadataProviderPriority.Second; }
}
private const string XmlFileName = "season.xml";
protected override bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo)
{
var xml = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, XmlFileName));
if (xml == null)
{
return false;
}
return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved;
}
/// <summary>
/// Fetches metadata and returns true or false indicating if any work that requires persistence was done
/// </summary>
/// <param name="item">The item.</param>
/// <param name="force">if set to <c>true</c> [force].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.Boolean}.</returns>
public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, XmlFileName));
if (metadataFile != null)
{
var path = metadataFile.FullName;
await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
new BaseItemXmlParser<Season>(Logger).Fetch((Season)item, path, cancellationToken);
}
finally
{
XmlParsingResourcePool.Release();
}
SetLastRefreshed(item, DateTime.UtcNow, providerInfo);
return true;
}
return false;
}
}
}

View File

@ -0,0 +1,63 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.TV
{
/// <summary>
/// Class SeriesProviderFromXml
/// </summary>
public class SeasonXmlProvider : BaseXmlProvider, ILocalMetadataProvider<Season>
{
private readonly ILogger _logger;
public SeasonXmlProvider(IFileSystem fileSystem, ILogger logger)
: base(fileSystem)
{
_logger = logger;
}
public async Task<MetadataResult<Season>> GetMetadata(string path, CancellationToken cancellationToken)
{
path = GetXmlFile(path).FullName;
var result = new MetadataResult<Season>();
await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
var person = new Season();
new BaseItemXmlParser<Season>(_logger).Fetch(person, path, cancellationToken);
result.HasMetadata = true;
result.Item = person;
}
catch (FileNotFoundException)
{
result.HasMetadata = false;
}
finally
{
XmlParsingResourcePool.Release();
}
return result;
}
public string Name
{
get { return "Media Browser Xml"; }
}
protected override FileInfo GetXmlFile(string path)
{
return new FileInfo(Path.Combine(path, "season.xml"));
}
}
}

View File

@ -1,4 +1,5 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
@ -19,16 +20,18 @@ using System.Xml;
namespace MediaBrowser.Providers.TV
{
public class ManualTvdbSeasonImageProvider : IRemoteImageProvider, IHasOrder
public class TvdbSeasonImageProvider : IRemoteImageProvider, IHasOrder, IHasChangeMonitor
{
private readonly IServerConfigurationManager _config;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IHttpClient _httpClient;
private readonly IFileSystem _fileSystem;
public ManualTvdbSeasonImageProvider(IServerConfigurationManager config, IHttpClient httpClient)
public TvdbSeasonImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
{
_config = config;
_httpClient = httpClient;
_fileSystem = fileSystem;
}
public string Name
@ -63,14 +66,17 @@ namespace MediaBrowser.Providers.TV
return images.Where(i => i.Type == imageType);
}
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
public async Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{
var season = (Season)item;
var series = season.Series;
var seriesId = season.Series != null ? season.Series.GetProviderId(MetadataProviders.Tvdb) : null;
var seriesId = series != null ? series.GetProviderId(MetadataProviders.Tvdb) : null;
if (!string.IsNullOrEmpty(seriesId) && season.IndexNumber.HasValue)
{
await TvdbSeriesProvider.Current.EnsureSeriesInfo(seriesId, series.GetPreferredMetadataLanguage(), cancellationToken).ConfigureAwait(false);
// Process images
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId);
@ -78,9 +84,7 @@ namespace MediaBrowser.Providers.TV
try
{
var result = GetImages(path, item.GetPreferredMetadataLanguage(), season.IndexNumber.Value, cancellationToken);
return Task.FromResult(result);
return GetImages(path, item.GetPreferredMetadataLanguage(), season.IndexNumber.Value, cancellationToken);
}
catch (FileNotFoundException)
{
@ -88,7 +92,7 @@ namespace MediaBrowser.Providers.TV
}
}
return Task.FromResult<IEnumerable<RemoteImageInfo>>(new RemoteImageInfo[] { });
return new RemoteImageInfo[] { };
}
private IEnumerable<RemoteImageInfo> GetImages(string xmlPath, string preferredLanguage, int seasonNumber, CancellationToken cancellationToken)
@ -335,5 +339,30 @@ namespace MediaBrowser.Providers.TV
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
});
}
public bool HasChanged(IHasMetadata item, DateTime date)
{
var season = (Season)item;
var series = season.Series;
if (series == null)
{
return false;
}
var tvdbId = series.GetProviderId(MetadataProviders.Tvdb);
if (!String.IsNullOrEmpty(tvdbId))
{
// Process images
var imagesXmlPath = Path.Combine(TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, tvdbId), "banners.xml");
var fileInfo = new FileInfo(imagesXmlPath);
return fileInfo.Exists && _fileSystem.GetLastWriteTimeUtc(fileInfo) > date;
}
return false;
}
}
}

View File

@ -1,211 +0,0 @@
using System.Net;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.TV
{
/// <summary>
/// Class RemoteSeasonProvider
/// </summary>
class TvdbSeasonProvider : BaseMetadataProvider
{
/// <summary>
/// The _provider manager
/// </summary>
private readonly IProviderManager _providerManager;
private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="TvdbSeasonProvider"/> class.
/// </summary>
/// <param name="logManager">The log manager.</param>
/// <param name="configurationManager">The configuration manager.</param>
/// <param name="providerManager">The provider manager.</param>
/// <exception cref="System.ArgumentNullException">httpClient</exception>
public TvdbSeasonProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
_providerManager = providerManager;
_fileSystem = fileSystem;
}
/// <summary>
/// Supportses the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public override bool Supports(BaseItem item)
{
return item is Season;
}
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override MetadataProviderPriority Priority
{
// Run after fanart
get { return MetadataProviderPriority.Fourth; }
}
/// <summary>
/// Gets a value indicating whether [requires internet].
/// </summary>
/// <value><c>true</c> if [requires internet]; otherwise, <c>false</c>.</value>
public override bool RequiresInternet
{
get
{
return true;
}
}
public override ItemUpdateType ItemUpdateType
{
get
{
return ItemUpdateType.ImageUpdate;
}
}
/// <summary>
/// Gets a value indicating whether [refresh on version change].
/// </summary>
/// <value><c>true</c> if [refresh on version change]; otherwise, <c>false</c>.</value>
protected override bool RefreshOnVersionChange
{
get
{
return true;
}
}
/// <summary>
/// Gets the provider version.
/// </summary>
/// <value>The provider version.</value>
protected override string ProviderVersion
{
get
{
return "2";
}
}
protected override bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo)
{
var season = (Season)item;
var seriesId = season.Series != null ? season.Series.GetProviderId(MetadataProviders.Tvdb) : null;
if (!string.IsNullOrEmpty(seriesId))
{
// Process images
var imagesXmlPath = Path.Combine(TvdbSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId), "banners.xml");
var imagesFileInfo = new FileInfo(imagesXmlPath);
if (imagesFileInfo.Exists)
{
return _fileSystem.GetLastWriteTimeUtc(imagesFileInfo) > providerInfo.LastRefreshed;
}
}
return false;
}
protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
{
if (item.HasImage(ImageType.Primary) && item.HasImage(ImageType.Banner) && item.BackdropImagePaths.Count > 0)
{
return false;
}
return base.NeedsRefreshInternal(item, providerInfo);
}
/// <summary>
/// Fetches metadata and returns true or false indicating if any work that requires persistence was done
/// </summary>
/// <param name="item">The item.</param>
/// <param name="force">if set to <c>true</c> [force].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.Boolean}.</returns>
public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualTvdbSeasonImageProvider.ProviderName).ConfigureAwait(false);
await DownloadImages(item, images.ToList(), cancellationToken).ConfigureAwait(false);
SetLastRefreshed(item, DateTime.UtcNow, providerInfo);
return true;
}
private async Task DownloadImages(BaseItem item, List<RemoteImageInfo> images, CancellationToken cancellationToken)
{
var options = ConfigurationManager.Configuration.GetMetadataOptions("Season") ?? new MetadataOptions();
var backdropLimit = options.GetLimit(ImageType.Backdrop);
if (!item.LockedFields.Contains(MetadataFields.Images))
{
if (!item.HasImage(ImageType.Primary))
{
await SaveImage(item, images, ImageType.Primary, cancellationToken).ConfigureAwait(false);
}
if (options.IsEnabled(ImageType.Banner) && !item.HasImage(ImageType.Banner))
{
await SaveImage(item, images, ImageType.Banner, cancellationToken).ConfigureAwait(false);
}
}
if (options.IsEnabled(ImageType.Backdrop) && item.BackdropImagePaths.Count < backdropLimit && !item.LockedFields.Contains(MetadataFields.Backdrops))
{
foreach (var backdrop in images.Where(i => i.Type == ImageType.Backdrop))
{
var url = backdrop.Url;
await _providerManager.SaveImage(item, url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, null, cancellationToken).ConfigureAwait(false);
if (item.BackdropImagePaths.Count >= backdropLimit) break;
}
}
}
private async Task SaveImage(BaseItem item, List<RemoteImageInfo> images, ImageType type, CancellationToken cancellationToken)
{
foreach (var image in images.Where(i => i.Type == type))
{
try
{
await _providerManager.SaveImage(item, image.Url, TvdbSeriesProvider.Current.TvDbResourcePool, type, null, cancellationToken).ConfigureAwait(false);
break;
}
catch (HttpException ex)
{
// Sometimes fanart has bad url's in their xml
if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound)
{
continue;
}
break;
}
}
}
}
}

View File

@ -324,6 +324,26 @@ namespace MediaBrowser.Providers.TV
await ExtractEpisodes(seriesDataPath, Path.Combine(seriesDataPath, preferredMetadataLanguage + ".xml"), lastTvDbUpdateTime).ConfigureAwait(false);
}
internal async Task EnsureSeriesInfo(string seriesId, string preferredMetadataLanguage, CancellationToken cancellationToken)
{
var seriesDataPath = GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId);
Directory.CreateDirectory(seriesDataPath);
var files = Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.TopDirectoryOnly)
.Select(Path.GetFileName)
.ToList();
var seriesXmlFilename = preferredMetadataLanguage + ".xml";
// Only download if not already there
// The prescan task will take care of updates so we don't need to re-download here
if (!files.Contains("banners.xml", StringComparer.OrdinalIgnoreCase) || !files.Contains("actors.xml", StringComparer.OrdinalIgnoreCase) || !files.Contains(seriesXmlFilename, StringComparer.OrdinalIgnoreCase))
{
await DownloadSeriesZip(seriesId, seriesDataPath, null, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
}
}
private void DeleteXmlFiles(string path)
{
try

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
<version>3.0.317</version>
<version>3.0.318</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.317" />
<dependency id="MediaBrowser.Common" version="3.0.318" />
<dependency id="NLog" version="2.1.0" />
<dependency id="SimpleInjector" version="2.4.1" />
<dependency id="sharpcompress" version="0.10.2" />

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
<version>3.0.317</version>
<version>3.0.318</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
<version>3.0.317</version>
<version>3.0.318</version>
<title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.317" />
<dependency id="MediaBrowser.Common" version="3.0.318" />
</dependencies>
</metadata>
<files>