mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-03-12 04:35:27 -07:00
feat(discover): Add original language filter
This commit is contained in:
parent
eea8663f7d
commit
ef7ec861d8
src
Ombi.Core/Engine/V2
Ombi.Settings/Settings/Models/External
Ombi.TheMovieDbApi
Ombi
ClientApp/src/app
interfaces
services
settings/themoviedb
Controllers/V2
@ -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<List<MultiSearchResult>> MultiSearch(string searchTerm, MultiSearchFilter filter, CancellationToken cancellationToken);
|
||||
Task<IEnumerable<Genre>> GetGenres(string media, CancellationToken requestAborted);
|
||||
Task<IEnumerable<Language>> GetLanguages(CancellationToken requestAborted);
|
||||
}
|
||||
}
|
@ -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<IEnumerable<Language>> GetLanguages(CancellationToken cancellationToken)
|
||||
{
|
||||
return await _movieDbApi.GetLanguages(cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,5 +11,7 @@ namespace Ombi.Core.Settings.Models.External
|
||||
public List<int> ExcludedMovieGenreIds { get; set; }
|
||||
|
||||
public List<int> ExcludedTvGenreIds { get; set; }
|
||||
|
||||
public List<string> OriginalLanguages { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ namespace Ombi.Api.TheMovieDb
|
||||
Task<WatchProviders> GetMovieWatchProviders(int theMoviedbId, CancellationToken token);
|
||||
Task<WatchProviders> GetTvWatchProviders(int theMoviedbId, CancellationToken token);
|
||||
Task<List<Genre>> GetGenres(string media, CancellationToken cancellationToken, string languageCode);
|
||||
Task<List<Language>> GetLanguages(CancellationToken cancellationToken);
|
||||
Task<List<WatchProvidersResults>> SearchWatchProviders(string media, string searchTerm, CancellationToken cancellationToken);
|
||||
Task<List<MovieDbSearchResult>> AdvancedSearch(DiscoverModel model, CancellationToken cancellationToken);
|
||||
}
|
||||
|
14
src/Ombi.TheMovieDbApi/Models/Language.cs
Normal file
14
src/Ombi.TheMovieDbApi/Models/Language.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
@ -438,6 +438,16 @@ namespace Ombi.Api.TheMovieDb
|
||||
return result.genres ?? new List<Genre>();
|
||||
}
|
||||
|
||||
public async Task<List<Language>> GetLanguages(CancellationToken cancellationToken)
|
||||
{
|
||||
var request = new Request($"/configuration/languages", BaseUri, HttpMethod.Get);
|
||||
request.AddQueryString("api_key", ApiToken);
|
||||
AddRetry(request);
|
||||
|
||||
var result = await Api.Request<List<Language>>(request, cancellationToken);
|
||||
return result ?? new List<Language>();
|
||||
}
|
||||
|
||||
public Task<TheMovieDbContainer<MultiSearch>> 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)
|
||||
|
@ -17,3 +17,8 @@ export interface IDiscoverModel {
|
||||
watchProviders?: number[];
|
||||
companies?: number[];
|
||||
}
|
||||
export interface ILanguage {
|
||||
iso_639_1 : string;
|
||||
english_name : string;
|
||||
name : string;
|
||||
}
|
||||
|
@ -339,7 +339,8 @@ export interface ITheMovieDbSettings extends ISettings {
|
||||
showAdultMovies: boolean;
|
||||
excludedKeywordIds: number[];
|
||||
excludedMovieGenreIds: number[];
|
||||
excludedTvGenreIds: number[]
|
||||
excludedTvGenreIds: number[];
|
||||
originalLanguages: string[];
|
||||
}
|
||||
|
||||
export interface IUpdateModel
|
||||
|
@ -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<IMultiSearchResult[]> {
|
||||
return this.http.post<IMultiSearchResult[]>(`${this.url}/multi/${encodeURIComponent(searchTerm)}`, filter);
|
||||
}
|
||||
|
||||
|
||||
public getGenres(media: string): Observable<IMovieDbKeyword[]> {
|
||||
return this.http.get<IMovieDbKeyword[]>(`${this.url}/Genres/${media}`, { headers: this.headers })
|
||||
}
|
||||
|
||||
public getLanguages(): Observable<ILanguage[]> {
|
||||
return this.http.get<ILanguage[]>(`${this.url}/Languages`, { headers: this.headers })
|
||||
}
|
||||
|
||||
public getFullMovieDetails(theMovieDbId: number): Observable<ISearchMovieResultV2> {
|
||||
return this.http.get<ISearchMovieResultV2>(`${this.url}/Movie/${theMovieDbId}`);
|
||||
}
|
||||
|
@ -13,6 +13,14 @@
|
||||
|
||||
<div class="form-group">
|
||||
<form [formGroup]='tagForm'>
|
||||
<mat-form-field appearance="outline" >
|
||||
<mat-label>Original languages</mat-label>
|
||||
<mat-select multiple formControlName="originalLanguages" [(value)]="settings.originalLanguages" matTooltip="Filter content by original language.">
|
||||
<mat-option *ngFor="let language of languages" [value]="language.iso_639_1">
|
||||
{{language.english_name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="example-full-width">
|
||||
<input type="text" placeholder="Excluded Keyword IDs for Movie & TV Suggestions" matInput
|
||||
@ -33,7 +41,7 @@
|
||||
<i matChipRemove class="fas fa-times fa-lg"></i>
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
|
||||
|
||||
<div class="md-form-field" style="margin-top:1em;">
|
||||
<mat-form-field appearance="outline" >
|
||||
<mat-label>Movie Genres</mat-label>
|
||||
@ -51,7 +59,7 @@
|
||||
{{key.name}}
|
||||
<i matChipRemove class="fas fa-times fa-lg"></i>
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</mat-chip-list>
|
||||
|
||||
<div class="md-form-field" style="margin-top:1em;">
|
||||
<mat-form-field appearance="outline" >
|
||||
|
@ -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 {
|
||||
|
@ -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<IEnumerable<Language>> GetLanguages()
|
||||
{
|
||||
return _multiSearchEngine.GetLanguages(HttpContext.RequestAborted);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns details for a single movie
|
||||
/// </summary>
|
||||
|
Loading…
x
Reference in New Issue
Block a user