diff --git a/src/Ombi.Core/Models/TesterResultModel.cs b/src/Ombi.Core/Models/TesterResultModel.cs index f23e14d43..563fa5cb2 100644 --- a/src/Ombi.Core/Models/TesterResultModel.cs +++ b/src/Ombi.Core/Models/TesterResultModel.cs @@ -3,6 +3,7 @@ public class TesterResultModel { public bool IsValid { get; set; } + public string Version { get; set; } public string ExpectedSubDir { get; set; } } } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 388686548..eb31a5c8f 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -312,7 +312,7 @@ namespace Ombi.Schedule.Jobs.Plex { break; } - if (quality.Equals(existing.Quality)) + if (quality == null || quality.Equals(existing.Quality)) { // We got it continue; diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISonarr.ts b/src/Ombi/ClientApp/src/app/interfaces/ISonarr.ts index ffe9e9b6d..bd43e671b 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISonarr.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISonarr.ts @@ -12,3 +12,8 @@ export interface ILanguageProfiles { name: string; id: number; } + +export interface ITag { + label: string; + id: number; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/interfaces/ITester.ts b/src/Ombi/ClientApp/src/app/interfaces/ITester.ts index c61292be4..b5615aae7 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ITester.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ITester.ts @@ -1,4 +1,5 @@ export interface ITesterResult { isValid: boolean; + version?: string; expectedSubDir?: string; } diff --git a/src/Ombi/ClientApp/src/app/services/applications/sonarr.service.ts b/src/Ombi/ClientApp/src/app/services/applications/sonarr.service.ts index 13a2076d4..ae41badf0 100644 --- a/src/Ombi/ClientApp/src/app/services/applications/sonarr.service.ts +++ b/src/Ombi/ClientApp/src/app/services/applications/sonarr.service.ts @@ -4,7 +4,7 @@ import { Injectable, Inject } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { ISonarrSettings } from "../../interfaces"; +import { ISonarrSettings, ITag } from "../../interfaces"; import { ILanguageProfiles, ISonarrProfile, ISonarrRootFolder } from "../../interfaces"; import { ServiceHelpers } from "../service.helpers"; @@ -36,6 +36,10 @@ export class SonarrService extends ServiceHelpers { return this.http.get(`${this.url}/v3/languageprofiles/`, {headers: this.headers}); } + public getTags(settings: ISonarrSettings): Observable { + return this.http.post(`${this.url}/tags/`, JSON.stringify(settings), {headers: this.headers}); + } + public isEnabled(): Promise { return this.http.get(`${this.url}/enabled/`, { headers: this.headers }).toPromise(); } diff --git a/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.html b/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.html index a3602b393..cc4ce8d72 100644 --- a/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.html +++ b/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.html @@ -57,14 +57,17 @@
- +
-
-
- -
-
+
+
+ +
+
+
+
+
Quality Profiles @@ -76,7 +79,7 @@
-
+
Quality Profiles (Anime) @@ -88,14 +91,18 @@
+
-
-
-
+
+
+
Default Root Folders @@ -107,7 +114,7 @@
-
+
Default Root Folders (Anime) @@ -118,21 +125,58 @@
+
+
+
+
+
+
+
+
+
+
+ + Default Tag + + {{tag.label}} + + +
+
+
+
+ + Anime Tags + + {{tag.label}} + + +
+
+
+ +
+ + + +
+
+
+
+
+
+
+
-
- -
-
-
-
- Language Profiles + Language Profiles {{lang.name}} @@ -141,19 +185,20 @@
-
+
- Language Profiles Anime + Anime {{lang.name}} A Language Profile Anime is required
-
+
+
@@ -170,18 +215,19 @@
+
- +
-
- +
+
diff --git a/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.ts b/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.ts index f6c9d9e38..fcd5bc47e 100644 --- a/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.ts @@ -1,7 +1,8 @@ import { Component, OnInit } from "@angular/core"; import { UntypedFormBuilder, FormControl, UntypedFormGroup, Validators } from "@angular/forms"; +import { finalize, map } from "rxjs"; -import { ILanguageProfiles, ISonarrProfile, ISonarrRootFolder } from "../../interfaces"; +import { ILanguageProfiles, ISonarrProfile, ISonarrRootFolder, ITag } from "../../interfaces"; import { ISonarrSettings } from "../../interfaces"; import { SonarrService } from "../../services"; @@ -21,14 +22,20 @@ export class SonarrComponent implements OnInit { public rootFoldersAnime: ISonarrRootFolder[]; public languageProfiles: ILanguageProfiles[]; public languageProfilesAnime: ILanguageProfiles[]; + + public tags: ITag[]; + public animeTags: ITag[]; + public selectedRootFolder: ISonarrRootFolder; public selectedQuality: ISonarrProfile; public selectedLanguageProfiles: ILanguageProfiles; public profilesRunning: boolean; public rootFoldersRunning: boolean; + public tagsRunning: boolean; public langRunning: boolean; public form: UntypedFormGroup; public advanced = false; + public sonarrVersion: string; formErrors: any; constructor(private settingsService: SettingsService, @@ -72,12 +79,29 @@ export class SonarrComponent implements OnInit { port: [x.port, [Validators.required]], addOnly: [x.addOnly], seasonFolders: [x.seasonFolders], - languageProfile: [x.languageProfile, [Validators.required, validateProfile]], + languageProfile: [x.languageProfile], languageProfileAnime: [x.languageProfileAnime], scanForAvailability: [x.scanForAvailability], - sendUserTags: [x.sendUserTags] + sendUserTags: [x.sendUserTags], + tag: [x.tag], + animeTag: [x.animeTag] }); + this.rootFolders = []; + this.qualities = []; + this.languageProfiles = []; + this.tags = []; + this.animeTags = []; + + if (x.enabled && this.form.valid) { + this.testerService.sonarrTest(x).subscribe(result => { + this.sonarrVersion = result.version[0]; + if (this.sonarrVersion === '3') { + this.form.controls.languageProfile.addValidators([Validators.required, validateProfile]); + } + }); + } + if (x.qualityProfile) { this.getProfiles(this.form); } @@ -87,6 +111,9 @@ export class SonarrComponent implements OnInit { if (x.languageProfile) { this.getLanguageProfiles(this.form); } + if (x.tag || x.animeTag) { + this.getTags(this.form); + } this.formErrors ={ apiKey: {}, @@ -97,12 +124,12 @@ export class SonarrComponent implements OnInit { }; this.onFormValuesChanged(); }); - 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 }); + this.animeTags.push({label: "None", id: -1}); + this.tags.push({label: "None", id: -1}); } public getProfiles(form: UntypedFormGroup) { @@ -142,14 +169,27 @@ export class SonarrComponent implements OnInit { }); } + public getTags(form: UntypedFormGroup) { + this.tagsRunning = true; + this.sonarrService.getTags(form.value).pipe( + finalize(() => { + this.tagsRunning = false; + this.animeTags.unshift({ label: "None", id: -1 }); + this.tags.unshift({ label: "None", id: -1 }); + this.notificationService.success("Successfully retrieved the Tags"); + }), + map(result => { + this.tags = result; + this.tags.forEach(val => this.animeTags.push(Object.assign({}, val))); + }) + ).subscribe() + } + public test(form: UntypedFormGroup) { - if (form.invalid) { - this.notificationService.error("Please check your entered values"); - return; - } const settings = form.value; this.testerService.sonarrTest(settings).subscribe(result => { if (result.isValid) { + this.sonarrVersion = result.version[0]; this.notificationService.success("Successfully connected to Sonarr!"); } else if (result.expectedSubDir) { this.notificationService.error("Your Sonarr Base URL must be set to " + result.expectedSubDir); @@ -179,6 +219,12 @@ export class SonarrComponent implements OnInit { this.notificationService.error("Please check your entered values"); } } + if (form.controls.animeTag.value == -1) { + form.controls.animeTag.setValue(null); + } + if (form.controls.tag.value == -1) { + form.controls.tag.setValue(null); + } this.settingsService.saveSonarr(form.value) .subscribe(x => { @@ -190,6 +236,7 @@ export class SonarrComponent implements OnInit { }); } } + function validateProfile(qualityProfile): { [key: string]:boolean } | null { if (qualityProfile.value !== undefined && (isNaN(qualityProfile.value) || qualityProfile.value == -1)) { diff --git a/src/Ombi/Controllers/V1/External/TesterController.cs b/src/Ombi/Controllers/V1/External/TesterController.cs index bedf207b1..79a008322 100644 --- a/src/Ombi/Controllers/V1/External/TesterController.cs +++ b/src/Ombi/Controllers/V1/External/TesterController.cs @@ -46,7 +46,7 @@ namespace Ombi.Controllers.V1.External /// public TesterController(INotificationService service, IDiscordNotification notification, IEmailNotification emailN, IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm, - IPlexApi plex, IEmbyApiFactory emby, IRadarrV3Api radarr, ISonarrApi sonarr, ILogger log, IEmailProvider provider, + IPlexApi plex, IEmbyApiFactory emby, IRadarrV3Api radarr, ISonarrV3Api sonarr, ILogger log, IEmailProvider provider, ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, ILegacyMobileNotification mobileNotification, ILidarrApi lidarrApi, IGotifyNotification gotifyNotification, IWhatsAppApi whatsAppApi, OmbiUserManager um, IWebhookNotification webhookNotification, IJellyfinApi jellyfinApi, IPrincipal user) @@ -90,7 +90,7 @@ namespace Ombi.Controllers.V1.External private IPlexApi PlexApi { get; } private IRadarrV3Api RadarrApi { get; } private IEmbyApiFactory EmbyApi { get; } - private ISonarrApi SonarrApi { get; } + private ISonarrV3Api SonarrApi { get; } private ICouchPotatoApi CouchPotatoApi { get; } private ILogger Log { get; } private IEmailProvider EmailProvider { get; } @@ -415,6 +415,7 @@ namespace Ombi.Controllers.V1.External return new TesterResultModel { IsValid = result.urlBase == settings.SubDir || string.IsNullOrEmpty(result.urlBase) && string.IsNullOrEmpty(settings.SubDir), + Version = result.version, ExpectedSubDir = result.urlBase }; }