mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-15 09:59:06 -07:00
converted season providers
This commit is contained in:
parent
6261f157f3
commit
30ebfab8e0
@ -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)
|
||||
{
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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" />
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Savers
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Media Browser xml";
|
||||
return "Media Browser Xml";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.Savers
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Media Browser xml";
|
||||
return "Media Browser Xml";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.Savers
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Media Browser xml";
|
||||
return "Media Browser Xml";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.Savers
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Media Browser xml";
|
||||
return "Media Browser Xml";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ namespace MediaBrowser.Providers.Savers
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Media Browser xml";
|
||||
return "Media Browser Xml";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.Savers
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Media Browser xml";
|
||||
return "Media Browser Xml";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.Savers
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Media Browser xml";
|
||||
return "Media Browser Xml";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace MediaBrowser.Providers.Savers
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Media Browser xml";
|
||||
return "Media Browser Xml";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ namespace MediaBrowser.Providers.Savers
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Media Browser xml";
|
||||
return "Media Browser Xml";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Savers
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Media Browser xml";
|
||||
return "Media Browser Xml";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Savers
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Media Browser xml";
|
||||
return "Media Browser Xml";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ namespace MediaBrowser.Providers.Savers
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Media Browser xml";
|
||||
return "Media Browser Xml";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
58
MediaBrowser.Providers/TV/SeasonMetadataService.cs
Normal file
58
MediaBrowser.Providers/TV/SeasonMetadataService.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
63
MediaBrowser.Providers/TV/SeasonXmlProvider.cs
Normal file
63
MediaBrowser.Providers/TV/SeasonXmlProvider.cs
Normal 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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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" />
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user