diff --git a/Emby.Notifications/Api/NotificationsService.cs b/Emby.Notifications/Api/NotificationsService.cs index 83845558ad..5591809712 100644 --- a/Emby.Notifications/Api/NotificationsService.cs +++ b/Emby.Notifications/Api/NotificationsService.cs @@ -1,3 +1,8 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1402 +#pragma warning disable SA1600 +#pragma warning disable SA1649 + using System; using System.Collections.Generic; using System.Linq; @@ -12,60 +17,6 @@ using MediaBrowser.Model.Services; namespace Emby.Notifications.Api { - [Route("/Notifications/{UserId}", "GET", Summary = "Gets notifications")] - public class GetNotifications : IReturn - { - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string UserId { get; set; } - - [ApiMember(Name = "IsRead", Description = "An optional filter by IsRead", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] - public bool? IsRead { get; set; } - - [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] - public int? StartIndex { get; set; } - - [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] - public int? Limit { get; set; } - } - - public class Notification - { - public string Id { get; set; } - - public string UserId { get; set; } - - public DateTime Date { get; set; } - - public bool IsRead { get; set; } - - public string Name { get; set; } - - public string Description { get; set; } - - public string Url { get; set; } - - public NotificationLevel Level { get; set; } - } - - public class NotificationResult - { - public Notification[] Notifications { get; set; } - public int TotalRecordCount { get; set; } - } - - public class NotificationsSummary - { - public int UnreadCount { get; set; } - public NotificationLevel MaxUnreadNotificationLevel { get; set; } - } - - [Route("/Notifications/{UserId}/Summary", "GET", Summary = "Gets a notification summary for a user")] - public class GetNotificationsSummary : IReturn - { - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string UserId { get; set; } - } - [Route("/Notifications/Types", "GET", Summary = "Gets notification types")] public class GetNotificationTypes : IReturn> { @@ -80,41 +31,21 @@ namespace Emby.Notifications.Api public class AddAdminNotification : IReturnVoid { [ApiMember(Name = "Name", Description = "The notification's name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Name { get; set; } + public string Name { get; set; } = string.Empty; [ApiMember(Name = "Description", Description = "The notification's description", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Description { get; set; } + public string Description { get; set; } = string.Empty; [ApiMember(Name = "ImageUrl", Description = "The notification's image url", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public string ImageUrl { get; set; } + public string? ImageUrl { get; set; } [ApiMember(Name = "Url", Description = "The notification's info url", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Url { get; set; } + public string? Url { get; set; } [ApiMember(Name = "Level", Description = "The notification level", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] public NotificationLevel Level { get; set; } } - [Route("/Notifications/{UserId}/Read", "POST", Summary = "Marks notifications as read")] - public class MarkRead : IReturnVoid - { - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string UserId { get; set; } - - [ApiMember(Name = "Ids", Description = "A list of notification ids, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)] - public string Ids { get; set; } - } - - [Route("/Notifications/{UserId}/Unread", "POST", Summary = "Marks notifications as unread")] - public class MarkUnread : IReturnVoid - { - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string UserId { get; set; } - - [ApiMember(Name = "Ids", Description = "A list of notification ids, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)] - public string Ids { get; set; } - } - [Authenticated] public class NotificationsService : IService { @@ -129,30 +60,19 @@ namespace Emby.Notifications.Api public object Get(GetNotificationTypes request) { + _ = request; // Silence unused variable warning return _notificationManager.GetNotificationTypes(); } public object Get(GetNotificationServices request) { + _ = request; // Silence unused variable warning return _notificationManager.GetNotificationServices().ToList(); } - public object Get(GetNotificationsSummary request) - { - return new NotificationsSummary - { - - }; - } - public Task Post(AddAdminNotification request) { // This endpoint really just exists as post of a real with sickbeard - return AddNotification(request); - } - - private Task AddNotification(AddAdminNotification request) - { var notification = new NotificationRequest { Date = DateTime.UtcNow, @@ -165,18 +85,5 @@ namespace Emby.Notifications.Api return _notificationManager.SendNotification(notification, CancellationToken.None); } - - public void Post(MarkRead request) - { - } - - public void Post(MarkUnread request) - { - } - - public object Get(GetNotifications request) - { - return new NotificationResult(); - } } } diff --git a/Emby.Notifications/CoreNotificationTypes.cs b/Emby.Notifications/CoreNotificationTypes.cs index 0f9fc08d99..73e0b0256a 100644 --- a/Emby.Notifications/CoreNotificationTypes.cs +++ b/Emby.Notifications/CoreNotificationTypes.cs @@ -1,7 +1,9 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1600 + using System; using System.Collections.Generic; using System.Linq; -using MediaBrowser.Controller; using MediaBrowser.Controller.Notifications; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Notifications; diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index 004ded77b1..e6bf785bff 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -4,6 +4,8 @@ netstandard2.1 false true + true + enable @@ -16,4 +18,16 @@ + + + + + + + + + + ../jellyfin.ruleset + + diff --git a/Emby.Notifications/NotificationConfigurationFactory.cs b/Emby.Notifications/NotificationConfigurationFactory.cs index d08475f7d2..b168ed221b 100644 --- a/Emby.Notifications/NotificationConfigurationFactory.cs +++ b/Emby.Notifications/NotificationConfigurationFactory.cs @@ -1,3 +1,6 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1600 + using System.Collections.Generic; using MediaBrowser.Common.Configuration; using MediaBrowser.Model.Notifications; @@ -13,7 +16,7 @@ namespace Emby.Notifications new ConfigurationStore { Key = "notifications", - ConfigurationType = typeof (NotificationOptions) + ConfigurationType = typeof(NotificationOptions) } }; } diff --git a/Emby.Notifications/Notifications.cs b/Emby.Notifications/NotificationEntryPoint.cs similarity index 69% rename from Emby.Notifications/Notifications.cs rename to Emby.Notifications/NotificationEntryPoint.cs index 7aa1e7ae89..ab92822fa2 100644 --- a/Emby.Notifications/Notifications.cs +++ b/Emby.Notifications/NotificationEntryPoint.cs @@ -21,70 +21,85 @@ using Microsoft.Extensions.Logging; namespace Emby.Notifications { /// - /// Creates notifications for various system events + /// Creates notifications for various system events. /// - public class Notifications : IServerEntryPoint + public class NotificationEntryPoint : IServerEntryPoint { private readonly ILogger _logger; - + private readonly IActivityManager _activityManager; + private readonly ILocalizationManager _localization; private readonly INotificationManager _notificationManager; - private readonly ILibraryManager _libraryManager; private readonly IServerApplicationHost _appHost; + private readonly IConfigurationManager _config; - private Timer LibraryUpdateTimer { get; set; } private readonly object _libraryChangedSyncLock = new object(); + private readonly List _itemsAdded = new List(); - private readonly IConfigurationManager _config; - private readonly ILocalizationManager _localization; - private readonly IActivityManager _activityManager; + private Timer? _libraryUpdateTimer; private string[] _coreNotificationTypes; - public Notifications( + private bool _disposed = false; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The activity manager. + /// The localization manager. + /// The notification manager. + /// The library manager. + /// The application host. + /// The configuration manager. + public NotificationEntryPoint( + ILogger logger, IActivityManager activityManager, ILocalizationManager localization, - ILogger logger, INotificationManager notificationManager, ILibraryManager libraryManager, IServerApplicationHost appHost, IConfigurationManager config) { _logger = logger; + _activityManager = activityManager; + _localization = localization; _notificationManager = notificationManager; _libraryManager = libraryManager; _appHost = appHost; _config = config; - _localization = localization; - _activityManager = activityManager; _coreNotificationTypes = new CoreNotificationTypes(localization).GetNotificationTypes().Select(i => i.Type).ToArray(); } + /// public Task RunAsync() { - _libraryManager.ItemAdded += _libraryManager_ItemAdded; - _appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged; - _appHost.HasUpdateAvailableChanged += _appHost_HasUpdateAvailableChanged; - _activityManager.EntryCreated += _activityManager_EntryCreated; + _libraryManager.ItemAdded += OnLibraryManagerItemAdded; + _appHost.HasPendingRestartChanged += OnAppHostHasPendingRestartChanged; + _appHost.HasUpdateAvailableChanged += OnAppHostHasUpdateAvailableChanged; + _activityManager.EntryCreated += OnActivityManagerEntryCreated; return Task.CompletedTask; } - private async void _appHost_HasPendingRestartChanged(object sender, EventArgs e) + private async void OnAppHostHasPendingRestartChanged(object sender, EventArgs e) { var type = NotificationType.ServerRestartRequired.ToString(); var notification = new NotificationRequest { NotificationType = type, - Name = string.Format(_localization.GetLocalizedString("ServerNameNeedsToBeRestarted"), _appHost.Name) + Name = string.Format( + CultureInfo.InvariantCulture, + _localization.GetLocalizedString("ServerNameNeedsToBeRestarted"), + _appHost.Name) }; await SendNotification(notification, null).ConfigureAwait(false); } - private async void _activityManager_EntryCreated(object sender, GenericEventArgs e) + private async void OnActivityManagerEntryCreated(object sender, GenericEventArgs e) { var entry = e.Argument; @@ -117,7 +132,7 @@ namespace Emby.Notifications return _config.GetConfiguration("notifications"); } - private async void _appHost_HasUpdateAvailableChanged(object sender, EventArgs e) + private async void OnAppHostHasUpdateAvailableChanged(object sender, EventArgs e) { if (!_appHost.HasUpdateAvailable) { @@ -136,8 +151,7 @@ namespace Emby.Notifications await SendNotification(notification, null).ConfigureAwait(false); } - private readonly List _itemsAdded = new List(); - private void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e) + private void OnLibraryManagerItemAdded(object sender, ItemChangeEventArgs e) { if (!FilterItem(e.Item)) { @@ -146,14 +160,17 @@ namespace Emby.Notifications lock (_libraryChangedSyncLock) { - if (LibraryUpdateTimer == null) + if (_libraryUpdateTimer == null) { - LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, 5000, - Timeout.Infinite); + _libraryUpdateTimer = new Timer( + LibraryUpdateTimerCallback, + null, + 5000, + Timeout.Infinite); } else { - LibraryUpdateTimer.Change(5000, Timeout.Infinite); + _libraryUpdateTimer.Change(5000, Timeout.Infinite); } _itemsAdded.Add(e.Item); @@ -188,7 +205,8 @@ namespace Emby.Notifications { items = _itemsAdded.ToList(); _itemsAdded.Clear(); - DisposeLibraryUpdateTimer(); + _libraryUpdateTimer!.Dispose(); // Shouldn't be null as it just set off this callback + _libraryUpdateTimer = null; } items = items.Take(10).ToList(); @@ -198,7 +216,10 @@ namespace Emby.Notifications var notification = new NotificationRequest { NotificationType = NotificationType.NewLibraryContent.ToString(), - Name = string.Format(_localization.GetLocalizedString("ValueHasBeenAddedToLibrary"), GetItemName(item)), + Name = string.Format( + CultureInfo.InvariantCulture, + _localization.GetLocalizedString("ValueHasBeenAddedToLibrary"), + GetItemName(item)), Description = item.Overview }; @@ -206,7 +227,7 @@ namespace Emby.Notifications } } - public static string GetItemName(BaseItem item) + private static string GetItemName(BaseItem item) { var name = item.Name; if (item is Episode episode) @@ -219,6 +240,7 @@ namespace Emby.Notifications episode.IndexNumber.Value, name); } + if (episode.ParentIndexNumber.HasValue) { name = string.Format( @@ -229,7 +251,6 @@ namespace Emby.Notifications } } - if (item is IHasSeries hasSeries) { name = hasSeries.SeriesName + " - " + name; @@ -257,7 +278,7 @@ namespace Emby.Notifications return name; } - private async Task SendNotification(NotificationRequest notification, BaseItem relatedItem) + private async Task SendNotification(NotificationRequest notification, BaseItem? relatedItem) { try { @@ -269,23 +290,37 @@ namespace Emby.Notifications } } + /// public void Dispose() { - DisposeLibraryUpdateTimer(); - - _libraryManager.ItemAdded -= _libraryManager_ItemAdded; - _appHost.HasPendingRestartChanged -= _appHost_HasPendingRestartChanged; - _appHost.HasUpdateAvailableChanged -= _appHost_HasUpdateAvailableChanged; - _activityManager.EntryCreated -= _activityManager_EntryCreated; + Dispose(true); + GC.SuppressFinalize(this); } - private void DisposeLibraryUpdateTimer() + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) { - if (LibraryUpdateTimer != null) + if (_disposed) + { + return; + } + + if (disposing) { - LibraryUpdateTimer.Dispose(); - LibraryUpdateTimer = null; + _libraryUpdateTimer?.Dispose(); } + + _libraryUpdateTimer = null; + + _libraryManager.ItemAdded -= OnLibraryManagerItemAdded; + _appHost.HasPendingRestartChanged -= OnAppHostHasPendingRestartChanged; + _appHost.HasUpdateAvailableChanged -= OnAppHostHasUpdateAvailableChanged; + _activityManager.EntryCreated -= OnActivityManagerEntryCreated; + + _disposed = true; } } } diff --git a/Emby.Notifications/NotificationManager.cs b/Emby.Notifications/NotificationManager.cs index eecbbea071..836aa3e729 100644 --- a/Emby.Notifications/NotificationManager.cs +++ b/Emby.Notifications/NotificationManager.cs @@ -16,20 +16,32 @@ using Microsoft.Extensions.Logging; namespace Emby.Notifications { + /// + /// NotificationManager class. + /// public class NotificationManager : INotificationManager { private readonly ILogger _logger; private readonly IUserManager _userManager; private readonly IServerConfigurationManager _config; - private INotificationService[] _services; - private INotificationTypeFactory[] _typeFactories; - - public NotificationManager(ILoggerFactory loggerFactory, IUserManager userManager, IServerConfigurationManager config) + private INotificationService[] _services = Array.Empty(); + private INotificationTypeFactory[] _typeFactories = Array.Empty(); + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// the user manager. + /// The server configuration manager. + public NotificationManager( + ILogger logger, + IUserManager userManager, + IServerConfigurationManager config) { + _logger = logger; _userManager = userManager; _config = config; - _logger = loggerFactory.CreateLogger(GetType().Name); } private NotificationOptions GetConfiguration() @@ -37,12 +49,14 @@ namespace Emby.Notifications return _config.GetConfiguration("notifications"); } + /// public Task SendNotification(NotificationRequest request, CancellationToken cancellationToken) { return SendNotification(request, null, cancellationToken); } - public Task SendNotification(NotificationRequest request, BaseItem relatedItem, CancellationToken cancellationToken) + /// + public Task SendNotification(NotificationRequest request, BaseItem? relatedItem, CancellationToken cancellationToken) { var notificationType = request.NotificationType; @@ -64,7 +78,8 @@ namespace Emby.Notifications return Task.WhenAll(tasks); } - private Task SendNotification(NotificationRequest request, + private Task SendNotification( + NotificationRequest request, INotificationService service, IEnumerable users, string title, @@ -79,7 +94,7 @@ namespace Emby.Notifications return Task.WhenAll(tasks); } - private IEnumerable GetUserIds(NotificationRequest request, NotificationOption options) + private IEnumerable GetUserIds(NotificationRequest request, NotificationOption? options) { if (request.SendToUserMode.HasValue) { @@ -109,7 +124,8 @@ namespace Emby.Notifications return request.UserIds; } - private async Task SendNotification(NotificationRequest request, + private async Task SendNotification( + NotificationRequest request, INotificationService service, string title, string description, @@ -161,12 +177,14 @@ namespace Emby.Notifications return GetConfiguration().IsServiceEnabled(service.Name, notificationType); } + /// public void AddParts(IEnumerable services, IEnumerable notificationTypeFactories) { _services = services.ToArray(); _typeFactories = notificationTypeFactories.ToArray(); } + /// public List GetNotificationTypes() { var list = _typeFactories.Select(i => @@ -180,7 +198,6 @@ namespace Emby.Notifications _logger.LogError(ex, "Error in GetNotificationTypes"); return new List(); } - }).SelectMany(i => i).ToList(); var config = GetConfiguration(); @@ -193,13 +210,13 @@ namespace Emby.Notifications return list; } + /// public IEnumerable GetNotificationServices() { return _services.Select(i => new NameIdPair { Name = i.Name, Id = i.Name.GetMD5().ToString("N", CultureInfo.InvariantCulture) - }).OrderBy(i => i.Name); } } diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index 64692c3703..8fd18466a1 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -18,6 +18,7 @@ false true true + enable