From 3c48def0d76417572193cd306846f1516e0e9038 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 16 Dec 2014 00:01:57 -0500 Subject: [PATCH] sync updates --- MediaBrowser.Api/Sync/SyncService.cs | 4 +- MediaBrowser.Controller/Entities/User.cs | 25 ++++++- .../Library/IUserManager.cs | 4 +- .../MediaBrowser.Model.Portable.csproj | 6 ++ .../MediaBrowser.Model.net35.csproj | 6 ++ .../ApiClient/ConnectionOptions.cs | 23 +++++++ .../ApiClient/IConnectionManager.cs | 9 +++ MediaBrowser.Model/Dto/UserDto.cs | 12 ++++ MediaBrowser.Model/MediaBrowser.Model.csproj | 2 + MediaBrowser.Model/Sync/SyncCategory.cs | 19 +++++ MediaBrowser.Model/Sync/SyncHelper.cs | 13 ++++ MediaBrowser.Model/Sync/SyncJob.cs | 10 +++ MediaBrowser.Model/Sync/SyncJobRequest.cs | 10 +++ MediaBrowser.Model/Sync/SyncOptions.cs | 3 +- MediaBrowser.Model/Users/UserPolicy.cs | 7 +- .../Channels/ChannelDownloadScheduledTask.cs | 18 ++++- .../Channels/ChannelManager.cs | 5 +- .../Channels/ChannelPostScanTask.cs | 2 + .../Library/UserManager.cs | 69 +++++++++++++++++-- .../Validators/UserViewPostScanTask.cs | 35 ---------- .../Localization/Server/server.json | 6 +- ...MediaBrowser.Server.Implementations.csproj | 1 - .../Session/HttpSessionController.cs | 22 +++++- .../Sync/SyncManager.cs | 6 +- .../Sync/SyncRepository.cs | 34 ++++++--- .../ApplicationHost.cs | 20 ++++-- .../Migrations/RenameXbmcOptions.cs | 2 +- .../Migrations/RenameXmlOptions.cs | 2 +- Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Model.Signed.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 32 files changed, 298 insertions(+), 89 deletions(-) create mode 100644 MediaBrowser.Model/ApiClient/ConnectionOptions.cs create mode 100644 MediaBrowser.Model/Sync/SyncCategory.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/UserViewPostScanTask.cs diff --git a/MediaBrowser.Api/Sync/SyncService.cs b/MediaBrowser.Api/Sync/SyncService.cs index 9cf19d160b..a3c2004fc5 100644 --- a/MediaBrowser.Api/Sync/SyncService.cs +++ b/MediaBrowser.Api/Sync/SyncService.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Api.Sync } [Route("/Sync/Targets", "GET", Summary = "Gets a list of available sync targets.")] - public class GetSyncTarget : IReturn> + public class GetSyncTargets : IReturn> { [ApiMember(Name = "UserId", Description = "UserId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] public string UserId { get; set; } @@ -62,7 +62,7 @@ namespace MediaBrowser.Api.Sync _syncManager = syncManager; } - public object Get(GetSyncTarget request) + public object Get(GetSyncTargets request) { var result = _syncManager.GetSyncTargets(request.UserId); diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index 3fa0a04356..3dfc8cc7d7 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -140,6 +140,29 @@ namespace MediaBrowser.Controller.Entities } } + private UserPolicy _policy; + private readonly object _policySyncLock = new object(); + [IgnoreDataMember] + public UserPolicy Policy + { + get + { + if (_policy == null) + { + lock (_policySyncLock) + { + if (_policy == null) + { + _policy = UserManager.GetUserPolicy(this); + } + } + } + + return _policy; + } + set { _policy = value; } + } + /// /// Renames the user. /// @@ -200,7 +223,7 @@ namespace MediaBrowser.Controller.Entities /// /// The configuration directory path. [IgnoreDataMember] - private string ConfigurationDirectoryPath + public string ConfigurationDirectoryPath { get { diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index debdafe4d5..9dc16ba4d2 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -168,9 +168,9 @@ namespace MediaBrowser.Controller.Library /// /// Gets the user policy. /// - /// The user identifier. + /// The user. /// UserPolicy. - UserPolicy GetUserPolicy(string userId); + UserPolicy GetUserPolicy(User user); /// /// Updates the user policy. diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index f2497c5a9b..8ad8ecbc93 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -80,6 +80,9 @@ ApiClient\ConnectionMode.cs + + ApiClient\ConnectionOptions.cs + ApiClient\ConnectionResult.cs @@ -1025,6 +1028,9 @@ Session\UserDataChangeInfo.cs + + Sync\SyncCategory.cs + Sync\SyncJob.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index b44accb7ac..04c61c8470 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -60,6 +60,9 @@ ApiClient\ConnectionMode.cs + + ApiClient\ConnectionOptions.cs + ApiClient\ConnectionState.cs @@ -984,6 +987,9 @@ Session\UserDataChangeInfo.cs + + Sync\SyncCategory.cs + Sync\SyncJob.cs diff --git a/MediaBrowser.Model/ApiClient/ConnectionOptions.cs b/MediaBrowser.Model/ApiClient/ConnectionOptions.cs new file mode 100644 index 0000000000..445eaa04ef --- /dev/null +++ b/MediaBrowser.Model/ApiClient/ConnectionOptions.cs @@ -0,0 +1,23 @@ + +namespace MediaBrowser.Model.ApiClient +{ + public class ConnectionOptions + { + /// + /// Gets or sets a value indicating whether [enable web socket]. + /// + /// true if [enable web socket]; otherwise, false. + public bool EnableWebSocket { get; set; } + /// + /// Gets or sets a value indicating whether [report capabilities]. + /// + /// true if [report capabilities]; otherwise, false. + public bool ReportCapabilities { get; set; } + + public ConnectionOptions() + { + EnableWebSocket = true; + ReportCapabilities = true; + } + } +} diff --git a/MediaBrowser.Model/ApiClient/IConnectionManager.cs b/MediaBrowser.Model/ApiClient/IConnectionManager.cs index 3b88366e8b..a54c330acd 100644 --- a/MediaBrowser.Model/ApiClient/IConnectionManager.cs +++ b/MediaBrowser.Model/ApiClient/IConnectionManager.cs @@ -77,6 +77,15 @@ namespace MediaBrowser.Model.ApiClient /// Task<ConnectionResult>. Task Connect(ServerInfo server, CancellationToken cancellationToken); + /// + /// Connects the specified server. + /// + /// The server. + /// The options. + /// The cancellation token. + /// Task<ConnectionResult>. + Task Connect(ServerInfo server, ConnectionOptions options, CancellationToken cancellationToken); + /// /// Connects the specified server. /// diff --git a/MediaBrowser.Model/Dto/UserDto.cs b/MediaBrowser.Model/Dto/UserDto.cs index 793a7efd2d..9b6d920306 100644 --- a/MediaBrowser.Model/Dto/UserDto.cs +++ b/MediaBrowser.Model/Dto/UserDto.cs @@ -1,6 +1,7 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Connect; using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.Users; using System; using System.ComponentModel; using System.Diagnostics; @@ -60,6 +61,10 @@ namespace MediaBrowser.Model.Dto /// true if this instance has password; otherwise, false. public bool HasPassword { get; set; } + /// + /// Gets or sets a value indicating whether this instance has configured password. + /// + /// true if this instance has configured password; otherwise, false. public bool HasConfiguredPassword { get; set; } /// @@ -80,6 +85,12 @@ namespace MediaBrowser.Model.Dto /// The configuration. public UserConfiguration Configuration { get; set; } + /// + /// Gets or sets the policy. + /// + /// The policy. + public UserPolicy Policy { get; set; } + /// /// Gets or sets the primary image aspect ratio. /// @@ -108,6 +119,7 @@ namespace MediaBrowser.Model.Dto public UserDto() { Configuration = new UserConfiguration(); + Policy = new UserPolicy(); } /// diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index f537508974..fbf45e0aee 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -104,6 +104,7 @@ + @@ -362,6 +363,7 @@ + diff --git a/MediaBrowser.Model/Sync/SyncCategory.cs b/MediaBrowser.Model/Sync/SyncCategory.cs new file mode 100644 index 0000000000..e0d7486853 --- /dev/null +++ b/MediaBrowser.Model/Sync/SyncCategory.cs @@ -0,0 +1,19 @@ + +namespace MediaBrowser.Model.Sync +{ + public enum SyncCategory + { + /// + /// The latest + /// + Latest = 0, + /// + /// The next up + /// + NextUp = 1, + /// + /// The resume + /// + Resume = 2 + } +} diff --git a/MediaBrowser.Model/Sync/SyncHelper.cs b/MediaBrowser.Model/Sync/SyncHelper.cs index ac595b5efc..64dc024e13 100644 --- a/MediaBrowser.Model/Sync/SyncHelper.cs +++ b/MediaBrowser.Model/Sync/SyncHelper.cs @@ -40,6 +40,7 @@ namespace MediaBrowser.Model.Sync if (item.IsFolder || item.IsGameGenre || item.IsMusicGenre || item.IsGenre || item.IsArtist || item.IsStudio || item.IsPerson) { options.Add(SyncOptions.SyncNewContent); + options.Add(SyncOptions.ItemLimit); break; } } @@ -47,5 +48,17 @@ namespace MediaBrowser.Model.Sync return options; } + + public static List GetSyncOptions(SyncCategory category) + { + List options = new List(); + + options.Add(SyncOptions.Quality); + options.Add(SyncOptions.UnwatchedOnly); + options.Add(SyncOptions.SyncNewContent); + options.Add(SyncOptions.ItemLimit); + + return options; + } } } diff --git a/MediaBrowser.Model/Sync/SyncJob.cs b/MediaBrowser.Model/Sync/SyncJob.cs index 491223db51..92662d7bbf 100644 --- a/MediaBrowser.Model/Sync/SyncJob.cs +++ b/MediaBrowser.Model/Sync/SyncJob.cs @@ -21,6 +21,16 @@ namespace MediaBrowser.Model.Sync /// The quality. public SyncQuality Quality { get; set; } /// + /// Gets or sets the category. + /// + /// The category. + public SyncCategory? Category { get; set; } + /// + /// Gets or sets the parent identifier. + /// + /// The parent identifier. + public string ParentId { get; set; } + /// /// Gets or sets the current progress. /// /// The current progress. diff --git a/MediaBrowser.Model/Sync/SyncJobRequest.cs b/MediaBrowser.Model/Sync/SyncJobRequest.cs index 42a40acc73..7d3016d0ef 100644 --- a/MediaBrowser.Model/Sync/SyncJobRequest.cs +++ b/MediaBrowser.Model/Sync/SyncJobRequest.cs @@ -15,6 +15,16 @@ namespace MediaBrowser.Model.Sync /// The item ids. public List ItemIds { get; set; } /// + /// Gets or sets the category. + /// + /// The category. + public SyncCategory? Category { get; set; } + /// + /// Gets or sets the parent identifier. + /// + /// The parent identifier. + public string ParentId { get; set; } + /// /// Gets or sets the quality. /// /// The quality. diff --git a/MediaBrowser.Model/Sync/SyncOptions.cs b/MediaBrowser.Model/Sync/SyncOptions.cs index edf22f7999..d4a7461f3a 100644 --- a/MediaBrowser.Model/Sync/SyncOptions.cs +++ b/MediaBrowser.Model/Sync/SyncOptions.cs @@ -6,6 +6,7 @@ namespace MediaBrowser.Model.Sync Name = 0, Quality = 1, UnwatchedOnly = 2, - SyncNewContent + SyncNewContent = 3, + ItemLimit = 4 } } diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index 02d1777472..b458e28546 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -1,11 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - + namespace MediaBrowser.Model.Users { public class UserPolicy { + public bool EnableSync { get; set; } } } diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs index e38aef8105..bfdbb8ccf2 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs @@ -13,8 +13,10 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Querying; +using MoreLinq; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Threading; @@ -64,7 +66,10 @@ namespace MediaBrowser.Server.Implementations.Channels { CleanChannelContent(cancellationToken); - var users = _userManager.Users.Select(i => i.Id.ToString("N")).ToList(); + var users = _userManager.Users + .DistinctBy(GetUserDistinctValue) + .Select(i => i.Id.ToString("N")) + .ToList(); var numComplete = 0; @@ -88,6 +93,15 @@ namespace MediaBrowser.Server.Implementations.Channels progress.Report(100); } + public static string GetUserDistinctValue(User user) + { + var channels = user.Configuration.BlockedChannels + .OrderBy(i => i) + .ToList(); + + return string.Join("|", channels.ToArray()); + } + private async Task DownloadContent(string user, CancellationToken cancellationToken, IProgress progress) @@ -201,7 +215,7 @@ namespace MediaBrowser.Server.Implementations.Channels if (IsSizeLimitReached(path, limit.Value)) { return; - } + } } var itemId = item.Id.ToString("N"); diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index 382d0077a7..9e7679f934 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -533,10 +533,13 @@ namespace MediaBrowser.Server.Implementations.Channels ? null : _userManager.GetUserById(query.UserId); + var limit = query.Limit; + // See below about parental control if (user != null) { query.StartIndex = null; + query.Limit = null; } var internalResult = await GetLatestChannelItemsInternal(query, cancellationToken).ConfigureAwait(false); @@ -554,7 +557,7 @@ namespace MediaBrowser.Server.Implementations.Channels if (user != null) { items = items.Where(i => i.IsVisible(user)) - .Take(10) + .Take(limit ?? 10) .ToArray(); totalRecordCount = items.Length; diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs index f677661f7a..72c524ec56 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Channels; using MediaBrowser.Model.Logging; +using MoreLinq; using System; using System.Collections.Generic; using System.Linq; @@ -27,6 +28,7 @@ namespace MediaBrowser.Server.Implementations.Channels public async Task Run(IProgress progress, CancellationToken cancellationToken) { var users = _userManager.Users + .DistinctBy(ChannelDownloadScheduledTask.GetUserDistinctValue) .Select(i => i.Id.ToString("N")) .ToList(); diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index ed45e890bf..791cae5531 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Events; +using System.Collections.Concurrent; +using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; @@ -317,7 +318,8 @@ namespace MediaBrowser.Server.Implementations.Library ConnectLinkType = user.ConnectLinkType, ConnectUserId = user.ConnectUserId, ConnectUserName = user.ConnectUserName, - ServerId = _appHost.SystemId + ServerId = _appHost.SystemId, + Policy = user.Policy }; var image = user.GetImageInfo(ImageType.Primary, 0); @@ -529,6 +531,8 @@ namespace MediaBrowser.Server.Implementations.Library _logger.ErrorException("Error deleting file {0}", ex, path); } + DeleteUserPolicy(user); + // Force this to be lazy loaded again Users = await LoadUsers().ConfigureAwait(false); @@ -715,7 +719,7 @@ namespace MediaBrowser.Server.Implementations.Library var usersReset = new List(); - var valid = !string.IsNullOrWhiteSpace(_lastPin) && + var valid = !string.IsNullOrWhiteSpace(_lastPin) && string.Equals(_lastPin, pin, StringComparison.OrdinalIgnoreCase) && _lastPasswordPinCreationResult != null && _lastPasswordPinCreationResult.ExpirationDate > DateTime.UtcNow; @@ -769,14 +773,65 @@ namespace MediaBrowser.Server.Implementations.Library public DateTime ExpirationDate { get; set; } } - public UserPolicy GetUserPolicy(string userId) + public UserPolicy GetUserPolicy(User user) { - throw new NotImplementedException(); + var path = GetPolifyFilePath(user); + + try + { + lock (_policySyncLock) + { + return (UserPolicy)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), path); + } + } + catch (Exception ex) + { + _logger.ErrorException("Error reading policy file: {0}", ex, path); + + return new UserPolicy + { + EnableSync = !user.ConnectLinkType.HasValue || user.ConnectLinkType.Value != UserLinkType.Guest + }; + } } - public Task UpdateUserPolicy(string userId, UserPolicy userPolicy) + private readonly object _policySyncLock = new object(); + public async Task UpdateUserPolicy(string userId, UserPolicy userPolicy) { - throw new NotImplementedException(); + var user = GetUserById(userId); + var path = GetPolifyFilePath(user); + + lock (_policySyncLock) + { + _xmlSerializer.SerializeToFile(userPolicy, path); + user.Policy = userPolicy; + } + } + + private void DeleteUserPolicy(User user) + { + var path = GetPolifyFilePath(user); + + try + { + lock (_policySyncLock) + { + File.Delete(path); + } + } + catch (IOException) + { + + } + catch (Exception ex) + { + _logger.ErrorException("Error deleting policy file", ex); + } + } + + private string GetPolifyFilePath(User user) + { + return Path.Combine(user.ConfigurationDirectoryPath, "policy.xml"); } } } diff --git a/MediaBrowser.Server.Implementations/Library/Validators/UserViewPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/UserViewPostScanTask.cs deleted file mode 100644 index 30ebcc3b82..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/UserViewPostScanTask.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Library; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - public class UserViewPostScanTask : ILibraryPostScanTask - { - private readonly IUserManager _userManager; - private readonly IUserViewManager _userViewManager; - - public UserViewPostScanTask(IUserManager userManager, IUserViewManager userViewManager) - { - _userManager = userManager; - _userViewManager = userViewManager; - } - - public async Task Run(IProgress progress, CancellationToken cancellationToken) - { - foreach (var user in _userManager.Users) - { - foreach (var view in await _userViewManager.GetUserViews(new UserViewQuery - { - UserId = user.Id.ToString("N") - - }, cancellationToken).ConfigureAwait(false)) - { - await view.RefreshMetadata(cancellationToken).ConfigureAwait(false); - } - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 6bb24be2b3..09cd286b43 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -232,10 +232,10 @@ "HeaderFeatureAccess": "Feature Access", "OptionAllowMediaPlayback": "Allow media playback", "OptionAllowBrowsingLiveTv": "Allow browsing of live tv", - "OptionAllowDeleteLibraryContent": "Allow this user to delete library content", + "OptionAllowDeleteLibraryContent": "Allow deletion of library content", "OptionAllowManageLiveTv": "Allow management of live tv recordings", - "OptionAllowRemoteControlOthers": "Allow this user to remote control other users", - "OptionAllowRemoteSharedDevices": "Allow this user to remote control shared devices", + "OptionAllowRemoteControlOthers": "Allow remote control of other users", + "OptionAllowRemoteSharedDevices": "Allow remote control of shared devices", "OptionAllowRemoteSharedDevicesHelp": "Dlna devices are considered shared until a user begins controlling it.", "HeaderRemoteControl": "Remote Control", "OptionMissingTmdbId": "Missing Tmdb Id", diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 84d62df3ae..7d0a751e14 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -215,7 +215,6 @@ - diff --git a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs index d2ace23a9a..4a64d37532 100644 --- a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs +++ b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs @@ -25,6 +25,7 @@ namespace MediaBrowser.Server.Implementations.Session private readonly string _postUrl; private Timer _pingTimer; + private DateTime _lastPingTime; public HttpSessionController(IHttpClient httpClient, IJsonSerializer json, @@ -68,10 +69,23 @@ namespace MediaBrowser.Server.Implementations.Session try { await SendMessage("Ping", CancellationToken.None).ConfigureAwait(false); + + _lastPingTime = DateTime.UtcNow; } catch { - ReportSessionEnded(); + var lastActivityDate = new[] { _lastPingTime, Session.LastActivityDate } + .Max(); + + var timeSinceLastPing = DateTime.UtcNow - lastActivityDate; + + // We don't want to stop the session due to one single request failure + // At the same time, we don't want the timeout to be too long because it will + // be sitting in active sessions available for remote control, when it's not + if (timeSinceLastPing >= TimeSpan.FromMinutes(5)) + { + ReportSessionEnded(); + } } } @@ -90,6 +104,8 @@ namespace MediaBrowser.Server.Implementations.Session { if (_pingTimer != null) { + _lastPingTime = DateTime.UtcNow; + var period = TimeSpan.FromSeconds(60); _pingTimer.Change(period, period); @@ -101,8 +117,8 @@ namespace MediaBrowser.Server.Implementations.Session return SendMessage(name, new Dictionary(), cancellationToken); } - private async Task SendMessage(string name, - Dictionary args, + private async Task SendMessage(string name, + Dictionary args, CancellationToken cancellationToken) { var url = PostUrl + "/" + name + ToQueryString(args); diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index f72b1541a7..c2f004f0b3 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Sync var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager); var user = _userManager.GetUserById(request.UserId); - + var items = processor .GetItemsForSync(request.ItemIds, user) .ToList(); @@ -85,7 +85,9 @@ namespace MediaBrowser.Server.Implementations.Sync DateLastModified = DateTime.UtcNow, SyncNewContent = request.SyncNewContent, ItemCount = items.Count, - Quality = request.Quality + Quality = request.Quality, + Category = request.Category, + ParentId = request.ParentId }; // It's just a static list diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 3e54111b0f..a9e319cc46 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -35,13 +35,13 @@ namespace MediaBrowser.Server.Implementations.Sync public async Task Initialize() { - var dbFile = Path.Combine(_appPaths.DataPath, "sync5.db"); + var dbFile = Path.Combine(_appPaths.DataPath, "sync6.db"); _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); string[] queries = { - "create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Quality TEXT NOT NULL, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)", + "create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Quality TEXT NOT NULL, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)", "create index if not exists idx_SyncJobs on SyncJobs(Id)", "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, JobId TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT)", @@ -65,7 +65,7 @@ namespace MediaBrowser.Server.Implementations.Sync _deleteJobCommand.Parameters.Add(_deleteJobCommand, "@Id"); _saveJobCommand = _connection.CreateCommand(); - _saveJobCommand.CommandText = "replace into SyncJobs (Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount) values (@Id, @TargetId, @Name, @Quality, @Status, @Progress, @UserId, @ItemIds, @UnwatchedOnly, @ItemLimit, @SyncNewContent, @DateCreated, @DateLastModified, @ItemCount)"; + _saveJobCommand.CommandText = "replace into SyncJobs (Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount) values (@Id, @TargetId, @Name, @Quality, @Status, @Progress, @UserId, @ItemIds, @Category, @ParentId, @UnwatchedOnly, @ItemLimit, @SyncNewContent, @DateCreated, @DateLastModified, @ItemCount)"; _saveJobCommand.Parameters.Add(_saveJobCommand, "@Id"); _saveJobCommand.Parameters.Add(_saveJobCommand, "@TargetId"); @@ -75,6 +75,8 @@ namespace MediaBrowser.Server.Implementations.Sync _saveJobCommand.Parameters.Add(_saveJobCommand, "@Progress"); _saveJobCommand.Parameters.Add(_saveJobCommand, "@UserId"); _saveJobCommand.Parameters.Add(_saveJobCommand, "@ItemIds"); + _saveJobCommand.Parameters.Add(_saveJobCommand, "@Category"); + _saveJobCommand.Parameters.Add(_saveJobCommand, "@ParentId"); _saveJobCommand.Parameters.Add(_saveJobCommand, "@UnwatchedOnly"); _saveJobCommand.Parameters.Add(_saveJobCommand, "@ItemLimit"); _saveJobCommand.Parameters.Add(_saveJobCommand, "@SyncNewContent"); @@ -95,7 +97,7 @@ namespace MediaBrowser.Server.Implementations.Sync _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@Progress"); } - private const string BaseJobSelectText = "select Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount from SyncJobs"; + private const string BaseJobSelectText = "select Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount from SyncJobs"; private const string BaseJobItemSelectText = "select Id, ItemId, JobId, OutputPath, Status, TargetId, DateCreated, Progress from SyncJobItems"; public SyncJob GetJob(string id) @@ -166,19 +168,29 @@ namespace MediaBrowser.Server.Implementations.Sync if (!reader.IsDBNull(8)) { - info.UnwatchedOnly = reader.GetBoolean(8); + info.Category = (SyncCategory)Enum.Parse(typeof(SyncCategory), reader.GetString(8), true); } if (!reader.IsDBNull(9)) { - info.ItemLimit = reader.GetInt32(9); + info.ParentId = reader.GetString(9); } - info.SyncNewContent = reader.GetBoolean(10); + if (!reader.IsDBNull(10)) + { + info.UnwatchedOnly = reader.GetBoolean(10); + } - info.DateCreated = reader.GetDateTime(11).ToUniversalTime(); - info.DateLastModified = reader.GetDateTime(12).ToUniversalTime(); - info.ItemCount = reader.GetInt32(13); + if (!reader.IsDBNull(11)) + { + info.ItemLimit = reader.GetInt32(11); + } + + info.SyncNewContent = reader.GetBoolean(12); + + info.DateCreated = reader.GetDateTime(13).ToUniversalTime(); + info.DateLastModified = reader.GetDateTime(14).ToUniversalTime(); + info.ItemCount = reader.GetInt32(15); return info; } @@ -213,6 +225,8 @@ namespace MediaBrowser.Server.Implementations.Sync _saveJobCommand.GetParameter(index++).Value = job.Progress; _saveJobCommand.GetParameter(index++).Value = job.UserId; _saveJobCommand.GetParameter(index++).Value = string.Join(",", job.RequestedItemIds.ToArray()); + _saveJobCommand.GetParameter(index++).Value = job.Category; + _saveJobCommand.GetParameter(index++).Value = job.ParentId; _saveJobCommand.GetParameter(index++).Value = job.UnwatchedOnly; _saveJobCommand.GetParameter(index++).Value = job.ItemLimit; _saveJobCommand.GetParameter(index++).Value = job.SyncNewContent; diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 1d69cd3252..0db7893e59 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -341,12 +341,20 @@ namespace MediaBrowser.Server.Startup.Common private void PerformVersionMigration() { - new MigrateUserFolders(ApplicationPaths).Run(); - new PlaylistImages(ServerConfigurationManager).Run(); - new RenameXbmcOptions(ServerConfigurationManager).Run(); - new RenameXmlOptions(ServerConfigurationManager).Run(); - new DeprecatePlugins(ApplicationPaths).Run(); - new DeleteDlnaProfiles(ApplicationPaths).Run(); + var migrations = new List + { + new MigrateUserFolders(ApplicationPaths), + new PlaylistImages(ServerConfigurationManager), + new RenameXbmcOptions(ServerConfigurationManager), + new RenameXmlOptions(ServerConfigurationManager), + new DeprecatePlugins(ApplicationPaths), + new DeleteDlnaProfiles(ApplicationPaths) + }; + + foreach (var task in migrations) + { + task.Run(); + } } /// diff --git a/MediaBrowser.Server.Startup.Common/Migrations/RenameXbmcOptions.cs b/MediaBrowser.Server.Startup.Common/Migrations/RenameXbmcOptions.cs index efc34c1d89..02b0f9a0ab 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/RenameXbmcOptions.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/RenameXbmcOptions.cs @@ -3,7 +3,7 @@ using System; namespace MediaBrowser.Server.Startup.Common.Migrations { - public class RenameXbmcOptions + public class RenameXbmcOptions : IVersionMigration { private readonly IServerConfigurationManager _config; diff --git a/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs b/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs index 3034fad31b..a955b57eaf 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs @@ -3,7 +3,7 @@ using System; namespace MediaBrowser.Server.Startup.Common.Migrations { - public class RenameXmlOptions + public class RenameXmlOptions : IVersionMigration { private readonly IServerConfigurationManager _config; diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 8a6c3004fb..b72992d4d5 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.519 + 3.0.520 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 25ad3d10c6..6e00e223c7 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.519 + 3.0.520 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index 32dd134db6..986ad497d8 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.519 + 3.0.520 MediaBrowser.Model - Signed Edition Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 57d8eb1c86..cbc8b37007 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.519 + 3.0.520 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - +