diff --git a/src/Ombi.Api.Lidarr/ILidarrApi.cs b/src/Ombi.Api.Lidarr/ILidarrApi.cs index 2fe74f803..d66f9716c 100644 --- a/src/Ombi.Api.Lidarr/ILidarrApi.cs +++ b/src/Ombi.Api.Lidarr/ILidarrApi.cs @@ -12,9 +12,9 @@ namespace Ombi.Api.Lidarr Task> GetRootFolders(string apiKey, string baseUrl); Task GetArtist(int artistId, string apiKey, string baseUrl); Task GetArtistByForeignId(string foreignArtistId, string apiKey, string baseUrl); - Task GetAlbumsByArtist(int artistId, string apiKey, string baseUrl); + Task GetAlbumsByArtist(string foreignArtistId); Task GetAlbumByForeignId(string foreignArtistId, string apiKey, string baseUrl); Task> GetArtists(string apiKey, string baseUrl); - Task> GetAllAlbums(string apiKey, string baseUrl); + Task> GetAllAlbums(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 09b670afa..84e0d090a 100644 --- a/src/Ombi.Api.Lidarr/LidarrApi.cs +++ b/src/Ombi.Api.Lidarr/LidarrApi.cs @@ -82,12 +82,10 @@ namespace Ombi.Api.Lidarr return albums.FirstOrDefault(); } - public Task GetAlbumsByArtist(int artistId, string apiKey, string baseUrl) + public Task GetAlbumsByArtist(string foreignArtistId) { - var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get); - - request.AddQueryString("artistId", artistId.ToString()); - AddHeaders(request, apiKey); + var request = new Request(string.Empty, $"https://api.lidarr.audio/api/v0.3/artist/{foreignArtistId}", + HttpMethod.Get) {IgnoreBaseUrlAppend = true}; return Api.Request(request); } @@ -99,12 +97,12 @@ namespace Ombi.Api.Lidarr return Api.Request>(request); } - public Task> GetAllAlbums(string apiKey, string baseUrl) + public Task> GetAllAlbums(string apiKey, string baseUrl) { var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get); AddHeaders(request, apiKey); - return Api.Request>(request); + return Api.Request>(request); } private void AddHeaders(Request request, string key) diff --git a/src/Ombi.Api.Lidarr/Models/AlbumByArtistResponse.cs b/src/Ombi.Api.Lidarr/Models/AlbumByArtistResponse.cs index 0a54dbfeb..62f19651f 100644 --- a/src/Ombi.Api.Lidarr/Models/AlbumByArtistResponse.cs +++ b/src/Ombi.Api.Lidarr/Models/AlbumByArtistResponse.cs @@ -1,27 +1,34 @@ -using System; - -namespace Ombi.Api.Lidarr.Models +namespace Ombi.Api.Lidarr.Models { public class AlbumByArtistResponse { - public string title { get; set; } - public string disambiguation { 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 object[] secondaryTypes { get; set; } - public int mediumCount { get; set; } - public Ratings ratings { get; set; } - public DateTime releaseDate { get; set; } - public Currentrelease currentRelease { get; set; } - public Release[] releases { get; set; } - public object[] genres { get; set; } - public Medium[] media { get; set; } - public Image[] images { get; set; } - public Statistics statistics { get; set; } - public int id { get; set; } + public Album[] Albums { get; set; } + public string ArtistName { get; set; } + public string Disambiguation { get; set; } + public string Id { get; set; } + public Image[] Images { get; set; } + public Link[] Links { get; set; } + public string Overview { get; set; } + public Rating Rating { get; set; } + public string SortName { get; set; } + public string Status { get; set; } + public string Type { get; set; } + } + + public class Rating + { + public int Count { get; set; } + public decimal Value { get; set; } + } + + public class Album + { + public string Disambiguation { get; set; } + public string Id { get; set; } + public string ReleaseDate { get; set; } + public string[] ReleaseStatuses { get; set; } + public string[] SecondaryTypes { get; set; } + public string Title { get; set; } + public string Type { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Models/AlbumResponse.cs b/src/Ombi.Api.Lidarr/Models/AlbumResponse.cs new file mode 100644 index 000000000..f9d35c43b --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/AlbumResponse.cs @@ -0,0 +1,27 @@ +using System; + +namespace Ombi.Api.Lidarr.Models +{ + public class AlbumResponse + { + public string title { get; set; } + public string disambiguation { 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 object[] secondaryTypes { get; set; } + public int mediumCount { get; set; } + public Ratings ratings { get; set; } + public DateTime releaseDate { get; set; } + public Currentrelease currentRelease { get; set; } + public Release[] releases { get; set; } + public object[] genres { get; set; } + public Medium[] media { get; set; } + public Image[] images { get; set; } + public Statistics statistics { get; set; } + public int id { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api/Request.cs b/src/Ombi.Api/Request.cs index cfd284f54..fd888d0d2 100644 --- a/src/Ombi.Api/Request.cs +++ b/src/Ombi.Api/Request.cs @@ -28,6 +28,7 @@ namespace Ombi.Api public bool IgnoreErrors { get; set; } public bool Retry { get; set; } public List StatusCodeToRetry { get; set; } = new List(); + public bool IgnoreBaseUrlAppend { get; set; } public Action OnBeforeDeserialization { get; set; } @@ -38,7 +39,7 @@ namespace Ombi.Api var sb = new StringBuilder(); if (!string.IsNullOrEmpty(BaseUrl)) { - sb.Append(!BaseUrl.EndsWith("/") ? string.Format("{0}/", BaseUrl) : BaseUrl); + sb.Append(!BaseUrl.EndsWith("/") && !IgnoreBaseUrlAppend ? string.Format("{0}/", BaseUrl) : BaseUrl); } sb.Append(Endpoint.StartsWith("/") ? Endpoint.Remove(0, 1) : Endpoint); return sb.ToString(); diff --git a/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs index a706472dd..e32c8e996 100644 --- a/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs @@ -19,12 +19,14 @@ namespace Ombi.Core.Tests.Rule.Search MovieMock = new Mock(); TvMock = new Mock(); - Rule = new ExistingRule(MovieMock.Object, TvMock.Object); + MusicMock = new Mock(); + Rule = new ExistingRule(MovieMock.Object, TvMock.Object, MusicMock.Object); } private ExistingRule Rule { get; set; } private Mock MovieMock { get; set; } private Mock TvMock { get; set; } + private Mock MusicMock { get; set; } [Test] diff --git a/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs index 44643bc9d..03294982a 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs @@ -9,7 +9,7 @@ namespace Ombi.Core.Engine { Task GetAlbumArtist(string foreignArtistId); Task GetArtist(int artistId); - Task GetArtistAlbums(string foreignArtistId); + Task> GetArtistAlbums(string foreignArtistId); Task> SearchAlbum(string search); Task> SearchArtist(string search); } diff --git a/src/Ombi.Core/Engine/MusicSearchEngine.cs b/src/Ombi.Core/Engine/MusicSearchEngine.cs index 7eba0429d..17f1aed54 100644 --- a/src/Ombi.Core/Engine/MusicSearchEngine.cs +++ b/src/Ombi.Core/Engine/MusicSearchEngine.cs @@ -82,12 +82,21 @@ namespace Ombi.Core.Engine /// /// Returns all albums by the specified artist /// - /// + /// /// - public async Task GetArtistAlbums(string foreignArtistId) + public async Task> GetArtistAlbums(string foreignArtistId) { var settings = await GetSettings(); - return await _lidarrApi.GetArtistByForeignId(foreignArtistId, settings.ApiKey, settings.FullUri); + var result = await _lidarrApi.GetAlbumsByArtist(foreignArtistId); + // We do not want any Singles (This will include EP's) + var albumsOnly = + result.Albums.Where(x => !x.Type.Equals("Single", StringComparison.InvariantCultureIgnoreCase)); + var vm = new List(); + foreach (var album in albumsOnly) + { + vm.Add(await MapIntoAlbumVm(album, result.Id, result.ArtistName, settings)); + } + return vm; } /// @@ -121,7 +130,7 @@ namespace Ombi.Core.Engine Links = a.links, Overview = a.overview, }; - + var poster = a.images?.FirstOrDefault(x => x.coverType.Equals("poaster")); if (poster == null) { @@ -147,6 +156,7 @@ namespace Ombi.Core.Engine }; if (vm.Monitored) { + //TODO THEY HAVE FIXED THIS IN DEV // The JSON is different for some stupid reason // Need to lookup the artist now and all the images -.-" var artist = await _lidarrApi.GetArtist(a.artistId, settings.ApiKey, settings.FullUri); @@ -171,6 +181,35 @@ namespace Ombi.Core.Engine return vm; } + + private async Task MapIntoAlbumVm(Album a, string artistId, string artistName, LidarrSettings settings) + { + var fullAlbum = await _lidarrApi.GetAlbumByForeignId(a.Id, settings.ApiKey, settings.FullUri); + var vm = new SearchAlbumViewModel + { + ForeignAlbumId = a.Id, + Monitored = fullAlbum.monitored, + Rating = fullAlbum.ratings?.value ?? 0m, + ReleaseDate = fullAlbum.releaseDate, + Title = a.Title, + Disk = fullAlbum.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url, + ForeignArtistId = artistId, + ArtistName = artistName, + Cover = fullAlbum.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url + }; + + if (vm.Cover.IsNullOrEmpty()) + { + vm.Cover = fullAlbum.remoteCover; + } + + await Rules.StartSpecificRules(vm, SpecificRules.LidarrAlbum); + + await RunSearchRules(vm); + + return vm; + } + private LidarrSettings _settings; private async Task GetSettings() { diff --git a/src/Ombi/ClientApp/app/search/music/artistsearch.component.html b/src/Ombi/ClientApp/app/search/music/artistsearch.component.html index b68990d69..5ea5433f1 100644 --- a/src/Ombi/ClientApp/app/search/music/artistsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/artistsearch.component.html @@ -51,7 +51,7 @@ --> - diff --git a/src/Ombi/ClientApp/app/search/music/artistsearch.component.ts b/src/Ombi/ClientApp/app/search/music/artistsearch.component.ts index 8794d5efc..76a223d09 100644 --- a/src/Ombi/ClientApp/app/search/music/artistsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/music/artistsearch.component.ts @@ -1,10 +1,7 @@ -import { Component, Input } from "@angular/core"; -import { TranslateService } from "@ngx-translate/core"; +import { Component, EventEmitter, Input, Output } from "@angular/core"; -import { AuthService } from "../../auth/auth.service"; -import { IRequestEngineResult, ISearchMovieResult } from "../../interfaces"; -import { ISearchArtistResult } from "../../interfaces/ISearchMusicResult"; -import { NotificationService, RequestService } from "../../services"; +import { ISearchAlbumResult, ISearchArtistResult } from "../../interfaces/ISearchMusicResult"; +import { SearchService } from "../../services"; @Component({ selector: "artist-search", @@ -13,51 +10,16 @@ import { NotificationService, RequestService } from "../../services"; export class ArtistSearchComponent { @Input() public result: ISearchArtistResult; - public engineResult: IRequestEngineResult; @Input() public defaultPoster: string; - constructor( - private requestService: RequestService, - private notificationService: NotificationService, private authService: AuthService, - private readonly translate: TranslateService) { + @Output() public viewAlbumsResult = new EventEmitter(); + + constructor(private searchService: SearchService) { } - 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.engineResult = x; - - if (this.engineResult.result) { - this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => { - this.notificationService.success(x); - searchResult.processed = true; - }); - } else { - if (this.engineResult.errorMessage && this.engineResult.message) { - this.notificationService.warning("Request Added", `${this.engineResult.message} - ${this.engineResult.errorMessage}`); - } else { - this.notificationService.warning("Request Added", this.engineResult.message ? this.engineResult.message : this.engineResult.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 viewAllAlbums() { + this.searchService.getAlbumsForArtist(this.result.forignArtistId).subscribe(x => { + this.viewAlbumsResult.emit(x); + }); } } diff --git a/src/Ombi/ClientApp/app/search/music/musicsearch.component.html b/src/Ombi/ClientApp/app/search/music/musicsearch.component.html index 867d7803e..b73ee553b 100644 --- a/src/Ombi/ClientApp/app/search/music/musicsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/musicsearch.component.html @@ -8,10 +8,10 @@
- - + +
@@ -29,7 +29,7 @@
- +

diff --git a/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts b/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts index ad980ff60..e022ab6c3 100644 --- a/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts @@ -22,7 +22,7 @@ export class MusicSearchComponent implements OnInit { public albumResult: ISearchAlbumResult[]; public result: IRequestEngineResult; public searchApplied = false; - public searchAlbum: boolean = false; + public searchAlbum: boolean = true; @Input() public issueCategories: IIssueCategory[]; @Input() public issuesEnabled: boolean; @@ -148,6 +148,13 @@ export class MusicSearchComponent implements OnInit { } } + public viewAlbumsForArtist(albums: ISearchAlbumResult[]) { + this.clearArtistResults(); + this.searchAlbum = true; + this.albumResult = albums; + this.setAlbumBackground(); + } + private clearArtistResults() { this.artistResult = []; this.searchApplied = false; diff --git a/src/Ombi/ClientApp/app/services/search.service.ts b/src/Ombi/ClientApp/app/services/search.service.ts index f6a5271f5..9769ad229 100644 --- a/src/Ombi/ClientApp/app/services/search.service.ts +++ b/src/Ombi/ClientApp/app/services/search.service.ts @@ -7,7 +7,7 @@ import { Observable } from "rxjs"; import { TreeNode } from "primeng/primeng"; import { ISearchMovieResult } from "../interfaces"; import { ISearchTvResult } from "../interfaces"; -import { ISearchArtistResult } from "../interfaces/ISearchMusicResult"; +import { ISearchAlbumResult, ISearchArtistResult } from "../interfaces/ISearchMusicResult"; import { ServiceHelpers } from "./service.helpers"; @Injectable() @@ -73,7 +73,10 @@ export class SearchService extends ServiceHelpers { 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); + public searchAlbum(searchTerm: string): Observable { + return this.http.get(`${this.url}/Music/Album/` + searchTerm); + } + public getAlbumsForArtist(foreignArtistId: string): Observable { + return this.http.get(`${this.url}/Music/Artist/Album/${foreignArtistId}`); } } diff --git a/src/Ombi/Controllers/SearchController.cs b/src/Ombi/Controllers/SearchController.cs index 026e4541d..5d05ceae5 100644 --- a/src/Ombi/Controllers/SearchController.cs +++ b/src/Ombi/Controllers/SearchController.cs @@ -206,5 +206,16 @@ namespace Ombi.Controllers { return await MusicEngine.SearchAlbum(searchTerm); } + + /// + /// Returns all albums for the artist using the ForeignArtistId + /// + /// We use Lidarr as the Provider + /// + [HttpGet("music/artist/album/{foreignArtistId}")] + public async Task> GetAlbumsByArtist(string foreignArtistId) + { + return await MusicEngine.GetArtistAlbums(foreignArtistId); + } } }