diff options
Diffstat (limited to 'MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs')
| -rw-r--r-- | MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs b/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs new file mode 100644 index 000000000..9d24490b2 --- /dev/null +++ b/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs @@ -0,0 +1,192 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Library; +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; + +namespace MediaBrowser.Providers.Music +{ + class FanartUpdatesPostScanTask : ILibraryPostScanTask + { + private const string UpdatesUrl = "http://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) + { + if (!_config.Configuration.EnableInternetProviders || !_config.Configuration.EnableFanArtUpdates) + { + progress.Report(100); + return; + } + + var path = FanartArtistProvider.GetArtistDataPath(_config.CommonApplicationPaths); + + Directory.CreateDirectory(path); + + var timestampFile = Path.Combine(path, "time.txt"); + + var timestampFileInfo = new FileInfo(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 ? File.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, cancellationToken).ConfigureAwait(false); + + progress.Report(5); + + await UpdateArtists(artistsToUpdate, progress, cancellationToken).ConfigureAwait(false); + } + + var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture); + + File.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, CancellationToken cancellationToken) + { + // First get last time + using (var stream = await _httpClient.Get(new HttpRequestOptions + { + Url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime), + CancellationToken = cancellationToken, + EnableHttpCompression = true, + ResourcePool = FanartArtistProvider.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.DownloadArtistXml(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; } + } + } +} |
