New: Choose PushBullet device from the UI

This commit is contained in:
Mark McDowall 2018-09-02 12:13:41 -07:00 committed by Taloth Saldono
parent d52b63e5e9
commit a86397f4bd
7 changed files with 100 additions and 13 deletions

View File

@ -35,6 +35,7 @@ namespace NzbDrone.Core.Annotations
Action, Action,
Url, Url,
Captcha, Captcha,
OAuth OAuth,
Device
} }
} }

View File

@ -1,6 +1,9 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq;
using FluentValidation.Results; using FluentValidation.Results;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Notifications.PushBullet namespace NzbDrone.Core.Notifications.PushBullet
{ {
@ -16,7 +19,6 @@ namespace NzbDrone.Core.Notifications.PushBullet
public override string Name => "Pushbullet"; public override string Name => "Pushbullet";
public override string Link => "https://www.pushbullet.com/"; public override string Link => "https://www.pushbullet.com/";
public override void OnGrab(GrabMessage grabMessage) public override void OnGrab(GrabMessage grabMessage)
{ {
_proxy.SendNotification(EPISODE_GRABBED_TITLE_BRANDED, grabMessage.Message, Settings); _proxy.SendNotification(EPISODE_GRABBED_TITLE_BRANDED, grabMessage.Message, Settings);
@ -35,5 +37,36 @@ namespace NzbDrone.Core.Notifications.PushBullet
return new ValidationResult(failures); return new ValidationResult(failures);
} }
public override object RequestAction(string action, IDictionary<string, string> query)
{
if (action == "getDevices")
{
// Return early if there is not an API key
if (Settings.ApiKey.IsNullOrWhiteSpace())
{
return new
{
devices = new List<object>()
};
}
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 { };
}
} }
} }

View File

@ -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; }
}
}

View File

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace NzbDrone.Core.Notifications.PushBullet
{
public class PushBulletDevicesResponse
{
public List<PushBulletDevice> Devices { get; set; }
}
}

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using FluentValidation.Results; using FluentValidation.Results;
@ -6,6 +7,7 @@ using NLog;
using RestSharp; using RestSharp;
using NzbDrone.Core.Rest; using NzbDrone.Core.Rest;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Serializer;
using RestSharp.Authenticators; using RestSharp.Authenticators;
namespace NzbDrone.Core.Notifications.PushBullet namespace NzbDrone.Core.Notifications.PushBullet
@ -13,13 +15,15 @@ namespace NzbDrone.Core.Notifications.PushBullet
public interface IPushBulletProxy public interface IPushBulletProxy
{ {
void SendNotification(string title, string message, PushBulletSettings settings); void SendNotification(string title, string message, PushBulletSettings settings);
List<PushBulletDevice> GetDevices(PushBulletSettings settings);
ValidationFailure Test(PushBulletSettings settings); ValidationFailure Test(PushBulletSettings settings);
} }
public class PushBulletProxy : IPushBulletProxy public class PushBulletProxy : IPushBulletProxy
{ {
private readonly Logger _logger; 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) public PushBulletProxy(Logger logger)
{ {
@ -88,6 +92,30 @@ namespace NzbDrone.Core.Notifications.PushBullet
} }
} }
public List<PushBulletDevice> 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<PushBulletDevicesResponse>(response.Content).Devices;
}
catch (RestException ex)
{
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
{
_logger.Error(ex, "Access token is invalid");
throw;
}
}
return new List<PushBulletDevice>();
}
public ValidationFailure Test(PushBulletSettings settings) public ValidationFailure Test(PushBulletSettings settings)
{ {
try try
@ -147,7 +175,7 @@ namespace NzbDrone.Core.Notifications.PushBullet
{ {
try try
{ {
var client = RestClientFactory.BuildClient(URL); var client = RestClientFactory.BuildClient(PUSH_URL);
request.AddParameter("type", "note"); request.AddParameter("type", "note");
request.AddParameter("title", title); request.AddParameter("title", title);
@ -165,7 +193,7 @@ namespace NzbDrone.Core.Notifications.PushBullet
{ {
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized) if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
{ {
_logger.Error(ex, "API Key is invalid"); _logger.Error(ex, "Access token is invalid");
throw; throw;
} }

View File

@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using FluentValidation; using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.ThingiProvider;
@ -24,10 +24,10 @@ namespace NzbDrone.Core.Notifications.PushBullet
ChannelTags = 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; } 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<string> DeviceIds { get; set; } public IEnumerable<string> DeviceIds { get; set; }
[FieldDefinition(2, Label = "Channel Tags", HelpText = "List of Channel Tags to send notifications to", Type = FieldType.Tag)] [FieldDefinition(2, Label = "Channel Tags", HelpText = "List of Channel Tags to send notifications to", Type = FieldType.Tag)]

View File

@ -778,6 +778,8 @@
<Compile Include="Notifications\Plex\PlexTv\PlexTvPinResponse.cs" /> <Compile Include="Notifications\Plex\PlexTv\PlexTvPinResponse.cs" />
<Compile Include="Notifications\Plex\PlexTv\PlexTvProxy.cs" /> <Compile Include="Notifications\Plex\PlexTv\PlexTvProxy.cs" />
<Compile Include="Notifications\Plex\PlexTv\PlexTvService.cs" /> <Compile Include="Notifications\Plex\PlexTv\PlexTvService.cs" />
<Compile Include="Notifications\PushBullet\PushBulletDevice.cs" />
<Compile Include="Notifications\PushBullet\PushBulletDevicesResponse.cs" />
<Compile Include="Profiles\Languages\LanguageProfile.cs" /> <Compile Include="Profiles\Languages\LanguageProfile.cs" />
<Compile Include="Profiles\Languages\LanguageProfileInUseException.cs" /> <Compile Include="Profiles\Languages\LanguageProfileInUseException.cs" />
<Compile Include="Lifecycle\ApplicationShutdownRequested.cs" /> <Compile Include="Lifecycle\ApplicationShutdownRequested.cs" />