Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sonarr): Added the ability to add default tags when sending to Sonarr #4803

Merged
merged 1 commit into from
Nov 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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