work on issues and imporving the api.

Also added the GroupMe Api project so we can later add this as another notification agent
pull/3895/head
Jamie Rees 5 years ago
parent 8de5057fd3
commit 189cfcaf05

@ -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<GroupMeResponse<List<Groups>>> 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<GroupMeResponse<List<Groups>>>(request, cancellationToken);
}
public async Task<GroupMeResponse<SendResponse>> 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<GroupMeResponse<SendResponse>>(request);
}
}
}

@ -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<GroupMeResponse<List<Groups>>> GetGroups(string token, CancellationToken cancellationToken);
Task<GroupMeResponse<SendResponse>> Send(string message, string token, int groupId);
}
}

@ -0,0 +1,61 @@
using System;
using Newtonsoft.Json;
namespace Ombi.Api.GroupMe.Models
{
public class GroupMeResponse<T>
{
[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
}
}

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

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

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
</ItemGroup>
</Project>

@ -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<T> Request<T>(Request request)
public async Task<T> Request<T>(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)
{

@ -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<T> Request<T>(Request request);
Task<T> Request<T>(Request request, CancellationToken cancellationToken = default(CancellationToken));
Task<string> RequestContent(Request request);
T DeserializeXml<T>(string receivedString);
}

@ -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<HttpResponseMessage> SendAsync(HttpRequestMessage request);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
Task<string> GetStringAsync(Uri requestUri);
}
}

@ -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<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
await Setup();
return await _client.SendAsync(request, cancellationToken);
}
public async Task<string> GetStringAsync(Uri requestUri)
{
await Setup();

@ -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<MovieFullInfoViewModel> GetFullMovieInformation(int theMovieDbId, string langCode = null);
Task<MovieFullInfoViewModel> GetFullMovieInformation(int theMovieDbId, CancellationToken cancellationToken, string langCode = null);
Task<IEnumerable<SearchMovieViewModel>> SimilarMovies(int theMovieDbId, string langCode);
Task<IEnumerable<SearchMovieViewModel>> PopularMovies();
Task<IEnumerable<SearchMovieViewModel>> TopRatedMovies();
Task<IEnumerable<SearchMovieViewModel>> UpcomingMovies();
Task<IEnumerable<SearchMovieViewModel>> NowPlayingMovies();
Task<IEnumerable<SearchMovieViewModel>> NowPlayingMovies(int currentPosition, int amountToLoad);
Task<MovieCollectionsViewModel> GetCollection(int collectionId, string langCode = null);
Task<MovieCollectionsViewModel> GetCollection(int collectionId, CancellationToken cancellationToken, string langCode = null);
Task<int> GetTvDbId(int theMovieDbId);
Task<IEnumerable<SearchMovieViewModel>> PopularMovies(int currentlyLoaded, int toLoad);
Task<IEnumerable<SearchMovieViewModel>> PopularMovies(int currentlyLoaded, int toLoad, CancellationToken cancellationToken);
Task<IEnumerable<SearchMovieViewModel>> TopRatedMovies(int currentlyLoaded, int toLoad);
Task<IEnumerable<SearchMovieViewModel>> UpcomingMovies(int currentlyLoaded, int toLoad);
Task<ActorCredits> GetMoviesByActor(int actorId, string langCode);

@ -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<List<MultiSearch>> MultiSearch(string searchTerm, string lang = "en");
Task<List<MultiSearch>> MultiSearch(string searchTerm, CancellationToken cancellationToken, string lang = "en");
}
}

@ -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<MovieFullInfoViewModel> GetFullMovieInformation(int theMovieDbId, string langCode = null)
public async Task<MovieFullInfoViewModel> 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<MovieCollectionsViewModel> GetCollection(int collectionId, string langCode = null)
public async Task<MovieCollectionsViewModel> 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
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<SearchMovieViewModel>> PopularMovies(int currentlyLoaded, int toLoad)
public async Task<IEnumerable<SearchMovieViewModel>> 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);

@ -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<List<MultiSearch>> MultiSearch(string searchTerm, string lang = "en")
public async Task<List<MultiSearch>> MultiSearch(string searchTerm, CancellationToken cancellationToken, string lang = "en")
{
return (await _movieDbApi.MultiSearch(searchTerm, lang)).results;
return (await _movieDbApi.MultiSearch(searchTerm, lang, cancellationToken)).results;
}
}
}

@ -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<IAppVeyorApi, AppVeyorApi>();
services.AddTransient<IOneSignalApi, OneSignalApi>();
services.AddTransient<ILidarrApi, LidarrApi>();
services.AddTransient<IGroupMeApi, GroupMeApi>();
}
public static void RegisterStore(this IServiceCollection services) {

@ -21,6 +21,7 @@
<ProjectReference Include="..\Ombi.Api.Emby\Ombi.Api.Emby.csproj" />
<ProjectReference Include="..\Ombi.Api.FanartTv\Ombi.Api.FanartTv.csproj" />
<ProjectReference Include="..\Ombi.Api.Github\Ombi.Api.Github.csproj" />
<ProjectReference Include="..\Ombi.Api.GroupMe\Ombi.Api.GroupMe.csproj" />
<ProjectReference Include="..\Ombi.Api.Lidarr\Ombi.Api.Lidarr.csproj" />
<ProjectReference Include="..\Ombi.Api.Mattermost\Ombi.Api.Mattermost.csproj" />
<ProjectReference Include="..\Ombi.Api.Notifications\Ombi.Api.Notifications.csproj" />

@ -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<T> GetOrAdd<T>(string cacheKey, Func<Task<T>> factory, DateTime absoluteExpiration = default(DateTime))
public async Task<T> GetOrAdd<T>(string cacheKey, Func<Task<T>> 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);

@ -1,11 +1,12 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Ombi.Helpers
{
public interface ICacheService
{
Task<T> GetOrAdd<T>(string cacheKey, Func<Task<T>> factory, DateTime absoluteExpiration = default(DateTime));
Task<T> GetOrAdd<T>(string cacheKey, Func<Task<T>> factory, DateTime absoluteExpiration = default(DateTime), CancellationToken cancellationToken = default(CancellationToken));
T GetOrAdd<T>(string cacheKey, Func<T> factory, DateTime absoluteExpiration);
void Remove(string key);
}

@ -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<MovieResponseDto> GetMovieInformation(int movieId);
Task<MovieResponseDto> GetMovieInformationWithExtraInfo(int movieId, string langCode = "en");
Task<List<MovieSearchResult>> NowPlaying(string languageCode, int? page = null);
Task<List<MovieSearchResult>> PopularMovies(string languageCode, int? page = null);
Task<List<MovieSearchResult>> PopularMovies(string languageCode, int? page = null, CancellationToken cancellationToken = default(CancellationToken));
Task<List<MovieSearchResult>> SearchMovie(string searchTerm, int? year, string languageCode);
Task<List<TvSearchResult>> SearchTv(string searchTerm);
Task<List<MovieSearchResult>> TopRated(string languageCode, int? page = null);
@ -21,9 +22,9 @@ namespace Ombi.Api.TheMovieDb
Task<TvInfo> GetTVInfo(string themoviedbid);
Task<TheMovieDbContainer<ActorResult>> SearchByActor(string searchTerm, string langCode);
Task<ActorCredits> GetActorMovieCredits(int actorId, string langCode);
Task<TheMovieDbContainer<MultiSearch>> MultiSearch(string searchTerm, string languageCode);
Task<FullMovieInfo> GetFullMovieInfo(int movieId, string langCode);
Task<TheMovieDbContainer<MultiSearch>> MultiSearch(string searchTerm, string languageCode, CancellationToken cancellationToken);
Task<TheMovieDbContainer<DiscoverMovies>> DiscoverMovies(string langCode, int keywordId);
Task<Collections> GetCollection(string langCode, int collectionId);
Task<FullMovieInfo> GetFullMovieInfo(int movieId, CancellationToken cancellationToken, string langCode);
Task<Collections> GetCollection(string langCode, int collectionId, CancellationToken cancellationToken);
}
}

@ -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<FullMovieInfo> GetFullMovieInfo(int movieId, string langCode)
public async Task<FullMovieInfo> 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<FullMovieInfo>(request);
return await Api.Request<FullMovieInfo>(request, cancellationToken);
}
public async Task<TheMovieDbContainer<DiscoverMovies>> DiscoverMovies(string langCode, int keywordId)
@ -55,14 +56,14 @@ namespace Ombi.Api.TheMovieDb
return await Api.Request<TheMovieDbContainer<DiscoverMovies>>(request);
}
public async Task<Collections> GetCollection(string langCode, int collectionId)
public async Task<Collections> 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<Collections> (request);
return await Api.Request<Collections>(request, cancellationToken);
}
public async Task<FindResult> Find(string externalId, ExternalSource source)
@ -156,7 +157,7 @@ namespace Ombi.Api.TheMovieDb
return Mapper.Map<List<MovieSearchResult>>(result.results);
}
public async Task<List<MovieSearchResult>> PopularMovies(string langageCode, int? page = null)
public async Task<List<MovieSearchResult>> 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<TheMovieDbContainer<SearchResult>>(request);
var result = await Api.Request<TheMovieDbContainer<SearchResult>>(request, cancellationToken);
return Mapper.Map<List<MovieSearchResult>>(result.results);
}
@ -222,13 +223,13 @@ namespace Ombi.Api.TheMovieDb
return await Api.Request<TvInfo>(request);
}
public async Task<TheMovieDbContainer<MultiSearch>> MultiSearch(string searchTerm, string languageCode)
public async Task<TheMovieDbContainer<MultiSearch>> 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<TheMovieDbContainer<MultiSearch>>(request);
var result = await Api.Request<TheMovieDbContainer<MultiSearch>>(request, cancellationToken);
return result;
}

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

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

@ -0,0 +1,28 @@
<table mat-table
[dataSource]="pendingIssues" multiTemplateDataRows
class="mat-elevation-z8">
<ng-container matColumnDef="{{column}}" *ngFor="let column of columnsToDisplay">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let element"> {{element[column]}} </td>
</ng-container>
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplay.length">
<div class="example-element-detail"
[@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
<div class="example-element-diagram">
<div class="example-element-position"> {{element.requestId}} </div>
</div>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let element; columns: columnsToDisplay;"
class="example-element-row"
[class.example-expanded-row]="expandedElement === element"
(click)="expandedElement = expandedElement === element ? null : element">
</tr>
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
</table>

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

@ -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,

@ -48,7 +48,7 @@ namespace Ombi.Controllers.V2
[HttpGet("multi/{searchTerm}")]
public async Task<List<MultiSearch>> MultiSearch(string searchTerm)
{
return await _multiSearchEngine.MultiSearch(searchTerm);
return await _multiSearchEngine.MultiSearch(searchTerm, Request.HttpContext.RequestAborted);
}
/// <summary>
@ -58,7 +58,7 @@ namespace Ombi.Controllers.V2
[HttpGet("movie/{movieDbId}")]
public async Task<MovieFullInfoViewModel> GetMovieInfo(int movieDbId)
{
return await _movieEngineV2.GetFullMovieInformation(movieDbId);
return await _movieEngineV2.GetFullMovieInformation(movieDbId, Request.HttpContext.RequestAborted);
}
/// <summary>
@ -69,7 +69,7 @@ namespace Ombi.Controllers.V2
[HttpGet("movie/collection/{collectionId}")]
public async Task<MovieCollectionsViewModel> GetMovieCollections(int collectionId)
{
return await _movieEngineV2.GetCollection(collectionId);
return await _movieEngineV2.GetCollection(collectionId, Request.HttpContext.RequestAborted);
}
/// <summary>
@ -133,7 +133,7 @@ namespace Ombi.Controllers.V2
[ProducesDefaultResponseType]
public async Task<IEnumerable<SearchMovieViewModel>> Popular(int currentPosition, int amountToLoad)
{
return await _movieEngineV2.PopularMovies(currentPosition, amountToLoad);
return await _movieEngineV2.PopularMovies(currentPosition, amountToLoad, Request.HttpContext.RequestAborted);
}
/// <summary>

@ -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)
{

Loading…
Cancel
Save