mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-12 08:16:05 -07:00
Added the Movie Sender, Movies will be sent to Radarr now #865
This commit is contained in:
parent
2c4ef05af1
commit
4c797733ca
13 changed files with 223 additions and 59 deletions
|
@ -10,5 +10,6 @@ namespace Ombi.Api.Radarr
|
||||||
Task<List<RadarrProfile>> GetProfiles(string apiKey, string baseUrl);
|
Task<List<RadarrProfile>> GetProfiles(string apiKey, string baseUrl);
|
||||||
Task<List<RadarrRootFolder>> GetRootFolders(string apiKey, string baseUrl);
|
Task<List<RadarrRootFolder>> GetRootFolders(string apiKey, string baseUrl);
|
||||||
Task<SystemStatus> SystemStatus(string apiKey, string baseUrl);
|
Task<SystemStatus> SystemStatus(string apiKey, string baseUrl);
|
||||||
|
Task<RadarrAddMovieResponse> AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath,string apiKey, string baseUrl, bool searchNow = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
27
src/Ombi.Api.Radarr/Models/RadarrAddMovie.cs
Normal file
27
src/Ombi.Api.Radarr/Models/RadarrAddMovie.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ombi.Api.Radarr.Models
|
||||||
|
{
|
||||||
|
public class RadarrAddMovieResponse
|
||||||
|
{
|
||||||
|
|
||||||
|
public RadarrAddMovieResponse()
|
||||||
|
{
|
||||||
|
images = new List<string>();
|
||||||
|
}
|
||||||
|
public RadarrError Error { get; set; }
|
||||||
|
public RadarrAddOptions addOptions { get; set; }
|
||||||
|
public string title { get; set; }
|
||||||
|
public string rootFolderPath { get; set; }
|
||||||
|
public int qualityProfileId { get; set; }
|
||||||
|
public bool monitored { get; set; }
|
||||||
|
public int tmdbId { get; set; }
|
||||||
|
public List<string> images { get; set; }
|
||||||
|
public string cleanTitle { get; set; }
|
||||||
|
public string imdbId { get; set; }
|
||||||
|
public string titleSlug { get; set; }
|
||||||
|
public int id { get; set; }
|
||||||
|
public int year { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
9
src/Ombi.Api.Radarr/Models/RadarrAddOptions.cs
Normal file
9
src/Ombi.Api.Radarr/Models/RadarrAddOptions.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Ombi.Api.Radarr.Models
|
||||||
|
{
|
||||||
|
public class RadarrAddOptions
|
||||||
|
{
|
||||||
|
public bool ignoreEpisodesWithFiles { get; set; }
|
||||||
|
public bool ignoreEpisodesWithoutFiles { get; set; }
|
||||||
|
public bool searchForMovie { get; set; }
|
||||||
|
}
|
||||||
|
}
|
21
src/Ombi.Api.Radarr/Models/RadarrError.cs
Normal file
21
src/Ombi.Api.Radarr/Models/RadarrError.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
namespace Ombi.Api.Radarr.Models
|
||||||
|
{
|
||||||
|
public class RadarrError
|
||||||
|
{
|
||||||
|
public string message { get; set; }
|
||||||
|
public string description { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RadarrErrorResponse
|
||||||
|
{
|
||||||
|
public string propertyName { get; set; }
|
||||||
|
public string errorMessage { get; set; }
|
||||||
|
public object attemptedValue { get; set; }
|
||||||
|
public FormattedMessagePlaceholderValues formattedMessagePlaceholderValues { get; set; }
|
||||||
|
}
|
||||||
|
public class FormattedMessagePlaceholderValues
|
||||||
|
{
|
||||||
|
public string propertyName { get; set; }
|
||||||
|
public object propertyValue { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
|
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
|
||||||
|
<ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
|
@ -1,9 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Ombi.Api.Radarr.Models;
|
using Ombi.Api.Radarr.Models;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
|
||||||
namespace Ombi.Api.Radarr
|
namespace Ombi.Api.Radarr
|
||||||
{
|
{
|
||||||
|
@ -50,6 +53,56 @@ namespace Ombi.Api.Radarr
|
||||||
return await Api.Request<List<MovieResponse>>(request);
|
return await Api.Request<List<MovieResponse>>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<RadarrAddMovieResponse> AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath, string apiKey, string baseUrl, bool searchNow = false)
|
||||||
|
{
|
||||||
|
var request = new Request(baseUrl, "/api/movie", HttpMethod.Post);
|
||||||
|
|
||||||
|
var options = new RadarrAddMovieResponse
|
||||||
|
{
|
||||||
|
title = title,
|
||||||
|
tmdbId = tmdbId,
|
||||||
|
qualityProfileId = qualityId,
|
||||||
|
rootFolderPath = rootPath,
|
||||||
|
titleSlug = title,
|
||||||
|
monitored = true,
|
||||||
|
year = year
|
||||||
|
};
|
||||||
|
|
||||||
|
if (searchNow)
|
||||||
|
{
|
||||||
|
options.addOptions = new RadarrAddOptions
|
||||||
|
{
|
||||||
|
searchForMovie = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
request.AddHeader("X-Api-Key", apiKey);
|
||||||
|
request.AddJsonBody(options);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await Api.Request(request);
|
||||||
|
if (response.Contains("\"message\":"))
|
||||||
|
{
|
||||||
|
var error = JsonConvert.DeserializeObject<RadarrError>(response);
|
||||||
|
return new RadarrAddMovieResponse { Error = error };
|
||||||
|
}
|
||||||
|
if (response.Contains("\"errorMessage\":"))
|
||||||
|
{
|
||||||
|
var error = JsonConvert.DeserializeObject<List<RadarrErrorResponse>>(response).FirstOrDefault();
|
||||||
|
return new RadarrAddMovieResponse { Error = new RadarrError { message = error?.errorMessage } };
|
||||||
|
}
|
||||||
|
return JsonConvert.DeserializeObject<RadarrAddMovieResponse>(response);
|
||||||
|
}
|
||||||
|
catch (JsonSerializationException jse)
|
||||||
|
{
|
||||||
|
Logger.LogError(LoggingEvents.RadarrApiException,jse, "Error When adding movie to Radarr");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the required headers and also the authorization header
|
/// Adds the required headers and also the authorization header
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -60,6 +60,38 @@ namespace Ombi.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<string> Request(Request request)
|
||||||
|
{
|
||||||
|
using (var httpClient = new HttpClient())
|
||||||
|
{
|
||||||
|
using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri))
|
||||||
|
{
|
||||||
|
// Add the Json Body
|
||||||
|
if (request.JsonBody != null)
|
||||||
|
{
|
||||||
|
httpRequestMessage.Content = new JsonContent(request.JsonBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add headers
|
||||||
|
foreach (var header in request.Headers)
|
||||||
|
{
|
||||||
|
httpRequestMessage.Headers.Add(header.Key, header.Value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
using (var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage))
|
||||||
|
{
|
||||||
|
if (!httpResponseMessage.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
// Logging
|
||||||
|
}
|
||||||
|
// do something with the response
|
||||||
|
var data = httpResponseMessage.Content;
|
||||||
|
|
||||||
|
|
||||||
|
return await data.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Ombi.Core.Engine.Interfaces;
|
using Ombi.Core.Engine.Interfaces;
|
||||||
|
|
||||||
namespace Ombi.Core.Engine
|
namespace Ombi.Core.Engine
|
||||||
|
@ -21,14 +22,18 @@ namespace Ombi.Core.Engine
|
||||||
public class MovieRequestEngine : BaseMediaEngine, IMovieRequestEngine
|
public class MovieRequestEngine : BaseMediaEngine, IMovieRequestEngine
|
||||||
{
|
{
|
||||||
public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user,
|
public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user,
|
||||||
INotificationService notificationService, IRuleEvaluator r) : base(user, requestService, r)
|
INotificationService notificationService, IRuleEvaluator r, IMovieSender sender, ILogger<MovieRequestEngine> log) : base(user, requestService, r)
|
||||||
{
|
{
|
||||||
MovieApi = movieApi;
|
MovieApi = movieApi;
|
||||||
NotificationService = notificationService;
|
NotificationService = notificationService;
|
||||||
|
Sender = sender;
|
||||||
|
Logger = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IMovieDbApi MovieApi { get; }
|
private IMovieDbApi MovieApi { get; }
|
||||||
private INotificationService NotificationService { get; }
|
private INotificationService NotificationService { get; }
|
||||||
|
private IMovieSender Sender { get; }
|
||||||
|
private ILogger<MovieRequestEngine> Logger { get; }
|
||||||
|
|
||||||
public async Task<RequestEngineResult> RequestMovie(SearchMovieViewModel model)
|
public async Task<RequestEngineResult> RequestMovie(SearchMovieViewModel model)
|
||||||
{
|
{
|
||||||
|
@ -91,7 +96,7 @@ namespace Ombi.Core.Engine
|
||||||
Status = movieInfo.Status,
|
Status = movieInfo.Status,
|
||||||
RequestedDate = DateTime.UtcNow,
|
RequestedDate = DateTime.UtcNow,
|
||||||
Approved = false,
|
Approved = false,
|
||||||
RequestedUsers = new List<string> {Username},
|
RequestedUsers = new List<string> { Username },
|
||||||
Issues = IssueState.None
|
Issues = IssueState.None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,32 +111,22 @@ namespace Ombi.Core.Engine
|
||||||
|
|
||||||
if (requestModel.Approved) // The rules have auto approved this
|
if (requestModel.Approved) // The rules have auto approved this
|
||||||
{
|
{
|
||||||
// var result = await MovieSender.Send(model);
|
var result = await Sender.Send(requestModel);
|
||||||
// if (result.Result)
|
if (result.Success && result.MovieSent)
|
||||||
// {
|
{
|
||||||
// return await AddRequest(model, settings,
|
return await AddMovieRequest(requestModel, /*settings,*/
|
||||||
// $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
|
$"{fullMovieName} has been successfully added!");
|
||||||
// }
|
}
|
||||||
// if (result.Error)
|
if (!result.Success)
|
||||||
|
{
|
||||||
// {
|
Logger.LogWarning("Tried auto sending movie but failed. Message: {0}", result.Message);
|
||||||
// return
|
return new RequestEngineResult
|
||||||
// Response.AsJson(new JsonResponseModel
|
{
|
||||||
// {
|
Message = result.Message,
|
||||||
// Message = "Could not add movie, please contact your administrator",
|
ErrorMessage = result.Message,
|
||||||
// Result = false
|
RequestAdded = false
|
||||||
// });
|
};
|
||||||
// }
|
}
|
||||||
// if (!result.MovieSendingEnabled)
|
|
||||||
// {
|
|
||||||
// return await AddRequest(model, settings, $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return Response.AsJson(new JsonResponseModel
|
|
||||||
// {
|
|
||||||
// Result = false,
|
|
||||||
// Message = Resources.UI.Search_CouchPotatoError
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return await AddMovieRequest(requestModel, /*settings,*/
|
return await AddMovieRequest(requestModel, /*settings,*/
|
||||||
|
@ -261,7 +256,7 @@ namespace Ombi.Core.Engine
|
||||||
// await RequestLimitRepo.UpdateAsync(usersLimit);
|
// await RequestLimitRepo.UpdateAsync(usersLimit);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
return new RequestEngineResult {RequestAdded = true};
|
return new RequestEngineResult { RequestAdded = true, Message = message };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<MovieRequestModel>> GetApprovedRequests()
|
public async Task<IEnumerable<MovieRequestModel>> GetApprovedRequests()
|
||||||
|
|
10
src/Ombi.Core/IMovieSender.cs
Normal file
10
src/Ombi.Core/IMovieSender.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Core.Models.Requests.Movie;
|
||||||
|
|
||||||
|
namespace Ombi.Core
|
||||||
|
{
|
||||||
|
public interface IMovieSender
|
||||||
|
{
|
||||||
|
Task<MovieSenderResult> Send(MovieRequestModel model, string qualityId = "");
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,17 +2,25 @@
|
||||||
using Ombi.Core.Settings;
|
using Ombi.Core.Settings;
|
||||||
using Ombi.Settings.Settings.Models.External;
|
using Ombi.Settings.Settings.Models.External;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Ombi.Api.Radarr;
|
||||||
|
using Ombi.Core.Models.Requests;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
|
||||||
namespace Ombi.Core
|
namespace Ombi.Core
|
||||||
{
|
{
|
||||||
public class MovieSender
|
public class MovieSender : IMovieSender
|
||||||
{
|
{
|
||||||
public MovieSender(ISettingsService<RadarrSettings> radarrSettings)
|
public MovieSender(ISettingsService<RadarrSettings> radarrSettings, IRadarrApi api, ILogger<MovieSender> log)
|
||||||
{
|
{
|
||||||
RadarrSettings = radarrSettings;
|
RadarrSettings = radarrSettings;
|
||||||
|
RadarrApi = api;
|
||||||
|
Log = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ISettingsService<RadarrSettings> RadarrSettings { get; }
|
private ISettingsService<RadarrSettings> RadarrSettings { get; }
|
||||||
|
private IRadarrApi RadarrApi { get; }
|
||||||
|
private ILogger<MovieSender> Log { get; }
|
||||||
|
|
||||||
public async Task<MovieSenderResult> Send(MovieRequestModel model, string qualityId = "")
|
public async Task<MovieSenderResult> Send(MovieRequestModel model, string qualityId = "")
|
||||||
{
|
{
|
||||||
|
@ -32,7 +40,7 @@ namespace Ombi.Core
|
||||||
|
|
||||||
if (radarrSettings.Enabled)
|
if (radarrSettings.Enabled)
|
||||||
{
|
{
|
||||||
//return SendToRadarr(model, radarrSettings, qualityId);
|
return await SendToRadarr(model, radarrSettings, qualityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MovieSenderResult
|
return new MovieSenderResult
|
||||||
|
@ -43,32 +51,33 @@ namespace Ombi.Core
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// var qualityProfile = 0;
|
private async Task<MovieSenderResult> SendToRadarr(BaseRequestModel model, RadarrSettings settings, string qualityId)
|
||||||
//{
|
{
|
||||||
//private MovieSenderResult SendToRadarr(MovieRequestModel model, RadarrSettings settings, string qualityId)
|
var qualityProfile = 0;
|
||||||
// if (!string.IsNullOrEmpty(qualityId)) // try to parse the passed in quality, otherwise use the settings default quality
|
if (!string.IsNullOrEmpty(qualityId)) // try to parse the passed in quality, otherwise use the settings default quality
|
||||||
// {
|
{
|
||||||
// int.TryParse(qualityId, out qualityProfile);
|
int.TryParse(qualityId, out qualityProfile);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if (qualityProfile <= 0)
|
if (qualityProfile <= 0)
|
||||||
// {
|
{
|
||||||
// int.TryParse(settings.QualityProfile, out qualityProfile);
|
int.TryParse(settings.DefaultQualityProfile, out qualityProfile);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// var rootFolderPath = model.RootFolderSelected <= 0 ? settings.FullRootPath : GetRootPath(model.RootFolderSelected, settings);
|
//var rootFolderPath = model.RootFolderSelected <= 0 ? settings.FullRootPath : GetRootPath(model.RootFolderSelected, settings);
|
||||||
// var result = RadarrApi.AddMovie(model.ProviderId, model.Title, model.ReleaseDate.Year, qualityProfile, rootFolderPath, settings.ApiKey, settings.FullUri, true);
|
var rootFolderPath = settings.DefaultRootPath; // TODO Allow changing in the UI
|
||||||
|
var result = await RadarrApi.AddMovie(model.ProviderId, model.Title, model.ReleaseDate.Year, qualityProfile, rootFolderPath, settings.ApiKey, settings.FullUri, true);
|
||||||
|
|
||||||
// if (!string.IsNullOrEmpty(result.Error?.message))
|
if (!string.IsNullOrEmpty(result.Error?.message))
|
||||||
// {
|
{
|
||||||
// Log.Error(result.Error.message);
|
Log.LogError(LoggingEvents.RadarrCacherException,result.Error.message);
|
||||||
// return new MovieSenderResult { Result = false, Error = true, MovieSendingEnabled = true };
|
return new MovieSenderResult { Success = false, Message = result.Error.message, MovieSent = false };
|
||||||
// }
|
}
|
||||||
// if (!string.IsNullOrEmpty(result.title))
|
if (!string.IsNullOrEmpty(result.title))
|
||||||
// {
|
{
|
||||||
// return new MovieSenderResult { Result = true, MovieSendingEnabled = true };
|
return new MovieSenderResult { Success = true, MovieSent = false };
|
||||||
// }
|
}
|
||||||
// return new MovieSenderResult { Result = false, MovieSendingEnabled = true };
|
return new MovieSenderResult { Success = true, MovieSent = false };
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -48,6 +48,7 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddTransient<ITvRequestEngine, TvRequestEngine>();
|
services.AddTransient<ITvRequestEngine, TvRequestEngine>();
|
||||||
services.AddTransient<ITvSearchEngine, TvSearchEngine>();
|
services.AddTransient<ITvSearchEngine, TvSearchEngine>();
|
||||||
services.AddSingleton<IRuleEvaluator, RuleEvaluator>();
|
services.AddSingleton<IRuleEvaluator, RuleEvaluator>();
|
||||||
|
services.AddSingleton<IMovieSender, MovieSender>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterApi(this IServiceCollection services)
|
public static void RegisterApi(this IServiceCollection services)
|
||||||
|
|
|
@ -5,7 +5,9 @@ namespace Ombi.Helpers
|
||||||
public class LoggingEvents
|
public class LoggingEvents
|
||||||
{
|
{
|
||||||
public static EventId ApiException => new EventId(1000);
|
public static EventId ApiException => new EventId(1000);
|
||||||
|
public static EventId RadarrApiException => new EventId(1001);
|
||||||
public static EventId CacherException => new EventId(2000);
|
public static EventId CacherException => new EventId(2000);
|
||||||
public static EventId RadarrCacherException => new EventId(2001);
|
public static EventId RadarrCacherException => new EventId(2001);
|
||||||
|
public static EventId MovieSender => new EventId(3000);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -78,8 +78,11 @@ namespace Ombi
|
||||||
|
|
||||||
services.AddHangfire(x =>
|
services.AddHangfire(x =>
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
x.UseMemoryStorage(new MemoryStorageOptions());
|
||||||
|
#else
|
||||||
x.UseSQLiteStorage("Data Source=Ombi.db;");
|
x.UseSQLiteStorage("Data Source=Ombi.db;");
|
||||||
//x.UseMemoryStorage(new MemoryStorageOptions());
|
#endif
|
||||||
x.UseActivator(new IoCJobActivator(services.BuildServiceProvider()));
|
x.UseActivator(new IoCJobActivator(services.BuildServiceProvider()));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue