New: MediaBrowser notifications

This commit is contained in:
Mark McDowall 2014-08-03 00:26:55 -07:00
parent 4fda97257b
commit daafb67fa7
8 changed files with 286 additions and 4 deletions

View File

@ -15,6 +15,8 @@ namespace NzbDrone.Common.Http
HttpResponse Get(HttpRequest request);
HttpResponse<T> Get<T>(HttpRequest request) where T : new();
HttpResponse Head(HttpRequest request);
HttpResponse Post(HttpRequest request);
HttpResponse<T> Post<T>(HttpRequest request) where T : new();
}
public class HttpClient : IHttpClient
@ -43,6 +45,7 @@ namespace NzbDrone.Common.Http
webRequest.UserAgent = UserAgentBuilder.UserAgent;
webRequest.KeepAlive = false;
webRequest.AllowAutoRedirect = request.AllowAutoRedirect;
webRequest.ContentLength = 0;
if (!RuntimeInfoBase.IsProduction)
{
@ -164,6 +167,18 @@ namespace NzbDrone.Common.Http
return Execute(request);
}
public HttpResponse Post(HttpRequest request)
{
request.Method = HttpMethod.POST;
return Execute(request);
}
public HttpResponse<T> Post<T>(HttpRequest request) where T : new()
{
var response = Post(request);
return new HttpResponse<T>(response);
}
protected virtual void AddRequestHeaders(HttpWebRequest webRequest, HttpHeader headers)
{
foreach (var header in headers)

View File

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using FluentValidation.Results;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Notifications.MediaBrowser
{
public class MediaBrowser : NotificationBase<MediaBrowserSettings>
{
private readonly IMediaBrowserService _mediaBrowserService;
public MediaBrowser(IMediaBrowserService mediaBrowserService)
{
_mediaBrowserService = mediaBrowserService;
}
public override string Link
{
get { return "http://mediabrowser.tv/"; }
}
public override void OnGrab(String message)
{
const string title = "Sonarr - Grabbed";
if (Settings.Notify)
{
_mediaBrowserService.Notify(Settings, title, message);
}
}
public override void OnDownload(DownloadMessage message)
{
const string title = "Sonarr - Downloaded";
if (Settings.Notify)
{
_mediaBrowserService.Notify(Settings, title, message.Message);
}
if (Settings.UpdateLibrary)
{
_mediaBrowserService.Update(Settings, message.Series);
}
}
public override void AfterRename(Series series)
{
if (Settings.UpdateLibrary)
{
_mediaBrowserService.Update(Settings, series);
}
}
public override ValidationResult Test()
{
var failures = new List<ValidationFailure>();
failures.AddIfNotNull(_mediaBrowserService.Test(Settings));
return new ValidationResult(failures);
}
}
}

View File

@ -0,0 +1,71 @@
using System;
using Newtonsoft.Json;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
namespace NzbDrone.Core.Notifications.MediaBrowser
{
public class MediaBrowserProxy
{
private readonly IHttpClient _httpClient;
private readonly Logger _logger;
public MediaBrowserProxy(IHttpClient httpClient, Logger logger)
{
_httpClient = httpClient;
_logger = logger;
}
public void Notify(MediaBrowserSettings settings, string title, string message)
{
var path = "/Notifications/Admin";
var request = BuildRequest(path, settings);
request.Body = new
{
Name = title,
Description = message,
ImageUrl = "https://raw.github.com/NzbDrone/NzbDrone/develop/Logo/64.png"
}.ToJson();
request.Headers.ContentType = "application/json";
ProcessRequest(request, settings);
}
public void Update(MediaBrowserSettings settings, Int32 tvdbId)
{
var path = String.Format("/Library/Series/Updated?tvdbid={0}", tvdbId);
var request = BuildRequest(path, settings);
ProcessRequest(request, settings);
}
private String ProcessRequest(HttpRequest request, MediaBrowserSettings settings)
{
request.Headers.Add("X-MediaBrowser-Token", settings.ApiKey);
var response = _httpClient.Post(request);
_logger.Trace("Response: {0}", response.Content);
CheckForError(response);
return response.Content;
}
private HttpRequest BuildRequest(string path, MediaBrowserSettings settings)
{
var url = String.Format(@"http://{0}/mediabrowser", settings.Address);
return new HttpRequestBuilder(url).Build(path);
}
private void CheckForError(HttpResponse response)
{
_logger.Debug("Looking for error in response: {0}", response);
//TODO: actually check for the error
}
}
}

View File

@ -0,0 +1,62 @@
using System;
using System.Net;
using FluentValidation.Results;
using NLog;
using NzbDrone.Core.Rest;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Notifications.MediaBrowser
{
public interface IMediaBrowserService
{
void Notify(MediaBrowserSettings settings, String title, String message);
void Update(MediaBrowserSettings settings, Series series);
ValidationFailure Test(MediaBrowserSettings settings);
}
public class MediaBrowserService : IMediaBrowserService
{
private readonly MediaBrowserProxy _proxy;
private readonly Logger _logger;
public MediaBrowserService(MediaBrowserProxy proxy, Logger logger)
{
_proxy = proxy;
_logger = logger;
}
public void Notify(MediaBrowserSettings settings, String title, String message)
{
_proxy.Notify(settings, title, message);
}
public void Update(MediaBrowserSettings settings, Series series)
{
_proxy.Update(settings, series.TvdbId);
}
public ValidationFailure Test(MediaBrowserSettings settings)
{
try
{
_logger.Debug("Testing connection to MediaBrowser: {0}", settings.Address);
Notify(settings, "Test from Sonarr", "Success! MediaBrowser has been successfully configured!");
}
catch (RestException ex)
{
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
{
return new ValidationFailure("ApiKey", "API Key is incorrect");
}
}
catch (Exception ex)
{
_logger.ErrorException("Unable to send test message: " + ex.Message, ex);
return new ValidationFailure("Host", "Unable to send test message: " + ex.Message);
}
return null;
}
}
}

View File

@ -0,0 +1,64 @@
using System;
using FluentValidation;
using FluentValidation.Results;
using Newtonsoft.Json;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Notifications.MediaBrowser
{
public class MediaBrowserSettingsValidator : AbstractValidator<MediaBrowserSettings>
{
public MediaBrowserSettingsValidator()
{
RuleFor(c => c.Host).NotEmpty();
RuleFor(c => c.ApiKey).NotEmpty();
}
}
public class MediaBrowserSettings : IProviderConfig
{
private static readonly MediaBrowserSettingsValidator Validator = new MediaBrowserSettingsValidator();
public MediaBrowserSettings()
{
Port = 8096;
}
[FieldDefinition(0, Label = "Host")]
public String Host { get; set; }
[FieldDefinition(1, Label = "Port")]
public Int32 Port { get; set; }
[FieldDefinition(2, Label = "API Key")]
public String ApiKey { get; set; }
[FieldDefinition(3, Label = "Send Notifications", HelpText = "Have MediaBrowser send notfications to configured providers", Type = FieldType.Checkbox)]
public Boolean Notify { get; set; }
[FieldDefinition(4, Label = "Update Library", HelpText = "Update Library on Download & Rename?", Type = FieldType.Checkbox)]
public Boolean UpdateLibrary { get; set; }
[JsonIgnore]
public String Address { get { return String.Format("{0}:{1}", Host, Port); } }
public bool IsValid
{
get
{
return !string.IsNullOrWhiteSpace(Host) && Port > 0;
}
}
public ValidationResult Validate()
{
return Validator.Validate(this);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}

View File

@ -109,10 +109,7 @@ namespace NzbDrone.Core.Notifications.Xbmc
private IRestClient BuildClient(XbmcSettings settings)
{
var url = string.Format(@"http://{0}/jsonrpc", settings.Address);
_logger.Debug("Url: " + url);
var url = String.Format(@"http://{0}/jsonrpc", settings.Address);
var client = RestClientFactory.BuildClient(url);
if (!settings.Username.IsNullOrWhiteSpace())

View File

@ -657,6 +657,10 @@
</Compile>
<Compile Include="Notifications\Growl\GrowlSettings.cs" />
<Compile Include="Notifications\INotification.cs" />
<Compile Include="Notifications\MediaBrowser\MediaBrowser.cs" />
<Compile Include="Notifications\MediaBrowser\MediaBrowserProxy.cs" />
<Compile Include="Notifications\MediaBrowser\MediaBrowserService.cs" />
<Compile Include="Notifications\MediaBrowser\MediaBrowserSettings.cs" />
<Compile Include="Notifications\NotificationBase.cs">
<SubType>Code</SubType>
</Compile>

View File

@ -39,6 +39,10 @@ namespace NzbDrone.Core.Rest
{
return response;
}
case HttpStatusCode.NoContent:
{
return response;
}
default:
{
Logger.Warn("[{0}] [{1}] Failed. [{2}]", response.Request.Method, response.ResponseUri.ToString(), response.StatusCode);