From 189cfcaf05f167a79ab7e724d9e3c6a427c2bfc0 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Fri, 31 May 2019 14:54:51 +0100 Subject: [PATCH] work on issues and imporving the api. Also added the GroupMe Api project so we can later add this as another notification agent --- src/Ombi.Api.GroupMe/GroupMeApi.cs | 48 +++++++++++++ src/Ombi.Api.GroupMe/IGroupMeApi.cs | 13 ++++ .../Models/GroupMeResponse.cs | 61 +++++++++++++++++ src/Ombi.Api.GroupMe/Models/Groups.cs | 38 +++++++++++ .../Models/SendMessageResponse.cs | 26 +++++++ src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj | 11 +++ src/Ombi.Api/Api.cs | 7 +- src/Ombi.Api/IApi.cs | 5 +- src/Ombi.Api/IOmbiHttpClient.cs | 2 + src/Ombi.Api/OmbiHttpClient.cs | 7 ++ .../Engine/Interfaces/IMovieEngineV2.cs | 7 +- src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs | 3 +- .../Engine/V2/MovieSearchEngineV2.cs | 13 ++-- src/Ombi.Core/Engine/V2/MultiSearchEngine.cs | 5 +- src/Ombi.DependencyInjection/IocExtensions.cs | 2 + .../Ombi.DependencyInjection.csproj | 1 + src/Ombi.Helpers/CacheService.cs | 8 ++- src/Ombi.Helpers/ICacheService.cs | 3 +- src/Ombi.TheMovieDbApi/IMovieDbApi.cs | 9 +-- src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 17 ++--- src/Ombi.sln | 11 ++- .../src/app/issues/components/index.ts | 20 ++++++ .../issues-list/issues-list.component.html | 28 ++++++++ .../issues-list/issues-list.component.ts | 67 +++++++++++++++++++ .../issues-list/issues-list.constants.ts | 3 + .../ClientApp/src/app/issues/issues.module.ts | 6 +- src/Ombi/Controllers/V2/SearchController.cs | 8 +-- src/Ombi/ErrorHandlingMiddlewear.cs | 1 + 28 files changed, 392 insertions(+), 38 deletions(-) create mode 100644 src/Ombi.Api.GroupMe/GroupMeApi.cs create mode 100644 src/Ombi.Api.GroupMe/IGroupMeApi.cs create mode 100644 src/Ombi.Api.GroupMe/Models/GroupMeResponse.cs create mode 100644 src/Ombi.Api.GroupMe/Models/Groups.cs create mode 100644 src/Ombi.Api.GroupMe/Models/SendMessageResponse.cs create mode 100644 src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj create mode 100644 src/Ombi/ClientApp/src/app/issues/components/index.ts create mode 100644 src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.html create mode 100644 src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.ts create mode 100644 src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.constants.ts diff --git a/src/Ombi.Api.GroupMe/GroupMeApi.cs b/src/Ombi.Api.GroupMe/GroupMeApi.cs new file mode 100644 index 000000000..bf5464f5d --- /dev/null +++ b/src/Ombi.Api.GroupMe/GroupMeApi.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Ombi.Api.GroupMe.Models; + +namespace Ombi.Api.GroupMe +{ + public class GroupMeApi : IGroupMeApi + { + public GroupMeApi(IApi api) + { + _api = api; + } + + private readonly IApi _api; + private const string BaseUrl = "https://api.groupme.com/v3/"; + + + public async Task>> GetGroups(string token, CancellationToken cancellationToken) + { + var request = new Request($"groups", BaseUrl, HttpMethod.Get); + request.AddQueryString("token", token); + request.AddQueryString("omit", "memberships"); + + return await _api.Request>>(request, cancellationToken); + } + + public async Task> Send(string message, string token, int groupId) + { + var request = new Request($"groups/{groupId}/messages", BaseUrl, HttpMethod.Post); + request.AddQueryString("token", token); + + var body = new + { + message = new + { + source_guid = Guid.NewGuid(), + text = message + } + }; + + request.AddJsonBody(body); + return await _api.Request>(request); + } + } +} diff --git a/src/Ombi.Api.GroupMe/IGroupMeApi.cs b/src/Ombi.Api.GroupMe/IGroupMeApi.cs new file mode 100644 index 000000000..456f3877e --- /dev/null +++ b/src/Ombi.Api.GroupMe/IGroupMeApi.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Ombi.Api.GroupMe.Models; + +namespace Ombi.Api.GroupMe +{ + public interface IGroupMeApi + { + Task>> GetGroups(string token, CancellationToken cancellationToken); + Task> Send(string message, string token, int groupId); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.GroupMe/Models/GroupMeResponse.cs b/src/Ombi.Api.GroupMe/Models/GroupMeResponse.cs new file mode 100644 index 000000000..f319d5ae2 --- /dev/null +++ b/src/Ombi.Api.GroupMe/Models/GroupMeResponse.cs @@ -0,0 +1,61 @@ +using System; +using Newtonsoft.Json; + +namespace Ombi.Api.GroupMe.Models +{ + public class GroupMeResponse + { + [JsonProperty(PropertyName = "response")] + public T Response { get; set; } + [JsonProperty(PropertyName = "meta")] + public Meta Meta { get; set; } + } + public class Meta + { + public bool Successful + { + get + { + switch (StatusCode) + { + case GroupMeStatusCode.OK: + case GroupMeStatusCode.Created: + case GroupMeStatusCode.NoContent: + case GroupMeStatusCode.NotModified: + return true; + case GroupMeStatusCode.BadRequest: + case GroupMeStatusCode.Unauthorized: + case GroupMeStatusCode.Forbidden: + case GroupMeStatusCode.NotFound: + case GroupMeStatusCode.EnhanceYourCalm: + case GroupMeStatusCode.InternalServerError: + case GroupMeStatusCode.BadGateway: + case GroupMeStatusCode.ServiceUnavailable: + return false; + default: + throw new ArgumentOutOfRangeException(nameof(GroupMeStatusCode)); + } + } + } + + public GroupMeStatusCode StatusCode => (GroupMeStatusCode) code; + public int code { get; set; } + public string[] errors { get; set; } + } + + public enum GroupMeStatusCode + { OK = 200, + Created = 201, + NoContent = 204, + NotModified = 304, + BadRequest = 400, + Unauthorized = 401, + Forbidden = 403, + NotFound = 404, + EnhanceYourCalm = 420, + InternalServerError = 500, + BadGateway = 502, + ServiceUnavailable = 503 + } + +} \ No newline at end of file diff --git a/src/Ombi.Api.GroupMe/Models/Groups.cs b/src/Ombi.Api.GroupMe/Models/Groups.cs new file mode 100644 index 000000000..bc793f3b9 --- /dev/null +++ b/src/Ombi.Api.GroupMe/Models/Groups.cs @@ -0,0 +1,38 @@ +namespace Ombi.Api.GroupMe.Models +{ + + public class Groups + { + public string id { get; set; } + public string group_id { get; set; } + public string name { get; set; } + public string phone_number { get; set; } + public string type { get; set; } + public string description { get; set; } + public string image_url { get; set; } + public string creator_user_id { get; set; } + public int created_at { get; set; } + public int updated_at { get; set; } + public bool office_mode { get; set; } + public string share_url { get; set; } + public string share_qr_code_url { get; set; } + public Messages messages { get; set; } + public int max_members { get; set; } + } + + public class Messages + { + public int count { get; set; } + public string last_message_id { get; set; } + public int last_message_created_at { get; set; } + public Preview preview { get; set; } + } + + public class Preview + { + public string nickname { get; set; } + public string text { get; set; } + public string image_url { get; set; } + public object[] attachments { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.GroupMe/Models/SendMessageResponse.cs b/src/Ombi.Api.GroupMe/Models/SendMessageResponse.cs new file mode 100644 index 000000000..57fb99d31 --- /dev/null +++ b/src/Ombi.Api.GroupMe/Models/SendMessageResponse.cs @@ -0,0 +1,26 @@ +namespace Ombi.Api.GroupMe.Models +{ + + public class SendResponse + { + public Message message { get; set; } + } + + public class Message + { + public string id { get; set; } + public string source_guid { get; set; } + public int created_at { get; set; } + public string user_id { get; set; } + public string group_id { get; set; } + public string name { get; set; } + public string avatar_url { get; set; } + public string text { get; set; } + public bool system { get; set; } + public object[] attachments { get; set; } + public object[] favorited_by { get; set; } + public string sender_type { get; set; } + public string sender_id { get; set; } + } + +} \ No newline at end of file diff --git a/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj b/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj new file mode 100644 index 000000000..a3651df3c --- /dev/null +++ b/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/src/Ombi.Api/Api.cs b/src/Ombi.Api/Api.cs index e405b6bca..8ab5bc947 100644 --- a/src/Ombi.Api/Api.cs +++ b/src/Ombi.Api/Api.cs @@ -4,6 +4,7 @@ using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Threading; using System.Threading.Tasks; using System.Xml.Serialization; using Newtonsoft.Json; @@ -29,13 +30,13 @@ namespace Ombi.Api NullValueHandling = NullValueHandling.Ignore }; - public async Task Request(Request request) + public async Task Request(Request request, CancellationToken cancellationToken = default(CancellationToken)) { using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri)) { AddHeadersBody(request, httpRequestMessage); - - var httpResponseMessage = await _client.SendAsync(httpRequestMessage); + + var httpResponseMessage = await _client.SendAsync(httpRequestMessage, cancellationToken); if (!httpResponseMessage.IsSuccessStatusCode) { diff --git a/src/Ombi.Api/IApi.cs b/src/Ombi.Api/IApi.cs index e573d2d07..f1daf0257 100644 --- a/src/Ombi.Api/IApi.cs +++ b/src/Ombi.Api/IApi.cs @@ -1,11 +1,12 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; namespace Ombi.Api { public interface IApi { Task Request(Request request); - Task Request(Request request); + Task Request(Request request, CancellationToken cancellationToken = default(CancellationToken)); Task RequestContent(Request request); T DeserializeXml(string receivedString); } diff --git a/src/Ombi.Api/IOmbiHttpClient.cs b/src/Ombi.Api/IOmbiHttpClient.cs index 97db4180b..1f6ff9514 100644 --- a/src/Ombi.Api/IOmbiHttpClient.cs +++ b/src/Ombi.Api/IOmbiHttpClient.cs @@ -1,5 +1,6 @@ using System; using System.Net.Http; +using System.Threading; using System.Threading.Tasks; namespace Ombi.Api @@ -7,6 +8,7 @@ namespace Ombi.Api public interface IOmbiHttpClient { Task SendAsync(HttpRequestMessage request); + Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken); Task GetStringAsync(Uri requestUri); } } \ No newline at end of file diff --git a/src/Ombi.Api/OmbiHttpClient.cs b/src/Ombi.Api/OmbiHttpClient.cs index ed7c596dd..5e9a7f411 100644 --- a/src/Ombi.Api/OmbiHttpClient.cs +++ b/src/Ombi.Api/OmbiHttpClient.cs @@ -27,6 +27,7 @@ using System; using System.Net.Http; +using System.Threading; using System.Threading.Tasks; using Ombi.Core.Settings; using Ombi.Helpers; @@ -61,6 +62,12 @@ namespace Ombi.Api return await _client.SendAsync(request); } + public async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + await Setup(); + return await _client.SendAsync(request, cancellationToken); + } + public async Task GetStringAsync(Uri requestUri) { await Setup(); diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs b/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs index 34cdd2590..c1ad70613 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Models.Search; @@ -8,16 +9,16 @@ namespace Ombi.Core.Engine.Interfaces { public interface IMovieEngineV2 { - Task GetFullMovieInformation(int theMovieDbId, string langCode = null); + Task GetFullMovieInformation(int theMovieDbId, CancellationToken cancellationToken, string langCode = null); Task> SimilarMovies(int theMovieDbId, string langCode); Task> PopularMovies(); Task> TopRatedMovies(); Task> UpcomingMovies(); Task> NowPlayingMovies(); Task> NowPlayingMovies(int currentPosition, int amountToLoad); - Task GetCollection(int collectionId, string langCode = null); + Task GetCollection(int collectionId, CancellationToken cancellationToken, string langCode = null); Task GetTvDbId(int theMovieDbId); - Task> PopularMovies(int currentlyLoaded, int toLoad); + Task> PopularMovies(int currentlyLoaded, int toLoad, CancellationToken cancellationToken); Task> TopRatedMovies(int currentlyLoaded, int toLoad); Task> UpcomingMovies(int currentlyLoaded, int toLoad); Task GetMoviesByActor(int actorId, string langCode); diff --git a/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs index 997d29281..3fc5a9271 100644 --- a/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs +++ b/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Ombi.Api.TheMovieDb.Models; @@ -6,6 +7,6 @@ namespace Ombi.Core.Engine.V2 { public interface IMultiSearchEngine { - Task> MultiSearch(string searchTerm, string lang = "en"); + Task> MultiSearch(string searchTerm, CancellationToken cancellationToken, string lang = "en"); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs index a27f89120..f33a7f3a6 100644 --- a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Security.Principal; +using System.Threading; using System.Threading.Tasks; namespace Ombi.Core.Engine.V2 @@ -38,20 +39,20 @@ namespace Ombi.Core.Engine.V2 private ILogger Logger { get; } - public async Task GetFullMovieInformation(int theMovieDbId, string langCode = null) + public async Task GetFullMovieInformation(int theMovieDbId, CancellationToken cancellationToken, string langCode = null) { langCode = await DefaultLanguageCode(langCode); var movieInfo = await Cache.GetOrAdd(nameof(GetFullMovieInformation) + theMovieDbId + langCode, - async () => await MovieApi.GetFullMovieInfo(theMovieDbId, langCode), DateTime.Now.AddHours(12)); + async () => await MovieApi.GetFullMovieInfo(theMovieDbId, cancellationToken, langCode), DateTime.Now.AddHours(12), cancellationToken); return await ProcessSingleMovie(movieInfo); } - public async Task GetCollection(int collectionId, string langCode = null) + public async Task GetCollection(int collectionId, CancellationToken cancellationToken, string langCode = null) { langCode = await DefaultLanguageCode(langCode); var collections = await Cache.GetOrAdd(nameof(GetCollection) + collectionId + langCode, - async () => await MovieApi.GetCollection(langCode, collectionId), DateTime.Now.AddDays(1)); + async () => await MovieApi.GetCollection(langCode, collectionId, cancellationToken), DateTime.Now.AddDays(1), cancellationToken); var c = await ProcessCollection(collections); c.Collection = c.Collection.OrderBy(x => x.ReleaseDate).ToList(); @@ -107,7 +108,7 @@ namespace Ombi.Core.Engine.V2 /// Gets popular movies by paging /// /// - public async Task> PopularMovies(int currentlyLoaded, int toLoad) + public async Task> PopularMovies(int currentlyLoaded, int toLoad, CancellationToken cancellationToken) { var langCode = await DefaultLanguageCode(null); @@ -117,7 +118,7 @@ namespace Ombi.Core.Engine.V2 foreach (var pagesToLoad in pages) { var apiResult = await Cache.GetOrAdd(nameof(PopularMovies) + pagesToLoad.Page + langCode, - async () => await MovieApi.PopularMovies(langCode, pagesToLoad.Page), DateTime.Now.AddHours(12)); + async () => await MovieApi.PopularMovies(langCode, pagesToLoad.Page, cancellationToken), DateTime.Now.AddHours(12), cancellationToken); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); } return await TransformMovieResultsToResponse(results); diff --git a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs index 65803c1ac..0bfa33e3f 100644 --- a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs +++ b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Security.Principal; +using System.Threading; using System.Threading.Tasks; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; @@ -27,9 +28,9 @@ namespace Ombi.Core.Engine.V2 private readonly IMovieDbApi _movieDbApi; - public async Task> MultiSearch(string searchTerm, string lang = "en") + public async Task> MultiSearch(string searchTerm, CancellationToken cancellationToken, string lang = "en") { - return (await _movieDbApi.MultiSearch(searchTerm, lang)).results; + return (await _movieDbApi.MultiSearch(searchTerm, lang, cancellationToken)).results; } } } diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 5c8c46739..26b843541 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -34,6 +34,7 @@ using Ombi.Api.DogNzb; using Ombi.Api.FanartTv; using Ombi.Api.Github; using Ombi.Api.Gotify; +using Ombi.Api.GroupMe; using Ombi.Api.Lidarr; using Ombi.Api.Mattermost; using Ombi.Api.Notifications; @@ -143,6 +144,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } public static void RegisterStore(this IServiceCollection services) { diff --git a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj index 8cb6122be..ade163151 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -21,6 +21,7 @@ + diff --git a/src/Ombi.Helpers/CacheService.cs b/src/Ombi.Helpers/CacheService.cs index ae57a9f61..4f2f69dc8 100644 --- a/src/Ombi.Helpers/CacheService.cs +++ b/src/Ombi.Helpers/CacheService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Caching.Memory; using Nito.AsyncEx; @@ -16,7 +17,7 @@ namespace Ombi.Helpers _memoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache)); } - public async Task GetOrAdd(string cacheKey, Func> factory, DateTime absoluteExpiration = default(DateTime)) + public async Task GetOrAdd(string cacheKey, Func> factory, DateTime absoluteExpiration = default(DateTime), CancellationToken cancellationToken = default(CancellationToken)) { if (absoluteExpiration == default(DateTime)) { @@ -33,6 +34,11 @@ namespace Ombi.Helpers return result; } + if (cancellationToken.CanBeCanceled) + { + cancellationToken.ThrowIfCancellationRequested(); + } + result = await factory(); _memoryCache.Set(cacheKey, result, absoluteExpiration); diff --git a/src/Ombi.Helpers/ICacheService.cs b/src/Ombi.Helpers/ICacheService.cs index 8c20d2d23..e3996a0e1 100644 --- a/src/Ombi.Helpers/ICacheService.cs +++ b/src/Ombi.Helpers/ICacheService.cs @@ -1,11 +1,12 @@ using System; +using System.Threading; using System.Threading.Tasks; namespace Ombi.Helpers { public interface ICacheService { - Task GetOrAdd(string cacheKey, Func> factory, DateTime absoluteExpiration = default(DateTime)); + Task GetOrAdd(string cacheKey, Func> factory, DateTime absoluteExpiration = default(DateTime), CancellationToken cancellationToken = default(CancellationToken)); T GetOrAdd(string cacheKey, Func factory, DateTime absoluteExpiration); void Remove(string key); } diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs index c04d4c58a..a6976b7a0 100644 --- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Ombi.Api.TheMovieDb.Models; using Ombi.TheMovieDbApi.Models; @@ -10,7 +11,7 @@ namespace Ombi.Api.TheMovieDb Task GetMovieInformation(int movieId); Task GetMovieInformationWithExtraInfo(int movieId, string langCode = "en"); Task> NowPlaying(string languageCode, int? page = null); - Task> PopularMovies(string languageCode, int? page = null); + Task> PopularMovies(string languageCode, int? page = null, CancellationToken cancellationToken = default(CancellationToken)); Task> SearchMovie(string searchTerm, int? year, string languageCode); Task> SearchTv(string searchTerm); Task> TopRated(string languageCode, int? page = null); @@ -21,9 +22,9 @@ namespace Ombi.Api.TheMovieDb Task GetTVInfo(string themoviedbid); Task> SearchByActor(string searchTerm, string langCode); Task GetActorMovieCredits(int actorId, string langCode); - Task> MultiSearch(string searchTerm, string languageCode); - Task GetFullMovieInfo(int movieId, string langCode); + Task> MultiSearch(string searchTerm, string languageCode, CancellationToken cancellationToken); Task> DiscoverMovies(string langCode, int keywordId); - Task GetCollection(string langCode, int collectionId); + Task GetFullMovieInfo(int movieId, CancellationToken cancellationToken, string langCode); + Task GetCollection(string langCode, int collectionId, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 53cf5a05f..68fdfb97a 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Net; using System.Net.Http; +using System.Threading; using System.Threading.Tasks; using AutoMapper; using Ombi.Api.TheMovieDb.Models; @@ -32,7 +33,7 @@ namespace Ombi.Api.TheMovieDb } - public async Task GetFullMovieInfo(int movieId, string langCode) + public async Task GetFullMovieInfo(int movieId, CancellationToken cancellationToken, string langCode) { var request = new Request($"movie/{movieId}", BaseUri, HttpMethod.Get); request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); @@ -40,7 +41,7 @@ namespace Ombi.Api.TheMovieDb request.FullUri = request.FullUri.AddQueryParameter("append_to_response", "videos,credits,similar,recommendations,release_dates,external_ids,keywords"); AddRetry(request); - return await Api.Request(request); + return await Api.Request(request, cancellationToken); } public async Task> DiscoverMovies(string langCode, int keywordId) @@ -55,14 +56,14 @@ namespace Ombi.Api.TheMovieDb return await Api.Request>(request); } - public async Task GetCollection(string langCode, int collectionId) + public async Task GetCollection(string langCode, int collectionId, CancellationToken cancellationToken) { // https://developers.themoviedb.org/3/discover/movie-discover var request = new Request($"collection/{collectionId}", BaseUri, HttpMethod.Get); request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); request.FullUri = request.FullUri.AddQueryParameter("language", langCode); - return await Api.Request (request); + return await Api.Request(request, cancellationToken); } public async Task Find(string externalId, ExternalSource source) @@ -156,7 +157,7 @@ namespace Ombi.Api.TheMovieDb return Mapper.Map>(result.results); } - public async Task> PopularMovies(string langageCode, int? page = null) + public async Task> PopularMovies(string langageCode, int? page = null, CancellationToken cancellationToken = default(CancellationToken)) { var request = new Request($"movie/popular", BaseUri, HttpMethod.Get); request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); @@ -166,7 +167,7 @@ namespace Ombi.Api.TheMovieDb request.FullUri = request.FullUri.AddQueryParameter("page", page.ToString()); } AddRetry(request); - var result = await Api.Request>(request); + var result = await Api.Request>(request, cancellationToken); return Mapper.Map>(result.results); } @@ -222,13 +223,13 @@ namespace Ombi.Api.TheMovieDb return await Api.Request(request); } - public async Task> MultiSearch(string searchTerm, string languageCode) + public async Task> MultiSearch(string searchTerm, string languageCode, CancellationToken cancellationToken) { var request = new Request("search/multi", BaseUri, HttpMethod.Get); request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); request.FullUri = request.FullUri.AddQueryParameter("language", languageCode); request.FullUri = request.FullUri.AddQueryParameter("query", searchTerm); - var result = await Api.Request>(request); + var result = await Api.Request>(request, cancellationToken); return result; } diff --git a/src/Ombi.sln b/src/Ombi.sln index af8171bec..f4e41db7b 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -102,9 +102,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Gotify", "Ombi.Api EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Settings.Tests", "Ombi.Settings.Tests\Ombi.Settings.Tests.csproj", "{F3969B69-3B07-4884-A7AB-0BAB8B84DF94}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Test.Common", "Ombi.Test.Common\Ombi.Test.Common.csproj", "{27111E7C-748E-4996-BD71-2117027C6460}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Test.Common", "Ombi.Test.Common\Ombi.Test.Common.csproj", "{27111E7C-748E-4996-BD71-2117027C6460}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Hubs", "Ombi.Hubs\Ombi.Hubs.csproj", "{67416CC5-13B2-44BB-98CE-39DA93D6F70E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Hubs", "Ombi.Hubs\Ombi.Hubs.csproj", "{67416CC5-13B2-44BB-98CE-39DA93D6F70E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.GroupMe", "Ombi.Api.GroupMe\Ombi.Api.GroupMe.csproj", "{9266403C-B04D-4C0F-AC39-82F12C781949}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -280,6 +282,10 @@ Global {67416CC5-13B2-44BB-98CE-39DA93D6F70E}.Debug|Any CPU.Build.0 = Debug|Any CPU {67416CC5-13B2-44BB-98CE-39DA93D6F70E}.Release|Any CPU.ActiveCfg = Release|Any CPU {67416CC5-13B2-44BB-98CE-39DA93D6F70E}.Release|Any CPU.Build.0 = Release|Any CPU + {9266403C-B04D-4C0F-AC39-82F12C781949}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9266403C-B04D-4C0F-AC39-82F12C781949}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9266403C-B04D-4C0F-AC39-82F12C781949}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9266403C-B04D-4C0F-AC39-82F12C781949}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -320,6 +326,7 @@ Global {105EA346-766E-45B8-928B-DE6991DCB7EB} = {9293CA11-360A-4C20-A674-B9E794431BF5} {F3969B69-3B07-4884-A7AB-0BAB8B84DF94} = {6F42AB98-9196-44C4-B888-D5E409F415A1} {27111E7C-748E-4996-BD71-2117027C6460} = {6F42AB98-9196-44C4-B888-D5E409F415A1} + {9266403C-B04D-4C0F-AC39-82F12C781949} = {9293CA11-360A-4C20-A674-B9E794431BF5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869} diff --git a/src/Ombi/ClientApp/src/app/issues/components/index.ts b/src/Ombi/ClientApp/src/app/issues/components/index.ts new file mode 100644 index 000000000..93bb4907d --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/index.ts @@ -0,0 +1,20 @@ +import { AuthGuard } from "../../auth/auth.guard"; +import { IssuesListComponent } from "./issues-list/issues-list.component"; +import { Routes } from "@angular/router"; + + + +export const components: any[] = [ + IssuesListComponent, +]; + + +export const entryComponents: any[] = [ +]; + +export const providers: any[] = [ +]; + +export const routes: Routes = [ + { path: "", component: IssuesListComponent, canActivate: [AuthGuard] }, +]; \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.html b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.html new file mode 100644 index 000000000..bcae7e76c --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.html @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + +
{{column}} {{element[column]}} +
+
+
{{element.requestId}}
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.ts b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.ts new file mode 100644 index 000000000..5528401ff --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.ts @@ -0,0 +1,67 @@ +import { Component, OnInit } from "@angular/core"; + +import { IssuesService } from "../../../services"; + +import { IIssueCount, IIssues, IPagenator, IssueStatus } from "../../../interfaces"; +import { COLUMNS } from "./issues-list.constants"; + +@Component({ + templateUrl: "issues-list.component.html", +}) +export class IssuesListComponent implements OnInit { + + public columnsToDisplay = COLUMNS + + public pendingIssues: IIssues[]; + public inProgressIssues: IIssues[]; + public resolvedIssues: IIssues[]; + + public count: IIssueCount; + + private takeAmount = 10; + private pendingSkip = 0; + private inProgressSkip = 0; + private resolvedSkip = 0; + + constructor(private issueService: IssuesService) { } + + public ngOnInit() { + this.getPending(); + this.getInProg(); + this.getResolved(); + this.issueService.getIssuesCount().subscribe(x => this.count = x); + } + + public changePagePending(event: IPagenator) { + this.pendingSkip = event.first; + this.getPending(); + } + + public changePageInProg(event: IPagenator) { + this.inProgressSkip = event.first; + this.getInProg(); + } + + public changePageResolved(event: IPagenator) { + this.resolvedSkip = event.first; + this.getResolved(); + } + + private getPending() { + this.issueService.getIssuesPage(this.takeAmount, this.pendingSkip, IssueStatus.Pending).subscribe(x => { + this.pendingIssues = x; + }); + } + + private getInProg() { + this.issueService.getIssuesPage(this.takeAmount, this.inProgressSkip, IssueStatus.InProgress).subscribe(x => { + this.inProgressIssues = x; + }); + } + + private getResolved() { + this.issueService.getIssuesPage(this.takeAmount, this.resolvedSkip, IssueStatus.Resolved).subscribe(x => { + this.resolvedIssues = x; + }); + } +} diff --git a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.constants.ts b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.constants.ts new file mode 100644 index 000000000..f4a00e24b --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.constants.ts @@ -0,0 +1,3 @@ +export const COLUMNS = [ + "title" +] \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/issues.module.ts b/src/Ombi/ClientApp/src/app/issues/issues.module.ts index d8abe45f8..cc7240553 100644 --- a/src/Ombi/ClientApp/src/app/issues/issues.module.ts +++ b/src/Ombi/ClientApp/src/app/issues/issues.module.ts @@ -16,9 +16,12 @@ import { IssuesComponent } from "./issues.component"; import { IssuesTableComponent } from "./issuestable.component"; import { PipeModule } from "../pipes/pipe.module"; +import { IssuesListComponent } from "./components/issues-list/issues-list.component"; + +import * as fromComponents from "./components"; const routes: Routes = [ - { path: "", component: IssuesComponent, canActivate: [AuthGuard] }, + { path: "", component: IssuesListComponent, canActivate: [AuthGuard] }, { path: ":id", component: IssueDetailsComponent, canActivate: [AuthGuard] }, ]; @@ -37,6 +40,7 @@ const routes: Routes = [ IssuesComponent, IssueDetailsComponent, IssuesTableComponent, + ...fromComponents.components ], exports: [ RouterModule, diff --git a/src/Ombi/Controllers/V2/SearchController.cs b/src/Ombi/Controllers/V2/SearchController.cs index 5a38c2dd8..070d54d33 100644 --- a/src/Ombi/Controllers/V2/SearchController.cs +++ b/src/Ombi/Controllers/V2/SearchController.cs @@ -48,7 +48,7 @@ namespace Ombi.Controllers.V2 [HttpGet("multi/{searchTerm}")] public async Task> MultiSearch(string searchTerm) { - return await _multiSearchEngine.MultiSearch(searchTerm); + return await _multiSearchEngine.MultiSearch(searchTerm, Request.HttpContext.RequestAborted); } /// @@ -58,7 +58,7 @@ namespace Ombi.Controllers.V2 [HttpGet("movie/{movieDbId}")] public async Task GetMovieInfo(int movieDbId) { - return await _movieEngineV2.GetFullMovieInformation(movieDbId); + return await _movieEngineV2.GetFullMovieInformation(movieDbId, Request.HttpContext.RequestAborted); } /// @@ -69,7 +69,7 @@ namespace Ombi.Controllers.V2 [HttpGet("movie/collection/{collectionId}")] public async Task GetMovieCollections(int collectionId) { - return await _movieEngineV2.GetCollection(collectionId); + return await _movieEngineV2.GetCollection(collectionId, Request.HttpContext.RequestAborted); } /// @@ -133,7 +133,7 @@ namespace Ombi.Controllers.V2 [ProducesDefaultResponseType] public async Task> Popular(int currentPosition, int amountToLoad) { - return await _movieEngineV2.PopularMovies(currentPosition, amountToLoad); + return await _movieEngineV2.PopularMovies(currentPosition, amountToLoad, Request.HttpContext.RequestAborted); } /// diff --git a/src/Ombi/ErrorHandlingMiddlewear.cs b/src/Ombi/ErrorHandlingMiddlewear.cs index 01e22d0b0..195e4a307 100644 --- a/src/Ombi/ErrorHandlingMiddlewear.cs +++ b/src/Ombi/ErrorHandlingMiddlewear.cs @@ -38,6 +38,7 @@ namespace Ombi //if (exception is NotFoundException) code = HttpStatusCode.NotFound; if (exception is UnauthorizedAccessException) code = HttpStatusCode.Unauthorized; + if (exception is OperationCanceledException) code = HttpStatusCode.NoContent; string result; if (exception.InnerException != null) {