using System; using System.Net; using NLog; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Http; using NzbDrone.Common.Serializer; using NzbDrone.Core.Exceptions; namespace NzbDrone.Core.Notifications.Plex.PlexTv { public interface IPlexTvProxy { string GetAuthToken(string clientIdentifier, int pinId); bool Ping(string clientIdentifier, string authToken); } public class PlexTvProxy : IPlexTvProxy { private readonly IHttpClient _httpClient; private readonly Logger _logger; public PlexTvProxy(IHttpClient httpClient, Logger logger) { _httpClient = httpClient; _logger = logger; } public string GetAuthToken(string clientIdentifier, int pinId) { var request = BuildRequest(clientIdentifier); request.ResourceUrl = $"/api/v2/pins/{pinId}"; if (!Json.TryDeserialize(ProcessRequest(request), out var response)) { response = new PlexTvPinResponse(); } return response.AuthToken; } public bool Ping(string clientIdentifier, string authToken) { try { // Allows us to tell plex.tv that we're still active and tokens should not be expired. var request = BuildRequest(clientIdentifier); request.ResourceUrl = "/api/v2/ping"; request.AddQueryParam("X-Plex-Token", authToken); ProcessRequest(request); return true; } catch (Exception e) { // Catch all exceptions and log at trace, this information could be interesting in debugging, but expired tokens will be handled elsewhere. _logger.Trace(e, "Unable to ping plex.tv"); } return false; } private HttpRequestBuilder BuildRequest(string clientIdentifier) { var requestBuilder = new HttpRequestBuilder("https://plex.tv") .Accept(HttpAccept.Json) .AddQueryParam("X-Plex-Client-Identifier", clientIdentifier) .AddQueryParam("X-Plex-Product", BuildInfo.AppName) .AddQueryParam("X-Plex-Platform", "Windows") .AddQueryParam("X-Plex-Platform-Version", "7") .AddQueryParam("X-Plex-Device-Name", BuildInfo.AppName) .AddQueryParam("X-Plex-Version", BuildInfo.Version.ToString()); return requestBuilder; } private string ProcessRequest(HttpRequestBuilder requestBuilder) { var httpRequest = requestBuilder.Build(); HttpResponse response; _logger.Debug("Url: {0}", httpRequest.Url); try { response = _httpClient.Execute(httpRequest); } catch (HttpException ex) { throw new NzbDroneClientException(ex.Response.StatusCode, "Unable to connect to plex.tv"); } catch (WebException) { throw new NzbDroneClientException(HttpStatusCode.BadRequest, "Unable to connect to plex.tv"); } return response.Content; } } }