Merge branch 'feature/v4' of https://github.com/tidusjar/Ombi into feature/v4

pull/3528/head
Jamie Rees 4 years ago
commit 4179e557d4

@ -1,18 +0,0 @@
name: '$(Build.SourceBranchName)_$(Date:yyyy.MM.dd)$(Rev:.r)'
trigger: none
variables:
- template: templates/variables.yml
jobs:
- job: Build
pool:
vmImage: ${{ variables.vmImage }}
steps:
- template: templates/build-steps.yml
- job: Publish
pool:
vmImage: ${{ variables.vmImage }}
steps:
- template: templates/publish-stepsnew.yml

@ -18,16 +18,28 @@ stages:
matrix:
win10-x64:
runtime: win10-x64
format: zip
compression: zip
win10-x86:
runtime: win10-x86
format: zip
compression: zip
osx-x64:
runtime: osx-x64
format: tar.gz
compression: tar
linux-x64:
runtime: linux-x64
format: tar.gz
compression: tar
linux-arm:
runtime: linux-arm
format: tar.gz
compression: tar
linux-arm64:
runtime: linux-arm64
format: tar.gz
compression: tar
pool:
vmImage: ${{ variables.vmImage }}
steps:
@ -42,6 +54,14 @@ stages:
buildType: 'current'
targetPath: '$(System.ArtifactsDirectory)'
- task: PowerShell@2
displayName: 'Get Release Notes'
inputs:
targetType: 'inline'
script: |
$response = Invoke-WebRequest -Uri "https://ombireleasenote.azurewebsites.net/api/ReleaseNotesFunction?buildId=$(Build.BuildId)"
Write-Host "##vso[task.setvariable variable=ReleaseNotes;]$response"
- task: GitHubRelease@1
inputs:
gitHubConnection: 'github.com_tidusjar'
@ -54,7 +74,7 @@ stages:
releaseNotesInline: '$(ReleaseNotes)'
assets: |
$(System.ArtifactsDirectory)/**/*.zip
$(System.ArtifactsDirectory)/S**/*.gz
$(System.ArtifactsDirectory)/**/*.tar.gz
isPreRelease: true
changeLogCompareToRelease: 'lastNonDraftRelease'
changeLogType: 'commitBased'

@ -6,28 +6,6 @@ steps:
inputs:
packageType: 'sdk'
version: '3.x'
- task: DotNetCoreInstaller@1
displayName: 'Use .NET Core sdk for versioning'
inputs:
packageType: 'sdk'
version: '2.1.x'
- task: PowerShell@2
displayName: 'Get Release Notes'
inputs:
targetType: 'inline'
script: |
$response = Invoke-WebRequest -Uri "https://ombireleasenote.azurewebsites.net/api/ReleaseNotesFunction?buildId=$(Build.BuildId)"
Write-Host "##vso[task.setvariable variable=ReleaseNotes;]$response"
- task: PowerShell@2
displayName: 'Set Version'
inputs:
targetType: 'inline'
script: |
dotnet tool install -g dotnet-setversion
setversion -r $(BuildVersion)
- task: Yarn@3
displayName: 'Install UI Dependancies'

@ -1,4 +1,24 @@
steps:
- task: DotNetCoreInstaller@1
displayName: 'Use .NET Core sdk '
inputs:
packageType: 'sdk'
version: '3.x'
- task: DotNetCoreInstaller@1
displayName: 'Use .NET Core sdk for versioning'
inputs:
packageType: 'sdk'
version: '2.1.x'
- task: PowerShell@2
displayName: 'Set Version'
inputs:
targetType: 'inline'
script: |
dotnet tool install -g dotnet-setversion
setversion -r $(BuildVersion)
- task: DotNetCoreCLI@2
displayName: 'publish $(runtime)'
inputs:
@ -26,12 +46,12 @@ steps:
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/$(runtime)'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/$(runtime).zip'
archiveType: $(compression)
archiveFile: '$(Build.ArtifactStagingDirectory)/$(runtime).$(format)'
replaceExistingArchive: true
- task: PublishPipelineArtifact@1
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)/$(runtime).zip'
targetPath: '$(Build.ArtifactStagingDirectory)/$(runtime).$(format)'
artifact: '$(runtime)'
publishLocation: 'pipeline'

@ -1,171 +0,0 @@
steps:
- task: DotNetCoreCLI@2
displayName: Publish Win10-x64
inputs:
command: 'publish'
publishWebProjects: true
arguments: '-c $(BuildConfiguration) -r "win10-x64" -o $(Build.ArtifactStagingDirectory)/win-64'
zipAfterPublish: false
modifyOutputPath: false
- task: CopyFiles@2
displayName: 'Copy Angular App Win10-x64'
inputs:
SourceFolder: '$(UiLocation)dist'
Contents: '**'
TargetFolder: '$(Build.ArtifactStagingDirectory)/win-64/ClientApp/dist'
- task: DotNetCoreCLI@2
displayName: Publish Win10-x86
inputs:
command: 'publish'
publishWebProjects: true
arguments: '-c $(BuildConfiguration) -r "win10-x86" -o $(Build.ArtifactStagingDirectory)/win-86'
zipAfterPublish: false
modifyOutputPath: false
- task: CopyFiles@2
displayName: 'Copy Angular App Win10-x86'
inputs:
SourceFolder: '$(UiLocation)dist'
Contents: '**'
TargetFolder: '$(Build.ArtifactStagingDirectory)/win-86/ClientApp/dist'
- task: DotNetCoreCLI@2
displayName: Publish OSX-x64
inputs:
command: 'publish'
publishWebProjects: true
arguments: '-c $(BuildConfiguration) -r "osx-x64" -o $(Build.ArtifactStagingDirectory)/osx-64'
zipAfterPublish: false
modifyOutputPath: false
- task: CopyFiles@2
displayName: 'Copy Angular App OSX-x64'
inputs:
SourceFolder: '$(UiLocation)dist'
Contents: '**'
TargetFolder: '$(Build.ArtifactStagingDirectory)/osx-64/ClientApp/dist'
- task: DotNetCoreCLI@2
displayName: Publish Linux-x64
inputs:
command: 'publish'
publishWebProjects: true
arguments: '-c $(BuildConfiguration) -r "linux-x64" -o $(Build.ArtifactStagingDirectory)/linux-64'
zipAfterPublish: false
modifyOutputPath: false
- task: CopyFiles@2
displayName: 'Copy Angular App Linux-x64'
inputs:
SourceFolder: '$(UiLocation)dist'
Contents: '**'
TargetFolder: '$(Build.ArtifactStagingDirectory)/linux-64/ClientApp/dist'
- task: DotNetCoreCLI@2
displayName: Publish Linux-ARM
inputs:
command: 'publish'
publishWebProjects: true
arguments: '-c $(BuildConfiguration) -r "linux-arm" -o $(Build.ArtifactStagingDirectory)/linux-arm'
zipAfterPublish: false
modifyOutputPath: false
- task: CopyFiles@2
displayName: 'Copy Angular App Linux-ARM'
inputs:
SourceFolder: '$(UiLocation)dist'
Contents: '**'
TargetFolder: '$(Build.ArtifactStagingDirectory)/linux-arm/ClientApp/dist'
- task: DotNetCoreCLI@2
displayName: Publish Linux-ARM-x64
inputs:
command: 'publish'
publishWebProjects: true
arguments: '-c $(BuildConfiguration) -r "linux-arm64" -o $(Build.ArtifactStagingDirectory)/linux-arm64'
zipAfterPublish: false
modifyOutputPath: false
- task: CopyFiles@2
displayName: 'Copy Angular App Linux-ARM64'
inputs:
SourceFolder: '$(UiLocation)dist'
Contents: '**'
TargetFolder: '$(Build.ArtifactStagingDirectory)/linux-arm64/ClientApp/dist'
### Zip them up
- task: ArchiveFiles@2
displayName: Zip Win-x64
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/win-64'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/win-x64-$(Build.BuildId).zip'
replaceExistingArchive: true
- task: ArchiveFiles@2
displayName: Zip Win-x86
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/win-86'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/win-x86-$(Build.BuildId).zip'
replaceExistingArchive: true
- task: ArchiveFiles@2
displayName: Zip OSX-x64
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/osx-64'
includeRootFolder: false
archiveType: 'tar'
archiveFile: '$(Build.ArtifactStagingDirectory)/osx-x64-$(Build.BuildId).tar.gz'
replaceExistingArchive: true
- task: ArchiveFiles@2
displayName: Zip Linux-x64
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/linux-64'
includeRootFolder: false
archiveType: 'tar'
archiveFile: '$(Build.ArtifactStagingDirectory)/linux-x64-$(Build.BuildId).tar.gz'
replaceExistingArchive: true
- task: ArchiveFiles@2
displayName: Zip Linux-ARM
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/linux-arm'
includeRootFolder: false
archiveType: 'tar'
archiveFile: '$(Build.ArtifactStagingDirectory)/linux-arm-$(Build.BuildId).tar.gz'
replaceExistingArchive: true
- task: ArchiveFiles@2
displayName: Zip Linux-ARM-x64
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/linux-arm64'
includeRootFolder: false
archiveType: 'tar'
archiveFile: '$(Build.ArtifactStagingDirectory)/linux-arm64-$(Build.BuildId).tar.gz'
replaceExistingArchive: true
- task: GitHubRelease@1
inputs:
gitHubConnection: 'github.com_tidusjar'
repositoryName: 'tidusjar/Ombi.Releases'
action: 'create'
target: 'c7fcbb77b58aef1076d635a9ef99e4374abc8672'
tagSource: 'userSpecifiedTag'
tag: '$(gitTag)'
releaseNotesSource: 'inline'
releaseNotesInline: '$(ReleaseNotes)'
assets: |
$(Build.ArtifactStagingDirectory)/*.zip
$(Build.ArtifactStagingDirectory)/*.gz
isPreRelease: true
changeLogCompareToRelease: 'lastNonDraftRelease'
changeLogType: 'commitBased'
condition: and(succeeded(), eq(variables['PublishToGithub'], 'true'))

@ -24,7 +24,4 @@ variables:
value: "$(Build.SourcesDirectory)/src/Ombi/ClientApp/"
- name: "BuildVersion"
value: "4.0.$(Build.BuildId)"
- name: "ReleaseNotes"
value: ""
value: "4.0.$(Build.BuildId)"

@ -0,0 +1,41 @@
using Ombi.Api;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using System.Threading.Tasks;
namespace Ombi.Api.Emby
{
public class EmbyApiFactory : IEmbyApiFactory
{
private readonly ISettingsService<EmbySettings> _embySettings;
private readonly IApi _api;
// TODO, if we need to derive futher, need to rework
public EmbyApiFactory(ISettingsService<EmbySettings> embySettings, IApi api)
{
_embySettings = embySettings;
_api = api;
}
public async Task<IEmbyApi> CreateClient()
{
var settings = await _embySettings.GetSettingsAsync();
return CreateClient(settings);
}
public IEmbyApi CreateClient(EmbySettings settings)
{
if (settings.IsJellyfin)
{
return new JellyfinApi(_api);
}
return new EmbyApi(_api);
}
}
public interface IEmbyApiFactory
{
Task<IEmbyApi> CreateClient();
IEmbyApi CreateClient(EmbySettings settings);
}
}

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Ombi.Api.Emby.Models;
using Ombi.Api.Emby.Models.Media.Tv;
using Ombi.Api.Emby.Models.Movie;
namespace Ombi.Api.Emby
{
public interface IBaseEmbyApi
{
Task<EmbySystemInfo> GetSystemInformation(string apiKey, string baseUrl);
Task<List<EmbyUser>> GetUsers(string baseUri, string apiKey);
Task<EmbyUser> LogIn(string username, string password, string apiKey, string baseUri);
Task<EmbyItemContainer<EmbyMovie>> GetAllMovies(string apiKey, int startIndex, int count, string userId,
string baseUri);
Task<EmbyItemContainer<EmbyEpisodes>> GetAllEpisodes(string apiKey, int startIndex, int count, string userId,
string baseUri);
Task<EmbyItemContainer<EmbySeries>> GetAllShows(string apiKey, int startIndex, int count, string userId,
string baseUri);
Task<EmbyItemContainer<EmbyMovie>> GetCollection(string mediaId,
string apiKey, string userId, string baseUrl);
Task<SeriesInformation> GetSeriesInformation(string mediaId, string apiKey, string userId, string baseUrl);
Task<MovieInformation> GetMovieInformation(string mediaId, string apiKey, string userId, string baseUrl);
Task<EpisodeInformation> GetEpisodeInformation(string mediaId, string apiKey, string userId, string baseUrl);
Task<PublicInfo> GetPublicInformation(string baseUrl);
}
}

@ -1,34 +1,10 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading.Tasks;
using Ombi.Api.Emby.Models;
using Ombi.Api.Emby.Models.Media.Tv;
using Ombi.Api.Emby.Models.Movie;
namespace Ombi.Api.Emby
{
public interface IEmbyApi
{
Task<EmbySystemInfo> GetSystemInformation(string apiKey, string baseUrl);
Task<List<EmbyUser>> GetUsers(string baseUri, string apiKey);
Task<EmbyUser> LogIn(string username, string password, string apiKey, string baseUri);
public interface IEmbyApi : IBaseEmbyApi
{
Task<EmbyConnectUser> LoginConnectUser(string username, string password);
Task<EmbyItemContainer<EmbyMovie>> GetAllMovies(string apiKey, int startIndex, int count, string userId,
string baseUri);
Task<EmbyItemContainer<EmbyEpisodes>> GetAllEpisodes(string apiKey, int startIndex, int count, string userId,
string baseUri);
Task<EmbyItemContainer<EmbySeries>> GetAllShows(string apiKey, int startIndex, int count, string userId,
string baseUri);
Task<EmbyItemContainer<EmbyMovie>> GetCollection(string mediaId,
string apiKey, string userId, string baseUrl);
Task<SeriesInformation> GetSeriesInformation(string mediaId, string apiKey, string userId, string baseUrl);
Task<MovieInformation> GetMovieInformation(string mediaId, string apiKey, string userId, string baseUrl);
Task<EpisodeInformation> GetEpisodeInformation(string mediaId, string apiKey, string userId, string baseUrl);
Task<PublicInfo> GetPublicInformation(string baseUrl);
}
}

@ -0,0 +1,180 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Internal;
using Newtonsoft.Json;
using Ombi.Api.Emby.Models;
using Ombi.Api.Emby.Models.Media.Tv;
using Ombi.Api.Emby.Models.Movie;
using Ombi.Helpers;
namespace Ombi.Api.Emby
{
public class JellyfinApi : IEmbyApi
{
public JellyfinApi(IApi api)
{
Api = api;
}
private IApi Api { get; }
/// <summary>
/// Returns all users from the Emby Instance
/// </summary>
/// <param name="baseUri"></param>
/// <param name="apiKey"></param>
public async Task<List<EmbyUser>> GetUsers(string baseUri, string apiKey)
{
var request = new Request("jellyfin/users", baseUri, HttpMethod.Get);
AddHeaders(request, apiKey);
var obj = await Api.Request<List<EmbyUser>>(request);
return obj;
}
public async Task<EmbySystemInfo> GetSystemInformation(string apiKey, string baseUrl)
{
var request = new Request("jellyfin/System/Info", baseUrl, HttpMethod.Get);
AddHeaders(request, apiKey);
var obj = await Api.Request<EmbySystemInfo>(request);
return obj;
}
public async Task<PublicInfo> GetPublicInformation(string baseUrl)
{
var request = new Request("jellyfin/System/Info/public", baseUrl, HttpMethod.Get);
AddHeaders(request, string.Empty);
var obj = await Api.Request<PublicInfo>(request);
return obj;
}
public async Task<EmbyUser> LogIn(string username, string password, string apiKey, string baseUri)
{
var request = new Request("jellyfin/users/authenticatebyname", baseUri, HttpMethod.Post);
var body = new
{
username,
pw = password,
};
request.AddJsonBody(body);
request.AddHeader("X-Emby-Authorization",
$"MediaBrowser Client=\"Ombi\", Device=\"Ombi\", DeviceId=\"v3\", Version=\"v3\"");
AddHeaders(request, apiKey);
var obj = await Api.Request<EmbyUser>(request);
return obj;
}
public async Task<EmbyItemContainer<EmbyMovie>> GetCollection(string mediaId, string apiKey, string userId, string baseUrl)
{
var request = new Request($"jellyfin/users/{userId}/items?parentId={mediaId}", baseUrl, HttpMethod.Get);
AddHeaders(request, apiKey);
request.AddQueryString("Fields", "ProviderIds,Overview");
request.AddQueryString("IsVirtualItem", "False");
return await Api.Request<EmbyItemContainer<EmbyMovie>>(request);
}
public async Task<EmbyItemContainer<EmbyMovie>> GetAllMovies(string apiKey, int startIndex, int count, string userId, string baseUri)
{
return await GetAll<EmbyMovie>("Movie", apiKey, userId, baseUri, true, startIndex, count);
}
public async Task<EmbyItemContainer<EmbyEpisodes>> GetAllEpisodes(string apiKey, int startIndex, int count, string userId, string baseUri)
{
return await GetAll<EmbyEpisodes>("Episode", apiKey, userId, baseUri, false, startIndex, count);
}
public async Task<EmbyItemContainer<EmbySeries>> GetAllShows(string apiKey, int startIndex, int count, string userId, string baseUri)
{
return await GetAll<EmbySeries>("Series", apiKey, userId, baseUri, false, startIndex, count);
}
public async Task<SeriesInformation> GetSeriesInformation(string mediaId, string apiKey, string userId, string baseUrl)
{
return await GetInformation<SeriesInformation>(mediaId, apiKey, userId, baseUrl);
}
public async Task<MovieInformation> GetMovieInformation(string mediaId, string apiKey, string userId, string baseUrl)
{
return await GetInformation<MovieInformation>(mediaId, apiKey, userId, baseUrl);
}
public async Task<EpisodeInformation> GetEpisodeInformation(string mediaId, string apiKey, string userId, string baseUrl)
{
return await GetInformation<EpisodeInformation>(mediaId, apiKey, userId, baseUrl);
}
private async Task<T> GetInformation<T>(string mediaId, string apiKey, string userId, string baseUrl)
{
var request = new Request($"jellyfin/users/{userId}/items/{mediaId}", baseUrl, HttpMethod.Get);
AddHeaders(request, apiKey);
var response = await Api.RequestContent(request);
return JsonConvert.DeserializeObject<T>(response);
}
private async Task<EmbyItemContainer<T>> GetAll<T>(string type, string apiKey, string userId, string baseUri, bool includeOverview = false)
{
var request = new Request($"jellyfin/users/{userId}/items", baseUri, HttpMethod.Get);
request.AddQueryString("Recursive", true.ToString());
request.AddQueryString("IncludeItemTypes", type);
request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview" : "ProviderIds");
request.AddQueryString("IsVirtualItem", "False");
AddHeaders(request, apiKey);
var obj = await Api.Request<EmbyItemContainer<T>>(request);
return obj;
}
private async Task<EmbyItemContainer<T>> GetAll<T>(string type, string apiKey, string userId, string baseUri, bool includeOverview, int startIndex, int count)
{
var request = new Request($"jellyfin/users/{userId}/items", baseUri, HttpMethod.Get);
request.AddQueryString("Recursive", true.ToString());
request.AddQueryString("IncludeItemTypes", type);
request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview" : "ProviderIds");
request.AddQueryString("startIndex", startIndex.ToString());
request.AddQueryString("limit", count.ToString());
request.AddQueryString("IsVirtualItem", "False");
AddHeaders(request, apiKey);
var obj = await Api.Request<EmbyItemContainer<T>>(request);
return obj;
}
private static void AddHeaders(Request req, string apiKey)
{
if (!string.IsNullOrEmpty(apiKey))
{
req.AddHeader("X-MediaBrowser-Token", apiKey);
}
req.AddHeader("Accept", "application/json");
req.AddContentHeader("Content-Type", "application/json");
req.AddHeader("Device", "Ombi");
}
public Task<EmbyConnectUser> LoginConnectUser(string username, string password)
{
throw new System.NotImplementedException();
}
}
}

@ -49,7 +49,7 @@ namespace Ombi.Core.Authentication
IPasswordHasher<OmbiUser> passwordHasher, IEnumerable<IUserValidator<OmbiUser>> userValidators,
IEnumerable<IPasswordValidator<OmbiUser>> passwordValidators, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<OmbiUser>> logger, IPlexApi plexApi,
IEmbyApi embyApi, ISettingsService<EmbySettings> embySettings, ISettingsService<AuthenticationSettings> auth)
IEmbyApiFactory embyApi, ISettingsService<EmbySettings> embySettings, ISettingsService<AuthenticationSettings> auth)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
_plexApi = plexApi;
@ -59,7 +59,7 @@ namespace Ombi.Core.Authentication
}
private readonly IPlexApi _plexApi;
private readonly IEmbyApi _embyApi;
private readonly IEmbyApiFactory _embyApi;
private readonly ISettingsService<EmbySettings> _embySettings;
private readonly ISettingsService<AuthenticationSettings> _authSettings;
@ -146,9 +146,12 @@ namespace Ombi.Core.Authentication
/// <returns></returns>
private async Task<bool> CheckEmbyPasswordAsync(OmbiUser user, string password)
{
var embySettings = await _embySettings.GetSettingsAsync();
var client = _embyApi.CreateClient(embySettings);
if (user.IsEmbyConnect)
{
var result = await _embyApi.LoginConnectUser(user.UserName, password);
var result = await client.LoginConnectUser(user.UserName, password);
if (result.AccessToken.HasValue())
{
// We cannot update the email address in the user importer due to there is no way
@ -165,12 +168,11 @@ namespace Ombi.Core.Authentication
}
}
var embySettings = await _embySettings.GetSettingsAsync();
foreach (var server in embySettings.Servers)
{
try
{
var result = await _embyApi.LogIn(user.UserName, password, server.ApiKey, server.FullUri);
var result = await client.LogIn(user.UserName, password, server.ApiKey, server.FullUri);
if (result != null)
{
return true;

@ -151,6 +151,8 @@ namespace Ombi.DependencyInjection
services.AddTransient<IMusicBrainzApi, MusicBrainzApi>();
services.AddTransient<IWhatsAppApi, WhatsAppApi>();
services.AddTransient<ICloudMobileNotification, CloudMobileNotification>();
services.AddTransient<IBaseEmbyApi, JellyfinApi>();
services.AddTransient<IEmbyApiFactory, EmbyApiFactory>();
}
public static void RegisterStore(this IServiceCollection services) {

@ -25,17 +25,18 @@ namespace Ombi.HealthChecks.Checks
using (var scope = CreateScope())
{
var settingsProvider = scope.ServiceProvider.GetRequiredService<ISettingsService<EmbySettings>>();
var api = scope.ServiceProvider.GetRequiredService<IEmbyApi>();
var api = scope.ServiceProvider.GetRequiredService<IEmbyApiFactory>();
var settings = await settingsProvider.GetSettingsAsync();
if (settings == null)
{
return HealthCheckResult.Healthy("Emby is not configured.");
}
var client = api.CreateClient(settings);
var taskResult = new List<Task<EmbySystemInfo>>();
foreach (var server in settings.Servers)
{
taskResult.Add(api.GetSystemInformation(server.ApiKey, server.FullUri));
taskResult.Add(client.GetSystemInformation(server.ApiKey, server.FullUri));
}
try

@ -20,28 +20,30 @@ namespace Ombi.Schedule.Jobs.Emby
{
public class EmbyContentSync : IEmbyContentSync
{
public EmbyContentSync(ISettingsService<EmbySettings> settings, IEmbyApi api, ILogger<EmbyContentSync> logger,
public EmbyContentSync(ISettingsService<EmbySettings> settings, IEmbyApiFactory api, ILogger<EmbyContentSync> logger,
IEmbyContentRepository repo, IHubContext<NotificationHub> notification)
{
_logger = logger;
_settings = settings;
_api = api;
_apiFactory = api;
_repo = repo;
_notification = notification;
}
private readonly ILogger<EmbyContentSync> _logger;
private readonly ISettingsService<EmbySettings> _settings;
private readonly IEmbyApi _api;
private readonly IEmbyApiFactory _apiFactory;
private readonly IEmbyContentRepository _repo;
private readonly IHubContext<NotificationHub> _notification;
private IEmbyApi Api { get; set; }
public async Task Execute(IJobExecutionContext job)
{
var embySettings = await _settings.GetSettingsAsync();
if (!embySettings.Enable)
return;
Api = _apiFactory.CreateClient(embySettings);
await _notification.Clients.Clients(NotificationHub.AdminConnectionIds)
.SendAsync(NotificationHub.NotificationEvent, "Emby Content Sync Started");
@ -76,7 +78,7 @@ namespace Ombi.Schedule.Jobs.Emby
//await _repo.ExecuteSql("DELETE FROM EmbyEpisode");
//await _repo.ExecuteSql("DELETE FROM EmbyContent");
var movies = await _api.GetAllMovies(server.ApiKey, 0, 200, server.AdministratorId, server.FullUri);
var movies = await Api.GetAllMovies(server.ApiKey, 0, 200, server.AdministratorId, server.FullUri);
var totalCount = movies.TotalRecordCount;
var processed = 1;
@ -89,7 +91,7 @@ namespace Ombi.Schedule.Jobs.Emby
if (movie.Type.Equals("boxset", StringComparison.InvariantCultureIgnoreCase))
{
var movieInfo =
await _api.GetCollection(movie.Id, server.ApiKey, server.AdministratorId, server.FullUri);
await Api.GetCollection(movie.Id, server.ApiKey, server.AdministratorId, server.FullUri);
foreach (var item in movieInfo.Items)
{
await ProcessMovies(item, mediaToAdd, server);
@ -106,7 +108,7 @@ namespace Ombi.Schedule.Jobs.Emby
}
// Get the next batch
movies = await _api.GetAllMovies(server.ApiKey, processed, 200, server.AdministratorId, server.FullUri);
movies = await Api.GetAllMovies(server.ApiKey, processed, 200, server.AdministratorId, server.FullUri);
await _repo.AddRange(mediaToAdd);
mediaToAdd.Clear();
@ -114,7 +116,7 @@ namespace Ombi.Schedule.Jobs.Emby
// TV Time
var tv = await _api.GetAllShows(server.ApiKey, 0, 200, server.AdministratorId, server.FullUri);
var tv = await Api.GetAllShows(server.ApiKey, 0, 200, server.AdministratorId, server.FullUri);
var totalTv = tv.TotalRecordCount;
processed = 1;
while (processed < totalTv)
@ -160,7 +162,7 @@ namespace Ombi.Schedule.Jobs.Emby
}
}
// Get the next batch
tv = await _api.GetAllShows(server.ApiKey, processed, 200, server.AdministratorId, server.FullUri);
tv = await Api.GetAllShows(server.ApiKey, processed, 200, server.AdministratorId, server.FullUri);
await _repo.AddRange(mediaToAdd);
mediaToAdd.Clear();
}

@ -44,10 +44,10 @@ namespace Ombi.Schedule.Jobs.Emby
{
public class EmbyEpisodeSync : IEmbyEpisodeSync
{
public EmbyEpisodeSync(ISettingsService<EmbySettings> s, IEmbyApi api, ILogger<EmbyEpisodeSync> l, IEmbyContentRepository repo
public EmbyEpisodeSync(ISettingsService<EmbySettings> s, IEmbyApiFactory api, ILogger<EmbyEpisodeSync> l, IEmbyContentRepository repo
, IHubContext<NotificationHub> notification)
{
_api = api;
_apiFactory = api;
_logger = l;
_settings = s;
_repo = repo;
@ -55,16 +55,18 @@ namespace Ombi.Schedule.Jobs.Emby
}
private readonly ISettingsService<EmbySettings> _settings;
private readonly IEmbyApi _api;
private readonly IEmbyApiFactory _apiFactory;
private readonly ILogger<EmbyEpisodeSync> _logger;
private readonly IEmbyContentRepository _repo;
private readonly IHubContext<NotificationHub> _notification;
private IEmbyApi Api { get; set; }
public async Task Execute(IJobExecutionContext job)
{
var settings = await _settings.GetSettingsAsync();
Api = _apiFactory.CreateClient(settings);
await _notification.Clients.Clients(NotificationHub.AdminConnectionIds)
.SendAsync(NotificationHub.NotificationEvent, "Emby Episode Sync Started");
foreach (var server in settings.Servers)
@ -80,7 +82,7 @@ namespace Ombi.Schedule.Jobs.Emby
private async Task CacheEpisodes(EmbyServers server)
{
var allEpisodes = await _api.GetAllEpisodes(server.ApiKey, 0, 200, server.AdministratorId, server.FullUri);
var allEpisodes = await Api.GetAllEpisodes(server.ApiKey, 0, 200, server.AdministratorId, server.FullUri);
var total = allEpisodes.TotalRecordCount;
var processed = 1;
var epToAdd = new HashSet<EmbyEpisode>();
@ -147,7 +149,7 @@ namespace Ombi.Schedule.Jobs.Emby
await _repo.AddRange(epToAdd);
epToAdd.Clear();
allEpisodes = await _api.GetAllEpisodes(server.ApiKey, processed, 200, server.AdministratorId, server.FullUri);
allEpisodes = await Api.GetAllEpisodes(server.ApiKey, processed, 200, server.AdministratorId, server.FullUri);
}
if (epToAdd.Any())

@ -45,10 +45,10 @@ namespace Ombi.Schedule.Jobs.Emby
{
public class EmbyUserImporter : IEmbyUserImporter
{
public EmbyUserImporter(IEmbyApi api, UserManager<OmbiUser> um, ILogger<EmbyUserImporter> log,
public EmbyUserImporter(IEmbyApiFactory api, UserManager<OmbiUser> um, ILogger<EmbyUserImporter> log,
ISettingsService<EmbySettings> embySettings, ISettingsService<UserManagementSettings> ums, IHubContext<NotificationHub> notification)
{
_api = api;
_apiFactory = api;
_userManager = um;
_log = log;
_embySettings = embySettings;
@ -56,12 +56,13 @@ namespace Ombi.Schedule.Jobs.Emby
_notification = notification;
}
private readonly IEmbyApi _api;
private readonly IEmbyApiFactory _apiFactory;
private readonly UserManager<OmbiUser> _userManager;
private readonly ILogger<EmbyUserImporter> _log;
private readonly ISettingsService<EmbySettings> _embySettings;
private readonly ISettingsService<UserManagementSettings> _userManagementSettings;
private readonly IHubContext<NotificationHub> _notification;
private IEmbyApi Api { get; set; }
public async Task Execute(IJobExecutionContext job)
{
@ -76,6 +77,8 @@ namespace Ombi.Schedule.Jobs.Emby
return;
}
Api = _apiFactory.CreateClient(settings);
await _notification.Clients.Clients(NotificationHub.AdminConnectionIds)
.SendAsync(NotificationHub.NotificationEvent, "Emby User Importer Started");
var allUsers = await _userManager.Users.Where(x => x.UserType == UserType.EmbyUser).ToListAsync();
@ -86,7 +89,7 @@ namespace Ombi.Schedule.Jobs.Emby
continue;
}
var embyUsers = await _api.GetUsers(server.FullUri, server.ApiKey);
var embyUsers = await Api.GetUsers(server.FullUri, server.ApiKey);
foreach (var embyUser in embyUsers)
{
// Check if we should import this user

@ -138,8 +138,8 @@ namespace Ombi.Schedule.Jobs.Ombi
// Filter out the ones that we haven't sent yet
var plexContentLocalDataset = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && x.HasTheMovieDb).ToHashSet();
var embyContentLocalDataset = embyContent.Where(x => x.Type == EmbyMediaType.Movie && x.HasTheMovieDb).ToHashSet();
var plexContentLocalDataset = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
var embyContentLocalDataset = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
var plexContentMoviesToSend = plexContentLocalDataset.Where(x => !addedPlexMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet();
var embyContentMoviesToSend = embyContentLocalDataset.Where(x => !addedEmbyMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet();
var lidarrContentAlbumsToSend = lidarrContent.Where(x => !addedAlbumLogIds.Contains(x.ForeignAlbumId)).ToHashSet();
@ -148,16 +148,16 @@ namespace Ombi.Schedule.Jobs.Ombi
_log.LogInformation("Albums to send: {0}", lidarrContentAlbumsToSend.Count());
// Find the movies that do not yet have MovieDbIds
var needsMovieDbPlex = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !x.HasTheMovieDb).ToHashSet();
var needsMovieDbEmby = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !x.HasTheMovieDb).ToHashSet();
var needsMovieDbPlex = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
var needsMovieDbEmby = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
var newPlexMovies = await GetMoviesWithoutId(addedPlexMovieLogIds, needsMovieDbPlex);
var newEmbyMovies = await GetMoviesWithoutId(addedEmbyMoviesLogIds, needsMovieDbEmby);
plexContentMoviesToSend = plexContentMoviesToSend.Union(newPlexMovies).ToHashSet();
embyContentMoviesToSend = embyContentMoviesToSend.Union(newEmbyMovies).ToHashSet();
var plexEpisodesToSend =
FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).Where(x => x.Series.HasTvDb).AsNoTracking(), addedPlexEpisodesLogIds);
var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).Where(x => x.Series.HasTvDb).AsNoTracking(),
FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), addedPlexEpisodesLogIds);
var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).AsNoTracking(),
addedEmbyEpisodesLogIds);
_log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count());
@ -386,7 +386,7 @@ namespace Ombi.Schedule.Jobs.Ombi
private HashSet<PlexEpisode> FilterPlexEpisodes(IEnumerable<PlexEpisode> source, IQueryable<RecentlyAddedLog> recentlyAdded)
{
var itemsToReturn = new HashSet<PlexEpisode>();
foreach (var ep in source)
foreach (var ep in source.Where(x => x.Series.HasTvDb))
{
var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId);
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))
@ -403,7 +403,7 @@ namespace Ombi.Schedule.Jobs.Ombi
private HashSet<EmbyEpisode> FilterEmbyEpisodes(IEnumerable<EmbyEpisode> source, IQueryable<RecentlyAddedLog> recentlyAdded)
{
var itemsToReturn = new HashSet<EmbyEpisode>();
foreach (var ep in source)
foreach (var ep in source.Where(x => x.Series.HasTvDb))
{
var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId);
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))

@ -23,7 +23,7 @@ namespace Ombi.Schedule.Jobs.Ombi
{
public RefreshMetadata(IPlexContentRepository plexRepo, IEmbyContentRepository embyRepo,
ILogger<RefreshMetadata> log, ITvMazeApi tvApi, ISettingsService<PlexSettings> plexSettings,
IMovieDbApi movieApi, ISettingsService<EmbySettings> embySettings, IEmbyApi embyApi, IHubContext<NotificationHub> notification)
IMovieDbApi movieApi, ISettingsService<EmbySettings> embySettings, IEmbyApiFactory embyApi, IHubContext<NotificationHub> notification)
{
_plexRepo = plexRepo;
_embyRepo = embyRepo;
@ -32,7 +32,7 @@ namespace Ombi.Schedule.Jobs.Ombi
_tvApi = tvApi;
_plexSettings = plexSettings;
_embySettings = embySettings;
_embyApi = embyApi;
_embyApiFactory = embyApi;
_notification = notification;
}
@ -43,8 +43,9 @@ namespace Ombi.Schedule.Jobs.Ombi
private readonly ITvMazeApi _tvApi;
private readonly ISettingsService<PlexSettings> _plexSettings;
private readonly ISettingsService<EmbySettings> _embySettings;
private readonly IEmbyApi _embyApi;
private readonly IEmbyApiFactory _embyApiFactory;
private readonly IHubContext<NotificationHub> _notification;
private IEmbyApi EmbyApi { get; set; }
public async Task Execute(IJobExecutionContext job)
{
@ -94,6 +95,7 @@ namespace Ombi.Schedule.Jobs.Ombi
private async Task StartEmby(EmbySettings s)
{
EmbyApi = _embyApiFactory.CreateClient(s);
await StartEmbyMovies(s);
await StartEmbyTv();
}
@ -221,7 +223,7 @@ namespace Ombi.Schedule.Jobs.Ombi
foreach (var server in settings.Servers)
{
_log.LogInformation($"Checking server {server.Name} for upto date metadata");
var movieInfo = await _embyApi.GetMovieInformation(movie.EmbyId, server.ApiKey, server.AdministratorId,
var movieInfo = await EmbyApi.GetMovieInformation(movie.EmbyId, server.ApiKey, server.AdministratorId,
server.FullUri);
if (movieInfo.ProviderIds?.Imdb.HasValue() ?? false)

@ -16,7 +16,7 @@ export class CookieComponent implements OnInit {
if (cookie.Auth) {
const jwtVal = cookie.Auth;
this.store.save("id_token", jwtVal);
this.router.navigate(["search"]);
this.router.navigate(["discover"]);
} else {
this.router.navigate(["login"]);
}

@ -3,6 +3,7 @@ import { SearchV2Service } from "../../../services";
import { ISearchMovieResult, ISearchTvResult, RequestType } from "../../../interfaces";
import { IDiscoverCardResult, DiscoverOption } from "../../interfaces";
import { trigger, transition, style, animate } from "@angular/animations";
import { StorageService } from "../../../shared/storage/storage-service";
@Component({
templateUrl: "./discover.component.html",
@ -21,7 +22,7 @@ export class DiscoverComponent implements OnInit {
public discoverResults: IDiscoverCardResult[] = [];
public movies: ISearchMovieResult[] = [];
public tvShows: ISearchTvResult[] = [];
public discoverOptions: DiscoverOption = DiscoverOption.Combined;
public DiscoverOption = DiscoverOption;
@ -36,22 +37,28 @@ export class DiscoverComponent implements OnInit {
private contentLoaded: number;
private isScrolling: boolean = false;
private mediaTypeStorageKey = "DiscoverOptions";
constructor(private searchService: SearchV2Service) { }
constructor(private searchService: SearchV2Service,
private storageService: StorageService) { }
public async ngOnInit() {
this.loading()
const localDiscoverOptions = +this.storageService.get(this.mediaTypeStorageKey);
if (localDiscoverOptions) {
this.discoverOptions = DiscoverOption[DiscoverOption[localDiscoverOptions]];
}
this.scrollDisabled = true;
switch (this.discoverOptions) {
case DiscoverOption.Combined:
this.movies = await this.searchService.popularMoviesByPage(0,12);
this.tvShows = await this.searchService.popularTvByPage(0,12);
this.movies = await this.searchService.popularMoviesByPage(0, 12);
this.tvShows = await this.searchService.popularTvByPage(0, 12);
break;
case DiscoverOption.Movie:
this.movies = await this.searchService.popularMoviesByPage(0,12);
this.movies = await this.searchService.popularMoviesByPage(0, 12);
break;
case DiscoverOption.Tv:
this.tvShows = await this.searchService.popularTvByPage(0,12);
this.tvShows = await this.searchService.popularTvByPage(0, 12);
break;
}
@ -108,7 +115,7 @@ export class DiscoverComponent implements OnInit {
case DiscoverOption.Tv:
this.tvShows = await this.searchService.anticipatedTvByPage(this.contentLoaded, 12);
break;
}
}
}
this.contentLoaded += 12;
@ -199,7 +206,8 @@ export class DiscoverComponent implements OnInit {
public async switchDiscoverMode(newMode: DiscoverOption) {
this.loading();
this.clear();
this.discoverOptions = newMode;
this.discoverOptions = newMode;
this.storageService.save(this.mediaTypeStorageKey, newMode.toString());
await this.ngOnInit();
this.finishLoading();
}

@ -10,8 +10,8 @@
</mat-select>
</mat-form-field>
<table mat-table [dataSource]="dataSource" class="table" matSort matSortActive="requestedDate"
matSortDisableClear matSortDirection="desc">
<table mat-table [dataSource]="dataSource" class="table" matSort [matSortActive]="defaultSort"
matSortDisableClear [matSortDirection]="defaultOrder">
<ng-container matColumnDef="requestedUser.requestedBy">

@ -1,4 +1,4 @@
import { Component, AfterViewInit, ViewChild, EventEmitter, Output, ChangeDetectorRef } from "@angular/core";
import { Component, AfterViewInit, ViewChild, EventEmitter, Output, ChangeDetectorRef, OnInit } from "@angular/core";
import { IMovieRequests, IRequestsViewModel } from "../../../interfaces";
import { MatPaginator, MatSort } from "@angular/material";
import { merge, Observable, of as observableOf } from 'rxjs';
@ -6,13 +6,14 @@ import { catchError, map, startWith, switchMap } from 'rxjs/operators';
import { RequestServiceV2 } from "../../../services/requestV2.service";
import { AuthService } from "../../../auth/auth.service";
import { StorageService } from "../../../shared/storage/storage-service";
@Component({
templateUrl: "./movies-grid.component.html",
selector: "movies-grid",
styleUrls: ["../requests-list.component.scss"]
})
export class MoviesGridComponent implements AfterViewInit {
export class MoviesGridComponent implements OnInit, AfterViewInit {
public dataSource: IMovieRequests[] = [];
public resultsLength: number;
public isLoadingResults = true;
@ -20,6 +21,11 @@ export class MoviesGridComponent implements AfterViewInit {
public gridCount: string = "15";
public showUnavailableRequests: boolean;
public isAdmin: boolean;
public defaultSort: string = "requestedDate";
public defaultOrder: string = "desc";
private storageKey = "Movie_DefaultRequestListSort";
private storageKeyOrder = "Movie_DefaultRequestListSortOrder";
@Output() public onOpenOptions = new EventEmitter<{ request: any, filter: any, onChange: any }>();
@ -27,9 +33,20 @@ export class MoviesGridComponent implements AfterViewInit {
@ViewChild(MatSort, { static: false }) sort: MatSort;
constructor(private requestService: RequestServiceV2, private ref: ChangeDetectorRef,
private auth: AuthService) {
private auth: AuthService, private storageService: StorageService) {
}
public ngOnInit() {
const defaultSort = this.storageService.get(this.storageKey);
const defaultOrder = this.storageService.get(this.storageKeyOrder);
if (defaultSort) {
this.defaultSort = defaultSort;
}
if (defaultOrder) {
this.defaultOrder = defaultOrder;
}
}
public async ngAfterViewInit() {
// const results = await this.requestService.getMovieRequests(this.gridCount, 0, OrderType.RequestedDateDesc,
@ -45,10 +62,12 @@ export class MoviesGridComponent implements AfterViewInit {
merge(this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
switchMap((value: any) => {
this.isLoadingResults = true;
// eturn this.exampleDatabase!.getRepoIssues(
// this.sort.active, this.sort.direction, this.paginator.pageIndex);
if (value.active || value.direction) {
this.storageService.save(this.storageKey, value.active);
this.storageService.save(this.storageKeyOrder, value.direction);
}
return this.loadData();
}),
map((data: IRequestsViewModel<IMovieRequests>) => {

@ -11,7 +11,7 @@
</ng-template>
</mat-tab>
<mat-tab label="Albums">
<h1>Some more tab content</h1>
<h1>Coming soon</h1>
<p>...</p>
</mat-tab>
</mat-tab-group>

@ -11,8 +11,8 @@
</mat-select>
</mat-form-field>
<table mat-table [dataSource]="dataSource" class="table" matSort matSortActive="title" matSortDisableClear
matSortDirection="desc">
<table mat-table [dataSource]="dataSource" class="table" matSort [matSortActive]="defaultSort" matSortDisableClear
[matSortDirection]="defaultOrder">
<ng-container matColumnDef="series">

@ -1,4 +1,4 @@
import { Component, AfterViewInit, ViewChild, Output, EventEmitter, ChangeDetectorRef } from "@angular/core";
import { Component, AfterViewInit, ViewChild, Output, EventEmitter, ChangeDetectorRef, OnInit } from "@angular/core";
import { IRequestsViewModel, IChildRequests } from "../../../interfaces";
import { MatPaginator, MatSort } from "@angular/material";
import { merge, of as observableOf, Observable } from 'rxjs';
@ -6,13 +6,14 @@ import { catchError, map, startWith, switchMap } from 'rxjs/operators';
import { RequestServiceV2 } from "../../../services/requestV2.service";
import { AuthService } from "../../../auth/auth.service";
import { StorageService } from "../../../shared/storage/storage-service";
@Component({
templateUrl: "./tv-grid.component.html",
selector: "tv-grid",
styleUrls: ["../requests-list.component.scss"]
})
export class TvGridComponent implements AfterViewInit {
export class TvGridComponent implements OnInit, AfterViewInit {
public dataSource: IChildRequests[] = [];
public resultsLength: number;
public isLoadingResults = true;
@ -20,6 +21,11 @@ export class TvGridComponent implements AfterViewInit {
public gridCount: string = "15";
public showUnavailableRequests: boolean;
public isAdmin: boolean;
public defaultSort: string = "requestedDate";
public defaultOrder: string = "desc";
private storageKey = "Tv_DefaultRequestListSort";
private storageKeyOrder = "Tv_DefaultRequestListSortOrder";
@Output() public onOpenOptions = new EventEmitter<{request: any, filter: any, onChange: any}>();
@ -27,8 +33,19 @@ export class TvGridComponent implements AfterViewInit {
@ViewChild(MatSort, {static: false}) sort: MatSort;
constructor(private requestService: RequestServiceV2, private auth: AuthService,
private ref: ChangeDetectorRef) {
private ref: ChangeDetectorRef, private storageService: StorageService) {
}
public ngOnInit() {
const defaultSort = this.storageService.get(this.storageKey);
const defaultOrder = this.storageService.get(this.storageKeyOrder);
if (defaultSort) {
this.defaultSort = defaultSort;
}
if (defaultOrder) {
this.defaultOrder = defaultOrder;
}
}
public async ngAfterViewInit() {
@ -40,8 +57,13 @@ export class TvGridComponent implements AfterViewInit {
merge(this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
switchMap((value: any) => {
this.isLoadingResults = true;
if (value.active || value.direction) {
this.storageService.save(this.storageKey, value.active);
this.storageService.save(this.storageKeyOrder, value.direction);
}
return this.loadData();
}),
map((data: IRequestsViewModel<IChildRequests>) => {

@ -24,13 +24,13 @@ namespace Ombi.Controllers.V1.External
/// </summary>
/// <param name="emby"></param>
/// <param name="embySettings"></param>
public EmbyController(IEmbyApi emby, ISettingsService<EmbySettings> embySettings)
public EmbyController(IEmbyApiFactory emby, ISettingsService<EmbySettings> embySettings)
{
EmbyApi = emby;
EmbySettings = embySettings;
}
private IEmbyApi EmbyApi { get; }
private IEmbyApiFactory EmbyApi { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
/// <summary>
@ -46,10 +46,11 @@ namespace Ombi.Controllers.V1.External
var settings = await EmbySettings.GetSettingsAsync();
if (settings?.Servers?.Any() ?? false) return null;
var client = await EmbyApi.CreateClient();
request.Enable = true;
var firstServer = request.Servers.FirstOrDefault();
// Test that we can connect
var result = await EmbyApi.GetUsers(firstServer.FullUri, firstServer.ApiKey);
var result = await client.GetUsers(firstServer.FullUri, firstServer.ApiKey);
if (result != null && result.Any())
{
@ -64,7 +65,8 @@ namespace Ombi.Controllers.V1.External
[HttpPost("info")]
public async Task<PublicInfo> GetServerInfo([FromBody] EmbyServers server)
{
var result = await EmbyApi.GetPublicInformation(server.FullUri);
var client = await EmbyApi.CreateClient();
var result = await client.GetPublicInformation(server.FullUri);
return result;
}
@ -77,9 +79,10 @@ namespace Ombi.Controllers.V1.External
{
var vm = new List<UsersViewModel>();
var s = await EmbySettings.GetSettingsAsync();
var client = EmbyApi.CreateClient(s);
foreach (var server in s?.Servers ?? new List<EmbyServers>())
{
var users = await EmbyApi.GetUsers(server.FullUri, server.ApiKey);
var users = await client.GetUsers(server.FullUri, server.ApiKey);
if (users != null && users.Any())
{
vm.AddRange(users.Select(u => new UsersViewModel

@ -42,7 +42,7 @@ namespace Ombi.Controllers.V1.External
/// </summary>
public TesterController(INotificationService service, IDiscordNotification notification, IEmailNotification emailN,
IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm,
IPlexApi plex, IEmbyApi emby, IRadarrApi radarr, ISonarrApi sonarr, ILogger<TesterController> log, IEmailProvider provider,
IPlexApi plex, IEmbyApiFactory emby, IRadarrApi radarr, ISonarrApi sonarr, ILogger<TesterController> log, IEmailProvider provider,
ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, ILegacyMobileNotification mobileNotification,
ILidarrApi lidarrApi, IGotifyNotification gotifyNotification, IWhatsAppApi whatsAppApi, OmbiUserManager um, IWebhookNotification webhookNotification)
{
@ -82,7 +82,7 @@ namespace Ombi.Controllers.V1.External
private IMattermostNotification MattermostNotification { get; }
private IPlexApi PlexApi { get; }
private IRadarrApi RadarrApi { get; }
private IEmbyApi EmbyApi { get; }
private IEmbyApiFactory EmbyApi { get; }
private ISonarrApi SonarrApi { get; }
private ICouchPotatoApi CouchPotatoApi { get; }
private ILogger<TesterController> Log { get; }
@ -322,8 +322,8 @@ namespace Ombi.Controllers.V1.External
{
try
{
var result = await EmbyApi.GetUsers(settings.FullUri, settings.ApiKey);
var client = await EmbyApi.CreateClient();
var result = await client.GetUsers(settings.FullUri, settings.ApiKey);
return result.Any();
}
catch (Exception e)

@ -18,7 +18,7 @@ namespace Ombi.Controllers.V1
public class LandingPageController : ControllerBase
{
public LandingPageController(ISettingsService<PlexSettings> plex, ISettingsService<EmbySettings> emby,
IPlexApi plexApi, IEmbyApi embyApi)
IPlexApi plexApi, IEmbyApiFactory embyApi)
{
_plexSettings = plex;
_embySettings = emby;
@ -27,7 +27,7 @@ namespace Ombi.Controllers.V1
}
private readonly IPlexApi _plexApi;
private readonly IEmbyApi _embyApi;
private readonly IEmbyApiFactory _embyApi;
private readonly ISettingsService<PlexSettings> _plexSettings;
private readonly ISettingsService<EmbySettings> _embySettings;
@ -65,11 +65,12 @@ namespace Ombi.Controllers.V1
var emby = await _embySettings.GetSettingsAsync();
if (emby.Enable)
{
var client = _embyApi.CreateClient(emby);
foreach (var server in emby.Servers)
{
try
{
var result = await _embyApi.GetUsers(server.FullUri, server.ApiKey);
var result = await client.GetUsers(server.FullUri, server.ApiKey);
if (result.Any())
{
model.ServersAvailable++;

@ -45,7 +45,7 @@ namespace Ombi.Controllers.V1
public SettingsController(ISettingsResolver resolver,
IMapper mapper,
INotificationTemplatesRepository templateRepo,
IEmbyApi embyApi,
IEmbyApiFactory embyApi,
ICacheService memCache,
IGithubApi githubApi,
IRecentlyAddedEngine engine)
@ -62,7 +62,7 @@ namespace Ombi.Controllers.V1
private ISettingsResolver SettingsResolver { get; }
private IMapper Mapper { get; }
private INotificationTemplatesRepository TemplateRepository { get; }
private readonly IEmbyApi _embyApi;
private readonly IEmbyApiFactory _embyApi;
private readonly ICacheService _cache;
private readonly IGithubApi _githubApi;
private readonly IRecentlyAddedEngine _recentlyAdded;
@ -212,9 +212,10 @@ namespace Ombi.Controllers.V1
{
if (emby.Enable)
{
var client = await _embyApi.CreateClient();
foreach (var server in emby.Servers)
{
var users = await _embyApi.GetUsers(server.FullUri, server.ApiKey);
var users = await client.GetUsers(server.FullUri, server.ApiKey);
var admin = users.FirstOrDefault(x => x.Policy.IsAdministrator);
server.AdministratorId = admin?.Id;
}

Loading…
Cancel
Save