Merge pull request #1778 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2016-05-24 22:11:52 -04:00
commit a4260a2cbc
37 changed files with 93 additions and 1423 deletions

View File

@ -159,6 +159,7 @@ namespace MediaBrowser.Api.Subtitles
builder.AppendLine("#EXT-X-TARGETDURATION:" + request.SegmentLength.ToString(CultureInfo.InvariantCulture));
builder.AppendLine("#EXT-X-VERSION:3");
builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
builder.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
long positionTicks = 0;
var segmentLengthTicks = TimeSpan.FromSeconds(request.SegmentLength).Ticks;
@ -170,7 +171,7 @@ namespace MediaBrowser.Api.Subtitles
var remaining = runtime - positionTicks;
var lengthTicks = Math.Min(remaining, segmentLengthTicks);
builder.AppendLine("#EXTINF:" + TimeSpan.FromTicks(lengthTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture));
builder.AppendLine("#EXTINF:" + TimeSpan.FromTicks(lengthTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture) + ",");
var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks);

View File

@ -456,7 +456,16 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException("No series exists with Id " + request.Id);
}
episodes = series.GetEpisodes(user, request.Season.Value);
var season = series.GetSeasons(user).FirstOrDefault(i => i.IndexNumber == request.Season.Value);
if (season == null)
{
episodes = new List<Episode>();
}
else
{
episodes = series.GetEpisodes(user, season);
}
}
else
{

View File

@ -1031,9 +1031,7 @@ namespace MediaBrowser.Controller.Entities
}
: options;
var result = await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
return result;
return await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
}
[IgnoreDataMember]

View File

@ -461,17 +461,15 @@ namespace MediaBrowser.Controller.Entities
foreach (var item in itemsRemoved)
{
if (item.LocationType == LocationType.Virtual ||
item.LocationType == LocationType.Remote)
var itemLocationType = item.LocationType;
if (itemLocationType == LocationType.Virtual ||
itemLocationType == LocationType.Remote)
{
// Don't remove these because there's no way to accurately validate them.
validChildren.Add(item);
}
else if (!string.IsNullOrEmpty(item.Path) && IsPathOffline(item.Path))
{
await UpdateIsOffline(item, true).ConfigureAwait(false);
validChildren.Add(item);
}
else
{

View File

@ -205,7 +205,7 @@ namespace MediaBrowser.Controller.Entities.TV
if (IndexNumber.HasValue && series != null)
{
return series.GetEpisodes(user, IndexNumber.Value, includeMissingEpisodes, includeVirtualUnairedEpisodes);
return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes);
}
var episodes = GetRecursiveChildren(user)

View File

@ -338,11 +338,11 @@ namespace MediaBrowser.Controller.Entities.TV
progress.Report(100);
}
public IEnumerable<Episode> GetEpisodes(User user, int seasonNumber)
public IEnumerable<Episode> GetEpisodes(User user, Season season)
{
var config = user.Configuration;
return GetEpisodes(user, seasonNumber, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
return GetEpisodes(user, season, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
}
private bool EnablePooling()
@ -350,7 +350,7 @@ namespace MediaBrowser.Controller.Entities.TV
return false;
}
public IEnumerable<Episode> GetEpisodes(User user, int seasonNumber, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
{
IEnumerable<Episode> episodes;
@ -388,7 +388,7 @@ namespace MediaBrowser.Controller.Entities.TV
}).Cast<Episode>();
}
episodes = FilterEpisodesBySeason(episodes, seasonNumber, DisplaySpecialsWithSeasons);
episodes = FilterEpisodesBySeason(episodes, parentSeason, DisplaySpecialsWithSeasons);
if (!includeMissingEpisodes)
{
@ -399,7 +399,7 @@ namespace MediaBrowser.Controller.Entities.TV
episodes = episodes.Where(i => !i.IsVirtualUnaired);
}
var sortBy = seasonNumber == 0 ? ItemSortBy.SortName : ItemSortBy.AiredEpisodeOrder;
var sortBy = (parentSeason.IndexNumber ?? -1) == 0 ? ItemSortBy.SortName : ItemSortBy.AiredEpisodeOrder;
return LibraryManager.Sort(episodes, user, new[] { sortBy }, SortOrder.Ascending)
.Cast<Episode>();
@ -408,10 +408,6 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// Filters the episodes by season.
/// </summary>
/// <param name="episodes">The episodes.</param>
/// <param name="seasonNumber">The season number.</param>
/// <param name="includeSpecials">if set to <c>true</c> [include specials].</param>
/// <returns>IEnumerable{Episode}.</returns>
public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials)
{
if (!includeSpecials || seasonNumber < 1)
@ -434,6 +430,55 @@ namespace MediaBrowser.Controller.Entities.TV
});
}
/// <summary>
/// Filters the episodes by season.
/// </summary>
public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, Season parentSeason, bool includeSpecials)
{
var seasonNumber = parentSeason.IndexNumber;
if (!includeSpecials || (seasonNumber.HasValue && seasonNumber.Value == 0))
{
var seasonPresentationKey = parentSeason.PresentationUniqueKey;
return episodes.Where(i =>
{
if ((i.ParentIndexNumber ?? -1) == seasonNumber)
{
return true;
}
if (!i.ParentIndexNumber.HasValue)
{
var season = i.Season;
return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
}
return false;
});
}
else
{
var seasonPresentationKey = parentSeason.PresentationUniqueKey;
return episodes.Where(episode =>
{
var currentSeasonNumber = episode.AiredSeasonNumber;
if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value)
{
return true;
}
if (!episode.ParentIndexNumber.HasValue)
{
var season = episode.Season;
return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
}
return false;
});
}
}
protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Series);

View File

@ -230,12 +230,6 @@
<Compile Include="..\MediaBrowser.Model\Configuration\SubtitlePlaybackMode.cs">
<Link>Configuration\SubtitlePlaybackMode.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\TheMovieDbOptions.cs">
<Link>Configuration\TheMovieDbOptions.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\TvdbOptions.cs">
<Link>Configuration\TvdbOptions.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\UnratedItem.cs">
<Link>Configuration\UnratedItem.cs</Link>
</Compile>

View File

@ -204,12 +204,6 @@
<Compile Include="..\MediaBrowser.Model\Configuration\SubtitlePlaybackMode.cs">
<Link>Configuration\SubtitlePlaybackMode.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\TheMovieDbOptions.cs">
<Link>Configuration\TheMovieDbOptions.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\TvdbOptions.cs">
<Link>Configuration\TvdbOptions.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\UnratedItem.cs">
<Link>Configuration\UnratedItem.cs</Link>
</Compile>

View File

@ -3,11 +3,6 @@ namespace MediaBrowser.Model.Configuration
{
public class FanartOptions
{
/// <summary>
/// Gets or sets a value indicating whether [enable automatic updates].
/// </summary>
/// <value><c>true</c> if [enable automatic updates]; otherwise, <c>false</c>.</value>
public bool EnableAutomaticUpdates { get; set; }
/// <summary>
/// Gets or sets the user API key.
/// </summary>

View File

@ -1,12 +0,0 @@

namespace MediaBrowser.Model.Configuration
{
public class TheMovieDbOptions
{
/// <summary>
/// Gets or sets a value indicating whether [enable automatic updates].
/// </summary>
/// <value><c>true</c> if [enable automatic updates]; otherwise, <c>false</c>.</value>
public bool EnableAutomaticUpdates { get; set; }
}
}

View File

@ -1,12 +0,0 @@

namespace MediaBrowser.Model.Configuration
{
public class TvdbOptions
{
/// <summary>
/// Gets or sets a value indicating whether [enable automatic updates].
/// </summary>
/// <value><c>true</c> if [enable automatic updates]; otherwise, <c>false</c>.</value>
public bool EnableAutomaticUpdates { get; set; }
}
}

View File

@ -97,8 +97,6 @@
<Compile Include="Configuration\FanartOptions.cs" />
<Compile Include="Configuration\MetadataConfiguration.cs" />
<Compile Include="Configuration\PeopleMetadataOptions.cs" />
<Compile Include="Configuration\TheMovieDbOptions.cs" />
<Compile Include="Configuration\TvdbOptions.cs" />
<Compile Include="Configuration\XbmcMetadataOptions.cs" />
<Compile Include="Configuration\SubtitlePlaybackMode.cs" />
<Compile Include="Connect\ConnectAuthenticationExchangeResult.cs" />

View File

@ -1,165 +0,0 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using MediaBrowser.Providers.Genres;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.Folders
{
public class DefaultImageProvider : IRemoteImageProvider, IHasItemChangeMonitor
{
private readonly IHttpClient _httpClient;
public DefaultImageProvider(IHttpClient httpClient)
{
_httpClient = httpClient;
}
public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
{
return new List<ImageType>
{
ImageType.Primary
};
}
public Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken)
{
var view = item as UserView;
if (view != null)
{
return GetImages(view.ViewType, cancellationToken);
}
var folder = (ICollectionFolder)item;
return GetImages(folder.CollectionType, cancellationToken);
}
private Task<IEnumerable<RemoteImageInfo>> GetImages(string viewType, CancellationToken cancellationToken)
{
var url = GetImageUrl(viewType);
var list = new List<RemoteImageInfo>();
if (!string.IsNullOrWhiteSpace(url))
{
list.AddRange(new List<RemoteImageInfo>{
new RemoteImageInfo
{
ProviderName = Name,
Url = url,
Type = ImageType.Primary
}
});
}
return Task.FromResult<IEnumerable<RemoteImageInfo>>(list);
}
private string GetImageUrl(string viewType)
{
const string urlPrefix = "https://raw.githubusercontent.com/MediaBrowser/Emby.Resources/master/images/folders/";
if (string.Equals(viewType, CollectionType.Books, StringComparison.OrdinalIgnoreCase))
{
return urlPrefix + "books.jpg";
}
if (string.Equals(viewType, CollectionType.Games, StringComparison.OrdinalIgnoreCase))
{
return urlPrefix + "games.jpg";
}
if (string.Equals(viewType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "music.jpg";
}
if (string.Equals(viewType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "photos.png";
}
if (string.Equals(viewType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "tv.jpg";
}
if (string.Equals(viewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase))
{
return urlPrefix + "channels.jpg";
}
if (string.Equals(viewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
{
return urlPrefix + "livetv.png";
}
if (string.Equals(viewType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "movies.jpg";
}
if (string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
{
return urlPrefix + "playlists.jpg";
}
if (string.Equals(viewType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "homevideos.jpg";
}
if (string.Equals(viewType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
{
return urlPrefix + "musicvideos.jpg";
}
if (string.Equals(viewType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "collections.jpg";
}
if (string.IsNullOrWhiteSpace(viewType))
{
//return urlPrefix + "generic.jpg";
}
return null;
}
public string Name
{
get { return "Default Image Provider"; }
}
public bool Supports(IHasImages item)
{
var view = item as UserView;
if (view != null)
{
return !string.IsNullOrWhiteSpace(GetImageUrl(view.ViewType));
}
var folder = item as ICollectionFolder;
if (folder != null)
{
return !string.IsNullOrWhiteSpace(GetImageUrl(folder.CollectionType));
}
return false;
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
Url = url,
ResourcePool = GenreImageProvider.ImageDownloadResourcePool
});
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
return GetSupportedImages(item).Any(i => !item.HasImage(i));
}
}
}

View File

@ -422,12 +422,6 @@ namespace MediaBrowser.Providers.Manager
providers = providers
.Where(i =>
{
var hasChangeMonitor = i as IHasChangeMonitor;
if (hasChangeMonitor != null)
{
return HasChanged(item, hasChangeMonitor, dateLastImageRefresh, options.DirectoryService);
}
var hasFileChangeMonitor = i as IHasItemChangeMonitor;
if (hasFileChangeMonitor != null)
{

View File

@ -89,7 +89,6 @@
<Compile Include="Channels\ChannelMetadataService.cs" />
<Compile Include="Chapters\ChapterManager.cs" />
<Compile Include="Folders\CollectionFolderMetadataService.cs" />
<Compile Include="Folders\DefaultImageProvider.cs" />
<Compile Include="Folders\FolderMetadataService.cs" />
<Compile Include="Folders\UserViewMetadataService.cs" />
<Compile Include="GameGenres\GameGenreMetadataService.cs" />
@ -145,10 +144,7 @@
<Compile Include="Omdb\OmdbProvider.cs" />
<Compile Include="Omdb\OmdbItemProvider.cs" />
<Compile Include="People\MovieDbPersonImageProvider.cs" />
<Compile Include="Movies\MovieUpdatesPrescanTask.cs" />
<Compile Include="Movies\FanArtMovieUpdatesPostScanTask.cs" />
<Compile Include="Movies\MovieDbProvider.cs" />
<Compile Include="Music\FanArtUpdatesPostScanTask.cs" />
<Compile Include="Music\FanArtAlbumProvider.cs" />
<Compile Include="Music\FanArtArtistProvider.cs" />
<Compile Include="Music\MusicBrainzAlbumProvider.cs" />
@ -168,7 +164,6 @@
<Compile Include="Subtitles\SubtitleManager.cs" />
<Compile Include="TV\DummySeasonProvider.cs" />
<Compile Include="TV\EpisodeMetadataService.cs" />
<Compile Include="TV\FanArt\FanArtTvUpdatesPostScanTask.cs" />
<Compile Include="TV\FanArt\FanArtSeasonProvider.cs" />
<Compile Include="TV\FanArt\FanartSeriesProvider.cs" />
<Compile Include="TV\MissingEpisodeProvider.cs" />

View File

@ -1,196 +0,0 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Music;
using MediaBrowser.Providers.TV;
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 CommonIO;
namespace MediaBrowser.Providers.Movies
{
class FanartMovieUpdatesPostScanTask : ILibraryPostScanTask
{
private const string UpdatesUrl = "https://webservice.fanart.tv/v3/movies/latest?api_key={0}&date={1}";
/// <summary>
/// The _HTTP client
/// </summary>
private readonly IHttpClient _httpClient;
/// <summary>
/// The _logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// The _config
/// </summary>
private readonly IServerConfigurationManager _config;
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
public FanartMovieUpdatesPostScanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_config = config;
_logger = logger;
_httpClient = httpClient;
_fileSystem = fileSystem;
}
/// <summary>
/// Runs the specified progress.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{
var options = FanartSeriesProvider.Current.GetFanartOptions();
if (!options.EnableAutomaticUpdates)
{
progress.Report(100);
return;
}
var path = FanartMovieImageProvider.GetMoviesDataPath(_config.CommonApplicationPaths);
_fileSystem.CreateDirectory(path);
var timestampFile = Path.Combine(path, "time.txt");
var timestampFileInfo = _fileSystem.GetFileInfo(timestampFile);
// Don't check for updates every single time
if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 3)
{
return;
}
// Find out the last time we queried for updates
var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList();
// If this is our first time, don't do any updates and just record the timestamp
if (!string.IsNullOrEmpty(lastUpdateTime))
{
var moviesToUpdate = await GetMovieIdsToUpdate(existingDirectories, lastUpdateTime, options, cancellationToken).ConfigureAwait(false);
progress.Report(5);
await UpdateMovies(moviesToUpdate, progress, cancellationToken).ConfigureAwait(false);
}
var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture);
_fileSystem.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
progress.Report(100);
}
private async Task<IEnumerable<string>> GetMovieIdsToUpdate(IEnumerable<string> existingIds, string lastUpdateTime, FanartOptions options, CancellationToken cancellationToken)
{
var url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime);
var clientKey = options.UserApiKey;
if (!string.IsNullOrWhiteSpace(clientKey))
{
url += "&client_key=" + clientKey;
}
// First get last time
using (var stream = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
EnableHttpCompression = true,
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool
}).ConfigureAwait(false))
{
using (var reader = new StreamReader(stream))
{
var json = await reader.ReadToEndAsync().ConfigureAwait(false);
// If empty fanart will return a string of "null", rather than an empty list
if (string.Equals(json, "null", StringComparison.OrdinalIgnoreCase))
{
return new List<string>();
}
var updates = _jsonSerializer.DeserializeFromString<List<RootObject>>(json);
var existingDictionary = existingIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
return updates.SelectMany(i =>
{
var list = new List<string>();
if (!string.IsNullOrWhiteSpace(i.imdb_id))
{
list.Add(i.imdb_id);
}
if (!string.IsNullOrWhiteSpace(i.tmdb_id))
{
list.Add(i.tmdb_id);
}
return list;
}).Where(existingDictionary.ContainsKey);
}
}
}
private async Task UpdateMovies(IEnumerable<string> idList, IProgress<double> progress, CancellationToken cancellationToken)
{
var list = idList.ToList();
var numComplete = 0;
foreach (var id in list)
{
_logger.Info("Updating movie " + id);
await FanartMovieImageProvider.Current.DownloadMovieJson(id, cancellationToken).ConfigureAwait(false);
numComplete++;
double percent = numComplete;
percent /= list.Count;
percent *= 95;
progress.Report(percent + 5);
}
}
/// <summary>
/// Dates the time to unix timestamp.
/// </summary>
/// <param name="dateTime">The date time.</param>
/// <returns>System.Double.</returns>
private static double DateTimeToUnixTimestamp(DateTime dateTime)
{
return (dateTime - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds;
}
public class RootObject
{
public string tmdb_id { get; set; }
public string imdb_id { get; set; }
public string name { get; set; }
public string new_images { get; set; }
public string total_images { get; set; }
}
}
}

View File

@ -24,7 +24,7 @@ using MediaBrowser.Providers.TV;
namespace MediaBrowser.Providers.Movies
{
public class FanartMovieImageProvider : IRemoteImageProvider, IHasItemChangeMonitor, IHasOrder
public class FanartMovieImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IServerConfigurationManager _config;
@ -241,33 +241,6 @@ namespace MediaBrowser.Providers.Movies
});
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
var options = FanartSeriesProvider.Current.GetFanartOptions();
if (!options.EnableAutomaticUpdates)
{
return false;
}
var id = item.GetProviderId(MetadataProviders.Tmdb);
if (string.IsNullOrEmpty(id))
{
id = item.GetProviderId(MetadataProviders.Imdb);
}
if (!string.IsNullOrEmpty(id))
{
// Process images
var path = GetFanartJsonPath(id);
var fileInfo = _fileSystem.GetFileInfo(path);
return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed;
}
return false;
}
/// <summary>
/// Gets the movie data path.
/// </summary>

View File

@ -17,7 +17,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.Movies
{
class MovieDbImageProvider : IRemoteImageProvider, IHasOrder, IHasItemChangeMonitor
class MovieDbImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
@ -221,10 +221,5 @@ namespace MediaBrowser.Providers.Movies
ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
});
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
return MovieDbProvider.Current.HasChanged(item);
}
}
}

View File

@ -409,33 +409,6 @@ namespace MediaBrowser.Providers.Movies
return await _httpClient.Get(options).ConfigureAwait(false);
}
public TheMovieDbOptions GetTheMovieDbOptions()
{
return _configurationManager.GetConfiguration<TheMovieDbOptions>("themoviedb");
}
public bool HasChanged(IHasMetadata item)
{
if (!GetTheMovieDbOptions().EnableAutomaticUpdates)
{
return false;
}
var tmdbId = item.GetProviderId(MetadataProviders.Tmdb);
if (!String.IsNullOrEmpty(tmdbId))
{
// Process images
var dataFilePath = GetDataFilePath(tmdbId, item.GetPreferredMetadataLanguage());
var fileInfo = _fileSystem.GetFileInfo(dataFilePath);
return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed;
}
return false;
}
public void Dispose()
{
Dispose(true);
@ -659,19 +632,4 @@ namespace MediaBrowser.Providers.Movies
});
}
}
public class TmdbConfigStore : IConfigurationFactory
{
public IEnumerable<ConfigurationStore> GetConfigurations()
{
return new List<ConfigurationStore>
{
new ConfigurationStore
{
Key = "themoviedb",
ConfigurationType = typeof(TheMovieDbOptions)
}
};
}
}
}

View File

@ -33,11 +33,6 @@ namespace MediaBrowser.Providers.Movies
get { return MovieDbProvider.Current.Name; }
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
return MovieDbProvider.Current.HasChanged(item);
}
public int Order
{
get

View File

@ -1,249 +0,0 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
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 CommonIO;
namespace MediaBrowser.Providers.Movies
{
public class MovieUpdatesPreScanTask : ILibraryPostScanTask
{
/// <summary>
/// The updates URL
/// </summary>
private const string UpdatesUrl = "https://api.themoviedb.org/3/movie/changes?start_date={0}&api_key={1}&page={2}";
/// <summary>
/// The _HTTP client
/// </summary>
private readonly IHttpClient _httpClient;
/// <summary>
/// The _logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// The _config
/// </summary>
private readonly IServerConfigurationManager _config;
private readonly IJsonSerializer _json;
private readonly IFileSystem _fileSystem;
private readonly ILibraryManager _libraryManager;
/// <summary>
/// Initializes a new instance of the <see cref="MovieUpdatesPreScanTask"/> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="httpClient">The HTTP client.</param>
/// <param name="config">The config.</param>
/// <param name="json">The json.</param>
public MovieUpdatesPreScanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IJsonSerializer json, IFileSystem fileSystem, ILibraryManager libraryManager)
{
_logger = logger;
_httpClient = httpClient;
_config = config;
_json = json;
_fileSystem = fileSystem;
_libraryManager = libraryManager;
}
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
/// <summary>
/// Runs the specified progress.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{
if (!MovieDbProvider.Current.GetTheMovieDbOptions().EnableAutomaticUpdates)
{
progress.Report(100);
return;
}
var path = MovieDbProvider.GetMoviesDataPath(_config.CommonApplicationPaths);
_fileSystem.CreateDirectory(path);
var timestampFile = Path.Combine(path, "time.txt");
var timestampFileInfo = _fileSystem.GetFileInfo(timestampFile);
// Don't check for updates every single time
if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 7)
{
return;
}
// Find out the last time we queried tvdb for updates
var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList();
if (!string.IsNullOrEmpty(lastUpdateTime))
{
long lastUpdateTicks;
if (long.TryParse(lastUpdateTime, NumberStyles.Any, UsCulture, out lastUpdateTicks))
{
var lastUpdateDate = new DateTime(lastUpdateTicks, DateTimeKind.Utc);
// They only allow up to 14 days of updates
if ((DateTime.UtcNow - lastUpdateDate).TotalDays > 13)
{
lastUpdateDate = DateTime.UtcNow.AddDays(-13);
}
var updatedIds = await GetIdsToUpdate(lastUpdateDate, 1, cancellationToken).ConfigureAwait(false);
var existingDictionary = existingDirectories.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
var idsToUpdate = updatedIds.Where(i => !string.IsNullOrWhiteSpace(i) && existingDictionary.ContainsKey(i));
await UpdateMovies(idsToUpdate, progress, cancellationToken).ConfigureAwait(false);
}
}
_fileSystem.WriteAllText(timestampFile, DateTime.UtcNow.Ticks.ToString(UsCulture), Encoding.UTF8);
progress.Report(100);
}
/// <summary>
/// Gets the ids to update.
/// </summary>
/// <param name="lastUpdateTime">The last update time.</param>
/// <param name="page">The page.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{System.String}}.</returns>
private async Task<IEnumerable<string>> GetIdsToUpdate(DateTime lastUpdateTime, int page, CancellationToken cancellationToken)
{
bool hasMorePages;
var list = new List<string>();
// First get last time
using (var stream = await _httpClient.Get(new HttpRequestOptions
{
Url = string.Format(UpdatesUrl, lastUpdateTime.ToString("yyyy-MM-dd"), MovieDbProvider.ApiKey, page),
CancellationToken = cancellationToken,
EnableHttpCompression = true,
ResourcePool = MovieDbProvider.Current.MovieDbResourcePool,
AcceptHeader = MovieDbProvider.AcceptHeader
}).ConfigureAwait(false))
{
var obj = _json.DeserializeFromStream<RootObject>(stream);
var data = obj.results.Select(i => i.id.ToString(UsCulture));
list.AddRange(data);
hasMorePages = page < obj.total_pages;
}
if (hasMorePages)
{
var more = await GetIdsToUpdate(lastUpdateTime, page + 1, cancellationToken).ConfigureAwait(false);
list.AddRange(more);
}
return list;
}
/// <summary>
/// Updates the movies.
/// </summary>
/// <param name="ids">The ids.</param>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private async Task UpdateMovies(IEnumerable<string> ids, IProgress<double> progress, CancellationToken cancellationToken)
{
var list = ids.ToList();
var numComplete = 0;
// Gather all movies into a lookup by tmdb id
var allMovies = _libraryManager.GetItemList(new Controller.Entities.InternalItemsQuery
{
IncludeItemTypes = new[] {typeof (Movie).Name},
Recursive = true
}).Where(i => !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tmdb)))
.ToLookup(i => i.GetProviderId(MetadataProviders.Tmdb));
foreach (var id in list)
{
// Find the preferred language(s) for the movie in the library
var languages = allMovies[id]
.Select(i => i.GetPreferredMetadataLanguage())
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
foreach (var language in languages)
{
try
{
await UpdateMovie(id, language, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error updating tmdb movie id {0}, language {1}", ex, id, language);
}
}
numComplete++;
double percent = numComplete;
percent /= list.Count;
percent *= 100;
progress.Report(percent);
}
}
/// <summary>
/// Updates the movie.
/// </summary>
/// <param name="id">The id.</param>
/// <param name="preferredMetadataLanguage">The preferred metadata language.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private Task UpdateMovie(string id, string preferredMetadataLanguage, CancellationToken cancellationToken)
{
_logger.Info("Updating movie from tmdb " + id + ", language " + preferredMetadataLanguage);
return MovieDbProvider.Current.DownloadMovieInfo(id, preferredMetadataLanguage, cancellationToken);
}
class Result
{
public int id { get; set; }
public bool? adult { get; set; }
}
class RootObject
{
public List<Result> results { get; set; }
public int page { get; set; }
public int total_pages { get; set; }
public int total_results { get; set; }
public RootObject()
{
results = new List<Result>();
}
}
}
}

View File

@ -19,7 +19,7 @@ using MediaBrowser.Model.Serialization;
namespace MediaBrowser.Providers.Music
{
public class FanartAlbumProvider : IRemoteImageProvider, IHasItemChangeMonitor, IHasOrder
public class FanartAlbumProvider : IRemoteImageProvider, IHasOrder
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IServerConfigurationManager _config;
@ -212,34 +212,5 @@ namespace MediaBrowser.Providers.Music
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool
});
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
var options = FanartSeriesProvider.Current.GetFanartOptions();
if (!options.EnableAutomaticUpdates)
{
return false;
}
var album = (MusicAlbum)item;
var artist = album.MusicArtist;
if (artist != null)
{
var artistMusicBrainzId = artist.GetProviderId(MetadataProviders.MusicBrainzArtist);
if (!String.IsNullOrEmpty(artistMusicBrainzId))
{
// Process images
var artistJsonPath = FanartArtistProvider.GetArtistJsonPath(_config.CommonApplicationPaths, artistMusicBrainzId);
var fileInfo = _fileSystem.GetFileInfo(artistJsonPath);
return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed;
}
}
return false;
}
}
}

View File

@ -22,7 +22,7 @@ using MediaBrowser.Model.Serialization;
namespace MediaBrowser.Providers.Music
{
public class FanartArtistProvider : IRemoteImageProvider, IHasItemChangeMonitor, IHasOrder
public class FanartArtistProvider : IRemoteImageProvider, IHasOrder
{
internal readonly SemaphoreSlim FanArtResourcePool = new SemaphoreSlim(3, 3);
internal const string ApiKey = "5c6b04c68e904cfed1e6cbc9a9e683d4";
@ -207,29 +207,6 @@ namespace MediaBrowser.Providers.Music
});
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
var options = FanartSeriesProvider.Current.GetFanartOptions();
if (!options.EnableAutomaticUpdates)
{
return false;
}
var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
if (!String.IsNullOrEmpty(id))
{
// Process images
var artistJsonPath = GetArtistJsonPath(_config.CommonApplicationPaths, id);
var fileInfo = _fileSystem.GetFileInfo(artistJsonPath);
return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed;
}
return false;
}
private readonly Task _cachedTask = Task.FromResult(true);
internal Task EnsureArtistJson(string musicBrainzId, CancellationToken cancellationToken)
{

View File

@ -1,203 +0,0 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
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 CommonIO;
using MediaBrowser.Providers.TV;
namespace MediaBrowser.Providers.Music
{
class FanartUpdatesPostScanTask : ILibraryPostScanTask
{
private const string UpdatesUrl = "https://api.fanart.tv/webservice/newmusic/{0}/{1}/";
/// <summary>
/// The _HTTP client
/// </summary>
private readonly IHttpClient _httpClient;
/// <summary>
/// The _logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// The _config
/// </summary>
private readonly IServerConfigurationManager _config;
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
public FanartUpdatesPostScanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_config = config;
_logger = logger;
_httpClient = httpClient;
_fileSystem = fileSystem;
}
/// <summary>
/// Runs the specified progress.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{
var options = FanartSeriesProvider.Current.GetFanartOptions();
if (!options.EnableAutomaticUpdates)
{
progress.Report(100);
return;
}
var path = FanartArtistProvider.GetArtistDataPath(_config.CommonApplicationPaths);
_fileSystem.CreateDirectory(path);
var timestampFile = Path.Combine(path, "time.txt");
var timestampFileInfo = _fileSystem.GetFileInfo(timestampFile);
// Don't check for updates every single time
if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 3)
{
return;
}
// Find out the last time we queried for updates
var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList();
// If this is our first time, don't do any updates and just record the timestamp
if (!string.IsNullOrEmpty(lastUpdateTime))
{
var artistsToUpdate = await GetArtistIdsToUpdate(existingDirectories, lastUpdateTime, options, cancellationToken).ConfigureAwait(false);
progress.Report(5);
await UpdateArtists(artistsToUpdate, progress, cancellationToken).ConfigureAwait(false);
}
var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture);
_fileSystem.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
progress.Report(100);
}
/// <summary>
/// Gets the artist ids to update.
/// </summary>
/// <param name="existingArtistIds">The existing series ids.</param>
/// <param name="lastUpdateTime">The last update time.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{System.String}}.</returns>
private async Task<IEnumerable<string>> GetArtistIdsToUpdate(IEnumerable<string> existingArtistIds, string lastUpdateTime, FanartOptions options, CancellationToken cancellationToken)
{
var url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime);
if (!string.IsNullOrWhiteSpace(options.UserApiKey))
{
url += "&client_key=" + options.UserApiKey;
}
// First get last time
using (var stream = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
EnableHttpCompression = true,
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool
}).ConfigureAwait(false))
{
// If empty fanart will return a string of "null", rather than an empty list
using (var reader = new StreamReader(stream))
{
var json = await reader.ReadToEndAsync().ConfigureAwait(false);
if (string.Equals(json, "null", StringComparison.OrdinalIgnoreCase))
{
return new List<string>();
}
var existingDictionary = existingArtistIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
var updates = _jsonSerializer.DeserializeFromString<List<FanArtUpdate>>(json);
return updates.Select(i => i.id).Where(existingDictionary.ContainsKey);
}
}
}
/// <summary>
/// Updates the artists.
/// </summary>
/// <param name="idList">The id list.</param>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private async Task UpdateArtists(IEnumerable<string> idList, IProgress<double> progress, CancellationToken cancellationToken)
{
var list = idList.ToList();
var numComplete = 0;
foreach (var id in list)
{
await UpdateArtist(id, cancellationToken).ConfigureAwait(false);
numComplete++;
double percent = numComplete;
percent /= list.Count;
percent *= 95;
progress.Report(percent + 5);
}
}
/// <summary>
/// Updates the artist.
/// </summary>
/// <param name="musicBrainzId">The musicBrainzId.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private Task UpdateArtist(string musicBrainzId, CancellationToken cancellationToken)
{
_logger.Info("Updating artist " + musicBrainzId);
return FanartArtistProvider.Current.DownloadArtistJson(musicBrainzId, cancellationToken);
}
/// <summary>
/// Dates the time to unix timestamp.
/// </summary>
/// <param name="dateTime">The date time.</param>
/// <returns>System.Double.</returns>
private static double DateTimeToUnixTimestamp(DateTime dateTime)
{
return (dateTime - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds;
}
public class FanArtUpdate
{
public string id { get; set; }
public string name { get; set; }
public string new_images { get; set; }
public string total_images { get; set; }
}
}
}

View File

@ -27,11 +27,6 @@ namespace MediaBrowser.Providers.Music
get { return MovieDbProvider.Current.Name; }
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
return MovieDbProvider.Current.HasChanged(item);
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();

View File

@ -21,7 +21,7 @@ using CommonIO;
namespace MediaBrowser.Providers.TV
{
public class FanArtSeasonProvider : IRemoteImageProvider, IHasOrder, IHasItemChangeMonitor
public class FanArtSeasonProvider : IRemoteImageProvider, IHasOrder
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IServerConfigurationManager _config;
@ -224,36 +224,5 @@ namespace MediaBrowser.Providers.TV
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool
});
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
var options = FanartSeriesProvider.Current.GetFanartOptions();
if (!options.EnableAutomaticUpdates)
{
return false;
}
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 imagesFilePath = FanartSeriesProvider.Current.GetFanartJsonPath(tvdbId);
var fileInfo = _fileSystem.GetFileInfo(imagesFilePath);
return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed;
}
return false;
}
}
}

View File

@ -1,192 +0,0 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
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 CommonIO;
namespace MediaBrowser.Providers.TV
{
class FanArtTvUpdatesPostScanTask : ILibraryPostScanTask
{
private const string UpdatesUrl = "https://webservice.fanart.tv/v3/tv/latest?api_key={0}&date={1}";
/// <summary>
/// The _HTTP client
/// </summary>
private readonly IHttpClient _httpClient;
/// <summary>
/// The _logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// The _config
/// </summary>
private readonly IServerConfigurationManager _config;
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
public FanArtTvUpdatesPostScanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_config = config;
_logger = logger;
_httpClient = httpClient;
_fileSystem = fileSystem;
}
/// <summary>
/// Runs the specified progress.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{
var options = FanartSeriesProvider.Current.GetFanartOptions();
if (!options.EnableAutomaticUpdates)
{
progress.Report(100);
return;
}
var path = FanartSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths);
_fileSystem.CreateDirectory(path);
var timestampFile = Path.Combine(path, "time.txt");
var timestampFileInfo = _fileSystem.GetFileInfo(timestampFile);
// Don't check for updates every single time
if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 3)
{
return;
}
// Find out the last time we queried for updates
var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList();
// If this is our first time, don't do any updates and just record the timestamp
if (!string.IsNullOrEmpty(lastUpdateTime))
{
var seriesToUpdate = await GetSeriesIdsToUpdate(existingDirectories, lastUpdateTime, options, cancellationToken).ConfigureAwait(false);
progress.Report(5);
await UpdateSeries(seriesToUpdate, progress, cancellationToken).ConfigureAwait(false);
}
var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture);
_fileSystem.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
progress.Report(100);
}
/// <summary>
/// Gets the series ids to update.
/// </summary>
/// <param name="existingSeriesIds">The existing series ids.</param>
/// <param name="lastUpdateTime">The last update time.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{System.String}}.</returns>
private async Task<IEnumerable<string>> GetSeriesIdsToUpdate(IEnumerable<string> existingSeriesIds, string lastUpdateTime, FanartOptions options, CancellationToken cancellationToken)
{
var url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime);
if (!string.IsNullOrWhiteSpace(options.UserApiKey))
{
url += "&client_key=" + options.UserApiKey;
}
// First get last time
using (var stream = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
EnableHttpCompression = true,
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool
}).ConfigureAwait(false))
{
// If empty fanart will return a string of "null", rather than an empty list
using (var reader = new StreamReader(stream))
{
var json = await reader.ReadToEndAsync().ConfigureAwait(false);
if (string.Equals(json, "null", StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(json))
{
return new List<string>();
}
var existingDictionary = existingSeriesIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
var updates = _jsonSerializer.DeserializeFromString<List<FanartUpdatesPostScanTask.FanArtUpdate>>(json);
return updates.Select(i => i.id).Where(existingDictionary.ContainsKey);
}
}
}
/// <summary>
/// Updates the series.
/// </summary>
/// <param name="idList">The id list.</param>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private async Task UpdateSeries(IEnumerable<string> idList, IProgress<double> progress, CancellationToken cancellationToken)
{
var list = idList.ToList();
var numComplete = 0;
foreach (var id in list)
{
_logger.Info("Updating series " + id);
await FanartSeriesProvider.Current.DownloadSeriesJson(id, cancellationToken).ConfigureAwait(false);
numComplete++;
double percent = numComplete;
percent /= list.Count;
percent *= 95;
progress.Report(percent + 5);
}
}
/// <summary>
/// Dates the time to unix timestamp.
/// </summary>
/// <param name="dateTime">The date time.</param>
/// <returns>System.Double.</returns>
private static double DateTimeToUnixTimestamp(DateTime dateTime)
{
return (dateTime - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds;
}
public class FanArtUpdate
{
public string id { get; set; }
public string name { get; set; }
public string new_images { get; set; }
public string total_images { get; set; }
}
}
}

View File

@ -23,7 +23,7 @@ using CommonIO;
namespace MediaBrowser.Providers.TV
{
public class FanartSeriesProvider : IRemoteImageProvider, IHasOrder, IHasItemChangeMonitor
public class FanartSeriesProvider : IRemoteImageProvider, IHasOrder
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IServerConfigurationManager _config;
@ -341,29 +341,6 @@ namespace MediaBrowser.Providers.TV
}
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
var options = GetFanartOptions();
if (!options.EnableAutomaticUpdates)
{
return false;
}
var tvdbId = item.GetProviderId(MetadataProviders.Tvdb);
if (!String.IsNullOrEmpty(tvdbId))
{
// Process images
var imagesFilePath = GetFanartJsonPath(tvdbId);
var fileInfo = _fileSystem.GetFileInfo(imagesFilePath);
return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed;
}
return false;
}
public class Image
{
public string id { get; set; }

View File

@ -16,7 +16,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.TV
{
public class MovieDbSeriesImageProvider : IRemoteImageProvider, IHasOrder, IHasItemChangeMonitor
public class MovieDbSeriesImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
@ -195,10 +195,5 @@ namespace MediaBrowser.Providers.TV
ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
});
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
return MovieDbSeriesProvider.Current.HasChanged(item);
}
}
}

View File

@ -414,28 +414,6 @@ namespace MediaBrowser.Providers.TV
return Path.Combine(path, filename);
}
public bool HasChanged(IHasMetadata item)
{
if (!MovieDbProvider.Current.GetTheMovieDbOptions().EnableAutomaticUpdates)
{
return false;
}
var tmdbId = item.GetProviderId(MetadataProviders.Tmdb);
if (!String.IsNullOrEmpty(tmdbId))
{
// Process images
var dataFilePath = GetDataFilePath(tmdbId, item.GetPreferredMetadataLanguage());
var fileInfo = _fileSystem.GetFileInfo(dataFilePath);
return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed;
}
return false;
}
private async Task<RemoteSearchResult> FindByExternalId(string id, string externalSource, CancellationToken cancellationToken)
{
var url = string.Format("https://api.themoviedb.org/3/tv/find/{0}?api_key={1}&external_source={2}",

View File

@ -17,7 +17,7 @@ using CommonIO;
namespace MediaBrowser.Providers.TV
{
public class TvdbEpisodeImageProvider : IRemoteImageProvider, IHasItemChangeMonitor
public class TvdbEpisodeImageProvider : IRemoteImageProvider
{
private readonly IServerConfigurationManager _config;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
@ -173,31 +173,5 @@ namespace MediaBrowser.Providers.TV
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
});
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
// For non-unaired items, only enable if configured
if (!TvdbSeriesProvider.Current.GetTvDbOptions().EnableAutomaticUpdates)
{
return false;
}
if (!item.HasImage(ImageType.Primary))
{
var episode = (Episode)item;
var series = episode.Series;
if (series != null && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
{
// Process images
var seriesXmlPath = TvdbSeriesProvider.Current.GetSeriesXmlPath(series.ProviderIds, series.GetPreferredMetadataLanguage());
return _fileSystem.GetLastWriteTimeUtc(seriesXmlPath) > item.DateLastRefreshed;
}
}
return false;
}
}
}

View File

@ -24,7 +24,7 @@ namespace MediaBrowser.Providers.TV
/// <summary>
/// Class RemoteEpisodeProvider
/// </summary>
class TvdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IItemIdentityProvider<EpisodeInfo>, IHasItemChangeMonitor
class TvdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IItemIdentityProvider<EpisodeInfo>
{
private static readonly string FullIdKey = MetadataProviders.Tvdb + "-Full";
@ -144,27 +144,6 @@ namespace MediaBrowser.Providers.TV
return result;
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
if (!TvdbSeriesProvider.Current.GetTvDbOptions().EnableAutomaticUpdates)
{
return false;
}
var episode = (Episode)item;
var series = episode.Series;
if (series != null && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
{
// Process images
var seriesXmlPath = TvdbSeriesProvider.Current.GetSeriesXmlPath(series.ProviderIds, series.GetPreferredMetadataLanguage());
return _fileSystem.GetLastWriteTimeUtc(seriesXmlPath) > item.DateLastRefreshed;
}
return false;
}
/// <summary>
/// Gets the episode XML files.
/// </summary>

View File

@ -20,7 +20,7 @@ using CommonIO;
namespace MediaBrowser.Providers.TV
{
public class TvdbSeasonImageProvider : IRemoteImageProvider, IHasOrder, IHasItemChangeMonitor
public class TvdbSeasonImageProvider : IRemoteImageProvider, IHasOrder
{
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
@ -362,28 +362,5 @@ namespace MediaBrowser.Providers.TV
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
});
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
if (!TvdbSeriesProvider.Current.GetTvDbOptions().EnableAutomaticUpdates)
{
return false;
}
var season = (Season)item;
var series = season.Series;
if (series != null && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
{
// Process images
var imagesXmlPath = Path.Combine(TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, series.ProviderIds), "banners.xml");
var fileInfo = _fileSystem.GetFileInfo(imagesXmlPath);
return fileInfo.Exists && _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed;
}
return false;
}
}
}

View File

@ -20,7 +20,7 @@ using CommonIO;
namespace MediaBrowser.Providers.TV
{
public class TvdbSeriesImageProvider : IRemoteImageProvider, IHasOrder, IHasItemChangeMonitor
public class TvdbSeriesImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IServerConfigurationManager _config;
private readonly IHttpClient _httpClient;
@ -331,25 +331,5 @@ namespace MediaBrowser.Providers.TV
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
});
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
{
if (!TvdbSeriesProvider.Current.GetTvDbOptions().EnableAutomaticUpdates)
{
return false;
}
if (TvdbSeriesProvider.IsValidSeries(item.ProviderIds))
{
// Process images
var imagesXmlPath = Path.Combine(TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, item.ProviderIds), "banners.xml");
var fileInfo = _fileSystem.GetFileInfo(imagesXmlPath);
return fileInfo.Exists && _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed;
}
return false;
}
}
}

View File

@ -311,11 +311,6 @@ namespace MediaBrowser.Providers.TV
return null;
}
public TvdbOptions GetTvDbOptions()
{
return _config.GetConfiguration<TvdbOptions>("tvdb");
}
internal static bool IsValidSeries(Dictionary<string, string> seriesProviderIds)
{
string id;
@ -392,27 +387,25 @@ namespace MediaBrowser.Providers.TV
var seriesXmlFilename = preferredMetadataLanguage + ".xml";
var automaticUpdatesEnabled = GetTvDbOptions().EnableAutomaticUpdates;
const int cacheDays = 1;
var seriesFile = files.FirstOrDefault(i => string.Equals(seriesXmlFilename, i.Name, StringComparison.OrdinalIgnoreCase));
// No need to check age if automatic updates are enabled
if (seriesFile == null || !seriesFile.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(seriesFile)).TotalDays > cacheDays))
if (seriesFile == null || !seriesFile.Exists || (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(seriesFile)).TotalDays > cacheDays)
{
return false;
}
var actorsXml = files.FirstOrDefault(i => string.Equals("actors.xml", i.Name, StringComparison.OrdinalIgnoreCase));
// No need to check age if automatic updates are enabled
if (actorsXml == null || !actorsXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(actorsXml)).TotalDays > cacheDays))
if (actorsXml == null || !actorsXml.Exists || (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(actorsXml)).TotalDays > cacheDays)
{
return false;
}
var bannersXml = files.FirstOrDefault(i => string.Equals("banners.xml", i.Name, StringComparison.OrdinalIgnoreCase));
// No need to check age if automatic updates are enabled
if (bannersXml == null || !bannersXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(bannersXml)).TotalDays > cacheDays))
if (bannersXml == null || !bannersXml.Exists || (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(bannersXml)).TotalDays > cacheDays)
{
return false;
}
@ -1450,19 +1443,4 @@ namespace MediaBrowser.Providers.TV
});
}
}
public class TvdbConfigStore : IConfigurationFactory
{
public IEnumerable<ConfigurationStore> GetConfigurations()
{
return new List<ConfigurationStore>
{
new ConfigurationStore
{
Key = "tvdb",
ConfigurationType = typeof(TvdbOptions)
}
};
}
}
}

View File

@ -28,6 +28,7 @@ namespace MediaBrowser.Server.Implementations.Devices
return base.IsVisible(user) && HasChildren();
}
[IgnoreDataMember]
public override string CollectionType
{
get { return Model.Entities.CollectionType.Photos; }

View File

@ -1670,7 +1670,13 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
var elapsed = (DateTime.UtcNow - startDate).TotalMilliseconds;
if (elapsed >= 400)
var slowThreshold = 1000;
#if DEBUG
slowThreshold = 200;
#endif
if (elapsed >= slowThreshold)
{
Logger.Debug("{2} query time (slow): {0}ms. Query: {1}",
Convert.ToInt32(elapsed),