Skip to content

Commit

Permalink
Fixed #3245
Browse files Browse the repository at this point in the history
  • Loading branch information
tidusjar committed Mar 24, 2020
1 parent 82f4107 commit 4340dc4
Show file tree
Hide file tree
Showing 15 changed files with 322 additions and 73 deletions.
41 changes: 41 additions & 0 deletions src/Ombi.Api.Emby/EmbyApiFactory.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
33 changes: 33 additions & 0 deletions src/Ombi.Api.Emby/IBaseEmbyApi.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
30 changes: 3 additions & 27 deletions src/Ombi.Api.Emby/IEmbyApi.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
180 changes: 180 additions & 0 deletions src/Ombi.Api.Emby/JellyfinApi.cs
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
12 changes: 7 additions & 5 deletions src/Ombi.Core/Authentication/OmbiUserManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public OmbiUserManager(IUserStore<OmbiUser> store, IOptions<IdentityOptions> opt
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;
Expand All @@ -59,7 +59,7 @@ public OmbiUserManager(IUserStore<OmbiUser> store, IOptions<IdentityOptions> opt
}

private readonly IPlexApi _plexApi;
private readonly IEmbyApi _embyApi;
private readonly IEmbyApiFactory _embyApi;
private readonly ISettingsService<EmbySettings> _embySettings;
private readonly ISettingsService<AuthenticationSettings> _authSettings;

Expand Down Expand Up @@ -146,9 +146,12 @@ private async Task<bool> CheckPlexPasswordAsync(OmbiUser user, string password)
/// <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
Expand All @@ -165,12 +168,11 @@ private async Task<bool> CheckEmbyPasswordAsync(OmbiUser user, string password)
}
}

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;
Expand Down
2 changes: 2 additions & 0 deletions src/Ombi.DependencyInjection/IocExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ public static void RegisterApi(this IServiceCollection services)
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) {
Expand Down
7 changes: 4 additions & 3 deletions src/Ombi.HealthChecks/Checks/EmbyHealthCheck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,18 @@ public override async Task<HealthCheckResult> CheckHealthAsync(
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
Expand Down
Loading

0 comments on commit 4340dc4

Please sign in to comment.