Fixed the artist search in ombi

Make minor improvements to the new search result
pull/3982/head
tidusjar 3 years ago
parent 2ffec6b1e6
commit df74e38672

@ -2,6 +2,7 @@
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hqub.MusicBrainz.API.Entities; using Hqub.MusicBrainz.API.Entities;
using Hqub.MusicBrainz.API.Entities.Collections;
using Ombi.Api.MusicBrainz.Models; using Ombi.Api.MusicBrainz.Models;
namespace Ombi.Api.MusicBrainz namespace Ombi.Api.MusicBrainz
@ -11,6 +12,7 @@ namespace Ombi.Api.MusicBrainz
Task<IEnumerable<Artist>> SearchArtist(string artistQuery); Task<IEnumerable<Artist>> SearchArtist(string artistQuery);
Task<IEnumerable<Release>> GetReleaseForArtist(string artistId); Task<IEnumerable<Release>> GetReleaseForArtist(string artistId);
Task<Artist> GetArtistInformation(string artistId); Task<Artist> GetArtistInformation(string artistId);
Task<Release> GetAlbumInformation(string albumId);
Task<ReleaseGroupArt> GetCoverArtForReleaseGroup(string musicBrainzId, CancellationToken token); Task<ReleaseGroupArt> GetCoverArtForReleaseGroup(string musicBrainzId, CancellationToken token);
} }
} }

@ -6,6 +6,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hqub.MusicBrainz.API; using Hqub.MusicBrainz.API;
using Hqub.MusicBrainz.API.Entities; using Hqub.MusicBrainz.API.Entities;
using Hqub.MusicBrainz.API.Entities.Collections;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ombi.Api.MusicBrainz.Models; using Ombi.Api.MusicBrainz.Models;
@ -20,6 +21,12 @@ namespace Ombi.Api.MusicBrainz
_api = api; _api = api;
} }
public Task<Release> GetAlbumInformation(string albumId)
{
var album = Release.GetAsync(albumId);
return album;
}
public async Task<IEnumerable<Artist>> SearchArtist(string artistQuery) public async Task<IEnumerable<Artist>> SearchArtist(string artistQuery)
{ {
var artist = await Artist.SearchAsync(artistQuery, 10); var artist = await Artist.SearchAsync(artistQuery, 10);

@ -9,5 +9,6 @@ namespace Ombi.Core.Engine.Interfaces
Task<ArtistInformation> GetArtistInformation(string artistId); Task<ArtistInformation> GetArtistInformation(string artistId);
Task<ArtistInformation> GetArtistInformationByRequestId(int requestId); Task<ArtistInformation> GetArtistInformationByRequestId(int requestId);
Task<AlbumArt> GetReleaseGroupArt(string musicBrainzId, CancellationToken token); Task<AlbumArt> GetReleaseGroupArt(string musicBrainzId, CancellationToken token);
Task<ReleaseGroup> GetAlbum(string albumId);
} }
} }

@ -5,6 +5,7 @@ using System.Linq;
using System.Security.Principal; using System.Security.Principal;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json;
using Ombi.Api.Lidarr; using Ombi.Api.Lidarr;
using Ombi.Api.Lidarr.Models; using Ombi.Api.Lidarr.Models;
using Ombi.Api.MusicBrainz; using Ombi.Api.MusicBrainz;
@ -41,6 +42,21 @@ namespace Ombi.Core.Engine.V2
_lidarrApi = lidarrApi; _lidarrApi = lidarrApi;
} }
public async Task<ReleaseGroup> GetAlbum(string albumId)
{
var g = await _musicBrainzApi.GetAlbumInformation(albumId);
var release = new ReleaseGroup
{
ReleaseType = g.ReleaseGroup.PrimaryType,
Id = g.Id,
Title = g.Title,
ReleaseDate = g.ReleaseGroup.FirstReleaseDate,
};
await RunSearchRules(release);
return release;
}
public async Task<ArtistInformation> GetArtistInformation(string artistId) public async Task<ArtistInformation> GetArtistInformation(string artistId)
{ {
var artist = await _musicBrainzApi.GetArtistInformation(artistId); var artist = await _musicBrainzApi.GetArtistInformation(artistId);
@ -84,12 +100,19 @@ namespace Ombi.Core.Engine.V2
if (lidarrArtistTask != null) if (lidarrArtistTask != null)
{ {
var artistResult = await lidarrArtistTask; try
info.Banner = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("banner", StringComparison.InvariantCultureIgnoreCase))?.url.ToHttpsUrl(); {
info.Logo = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("logo", StringComparison.InvariantCultureIgnoreCase))?.url.ToHttpsUrl(); var artistResult = await lidarrArtistTask;
info.Poster = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("poster", StringComparison.InvariantCultureIgnoreCase))?.url.ToHttpsUrl(); info.Banner = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("banner", StringComparison.InvariantCultureIgnoreCase))?.url.ToHttpsUrl();
info.FanArt = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("fanart", StringComparison.InvariantCultureIgnoreCase))?.url.ToHttpsUrl(); info.Logo = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("logo", StringComparison.InvariantCultureIgnoreCase))?.url.ToHttpsUrl();
info.Overview = artistResult.overview; info.Poster = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("poster", StringComparison.InvariantCultureIgnoreCase))?.url.ToHttpsUrl();
info.FanArt = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("fanart", StringComparison.InvariantCultureIgnoreCase))?.url.ToHttpsUrl();
info.Overview = artistResult.overview;
}
catch (JsonSerializationException)
{
// swallow, Lidarr probably doesn't have this artist
}
} }
return info; return info;
@ -118,7 +141,7 @@ namespace Ombi.Core.Engine.V2
return new AlbumArt(); return new AlbumArt();
} }
public async Task<ArtistInformation> GetArtistInformationByRequestId(int requestId) public async Task<ArtistInformation> GetArtistInformationByRequestId(int requestId)
{ {
var request = await RequestService.MusicRequestRepository.Find(requestId); var request = await RequestService.MusicRequestRepository.Find(requestId);

@ -31,9 +31,9 @@ export class DiscoverCardDetailsComponent implements OnInit {
public async ngOnInit() { public async ngOnInit() {
this.loading = true; this.loading = true;
if (this.data.type === RequestType.movie) { if (this.data.type === RequestType.movie) {
this.movie = await this.searchService.getFullMovieDetailsPromise(this.data.id); this.movie = await this.searchService.getFullMovieDetailsPromise(+this.data.id);
} else if (this.data.type === RequestType.tvShow) { } else if (this.data.type === RequestType.tvShow) {
this.tv = await this.searchService.getTvInfo(this.data.id); this.tv = await this.searchService.getTvInfo(+this.data.id);
const creator = this.tv.crew.filter(tv => { const creator = this.tv.crew.filter(tv => {
return tv.type === "Creator"; return tv.type === "Creator";
})[0]; })[0];
@ -67,7 +67,7 @@ export class DiscoverCardDetailsComponent implements OnInit {
public async request() { public async request() {
this.loading = true; this.loading = true;
if (this.data.type === RequestType.movie) { if (this.data.type === RequestType.movie) {
const result = await this.requestService.requestMovie({ theMovieDbId: this.data.id, languageCode: "", requestOnBehalf: null }).toPromise(); const result = await this.requestService.requestMovie({ theMovieDbId: +this.data.id, languageCode: "", requestOnBehalf: null }).toPromise();
this.loading = false; this.loading = false;
if (result.result) { if (result.result) {

@ -1,5 +1,5 @@
<div class="card-spacing box" *ngIf="result" [style.display]="hide ? 'none' : 'block'"> <div class="card-spacing box" *ngIf="result" [style.display]="hide ? 'none' : 'block'">
<mat-card class="mat-elevation-z8 dark-card" [routerLink]="result.type === RequestType.movie ? '/details/movie/' + result.id : '/details/tv/' + result.id"> <mat-card class="mat-elevation-z8 dark-card" [routerLink]="generateDetailsLink()">
<div class="ribbon {{getStatusClass()}} ribbon-top-right"><span> <div class="ribbon {{getStatusClass()}} ribbon-top-right"><span>
{{getAvailbilityStatus()}} {{getAvailbilityStatus()}}
</span></div> </span></div>

@ -1,7 +1,7 @@
import { Component, OnInit, Input } from "@angular/core"; import { Component, OnInit, Input } from "@angular/core";
import { IDiscoverCardResult } from "../../interfaces"; import { IDiscoverCardResult } from "../../interfaces";
import { RequestType } from "../../../interfaces"; import { RequestType } from "../../../interfaces";
import { SearchV2Service } from "../../../services"; import { SearchService, SearchV2Service } from "../../../services";
import { MatDialog } from "@angular/material/dialog"; import { MatDialog } from "@angular/material/dialog";
import { DiscoverCardDetailsComponent } from "./discover-card-details.component"; import { DiscoverCardDetailsComponent } from "./discover-card-details.component";
import { ISearchTvResultV2 } from "../../../interfaces/ISearchTvResultV2"; import { ISearchTvResultV2 } from "../../../interfaces/ISearchTvResultV2";
@ -18,7 +18,7 @@ export class DiscoverCardComponent implements OnInit {
public RequestType = RequestType; public RequestType = RequestType;
public hide: boolean; public hide: boolean;
constructor(private searchService: SearchV2Service, private dialog: MatDialog) { } constructor(private searchService: SearchV2Service, private v1Search: SearchService, private dialog: MatDialog) { }
public ngOnInit() { public ngOnInit() {
if (this.result.type == RequestType.tvShow) { if (this.result.type == RequestType.tvShow) {
@ -27,6 +27,9 @@ export class DiscoverCardComponent implements OnInit {
if (this.result.type == RequestType.movie) { if (this.result.type == RequestType.movie) {
this.getExtraMovieInfo(); this.getExtraMovieInfo();
} }
if (this.result.type == RequestType.album) {
this.getAlbumInformation();
}
} }
public openDetails(details: IDiscoverCardResult) { public openDetails(details: IDiscoverCardResult) {
@ -35,9 +38,9 @@ export class DiscoverCardComponent implements OnInit {
public async getExtraTvInfo() { public async getExtraTvInfo() {
if (this.result.tvMovieDb) { if (this.result.tvMovieDb) {
var result = await this.searchService.getTvInfoWithMovieDbId(this.result.id); var result = await this.searchService.getTvInfoWithMovieDbId(+this.result.id);
} else { } else {
var result = await this.searchService.getTvInfo(this.result.id); var result = await this.searchService.getTvInfo(+this.result.id);
} }
if(result.status === "404") { if(result.status === "404") {
this.hide = true; this.hide = true;
@ -48,6 +51,34 @@ export class DiscoverCardComponent implements OnInit {
} }
public async getAlbumInformation() {
this.searchService.getArtistInformation(this.result.id.toString()).subscribe(x => {
if (x.poster) {
this.result.posterPath = x.poster;
} else {
this.searchService.getReleaseGroupArt(this.result.id.toString()).subscribe(art => {
if(art.image) {
this.result.posterPath = art.image;
}
})
}
this.result.title = x.startYear ? `${x.name} (${x.startYear})` : x.name;
this.result.overview = x.overview;
});
}
public generateDetailsLink(): string {
let link = "";
switch(this.result.type){
case RequestType.movie:
return `/details/movie/${this.result.id}`;
case RequestType.tvShow:
return `/details/tv/${this.result.id}`;
case RequestType.album: //Actually artist
return `/details/artist/${this.result.id}`;
}
}
public getStatusClass(): string { public getStatusClass(): string {
if (this.result.available) { if (this.result.available) {
return "available"; return "available";
@ -76,7 +107,7 @@ export class DiscoverCardComponent implements OnInit {
private getExtraMovieInfo() { private getExtraMovieInfo() {
if (!this.result.imdbid) { if (!this.result.imdbid) {
this.searchService.getFullMovieDetails(this.result.id) this.searchService.getFullMovieDetails(+this.result.id)
.subscribe(m => { .subscribe(m => {
this.updateMovieItem(m); this.updateMovieItem(m);
}); });

@ -27,8 +27,8 @@ export class DiscoverGridComponent implements OnInit {
public movie: ISearchMovieResultV2; public movie: ISearchMovieResultV2;
constructor(private searchService: SearchV2Service, private dialog: MatDialog, constructor(private searchService: SearchV2Service, private dialog: MatDialog,
private requestService: RequestService, private notification: MatSnackBar, private requestService: RequestService, private notification: MatSnackBar,
private router: Router, private sanitizer: DomSanitizer, private imageService: ImageService) { } private router: Router, private sanitizer: DomSanitizer, private imageService: ImageService) { }
public ngOnInit() { public ngOnInit() {
if (this.result.type == RequestType.tvShow) { if (this.result.type == RequestType.tvShow) {
@ -40,7 +40,7 @@ export class DiscoverGridComponent implements OnInit {
} }
public async getExtraTvInfo() { public async getExtraTvInfo() {
this.tv = await this.searchService.getTvInfo(this.result.id); this.tv = await this.searchService.getTvInfo(+this.result.id);
this.setTvDefaults(this.tv); this.setTvDefaults(this.tv);
this.updateTvItem(this.tv); this.updateTvItem(this.tv);
const creator = this.tv.crew.filter(tv => { const creator = this.tv.crew.filter(tv => {
@ -80,35 +80,33 @@ export class DiscoverGridComponent implements OnInit {
} }
private getExtraMovieInfo() { private getExtraMovieInfo() {
// if (!this.result.imdbid) { this.searchService.getFullMovieDetails(+this.result.id)
this.searchService.getFullMovieDetails(this.result.id) .subscribe(m => {
.subscribe(m => { this.movie = m;
this.movie = m; this.updateMovieItem(m);
this.updateMovieItem(m); });
});
this.setMovieBackground()
this.setMovieBackground()
// }
} }
private setMovieBackground(): void { private setMovieBackground(): void {
this.result.background = this.sanitizer.bypassSecurityTrustStyle this.result.background = this.sanitizer.bypassSecurityTrustStyle
("linear-gradient( rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url(" + "https://image.tmdb.org/t/p/original" + this.result.background + ")"); ("linear-gradient( rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url(" + "https://image.tmdb.org/t/p/original" + this.result.background + ")");
} }
private setTvBackground(): void { private setTvBackground(): void {
if (this.result.background != null) { if (this.result.background != null) {
this.result.background = this.sanitizer.bypassSecurityTrustStyle this.result.background = this.sanitizer.bypassSecurityTrustStyle
("linear-gradient( rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url(https://image.tmdb.org/t/p/original" + this.result.background + ")"); ("linear-gradient( rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url(https://image.tmdb.org/t/p/original" + this.result.background + ")");
} else { } else {
this.imageService.getTvBanner(this.result.id).subscribe(x => { this.imageService.getTvBanner(+this.result.id).subscribe(x => {
if (x) { if (x) {
this.result.background = this.sanitizer.bypassSecurityTrustStyle this.result.background = this.sanitizer.bypassSecurityTrustStyle
("linear-gradient( rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url(" + x + ")"); ("linear-gradient( rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url(" + x + ")");
} }
}); });
} }
} }
private updateMovieItem(updated: ISearchMovieResultV2) { private updateMovieItem(updated: ISearchMovieResultV2) {
this.result.url = "http://www.imdb.com/title/" + updated.imdbId + "/"; this.result.url = "http://www.imdb.com/title/" + updated.imdbId + "/";
@ -139,7 +137,7 @@ export class DiscoverGridComponent implements OnInit {
public async request() { public async request() {
this.requesting = true; this.requesting = true;
if (this.result.type === RequestType.movie) { if (this.result.type === RequestType.movie) {
const result = await this.requestService.requestMovie({ theMovieDbId: this.result.id, languageCode: "", requestOnBehalf: null }).toPromise(); const result = await this.requestService.requestMovie({ theMovieDbId: +this.result.id, languageCode: "", requestOnBehalf: null }).toPromise();
if (result.result) { if (result.result) {
this.result.requested = true; this.result.requested = true;
@ -148,7 +146,7 @@ export class DiscoverGridComponent implements OnInit {
this.notification.open(result.errorMessage, "Ok"); this.notification.open(result.errorMessage, "Ok");
} }
} else if (this.result.type === RequestType.tvShow) { } else if (this.result.type === RequestType.tvShow) {
this.dialog.open(EpisodeRequestComponent, { width: "700px", data: <EpisodeRequestData> { series: this.tv, requestOnBehalf: null }, panelClass: 'modal-panel' }) this.dialog.open(EpisodeRequestComponent, { width: "700px", data: <EpisodeRequestData>{ series: this.tv, requestOnBehalf: null }, panelClass: 'modal-panel' })
} }
this.requesting = false; this.requesting = false;
} }

@ -39,7 +39,7 @@ export class DiscoverSearchResultsComponent implements OnInit {
this.filterService.onFilterChange.subscribe(async x => { this.filterService.onFilterChange.subscribe(async x => {
if (!isEqual(this.filter, x)) { if (!isEqual(this.filter, x)) {
this.filter = { ...x }; this.filter = { ...x };
await this.search(); await this.search();
} }
}); });
@ -50,7 +50,7 @@ export class DiscoverSearchResultsComponent implements OnInit {
if (filter) { if (filter) {
this.filter = Object.assign(new SearchFilter(), JSON.parse(filter)); this.filter = Object.assign(new SearchFilter(), JSON.parse(filter));
} else { } else {
this.filter = new SearchFilter({ movies: true, tvShows: true, people: false, music: false}); this.filter = new SearchFilter({ movies: true, tvShows: true, people: false, music: false });
} }
this.loading(); this.loading();
await this.search(); await this.search();
@ -69,12 +69,22 @@ export class DiscoverSearchResultsComponent implements OnInit {
mediaType = RequestType.album; mediaType = RequestType.album;
} }
let poster = `https://image.tmdb.org/t/p/w300/${m.poster}`;
if (!m.poster) {
if (mediaType === RequestType.movie) {
poster = "images/default_movie_poster.png"
}
if (mediaType === RequestType.tvShow) {
poster = "images/default_tv_poster.png"
}
}
this.discoverResults.push({ this.discoverResults.push({
posterPath: `https://image.tmdb.org/t/p/w300/${m.poster}`, posterPath: mediaType !== RequestType.album ? poster : "images/default-music-placeholder.png",
requested: false, requested: false,
title: m.title, title: m.title,
type: mediaType, type: mediaType,
id: +m.id, id: m.id,
url: "", url: "",
rating: 0, rating: 0,
overview: "", overview: "",

@ -1,7 +1,7 @@
import { RequestType } from "../interfaces"; import { RequestType } from "../interfaces";
export interface IDiscoverCardResult { export interface IDiscoverCardResult {
id: number; id: number | string;
posterPath: string; posterPath: string;
url: string | undefined; url: string | undefined;
title: string; title: string;

@ -89,6 +89,9 @@ export class SearchService extends ServiceHelpers {
public searchAlbum(searchTerm: string): Observable<ISearchAlbumResult[]> { public searchAlbum(searchTerm: string): Observable<ISearchAlbumResult[]> {
return this.http.get<ISearchAlbumResult[]>(`${this.url}/Music/Album/` + searchTerm); return this.http.get<ISearchAlbumResult[]>(`${this.url}/Music/Album/` + searchTerm);
} }
public getAlbumInformation(foreignAlbumId: string): Observable<ISearchAlbumResult> {
return this.http.get<ISearchAlbumResult>(`${this.url}/Music/Album/info/` + foreignAlbumId);
}
public getAlbumsForArtist(foreignArtistId: string): Observable<ISearchAlbumResult[]> { public getAlbumsForArtist(foreignArtistId: string): Observable<ISearchAlbumResult[]> {
return this.http.get<ISearchAlbumResult[]>(`${this.url}/Music/Artist/Album/${foreignArtistId}`); return this.http.get<ISearchAlbumResult[]>(`${this.url}/Music/Artist/Album/${foreignArtistId}`);
} }

@ -9,7 +9,7 @@ import { ServiceHelpers } from "./service.helpers";
import { ISearchMovieResultV2 } from "../interfaces/ISearchMovieResultV2"; import { ISearchMovieResultV2 } from "../interfaces/ISearchMovieResultV2";
import { ISearchTvResultV2, IMovieCollectionsViewModel, IActorCredits } from "../interfaces/ISearchTvResultV2"; import { ISearchTvResultV2, IMovieCollectionsViewModel, IActorCredits } from "../interfaces/ISearchTvResultV2";
import { IArtistSearchResult, IAlbumArt } from "../interfaces/IMusicSearchResultV2"; import { IArtistSearchResult, IAlbumArt, IReleaseGroups } from "../interfaces/IMusicSearchResultV2";
import { SearchFilter } from "../my-nav/SearchFilter"; import { SearchFilter } from "../my-nav/SearchFilter";
import { IMovieRatings, ITvRatings } from "../interfaces/IRatings"; import { IMovieRatings, ITvRatings } from "../interfaces/IRatings";
import { IStreamingData } from "../interfaces/IStreams"; import { IStreamingData } from "../interfaces/IStreams";
@ -124,6 +124,10 @@ export class SearchV2Service extends ServiceHelpers {
return this.http.get<IAlbumArt>(`${this.url}/releasegroupart/${mbid}`); return this.http.get<IAlbumArt>(`${this.url}/releasegroupart/${mbid}`);
} }
public getAlbum(mbid: string): Observable<IReleaseGroups> {
return this.http.get<IReleaseGroups>(`${this.url}/artist/album/${mbid}`);
}
public getRottenMovieRatings(name: string, year: number): Observable<IMovieRatings> { public getRottenMovieRatings(name: string, year: number): Observable<IMovieRatings> {
return this.http.get<IMovieRatings>(`${this.url}/ratings/movie/${name}/${year}`); return this.http.get<IMovieRatings>(`${this.url}/ratings/movie/${name}/${year}`);
} }

@ -16,6 +16,7 @@ using Ombi.Core.Models.Search.V2.Music;
using Ombi.Models; using Ombi.Models;
using Ombi.Api.RottenTomatoes.Models; using Ombi.Api.RottenTomatoes.Models;
using Ombi.Api.RottenTomatoes; using Ombi.Api.RottenTomatoes;
using Hqub.MusicBrainz.API.Entities.Collections;
namespace Ombi.Controllers.V2 namespace Ombi.Controllers.V2
{ {
@ -396,6 +397,14 @@ namespace Ombi.Controllers.V2
return await _musicEngine.GetArtistInformationByRequestId(requestId); return await _musicEngine.GetArtistInformationByRequestId(requestId);
} }
[HttpGet("artist/album/{albumId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesDefaultResponseType]
public Task<ReleaseGroup> GetAlbumInformation(string albumId)
{
return _musicEngine.GetAlbum(albumId);
}
[HttpGet("releasegroupart/{musicBrainzId}")] [HttpGet("releasegroupart/{musicBrainzId}")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesDefaultResponseType] [ProducesDefaultResponseType]

@ -45,6 +45,8 @@ namespace Ombi
} }
}); });
Console.WriteLine(HelpOutput(result)); Console.WriteLine(HelpOutput(result));
UrlArgs = host; UrlArgs = host;

Loading…
Cancel
Save