diff --git a/PlexRequests.Services.Tests/NotificationServiceTests.cs b/PlexRequests.Services.Tests/NotificationServiceTests.cs index ffbd75bfe..877ddcbbf 100644 --- a/PlexRequests.Services.Tests/NotificationServiceTests.cs +++ b/PlexRequests.Services.Tests/NotificationServiceTests.cs @@ -97,7 +97,7 @@ namespace PlexRequests.Services.Tests { Assert.DoesNotThrow( () => - { NotificationService.Publish(string.Empty, string.Empty); }); + { NotificationService.Publish(new NotificationModel()); }); } [Test] @@ -112,11 +112,11 @@ namespace PlexRequests.Services.Tests NotificationService.Subscribe(notificationMock2.Object); Assert.That(NotificationService.Observers.Count, Is.EqualTo(2)); + var model = new NotificationModel {Title = "abc", Body = "test"}; + NotificationService.Publish(model); - NotificationService.Publish("a","b"); - - notificationMock1.Verify(x => x.Notify("a","b"), Times.Once); - notificationMock2.Verify(x => x.Notify("a","b"), Times.Once); + notificationMock1.Verify(x => x.Notify(model), Times.Once); + notificationMock2.Verify(x => x.Notify(model), Times.Once); } } } \ No newline at end of file diff --git a/PlexRequests.Services/Notification/EmailMessageNotification.cs b/PlexRequests.Services/Notification/EmailMessageNotification.cs index 2c5c84158..43d567cd8 100644 --- a/PlexRequests.Services/Notification/EmailMessageNotification.cs +++ b/PlexRequests.Services/Notification/EmailMessageNotification.cs @@ -42,10 +42,12 @@ namespace PlexRequests.Services.Notification EmailNotificationSettings = settings; } - private static Logger Log = LogManager.GetCurrentClassLogger(); + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); private ISettingsService EmailNotificationSettings { get; } + private EmailNotificationSettings Settings => GetConfiguration(); public string NotificationName => "EmailMessageNotification"; - public bool Notify(string title, string requester) + + public bool Notify(NotificationModel model) { var configuration = GetConfiguration(); if (!ValidateConfiguration(configuration)) @@ -53,21 +55,62 @@ namespace PlexRequests.Services.Notification return false; } + switch (model.NotificationType) + { + case NotificationType.NewRequest: + return EmailNewRequest(model); + case NotificationType.Issue: + return EmailIssue(model); + case NotificationType.RequestAvailable: + break; + case NotificationType.RequestApproved: + break; + case NotificationType.AdminNote: + break; + default: + throw new ArgumentOutOfRangeException(); + } + + return false; + } + + private EmailNotificationSettings GetConfiguration() + { + var settings = EmailNotificationSettings.GetSettings(); + return settings; + } + + private bool ValidateConfiguration(EmailNotificationSettings settings) + { + if (!settings.Enabled) + { + return false; + } + if (string.IsNullOrEmpty(settings.EmailHost) || string.IsNullOrEmpty(settings.EmailUsername) || string.IsNullOrEmpty(settings.EmailPassword) || string.IsNullOrEmpty(settings.RecipientEmail) || string.IsNullOrEmpty(settings.EmailPort.ToString())) + { + return false; + } + + return true; + } + + private bool EmailNewRequest(NotificationModel model) + { var message = new MailMessage { IsBodyHtml = true, - To = { new MailAddress(configuration.RecipientEmail) }, - Body = $"User {requester} has requested {title}!", - From = new MailAddress(configuration.EmailUsername), - Subject = $"New Request for {title}!" + To = { new MailAddress(Settings.RecipientEmail) }, + Body = $"Hello! The user '{model.User}' has requested {model.Title}! Please log in to approve this request. Request Date: {model.DateTime.ToString("f")}", + From = new MailAddress(Settings.EmailUsername), + Subject = $"Plex Requests: New request for {model.Title}!" }; try { - using (var smtp = new SmtpClient(configuration.EmailHost, configuration.EmailPort)) + using (var smtp = new SmtpClient(Settings.EmailHost, Settings.EmailPort)) { - smtp.Credentials = new NetworkCredential(configuration.EmailUsername, configuration.EmailPassword); - smtp.EnableSsl = configuration.Ssl; + smtp.Credentials = new NetworkCredential(Settings.EmailUsername, Settings.EmailPassword); + smtp.EnableSsl = Settings.Ssl; smtp.Send(message); return true; } @@ -83,26 +126,36 @@ namespace PlexRequests.Services.Notification return false; } - private EmailNotificationSettings GetConfiguration() + private bool EmailIssue(NotificationModel model) { - var settings = EmailNotificationSettings.GetSettings(); - return settings; - } + var message = new MailMessage + { + IsBodyHtml = true, + To = { new MailAddress(Settings.RecipientEmail) }, + Body = $"Hello! The user '{model.User}' has reported a new issue {model.Body} for the title {model.Title}!", + From = new MailAddress(Settings.EmailUsername), + Subject = $"Plex Requests: New issue for {model.Title}!" + }; - private bool ValidateConfiguration(EmailNotificationSettings settings) - { - if (!settings.Enabled) + try { - return false; + using (var smtp = new SmtpClient(Settings.EmailHost, Settings.EmailPort)) + { + smtp.Credentials = new NetworkCredential(Settings.EmailUsername, Settings.EmailPassword); + smtp.EnableSsl = Settings.Ssl; + smtp.Send(message); + return true; + } } - if (string.IsNullOrEmpty(settings.EmailHost) || string.IsNullOrEmpty(settings.EmailUsername) - || string.IsNullOrEmpty(settings.EmailPassword) || string.IsNullOrEmpty(settings.RecipientEmail) - || string.IsNullOrEmpty(settings.EmailPort.ToString())) + catch (SmtpException smtp) { - return false; + Log.Fatal(smtp); } - - return true; + catch (Exception e) + { + Log.Fatal(e); + } + return false; } } } \ No newline at end of file diff --git a/PlexRequests.Services/Notification/INotification.cs b/PlexRequests.Services/Notification/INotification.cs index 6b85bd178..dd099747d 100644 --- a/PlexRequests.Services/Notification/INotification.cs +++ b/PlexRequests.Services/Notification/INotification.cs @@ -38,9 +38,8 @@ namespace PlexRequests.Services.Notification /// /// Notifies the specified title. /// - /// The title. - /// The requester. + /// The model. /// - bool Notify(string title, string requester); + bool Notify(NotificationModel model); } } \ No newline at end of file diff --git a/PlexRequests.Services/Notification/NotificationModel.cs b/PlexRequests.Services/Notification/NotificationModel.cs new file mode 100644 index 000000000..264d3e609 --- /dev/null +++ b/PlexRequests.Services/Notification/NotificationModel.cs @@ -0,0 +1,39 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: NotificationModel.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; + +namespace PlexRequests.Services.Notification +{ + public class NotificationModel + { + public string Title { get; set; } + public string Body { get; set; } + public DateTime DateTime { get; set; } + public NotificationType NotificationType { get; set; } + public string User { get; set; } + } +} \ No newline at end of file diff --git a/PlexRequests.Services/Notification/NotificationService.cs b/PlexRequests.Services/Notification/NotificationService.cs index 81968c28d..817dcd2d9 100644 --- a/PlexRequests.Services/Notification/NotificationService.cs +++ b/PlexRequests.Services/Notification/NotificationService.cs @@ -44,7 +44,7 @@ namespace PlexRequests.Services.Notification Observers = new Dictionary(); } - public static void Publish(string title, string requester) + public static void Publish(NotificationModel model) { Log.Trace("Notifying all observers: "); Log.Trace(Observers.DumpJson()); @@ -55,7 +55,7 @@ namespace PlexRequests.Services.Notification new Thread(() => { Thread.CurrentThread.IsBackground = true; - notification.Notify(title, requester); + notification.Notify(model); }).Start(); } } diff --git a/PlexRequests.Services/Notification/NotificationType.cs b/PlexRequests.Services/Notification/NotificationType.cs new file mode 100644 index 000000000..bf919fe39 --- /dev/null +++ b/PlexRequests.Services/Notification/NotificationType.cs @@ -0,0 +1,37 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: NotificationType.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 +namespace PlexRequests.Services.Notification +{ + public enum NotificationType + { + NewRequest, + Issue, + RequestAvailable, + RequestApproved, + AdminNote, + } +} diff --git a/PlexRequests.Services/Notification/PushbulletNotification.cs b/PlexRequests.Services/Notification/PushbulletNotification.cs index 5000919f7..be6af1ef2 100644 --- a/PlexRequests.Services/Notification/PushbulletNotification.cs +++ b/PlexRequests.Services/Notification/PushbulletNotification.cs @@ -39,27 +39,59 @@ namespace PlexRequests.Services.Notification public PushbulletNotification(IPushbulletApi pushbulletApi, ISettingsService settings) { PushbulletApi = pushbulletApi; - Settings = settings; + SettingsService = settings; } private IPushbulletApi PushbulletApi { get; } - private ISettingsService Settings { get; } + private ISettingsService SettingsService { get; } + private PushbulletNotificationSettings Settings => GetSettings(); private static Logger Log = LogManager.GetCurrentClassLogger(); public string NotificationName => "PushbulletNotification"; - public bool Notify(string title, string requester) + public bool Notify(NotificationModel model) { - var settings = GetSettings(); - - if (!settings.Enabled) + if (!ValidateConfiguration()) { return false; } - var message = $"{title} has been requested by {requester}"; - var pushTitle = $"Plex Requests: {title}"; + switch (model.NotificationType) + { + case NotificationType.NewRequest: + return PushNewRequest(model); + + case NotificationType.Issue: + return PushIssue(model); + + case NotificationType.RequestAvailable: + break; + case NotificationType.RequestApproved: + break; + case NotificationType.AdminNote: + break; + default: + throw new ArgumentOutOfRangeException(); + } + return false; + + } + + private bool ValidateConfiguration() + { + return !Settings.Enabled && !string.IsNullOrEmpty(Settings.AccessToken); + } + + private PushbulletNotificationSettings GetSettings() + { + return SettingsService.GetSettings(); + } + + private bool PushNewRequest(NotificationModel model) + { + var message = $"{model.Title} has been requested by user: {model.User}"; + var pushTitle = $"Plex Requests: {model.Title} has been requested!"; try { - var result = PushbulletApi.Push(settings.AccessToken, pushTitle, message, settings.DeviceIdentifier); + var result = PushbulletApi.Push(Settings.AccessToken, pushTitle, message, Settings.DeviceIdentifier); if (result != null) { return true; @@ -72,9 +104,23 @@ namespace PlexRequests.Services.Notification return false; } - private PushbulletNotificationSettings GetSettings() + private bool PushIssue(NotificationModel model) { - return Settings.GetSettings(); + var message = $"A new issue: {model.Title} has been reported by user: {model.User} for the title: {model.Body}"; + var pushTitle = $"Plex Requests: A new issue has been reported for {model.Body}"; + try + { + var result = PushbulletApi.Push(Settings.AccessToken, pushTitle, message, Settings.DeviceIdentifier); + if (result != null) + { + return true; + } + } + catch (Exception e) + { + Log.Fatal(e); + } + return false; } } } \ No newline at end of file diff --git a/PlexRequests.Services/PlexRequests.Services.csproj b/PlexRequests.Services/PlexRequests.Services.csproj index 29ad390d5..0317cf36b 100644 --- a/PlexRequests.Services/PlexRequests.Services.csproj +++ b/PlexRequests.Services/PlexRequests.Services.csproj @@ -79,7 +79,9 @@ + + diff --git a/PlexRequests.UI/Modules/SearchModule.cs b/PlexRequests.UI/Modules/SearchModule.cs index 7d1d0dcab..5fce72960 100644 --- a/PlexRequests.UI/Modules/SearchModule.cs +++ b/PlexRequests.UI/Modules/SearchModule.cs @@ -182,7 +182,7 @@ namespace PlexRequests.UI.Modules var movieInfo = movieApi.GetMovieInformation(movieId).Result; Log.Trace("Getting movie info from TheMovieDb"); Log.Trace(movieInfo.DumpJson); -//#if !DEBUG + //#if !DEBUG try { if (CheckIfTitleExistsInPlex(movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString())) @@ -194,7 +194,7 @@ namespace PlexRequests.UI.Modules { return Response.AsJson(new JsonResponseModel { Result = false, Message = $"We could not check if {movieInfo.Title} is in Plex, are you sure it's correctly setup?" }); } -//#endif + //#endif var model = new RequestedModel { @@ -241,7 +241,8 @@ namespace PlexRequests.UI.Modules Log.Debug("Adding movie to database requests"); var id = RequestService.AddRequest(model); - NotificationService.Publish(model.Title, model.RequestedBy); + var notificationModel = new NotificationModel { Title = model.Title, User = model.RequestedBy, DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest }; + NotificationService.Publish(notificationModel); return Response.AsJson(new JsonResponseModel { Result = true }); } @@ -269,7 +270,7 @@ namespace PlexRequests.UI.Modules var tvApi = new TvMazeApi(); var showInfo = tvApi.ShowLookupByTheTvDbId(showId); -//#if !DEBUG + //#if !DEBUG try { if (CheckIfTitleExistsInPlex(showInfo.name, showInfo.premiered?.Substring(0, 4))) // Take only the year Format = 2014-01-01 @@ -281,7 +282,7 @@ namespace PlexRequests.UI.Modules { return Response.AsJson(new JsonResponseModel { Result = false, Message = $"We could not check if {showInfo.name} is in Plex, are you sure it's correctly setup?" }); } -//#endif + //#endif DateTime firstAir; DateTime.TryParse(showInfo.premiered, out firstAir); @@ -344,7 +345,9 @@ namespace PlexRequests.UI.Modules } RequestService.AddRequest(model); - NotificationService.Publish(model.Title, model.RequestedBy); + + var notificationModel = new NotificationModel { Title = model.Title, User = model.RequestedBy, DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest }; + NotificationService.Publish(notificationModel); return Response.AsJson(new { Result = true }); } diff --git a/PlexRequests.UI/NLog.config b/PlexRequests.UI/NLog.config index 4810bdc88..39605a1f7 100644 --- a/PlexRequests.UI/NLog.config +++ b/PlexRequests.UI/NLog.config @@ -13,21 +13,22 @@ layout="${date} ${logger} ${level}: ${message}" /> - + + - + \ No newline at end of file diff --git a/PlexRequests.UI/Program.cs b/PlexRequests.UI/Program.cs index a16a5c393..80f0adebb 100644 --- a/PlexRequests.UI/Program.cs +++ b/PlexRequests.UI/Program.cs @@ -61,7 +61,6 @@ namespace PlexRequests.UI } port = portResult; } - Log.Trace("Getting product version"); WriteOutVersion(); @@ -126,7 +125,7 @@ namespace PlexRequests.UI { CommandType = CommandType.Text, ConnectionString = connectionString, - DBProvider = "Mono.Data.Sqlite, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756", + DBProvider = "Mono.Data.Sqlite.SqliteConnection, Mono.Data.Sqlite, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756", Name = "database" };