aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Channels/ChannelPostScanTask.cs
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2016-11-02 16:53:50 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2016-11-02 16:53:50 -0400
commitd71d2a5d02cf31b67420b54160868247f23546bb (patch)
tree264b96d3ac4ca7cf2040344ffa57e8418b2b5554 /Emby.Server.Implementations/Channels/ChannelPostScanTask.cs
parent8f64a5555b055f42d4c3814725a4e961c2fc980d (diff)
move classes to portable server project
Diffstat (limited to 'Emby.Server.Implementations/Channels/ChannelPostScanTask.cs')
-rw-r--r--Emby.Server.Implementations/Channels/ChannelPostScanTask.cs257
1 files changed, 257 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/Channels/ChannelPostScanTask.cs b/Emby.Server.Implementations/Channels/ChannelPostScanTask.cs
new file mode 100644
index 000000000..aef06bd1d
--- /dev/null
+++ b/Emby.Server.Implementations/Channels/ChannelPostScanTask.cs
@@ -0,0 +1,257 @@
+using MediaBrowser.Common.Progress;
+using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Channels;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Model.Extensions;
+
+namespace Emby.Server.Implementations.Channels
+{
+ public class ChannelPostScanTask
+ {
+ private readonly IChannelManager _channelManager;
+ private readonly IUserManager _userManager;
+ private readonly ILogger _logger;
+ private readonly ILibraryManager _libraryManager;
+
+ public ChannelPostScanTask(IChannelManager channelManager, IUserManager userManager, ILogger logger, ILibraryManager libraryManager)
+ {
+ _channelManager = channelManager;
+ _userManager = userManager;
+ _logger = logger;
+ _libraryManager = libraryManager;
+ }
+
+ public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ var users = _userManager.Users
+ .DistinctBy(GetUserDistinctValue)
+ .Select(i => i.Id.ToString("N"))
+ .ToList();
+
+ var numComplete = 0;
+
+ foreach (var user in users)
+ {
+ double percentPerUser = 1;
+ percentPerUser /= users.Count;
+ var startingPercent = numComplete * percentPerUser * 100;
+
+ var innerProgress = new ActionableProgress<double>();
+ innerProgress.RegisterAction(p => progress.Report(startingPercent + percentPerUser * p));
+
+ await DownloadContent(user, cancellationToken, innerProgress).ConfigureAwait(false);
+
+ numComplete++;
+ double percent = numComplete;
+ percent /= users.Count;
+ progress.Report(percent * 100);
+ }
+
+ await CleanDatabase(cancellationToken).ConfigureAwait(false);
+
+ progress.Report(100);
+ }
+
+ public static string GetUserDistinctValue(User user)
+ {
+ var channels = user.Policy.EnabledChannels
+ .OrderBy(i => i)
+ .ToList();
+
+ return string.Join("|", channels.ToArray());
+ }
+
+ private async Task DownloadContent(string user, CancellationToken cancellationToken, IProgress<double> progress)
+ {
+ var channels = await _channelManager.GetChannelsInternal(new ChannelQuery
+ {
+ UserId = user
+
+ }, cancellationToken);
+
+ var numComplete = 0;
+ var numItems = channels.Items.Length;
+
+ foreach (var channel in channels.Items)
+ {
+ var channelId = channel.Id.ToString("N");
+
+ var features = _channelManager.GetChannelFeatures(channelId);
+
+ const int currentRefreshLevel = 1;
+ var maxRefreshLevel = features.AutoRefreshLevels ?? 0;
+ maxRefreshLevel = Math.Max(maxRefreshLevel, 2);
+
+ if (maxRefreshLevel > 0)
+ {
+ var innerProgress = new ActionableProgress<double>();
+
+ var startingNumberComplete = numComplete;
+ innerProgress.RegisterAction(p =>
+ {
+ double innerPercent = startingNumberComplete;
+ innerPercent += p / 100;
+ innerPercent /= numItems;
+ progress.Report(innerPercent * 100);
+ });
+
+ try
+ {
+ await GetAllItems(user, channelId, null, currentRefreshLevel, maxRefreshLevel, innerProgress, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error getting channel content", ex);
+ }
+ }
+
+ numComplete++;
+ double percent = numComplete;
+ percent /= numItems;
+ progress.Report(percent * 100);
+ }
+
+ progress.Report(100);
+ }
+
+ private async Task CleanDatabase(CancellationToken cancellationToken)
+ {
+ var installedChannelIds = ((ChannelManager)_channelManager).GetInstalledChannelIds();
+
+ var databaseIds = _libraryManager.GetItemIds(new InternalItemsQuery
+ {
+ IncludeItemTypes = new[] { typeof(Channel).Name }
+ });
+
+ var invalidIds = databaseIds
+ .Except(installedChannelIds)
+ .ToList();
+
+ foreach (var id in invalidIds)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ await CleanChannel(id, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ private async Task CleanChannel(Guid id, CancellationToken cancellationToken)
+ {
+ _logger.Info("Cleaning channel {0} from database", id);
+
+ // Delete all channel items
+ var allIds = _libraryManager.GetItemIds(new InternalItemsQuery
+ {
+ ChannelIds = new[] { id.ToString("N") }
+ });
+
+ foreach (var deleteId in allIds)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ await DeleteItem(deleteId).ConfigureAwait(false);
+ }
+
+ // Finally, delete the channel itself
+ await DeleteItem(id).ConfigureAwait(false);
+ }
+
+ private Task DeleteItem(Guid id)
+ {
+ var item = _libraryManager.GetItemById(id);
+
+ if (item == null)
+ {
+ return Task.FromResult(true);
+ }
+
+ return _libraryManager.DeleteItem(item, new DeleteOptions
+ {
+ DeleteFileLocation = false
+ });
+ }
+
+ private async Task GetAllItems(string user, string channelId, string folderId, int currentRefreshLevel, int maxRefreshLevel, IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ var folderItems = new List<string>();
+
+ var innerProgress = new ActionableProgress<double>();
+ innerProgress.RegisterAction(p => progress.Report(p / 2));
+
+ var result = await _channelManager.GetChannelItemsInternal(new ChannelItemQuery
+ {
+ ChannelId = channelId,
+ UserId = user,
+ FolderId = folderId
+
+ }, innerProgress, cancellationToken);
+
+ folderItems.AddRange(result.Items.Where(i => i.IsFolder).Select(i => i.Id.ToString("N")));
+
+ var totalRetrieved = result.Items.Length;
+ var totalCount = result.TotalRecordCount;
+
+ while (totalRetrieved < totalCount)
+ {
+ result = await _channelManager.GetChannelItemsInternal(new ChannelItemQuery
+ {
+ ChannelId = channelId,
+ UserId = user,
+ StartIndex = totalRetrieved,
+ FolderId = folderId
+
+ }, new Progress<double>(), cancellationToken);
+
+ folderItems.AddRange(result.Items.Where(i => i.IsFolder).Select(i => i.Id.ToString("N")));
+
+ totalRetrieved += result.Items.Length;
+ totalCount = result.TotalRecordCount;
+ }
+
+ progress.Report(50);
+
+ if (currentRefreshLevel < maxRefreshLevel)
+ {
+ var numComplete = 0;
+ var numItems = folderItems.Count;
+
+ foreach (var folder in folderItems)
+ {
+ try
+ {
+ innerProgress = new ActionableProgress<double>();
+
+ var startingNumberComplete = numComplete;
+ innerProgress.RegisterAction(p =>
+ {
+ double innerPercent = startingNumberComplete;
+ innerPercent += p / 100;
+ innerPercent /= numItems;
+ progress.Report(innerPercent * 50 + 50);
+ });
+
+ await GetAllItems(user, channelId, folder, currentRefreshLevel + 1, maxRefreshLevel, innerProgress, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error getting channel content", ex);
+ }
+
+ numComplete++;
+ double percent = numComplete;
+ percent /= numItems;
+ progress.Report(percent * 50 + 50);
+ }
+ }
+
+ progress.Report(100);
+ }
+ }
+}