diff --git a/PlexRequests.Api.Interfaces/IPushoverApi.cs b/PlexRequests.Api.Interfaces/IPushoverApi.cs
new file mode 100644
index 000000000..42e3f2217
--- /dev/null
+++ b/PlexRequests.Api.Interfaces/IPushoverApi.cs
@@ -0,0 +1,36 @@
+#region Copyright
+// /************************************************************************
+// Copyright (c) 2016 Jamie Rees
+// File: IPushoverApi.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 PlexRequests.Api.Models.Notifications;
+
+namespace PlexRequests.Api.Interfaces
+{
+ public interface IPushoverApi
+ {
+ PushoverResponse Push(string accessToken, string message, string userToken);
+ }
+}
\ No newline at end of file
diff --git a/PlexRequests.Api.Interfaces/PlexRequests.Api.Interfaces.csproj b/PlexRequests.Api.Interfaces/PlexRequests.Api.Interfaces.csproj
index 3ea7be621..7522c8156 100644
--- a/PlexRequests.Api.Interfaces/PlexRequests.Api.Interfaces.csproj
+++ b/PlexRequests.Api.Interfaces/PlexRequests.Api.Interfaces.csproj
@@ -49,6 +49,7 @@
+
diff --git a/PlexRequests.Api.Models/Notifications/PushoverResponse.cs b/PlexRequests.Api.Models/Notifications/PushoverResponse.cs
new file mode 100644
index 000000000..94849fba1
--- /dev/null
+++ b/PlexRequests.Api.Models/Notifications/PushoverResponse.cs
@@ -0,0 +1,34 @@
+#region Copyright
+// /************************************************************************
+// Copyright (c) 2016 Jamie Rees
+// File: PushoverResponse.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.Api.Models.Notifications
+{
+ public class PushoverResponse
+ {
+ public int status { get; set; }
+ public string request { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/PlexRequests.Api.Models/PlexRequests.Api.Models.csproj b/PlexRequests.Api.Models/PlexRequests.Api.Models.csproj
index bd3151c55..8a4da4222 100644
--- a/PlexRequests.Api.Models/PlexRequests.Api.Models.csproj
+++ b/PlexRequests.Api.Models/PlexRequests.Api.Models.csproj
@@ -50,6 +50,7 @@
+
diff --git a/PlexRequests.Api/PlexRequests.Api.csproj b/PlexRequests.Api/PlexRequests.Api.csproj
index 2f204c975..6422dfd6f 100644
--- a/PlexRequests.Api/PlexRequests.Api.csproj
+++ b/PlexRequests.Api/PlexRequests.Api.csproj
@@ -72,6 +72,7 @@
MockApiData.resx
+
diff --git a/PlexRequests.Api/PushoverApi.cs b/PlexRequests.Api/PushoverApi.cs
new file mode 100644
index 000000000..1de5694aa
--- /dev/null
+++ b/PlexRequests.Api/PushoverApi.cs
@@ -0,0 +1,56 @@
+#region Copyright
+// /************************************************************************
+// Copyright (c) 2016 Jamie Rees
+// File: PlexApi.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 Nancy.Helpers;
+using PlexRequests.Api.Interfaces;
+using PlexRequests.Api.Models.Notifications;
+
+using RestSharp;
+
+namespace PlexRequests.Api
+{
+ public class PushoverApi : IPushoverApi
+ {
+ public PushoverResponse Push(string accessToken, string message, string userToken)
+ {
+ var request = new RestRequest
+ {
+ Method = Method.POST,
+ Resource = "messages.json?token={token}&user={user}&message={message}"
+ };
+
+ request.AddUrlSegment("token", accessToken);
+ request.AddUrlSegment("message", message);
+ request.AddUrlSegment("user", userToken);
+
+
+ var api = new ApiRequest();
+ return api.ExecuteJson(request, new Uri("https://api.pushover.net/1"));
+ }
+ }
+}
+
diff --git a/PlexRequests.Core/PlexRequests.Core.csproj b/PlexRequests.Core/PlexRequests.Core.csproj
index e1c4ee1f3..9b698ab96 100644
--- a/PlexRequests.Core/PlexRequests.Core.csproj
+++ b/PlexRequests.Core/PlexRequests.Core.csproj
@@ -73,6 +73,7 @@
+
diff --git a/PlexRequests.Core/SettingModels/PushoverNotificationSettings.cs b/PlexRequests.Core/SettingModels/PushoverNotificationSettings.cs
new file mode 100644
index 000000000..ac6c4c435
--- /dev/null
+++ b/PlexRequests.Core/SettingModels/PushoverNotificationSettings.cs
@@ -0,0 +1,9 @@
+namespace PlexRequests.Core.SettingModels
+{
+ public class PushoverNotificationSettings : Settings
+ {
+ public bool Enabled { get; set; }
+ public string AccessToken { get; set; }
+ public string UserToken { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/PlexRequests.Services/Notification/PushoverNotification.cs b/PlexRequests.Services/Notification/PushoverNotification.cs
new file mode 100644
index 000000000..2c3bf6bfe
--- /dev/null
+++ b/PlexRequests.Services/Notification/PushoverNotification.cs
@@ -0,0 +1,132 @@
+#region Copyright
+// /************************************************************************
+// Copyright (c) 2016 Jamie Rees
+// File: PushbulletNotification.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 NLog;
+
+using PlexRequests.Api.Interfaces;
+using PlexRequests.Core;
+using PlexRequests.Core.SettingModels;
+
+namespace PlexRequests.Services.Notification
+{
+ public class PushoverNotification : INotification
+ {
+ public PushoverNotification(IPushoverApi pushoverApi, ISettingsService settings)
+ {
+ PushoverApi = pushoverApi;
+ SettingsService = settings;
+ }
+ private IPushoverApi PushoverApi { get; }
+ private ISettingsService SettingsService { get; }
+ private PushoverNotificationSettings Settings => GetSettings();
+
+ private static Logger Log = LogManager.GetCurrentClassLogger();
+ public string NotificationName => "PushoverNotification";
+ public bool Notify(NotificationModel model)
+ {
+ if (!ValidateConfiguration())
+ {
+ return false;
+ }
+
+ 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()
+ {
+ if (!Settings.Enabled)
+ {
+ return false;
+ }
+ if (string.IsNullOrEmpty(Settings.AccessToken) || string.IsNullOrEmpty(Settings.UserToken))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private PushoverNotificationSettings GetSettings()
+ {
+ return SettingsService.GetSettings();
+ }
+
+ private bool PushNewRequest(NotificationModel model)
+ {
+ var message = $"Plex Requests: {model.Title} has been requested by user: {model.User}";
+ try
+ {
+ var result = PushoverApi.Push(Settings.AccessToken, message, Settings.UserToken);
+ if (result?.status == 1)
+ {
+ return true;
+ }
+ }
+ catch (Exception e)
+ {
+ Log.Fatal(e);
+ }
+ return false;
+ }
+
+ private bool PushIssue(NotificationModel model)
+ {
+ var message = $"Plex Requests: A new issue: {model.Body} has been reported by user: {model.User} for the title: {model.Title}";
+ try
+ {
+ var result = PushoverApi.Push(Settings.AccessToken, message, Settings.UserToken);
+ 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 0317cf36b..e1ba81532 100644
--- a/PlexRequests.Services/PlexRequests.Services.csproj
+++ b/PlexRequests.Services/PlexRequests.Services.csproj
@@ -82,6 +82,7 @@
+
diff --git a/PlexRequests.UI.Tests/AdminModuleTests.cs b/PlexRequests.UI.Tests/AdminModuleTests.cs
index e42eb4a13..08c84235b 100644
--- a/PlexRequests.UI.Tests/AdminModuleTests.cs
+++ b/PlexRequests.UI.Tests/AdminModuleTests.cs
@@ -55,9 +55,11 @@ namespace PlexRequests.UI.Tests
private Mock> SickRageSettingsMock { get; set; }
private Mock> EmailMock { get; set; }
private Mock> PushbulletSettings { get; set; }
+ private Mock> PushoverSettings { get; set; }
private Mock PlexMock { get; set; }
private Mock SonarrApiMock { get; set; }
private Mock PushbulletApi { get; set; }
+ private Mock PushoverApi { get; set; }
private Mock CpApi { get; set; }
private ConfigurableBootstrapper Bootstrapper { get; set; }
@@ -83,6 +85,8 @@ namespace PlexRequests.UI.Tests
PushbulletSettings = new Mock>();
CpApi = new Mock();
SickRageSettingsMock = new Mock>();
+ PushoverSettings = new Mock>();
+ PushoverApi = new Mock();
Bootstrapper = new ConfigurableBootstrapper(with =>
{
@@ -99,6 +103,8 @@ namespace PlexRequests.UI.Tests
with.Dependency(PushbulletSettings.Object);
with.Dependency(CpApi.Object);
with.Dependency(SickRageSettingsMock.Object);
+ with.Dependency(PushoverSettings.Object);
+ with.Dependency(PushoverApi.Object);
with.RootPathProvider();
with.RequestStartup((container, pipelines, context) =>
{
diff --git a/PlexRequests.UI/Bootstrapper.cs b/PlexRequests.UI/Bootstrapper.cs
index 8fd5aad2b..9c07266e9 100644
--- a/PlexRequests.UI/Bootstrapper.cs
+++ b/PlexRequests.UI/Bootstrapper.cs
@@ -74,6 +74,7 @@ namespace PlexRequests.UI
container.Register, SettingsServiceV2>();
container.Register, SettingsServiceV2>();
container.Register, SettingsServiceV2>();
+ container.Register, SettingsServiceV2>();
// Repo's
container.Register, GenericRepository>();
@@ -88,6 +89,7 @@ namespace PlexRequests.UI
// Api's
container.Register();
container.Register();
+ container.Register();
container.Register();
container.Register();
container.Register();
@@ -137,7 +139,14 @@ namespace PlexRequests.UI
var pushbulletSettings = pushbulletService.GetSettings();
if (pushbulletSettings.Enabled)
{
- NotificationService.Subscribe(new PushbulletNotification(container.Resolve(), container.Resolve>()));
+ NotificationService.Subscribe(new PushbulletNotification(container.Resolve(), pushbulletService));
+ }
+
+ var pushoverService = container.Resolve>();
+ var pushoverSettings = pushoverService.GetSettings();
+ if (pushoverSettings.Enabled)
+ {
+ NotificationService.Subscribe(new PushoverNotification(container.Resolve(), pushoverService));
}
}
}
diff --git a/PlexRequests.UI/Modules/AdminModule.cs b/PlexRequests.UI/Modules/AdminModule.cs
index 7876aa41c..d97d06129 100644
--- a/PlexRequests.UI/Modules/AdminModule.cs
+++ b/PlexRequests.UI/Modules/AdminModule.cs
@@ -59,9 +59,11 @@ namespace PlexRequests.UI.Modules
private ISettingsService SickRageService { get; }
private ISettingsService EmailService { get; }
private ISettingsService PushbulletService { get; }
+ private ISettingsService PushoverService { get; }
private IPlexApi PlexApi { get; }
private ISonarrApi SonarrApi { get; }
- private PushbulletApi PushbulletApi { get; }
+ private IPushbulletApi PushbulletApi { get; }
+ private IPushoverApi PushoverApi { get; }
private ICouchPotatoApi CpApi { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
@@ -76,7 +78,9 @@ namespace PlexRequests.UI.Modules
IPlexApi plexApi,
ISettingsService pbSettings,
PushbulletApi pbApi,
- ICouchPotatoApi cpApi) : base("admin")
+ ICouchPotatoApi cpApi,
+ ISettingsService pushoverSettings,
+ IPushoverApi pushoverApi) : base("admin")
{
RpService = rpService;
CpService = cpService;
@@ -90,6 +94,8 @@ namespace PlexRequests.UI.Modules
PushbulletApi = pbApi;
CpApi = cpApi;
SickRageService = sickrage;
+ PushoverService = pushoverSettings;
+ PushoverApi = pushoverApi;
#if !DEBUG
this.RequiresAuthentication();
@@ -126,6 +132,9 @@ namespace PlexRequests.UI.Modules
Get["/pushbulletnotification"] = _ => PushbulletNotifications();
Post["/pushbulletnotification"] = _ => SavePushbulletNotifications();
+
+ Get["/pushovernotification"] = _ => PushoverNotifications();
+ Post["/pushovernotification"] = _ => SavePushoverNotifications();
}
private Negotiator Authentication()
@@ -415,6 +424,38 @@ namespace PlexRequests.UI.Modules
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
}
+ private Negotiator PushoverNotifications()
+ {
+ var settings = PushoverService.GetSettings();
+ return View["PushoverNotifications", settings];
+ }
+
+ private Response SavePushoverNotifications()
+ {
+ var settings = this.Bind();
+ var valid = this.Validate(settings);
+ if (!valid.IsValid)
+ {
+ return Response.AsJson(valid.SendJsonError());
+ }
+ Log.Trace(settings.DumpJson());
+
+ var result = PushoverService.SaveSettings(settings);
+ if (settings.Enabled)
+ {
+ NotificationService.Subscribe(new PushoverNotification(PushoverApi, PushoverService));
+ }
+ else
+ {
+ NotificationService.UnSubscribe(new PushoverNotification(PushoverApi, PushoverService));
+ }
+
+ Log.Info("Saved email settings, result: {0}", result);
+ return Response.AsJson(result
+ ? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Pushbullet Notifications!" }
+ : new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
+ }
+
private Response GetCpProfiles()
{
var settings = this.Bind();
diff --git a/PlexRequests.UI/PlexRequests.UI.csproj b/PlexRequests.UI/PlexRequests.UI.csproj
index 44ec9805c..a62ab2592 100644
--- a/PlexRequests.UI/PlexRequests.UI.csproj
+++ b/PlexRequests.UI/PlexRequests.UI.csproj
@@ -166,6 +166,7 @@
+
@@ -335,6 +336,9 @@
Always
+
+ Always
+ web.config
diff --git a/PlexRequests.UI/Validators/PushoverSettingsValidator.cs b/PlexRequests.UI/Validators/PushoverSettingsValidator.cs
new file mode 100644
index 000000000..55a218aa0
--- /dev/null
+++ b/PlexRequests.UI/Validators/PushoverSettingsValidator.cs
@@ -0,0 +1,41 @@
+#region Copyright
+// /************************************************************************
+// Copyright (c) 2016 Jamie Rees
+// File: SonarrValidator.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 FluentValidation;
+
+using PlexRequests.Core.SettingModels;
+
+namespace PlexRequests.UI.Validators
+{
+ public class PushoverSettingsValidator : AbstractValidator
+ {
+ public PushoverSettingsValidator()
+ {
+ RuleFor(request => request.AccessToken).NotEmpty().WithMessage("You must specify a API Token.");
+ RuleFor(request => request.UserToken).NotEmpty().WithMessage("You must specify a User Token.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/PlexRequests.UI/Views/Admin/PushoverNotifications.cshtml b/PlexRequests.UI/Views/Admin/PushoverNotifications.cshtml
new file mode 100644
index 000000000..0877739d0
--- /dev/null
+++ b/PlexRequests.UI/Views/Admin/PushoverNotifications.cshtml
@@ -0,0 +1,74 @@
+@Html.Partial("_Sidebar")
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PlexRequests.UI/Views/Admin/_Sidebar.cshtml b/PlexRequests.UI/Views/Admin/_Sidebar.cshtml
index 2877729c7..51e181921 100644
--- a/PlexRequests.UI/Views/Admin/_Sidebar.cshtml
+++ b/PlexRequests.UI/Views/Admin/_Sidebar.cshtml
@@ -71,6 +71,15 @@
Pushbullet Notifications
}
+ @if (Context.Request.Path == "/admin/pushovernotification")
+ {
+ Pushover Notifications
+ }
+ else
+ {
+ Pushover Notifications
+ }
+
@if (Context.Request.Path == "/admin/status")
{
Status