think i did it

This commit is contained in:
tidusjar 2022-11-25 16:26:23 +00:00
commit 4ed0ac6e6b
19 changed files with 309 additions and 146 deletions

View file

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Ombi.Api.Radarr.Models;
using Ombi.Api.Radarr.Models.V3;
@ -14,7 +15,8 @@ namespace Ombi.Api.Radarr
Task<MovieResponse> GetMovie(int id, string apiKey, string baseUrl);
Task<MovieResponse> UpdateMovie(MovieResponse movie, string apiKey, string baseUrl);
Task<bool> MovieSearch(int[] movieIds, string apiKey, string baseUrl);
Task<RadarrAddMovie> AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath,string apiKey, string baseUrl, bool searchNow, string minimumAvailability);
Task<RadarrAddMovie> AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath,string apiKey, string baseUrl, bool searchNow, string minimumAvailability, List<int> tags);
Task<List<Tag>> GetTags(string apiKey, string baseUrl);
Task<Tag> CreateTag(string apiKey, string baseUrl, string tagName);
}
}

View file

@ -29,5 +29,6 @@ namespace Ombi.Api.Radarr.Models
public int year { get; set; }
public string minimumAvailability { get; set; }
public long sizeOnDisk { get; set; }
public int[] tags { get; set; }
}
}

View file

@ -72,7 +72,7 @@ namespace Ombi.Api.Radarr
return await Api.Request<MovieResponse>(request);
}
public async Task<RadarrAddMovie> AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath, string apiKey, string baseUrl, bool searchNow, string minimumAvailability)
public async Task<RadarrAddMovie> AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath, string apiKey, string baseUrl, bool searchNow, string minimumAvailability, List<int> tags)
{
var request = new Request("/api/v3/movie", baseUrl, HttpMethod.Post);
@ -86,7 +86,8 @@ namespace Ombi.Api.Radarr
monitored = true,
year = year,
minimumAvailability = minimumAvailability,
sizeOnDisk = 0
sizeOnDisk = 0,
tags = tags.Any() ? tags.ToArray() : Enumerable.Empty<int>().ToArray()
};
if (searchNow)
@ -156,5 +157,14 @@ namespace Ombi.Api.Radarr
{
request.AddHeader("X-Api-Key", key);
}
public Task<Tag> CreateTag(string apiKey, string baseUrl, string tagName)
{
var request = new Request($"/api/v3/tag", baseUrl, HttpMethod.Post);
request.AddHeader("X-Api-Key", apiKey);
request.AddJsonBody(new { Label = tagName });
return Api.Request<Tag>(request);
}
}
}

View file

@ -15,6 +15,8 @@ using Ombi.Store.Entities;
using Ombi.Store.Repository;
using System.Collections.Generic;
using Ombi.Api.Radarr.Models;
using Microsoft.Extensions.Options;
using Ombi.Api.Sonarr;
namespace Ombi.Core.Senders
{
@ -67,7 +69,7 @@ namespace Ombi.Core.Senders
}
if (radarrSettings.Enabled)
{
return await SendToRadarr(model, is4K, radarrSettings);
return await SendToRadarr(model, radarrSettings);
}
var dogSettings = await _dogNzbSettings.GetSettingsAsync();
@ -131,7 +133,7 @@ namespace Ombi.Core.Senders
return await _dogNzbApi.AddMovie(settings.ApiKey, id);
}
private async Task<SenderResult> SendToRadarr(MovieRequests model, bool is4K, RadarrSettings settings)
private async Task<SenderResult> SendToRadarr(MovieRequests model, RadarrSettings settings)
{
var qualityToUse = int.Parse(settings.DefaultQualityProfile);
@ -154,6 +156,17 @@ namespace Ombi.Core.Senders
}
}
var tags = new List<int>();
if (settings.Tag.HasValue)
{
tags.Add(settings.Tag.Value);
}
if (settings.SendUserTags)
{
var userTag = await GetOrCreateTag(model, settings);
tags.Add(userTag.id);
}
// Overrides on the request take priority
if (model.QualityOverride > 0)
{
@ -174,7 +187,7 @@ namespace Ombi.Core.Senders
{
var result = await _radarrV3Api.AddMovie(model.TheMovieDbId, model.Title, model.ReleaseDate.Year,
qualityToUse, rootFolderPath, settings.ApiKey, settings.FullUri, !settings.AddOnly,
settings.MinimumAvailability);
settings.MinimumAvailability, tags);
if (!string.IsNullOrEmpty(result.Error?.message))
{
@ -212,5 +225,17 @@ namespace Ombi.Core.Senders
var selectedPath = paths.FirstOrDefault(x => x.id == overrideId);
return selectedPath?.path ?? string.Empty;
}
private async Task<Tag> GetOrCreateTag(MovieRequests model, RadarrSettings s)
{
var tagName = model.RequestedUser.UserName;
// Does tag exist?
var allTags = await _radarrV3Api.GetTags(s.ApiKey, s.FullUri);
var existingTag = allTags.FirstOrDefault(x => x.label.Equals(tagName, StringComparison.InvariantCultureIgnoreCase));
existingTag ??= await _radarrV3Api.CreateTag(s.ApiKey, s.FullUri, tagName);
return existingTag;
}
}
}

View file

@ -9,6 +9,8 @@
public bool AddOnly { get; set; }
public string MinimumAvailability { get; set; }
public bool ScanForAvailability { get; set; }
public int? Tag { get; set; }
public bool SendUserTags { get; set; }
}
public class Radarr4KSettings : RadarrSettings

View file

@ -19,11 +19,11 @@
public string RootPathAnime { get; set; }
public int? AnimeTag { get; set; }
public int? Tag { get; set; }
public bool SendUserTags { get; set; }
public bool AddOnly { get; set; }
public int LanguageProfile { get; set; }
public int LanguageProfileAnime { get; set; }
public bool ScanForAvailability { get; set; }
public bool SendUserTags { get; set; }
}
}

View file

@ -157,7 +157,7 @@ export class DiscoverCardComponent implements OnInit {
AdminRequestDialogComponent,
{
width: "700px",
data: { type: RequestType.movie, id: this.result.id },
data: { type: RequestType.movie, id: this.result.id, is4k: is4k },
panelClass: "modal-panel",
}
);

View file

@ -160,6 +160,8 @@ export interface IRadarrSettings extends IExternalSettings {
addOnly: boolean;
minimumAvailability: string;
scanForAvailability: boolean;
tag: number | null;
sendUserTags: boolean;
}
export interface IRadarrCombined {

View file

@ -111,7 +111,7 @@ export class MovieDetailsComponent implements OnInit{
is4K = false;
}
if (this.isAdmin) {
const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.movie, id: this.movie.id }, panelClass: 'modal-panel' });
const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.movie, id: this.movie.id, is4K: is4K }, panelClass: 'modal-panel' });
dialog.afterClosed().subscribe(async (result) => {
if (result) {
const requestResult = await firstValueFrom(this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId,

View file

@ -62,7 +62,7 @@ export class TvRequestGridComponent {
});
if (this.isAdmin) {
const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.tvShow, id: this.tv.id }, panelClass: 'modal-panel' });
const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.tvShow, id: this.tv.id, is4k: null }, panelClass: 'modal-panel' });
dialog.afterClosed().subscribe(async (result) => {
if (result) {
viewModel.requestOnBehalf = result.username?.id;

View file

@ -28,15 +28,23 @@ export class RadarrService extends ServiceHelpers {
return this.http.get<IRadarrProfile[]>(`${this.url}/Profiles/`, { headers: this.headers });
}
public getRootFolders4kFromSettings(): Observable<IRadarrRootFolder[]> {
return this.http.get<IRadarrRootFolder[]>(`${this.url}/RootFolders/4k`, { headers: this.headers });
}
public getQualityProfiles4kFromSettings(): Observable<IRadarrProfile[]> {
return this.http.get<IRadarrProfile[]>(`${this.url}/Profiles/4k`, { headers: this.headers });
}
public isRadarrEnabled(): Observable<boolean> {
return this.http.get<boolean>(`${this.url}/enabled/`, { headers: this.headers });
}
public getTagsWithSettings(settings: IRadarrSettings): Observable<ITag[]> {
return this.http.post<ITag[]>(`${this.url}/enabled/`, JSON.stringify(settings), { headers: this.headers });
return this.http.post<ITag[]>(`${this.url}/tags/`, JSON.stringify(settings), { headers: this.headers });
}
public getTags(): Observable<ITag[]> {
return this.http.get<ITag[]>(`${this.url}/enabled/`, { headers: this.headers })
return this.http.get<ITag[]>(`${this.url}/tags/`, { headers: this.headers })
}
}

View file

@ -8,6 +8,10 @@
<div class="md-form-field">
<mat-slide-toggle formControlName="scanForAvailability">Scan for Availability</mat-slide-toggle>
</div>
<div class="md-form-field">
<mat-slide-toggle formControlName="sendUserTags" id="sendUserTags">Add the user as a tag</mat-slide-toggle>
<small><br>This will add the username of the requesting user as a tag in Sonarr. If the tag doesn't exist, Ombi will create it.</small>
</div>
<div class="md-form-field" >
<mat-slide-toggle formControlName="addOnly">
Do not search for Movies
@ -79,6 +83,22 @@
</mat-form-field>
</div>
<div class="md-form-field">
<div class="md-form-field" style="display:inline;">
<button mat-raised-button (click)="getTags(form)" type="button" color="primary">Load Tags <span *ngIf="tagsRunning" class="fas fa-spinner fa-spin"></span></button>
</div>
<div class="md-form-field" style="margin-top:1em;"></div>
<mat-form-field appearance="outline" >
<mat-label>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 class="md-form-field">
<mat-form-field appearance="outline" >
<mat-label>Default Minimum Availability</mat-label>

View file

@ -1,7 +1,8 @@
import { ChangeDetectionStrategy, Component, OnInit } from "@angular/core";
import { ControlContainer, UntypedFormGroup, Validators } from "@angular/forms";
import { finalize, map } from "rxjs";
import { IMinimumAvailability, IRadarrProfile, IRadarrRootFolder, IRadarrSettings } from "../../../interfaces";
import { IMinimumAvailability, IRadarrProfile, IRadarrRootFolder, IRadarrSettings, ITag } from "../../../interfaces";
import { TesterService, NotificationService, RadarrService } from "../../../services";
@ -16,8 +17,10 @@ export class RadarrFormComponent implements OnInit {
public qualities: IRadarrProfile[];
public rootFolders: IRadarrRootFolder[];
public minimumAvailabilityOptions: IMinimumAvailability[];
public tags: ITag[];
public profilesRunning: boolean;
public rootFoldersRunning: boolean;
public tagsRunning: boolean;
public form: UntypedFormGroup;
constructor(private radarrService: RadarrService,
@ -34,6 +37,10 @@ export class RadarrFormComponent implements OnInit {
this.rootFolders = [];
this.rootFolders.push({ path: "Please Select", id: -1 });
this.tags = [];
this.tags.push({ label: "None", id: -1 });
this.minimumAvailabilityOptions = [
{ name: "Announced", value: "Announced" },
{ name: "In Cinemas", value: "InCinemas" },
@ -47,9 +54,16 @@ export class RadarrFormComponent implements OnInit {
if (this.form.controls.defaultRootPath.value) {
this.getRootFolders(this.form);
}
if (this.form.controls.tag.value) {
this.getTags(this.form);
}
this.toggleValidators();
}
public toggleValidators() {
debugger;
const enabled = this.form.controls.enabled.value as boolean;
this.form.controls.apiKey.setValidators(enabled ? [Validators.required] : null);
this.form.controls.defaultQualityProfile.setValidators(enabled ? [Validators.required] : null);
@ -81,6 +95,20 @@ export class RadarrFormComponent implements OnInit {
});
}
public getTags(form: UntypedFormGroup) {
this.tagsRunning = true;
this.radarrService.getTagsWithSettings(form.value).pipe(
finalize(() => {
this.tagsRunning = false;
this.tags.unshift({ label: "None", id: -1 });
this.notificationService.success("Successfully retrieved the Tags");
}),
map(result => {
this.tags = result;
})
).subscribe()
}
public test(form: UntypedFormGroup) {
if (form.invalid) {
this.notificationService.error("Please check your entered values");

View file

@ -40,6 +40,8 @@ export class RadarrComponent implements OnInit {
apiKey: [x.settings.radarr.apiKey],
defaultQualityProfile: [+x.settings.radarr.defaultQualityProfile],
defaultRootPath: [x.settings.radarr.defaultRootPath],
tag: [x.settings.radarr.tag],
sendUserTags: [x.settings.radarr.sendUserTags],
ssl: [x.settings.radarr.ssl],
subDir: [x.settings.radarr.subDir],
ip: [x.settings.radarr.ip],
@ -53,6 +55,8 @@ export class RadarrComponent implements OnInit {
apiKey: [x.settings.radarr4K.apiKey],
defaultQualityProfile: [+x.settings.radarr4K.defaultQualityProfile],
defaultRootPath: [x.settings.radarr4K.defaultRootPath],
tag: [x.settings.radarr4K.tag],
sendUserTags: [x.settings.radarr4K.sendUserTags],
ssl: [x.settings.radarr4K.ssl],
subDir: [x.settings.radarr4K.subDir],
ip: [x.settings.radarr4K.ip],
@ -71,7 +75,6 @@ export class RadarrComponent implements OnInit {
}))
}
});
}
@ -83,15 +86,24 @@ export class RadarrComponent implements OnInit {
const radarrForm = form.controls.radarr as UntypedFormGroup;
const radarr4KForm = form.controls.radarr4K as UntypedFormGroup;
if (radarrForm.controls.enabled.value && (radarrForm.controls.defaultQualityProfile.value === -1 || radarrForm.controls.defaultRootPath.value === "Please Select")) {
if (radarrForm.controls.enabled.value && (radarrForm.controls.defaultQualityProfile.value === -1
|| radarrForm.controls.defaultRootPath.value === "Please Select")) {
this.notificationService.error("Please check your entered values for Radarr");
return;
}
if (radarr4KForm.controls.enabled.value && (radarr4KForm.controls.defaultQualityProfile.value === -1 || radarr4KForm.controls.defaultRootPath.value === "Please Select")) {
if (radarr4KForm.controls.enabled.value && (radarr4KForm.controls.defaultQualityProfile.value === -1
|| radarr4KForm.controls.defaultRootPath.value === "Please Select")) {
this.notificationService.error("Please check your entered values for Radarr 4K");
return;
}
if (radarr4KForm.controls.tag.value === -1) {
radarr4KForm.controls.tag.setValue(null);
}
if (radarrForm.controls.tag.value === -1) {
radarr4KForm.controls.tag.setValue(null);
}
const settings = <IRadarrCombined> form.value;
this.radarrFacade.updateSettings(settings).subscribe(x => {
if (x) {

View file

@ -138,7 +138,7 @@
<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-label>Tag</mat-label>
<mat-select formControlName="tag">
<mat-option *ngFor="let tag of tags" [value]="tag.id">{{tag.label}} </mat-option>
</mat-select>

View file

@ -65,25 +65,25 @@
<!-- Radarr -->
<div *ngIf="data.type === RequestType.movie && radarrEnabled"><hr />
<div>
<h3>Radarr Overrides</h3>
<mat-form-field appearance="outline" floatLabel=auto>
<mat-label>{{'MediaDetails.QualityProfilesSelect' | translate }}</mat-label>
<mat-select id="radarrQualitySelect" formControlName="radarrPathId">
<mat-option id="radarrQualitySelect{{profile.id}}" *ngFor="let profile of radarrProfiles" value="{{profile.id}}">{{profile.name}}</mat-option>
</mat-select>
</mat-form-field>
<div>
<h3>Radarr Overrides</h3>
<mat-form-field appearance="outline" floatLabel=auto>
<mat-label>{{'MediaDetails.QualityProfilesSelect' | translate }}</mat-label>
<mat-select id="radarrQualitySelect" formControlName="radarrPathId">
<mat-option id="radarrQualitySelect{{profile.id}}" *ngFor="let profile of radarrProfiles" value="{{profile.id}}">{{profile.name}}</mat-option>
</mat-select>
</mat-form-field>
</div>
<div mat-dialog-content>
<mat-form-field appearance="outline" floatLabel=auto>
<mat-label>{{'MediaDetails.RootFolderSelect' | translate }}</mat-label>
<mat-select id="radarrFolderSelect" formControlName="radarrFolderId">
<mat-option id="radarrFolderSelect{{profile.id}}" *ngFor="let profile of radarrRootFolders" value="{{profile.id}}">{{profile.path}}</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
<div mat-dialog-content>
<mat-form-field appearance="outline" floatLabel=auto>
<mat-label>{{'MediaDetails.RootFolderSelect' | translate }}</mat-label>
<mat-select id="radarrFolderSelect" formControlName="radarrFolderId">
<mat-option id="radarrFolderSelect{{profile.id}}" *ngFor="let profile of radarrRootFolders" value="{{profile.id}}">{{profile.path}}</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
<!-- End Radarr-->
<!-- End Radarr-->
<div mat-dialog-actions class="right-buttons">

View file

@ -1,124 +1,143 @@
import { Component, Inject, OnInit } from "@angular/core";
import { UntypedFormBuilder, UntypedFormGroup } from "@angular/forms";
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
import { SonarrFacade } from "app/state/sonarr";
import { firstValueFrom, Observable } from "rxjs";
import { startWith, map } from "rxjs/operators";
import { ILanguageProfiles, IRadarrProfile, IRadarrRootFolder, ISonarrProfile, ISonarrRootFolder, IUserDropdown, RequestType } from "../../interfaces";
import { IdentityService, RadarrService, SonarrService } from "../../services";
import { Component, Inject, OnInit } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { RadarrFacade } from 'app/state/radarr';
import { SonarrFacade } from 'app/state/sonarr';
import { firstValueFrom, Observable } from 'rxjs';
import { startWith, map } from 'rxjs/operators';
import {
ILanguageProfiles,
IRadarrProfile,
IRadarrRootFolder,
ISonarrProfile,
ISonarrRootFolder,
IUserDropdown,
RequestType,
} from '../../interfaces';
import { IdentityService, RadarrService, SonarrService } from '../../services';
export interface IAdminRequestDialogData {
type: RequestType,
id: number
type: RequestType;
id: number;
is4k: boolean | null;
}
@Component({
selector: "admin-request-dialog",
templateUrl: "admin-request-dialog.component.html",
styleUrls: [ "admin-request-dialog.component.scss" ]
selector: 'admin-request-dialog',
templateUrl: 'admin-request-dialog.component.html',
styleUrls: ['admin-request-dialog.component.scss'],
})
export class AdminRequestDialogComponent implements OnInit {
constructor(
public dialogRef: MatDialogRef<AdminRequestDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: IAdminRequestDialogData,
private identityService: IdentityService,
private sonarrService: SonarrService,
private radarrService: RadarrService,
private fb: UntypedFormBuilder,
private sonarrFacade: SonarrFacade
) {}
constructor(
public dialogRef: MatDialogRef<AdminRequestDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: IAdminRequestDialogData,
private identityService: IdentityService,
private sonarrService: SonarrService,
private radarrService: RadarrService,
private fb: UntypedFormBuilder,
private sonarrFacade: SonarrFacade,
private radarrFacade: RadarrFacade,
) {}
public form: UntypedFormGroup;
public RequestType = RequestType;
public form: UntypedFormGroup;
public RequestType = RequestType;
public options: IUserDropdown[];
public filteredOptions: Observable<IUserDropdown[]>;
public userId: string;
public options: IUserDropdown[];
public filteredOptions: Observable<IUserDropdown[]>;
public userId: string;
public radarrEnabled: boolean;
public sonarrEnabled: boolean;
public radarrEnabled: boolean;
public radarr4kEnabled: boolean;
public sonarrEnabled: boolean;
public sonarrProfiles: ISonarrProfile[];
public sonarrRootFolders: ISonarrRootFolder[];
public sonarrLanguageProfiles: ILanguageProfiles[];
public radarrProfiles: IRadarrProfile[];
public radarrRootFolders: IRadarrRootFolder[];
public sonarrProfiles: ISonarrProfile[];
public sonarrRootFolders: ISonarrRootFolder[];
public sonarrLanguageProfiles: ILanguageProfiles[];
public radarrProfiles: IRadarrProfile[];
public radarrRootFolders: IRadarrRootFolder[];
public async ngOnInit() {
public async ngOnInit() {
this.form = this.fb.group({
username: [null],
sonarrPathId: [null],
sonarrFolderId: [null],
sonarrLanguageId: [null],
radarrPathId: [null],
radarrFolderId: [null],
});
this.form = this.fb.group({
username: [null],
sonarrPathId: [null],
sonarrFolderId: [null],
sonarrLanguageId: [null],
radarrPathId: [null],
radarrFolderId: [null]
})
this.options = await firstValueFrom(this.identityService.getUsersDropdown());
this.options = await firstValueFrom(this.identityService.getUsersDropdown());
this.filteredOptions = this.form.controls['username'].valueChanges.pipe(
startWith(''),
map((value) => this._filter(value)),
);
this.filteredOptions = this.form.controls['username'].valueChanges.pipe(
startWith(""),
map((value) => this._filter(value))
);
if (this.data.type === RequestType.tvShow) {
this.sonarrEnabled = this.sonarrFacade.isEnabled();
if (this.sonarrEnabled) {
console.log(this.sonarrFacade.version());
if (this.sonarrFacade.version()[0] === '3') {
this.sonarrService.getV3LanguageProfilesWithoutSettings().subscribe((profiles: ILanguageProfiles[]) => {
this.sonarrLanguageProfiles = profiles;
});
}
this.sonarrService.getQualityProfilesWithoutSettings().subscribe((c) => {
this.sonarrProfiles = c;
});
this.sonarrService.getRootFoldersWithoutSettings().subscribe((c) => {
this.sonarrRootFolders = c;
});
}
}
if (this.data.type === RequestType.movie) {
this.radarrEnabled = this.radarrFacade.isEnabled();
this.radarr4kEnabled = this.radarrFacade.is4KEnabled();
if (this.data.type === RequestType.tvShow) {
this.sonarrEnabled = this.sonarrFacade.isEnabled();
if (this.sonarrEnabled) {
console.log(this.sonarrFacade.version());
if (this.sonarrFacade.version()[0] === "3") {
this.sonarrService.getV3LanguageProfilesWithoutSettings().subscribe((profiles: ILanguageProfiles[]) => {
this.sonarrLanguageProfiles = profiles;
})
}
this.sonarrService.getQualityProfilesWithoutSettings().subscribe(c => {
this.sonarrProfiles = c;
});
this.sonarrService.getRootFoldersWithoutSettings().subscribe(c => {
this.sonarrRootFolders = c;
});
}
}
if (this.data.type === RequestType.movie) {
this.radarrEnabled = await firstValueFrom(this.radarrService.isRadarrEnabled());
if (this.radarrEnabled) {
this.radarrService.getQualityProfilesFromSettings().subscribe(c => {
this.radarrProfiles = c;
});
this.radarrService.getRootFoldersFromSettings().subscribe(c => {
this.radarrRootFolders = c;
});
}
}
}
if (this.data.is4k ?? false) {
if (this.radarr4kEnabled) {
this.radarrService.getQualityProfiles4kFromSettings().subscribe((c) => {
this.radarrProfiles = c;
});
this.radarrService.getRootFolders4kFromSettings().subscribe((c) => {
this.radarrRootFolders = c;
});
}
} else {
if (this.radarrEnabled) {
this.radarrService.getQualityProfilesFromSettings().subscribe((c) => {
this.radarrProfiles = c;
});
this.radarrService.getRootFoldersFromSettings().subscribe((c) => {
this.radarrRootFolders = c;
});
}
}
}
}
public displayFn(user: IUserDropdown): string {
const username = user?.username ? user.username : "";
const email = user?.email ? `(${user.email})` : "";
if (username || email) {
return `${username} ${email}`;
}
return '';
}
public displayFn(user: IUserDropdown): string {
const username = user?.username ? user.username : '';
const email = user?.email ? `(${user.email})` : '';
if (username || email) {
return `${username} ${email}`;
}
return '';
}
private _filter(value: string | IUserDropdown): IUserDropdown[] {
const filterValue =
typeof value === "string"
? value.toLowerCase()
: value.username.toLowerCase();
private _filter(value: string | IUserDropdown): IUserDropdown[] {
const filterValue = typeof value === 'string' ? value.toLowerCase() : value.username.toLowerCase();
return this.options.filter((option) =>
option.username.toLowerCase().includes(filterValue)
);
}
return this.options.filter((option) => option.username.toLowerCase().includes(filterValue));
}
public async submitRequest() {
const model = this.form.value;
model.radarrQualityOverrideTitle = this.radarrProfiles?.filter(x => x.id == model.radarrPathId)[0]?.name;
model.radarrRootFolderTitle = this.radarrRootFolders?.filter(x => x.id == model.radarrFolderId)[0]?.path;
model.sonarrRootFolderTitle = this.sonarrRootFolders?.filter(x => x.id == model.sonarrFolderId)[0]?.path;
model.sonarrQualityOverrideTitle = this.sonarrProfiles?.filter(x => x.id == model.sonarrPathId)[0]?.name;
model.sonarrLanguageProfileTitle = this.sonarrLanguageProfiles?.filter(x => x.id == model.sonarrLanguageId)[0]?.name;
this.dialogRef.close(model);
}
public async submitRequest() {
const model = this.form.value;
model.radarrQualityOverrideTitle = this.radarrProfiles?.filter((x) => x.id == model.radarrPathId)[0]?.name;
model.radarrRootFolderTitle = this.radarrRootFolders?.filter((x) => x.id == model.radarrFolderId)[0]?.path;
model.sonarrRootFolderTitle = this.sonarrRootFolders?.filter((x) => x.id == model.sonarrFolderId)[0]?.path;
model.sonarrQualityOverrideTitle = this.sonarrProfiles?.filter((x) => x.id == model.sonarrPathId)[0]?.name;
model.sonarrLanguageProfileTitle = this.sonarrLanguageProfiles?.filter((x) => x.id == model.sonarrLanguageId)[0]?.name;
this.dialogRef.close(model);
}
}

View file

@ -62,7 +62,7 @@ export class EpisodeRequestComponent {
});
if (this.data.isAdmin) {
const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.tvShow, id: this.data.series.id }, panelClass: 'modal-panel' });
const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.tvShow, id: this.data.series.id, is4k: null }, panelClass: 'modal-panel' });
dialog.afterClosed().subscribe(async (result) => {
if (result) {
viewModel.requestOnBehalf = result.username?.id;

View file

@ -18,18 +18,18 @@ namespace Ombi.Controllers.V1.External
public class RadarrController : ControllerBase
{
public RadarrController(IRadarrApi radarr, ISettingsService<RadarrSettings> settings,
ICacheService mem, IRadarrV3Api radarrV3Api)
public RadarrController(
ISettingsService<RadarrSettings> settings,
ISettingsService<Radarr4KSettings> radarr4kSettings,
IRadarrV3Api radarrV3Api)
{
_radarrApi = radarr;
_radarrSettings = settings;
_cache = mem;
_radarr4KSettings = radarr4kSettings;
_radarrV3Api = radarrV3Api;
}
private readonly IRadarrApi _radarrApi;
private readonly ISettingsService<RadarrSettings> _radarrSettings;
private readonly ICacheService _cache;
private readonly ISettingsService<Radarr4KSettings> _radarr4KSettings;
private readonly IRadarrV3Api _radarrV3Api;
/// <summary>
/// Gets the Radarr profiles.
@ -80,6 +80,23 @@ namespace Ombi.Controllers.V1.External
return null;
}
/// <summary>
/// Gets the Radarr 4K profiles using the saved settings
/// <remarks>The data is cached for an hour</remarks>
/// </summary>
/// <returns></returns>
[HttpGet("Profiles/4k")]
[PowerUser]
public async Task<IActionResult> GetProfiles4K()
{
var settings = await _radarr4KSettings.GetSettingsAsync();
if (settings.Enabled)
{
return Ok(await _radarrV3Api.GetProfiles(settings.ApiKey, settings.FullUri));
}
return null;
}
/// <summary>
/// Gets the Radarr root folders using the saved settings.
/// <remarks>The data is cached for an hour</remarks>
@ -97,6 +114,23 @@ namespace Ombi.Controllers.V1.External
return null;
}
/// <summary>
/// Gets the Radarr 4K root folders using the saved settings.
/// <remarks>The data is cached for an hour</remarks>
/// </summary>
/// <returns></returns>
[HttpGet("RootFolders/4k")]
[PowerUser]
public async Task<IEnumerable<RadarrRootFolder>> GetRootFolders4K()
{
var settings = await _radarr4KSettings.GetSettingsAsync();
if (settings.Enabled)
{
return await _radarrV3Api.GetRootFolders(settings.ApiKey, settings.FullUri);
}
return null;
}
/// <summary>
/// Gets the Radarr tags
/// </summary>