Skip to content

Commit

Permalink
feat(sonarr): Added the ability to add default tags when sending to S…
Browse files Browse the repository at this point in the history
…onarr
  • Loading branch information
tidusjar committed Nov 18, 2022
1 parent 3e23d36 commit 98a3cc5
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 43 deletions.
1 change: 1 addition & 0 deletions src/Ombi.Core/Models/TesterResultModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
public class TesterResultModel
{
public bool IsValid { get; set; }
public string Version { get; set; }
public string ExpectedSubDir { get; set; }
}
}
2 changes: 1 addition & 1 deletion src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ public async Task MovieLoop(PlexServers servers, Mediacontainer content, HashSet
{
break;
}
if (quality.Equals(existing.Quality))
if (quality == null || quality.Equals(existing.Quality))
{
// We got it
continue;
Expand Down
5 changes: 5 additions & 0 deletions src/Ombi/ClientApp/src/app/interfaces/ISonarr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@ export interface ILanguageProfiles {
name: string;
id: number;
}

export interface ITag {
label: string;
id: number;
}
1 change: 1 addition & 0 deletions src/Ombi/ClientApp/src/app/interfaces/ITester.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export interface ITesterResult {
isValid: boolean;
version?: string;
expectedSubDir?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -36,6 +36,10 @@ export class SonarrService extends ServiceHelpers {
return this.http.get<ILanguageProfiles[]>(`${this.url}/v3/languageprofiles/`, {headers: this.headers});
}

public getTags(settings: ISonarrSettings): Observable<ITag[]> {
return this.http.post<ITag[]>(`${this.url}/tags/`, JSON.stringify(settings), {headers: this.headers});
}

public isEnabled(): Promise<boolean> {
return this.http.get<boolean>(`${this.url}/enabled/`, { headers: this.headers }).toPromise();
}
Expand Down
104 changes: 75 additions & 29 deletions src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,17 @@
</div>
</div>
<div class="col-md-5 col-4 col-sm-12">
<label for="username" class="control-label"><h3>Sonarr Interface</h3></label>

<div class="form-group col-md-12">
<div id="profiles">
<div class="md-form-field" style="display:inline;">
<button mat-raised-button id="profiles" (click)="getProfiles(form)" class="mat-stroked-button">
Load Qualities <span *ngIf="profilesRunning" class="fas fa-spinner fa-spin"></span></button>
<div class="md-form-field" style="margin-top:1em;"></div>
</div>
<div class="row">
<div class="col-md-12">
<button mat-raised-button id="profiles" type="button" (click)="getProfiles(form)" class="mat-stroked-button">
Load Qualities <span *ngIf="profilesRunning" class="fas fa-spinner fa-spin"></span></button>
<div class="md-form-field" style="margin-top:1em;"></div>
</div>
</div>
<div class="row">
<div id="profiles" class="col-md-6">
<div class="md-form-field" style="display:contents;">
<mat-form-field appearance="outline">
<mat-label>Quality Profiles</mat-label>
Expand All @@ -76,7 +79,7 @@
</div>

</div>
<div id="qualityProfileAnime">
<div id="qualityProfileAnime" class="col-md-6">
<div class="md-form-field" style="display:contents;">
<mat-form-field appearance="outline">
<mat-label>Quality Profiles (Anime)</mat-label>
Expand All @@ -88,14 +91,18 @@
</div>
</div>
</div>
</div>


<div class="form-group col-md-12">
<div id="rootFolders">
<div class="md-form-field" style="display:inline">
<button mat-raised-button id="rootFolder" (click)="getRootFolders(form)" class="mat-stroked-button">
<div class="row">
<div class="col-md-12">
<button mat-raised-button id="rootFolder" type="button" (click)="getRootFolders(form)" class="mat-stroked-button">
Load Folders <span *ngIf="rootFoldersRunning" class="fas fa-spinner fa-spin"></span></button><div class="md-form-field" style="margin-top:1em;"></div>
</div>
</div>
<div class="row">
<div id="rootFolders" class="col-md-6">
<div class="md-form-field" style="display:contents;">
<mat-form-field appearance="outline">
<mat-label>Default Root Folders</mat-label>
Expand All @@ -107,7 +114,7 @@
</div>

</div>
<div id="rootFoldersAnime">
<div id="rootFoldersAnime" class="col-md-6">
<div class="md-form-field" style="display:contents;">
<mat-form-field appearance="outline">
<mat-label>Default Root Folders (Anime)</mat-label>
Expand All @@ -118,21 +125,58 @@
</mat-form-field>
</div>
</div>
</div></div>

<div class="form-group col-md-12">
<div class="row">
<div class="col-md-12">
<button mat-raised-button id="rootFolder" type="button" (click)="getTags(form)" class="mat-stroked-button">
Load Tags <span *ngIf="tagsRunning" class="fas fa-spinner fa-spin"></span></button><div class="md-form-field" style="margin-top:1em;"></div>
</div>
</div>
<div class="row">
<div id="tag" class="col-md-6">
<div class="md-form-field" style="display:contents;">
<mat-form-field appearance="outline">
<mat-label>Default Tag</mat-label>
<mat-select formControlName="tag">
<mat-option *ngFor="let tag of tags" [value]="tag.id">{{tag.label}} </mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
<div id="animeTag" class="col-md-6">
<div class="md-form-field" style="display:contents;">
<mat-form-field appearance="outline">
<mat-label>Anime Tags</mat-label>
<mat-select formControlName="animeTag">
<mat-option *ngFor="let tag of animeTags" [value]="tag.id">{{tag.label}} </mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div></div>

<div class="form-group col-md-12" *ngIf="sonarrVersion === '3'">
<label for="select" class="control-label">Language Profiles
<i *ngIf="form.get('languageProfile').hasError('required')" class="fas fa-exclamation-circle error-text" pTooltip="A Language Profile is required"></i>
</label>


<div class="md-form-field" style="display:inline">
<div class="row">
<div class="col-md-12">
<button type="button" mat-raised-button (click)="getLanguageProfiles(form)" class="mat-stroked-button">Load
Languages <span *ngIf="langRunning" class="fas fa-spinner fa-spin"> </span></button><div class="md-form-field" style="margin-top:1em;"></div>
</div>
</div>
</div>
<div class="row">
<div id="langaugeProfile" class="col-md-6">

<div class="form-group col-md-12">
<label for="select" class="control-label">Language Profiles
<i *ngIf="form.get('languageProfile').hasError('required')" class="fas fa-exclamation-circle error-text" pTooltip="A Language Profile is required"></i>
</label>
<div id="langaugeProfile">
<div class="md-form-field" style="display:inline">
<button type="button" mat-raised-button (click)="getLanguageProfiles(form)" class="mat-stroked-button">Load
Languages <span *ngIf="langRunning" class="fas fa-spinner fa-spin"> </span></button><div class="md-form-field" style="margin-top:1em;"></div>
</div>
<div class="md-form-field" style="display:contents;">
<mat-form-field appearance="outline">
<mat-label>Language Profiles </mat-label>
<mat-label>Language Profiles</mat-label>
<mat-select formControlName="languageProfile">
<mat-option *ngFor="let lang of languageProfiles" [value]="lang.id">{{lang.name}}</mat-option>
</mat-select>
Expand All @@ -141,19 +185,20 @@
</div>

</div>
<div id="langaugeProfileAnime">
<div id="langaugeProfileAnime" class="col-md-6">
<div class="md-form-field" style="display:contents;">
<mat-form-field appearance="outline">
<mat-label>Language Profiles Anime</mat-label>
<mat-label>Anime</mat-label>
<mat-select formControlName="languageProfileAnime">
<mat-option *ngFor="let lang of languageProfiles" [value]="lang.id">{{lang.name}}</mat-option>
</mat-select>
<mat-error>A Language Profile Anime is required</mat-error>
</mat-form-field>
</div>

</div>

</div>
</div>


<div class="form-group col-md-12">
Expand All @@ -170,18 +215,19 @@
</div>
</div>
<div class="col-md-4">

<div class="form-group col-md-7">
<div>
<button mat-raised-button type="submit" class="mat-stroked-button accent mat-accent">Submit</button>
<button mat-raised-button type="button" (click)="test(form)" class="mat-stroked-button">Test Connectivity
<span id="spinner"> </span></button>
</div>
</div>

<div class="form-group col-md-7">
<div>
<button mat-raised-button type="button" (click)="test(form)" class="mat-stroked-button">Test Connectivity
<span id="spinner"> </span></button>
<button mat-raised-button type="submit" class="mat-stroked-button accent mat-accent">Submit</button>
</div>
</div>

</div>
</div>
</form>
Expand Down
67 changes: 57 additions & 10 deletions src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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,
Expand Down Expand Up @@ -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);
}
Expand All @@ -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: {},
Expand All @@ -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) {
Expand Down Expand Up @@ -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 = <ISonarrSettings> 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);
Expand Down Expand Up @@ -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 => {
Expand All @@ -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)) {
Expand Down
Loading

0 comments on commit 98a3cc5

Please sign in to comment.