mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-16 02:02:55 -07:00
got the view albums button working !wip
This commit is contained in:
parent
3750243f11
commit
5df232f3f5
14 changed files with 151 additions and 94 deletions
|
@ -12,9 +12,9 @@ namespace Ombi.Api.Lidarr
|
|||
Task<List<LidarrRootFolder>> GetRootFolders(string apiKey, string baseUrl);
|
||||
Task<ArtistResult> GetArtist(int artistId, string apiKey, string baseUrl);
|
||||
Task<ArtistResult> GetArtistByForeignId(string foreignArtistId, string apiKey, string baseUrl);
|
||||
Task<AlbumByArtistResponse> GetAlbumsByArtist(int artistId, string apiKey, string baseUrl);
|
||||
Task<AlbumByArtistResponse> GetAlbumsByArtist(string foreignArtistId);
|
||||
Task<AlbumLookup> GetAlbumByForeignId(string foreignArtistId, string apiKey, string baseUrl);
|
||||
Task<List<ArtistResult>> GetArtists(string apiKey, string baseUrl);
|
||||
Task<List<AlbumByArtistResponse>> GetAllAlbums(string apiKey, string baseUrl);
|
||||
Task<List<AlbumResponse>> GetAllAlbums(string apiKey, string baseUrl);
|
||||
}
|
||||
}
|
|
@ -82,12 +82,10 @@ namespace Ombi.Api.Lidarr
|
|||
return albums.FirstOrDefault();
|
||||
}
|
||||
|
||||
public Task<AlbumByArtistResponse> GetAlbumsByArtist(int artistId, string apiKey, string baseUrl)
|
||||
public Task<AlbumByArtistResponse> 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<AlbumByArtistResponse>(request);
|
||||
}
|
||||
|
||||
|
@ -99,12 +97,12 @@ namespace Ombi.Api.Lidarr
|
|||
return Api.Request<List<ArtistResult>>(request);
|
||||
}
|
||||
|
||||
public Task<List<AlbumByArtistResponse>> GetAllAlbums(string apiKey, string baseUrl)
|
||||
public Task<List<AlbumResponse>> GetAllAlbums(string apiKey, string baseUrl)
|
||||
{
|
||||
var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get);
|
||||
|
||||
AddHeaders(request, apiKey);
|
||||
return Api.Request<List<AlbumByArtistResponse>>(request);
|
||||
return Api.Request<List<AlbumResponse>>(request);
|
||||
}
|
||||
|
||||
private void AddHeaders(Request request, string key)
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
27
src/Ombi.Api.Lidarr/Models/AlbumResponse.cs
Normal file
27
src/Ombi.Api.Lidarr/Models/AlbumResponse.cs
Normal file
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ namespace Ombi.Api
|
|||
public bool IgnoreErrors { get; set; }
|
||||
public bool Retry { get; set; }
|
||||
public List<HttpStatusCode> StatusCodeToRetry { get; set; } = new List<HttpStatusCode>();
|
||||
public bool IgnoreBaseUrlAppend { get; set; }
|
||||
|
||||
public Action<string> 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();
|
||||
|
|
|
@ -19,12 +19,14 @@ namespace Ombi.Core.Tests.Rule.Search
|
|||
|
||||
MovieMock = new Mock<IMovieRequestRepository>();
|
||||
TvMock = new Mock<ITvRequestRepository>();
|
||||
Rule = new ExistingRule(MovieMock.Object, TvMock.Object);
|
||||
MusicMock = new Mock<IMusicRequestRepository>();
|
||||
Rule = new ExistingRule(MovieMock.Object, TvMock.Object, MusicMock.Object);
|
||||
}
|
||||
|
||||
private ExistingRule Rule { get; set; }
|
||||
private Mock<IMovieRequestRepository> MovieMock { get; set; }
|
||||
private Mock<ITvRequestRepository> TvMock { get; set; }
|
||||
private Mock<IMusicRequestRepository> MusicMock { get; set; }
|
||||
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Ombi.Core.Engine
|
|||
{
|
||||
Task<ArtistResult> GetAlbumArtist(string foreignArtistId);
|
||||
Task<ArtistResult> GetArtist(int artistId);
|
||||
Task<ArtistResult> GetArtistAlbums(string foreignArtistId);
|
||||
Task<IEnumerable<SearchAlbumViewModel>> GetArtistAlbums(string foreignArtistId);
|
||||
Task<IEnumerable<SearchAlbumViewModel>> SearchAlbum(string search);
|
||||
Task<IEnumerable<SearchArtistViewModel>> SearchArtist(string search);
|
||||
}
|
||||
|
|
|
@ -82,12 +82,21 @@ namespace Ombi.Core.Engine
|
|||
/// <summary>
|
||||
/// Returns all albums by the specified artist
|
||||
/// </summary>
|
||||
/// <param name="artistId"></param>
|
||||
/// <param name="foreignArtistId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<ArtistResult> GetArtistAlbums(string foreignArtistId)
|
||||
public async Task<IEnumerable<SearchAlbumViewModel>> 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<SearchAlbumViewModel>();
|
||||
foreach (var album in albumsOnly)
|
||||
{
|
||||
vm.Add(await MapIntoAlbumVm(album, result.Id, result.ArtistName, settings));
|
||||
}
|
||||
return vm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -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<SearchAlbumViewModel> 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<LidarrSettings> GetSettings()
|
||||
{
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
<a *ngIf="result.showSubscribe && result.subscribed" style="color:red" (click)="unSubscribe(result)" pTooltip="Unsubscribe notification"> <i class="fa fa-rss"></i></a> -->
|
||||
</div>
|
||||
</div>
|
||||
<button style="text-align: right" class="btn btn-info-outline">
|
||||
<button style="text-align: right" class="btn btn-info-outline" (click)="viewAllAlbums()">
|
||||
<i class="fa fa-eye"></i> View Albums</button>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -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<ISearchAlbumResult[]>();
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<input type="radio" id="Artist" name="Mode" [checked]="!searchAlbum" (click)="searchMode(false)">
|
||||
<label for="Artist">Artist Search</label>
|
||||
<input type="radio" id="Album" name="Mode" [checked]="searchAlbum" (click)="searchMode(true)">
|
||||
<label for="Album">Album Search</label>
|
||||
<input type="radio" id="Artist" name="Mode" [checked]="!searchAlbum" (click)="searchMode(false)">
|
||||
<label for="Artist">Artist Search</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
|||
</div>
|
||||
|
||||
<div *ngFor="let result of artistResult">
|
||||
<artist-search [result]="result" [defaultPoster]="defaultPoster"></artist-search>
|
||||
<artist-search [result]="result" [defaultPoster]="defaultPoster" (viewAlbumsResult)="viewAlbumsForArtist($event)"></artist-search>
|
||||
<br/>
|
||||
<br/>
|
||||
</div>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<ISearchArtistResult[]> {
|
||||
return this.http.get<ISearchArtistResult[]>(`${this.url}/Music/Artist/` + searchTerm);
|
||||
}
|
||||
public searchAlbum(searchTerm: string): Observable<any> {
|
||||
return this.http.get<any>(`${this.url}/Music/Album/` + searchTerm);
|
||||
public searchAlbum(searchTerm: string): Observable<ISearchAlbumResult[]> {
|
||||
return this.http.get<ISearchAlbumResult[]>(`${this.url}/Music/Album/` + searchTerm);
|
||||
}
|
||||
public getAlbumsForArtist(foreignArtistId: string): Observable<ISearchAlbumResult[]> {
|
||||
return this.http.get<ISearchAlbumResult[]>(`${this.url}/Music/Artist/Album/${foreignArtistId}`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -206,5 +206,16 @@ namespace Ombi.Controllers
|
|||
{
|
||||
return await MusicEngine.SearchAlbum(searchTerm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all albums for the artist using the ForeignArtistId
|
||||
/// </summary>
|
||||
/// <remarks>We use Lidarr as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("music/artist/album/{foreignArtistId}")]
|
||||
public async Task<IEnumerable<SearchAlbumViewModel>> GetAlbumsByArtist(string foreignArtistId)
|
||||
{
|
||||
return await MusicEngine.GetArtistAlbums(foreignArtistId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue