diff --git a/src/Ombi.Api.Plex/IPlexApi.cs b/src/Ombi.Api.Plex/IPlexApi.cs index c79ec50c9..a4597765e 100644 --- a/src/Ombi.Api.Plex/IPlexApi.cs +++ b/src/Ombi.Api.Plex/IPlexApi.cs @@ -23,7 +23,7 @@ namespace Ombi.Api.Plex Task GetUsers(string authToken); Task GetAccount(string authToken); Task GetRecentlyAdded(string authToken, string uri, string sectionId); - Task GetPin(int pinId); + Task GetPin(int pinId); Task GetOAuthUrl(string code, string applicationUrl); Task AddUser(string emailAddress, string serverId, string authToken, int[] libs); } diff --git a/src/Ombi.Api.Plex/Models/OAuth/OAuthPin.cs b/src/Ombi.Api.Plex/Models/OAuth/OAuthPin.cs index e65cd91d4..3ab857ed3 100644 --- a/src/Ombi.Api.Plex/Models/OAuth/OAuthPin.cs +++ b/src/Ombi.Api.Plex/Models/OAuth/OAuthPin.cs @@ -1,7 +1,14 @@ using System; +using System.Collections.Generic; namespace Ombi.Api.Plex.Models.OAuth { + public class OAuthContainer + { + public OAuthPin Result { get; set; } + public OAuthErrorsContainer Errors { get; set; } + } + public class OAuthPin { public int id { get; set; } @@ -24,4 +31,15 @@ namespace Ombi.Api.Plex.Models.OAuth public string coordinates { get; set; } } + public class OAuthErrorsContainer + { + public List errors { get; set; } + } + + public class OAuthErrors + { + public int code { get; set; } + public string message { get; set; } + } + } \ No newline at end of file diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index 0d6356457..b80534bb9 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -1,7 +1,7 @@ using System; using System.Net.Http; -using System.Reflection; using System.Threading.Tasks; +using Newtonsoft.Json; using Ombi.Api.Plex.Models; using Ombi.Api.Plex.Models.Friends; using Ombi.Api.Plex.Models.OAuth; @@ -208,12 +208,28 @@ namespace Ombi.Api.Plex return await Api.Request(request); } - public async Task GetPin(int pinId) + public async Task GetPin(int pinId) { var request = new Request($"api/v2/pins/{pinId}", "https://plex.tv/", HttpMethod.Get); await AddHeaders(request); - return await Api.Request(request); + var response = await Api.RequestContent(request); + + if (response.Contains("errors")) + { + var errors = JsonConvert.DeserializeObject(response, Ombi.Api.Api.Settings); + return new OAuthContainer + { + Errors = errors + }; + } + + var pinResult = JsonConvert.DeserializeObject(response, Ombi.Api.Api.Settings); + + return new OAuthContainer + { + Result = pinResult + }; } public async Task GetOAuthUrl(string code, string applicationUrl) diff --git a/src/Ombi.Api/Api.cs b/src/Ombi.Api/Api.cs index 7a8e7678b..66dec8b0b 100644 --- a/src/Ombi.Api/Api.cs +++ b/src/Ombi.Api/Api.cs @@ -73,7 +73,7 @@ namespace Ombi.Api } // do something with the response - var receivedString = await httpResponseMessage.Content.ReadAsStringAsync(); + var receivedString = await httpResponseMessage.Content.ReadAsStringAsync(cancellationToken); LogDebugContent(receivedString); if (request.ContentType == ContentType.Json) { diff --git a/src/Ombi.Core/Authentication/PlexOAuthManager.cs b/src/Ombi.Core/Authentication/PlexOAuthManager.cs index 76b1b5d97..78f33cee8 100644 --- a/src/Ombi.Core/Authentication/PlexOAuthManager.cs +++ b/src/Ombi.Core/Authentication/PlexOAuthManager.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Ombi.Api.Plex; using Ombi.Api.Plex.Models; using Ombi.Api.Plex.Models.OAuth; @@ -11,24 +13,37 @@ namespace Ombi.Core.Authentication { public class PlexOAuthManager : IPlexOAuthManager { - public PlexOAuthManager(IPlexApi api, ISettingsService settings) + public PlexOAuthManager(IPlexApi api, ISettingsService settings, ILogger logger) { _api = api; _customizationSettingsService = settings; + _logger = logger; } private readonly IPlexApi _api; private readonly ISettingsService _customizationSettingsService; + private readonly ILogger _logger; public async Task GetAccessTokenFromPin(int pinId) { var pin = await _api.GetPin(pinId); - if (pin.expiresAt < DateTime.UtcNow) + if (pin.Errors != null) { + foreach (var err in pin.Errors?.errors ?? new List()) + { + _logger.LogError($"Code: '{err.code}' : '{err.message}'"); + } + + return string.Empty; + } + + if (pin.Result.expiresIn <= 0) + { + _logger.LogError("Pin has expired"); return string.Empty; } - return pin.authToken; + return pin.Result.authToken; } public async Task GetAccount(string accessToken) diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html index 0fd13097c..4e088bd69 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html @@ -82,6 +82,11 @@ {{ 'Requests.MarkAvailable' | translate }} + + diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts index 01c8a5783..9cb446656 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts @@ -168,6 +168,17 @@ export class MovieDetailsComponent { } } + + public async markUnavailable() { + const result = await this.requestService.markMovieUnavailable({ id: this.movieRequest.id }).toPromise(); + if (result.result) { + this.movie.available = false; + this.messageService.send(result.message, "Ok"); + } else { + this.messageService.send(result.errorMessage, "Ok"); + } + } + public setAdvancedOptions(data: IAdvancedData) { this.advancedOptions = data; if (data.rootFolderId) { diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/top-banner/top-banner.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/top-banner/top-banner.component.html index 55550160e..ba45ea5fa 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/top-banner/top-banner.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/top-banner/top-banner.component.html @@ -9,7 +9,8 @@
-

{{title}} +

{{title}} + ({{releaseDate | amLocal | amDateFormat: 'YYYY'}})

diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/top-banner/top-banner.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/top-banner/top-banner.component.ts index c7db74305..ec2379b0b 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/top-banner/top-banner.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/top-banner/top-banner.component.ts @@ -13,6 +13,12 @@ export class TopBannerComponent { @Input() available: boolean; @Input() background: any; + get releaseDateFormat(): Date|null { + if (this.releaseDate && this.releaseDate instanceof Date && this.releaseDate.getFullYear() !== 1) { + return this.releaseDate; + } + return null; + } constructor(private sanitizer:DomSanitizer){ } diff --git a/src/Ombi/ClientApp/src/app/services/applications/plextv.service.ts b/src/Ombi/ClientApp/src/app/services/applications/plextv.service.ts index f214ac291..3ce0e0a8b 100644 --- a/src/Ombi/ClientApp/src/app/services/applications/plextv.service.ts +++ b/src/Ombi/ClientApp/src/app/services/applications/plextv.service.ts @@ -20,6 +20,7 @@ export class PlexTvService { "X-Plex-Device": "Ombi (Web)", "X-Plex-Platform": "Web", "Accept": "application/json", + 'X-Plex-Model': 'Plex OAuth', }); return this.http.post("https://plex.tv/api/v2/pins?strong=true", null, {headers}); } diff --git a/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.html b/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.html index 396fe12ad..d1ab4edb6 100644 --- a/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.html +++ b/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.html @@ -1,4 +1,4 @@ - +
@@ -55,7 +55,7 @@ Quality Profiles - {{profile.label}} + {{profile.label}} A Default Quality Profile is required @@ -85,4 +85,4 @@
-
\ No newline at end of file +