mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-16 02:02:55 -07:00
Did the frontend settings for Sonarr to add V3. !wip #2359
This commit is contained in:
parent
3fe0e2de19
commit
a69637a3fb
10 changed files with 174 additions and 64 deletions
|
@ -18,13 +18,13 @@ namespace Ombi.Core.Tests.Rule.Search
|
|||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
ContextMock = new Mock<IRepository<CouchPotatoCache>>();
|
||||
ContextMock = new Mock<IExternalRepository<CouchPotatoCache>>();
|
||||
Rule = new CouchPotatoCacheRule(ContextMock.Object);
|
||||
|
||||
}
|
||||
|
||||
private CouchPotatoCacheRule Rule { get; set; }
|
||||
private Mock<IRepository<CouchPotatoCache>> ContextMock { get; set; }
|
||||
private Mock<IExternalRepository<CouchPotatoCache>> ContextMock { get; set; }
|
||||
|
||||
[Test]
|
||||
public async Task Should_ReturnApproved_WhenMovieIsInCouchPotato()
|
||||
|
|
|
@ -15,13 +15,13 @@ namespace Ombi.Core.Tests.Rule.Search
|
|||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
ContextMock = new Mock<IRepository<RadarrCache>>();
|
||||
ContextMock = new Mock<IExternalRepository<RadarrCache>>();
|
||||
Rule = new RadarrCacheRule(ContextMock.Object);
|
||||
|
||||
}
|
||||
|
||||
private RadarrCacheRule Rule { get; set; }
|
||||
private Mock<IRepository<RadarrCache>> ContextMock { get; set; }
|
||||
private Mock<IExternalRepository<RadarrCache>> ContextMock { get; set; }
|
||||
|
||||
[Test]
|
||||
public async Task Should_ReturnApproved_WhenMovieIsInRadarr()
|
||||
|
|
|
@ -21,11 +21,12 @@ namespace Ombi.Core.Senders
|
|||
{
|
||||
public class TvSender : ITvSender
|
||||
{
|
||||
public TvSender(ISonarrApi sonarrApi, ILogger<TvSender> log, ISettingsService<SonarrSettings> sonarrSettings,
|
||||
public TvSender(ISonarrApi sonarrApi, ISonarrV3Api sonarrV3Api, ILogger<TvSender> log, ISettingsService<SonarrSettings> sonarrSettings,
|
||||
ISettingsService<DogNzbSettings> dog, IDogNzbApi dogApi, ISettingsService<SickRageSettings> srSettings,
|
||||
ISickRageApi srApi, IRepository<UserQualityProfiles> userProfiles)
|
||||
{
|
||||
SonarrApi = sonarrApi;
|
||||
SonarrV3Api = sonarrV3Api;
|
||||
Logger = log;
|
||||
SonarrSettings = sonarrSettings;
|
||||
DogNzbSettings = dog;
|
||||
|
@ -36,6 +37,7 @@ namespace Ombi.Core.Senders
|
|||
}
|
||||
|
||||
private ISonarrApi SonarrApi { get; }
|
||||
private ISonarrV3Api SonarrV3Api { get; }
|
||||
private IDogNzbApi DogNzbApi { get; }
|
||||
private ISickRageApi SickRageApi { get; }
|
||||
private ILogger<TvSender> Logger { get; }
|
||||
|
@ -175,6 +177,16 @@ namespace Ombi.Core.Senders
|
|||
qualityToUse = model.ParentRequest.QualityOverride.Value;
|
||||
}
|
||||
|
||||
|
||||
// Are we using v3 sonarr?
|
||||
var sonarrV3 = s.V3;
|
||||
var languageProfileId = 0;
|
||||
if (sonarrV3)
|
||||
{
|
||||
languageProfileId = s.LanguageProfile;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
// Does the series actually exist?
|
||||
|
|
|
@ -19,5 +19,6 @@
|
|||
public string RootPathAnime { get; set; }
|
||||
public bool AddOnly { get; set; }
|
||||
public bool V3 { get; set; }
|
||||
public int LanguageProfile { get; set; }
|
||||
}
|
||||
}
|
|
@ -72,6 +72,8 @@ export interface ISonarrSettings extends IExternalSettings {
|
|||
rootPathAnime: string;
|
||||
fullRootPath: string;
|
||||
addOnly: boolean;
|
||||
v3: boolean;
|
||||
languageProfile: number;
|
||||
}
|
||||
|
||||
export interface IRadarrSettings extends IExternalSettings {
|
||||
|
|
|
@ -7,3 +7,8 @@ export interface ISonarrProfile {
|
|||
name: string;
|
||||
id: number;
|
||||
}
|
||||
|
||||
export interface ILanguageProfiles {
|
||||
name: string;
|
||||
id: number;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import { HttpClient } from "@angular/common/http";
|
|||
import { Observable } from "rxjs";
|
||||
|
||||
import { ISonarrSettings } from "../../interfaces";
|
||||
import { ISonarrProfile, ISonarrRootFolder } from "../../interfaces";
|
||||
import { ILanguageProfiles, ISonarrProfile, ISonarrRootFolder } from "../../interfaces";
|
||||
import { ServiceHelpers } from "../service.helpers";
|
||||
|
||||
@Injectable()
|
||||
|
@ -27,4 +27,8 @@ export class SonarrService extends ServiceHelpers {
|
|||
public getQualityProfilesWithoutSettings(): Observable<ISonarrProfile[]> {
|
||||
return this.http.get<ISonarrProfile[]>(`${this.url}/Profiles/`, {headers: this.headers});
|
||||
}
|
||||
|
||||
public getV3LanguageProfiles(settings: ISonarrSettings): Observable<ILanguageProfiles[]> {
|
||||
return this.http.post<ILanguageProfiles[]>(`${this.url}/v3/languageprofiles/`, JSON.stringify(settings), {headers: this.headers});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
<settings-menu></settings-menu>
|
||||
<settings-menu></settings-menu>
|
||||
<div *ngIf="form">
|
||||
<fieldset>
|
||||
<legend>Sonarr Settings</legend>
|
||||
|
@ -10,33 +9,47 @@
|
|||
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)" style="padding-top:5%;">
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" id="enable" formControlName="enabled">
|
||||
<label for="enable">Enable</label>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" id="enable" formControlName="enabled">
|
||||
<label for="enable">Enable</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" id="v3" formControlName="v3">
|
||||
<label for="v3">Sonarr V3</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="Ip" class="control-label">Sonarr Hostname or IP</label>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " formControlName="ip" id="Ip" name="Ip" placeholder="localhost" [ngClass]="{'form-error': form.get('ip').hasError('required')}">
|
||||
<small *ngIf="form.get('ip').hasError('required')" class="error-text">The IP/Hostname is required</small>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " formControlName="ip" id="Ip" name="Ip"
|
||||
placeholder="localhost" [ngClass]="{'form-error': form.get('ip').hasError('required')}">
|
||||
<small *ngIf="form.get('ip').hasError('required')" class="error-text">The IP/Hostname is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="portNumber" class="control-label">Port</label>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " [ngClass]="{'form-error': form.get('port').hasError('required')}" formControlName="port" id="portNumber" name="Port" placeholder="Port Number">
|
||||
<small *ngIf="form.get('port').hasError('required')" class="error-text">The Port is required</small>
|
||||
<input type="text" class="form-control form-control-custom " [ngClass]="{'form-error': form.get('port').hasError('required')}"
|
||||
formControlName="port" id="portNumber" name="Port" placeholder="Port Number">
|
||||
<small *ngIf="form.get('port').hasError('required')" class="error-text">The Port is required</small>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="ApiKey" class="control-label">Sonarr API Key</label>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " [ngClass]="{'form-error': form.get('apiKey').hasError('required')}" formControlName="apiKey" id="ApiKey" name="ApiKey">
|
||||
<small *ngIf="form.get('apiKey').hasError('required')" class="error-text">The API Key is required</small>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " [ngClass]="{'form-error': form.get('apiKey').hasError('required')}"
|
||||
formControlName="apiKey" id="ApiKey" name="ApiKey">
|
||||
<small *ngIf="form.get('apiKey').hasError('required')" class="error-text">The API Key is required</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
|
@ -48,63 +61,80 @@
|
|||
<div class="form-group">
|
||||
<label for="SubDir" class="control-label">Sonarr Base Url</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom" formControlName="subDir" id="SubDir" name="SubDir">
|
||||
<input type="text" class="form-control form-control-custom" formControlName="subDir" id="SubDir"
|
||||
name="SubDir">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<button type="button" (click)="getProfiles(form)" class="btn btn-primary-outline">Get Quality Profiles <span *ngIf="profilesRunning" class="fa fa-spinner fa-spin"></span></button>
|
||||
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="profiles" class="control-label">Quality Profiles</label>
|
||||
<div id="profiles">
|
||||
<select class="form-control form-control-custom col-md-5 form-half" [ngClass]="{'form-error': form.get('qualityProfile').hasError('required')}"
|
||||
id="select" formControlName="qualityProfile">
|
||||
<option *ngFor="let quality of qualities" value="{{quality.id}}">{{quality.name}}</option>
|
||||
</select>
|
||||
<button type="button" (click)="getProfiles(form)" class="btn btn-primary-outline col-md-4 col-md-push-1">
|
||||
Load Qualities <span *ngIf="profilesRunning" class="fa fa-spinner fa-spin"></span></button>
|
||||
<small *ngIf="form.get('qualityProfile').hasError('required')" class="error-text">A Default Quality
|
||||
Profile is required</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="select" class="control-label">Quality Profiles</label>
|
||||
<div id="profiles">
|
||||
<select class="form-control form-control-custom" [ngClass]="{'form-error': form.get('qualityProfile').hasError('required')}" id="select" formControlName="qualityProfile">
|
||||
<option *ngFor="let quality of qualities" value="{{quality.id}}" >{{quality.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<small *ngIf="form.get('qualityProfile').hasError('required')" class="error-text">A Default Quality Profile is required</small>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="select" class="control-label">Quality Profiles (Anime)</label>
|
||||
<div id="qualityProfileAnime">
|
||||
<select class="form-control form-control-custom" id="qualityProfileAnime" formControlName="qualityProfileAnime">
|
||||
<option *ngFor="let quality of qualities" value="{{quality.id}}" >{{quality.name}}</option>
|
||||
<select class="form-control form-control-custom col-md-5 form-half" id="qualityProfileAnime" formControlName="qualityProfileAnime">
|
||||
<option *ngFor="let quality of qualities" value="{{quality.id}}">{{quality.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<button type="button" (click)="getRootFolders(form)" class="btn btn-primary-outline">Get Root Folders <span *ngIf="rootFoldersRunning" class="fa fa-spinner fa-spin"></span></button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-group col-md-12">
|
||||
<label for="rootFolders" class="control-label">Default Root Folders</label>
|
||||
<div id="rootFolders">
|
||||
<select class="form-control form-control-custom" formControlName="rootPath" [ngClass]="{'form-error': form.get('rootPath').hasError('required')}">
|
||||
<select class="form-control form-control-custom col-md-5 form-half" formControlName="rootPath"
|
||||
[ngClass]="{'form-error': form.get('rootPath').hasError('required')}">
|
||||
<option *ngFor="let folder of rootFolders" value="{{folder.id}}">{{folder.path}}</option>
|
||||
</select>
|
||||
<button type="button" (click)="getRootFolders(form)" class="btn btn-primary-outline col-md-4 col-md-push-1">
|
||||
Load Folders <span *ngIf="rootFoldersRunning" class="fa fa-spinner fa-spin"></span></button>
|
||||
<small *ngIf="form.get('rootPath').hasError('required')" class="error-text">A Default Root Path
|
||||
is
|
||||
required</small>
|
||||
</div>
|
||||
<small *ngIf="form.get('rootPath').hasError('required')" class="error-text">A Default Root Path is required</small>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<label for="rootFoldersAnime" class="control-label">Default Root Folders (Anime)</label>
|
||||
<div id="rootFoldersAnime">
|
||||
<select class="form-control form-control-custom" formControlName="rootPathAnime">
|
||||
<select class="form-control form-control-custom col-md-5 form-half" formControlName="rootPathAnime">
|
||||
<option *ngFor="let folder of rootFoldersAnime" value="{{folder.id}}">{{folder.path}}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12" *ngIf="form.controls.v3.value">
|
||||
<label for="select" class="control-label">Language Profiles</label>
|
||||
<div id="langaugeProfile">
|
||||
<select formControlName="langaugeProfile" class="form-control form-control-custom col-md-5 form-half"
|
||||
id="select" [ngClass]="{'form-error': form.get('langaugeProfile').hasError('required')}">
|
||||
<option *ngFor="let lang of languageProfiles" value="{{lang.id}}">{{lang.name}}</option>
|
||||
</select>
|
||||
<button (click)="getLanguageProfiles(form)" type="button" class="btn btn-primary-outline col-md-4 col-md-push-1">Load
|
||||
Languages <span *ngIf="langRunning" class="fa fa-spinner fa-spin"> </span></button>
|
||||
|
||||
<small *ngIf="form.get('langaugeProfile').hasError('required')" class="error-text">A Default
|
||||
Langauage Profile is required</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-group col-md-12">
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" id="SeasonFolders" name="SeasonFolders" formControlName="seasonFolders">
|
||||
<label for="SeasonFolders">Enable season folders</label>
|
||||
|
@ -112,26 +142,27 @@
|
|||
<label>Enabled Season Folders to organize seasons into individual folders within a show.</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group" *ngIf="advanced" style="color:#ff761b">
|
||||
<div class="form-group col-md-12" *ngIf="advanced" style="color:#ff761b">
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" id="addOnly" formControlName="addOnly">
|
||||
<label for="addOnly">Do not search</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-group col-md-6">
|
||||
<div>
|
||||
<button type="submit" class="btn btn-primary-outline ">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-6">
|
||||
<div>
|
||||
<button type="button" (click)="test(form)" class="btn btn-primary-outline">Test Connectivity <span id="spinner"> </span></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<button type="submit" class="btn btn-primary-outline ">Submit</button>
|
||||
<button type="button" (click)="test(form)" class="btn btn-primary-outline">Test Connectivity
|
||||
<span id="spinner"> </span></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
|
@ -1,7 +1,7 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
|
||||
|
||||
import { ISonarrProfile, ISonarrRootFolder } from "../../interfaces";
|
||||
import { ILanguageProfiles, ISonarrProfile, ISonarrRootFolder } from "../../interfaces";
|
||||
|
||||
import { ISonarrSettings } from "../../interfaces";
|
||||
import { SonarrService } from "../../services";
|
||||
|
@ -18,10 +18,13 @@ export class SonarrComponent implements OnInit {
|
|||
public qualitiesAnime: ISonarrProfile[];
|
||||
public rootFolders: ISonarrRootFolder[];
|
||||
public rootFoldersAnime: ISonarrRootFolder[];
|
||||
public languageProfiles: ILanguageProfiles[];
|
||||
public selectedRootFolder: ISonarrRootFolder;
|
||||
public selectedQuality: ISonarrProfile;
|
||||
public selectedLanguageProfiles: ILanguageProfiles;
|
||||
public profilesRunning: boolean;
|
||||
public rootFoldersRunning: boolean;
|
||||
public langRunning: boolean;
|
||||
public form: FormGroup;
|
||||
public advanced = false;
|
||||
|
||||
|
@ -48,6 +51,7 @@ export class SonarrComponent implements OnInit {
|
|||
addOnly: [x.addOnly],
|
||||
seasonFolders: [x.seasonFolders],
|
||||
v3: [x.v3],
|
||||
langaugeProfile: [x.languageProfile],
|
||||
});
|
||||
|
||||
if (x.qualityProfile) {
|
||||
|
@ -56,11 +60,16 @@ export class SonarrComponent implements OnInit {
|
|||
if (x.rootPath) {
|
||||
this.getRootFolders(this.form);
|
||||
}
|
||||
if(x.languageProfile) {
|
||||
this.getLanguageProfiles(this.form);
|
||||
}
|
||||
});
|
||||
this.rootFolders = [];
|
||||
this.qualities = [];
|
||||
this.languageProfiles = [];
|
||||
this.rootFolders.push({ path: "Please Select", id: -1 });
|
||||
this.qualities.push({ name: "Please Select", id: -1 });
|
||||
this.languageProfiles.push({ name: "Please Select", id: -1 });
|
||||
}
|
||||
|
||||
public getProfiles(form: FormGroup) {
|
||||
|
@ -89,6 +98,18 @@ export class SonarrComponent implements OnInit {
|
|||
});
|
||||
}
|
||||
|
||||
public getLanguageProfiles(form: FormGroup) {
|
||||
this.langRunning = true;
|
||||
this.sonarrService.getV3LanguageProfiles(form.value)
|
||||
.subscribe(x => {
|
||||
this.languageProfiles = x;
|
||||
this.languageProfiles.unshift({ name: "Please Select", id: -1 });
|
||||
|
||||
this.langRunning = false;
|
||||
this.notificationService.success("Successfully retrieved the Languge Profiles");
|
||||
});
|
||||
}
|
||||
|
||||
public test(form: FormGroup) {
|
||||
if (form.invalid) {
|
||||
this.notificationService.error("Please check your entered values");
|
||||
|
|
|
@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authorization;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Ombi.Api.Sonarr;
|
||||
using Ombi.Api.Sonarr.Models;
|
||||
using Ombi.Api.Sonarr.Models.V3;
|
||||
using Ombi.Attributes;
|
||||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
|
@ -16,14 +17,16 @@ namespace Ombi.Controllers.External
|
|||
[Produces("application/json")]
|
||||
public class SonarrController : Controller
|
||||
{
|
||||
public SonarrController(ISonarrApi sonarr, ISettingsService<SonarrSettings> settings)
|
||||
public SonarrController(ISonarrApi sonarr, ISonarrV3Api sonarrv3, ISettingsService<SonarrSettings> settings)
|
||||
{
|
||||
SonarrApi = sonarr;
|
||||
SonarrV3Api = sonarrv3;
|
||||
SonarrSettings = settings;
|
||||
SonarrSettings.ClearCache();
|
||||
}
|
||||
|
||||
private ISonarrApi SonarrApi { get; }
|
||||
private ISonarrV3Api SonarrV3Api { get; }
|
||||
private ISettingsService<SonarrSettings> SonarrSettings { get; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -82,5 +85,36 @@ namespace Ombi.Controllers.External
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Sonarr V3 language profiles
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("v3/LanguageProfiles")]
|
||||
[PowerUser]
|
||||
public async Task<IEnumerable<LanguageProfiles>> GetLanguageProfiles()
|
||||
{
|
||||
var settings = await SonarrSettings.GetSettingsAsync();
|
||||
if (settings.Enabled)
|
||||
{
|
||||
return await SonarrV3Api.LanguageProfiles(settings.ApiKey, settings.FullUri);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Sonarr V3 language profiles
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("v3/LanguageProfiles")]
|
||||
[PowerUser]
|
||||
public async Task<IEnumerable<LanguageProfiles>> GetLanguageProfiles([FromBody] SonarrSettings settings)
|
||||
{
|
||||
return await SonarrV3Api.LanguageProfiles(settings.ApiKey, settings.FullUri);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue