mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-16 02:02:55 -07:00
Added the support for TV Series integrating with Sonarr
This commit is contained in:
parent
31615ff69c
commit
5dd9885885
15 changed files with 250 additions and 10 deletions
|
@ -34,5 +34,8 @@ namespace PlexRequests.Api.Interfaces
|
|||
public interface ISonarrApi
|
||||
{
|
||||
List<SonarrProfile> GetProfiles(string apiKey, Uri baseUrl);
|
||||
|
||||
SonarrAddSeries AddSeries(int tvdbId, string title, int qualityId, bool seasonFolders, string rootPath,
|
||||
bool episodes, string apiKey, Uri baseUrl);
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@
|
|||
<Compile Include="Plex\PlexSearch.cs" />
|
||||
<Compile Include="Plex\PlexUserRequest.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Sonarr\SonarrAddSeries.cs" />
|
||||
<Compile Include="Sonarr\SonarrProfile.cs" />
|
||||
<Compile Include="Tv\Authentication.cs" />
|
||||
<Compile Include="Tv\TvSearchResult.cs" />
|
||||
|
|
37
PlexRequests.Api.Models/Sonarr/SonarrAddSeries.cs
Normal file
37
PlexRequests.Api.Models/Sonarr/SonarrAddSeries.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PlexRequests.Api.Models.Sonarr
|
||||
{
|
||||
public class Season
|
||||
{
|
||||
public int seasonNumber { get; set; }
|
||||
public bool monitored { get; set; }
|
||||
}
|
||||
|
||||
public class SonarrAddSeries
|
||||
{
|
||||
public AddOptions addOptions { get; set; }
|
||||
public string title { get; set; }
|
||||
public List<Season> seasons { get; set; }
|
||||
public string rootFolderPath { get; set; }
|
||||
public int qualityProfileId { get; set; }
|
||||
public bool seasonFolder { get; set; }
|
||||
public bool monitored { get; set; }
|
||||
public int tvdbId { get; set; }
|
||||
public int tvRageId { get; set; }
|
||||
public string cleanTitle { get; set; }
|
||||
public string imdbId { get; set; }
|
||||
public string titleSlug { get; set; }
|
||||
public int id { get; set; }
|
||||
}
|
||||
|
||||
public class AddOptions
|
||||
{
|
||||
public bool ignoreEpisodesWithFiles { get; set; }
|
||||
public bool ignoreEpisodesWithoutFiles { get; set; }
|
||||
public bool searchForMissingEpisodes { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
37
PlexRequests.Api/MockApiData.Designer.cs
generated
37
PlexRequests.Api/MockApiData.Designer.cs
generated
|
@ -60,6 +60,43 @@ namespace PlexRequests.Api {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {
|
||||
/// "title": "Archer (2009)",
|
||||
/// "seasons": [
|
||||
/// {
|
||||
/// "seasonNumber": 5,
|
||||
/// "monitored": true
|
||||
/// },
|
||||
/// {
|
||||
/// "seasonNumber": 4,
|
||||
/// "monitored": true
|
||||
/// },
|
||||
/// {
|
||||
/// "seasonNumber": 3,
|
||||
/// "monitored": true
|
||||
/// },
|
||||
/// {
|
||||
/// "seasonNumber": 2,
|
||||
/// "monitored": true
|
||||
/// },
|
||||
/// {
|
||||
/// "seasonNumber": 1,
|
||||
/// "monitored": true
|
||||
/// },
|
||||
/// {
|
||||
/// "seasonNumber": 0,
|
||||
/// "monitored": false
|
||||
/// }
|
||||
/// ],
|
||||
/// "pat [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string Sonarr_AddSeriesResult {
|
||||
get {
|
||||
return ResourceManager.GetString("Sonarr_AddSeriesResult", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to [
|
||||
/// {
|
||||
|
|
|
@ -117,6 +117,47 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Sonarr_AddSeriesResult" xml:space="preserve">
|
||||
<value>{
|
||||
"title": "Archer (2009)",
|
||||
"seasons": [
|
||||
{
|
||||
"seasonNumber": 5,
|
||||
"monitored": true
|
||||
},
|
||||
{
|
||||
"seasonNumber": 4,
|
||||
"monitored": true
|
||||
},
|
||||
{
|
||||
"seasonNumber": 3,
|
||||
"monitored": true
|
||||
},
|
||||
{
|
||||
"seasonNumber": 2,
|
||||
"monitored": true
|
||||
},
|
||||
{
|
||||
"seasonNumber": 1,
|
||||
"monitored": true
|
||||
},
|
||||
{
|
||||
"seasonNumber": 0,
|
||||
"monitored": false
|
||||
}
|
||||
],
|
||||
"path": "T:\\Archer (2009)",
|
||||
"qualityProfileId": 1,
|
||||
"seasonFolder": true,
|
||||
"monitored": true,
|
||||
"tvdbId": 110381,
|
||||
"tvRageId": 23354,
|
||||
"cleanTitle": "archer2009",
|
||||
"imdbId": "tt1486217",
|
||||
"titleSlug": "archer-2009",
|
||||
"id": 1
|
||||
}</value>
|
||||
</data>
|
||||
<data name="Sonarr_Profiles" xml:space="preserve">
|
||||
<value>[
|
||||
{
|
||||
|
|
|
@ -42,5 +42,13 @@ namespace PlexRequests.Api.Mocks
|
|||
var obj = JsonConvert.DeserializeObject<List<SonarrProfile>>(json);
|
||||
return obj;
|
||||
}
|
||||
|
||||
public SonarrAddSeries AddSeries(int tvdbId, string title, int qualityId, bool seasonFolders, string rootPath, bool episodes,
|
||||
string apiKey, Uri baseUrl)
|
||||
{
|
||||
var json = MockApiData.Sonarr_AddSeriesResult;
|
||||
var obj = JsonConvert.DeserializeObject<SonarrAddSeries>(json);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -53,5 +53,50 @@ namespace PlexRequests.Api
|
|||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public SonarrAddSeries AddSeries(int tvdbId, string title, int qualityId, bool seasonFolders, string rootPath, bool episodes, string apiKey, Uri baseUrl)
|
||||
{
|
||||
|
||||
var request = new RestRequest
|
||||
{
|
||||
Resource = "/api/Series?",
|
||||
Method = Method.POST
|
||||
};
|
||||
|
||||
var options = new SonarrAddSeries();
|
||||
if (episodes == true)
|
||||
{
|
||||
options.addOptions = new AddOptions
|
||||
{
|
||||
ignoreEpisodesWithFiles = true,
|
||||
ignoreEpisodesWithoutFiles = true,
|
||||
searchForMissingEpisodes = false
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
options.addOptions = new AddOptions
|
||||
{
|
||||
ignoreEpisodesWithFiles = false,
|
||||
searchForMissingEpisodes = true,
|
||||
ignoreEpisodesWithoutFiles = false
|
||||
};
|
||||
}
|
||||
options.seasonFolder = seasonFolders;
|
||||
options.title = title;
|
||||
options.qualityProfileId = qualityId;
|
||||
options.tvdbId = tvdbId;
|
||||
options.titleSlug = title;
|
||||
options.seasons = new List<Season>();
|
||||
options.rootFolderPath = rootPath;
|
||||
|
||||
|
||||
request.AddHeader("X-Api-Key", apiKey);
|
||||
request.AddJsonBody(options);
|
||||
|
||||
var obj = Api.ExecuteJson<SonarrAddSeries>(request, baseUrl);
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,6 +37,8 @@ namespace PlexRequests.Core.SettingModels
|
|||
public int Port { get; set; }
|
||||
public string ApiKey { get; set; }
|
||||
public string QualityProfile { get; set; }
|
||||
public bool SeasonFolders { get; set; }
|
||||
public string RootPath { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public Uri FullUri
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace PlexRequests.Store
|
|||
return false;
|
||||
}
|
||||
|
||||
public string DbFile = "RequestPlex.sqlite";
|
||||
public string DbFile = "PlexRequests.sqlite";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the database connection.
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace PlexRequests.Store
|
|||
public bool Available { get; set; }
|
||||
public IssueState Issues { get; set; }
|
||||
public string OtherMessage { get; set; }
|
||||
public bool LatestTv { get; set; }
|
||||
}
|
||||
|
||||
public enum RequestType
|
||||
|
|
|
@ -28,6 +28,7 @@ CREATE TABLE IF NOT EXISTS Requested
|
|||
ReleaseDate varchar(50) NOT NULL,
|
||||
Status varchar(50) NOT NULL,
|
||||
Approved INTEGER NOT NULL,
|
||||
LatestTv INTEGER NOT NULL,
|
||||
RequestedBy varchar(50),
|
||||
RequestedDate varchar(50) NOT NULL,
|
||||
Available INTEGER(50),
|
||||
|
|
|
@ -44,13 +44,16 @@ namespace PlexRequests.UI.Modules
|
|||
public class ApprovalModule : BaseModule
|
||||
{
|
||||
|
||||
public ApprovalModule(IRepository<RequestedModel> service, ISettingsService<CouchPotatoSettings> cpService, ICouchPotatoApi cpApi) : base("approval")
|
||||
public ApprovalModule(IRepository<RequestedModel> service, ISettingsService<CouchPotatoSettings> cpService, ICouchPotatoApi cpApi, ISonarrApi sonarrApi,
|
||||
ISettingsService<SonarrSettings> sonarrSettings) : base("approval")
|
||||
{
|
||||
this.RequiresAuthentication();
|
||||
|
||||
Service = service;
|
||||
CpService = cpService;
|
||||
CpApi = cpApi;
|
||||
SonarrApi = sonarrApi;
|
||||
SonarrSettings = sonarrSettings;
|
||||
|
||||
Post["/approve"] = parameters => Approve((int)Request.Form.requestid);
|
||||
Post["/approveall"] = x => ApproveAll();
|
||||
|
@ -59,7 +62,9 @@ namespace PlexRequests.UI.Modules
|
|||
private IRepository<RequestedModel> Service { get; set; }
|
||||
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
private ISettingsService<SonarrSettings> SonarrSettings { get; set; }
|
||||
private ISettingsService<CouchPotatoSettings> CpService { get; }
|
||||
private ISonarrApi SonarrApi { get; set; }
|
||||
private ICouchPotatoApi CpApi { get; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -95,8 +100,21 @@ namespace PlexRequests.UI.Modules
|
|||
|
||||
private Response RequestTvAndUpdateStatus(RequestedModel request)
|
||||
{
|
||||
// TODO
|
||||
return Response.AsJson(new JsonResponseModel());
|
||||
var sonarrSettings = SonarrSettings.GetSettings();
|
||||
int qualityProfile;
|
||||
int.TryParse(sonarrSettings.QualityProfile, out qualityProfile);
|
||||
var result = SonarrApi.AddSeries(request.ProviderId, request.Title, qualityProfile,
|
||||
sonarrSettings.SeasonFolders, sonarrSettings.RootPath, request.LatestTv, sonarrSettings.ApiKey,
|
||||
sonarrSettings.FullUri);
|
||||
|
||||
if (!string.IsNullOrEmpty(result.title))
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false, Message = "Could not add the series to Sonarr"
|
||||
});
|
||||
}
|
||||
|
||||
private Response RequestMovieAndUpdateStatus(RequestedModel request)
|
||||
|
|
|
@ -32,6 +32,7 @@ using Nancy.Responses.Negotiation;
|
|||
using NLog;
|
||||
|
||||
using PlexRequests.Api;
|
||||
using PlexRequests.Api.Interfaces;
|
||||
using PlexRequests.Core;
|
||||
using PlexRequests.Core.SettingModels;
|
||||
using PlexRequests.Helpers;
|
||||
|
@ -46,7 +47,7 @@ namespace PlexRequests.UI.Modules
|
|||
{
|
||||
public SearchModule(ICacheProvider cache, ISettingsService<CouchPotatoSettings> cpSettings,
|
||||
ISettingsService<PlexRequestSettings> prSettings, IAvailabilityChecker checker,
|
||||
IRequestService request) : base("search")
|
||||
IRequestService request, ISonarrApi sonarrApi, ISettingsService<SonarrSettings> sonarrSettings) : base("search")
|
||||
{
|
||||
CpService = cpSettings;
|
||||
PrService = prSettings;
|
||||
|
@ -55,6 +56,8 @@ namespace PlexRequests.UI.Modules
|
|||
Cache = cache;
|
||||
Checker = checker;
|
||||
RequestService = request;
|
||||
SonarrApi = sonarrApi;
|
||||
SonarrService = sonarrSettings;
|
||||
|
||||
Get["/"] = parameters => RequestLoad();
|
||||
|
||||
|
@ -68,11 +71,13 @@ namespace PlexRequests.UI.Modules
|
|||
Post["request/tv"] = parameters => RequestTvShow((int)Request.Form.tvId, (bool)Request.Form.latest);
|
||||
}
|
||||
private TheMovieDbApi MovieApi { get; }
|
||||
private ISonarrApi SonarrApi { get; }
|
||||
private TheTvDbApi TvApi { get; }
|
||||
private IRequestService RequestService { get; }
|
||||
private ICacheProvider Cache { get; }
|
||||
private ISettingsService<CouchPotatoSettings> CpService { get; }
|
||||
private ISettingsService<PlexRequestSettings> PrService { get; }
|
||||
private ISettingsService<SonarrSettings> SonarrService { get; }
|
||||
private IAvailabilityChecker Checker { get; }
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
private string AuthToken => Cache.GetOrSet(CacheKeys.TvDbToken, TvApi.Authenticate, 50);
|
||||
|
@ -257,10 +262,26 @@ namespace PlexRequests.UI.Modules
|
|||
RequestedDate = DateTime.Now,
|
||||
Approved = false,
|
||||
RequestedBy = Session[SessionKeys.UsernameKey].ToString(),
|
||||
Issues = IssueState.None
|
||||
Issues = IssueState.None,
|
||||
LatestTv = latest
|
||||
};
|
||||
|
||||
RequestService.AddRequest(showId, model);
|
||||
|
||||
var settings = PrService.GetSettings();
|
||||
if (!settings.RequireApproval)
|
||||
{
|
||||
var sonarrSettings = SonarrService.GetSettings();
|
||||
int qualityProfile;
|
||||
int.TryParse(sonarrSettings.QualityProfile, out qualityProfile);
|
||||
var result = SonarrApi.AddSeries(model.ProviderId, model.Title, qualityProfile,
|
||||
sonarrSettings.SeasonFolders, sonarrSettings.RootPath, model.LatestTv, sonarrSettings.ApiKey,
|
||||
sonarrSettings.FullUri);
|
||||
Log.Info("Added series {0} to Sonarr, Result: {1}", model.Title, result);
|
||||
Log.Trace("Model sent to Sonarr: ");
|
||||
Log.Trace(model.DumpJson());
|
||||
}
|
||||
|
||||
return Response.AsJson(new { Result = true });
|
||||
}
|
||||
private string GetAuthToken(TheTvDbApi api)
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="">
|
||||
<button id="requestToken" class="btn btn-primary-outline-outline">Request Token <i class="fa fa-key"></i></button>
|
||||
<button id="requestToken" class="btn btn-primary-outline">Request Token <i class="fa fa-key"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
int port;
|
||||
if (Model.Port == 0)
|
||||
{
|
||||
port = 80;
|
||||
port = 8989;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -50,6 +50,31 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="RootPath" class="control-label">Root save directory for TV shows</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom " id="RootPath" name="RootPath" value="@Model.RootPath">
|
||||
<label>Enter the root folder where tv shows are saved. For example <strong>C:\Media\TV</strong>.</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
@if (Model.SeasonFolders)
|
||||
{
|
||||
<input type="checkbox" id="SeasonFolders" name="SeasonFolders" checked="checked">
|
||||
}
|
||||
else
|
||||
{
|
||||
<input type="checkbox" id="SeasonFolders" name="SeasonFolders">
|
||||
}
|
||||
<label>Enable season folders</label>
|
||||
<label>Enabled Season Folders to organize seasons into individual folders within a show.</label>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<button id="save" type="submit" class="btn btn-primary-outline ">Submit</button>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue