diff --git a/PlexRequests.Services/Interfaces/INotificationEngine.cs b/PlexRequests.Services/Interfaces/INotificationEngine.cs new file mode 100644 index 000000000..ba53eb9bf --- /dev/null +++ b/PlexRequests.Services/Interfaces/INotificationEngine.cs @@ -0,0 +1,39 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: INotificationEngine.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using System.Collections.Generic; +using System.Threading.Tasks; +using PlexRequests.Store; + +namespace PlexRequests.Services.Interfaces +{ + public interface INotificationEngine + { + Task NotifyUsers(IEnumerable modelChanged, string apiKey); + Task NotifyUsers(RequestedModel modelChanged, string apiKey); + } +} \ No newline at end of file diff --git a/PlexRequests.Services/Jobs/PlexAvailabilityChecker.cs b/PlexRequests.Services/Jobs/PlexAvailabilityChecker.cs index e58a18c17..c72ed45d5 100644 --- a/PlexRequests.Services/Jobs/PlexAvailabilityChecker.cs +++ b/PlexRequests.Services/Jobs/PlexAvailabilityChecker.cs @@ -53,7 +53,7 @@ namespace PlexRequests.Services.Jobs public class PlexAvailabilityChecker : IJob, IAvailabilityChecker { public PlexAvailabilityChecker(ISettingsService plexSettings, IRequestService request, IPlexApi plex, ICacheProvider cache, - INotificationService notify, IJobRecord rec, IRepository users, IRepository repo) + INotificationService notify, IJobRecord rec, IRepository users, IRepository repo, INotificationEngine e) { Plex = plexSettings; RequestService = request; @@ -63,6 +63,7 @@ namespace PlexRequests.Services.Jobs Job = rec; UserNotifyRepo = users; EpisodeRepo = repo; + NotificationEngine = e; } private ISettingsService Plex { get; } @@ -74,6 +75,9 @@ namespace PlexRequests.Services.Jobs private INotificationService Notification { get; } private IJobRecord Job { get; } private IRepository UserNotifyRepo { get; } + private INotificationEngine NotificationEngine { get; } + + public void CheckAndUpdateAll() { var plexSettings = Plex.GetSettings(); @@ -148,7 +152,7 @@ namespace PlexRequests.Services.Jobs if (modifiedModel.Any()) { - NotifyUsers(modifiedModel, plexSettings.PlexAuthToken); + NotificationEngine.NotifyUsers(modifiedModel, plexSettings.PlexAuthToken); RequestService.BatchUpdate(modifiedModel); } @@ -462,63 +466,6 @@ namespace PlexRequests.Services.Jobs return true; } - private void NotifyUsers(IEnumerable modelChanged, string apiKey) - { - try - { - var plexUser = PlexApi.GetUsers(apiKey); - var userAccount = PlexApi.GetAccount(apiKey); - - var adminUsername = userAccount.Username ?? string.Empty; - - var users = UserNotifyRepo.GetAll().ToList(); - Log.Debug("Notifying Users Count {0}", users.Count); - foreach (var model in modelChanged) - { - var selectedUsers = users.Select(x => x.Username).Intersect(model.RequestedUsers); - foreach (var user in selectedUsers) - { - Log.Info("Notifying user {0}", user); - if (user == adminUsername) - { - Log.Info("This user is the Plex server owner"); - PublishUserNotification(userAccount.Username, userAccount.Email, model.Title); - return; - } - - var email = plexUser.User.FirstOrDefault(x => x.Username == user); - if (email == null) - { - Log.Info("There is no email address for this Plex user, cannot send notification"); - // We do not have a plex user that requested this! - continue; - } - - Log.Info("Sending notification to: {0} at: {1}, for title: {2}", email.Username, email.Email, model.Title); - PublishUserNotification(email.Username, email.Email, model.Title); - } - } - } - catch (Exception e) - { - Log.Error(e); - } - } - - private void PublishUserNotification(string username, string email, string title) - { - var notificationModel = new NotificationModel - { - User = username, - UserEmail = email, - NotificationType = NotificationType.RequestAvailable, - Title = title - }; - - // Send the notification to the user. - Notification.Publish(notificationModel); - } - public void Execute(IJobExecutionContext context) { try diff --git a/PlexRequests.Services/Notification/NotificationEngine.cs b/PlexRequests.Services/Notification/NotificationEngine.cs new file mode 100644 index 000000000..ccbe07fec --- /dev/null +++ b/PlexRequests.Services/Notification/NotificationEngine.cs @@ -0,0 +1,156 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: NotificationEngine.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using NLog; +using NLog.Fluent; +using PlexRequests.Api; +using PlexRequests.Api.Interfaces; +using PlexRequests.Core.Models; +using PlexRequests.Services.Interfaces; +using PlexRequests.Store; +using PlexRequests.Store.Models; +using PlexRequests.Store.Repository; + +namespace PlexRequests.Services.Notification +{ + public class NotificationEngine : INotificationEngine + { + public NotificationEngine(IPlexApi p, IRepository repo, INotificationService service) + { + PlexApi = p; + UserNotifyRepo = repo; + Notification = service; + } + + private IPlexApi PlexApi { get; } + private IRepository UserNotifyRepo { get; } + private static Logger Log = LogManager.GetCurrentClassLogger(); + private INotificationService Notification { get; } + + public async Task NotifyUsers(IEnumerable modelChanged, string apiKey) + { + try + { + var plexUser = PlexApi.GetUsers(apiKey); + var userAccount = PlexApi.GetAccount(apiKey); + + var adminUsername = userAccount.Username ?? string.Empty; + + var users = UserNotifyRepo.GetAll().ToList(); + Log.Debug("Notifying Users Count {0}", users.Count); + foreach (var model in modelChanged) + { + var selectedUsers = users.Select(x => x.Username).Intersect(model.RequestedUsers, StringComparer.CurrentCultureIgnoreCase); + foreach (var user in selectedUsers) + { + Log.Info("Notifying user {0}", user); + if (user.Equals(adminUsername, StringComparison.CurrentCultureIgnoreCase)) + { + Log.Info("This user is the Plex server owner"); + await PublishUserNotification(userAccount.Username, userAccount.Email, model.Title); + return; + } + + var email = plexUser.User.FirstOrDefault(x => x.Username.Equals(user, StringComparison.CurrentCultureIgnoreCase)); + if (email == null) + { + Log.Info("There is no email address for this Plex user, cannot send notification"); + // We do not have a plex user that requested this! + continue; + } + + Log.Info("Sending notification to: {0} at: {1}, for title: {2}", email.Username, email.Email, model.Title); + await PublishUserNotification(email.Username, email.Email, model.Title); + } + } + } + catch (Exception e) + { + Log.Error(e); + } + } + + public async Task NotifyUsers(RequestedModel model, string apiKey) + { + try + { + var plexUser = PlexApi.GetUsers(apiKey); + var userAccount = PlexApi.GetAccount(apiKey); + + var adminUsername = userAccount.Username ?? string.Empty; + + var users = UserNotifyRepo.GetAll().ToList(); + Log.Debug("Notifying Users Count {0}", users.Count); + + var selectedUsers = users.Select(x => x.Username).Intersect(model.RequestedUsers, StringComparer.CurrentCultureIgnoreCase); + foreach (var user in selectedUsers) + { + Log.Info("Notifying user {0}", user); + if (user.Equals(adminUsername, StringComparison.CurrentCultureIgnoreCase)) + { + Log.Info("This user is the Plex server owner"); + await PublishUserNotification(userAccount.Username, userAccount.Email, model.Title); + return; + } + + var email = plexUser.User.FirstOrDefault(x => x.Username.Equals(user, StringComparison.CurrentCultureIgnoreCase)); + if (email == null) + { + Log.Info("There is no email address for this Plex user, cannot send notification"); + // We do not have a plex user that requested this! + continue; + } + + Log.Info("Sending notification to: {0} at: {1}, for title: {2}", email.Username, email.Email, model.Title); + await PublishUserNotification(email.Username, email.Email, model.Title); + } + } + catch (Exception e) + { + Log.Error(e); + } + } + + private async Task PublishUserNotification(string username, string email, string title) + { + var notificationModel = new NotificationModel + { + User = username, + UserEmail = email, + NotificationType = NotificationType.RequestAvailable, + Title = title + }; + + // Send the notification to the user. + await Notification.Publish(notificationModel); + } + } +} \ No newline at end of file diff --git a/PlexRequests.Services/PlexRequests.Services.csproj b/PlexRequests.Services/PlexRequests.Services.csproj index df4d694c9..6aed947bc 100644 --- a/PlexRequests.Services/PlexRequests.Services.csproj +++ b/PlexRequests.Services/PlexRequests.Services.csproj @@ -75,6 +75,7 @@ + @@ -97,6 +98,7 @@ + diff --git a/PlexRequests.UI/Modules/RequestsModule.cs b/PlexRequests.UI/Modules/RequestsModule.cs index cb8ed6882..8a2a9821a 100644 --- a/PlexRequests.UI/Modules/RequestsModule.cs +++ b/PlexRequests.UI/Modules/RequestsModule.cs @@ -67,7 +67,8 @@ namespace PlexRequests.UI.Modules ISonarrApi sonarrApi, ISickRageApi sickRageApi, ICacheProvider cache, - IAnalytics an) : base("requests", prSettings) + IAnalytics an, + INotificationEngine engine) : base("requests", prSettings) { Service = service; PrSettings = prSettings; @@ -81,6 +82,7 @@ namespace PlexRequests.UI.Modules CpApi = cpApi; Cache = cache; Analytics = an; + NotificationEngine = engine; Get["/", true] = async (x, ct) => await LoadRequests(); Get["/movies", true] = async (x, ct) => await GetMovies(); @@ -108,6 +110,7 @@ namespace PlexRequests.UI.Modules private ISickRageApi SickRageApi { get; } private ICouchPotatoApi CpApi { get; } private ICacheProvider Cache { get; } + private INotificationEngine NotificationEngine { get; } private async Task LoadRequests() { @@ -376,6 +379,8 @@ namespace PlexRequests.UI.Modules originalRequest.Available = available; var result = await Service.UpdateRequestAsync(originalRequest); + var plexService = await PlexSettings.GetSettingsAsync(); + await NotificationEngine.NotifyUsers(originalRequest, plexService.PlexAuthToken); return Response.AsJson(result ? new { Result = true, Available = available, Message = string.Empty } : new { Result = false, Available = false, Message = "Could not update the availability, please try again or check the logs" });