diff --git a/src/NzbDrone.Core/Annotations/FieldDefinitionAttribute.cs b/src/NzbDrone.Core/Annotations/FieldDefinitionAttribute.cs index 35dd1e5df..1da298c1d 100644 --- a/src/NzbDrone.Core/Annotations/FieldDefinitionAttribute.cs +++ b/src/NzbDrone.Core/Annotations/FieldDefinitionAttribute.cs @@ -35,6 +35,7 @@ public enum FieldType Action, Url, Captcha, - OAuth + OAuth, + Device } } diff --git a/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs b/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs index 066cd6f57..8634d08ed 100644 --- a/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs +++ b/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs @@ -1,6 +1,9 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; using FluentValidation.Results; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Validation; namespace NzbDrone.Core.Notifications.PushBullet { @@ -16,7 +19,6 @@ public PushBullet(IPushBulletProxy proxy) public override string Name => "Pushbullet"; public override string Link => "https://www.pushbullet.com/"; - public override void OnGrab(GrabMessage grabMessage) { _proxy.SendNotification(EPISODE_GRABBED_TITLE_BRANDED, grabMessage.Message, Settings); @@ -35,5 +37,36 @@ public override ValidationResult Test() return new ValidationResult(failures); } + + public override object RequestAction(string action, IDictionary query) + { + if (action == "getDevices") + { + // Return early if there is not an API key + if (Settings.ApiKey.IsNullOrWhiteSpace()) + { + return new + { + devices = new List() + }; + } + + Settings.Validate().Filter("ApiKey").ThrowOnError(); + var devices = _proxy.GetDevices(Settings); + + return new + { + devices = devices.Where(d => d.Nickname.IsNotNullOrWhiteSpace()) + .OrderBy(d => d.Nickname, StringComparer.InvariantCultureIgnoreCase) + .Select(d => new + { + id = d.Id, + name = d.Nickname + }) + }; + } + + return new { }; + } } } diff --git a/src/NzbDrone.Core/Notifications/PushBullet/PushBulletDevice.cs b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletDevice.cs new file mode 100644 index 000000000..5d88e906e --- /dev/null +++ b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletDevice.cs @@ -0,0 +1,14 @@ +using Newtonsoft.Json; + +namespace NzbDrone.Core.Notifications.PushBullet +{ + public class PushBulletDevice + { + [JsonProperty(PropertyName = "Iden")] + public string Id { get; set; } + + public string Nickname { get; set; } + public string Manufacturer { get; set; } + public string Model { get; set; } + } +} diff --git a/src/NzbDrone.Core/Notifications/PushBullet/PushBulletDevicesResponse.cs b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletDevicesResponse.cs new file mode 100644 index 000000000..ae50f82b0 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletDevicesResponse.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace NzbDrone.Core.Notifications.PushBullet +{ + public class PushBulletDevicesResponse + { + public List Devices { get; set; } + } +} diff --git a/src/NzbDrone.Core/Notifications/PushBullet/PushBulletProxy.cs b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletProxy.cs index 497d8e7f0..dcc94a116 100644 --- a/src/NzbDrone.Core/Notifications/PushBullet/PushBulletProxy.cs +++ b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletProxy.cs @@ -1,4 +1,5 @@ -using System; +using System; +using System.Collections.Generic; using System.Linq; using System.Net; using FluentValidation.Results; @@ -6,6 +7,7 @@ using RestSharp; using NzbDrone.Core.Rest; using NzbDrone.Common.Extensions; +using NzbDrone.Common.Serializer; using RestSharp.Authenticators; namespace NzbDrone.Core.Notifications.PushBullet @@ -13,13 +15,15 @@ namespace NzbDrone.Core.Notifications.PushBullet public interface IPushBulletProxy { void SendNotification(string title, string message, PushBulletSettings settings); + List GetDevices(PushBulletSettings settings); ValidationFailure Test(PushBulletSettings settings); } public class PushBulletProxy : IPushBulletProxy { private readonly Logger _logger; - private const string URL = "https://api.pushbullet.com/v2/pushes"; + private const string PUSH_URL = "https://api.pushbullet.com/v2/pushes"; + private const string DEVICE_URL = "https://api.pushbullet.com/v2/devices"; public PushBulletProxy(Logger logger) { @@ -88,6 +92,30 @@ public void SendNotification(string title, string message, PushBulletSettings se } } + public List GetDevices(PushBulletSettings settings) + { + try + { + var client = RestClientFactory.BuildClient(DEVICE_URL); + var request = new RestRequest(Method.GET); + + client.Authenticator = new HttpBasicAuthenticator(settings.ApiKey, string.Empty); + var response = client.ExecuteAndValidate(request); + + return Json.Deserialize(response.Content).Devices; + } + catch (RestException ex) + { + if (ex.Response.StatusCode == HttpStatusCode.Unauthorized) + { + _logger.Error(ex, "Access token is invalid"); + throw; + } + } + + return new List(); + } + public ValidationFailure Test(PushBulletSettings settings) { try @@ -147,7 +175,7 @@ private void SendNotification(string title, string message, RestRequest request, { try { - var client = RestClientFactory.BuildClient(URL); + var client = RestClientFactory.BuildClient(PUSH_URL); request.AddParameter("type", "note"); request.AddParameter("title", title); @@ -165,7 +193,7 @@ private void SendNotification(string title, string message, RestRequest request, { if (ex.Response.StatusCode == HttpStatusCode.Unauthorized) { - _logger.Error(ex, "API Key is invalid"); + _logger.Error(ex, "Access token is invalid"); throw; } diff --git a/src/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs index d2c6d1e4c..4e8ee404f 100644 --- a/src/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs +++ b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using FluentValidation; using NzbDrone.Core.Annotations; using NzbDrone.Core.ThingiProvider; @@ -20,14 +20,14 @@ public class PushBulletSettings : IProviderConfig public PushBulletSettings() { - DeviceIds = new string[]{}; - ChannelTags = new string[]{}; + DeviceIds = new string[] { }; + ChannelTags = new string[] { }; } - [FieldDefinition(0, Label = "API Key", HelpLink = "https://www.pushbullet.com/")] + [FieldDefinition(0, Label = "Access Token", HelpLink = "https://www.pushbullet.com/#settings/account")] public string ApiKey { get; set; } - [FieldDefinition(1, Label = "Device IDs", HelpText = "List of device IDs, use device_iden in the device's URL on pushbullet.com (leave blank to send to all devices)", Type = FieldType.Tag)] + [FieldDefinition(1, Label = "Device IDs", HelpText = "List of device IDs (leave blank to send to all devices)", Type = FieldType.Device)] public IEnumerable DeviceIds { get; set; } [FieldDefinition(2, Label = "Channel Tags", HelpText = "List of Channel Tags to send notifications to", Type = FieldType.Tag)] diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 1ef0755f8..728484f11 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -778,6 +778,8 @@ + + @@ -1330,4 +1332,4 @@ --> - + \ No newline at end of file