From ef7ec861d8aede2a4817752c990617f583805391 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Sat, 23 Apr 2022 12:42:30 +0200 Subject: [PATCH 1/2] feat(discover): Add original language filter --- src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs | 2 + src/Ombi.Core/Engine/V2/MultiSearchEngine.cs | 5 ++ .../Models/External/TheMovieDbSettings.cs | 2 + src/Ombi.TheMovieDbApi/IMovieDbApi.cs | 1 + src/Ombi.TheMovieDbApi/Models/Language.cs | 14 +++++ src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 14 +++++ .../ClientApp/src/app/interfaces/IMovieDb.ts | 5 ++ .../ClientApp/src/app/interfaces/ISettings.ts | 3 +- .../src/app/services/searchV2.service.ts | 8 ++- .../themoviedb/themoviedb.component.html | 12 ++++- .../themoviedb/themoviedb.component.ts | 53 +++++++++++-------- src/Ombi/Controllers/V2/SearchController.cs | 7 +++ 12 files changed, 100 insertions(+), 26 deletions(-) create mode 100644 src/Ombi.TheMovieDbApi/Models/Language.cs diff --git a/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs index 7ad8c509a..7666db6fe 100644 --- a/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs +++ b/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Threading.Tasks; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Models.Search.V2; +using Ombi.TheMovieDbApi.Models; // Due to conflicting Genre models in // Ombi.TheMovieDbApi.Models and Ombi.Api.TheMovieDb.Models @@ -14,5 +15,6 @@ namespace Ombi.Core.Engine.V2 { Task> MultiSearch(string searchTerm, MultiSearchFilter filter, CancellationToken cancellationToken); Task> GetGenres(string media, CancellationToken requestAborted); + Task> GetLanguages(CancellationToken requestAborted); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs index 362a79e43..3f96f1598 100644 --- a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs +++ b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs @@ -17,6 +17,7 @@ using Ombi.Settings.Settings.Models; using Ombi.Settings.Settings.Models.External; using Ombi.Store.Entities; using Ombi.Store.Repository; +using Ombi.TheMovieDbApi.Models; // Due to conflicting Genre models in // Ombi.TheMovieDbApi.Models and Ombi.Api.TheMovieDb.Models @@ -124,5 +125,9 @@ namespace Ombi.Core.Engine.V2 var lang = await DefaultLanguageCode(null); return await _movieDbApi.GetGenres(media, cancellationToken, lang); } + public async Task> GetLanguages(CancellationToken cancellationToken) + { + return await _movieDbApi.GetLanguages(cancellationToken); + } } } diff --git a/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs index c2df1b9b3..cbb0233a0 100644 --- a/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs @@ -11,5 +11,7 @@ namespace Ombi.Core.Settings.Models.External public List ExcludedMovieGenreIds { get; set; } public List ExcludedTvGenreIds { get; set; } + + public List OriginalLanguages { get; set; } } } diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs index dc2e5525c..51da958b6 100644 --- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -41,6 +41,7 @@ namespace Ombi.Api.TheMovieDb Task GetMovieWatchProviders(int theMoviedbId, CancellationToken token); Task GetTvWatchProviders(int theMoviedbId, CancellationToken token); Task> GetGenres(string media, CancellationToken cancellationToken, string languageCode); + Task> GetLanguages(CancellationToken cancellationToken); Task> SearchWatchProviders(string media, string searchTerm, CancellationToken cancellationToken); Task> AdvancedSearch(DiscoverModel model, CancellationToken cancellationToken); } diff --git a/src/Ombi.TheMovieDbApi/Models/Language.cs b/src/Ombi.TheMovieDbApi/Models/Language.cs new file mode 100644 index 000000000..c6b14a654 --- /dev/null +++ b/src/Ombi.TheMovieDbApi/Models/Language.cs @@ -0,0 +1,14 @@ +using Newtonsoft.Json; + +namespace Ombi.TheMovieDbApi.Models +{ + public class Language + { + [JsonProperty("iso_639_1")] + public string Id { get; set; } + [JsonProperty("english_name")] + public string EnglishName { get; set; } + [JsonProperty("name")] + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 335ea7da3..02862fb7d 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -438,6 +438,16 @@ namespace Ombi.Api.TheMovieDb return result.genres ?? new List(); } + public async Task> GetLanguages(CancellationToken cancellationToken) + { + var request = new Request($"/configuration/languages", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + AddRetry(request); + + var result = await Api.Request>(request, cancellationToken); + return result ?? new List(); + } + public Task> MultiSearch(string searchTerm, string languageCode, CancellationToken cancellationToken) { var request = new Request("search/multi", BaseUri, HttpMethod.Get); @@ -472,6 +482,10 @@ namespace Ombi.Api.TheMovieDb { request.AddQueryString("without_keywords", string.Join(",", settings.ExcludedKeywordIds)); } + if (settings.OriginalLanguages?.Any() == true) + { + request.AddQueryString("with_original_language", string.Join("|", settings.OriginalLanguages)); + } } private async Task AddGenreFilter(Request request, string media_type) diff --git a/src/Ombi/ClientApp/src/app/interfaces/IMovieDb.ts b/src/Ombi/ClientApp/src/app/interfaces/IMovieDb.ts index f82225434..77352de4b 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IMovieDb.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IMovieDb.ts @@ -17,3 +17,8 @@ export interface IDiscoverModel { watchProviders?: number[]; companies?: number[]; } +export interface ILanguage { + iso_639_1 : string; + english_name : string; + name : string; +} diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts index 95b1fba00..4594d2a2f 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts @@ -339,7 +339,8 @@ export interface ITheMovieDbSettings extends ISettings { showAdultMovies: boolean; excludedKeywordIds: number[]; excludedMovieGenreIds: number[]; - excludedTvGenreIds: number[] + excludedTvGenreIds: number[]; + originalLanguages: string[]; } export interface IUpdateModel diff --git a/src/Ombi/ClientApp/src/app/services/searchV2.service.ts b/src/Ombi/ClientApp/src/app/services/searchV2.service.ts index c80655370..56b1057c6 100644 --- a/src/Ombi/ClientApp/src/app/services/searchV2.service.ts +++ b/src/Ombi/ClientApp/src/app/services/searchV2.service.ts @@ -4,7 +4,7 @@ import { Injectable, Inject } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { IDiscoverModel, IMovieDbKeyword, IMultiSearchResult, ISearchMovieResult, ISearchTvResult } from "../interfaces"; +import { IDiscoverModel, ILanguage, IMovieDbKeyword, IMultiSearchResult, ISearchMovieResult, ISearchTvResult } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; import { ISearchMovieResultV2 } from "../interfaces/ISearchMovieResultV2"; @@ -23,11 +23,15 @@ export class SearchV2Service extends ServiceHelpers { public multiSearch(searchTerm: string, filter: SearchFilter): Observable { return this.http.post(`${this.url}/multi/${encodeURIComponent(searchTerm)}`, filter); } - + public getGenres(media: string): Observable { return this.http.get(`${this.url}/Genres/${media}`, { headers: this.headers }) } + public getLanguages(): Observable { + return this.http.get(`${this.url}/Languages`, { headers: this.headers }) + } + public getFullMovieDetails(theMovieDbId: number): Observable { return this.http.get(`${this.url}/Movie/${theMovieDbId}`); } diff --git a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.html b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.html index fb10cc142..d01768947 100644 --- a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.html +++ b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.html @@ -13,6 +13,14 @@
+ + Original languages + + + {{language.english_name}} + + + - +
Movie Genres @@ -51,7 +59,7 @@ {{key.name}} - +
diff --git a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts index 512f60363..7f4076e87 100644 --- a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts @@ -1,7 +1,7 @@ import {COMMA, ENTER} from "@angular/cdk/keycodes"; import { Component, ElementRef, OnInit, ViewChild } from "@angular/core"; import { FormBuilder, FormGroup } from "@angular/forms"; -import { IMovieDbKeyword, ITheMovieDbSettings } from "../../interfaces"; +import { ILanguage, IMovieDbKeyword, ITheMovieDbSettings } from "../../interfaces"; import { debounceTime, switchMap } from "rxjs/operators"; import { MatAutocomplete } from "@angular/material/autocomplete"; @@ -22,14 +22,17 @@ interface IKeywordTag { export class TheMovieDbComponent implements OnInit { public settings: ITheMovieDbSettings; + public originalLanguages: ILanguage[]; public excludedKeywords: IKeywordTag[]; public excludedMovieGenres: IKeywordTag[]; public excludedTvGenres: IKeywordTag[]; public tagForm: FormGroup; + public languages: ILanguage[]; public filteredTags: IMovieDbKeyword[]; public filteredMovieGenres: IMovieDbKeyword[]; public filteredTvGenres: IMovieDbKeyword[]; + constructor(private settingsService: SettingsService, private notificationService: NotificationService, private tmdbService: TheMovieDbService, @@ -37,14 +40,30 @@ export class TheMovieDbComponent implements OnInit { private fb: FormBuilder) { } public ngOnInit() { - this.tagForm = this.fb.group({ - input: null, - excludedMovieGenres: null, - excludedTvGenres: null, - }); this.settingsService.getTheMovieDbSettings().subscribe(settings => { this.settings = settings; + this.tagForm = this.fb.group({ + input: null, + originalLanguages: [this.settings.originalLanguages], + excludedMovieGenres: null, + excludedTvGenres: null, + }); + + this.tagForm + .get("input") + .valueChanges.pipe( + debounceTime(600), + switchMap((value: string) => { + if (value) { + return this.tmdbService.getKeywords(value); + } + return []; + }) + ) + .subscribe((r) => (this.filteredTags = r)); + + // Map Keyword ids -> keyword name this.excludedKeywords = settings.excludedKeywordIds ? settings.excludedKeywordIds.map(id => ({ @@ -82,8 +101,12 @@ export class TheMovieDbComponent implements OnInit { } }); }); - }); - + }); + + this.searchService.getLanguages().subscribe((results) => { + this.languages = results.sort((a: ILanguage, b: ILanguage) => (a.english_name > b.english_name) ? 1 : -1);; + }); + // Map Tv Genre ids -> genre name this.excludedTvGenres = settings.excludedTvGenreIds ? settings.excludedTvGenreIds.map(id => ({ @@ -102,22 +125,10 @@ export class TheMovieDbComponent implements OnInit { genre.name = result.name; } }); - }); + }); }); }); - this.tagForm - .get("input") - .valueChanges.pipe( - debounceTime(600), - switchMap((value: string) => { - if (value) { - return this.tmdbService.getKeywords(value); - } - return []; - }) - ) - .subscribe((r) => (this.filteredTags = r)); } public remove(tag: IKeywordTag, tag_type: string): void { diff --git a/src/Ombi/Controllers/V2/SearchController.cs b/src/Ombi/Controllers/V2/SearchController.cs index fc970b793..5227f06ec 100644 --- a/src/Ombi/Controllers/V2/SearchController.cs +++ b/src/Ombi/Controllers/V2/SearchController.cs @@ -19,6 +19,7 @@ using Ombi.Helpers; // Due to conflicting Genre models in // Ombi.TheMovieDbApi.Models and Ombi.Api.TheMovieDb.Models using Genre = Ombi.TheMovieDbApi.Models.Genre; +using Ombi.TheMovieDbApi.Models; namespace Ombi.Controllers.V2 { @@ -69,6 +70,12 @@ namespace Ombi.Controllers.V2 return _multiSearchEngine.GetGenres(media, HttpContext.RequestAborted); } + [HttpGet("Languages")] + public Task> GetLanguages() + { + return _multiSearchEngine.GetLanguages(HttpContext.RequestAborted); + } + /// /// Returns details for a single movie /// From 3cc84778a46191fc0c8d87e2222bef8210cb9351 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Mon, 25 Apr 2022 15:10:57 +0200 Subject: [PATCH 2/2] Add information about cache refresh --- .../src/app/settings/themoviedb/themoviedb.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts index 7f4076e87..02ce9dc1d 100644 --- a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts @@ -173,7 +173,7 @@ export class TheMovieDbComponent implements OnInit { this.settingsService.saveTheMovieDbSettings(this.settings).subscribe(x => { if (x) { - this.notificationService.success("Successfully saved The Movie Database settings"); + this.notificationService.success("Successfully saved The Movie Database settings. Restart the server to refresh the cache."); } else { this.notificationService.success("There was an error when saving The Movie Database settings"); }