diff --git a/src/Ombi.Api.MusicBrainz/IMusicBrainzApi.cs b/src/Ombi.Api.MusicBrainz/IMusicBrainzApi.cs new file mode 100644 index 000000000..ab8d7ad30 --- /dev/null +++ b/src/Ombi.Api.MusicBrainz/IMusicBrainzApi.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Api.MusicBrainz.Models.Lookup; +using Ombi.Api.MusicBrainz.Models.Search; + +namespace Ombi.Api.MusicBrainz +{ + public interface IMusicBrainzApi + { + Task> SearchArtist(string artistQuery); + Task> GetReleaseGroups(string artistId); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.MusicBrainz/Models/Lookup/ReleaseGroups.cs b/src/Ombi.Api.MusicBrainz/Models/Lookup/ReleaseGroups.cs new file mode 100644 index 000000000..58730d144 --- /dev/null +++ b/src/Ombi.Api.MusicBrainz/Models/Lookup/ReleaseGroups.cs @@ -0,0 +1,27 @@ +using Newtonsoft.Json; + +namespace Ombi.Api.MusicBrainz.Models.Lookup +{ + + [JsonPluralName("release-groups")] + public class ReleaseGroups + { + [JsonProperty(PropertyName = "id")] + public string Id { get; set; } + [JsonProperty(PropertyName = "primary-type-ids")] + public string PrimaryTypeId { get; set; } + [JsonProperty(PropertyName = "disambiguation")] + public string Disambiguation { get; set; } + [JsonProperty(PropertyName = "secondary-types")] + public string[] SecondaryTypes { get; set; } + [JsonProperty(PropertyName = "primary-type")] + public string PrimaryType { get; set; } // Album / Single / Live / EP + [JsonProperty(PropertyName = "first-release-date")] + public string FirstReleaseDate { get; set; } + [JsonProperty(PropertyName = "secondary-type-ids")] + public string[] SecondaryTypeIds { get; set; } + [JsonProperty(PropertyName = "title")] + public string Title { get; set; } // Release title + } + +} \ No newline at end of file diff --git a/src/Ombi.Api.MusicBrainz/Models/MusicBrainzResult.cs b/src/Ombi.Api.MusicBrainz/Models/MusicBrainzResult.cs new file mode 100644 index 000000000..02a1a7c79 --- /dev/null +++ b/src/Ombi.Api.MusicBrainz/Models/MusicBrainzResult.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace Ombi.Api.MusicBrainz.Models +{ + public class MusicBrainzResult + { + public DateTime created { get; set; } + public int count { get; set; } + public int offset { get; set; } + [JsonPropertyNameBasedOnItemClass] + public List Data { get; set; } + } + +} \ No newline at end of file diff --git a/src/Ombi.Api.MusicBrainz/Models/Search/ArtistSearchResult.cs b/src/Ombi.Api.MusicBrainz/Models/Search/ArtistSearchResult.cs new file mode 100644 index 000000000..cc2aaf7bf --- /dev/null +++ b/src/Ombi.Api.MusicBrainz/Models/Search/ArtistSearchResult.cs @@ -0,0 +1,83 @@ +using Newtonsoft.Json; + +namespace Ombi.Api.MusicBrainz.Models.Search +{ + + [JsonPluralName("artists")] + public class Artist + { + public string id { get; set; } + public string type { get; set; } + [JsonProperty(PropertyName = "type-id")] + public string typeid { get; set; } + public int score { get; set; } + public string name { get; set; } + [JsonProperty(PropertyName = "sort-name")] + public string sortname { get; set; } + public string country { get; set; } + public Area area { get; set; } + [JsonProperty(PropertyName = "begin-area")] + public BeginArea beginarea { get; set; } + [JsonProperty(PropertyName = "life-span")] + public LifeSpan2 lifespan { get; set; } + public Tag[] tags { get; set; } + [JsonProperty(PropertyName = "isni-list")] + public IsniList[] isnilist { get; set; } + public string disambiguation { get; set; } + } + + public class Area + { + public string id { get; set; } + public string type { get; set; } + [JsonProperty(PropertyName = "type-id")] + public string typeid { get; set; } + public string name { get; set; } + + [JsonProperty(PropertyName = "sort-name")] + public string sortname { get; set; } + [JsonProperty(PropertyName = "life-span")] + public LifeSpan lifespan { get; set; } + } + + public class LifeSpan + { + public object ended { get; set; } + } + + public class BeginArea + { + public string id { get; set; } + public string type { get; set; } + [JsonProperty(PropertyName = "type-id")] + public string typeid { get; set; } + public string name { get; set; } + [JsonProperty(PropertyName = "sort-name")] + public string sortname { get; set; } + [JsonProperty(PropertyName = "life-span")] + public LifeSpan1 lifespan { get; set; } + } + + public class LifeSpan1 + { + public object ended { get; set; } + } + + public class LifeSpan2 + { + public string begin { get; set; } + public object ended { get; set; } + } + + public class Tag + { + public int count { get; set; } + public string name { get; set; } + } + + public class IsniList + { + public string isni { get; set; } + } + +} \ No newline at end of file diff --git a/src/Ombi.Api.MusicBrainz/MusicBrainzApi.cs b/src/Ombi.Api.MusicBrainz/MusicBrainzApi.cs new file mode 100644 index 000000000..196ad2a74 --- /dev/null +++ b/src/Ombi.Api.MusicBrainz/MusicBrainzApi.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Ombi.Api; +using Ombi.Api.MusicBrainz.Models; +using Ombi.Api.MusicBrainz.Models.Lookup; +using Ombi.Api.MusicBrainz.Models.Search; + +namespace Ombi.Api.MusicBrainz +{ + public class MusicBrainzApi : IMusicBrainzApi + { + public MusicBrainzApi(IApi api) + { + _api = api; + } + + private readonly IApi _api; + private const string _baseUrl = "https://musicbrainz.org/ws/2/"; + + public async Task> SearchArtist(string artistQuery) + { + var request = new Request("artist", _baseUrl, HttpMethod.Get); + + request.AddQueryString("query", artistQuery); + AddHeaders(request); + var albums = await _api.Request>(request); + return albums.Data.Where(x => !x.type.Equals("Person", StringComparison.CurrentCultureIgnoreCase)); + } + + public async Task> GetReleaseGroups(string artistId) + { + var request = new Request("release-group", _baseUrl, HttpMethod.Get); + + request.AddQueryString("artist", artistId); + AddHeaders(request); + + // The count properties for release groups is called releasegroupcount... Will sort this out if I need paging + var releases = await _api.Request>(request); + return releases.Data; + } + + private void AddHeaders(Request req) + { + req.AddHeader("Accept", "application/json"); + } + } +} diff --git a/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj b/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj new file mode 100644 index 000000000..2b49de164 --- /dev/null +++ b/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj @@ -0,0 +1,10 @@ + + + + netstandard2.0 + + + + + + diff --git a/src/Ombi.Api/Api.cs b/src/Ombi.Api/Api.cs index 3c7e6967a..3f9928c33 100644 --- a/src/Ombi.Api/Api.cs +++ b/src/Ombi.Api/Api.cs @@ -27,7 +27,8 @@ namespace Ombi.Api private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings { - NullValueHandling = NullValueHandling.Ignore + NullValueHandling = NullValueHandling.Ignore, + ContractResolver = new PluralPropertyContractResolver() }; public async Task Request(Request request, CancellationToken cancellationToken = default(CancellationToken)) diff --git a/src/Ombi.Api/Attribute/JsonPluralNameAttribute.cs b/src/Ombi.Api/Attribute/JsonPluralNameAttribute.cs new file mode 100644 index 000000000..5c257a85a --- /dev/null +++ b/src/Ombi.Api/Attribute/JsonPluralNameAttribute.cs @@ -0,0 +1,17 @@ +using System; + +namespace Ombi.Api +{ + public class JsonPropertyNameBasedOnItemClassAttribute : Attribute + { + } + + public class JsonPluralNameAttribute : Attribute + { + public string PluralName { get; set; } + public JsonPluralNameAttribute(string pluralName) + { + PluralName = pluralName; + } + } +} \ No newline at end of file diff --git a/src/Ombi.Api/Attribute/PluralPropertyContractResolver.cs b/src/Ombi.Api/Attribute/PluralPropertyContractResolver.cs new file mode 100644 index 000000000..28cd6dfba --- /dev/null +++ b/src/Ombi.Api/Attribute/PluralPropertyContractResolver.cs @@ -0,0 +1,33 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using System; +using System.Reflection; + +namespace Ombi.Api +{ + public class PluralPropertyContractResolver : DefaultContractResolver + { + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + JsonProperty prop = base.CreateProperty(member, memberSerialization); + if (prop.PropertyType.IsGenericType && member.GetCustomAttribute() != null) + { + Type itemType = prop.PropertyType.GetGenericArguments()[0]; + JsonPluralNameAttribute att = itemType.GetCustomAttribute(); + prop.PropertyName = att != null ? att.PluralName : Pluralize(itemType.Name); + } + return prop; + } + + protected string Pluralize(string name) + { + if (name.EndsWith("y") && !name.EndsWith("ay") && !name.EndsWith("ey") && !name.EndsWith("oy") && !name.EndsWith("uy")) + return name.Substring(0, name.Length - 1) + "ies"; + + if (name.EndsWith("s")) + return name + "es"; + + return name + "s"; + } + } +} \ No newline at end of file diff --git a/src/Ombi.Api/OmbiHttpClient.cs b/src/Ombi.Api/OmbiHttpClient.cs index 5e9a7f411..0b00664be 100644 --- a/src/Ombi.Api/OmbiHttpClient.cs +++ b/src/Ombi.Api/OmbiHttpClient.cs @@ -47,6 +47,7 @@ namespace Ombi.Api { _cache = cache; _settings = s; + _runtimeVersion = AssemblyHelper.GetRuntimeVersion(); } private static HttpClient _client; @@ -54,6 +55,7 @@ namespace Ombi.Api private readonly ICacheService _cache; private readonly ISettingsService _settings; + private readonly string _runtimeVersion; public async Task SendAsync(HttpRequestMessage request) @@ -84,7 +86,7 @@ namespace Ombi.Api _handler = await GetHandler(); } _client = new HttpClient(_handler); - _client.DefaultRequestHeaders.Add("User-Agent","Ombi"); + _client.DefaultRequestHeaders.Add("User-Agent",$"Ombi/{_runtimeVersion} (https://ombi.io/)"); } } diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 26b843541..fbb90bf5e 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -64,6 +64,7 @@ using Ombi.Schedule.Jobs.SickRage; using Ombi.Schedule.Processor; using Ombi.Store.Entities; using Quartz.Spi; +using Ombi.Api.MusicBrainz; namespace Ombi.DependencyInjection { @@ -145,6 +146,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 ade163151..e4f2860b6 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -24,6 +24,7 @@ + diff --git a/src/Ombi.Helpers/AssemblyHelper.cs b/src/Ombi.Helpers/AssemblyHelper.cs index d2c266369..055d19dc1 100644 --- a/src/Ombi.Helpers/AssemblyHelper.cs +++ b/src/Ombi.Helpers/AssemblyHelper.cs @@ -9,7 +9,7 @@ namespace Ombi.Helpers var version = Assembly.GetEntryAssembly() .GetCustomAttribute() .InformationalVersion; - return version.Equals("1.0.0") ? "3.0.0-develop" : version; + return version.Equals("1.0.0") ? "4.0.0-develop" : version; } } } \ No newline at end of file diff --git a/src/Ombi.sln b/src/Ombi.sln index f4e41db7b..d557516c9 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -106,7 +106,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Test.Common", "Ombi.Te EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Hubs", "Ombi.Hubs\Ombi.Hubs.csproj", "{67416CC5-13B2-44BB-98CE-39DA93D6F70E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.GroupMe", "Ombi.Api.GroupMe\Ombi.Api.GroupMe.csproj", "{9266403C-B04D-4C0F-AC39-82F12C781949}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.GroupMe", "Ombi.Api.GroupMe\Ombi.Api.GroupMe.csproj", "{9266403C-B04D-4C0F-AC39-82F12C781949}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.MusicBrainz", "Ombi.Api.MusicBrainz\Ombi.Api.MusicBrainz.csproj", "{C5C1769B-4197-4410-A160-0EEF39EDDC98}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -286,6 +288,10 @@ Global {9266403C-B04D-4C0F-AC39-82F12C781949}.Debug|Any CPU.Build.0 = Debug|Any CPU {9266403C-B04D-4C0F-AC39-82F12C781949}.Release|Any CPU.ActiveCfg = Release|Any CPU {9266403C-B04D-4C0F-AC39-82F12C781949}.Release|Any CPU.Build.0 = Release|Any CPU + {C5C1769B-4197-4410-A160-0EEF39EDDC98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C5C1769B-4197-4410-A160-0EEF39EDDC98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C5C1769B-4197-4410-A160-0EEF39EDDC98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C5C1769B-4197-4410-A160-0EEF39EDDC98}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -327,6 +333,7 @@ Global {F3969B69-3B07-4884-A7AB-0BAB8B84DF94} = {6F42AB98-9196-44C4-B888-D5E409F415A1} {27111E7C-748E-4996-BD71-2117027C6460} = {6F42AB98-9196-44C4-B888-D5E409F415A1} {9266403C-B04D-4C0F-AC39-82F12C781949} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {C5C1769B-4197-4410-A160-0EEF39EDDC98} = {9293CA11-360A-4C20-A674-B9E794431BF5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869} diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts index 2145ba9e6..5a4dd3562 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts @@ -186,6 +186,7 @@ export interface IAbout { osDescription: string; processArchitecture: string; applicationBasePath: string; + notSupported: boolean; } export interface ICouchPotatoSettings extends IExternalSettings { diff --git a/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.html new file mode 100644 index 000000000..6882790f8 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.html @@ -0,0 +1,211 @@ +
+ +
+ +
+ + + +
+
+ +
+ + + + +
+ + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + +
+ +
+
+
+ + + {{movie.overview}} + + +
+
+ +
+
+ +
+
+ +
+
+ + + + + {{'MediaDetails.RecommendationsTitle' | translate}} + + + +
+ +
+ + +
+
+
+ + + + {{'MediaDetails.SimilarTitle' | translate}} + + + +
+ +
+ + +
+
+
+ + + + {{'MediaDetails.VideosTitle' | translate}} + + + +
+ +
+ +
+
+
+
+
+
+ + + +
+
+ + + + +
+ + + + +
+
+
+ + + + + + + + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.ts new file mode 100644 index 000000000..7b291f9de --- /dev/null +++ b/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.ts @@ -0,0 +1,115 @@ +import { Component, ViewEncapsulation } from "@angular/core"; +import { ImageService, SearchV2Service, RequestService, MessageService } from "../../../services"; +import { ActivatedRoute } from "@angular/router"; +import { DomSanitizer } from "@angular/platform-browser"; +import { ISearchMovieResultV2 } from "../../../interfaces/ISearchMovieResultV2"; +import { MatDialog } from "@angular/material"; +import { YoutubeTrailerComponent } from "../shared/youtube-trailer.component"; +import { AuthService } from "../../../auth/auth.service"; +import { IMovieRequests, RequestType, IAdvancedData } from "../../../interfaces"; +import { DenyDialogComponent } from "../shared/deny-dialog/deny-dialog.component"; +import { NewIssueComponent } from "../shared/new-issue/new-issue.component"; + +@Component({ + templateUrl: "./artist-details.component.html", + styleUrls: ["../../media-details.component.scss"], +}) +export class ArtistDetailsComponent { + public movie: ISearchMovieResultV2; + public hasRequest: boolean; + public movieRequest: IMovieRequests; + public isAdmin: boolean; + public advancedOptions: IAdvancedData; + + private theMovidDbId: number; + + constructor(private searchService: SearchV2Service, private route: ActivatedRoute, + private sanitizer: DomSanitizer, private imageService: ImageService, + public dialog: MatDialog, private requestService: RequestService, + public messageService: MessageService, private auth: AuthService) { + this.route.params.subscribe((params: any) => { + this.theMovidDbId = params.movieDbId; + this.load(); + }); + } + + public load() { + + this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + this.searchService.getFullMovieDetails(this.theMovidDbId).subscribe(async x => { + this.movie = x; + if (this.movie.requestId > 0) { + // Load up this request + this.hasRequest = true; + this.movieRequest = await this.requestService.getMovieRequest(this.movie.requestId); + } + this.imageService.getMovieBanner(this.theMovidDbId.toString()).subscribe(x => { + this.movie.background = this.sanitizer.bypassSecurityTrustStyle + ("url(" + x + ")"); + }); + }); + + } + + public async request() { + const result = await this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId, languageCode: null }).toPromise(); + if (result.result) { + this.movie.requested = true; + this.messageService.send(result.message, "Ok"); + } else { + this.messageService.send(result.errorMessage, "Ok"); + } + } + + public openDialog() { + this.dialog.open(YoutubeTrailerComponent, { + width: '560px', + data: this.movie.videos.results[0].key + }); + } + + public async deny() { + const dialogRef = this.dialog.open(DenyDialogComponent, { + width: '250px', + data: {requestId: this.movieRequest.id, requestType: RequestType.movie} + }); + + dialogRef.afterClosed().subscribe(result => { + this.movieRequest.denied = result; + if(this.movieRequest.denied) { + this.movie.approved = false; + } + }); + } + + public async issue() { + const dialogRef = this.dialog.open(NewIssueComponent, { + width: '500px', + data: {requestId: this.movieRequest ? this.movieRequest.id : null, requestType: RequestType.movie, imdbid: this.movie.imdbId} + }); + } + + public async approve() { + const result = await this.requestService.approveMovie({ id: this.movieRequest.id }).toPromise(); + if (result.result) { + this.movie.approved = false; + this.messageService.send("Successfully Approved", "Ok"); + } else { + this.messageService.send(result.errorMessage, "Ok"); + } + } + + public async markAvailable() { + const result = await this.requestService.markMovieAvailable({id: this.movieRequest.id}).toPromise(); + if (result.result) { + this.movie.available = true; + this.messageService.send(result.message, "Ok"); + } else { + this.messageService.send(result.errorMessage, "Ok"); + } + } + + public setAdvancedOptions(data: any) { + this.advancedOptions = data; + } +} diff --git a/src/Ombi/ClientApp/src/app/media-details/components/index.ts b/src/Ombi/ClientApp/src/app/media-details/components/index.ts index 54fcfd554..5f1a2dd6a 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/index.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/index.ts @@ -14,6 +14,7 @@ import { MovieAdvancedOptionsComponent } from "./movie/panels/movie-advanced-opt import { SearchService, RequestService, RadarrService } from "../../services"; import { RequestServiceV2 } from "../../services/requestV2.service"; import { NewIssueComponent } from "./shared/new-issue/new-issue.component"; +import { ArtistDetailsComponent } from "./artist/artist-details.component"; export const components: any[] = [ MovieDetailsComponent, @@ -30,6 +31,7 @@ export const components: any[] = [ MovieAdminPanelComponent, MovieAdvancedOptionsComponent, NewIssueComponent, + ArtistDetailsComponent, ]; export const entryComponents: any[] = [ diff --git a/src/Ombi/ClientApp/src/app/settings/about/about.component.html b/src/Ombi/ClientApp/src/app/settings/about/about.component.html index ca57adf14..c4989929d 100644 --- a/src/Ombi/ClientApp/src/app/settings/about/about.component.html +++ b/src/Ombi/ClientApp/src/app/settings/about/about.component.html @@ -3,6 +3,9 @@ About
+
+
NOT SUPPORTED OS. Please use the docker image available on the Container Station
+
Users Online
{{connectedUsers.length}}
diff --git a/src/Ombi/Controllers/V1/SettingsController.cs b/src/Ombi/Controllers/V1/SettingsController.cs index c5916a078..dd8f66a9e 100644 --- a/src/Ombi/Controllers/V1/SettingsController.cs +++ b/src/Ombi/Controllers/V1/SettingsController.cs @@ -122,7 +122,8 @@ namespace Ombi.Controllers.V1 OsArchitecture = RuntimeInformation.OSArchitecture.ToString(), OsDescription = RuntimeInformation.OSDescription, ProcessArchitecture = RuntimeInformation.ProcessArchitecture.ToString(), - ApplicationBasePath =Directory.GetCurrentDirectory() + ApplicationBasePath = Directory.GetCurrentDirectory(), + NotSupported = Directory.GetCurrentDirectory().Contains("qpkg") }; var version = AssemblyHelper.GetRuntimeVersion(); diff --git a/src/Ombi/Controllers/V2/SearchController.cs b/src/Ombi/Controllers/V2/SearchController.cs index 070d54d33..6cceb86aa 100644 --- a/src/Ombi/Controllers/V2/SearchController.cs +++ b/src/Ombi/Controllers/V2/SearchController.cs @@ -5,7 +5,8 @@ using Microsoft.AspNetCore.Http; using System.Threading.Tasks; using System.Collections.Generic; - +using Ombi.Api.MusicBrainz; +using Ombi.Api.MusicBrainz.Models.Search; using Ombi.Core; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Engine.V2; @@ -22,7 +23,7 @@ namespace Ombi.Controllers.V2 public class SearchController : ControllerBase { public SearchController(IMultiSearchEngine multiSearchEngine, ITvSearchEngine tvSearchEngine, - IMovieEngineV2 v2Movie, ITVSearchEngineV2 v2Tv) + IMovieEngineV2 v2Movie, ITVSearchEngineV2 v2Tv, IMusicBrainzApi musicApi) { _multiSearchEngine = multiSearchEngine; _tvSearchEngine = tvSearchEngine; @@ -30,12 +31,14 @@ namespace Ombi.Controllers.V2 _movieEngineV2 = v2Movie; _movieEngineV2.ResultLimit = 12; _tvEngineV2 = v2Tv; + music = musicApi; } private readonly IMultiSearchEngine _multiSearchEngine; private readonly IMovieEngineV2 _movieEngineV2; private readonly ITVSearchEngineV2 _tvEngineV2; private readonly ITvSearchEngine _tvSearchEngine; + private readonly IMusicBrainzApi music; /// /// Returns search results for both TV and Movies @@ -334,5 +337,15 @@ namespace Ombi.Controllers.V2 { return await _movieEngineV2.GetMoviesByActor(actorId, null); } + + + [HttpGet("artist/{name}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task> GetArtists(string name) + { + return await music.SearchArtist(name); + } + } } \ No newline at end of file diff --git a/src/Ombi/Models/AboutViewModel.cs b/src/Ombi/Models/AboutViewModel.cs index 457cbd44d..fc16e3d70 100644 --- a/src/Ombi/Models/AboutViewModel.cs +++ b/src/Ombi/Models/AboutViewModel.cs @@ -9,5 +9,6 @@ public string OsDescription { get; set; } public string ProcessArchitecture { get; set; } public string ApplicationBasePath { get; set; } + public bool NotSupported { get; set; } } } \ No newline at end of file