From 74a17773cfe48b932a29c59753d87bf7bd41d4d0 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 28 Jun 2018 21:37:51 +0100 Subject: [PATCH 001/111] Added some new assembly nothing is going on here... !wip --- src/Ombi.Api.Lidarr/LidarrApi.cs | 62 +++++++++++++++++++ src/Ombi.Api.Lidarr/Models/AlbumLookup.cs | 25 ++++++++ src/Ombi.Api.Lidarr/Models/Artist.cs | 25 ++++++++ src/Ombi.Api.Lidarr/Models/ArtistLookup.cs | 32 ++++++++++ src/Ombi.Api.Lidarr/Models/Image.cs | 8 +++ src/Ombi.Api.Lidarr/Models/LidarrProfile.cs | 31 ++++++++++ .../Models/LidarrRootFolder.cs | 11 ++++ src/Ombi.Api.Lidarr/Models/Link.cs | 8 +++ src/Ombi.Api.Lidarr/Models/Ratings.cs | 8 +++ src/Ombi.Api.Lidarr/Models/Statistics.cs | 12 ++++ src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj | 11 ++++ src/Ombi.sln | 9 ++- 12 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 src/Ombi.Api.Lidarr/LidarrApi.cs create mode 100644 src/Ombi.Api.Lidarr/Models/AlbumLookup.cs create mode 100644 src/Ombi.Api.Lidarr/Models/Artist.cs create mode 100644 src/Ombi.Api.Lidarr/Models/ArtistLookup.cs create mode 100644 src/Ombi.Api.Lidarr/Models/Image.cs create mode 100644 src/Ombi.Api.Lidarr/Models/LidarrProfile.cs create mode 100644 src/Ombi.Api.Lidarr/Models/LidarrRootFolder.cs create mode 100644 src/Ombi.Api.Lidarr/Models/Link.cs create mode 100644 src/Ombi.Api.Lidarr/Models/Ratings.cs create mode 100644 src/Ombi.Api.Lidarr/Models/Statistics.cs create mode 100644 src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj diff --git a/src/Ombi.Api.Lidarr/LidarrApi.cs b/src/Ombi.Api.Lidarr/LidarrApi.cs new file mode 100644 index 000000000..62b412fc1 --- /dev/null +++ b/src/Ombi.Api.Lidarr/LidarrApi.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Ombi.Api.Lidarr.Models; + +namespace Ombi.Api.Lidarr +{ + public class LidarrApi + { + public LidarrApi(ILogger logger, IApi api) + { + Api = api; + Logger = logger; + } + + private IApi Api { get; } + private ILogger Logger { get; } + + private const string ApiVersion = "/api/v1"; + + public async Task> GetProfiles(string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/profile", baseUrl, HttpMethod.Get); + + AddHeaders(request, apiKey); + return await Api.Request>(request); + } + + public async Task> GetRootFolders(string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/rootfolder", baseUrl, HttpMethod.Get); + + AddHeaders(request, apiKey); + return await Api.Request>(request); + } + + public async Task> ArtistLookup(string searchTerm, string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/Artist/lookup", baseUrl, HttpMethod.Get); + request.AddQueryString("term", searchTerm); + + AddHeaders(request, apiKey); + return await Api.Request>(request); + } + + public async Task> AlbumLookup(string searchTerm, string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/Album/lookup", baseUrl, HttpMethod.Get); + request.AddQueryString("term", searchTerm); + + AddHeaders(request, apiKey); + return await Api.Request>(request); + } + + private void AddHeaders(Request request, string key) + { + request.AddHeader("X-Api-Key", key); + } + } +} diff --git a/src/Ombi.Api.Lidarr/Models/AlbumLookup.cs b/src/Ombi.Api.Lidarr/Models/AlbumLookup.cs new file mode 100644 index 000000000..b2394eb5f --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/AlbumLookup.cs @@ -0,0 +1,25 @@ +using System; + +namespace Ombi.Api.Lidarr.Models +{ + public class AlbumLookup + { + public string title { get; set; } + public int artistId { get; set; } + public string foreignAlbumId { get; set; } + public bool monitored { get; set; } + public int profileId { get; set; } + public int duration { get; set; } + public string albumType { get; set; } + public string[] secondaryTypes { get; set; } + public int mediumCount { get; set; } + public Ratings ratings { get; set; } + public DateTime releaseDate { get; set; } + //public object[] releases { get; set; } + public object[] genres { get; set; } + //public object[] media { get; set; } + public Artist artist { get; set; } + public Image[] images { get; set; } + public string remoteCover { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Models/Artist.cs b/src/Ombi.Api.Lidarr/Models/Artist.cs new file mode 100644 index 000000000..bc6afc20e --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/Artist.cs @@ -0,0 +1,25 @@ +using System; + +namespace Ombi.Api.Lidarr.Models +{ + public class Artist + { + public string status { get; set; } + public bool ended { get; set; } + public string artistName { get; set; } + public string foreignArtistId { get; set; } + public int tadbId { get; set; } + public int discogsId { get; set; } + public object[] links { get; set; } + public object[] images { get; set; } + public int qualityProfileId { get; set; } + public int languageProfileId { get; set; } + public int metadataProfileId { get; set; } + public bool albumFolder { get; set; } + public bool monitored { get; set; } + public object[] genres { get; set; } + public object[] tags { get; set; } + public DateTime added { get; set; } + public Statistics statistics { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Models/ArtistLookup.cs b/src/Ombi.Api.Lidarr/Models/ArtistLookup.cs new file mode 100644 index 000000000..aa454c0a0 --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/ArtistLookup.cs @@ -0,0 +1,32 @@ +using System; +using System.Net.Mime; + +namespace Ombi.Api.Lidarr.Models +{ + public class ArtistLookup + { + public string status { get; set; } + public bool ended { get; set; } + public string artistName { get; set; } + public string foreignArtistId { get; set; } + public int tadbId { get; set; } + public int discogsId { get; set; } + public string overview { get; set; } + public string artistType { get; set; } + public string disambiguation { get; set; } + public Link[] links { get; set; } + public Image[] images { get; set; } + public string remotePoster { get; set; } + public int qualityProfileId { get; set; } + public int languageProfileId { get; set; } + public int metadataProfileId { get; set; } + public bool albumFolder { get; set; } + public bool monitored { get; set; } + public string cleanName { get; set; } + public string sortName { get; set; } + public object[] tags { get; set; } + public DateTime added { get; set; } + public Ratings ratings { get; set; } + public Statistics statistics { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Models/Image.cs b/src/Ombi.Api.Lidarr/Models/Image.cs new file mode 100644 index 000000000..172a13fe9 --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/Image.cs @@ -0,0 +1,8 @@ +namespace Ombi.Api.Lidarr.Models +{ + public class Image + { + public string coverType { get; set; } + public string url { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Models/LidarrProfile.cs b/src/Ombi.Api.Lidarr/Models/LidarrProfile.cs new file mode 100644 index 000000000..3dc436606 --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/LidarrProfile.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; + +namespace Ombi.Api.Lidarr.Models +{ + public class Cutoff + { + public int id { get; set; } + public string name { get; set; } + } + + public class Quality + { + public int id { get; set; } + public string name { get; set; } + } + + public class Item + { + public Quality quality { get; set; } + public bool allowed { get; set; } + } + + public class LidarrProfile +{ + public string name { get; set; } + public Cutoff cutoff { get; set; } + public List items { get; set; } + public string language { get; set; } + public int id { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Models/LidarrRootFolder.cs b/src/Ombi.Api.Lidarr/Models/LidarrRootFolder.cs new file mode 100644 index 000000000..a3a252f04 --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/LidarrRootFolder.cs @@ -0,0 +1,11 @@ +namespace Ombi.Api.Lidarr.Models +{ + public class LidarrRootFolder + { + public string path { get; set; } + public long freeSpace { get; set; } + public object[] unmappedFolders { get; set; } + public int id { get; set; } + } + +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Models/Link.cs b/src/Ombi.Api.Lidarr/Models/Link.cs new file mode 100644 index 000000000..492ac0426 --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/Link.cs @@ -0,0 +1,8 @@ +namespace Ombi.Api.Lidarr.Models +{ + public class Link + { + public string url { get; set; } + public string name { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Models/Ratings.cs b/src/Ombi.Api.Lidarr/Models/Ratings.cs new file mode 100644 index 000000000..8260e6676 --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/Ratings.cs @@ -0,0 +1,8 @@ +namespace Ombi.Api.Lidarr.Models +{ + public class Ratings + { + public int votes { get; set; } + public float value { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Models/Statistics.cs b/src/Ombi.Api.Lidarr/Models/Statistics.cs new file mode 100644 index 000000000..520ea747a --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/Statistics.cs @@ -0,0 +1,12 @@ +namespace Ombi.Api.Lidarr.Models +{ + public class Statistics + { + public int albumCount { get; set; } + public int trackFileCount { get; set; } + public int trackCount { get; set; } + public int totalTrackCount { get; set; } + public int sizeOnDisk { get; set; } + public int percentOfTracks { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj b/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj new file mode 100644 index 000000000..a3651df3c --- /dev/null +++ b/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/src/Ombi.sln b/src/Ombi.sln index ab9f8550c..1dfaa1dc6 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -92,7 +92,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Github", "Ombi.Api EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.SickRage", "Ombi.Api.SickRage\Ombi.Api.SickRage.csproj", "{94C9A366-2595-45EA-AABB-8E4A2E90EC5B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Notifications", "Ombi.Api.Notifications\Ombi.Api.Notifications.csproj", "{10D1FE9D-9124-42B7-B1E1-CEB99B832618}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Notifications", "Ombi.Api.Notifications\Ombi.Api.Notifications.csproj", "{10D1FE9D-9124-42B7-B1E1-CEB99B832618}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Lidarr", "Ombi.Api.Lidarr\Ombi.Api.Lidarr.csproj", "{4FA21A20-92F4-462C-B929-2C517A88CC56}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -244,6 +246,10 @@ Global {10D1FE9D-9124-42B7-B1E1-CEB99B832618}.Debug|Any CPU.Build.0 = Debug|Any CPU {10D1FE9D-9124-42B7-B1E1-CEB99B832618}.Release|Any CPU.ActiveCfg = Release|Any CPU {10D1FE9D-9124-42B7-B1E1-CEB99B832618}.Release|Any CPU.Build.0 = Release|Any CPU + {4FA21A20-92F4-462C-B929-2C517A88CC56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4FA21A20-92F4-462C-B929-2C517A88CC56}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FA21A20-92F4-462C-B929-2C517A88CC56}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4FA21A20-92F4-462C-B929-2C517A88CC56}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -279,6 +285,7 @@ Global {55866DEE-46D1-4AF7-B1A2-62F6190C8EC7} = {9293CA11-360A-4C20-A674-B9E794431BF5} {94C9A366-2595-45EA-AABB-8E4A2E90EC5B} = {9293CA11-360A-4C20-A674-B9E794431BF5} {10D1FE9D-9124-42B7-B1E1-CEB99B832618} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {4FA21A20-92F4-462C-B929-2C517A88CC56} = {9293CA11-360A-4C20-A674-B9E794431BF5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869} From 2eec6c9c307c2508f5383268e3db51036dbddde6 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 28 Jun 2018 21:43:48 +0100 Subject: [PATCH 002/111] Nothing to see here. Move along !wip #2313 --- .../Models/External/LidarrSettings.cs | 12 ++ .../ClientApp/app/interfaces/ISettings.ts | 8 ++ .../app/services/settings.service.ts | 8 ++ .../app/settings/lidarr/lidarr.component.html | 101 +++++++++++++++ .../app/settings/lidarr/lidarr.component.ts | 117 ++++++++++++++++++ .../ClientApp/app/settings/settings.module.ts | 3 + src/Ombi/Controllers/SettingsController.cs | 21 ++++ 7 files changed, 270 insertions(+) create mode 100644 src/Ombi.Settings/Settings/Models/External/LidarrSettings.cs create mode 100644 src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html create mode 100644 src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts diff --git a/src/Ombi.Settings/Settings/Models/External/LidarrSettings.cs b/src/Ombi.Settings/Settings/Models/External/LidarrSettings.cs new file mode 100644 index 000000000..560a6e2d2 --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/External/LidarrSettings.cs @@ -0,0 +1,12 @@ +using Ombi.Core.Settings.Models.External; + +namespace Ombi.Settings.Settings.Models.External +{ + public class LidarrSettings : ExternalSettings + { + public bool Enabled { get; set; } + public string ApiKey { get; set; } + public string DefaultQualityProfile { get; set; } + public string DefaultRootPath { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index dc1825c83..1495413da 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -83,6 +83,14 @@ export interface IRadarrSettings extends IExternalSettings { minimumAvailability: string; } +export interface ILidarrSettings extends IExternalSettings { + enabled: boolean; + apiKey: string; + defaultQualityProfile: string; + defaultRootPath: string; + fullRootPath: string; +} + export interface ILandingPageSettings extends ISettings { enabled: boolean; diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index 726c86d63..51bf149ed 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -91,6 +91,14 @@ export class SettingsService extends ServiceHelpers { return this.http.post(`${this.url}/Radarr`, JSON.stringify(settings), {headers: this.headers}); } + public getLidarr(): Observable { + return this.http.get(`${this.url}/Lidarr`, {headers: this.headers}); + } + + public saveLidarr(settings: ILidarrSettings): Observable { + return this.http.post(`${this.url}/Lidarr`, JSON.stringify(settings), {headers: this.headers}); + } + public getAuthentication(): Observable { return this.http.get(`${this.url}/Authentication`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html new file mode 100644 index 000000000..d36295038 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html @@ -0,0 +1,101 @@ + + +
+
+ Lidarr Settings +
+
+
+
+ + +
+
+ + + +
+ + + + The IP/Hostname is required +
+ +
+ + + + The Port is required +
+ + +
+ + + + The API Key is required +
+
+
+ + + +
+
+
+ +
+ +
+
+
+
+
+
+ +
+
+
+ +
+ +
+ A Default Quality Profile is required +
+ +
+
+ + +
+ +
+
+ +
+ +
+ A Default Root Path is required +
+ + +
+
+ +
+
+ + +
+
+ +
+
+
+
+
+
diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts new file mode 100644 index 000000000..7e5571f14 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts @@ -0,0 +1,117 @@ +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; + +import { ILidarrSettings, IMinimumAvailability, IRadarrProfile, IRadarrRootFolder } from "../../interfaces"; +import { IRadarrSettings } from "../../interfaces"; +import { RadarrService } from "../../services"; +import { TesterService } from "../../services"; +import { NotificationService } from "../../services"; +import { SettingsService } from "../../services"; + +@Component({ + templateUrl: "./Lidarr.component.html", +}) +export class LidarrComponent implements OnInit { + + public qualities: IRadarrProfile[]; + public rootFolders: IRadarrRootFolder[]; + public minimumAvailabilityOptions: IMinimumAvailability[]; + public profilesRunning: boolean; + public rootFoldersRunning: boolean; + public advanced = false; + public form: FormGroup; + + constructor(private settingsService: SettingsService, + private radarrService: RadarrService, + private notificationService: NotificationService, + private fb: FormBuilder, + private testerService: TesterService) { } + + public ngOnInit() { + this.settingsService.getLidarr() + .subscribe(x => { + + this.form = this.fb.group({ + enabled: [x.enabled], + apiKey: [x.apiKey, [Validators.required]], + defaultQualityProfile: [x.defaultQualityProfile, [Validators.required]], + defaultRootPath: [x.defaultRootPath, [Validators.required]], + ssl: [x.ssl], + subDir: [x.subDir], + ip: [x.ip, [Validators.required]], + port: [x.port, [Validators.required]], + }); + + if (x.defaultQualityProfile) { + this.getProfiles(this.form); + } + if (x.defaultRootPath) { + this.getRootFolders(this.form); + } + }); + + this.qualities = []; + this.qualities.push({ name: "Please Select", id: -1 }); + + this.rootFolders = []; + this.rootFolders.push({ path: "Please Select", id: -1 }); + } + + public getProfiles(form: FormGroup) { + this.profilesRunning = true; + this.radarrService.getQualityProfiles(form.value).subscribe(x => { + this.qualities = x; + this.qualities.unshift({ name: "Please Select", id: -1 }); + + this.profilesRunning = false; + this.notificationService.success("Successfully retrieved the Quality Profiles"); + }); + } + + public getRootFolders(form: FormGroup) { + this.rootFoldersRunning = true; + this.radarrService.getRootFolders(form.value).subscribe(x => { + this.rootFolders = x; + this.rootFolders.unshift({ path: "Please Select", id: -1 }); + + this.rootFoldersRunning = false; + this.notificationService.success("Successfully retrieved the Root Folders"); + }); + } + + public test(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + const settings = form.value; + this.testerService.radarrTest(settings).subscribe(x => { + if (x === true) { + this.notificationService.success("Successfully connected to Lidarr!"); + } else { + this.notificationService.error("We could not connect to Lidarr!"); + } + }); + } + +public onSubmit(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + if(form.controls.defaultQualityProfile.value === "-1" || form.controls.defaultRootPath.value === "Please Select") { + this.notificationService.error("Please check your entered values"); + return; + } + + const settings = form.value; + this.settingsService.saveLidarr(settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved Lidarr settings"); + } else { + this.notificationService.success("There was an error when saving the Lidarr settings"); + } + }); + + } +} diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 0069cf262..44c1455f0 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -34,6 +34,7 @@ import { TelegramComponent } from "./notifications/telegram.component"; import { OmbiComponent } from "./ombi/ombi.component"; import { PlexComponent } from "./plex/plex.component"; import { RadarrComponent } from "./radarr/radarr.component"; +import { LidarrComponent } from "./lidarr/lidarr.component"; import { SickRageComponent } from "./sickrage/sickrage.component"; import { SonarrComponent } from "./sonarr/sonarr.component"; import { UpdateComponent } from "./update/update.component"; @@ -71,6 +72,7 @@ const routes: Routes = [ { path: "Mobile", component: MobileComponent, canActivate: [AuthGuard] }, { path: "MassEmail", component: MassEmailComponent, canActivate: [AuthGuard] }, { path: "Newsletter", component: NewsletterComponent, canActivate: [AuthGuard] }, + { path: "Lidarr", component: LidarrComponent, canActivate: [AuthGuard] }, ]; @NgModule({ @@ -122,6 +124,7 @@ const routes: Routes = [ MobileComponent, MassEmailComponent, NewsletterComponent, + LidarrComponent, ], exports: [ RouterModule, diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 895621ad3..6c2e7475f 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -301,6 +301,27 @@ namespace Ombi.Controllers return await Get(); } + /// + /// Gets the Lidarr Settings. + /// + /// + [HttpGet("lidarr")] + public async Task LidarrSettings() + { + return await Get(); + } + + /// + /// Save the Lidarr settings. + /// + /// The settings. + /// + [HttpPost("sonarr")] + public async Task LidarrSettings([FromBody]LidarrSettings settings) + { + return await Save(settings); + } + /// /// Save the Authentication settings. /// From ce79fec216005a18e8ea109b712ab25ab95ccbcf Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 21 Aug 2018 13:55:24 +0100 Subject: [PATCH 003/111] Stript out certain characters when sending a pushover message #2385 --- src/Ombi.Core.Tests/Ombi.Core.Tests.csproj | 8 +++--- src/Ombi.Core.Tests/StringHelperTests.cs | 26 +++++++++++++++++++ src/Ombi.Helpers/StringHelper.cs | 5 ++++ .../Agents/PushoverNotification.cs | 3 ++- 4 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 src/Ombi.Core.Tests/StringHelperTests.cs diff --git a/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj index 8f0abee8f..30de4b6f0 100644 --- a/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj +++ b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj @@ -5,10 +5,10 @@ - - - - + + + + diff --git a/src/Ombi.Core.Tests/StringHelperTests.cs b/src/Ombi.Core.Tests/StringHelperTests.cs new file mode 100644 index 000000000..c1b95fcd7 --- /dev/null +++ b/src/Ombi.Core.Tests/StringHelperTests.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +using NUnit.Framework; +using Ombi.Helpers; + +namespace Ombi.Core.Tests +{ + [TestFixture] + public class StringHelperTests + { + [TestCaseSource(nameof(StripCharsData))] + public string StripCharacters(string str, char[] chars) + { + return str.StripCharacters(chars); + } + + private static IEnumerable StripCharsData + { + get + { + yield return new TestCaseData("this!is^a*string",new []{'!','^','*'}).Returns("thisisastring").SetName("Basic Strip Multipe Chars"); + yield return new TestCaseData("What is this madness'",new []{'\'','^','*'}).Returns("What is this madness").SetName("Basic Strip Multipe Chars"); + } + } + } +} \ No newline at end of file diff --git a/src/Ombi.Helpers/StringHelper.cs b/src/Ombi.Helpers/StringHelper.cs index aba120c65..2dad81015 100644 --- a/src/Ombi.Helpers/StringHelper.cs +++ b/src/Ombi.Helpers/StringHelper.cs @@ -75,5 +75,10 @@ namespace Ombi.Helpers return -1; } + + public static string StripCharacters(this string str, params char[] chars) + { + return string.Concat(str.Where(c => !chars.Contains(c))); + } } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/PushoverNotification.cs b/src/Ombi.Notifications/Agents/PushoverNotification.cs index 5b82eb8a3..72af001dc 100644 --- a/src/Ombi.Notifications/Agents/PushoverNotification.cs +++ b/src/Ombi.Notifications/Agents/PushoverNotification.cs @@ -177,7 +177,8 @@ namespace Ombi.Notifications.Agents { try { - await Api.PushAsync(settings.AccessToken, model.Message, settings.UserToken); + //&+' < > + await Api.PushAsync(settings.AccessToken, model.Message.StripCharacters('&','+','<','>'), settings.UserToken); } catch (Exception e) { From eb1c2a695995b3192a9bd76596214b0aa102b426 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 22 Aug 2018 14:01:50 +0100 Subject: [PATCH 004/111] !wip added the lidarr settings ui --- src/Ombi.Api.Lidarr/ILidarrApi.cs | 14 ++ src/Ombi.Api.Lidarr/LidarrApi.cs | 2 +- src/Ombi.DependencyInjection/IocExtensions.cs | 2 + .../Ombi.DependencyInjection.csproj | 1 + src/Ombi.Helpers/CacheKeys.cs | 2 + src/Ombi/ClientApp/app/interfaces/IIssues.ts | 2 +- src/Ombi/ClientApp/app/interfaces/ILidarr.ts | 9 + src/Ombi/ClientApp/app/interfaces/IUser.ts | 2 +- src/Ombi/ClientApp/app/interfaces/index.ts | 1 + .../app/issues/issuestable.component.ts | 2 +- .../recentlyAdded/recentlyAdded.component.ts | 2 +- .../app/requests/request.component.ts | 4 +- .../app/requests/tvrequests.component.ts | 2 +- .../search/music/musicsearch.component.html | 118 ++++++++++ .../app/search/music/musicsearch.component.ts | 214 ++++++++++++++++++ .../ClientApp/app/search/search.component.ts | 4 +- .../app/services/applications/index.ts | 1 + .../services/applications/lidarr.service.ts | 29 +++ .../ClientApp/app/services/mobile.service.ts | 2 +- .../services/notificationMessage.service.ts | 2 +- .../app/services/recentlyAdded.service.ts | 2 +- .../ClientApp/app/services/search.service.ts | 4 + .../app/services/settings.service.ts | 1 + .../app/settings/jobs/jobs.component.ts | 2 +- .../notifications/newsletter.component.ts | 2 +- .../ClientApp/app/settings/settings.module.ts | 5 +- .../app/settings/settingsmenu.component.html | 9 + .../app/shared/issues-report.component.ts | 4 +- .../app/wizard/plex/plexoauth.component.ts | 2 +- .../Controllers/External/LidarrController.cs | 91 ++++++++ .../Controllers/External/RadarrController.cs | 4 +- src/Ombi/Ombi.csproj | 1 + 32 files changed, 520 insertions(+), 22 deletions(-) create mode 100644 src/Ombi.Api.Lidarr/ILidarrApi.cs create mode 100644 src/Ombi/ClientApp/app/interfaces/ILidarr.ts create mode 100644 src/Ombi/ClientApp/app/search/music/musicsearch.component.html create mode 100644 src/Ombi/ClientApp/app/search/music/musicsearch.component.ts create mode 100644 src/Ombi/ClientApp/app/services/applications/lidarr.service.ts create mode 100644 src/Ombi/Controllers/External/LidarrController.cs diff --git a/src/Ombi.Api.Lidarr/ILidarrApi.cs b/src/Ombi.Api.Lidarr/ILidarrApi.cs new file mode 100644 index 000000000..6732693db --- /dev/null +++ b/src/Ombi.Api.Lidarr/ILidarrApi.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Api.Lidarr.Models; + +namespace Ombi.Api.Lidarr +{ + public interface ILidarrApi + { + Task> AlbumLookup(string searchTerm, string apiKey, string baseUrl); + Task> ArtistLookup(string searchTerm, string apiKey, string baseUrl); + Task> GetProfiles(string apiKey, string baseUrl); + Task> GetRootFolders(string apiKey, string baseUrl); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/LidarrApi.cs b/src/Ombi.Api.Lidarr/LidarrApi.cs index 62b412fc1..2becb57aa 100644 --- a/src/Ombi.Api.Lidarr/LidarrApi.cs +++ b/src/Ombi.Api.Lidarr/LidarrApi.cs @@ -7,7 +7,7 @@ using Ombi.Api.Lidarr.Models; namespace Ombi.Api.Lidarr { - public class LidarrApi + public class LidarrApi : ILidarrApi { public LidarrApi(ILogger logger, IApi api) { diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 2644fa9c7..d0a56bbcd 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -32,6 +32,7 @@ using Ombi.Api.CouchPotato; using Ombi.Api.DogNzb; using Ombi.Api.FanartTv; using Ombi.Api.Github; +using Ombi.Api.Lidarr; using Ombi.Api.Mattermost; using Ombi.Api.Notifications; using Ombi.Api.Pushbullet; @@ -117,6 +118,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } public static void RegisterStore(this IServiceCollection services) { diff --git a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj index 2e7f984a7..6fe083fe3 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -21,6 +21,7 @@ + diff --git a/src/Ombi.Helpers/CacheKeys.cs b/src/Ombi.Helpers/CacheKeys.cs index e6c482f7b..f7a40d321 100644 --- a/src/Ombi.Helpers/CacheKeys.cs +++ b/src/Ombi.Helpers/CacheKeys.cs @@ -18,6 +18,8 @@ namespace Ombi.Helpers public const string NowPlayingMovies = nameof(NowPlayingMovies); public const string RadarrRootProfiles = nameof(RadarrRootProfiles); public const string RadarrQualityProfiles = nameof(RadarrQualityProfiles); + public const string LidarrRootFolders = nameof(LidarrRootFolders); + public const string LidarrQualityProfiles = nameof(LidarrQualityProfiles); public const string FanartTv = nameof(FanartTv); } } diff --git a/src/Ombi/ClientApp/app/interfaces/IIssues.ts b/src/Ombi/ClientApp/app/interfaces/IIssues.ts index cd2ad53a6..dce9882ec 100644 --- a/src/Ombi/ClientApp/app/interfaces/IIssues.ts +++ b/src/Ombi/ClientApp/app/interfaces/IIssues.ts @@ -1,4 +1,4 @@ -import { IIssueCategory, IUser, RequestType } from "./"; +import { IIssueCategory, IUser, RequestType } from "."; export interface IIssues { id?: number; diff --git a/src/Ombi/ClientApp/app/interfaces/ILidarr.ts b/src/Ombi/ClientApp/app/interfaces/ILidarr.ts new file mode 100644 index 000000000..2674a7dac --- /dev/null +++ b/src/Ombi/ClientApp/app/interfaces/ILidarr.ts @@ -0,0 +1,9 @@ +export interface ILidarrRootFolder { + id: number; + path: string; +} + +export interface ILidarrProfile { + name: string; + id: number; +} diff --git a/src/Ombi/ClientApp/app/interfaces/IUser.ts b/src/Ombi/ClientApp/app/interfaces/IUser.ts index 0e8141b52..cd96848fb 100644 --- a/src/Ombi/ClientApp/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/app/interfaces/IUser.ts @@ -1,4 +1,4 @@ -import { ICheckbox } from "./index"; +import { ICheckbox } from "."; export interface IUser { id: string; diff --git a/src/Ombi/ClientApp/app/interfaces/index.ts b/src/Ombi/ClientApp/app/interfaces/index.ts index 538e1bd95..013d4278d 100644 --- a/src/Ombi/ClientApp/app/interfaces/index.ts +++ b/src/Ombi/ClientApp/app/interfaces/index.ts @@ -14,3 +14,4 @@ export * from "./ISonarr"; export * from "./IUser"; export * from "./IIssues"; export * from "./IRecentlyAdded"; +export * from "./ILidarr"; diff --git a/src/Ombi/ClientApp/app/issues/issuestable.component.ts b/src/Ombi/ClientApp/app/issues/issuestable.component.ts index 5df8a35bd..aadfd546a 100644 --- a/src/Ombi/ClientApp/app/issues/issuestable.component.ts +++ b/src/Ombi/ClientApp/app/issues/issuestable.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; -import { IIssues, IPagenator, IssueStatus } from "./../interfaces"; +import { IIssues, IPagenator, IssueStatus } from "../interfaces"; @Component({ selector: "issues-table", diff --git a/src/Ombi/ClientApp/app/recentlyAdded/recentlyAdded.component.ts b/src/Ombi/ClientApp/app/recentlyAdded/recentlyAdded.component.ts index 303e530e1..d2120cdcf 100644 --- a/src/Ombi/ClientApp/app/recentlyAdded/recentlyAdded.component.ts +++ b/src/Ombi/ClientApp/app/recentlyAdded/recentlyAdded.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from "@angular/core"; import { NguCarouselConfig } from "@ngu/carousel"; import { ImageService, RecentlyAddedService } from "../services"; -import { IRecentlyAddedMovies, IRecentlyAddedTvShows } from "./../interfaces"; +import { IRecentlyAddedMovies, IRecentlyAddedTvShows } from "../interfaces"; @Component({ templateUrl: "recentlyAdded.component.html", diff --git a/src/Ombi/ClientApp/app/requests/request.component.ts b/src/Ombi/ClientApp/app/requests/request.component.ts index 08df3f2be..557bb7a07 100644 --- a/src/Ombi/ClientApp/app/requests/request.component.ts +++ b/src/Ombi/ClientApp/app/requests/request.component.ts @@ -1,8 +1,8 @@  import { Component, OnInit } from "@angular/core"; -import { IIssueCategory } from "./../interfaces"; -import { IssuesService, SettingsService } from "./../services"; +import { IIssueCategory } from "../interfaces"; +import { IssuesService, SettingsService } from "../services"; @Component({ templateUrl: "./request.component.html", diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts index 6a17066d7..144de0206 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts @@ -7,7 +7,7 @@ import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { AuthService } from "../auth/auth.service"; import { FilterType, IIssueCategory, IPagenator, IRequestsViewModel, ISonarrProfile, ISonarrRootFolder, ITvRequests, OrderType } from "../interfaces"; import { NotificationService, RequestService, SonarrService } from "../services"; -import { ImageService } from "./../services/image.service"; +import { ImageService } from "../services/image.service"; @Component({ selector: "tv-requests", diff --git a/src/Ombi/ClientApp/app/search/music/musicsearch.component.html b/src/Ombi/ClientApp/app/search/music/musicsearch.component.html new file mode 100644 index 000000000..44dc345bc --- /dev/null +++ b/src/Ombi/ClientApp/app/search/music/musicsearch.component.html @@ -0,0 +1,118 @@ + +
+ +
+
+ +
+
+
+
+ +
+ +
+ +
+
+
+ poster + +
+
+
+ +

{{result.title}} ({{result.releaseDate | date: 'yyyy'}})

+
+ + {{ 'Search.TheatricalRelease' | translate: {date: result.releaseDate | date: 'mediumDate'} }} + {{ 'Search.DigitalDate' | translate: {date: result.digitalReleaseDate | date: 'mediumDate'} }} + + + + + {{result.quality}}p + + + + + + + + + +
+
+

{{result.overview}}

+
+ + +
+
+
+ + + +
+
+
+ +
+
+
+ + + + + + +
+ + +
+ + + +
+ +
+
+
+
+ +
+
+ + + diff --git a/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts b/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts new file mode 100644 index 000000000..38f02eb8b --- /dev/null +++ b/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts @@ -0,0 +1,214 @@ +import { PlatformLocation } from "@angular/common"; +import { Component, Input, OnInit } from "@angular/core"; +import { DomSanitizer } from "@angular/platform-browser"; +import { TranslateService } from "@ngx-translate/core"; +import { Subject } from "rxjs"; +import { debounceTime, distinctUntilChanged } from "rxjs/operators"; + +import { AuthService } from "../auth/auth.service"; +import { IIssueCategory, IRequestEngineResult, ISearchMovieResult } from "../interfaces"; +import { NotificationService, RequestService, SearchService } from "../services"; + +@Component({ + selector: "music-search", + templateUrl: "./music.component.html", +}) +export class MusicSearchComponent implements OnInit { + + public searchText: string; + public searchChanged: Subject = new Subject(); + public movieResults: ISearchMovieResult[]; + public result: IRequestEngineResult; + public searchApplied = false; + + @Input() public issueCategories: IIssueCategory[]; + @Input() public issuesEnabled: boolean; + public issuesBarVisible = false; + public issueRequestTitle: string; + public issueRequestId: number; + public issueProviderId: string; + public issueCategorySelected: IIssueCategory; + public defaultPoster: string; + + constructor( + private searchService: SearchService, private requestService: RequestService, + private notificationService: NotificationService, private authService: AuthService, + private readonly translate: TranslateService, private sanitizer: DomSanitizer, + private readonly platformLocation: PlatformLocation) { + + this.searchChanged.pipe( + debounceTime(600), // Wait Xms after the last event before emitting last event + distinctUntilChanged(), // only emit if value is different from previous value + ).subscribe(x => { + this.searchText = x as string; + if (this.searchText === "") { + this.clearResults(); + return; + } + this.searchService.searchMusic(this.searchText) + .subscribe(x => { + this.movieResults = x; + this.searchApplied = true; + // Now let's load some extra info including IMDB Id + // This way the search is fast at displaying results. + this.getExtraInfo(); + }); + }); + this.defaultPoster = "../../../images/default_movie_poster.png"; + const base = this.platformLocation.getBaseHrefFromDOM(); + if (base) { + this.defaultPoster = "../../.." + base + "/images/default_movie_poster.png"; + } + } + + public ngOnInit() { + this.searchText = ""; + this.movieResults = []; + this.result = { + message: "", + result: false, + errorMessage: "", + }; + this.popularMovies(); + } + + public search(text: any) { + this.searchChanged.next(text.target.value); + } + + public request(searchResult: ISearchMovieResult) { + searchResult.requested = true; + searchResult.requestProcessing = true; + searchResult.showSubscribe = false; + if (this.authService.hasRole("admin") || this.authService.hasRole("AutoApproveMovie")) { + searchResult.approved = true; + } + + try { + this.requestService.requestMovie({ theMovieDbId: searchResult.id }) + .subscribe(x => { + this.result = x; + + if (this.result.result) { + this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => { + this.notificationService.success(x); + searchResult.processed = true; + }); + } else { + if (this.result.errorMessage && this.result.message) { + this.notificationService.warning("Request Added", `${this.result.message} - ${this.result.errorMessage}`); + } else { + this.notificationService.warning("Request Added", this.result.message ? this.result.message : this.result.errorMessage); + } + searchResult.requested = false; + searchResult.approved = false; + searchResult.processed = false; + searchResult.requestProcessing = false; + + } + }); + } catch (e) { + + searchResult.processed = false; + searchResult.requestProcessing = false; + this.notificationService.error(e); + } + } + + public popularMovies() { + this.clearResults(); + this.searchService.popularMovies() + .subscribe(x => { + this.movieResults = x; + this.getExtraInfo(); + }); + } + public nowPlayingMovies() { + this.clearResults(); + this.searchService.nowPlayingMovies() + .subscribe(x => { + this.movieResults = x; + this.getExtraInfo(); + }); + } + public topRatedMovies() { + this.clearResults(); + this.searchService.topRatedMovies() + .subscribe(x => { + this.movieResults = x; + this.getExtraInfo(); + }); + } + public upcomingMovies() { + this.clearResults(); + this.searchService.upcomingMovies() + .subscribe(x => { + this.movieResults = x; + this.getExtraInfo(); + }); + } + + public reportIssue(catId: IIssueCategory, req: ISearchMovieResult) { + this.issueRequestId = req.id; + this.issueRequestTitle = req.title + `(${req.releaseDate.getFullYear})`; + this.issueCategorySelected = catId; + this.issuesBarVisible = true; + this.issueProviderId = req.id.toString(); + } + + public similarMovies(theMovieDbId: number) { + this.clearResults(); + this.searchService.similarMovies(theMovieDbId) + .subscribe(x => { + this.movieResults = x; + this.getExtraInfo(); + }); + } + + public subscribe(r: ISearchMovieResult) { + r.subscribed = true; + this.requestService.subscribeToMovie(r.requestId) + .subscribe(x => { + this.notificationService.success("Subscribed To Movie!"); + }); + } + + public unSubscribe(r: ISearchMovieResult) { + r.subscribed = false; + this.requestService.unSubscribeToMovie(r.requestId) + .subscribe(x => { + this.notificationService.success("Unsubscribed Movie!"); + }); + } + + private getExtraInfo() { + + this.movieResults.forEach((val, index) => { + if (val.posterPath === null) { + val.posterPath = this.defaultPoster; + } else { + val.posterPath = "https://image.tmdb.org/t/p/w300/" + val.posterPath; + } + val.background = this.sanitizer.bypassSecurityTrustStyle + ("url(" + "https://image.tmdb.org/t/p/w1280" + val.backdropPath + ")"); + this.searchService.getMovieInformation(val.id) + .subscribe(m => { + this.updateItem(val, m); + }); + }); + } + + private updateItem(key: ISearchMovieResult, updated: ISearchMovieResult) { + const index = this.movieResults.indexOf(key, 0); + if (index > -1) { + const copy = { ...this.movieResults[index] }; + this.movieResults[index] = updated; + this.movieResults[index].background = copy.background; + this.movieResults[index].posterPath = copy.posterPath; + } + } + private clearResults() { + this.movieResults = []; + this.searchApplied = false; + } +} diff --git a/src/Ombi/ClientApp/app/search/search.component.ts b/src/Ombi/ClientApp/app/search/search.component.ts index f583266ee..4f1c6c3ad 100644 --- a/src/Ombi/ClientApp/app/search/search.component.ts +++ b/src/Ombi/ClientApp/app/search/search.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from "@angular/core"; -import { IIssueCategory } from "./../interfaces"; -import { IssuesService, SettingsService } from "./../services"; +import { IIssueCategory } from "../interfaces"; +import { IssuesService, SettingsService } from "../services"; @Component({ templateUrl: "./search.component.html", diff --git a/src/Ombi/ClientApp/app/services/applications/index.ts b/src/Ombi/ClientApp/app/services/applications/index.ts index 9fe4a5403..295a53415 100644 --- a/src/Ombi/ClientApp/app/services/applications/index.ts +++ b/src/Ombi/ClientApp/app/services/applications/index.ts @@ -6,3 +6,4 @@ export * from "./sonarr.service"; export * from "./tester.service"; export * from "./plexoauth.service"; export * from "./plextv.service"; +export * from "./lidarr.service"; diff --git a/src/Ombi/ClientApp/app/services/applications/lidarr.service.ts b/src/Ombi/ClientApp/app/services/applications/lidarr.service.ts new file mode 100644 index 000000000..ddd7e48ec --- /dev/null +++ b/src/Ombi/ClientApp/app/services/applications/lidarr.service.ts @@ -0,0 +1,29 @@ +import { PlatformLocation } from "@angular/common"; +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { Observable } from "rxjs"; + +import { ILidarrProfile, ILidarrRootFolder } from "../../interfaces"; +import { ILidarrSettings } from "../../interfaces"; +import { ServiceHelpers } from "../service.helpers"; + +@Injectable() +export class LidarrService extends ServiceHelpers { + constructor(http: HttpClient, public platformLocation: PlatformLocation) { + super(http, "/api/v1/Lidarr", platformLocation); + } + + public getRootFolders(settings: ILidarrSettings): Observable { + return this.http.post(`${this.url}/RootFolders/`, JSON.stringify(settings), {headers: this.headers}); + } + public getQualityProfiles(settings: ILidarrSettings): Observable { + return this.http.post(`${this.url}/Profiles/`, JSON.stringify(settings), {headers: this.headers}); + } + + public getRootFoldersFromSettings(): Observable { + return this.http.get(`${this.url}/RootFolders/`, {headers: this.headers}); + } + public getQualityProfilesFromSettings(): Observable { + return this.http.get(`${this.url}/Profiles/`, {headers: this.headers}); + } +} diff --git a/src/Ombi/ClientApp/app/services/mobile.service.ts b/src/Ombi/ClientApp/app/services/mobile.service.ts index 29cf5f609..1f9e3fb24 100644 --- a/src/Ombi/ClientApp/app/services/mobile.service.ts +++ b/src/Ombi/ClientApp/app/services/mobile.service.ts @@ -4,7 +4,7 @@ import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { IMobileUsersViewModel } from "./../interfaces"; +import { IMobileUsersViewModel } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @Injectable() diff --git a/src/Ombi/ClientApp/app/services/notificationMessage.service.ts b/src/Ombi/ClientApp/app/services/notificationMessage.service.ts index 1e4603689..93727c5d2 100644 --- a/src/Ombi/ClientApp/app/services/notificationMessage.service.ts +++ b/src/Ombi/ClientApp/app/services/notificationMessage.service.ts @@ -4,7 +4,7 @@ import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { IMassEmailModel } from "./../interfaces"; +import { IMassEmailModel } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; diff --git a/src/Ombi/ClientApp/app/services/recentlyAdded.service.ts b/src/Ombi/ClientApp/app/services/recentlyAdded.service.ts index 18e24470c..c062f973b 100644 --- a/src/Ombi/ClientApp/app/services/recentlyAdded.service.ts +++ b/src/Ombi/ClientApp/app/services/recentlyAdded.service.ts @@ -4,7 +4,7 @@ import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { IRecentlyAddedMovies, IRecentlyAddedTvShows } from "./../interfaces"; +import { IRecentlyAddedMovies, IRecentlyAddedTvShows } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @Injectable() diff --git a/src/Ombi/ClientApp/app/services/search.service.ts b/src/Ombi/ClientApp/app/services/search.service.ts index 4454bda0a..e0da44613 100644 --- a/src/Ombi/ClientApp/app/services/search.service.ts +++ b/src/Ombi/ClientApp/app/services/search.service.ts @@ -68,4 +68,8 @@ export class SearchService extends ServiceHelpers { public trendingTv(): Observable { return this.http.get(`${this.url}/Tv/trending`, {headers: this.headers}); } + // Music + public searchMusic(searchTerm: string): Observable { + return this.http.get(`${this.url}/Music/` + searchTerm); + } } diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index d912d03ff..2016d10b7 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -18,6 +18,7 @@ import { IJobSettings, IJobSettingsViewModel, ILandingPageSettings, + ILidarrSettings, IMattermostNotifcationSettings, IMobileNotifcationSettings, INewsletterNotificationSettings, diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts index d0a7a8b83..c69d07731 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts @@ -3,7 +3,7 @@ import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { NotificationService, SettingsService } from "../../services"; -import { ICronTestModel } from "./../../interfaces"; +import { ICronTestModel } from "../../interfaces"; @Component({ templateUrl: "./jobs.component.html", diff --git a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts index 06ed6617a..eae7176e2 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts +++ b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts @@ -2,7 +2,7 @@ import { INewsletterNotificationSettings, NotificationType } from "../../interfaces"; import { JobService, NotificationService, SettingsService } from "../../services"; -import { TesterService } from "./../../services/applications/tester.service"; +import { TesterService } from "../../services/applications/tester.service"; @Component({ templateUrl: "./newsletter.component.html", diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 6ba7e3f52..f102a03fe 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -8,7 +8,7 @@ import { ClipboardModule } from "ngx-clipboard"; import { AuthGuard } from "../auth/auth.guard"; import { AuthService } from "../auth/auth.service"; import { - CouchPotatoService, EmbyService, IssuesService, JobService, MobileService, NotificationMessageService, PlexService, RadarrService, + CouchPotatoService, EmbyService, IssuesService, JobService, LidarrService, MobileService, NotificationMessageService, PlexService, RadarrService, SonarrService, TesterService, ValidationService, } from "../services"; @@ -22,6 +22,7 @@ import { EmbyComponent } from "./emby/emby.component"; import { IssuesComponent } from "./issues/issues.component"; import { JobsComponent } from "./jobs/jobs.component"; import { LandingPageComponent } from "./landingpage/landingpage.component"; +import { LidarrComponent } from "./lidarr/lidarr.component"; import { MassEmailComponent } from "./massemail/massemail.component"; import { DiscordComponent } from "./notifications/discord.component"; import { EmailNotificationComponent } from "./notifications/emailnotification.component"; @@ -36,7 +37,6 @@ import { TelegramComponent } from "./notifications/telegram.component"; import { OmbiComponent } from "./ombi/ombi.component"; import { PlexComponent } from "./plex/plex.component"; import { RadarrComponent } from "./radarr/radarr.component"; -import { LidarrComponent } from "./lidarr/lidarr.component"; import { SickRageComponent } from "./sickrage/sickrage.component"; import { SonarrComponent } from "./sonarr/sonarr.component"; import { UpdateComponent } from "./update/update.component"; @@ -145,6 +145,7 @@ const routes: Routes = [ EmbyService, MobileService, NotificationMessageService, + LidarrService, ], }) diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index 6c6bb5c3f..a3e5a16e7 100644 --- a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html @@ -48,6 +48,15 @@ + +
  • {{ 'Search.TvTab' | translate }}
  • +
  • + {{ 'Search.MusicTab' | translate }} +
  • @@ -25,6 +28,9 @@
    +
    + +
    diff --git a/src/Ombi/ClientApp/app/search/search.component.ts b/src/Ombi/ClientApp/app/search/search.component.ts index 4f1c6c3ad..74221e71c 100644 --- a/src/Ombi/ClientApp/app/search/search.component.ts +++ b/src/Ombi/ClientApp/app/search/search.component.ts @@ -9,8 +9,10 @@ import { IssuesService, SettingsService } from "../services"; export class SearchComponent implements OnInit { public showTv: boolean; public showMovie: boolean; + public showMusic: boolean; public issueCategories: IIssueCategory[]; public issuesEnabled = false; + public musicEnabled: boolean; constructor(private issuesService: IssuesService, private settingsService: SettingsService) { @@ -18,8 +20,10 @@ export class SearchComponent implements OnInit { } public ngOnInit() { + this.settingsService.getLidarr().subscribe(x => this.musicEnabled = x.enabled); this.showMovie = true; this.showTv = false; + this.showMusic = false; this.issuesService.getCategories().subscribe(x => this.issueCategories = x); this.settingsService.getIssueSettings().subscribe(x => this.issuesEnabled = x.enabled); } @@ -27,10 +31,17 @@ export class SearchComponent implements OnInit { public selectMovieTab() { this.showMovie = true; this.showTv = false; + this.showMusic = false; } public selectTvTab() { this.showMovie = false; this.showTv = true; + this.showMusic = false; + } + public selectMusicTab() { + this.showMovie = false; + this.showTv = false; + this.showMusic = true; } } diff --git a/src/Ombi/ClientApp/app/search/search.module.ts b/src/Ombi/ClientApp/app/search/search.module.ts index 855207616..3e8181807 100644 --- a/src/Ombi/ClientApp/app/search/search.module.ts +++ b/src/Ombi/ClientApp/app/search/search.module.ts @@ -7,6 +7,7 @@ import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { MovieSearchComponent } from "./moviesearch.component"; import { MovieSearchGridComponent } from "./moviesearchgrid.component"; +import { MusicSearchComponent } from "./music/musicsearch.component"; import { SearchComponent } from "./search.component"; import { SeriesInformationComponent } from "./seriesinformation.component"; import { TvSearchComponent } from "./tvsearch.component"; @@ -41,6 +42,7 @@ const routes: Routes = [ TvSearchComponent, SeriesInformationComponent, MovieSearchGridComponent, + MusicSearchComponent, ], exports: [ RouterModule, diff --git a/src/Ombi/ClientApp/app/services/search.service.ts b/src/Ombi/ClientApp/app/services/search.service.ts index e0da44613..7d2783dd9 100644 --- a/src/Ombi/ClientApp/app/services/search.service.ts +++ b/src/Ombi/ClientApp/app/services/search.service.ts @@ -69,7 +69,10 @@ export class SearchService extends ServiceHelpers { return this.http.get(`${this.url}/Tv/trending`, {headers: this.headers}); } // Music - public searchMusic(searchTerm: string): Observable { - return this.http.get(`${this.url}/Music/` + searchTerm); + public searchArtist(searchTerm: string): Observable { + return this.http.get(`${this.url}/Music/Artist/` + searchTerm); + } + public searchAlbum(searchTerm: string): Observable { + return this.http.get(`${this.url}/Music/Album/` + searchTerm); } } diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts index 7e5571f14..91d7ead80 100644 --- a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts @@ -3,8 +3,7 @@ import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { ILidarrSettings, IMinimumAvailability, IRadarrProfile, IRadarrRootFolder } from "../../interfaces"; import { IRadarrSettings } from "../../interfaces"; -import { RadarrService } from "../../services"; -import { TesterService } from "../../services"; +import { LidarrService, TesterService } from "../../services"; import { NotificationService } from "../../services"; import { SettingsService } from "../../services"; @@ -22,7 +21,7 @@ export class LidarrComponent implements OnInit { public form: FormGroup; constructor(private settingsService: SettingsService, - private radarrService: RadarrService, + private lidarrService: LidarrService, private notificationService: NotificationService, private fb: FormBuilder, private testerService: TesterService) { } @@ -59,7 +58,7 @@ export class LidarrComponent implements OnInit { public getProfiles(form: FormGroup) { this.profilesRunning = true; - this.radarrService.getQualityProfiles(form.value).subscribe(x => { + this.lidarrService.getQualityProfiles(form.value).subscribe(x => { this.qualities = x; this.qualities.unshift({ name: "Please Select", id: -1 }); @@ -70,7 +69,7 @@ export class LidarrComponent implements OnInit { public getRootFolders(form: FormGroup) { this.rootFoldersRunning = true; - this.radarrService.getRootFolders(form.value).subscribe(x => { + this.lidarrService.getRootFolders(form.value).subscribe(x => { this.rootFolders = x; this.rootFolders.unshift({ path: "Please Select", id: -1 }); diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index a3e5a16e7..a8d89ab1c 100644 --- a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html @@ -50,7 +50,7 @@