From 3008cd124d8454024d1de6340497fd4f91d3e815 Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Sat, 19 Oct 2019 00:53:27 -0500 Subject: [PATCH] Add adult movie filtering --- src/Ombi.Api/Request.cs | 19 +-- .../Models/External/TheMovieDbSettings.cs | 9 ++ src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 122 ++++++++++++------ .../ClientApp/app/interfaces/ISettings.ts | 5 + .../app/services/settings.service.ts | 9 ++ .../ClientApp/app/settings/settings.module.ts | 3 + .../app/settings/settingsmenu.component.html | 1 + .../themoviedb/themoviedb.component.html | 29 +++++ .../themoviedb/themoviedb.component.ts | 32 +++++ src/Ombi/Controllers/SettingsController.cs | 19 +++ 10 files changed, 187 insertions(+), 61 deletions(-) create mode 100644 src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs create mode 100644 src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html create mode 100644 src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts diff --git a/src/Ombi.Api/Request.cs b/src/Ombi.Api/Request.cs index fd888d0d2..918e189fe 100644 --- a/src/Ombi.Api/Request.cs +++ b/src/Ombi.Api/Request.cs @@ -93,24 +93,7 @@ namespace Ombi.Api public void AddQueryString(string key, string value) { if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) return; - - var builder = new UriBuilder(FullUri); - var startingTag = string.Empty; - var hasQuery = false; - if (string.IsNullOrEmpty(builder.Query)) - { - startingTag = "?"; - } - else - { - hasQuery = true; - startingTag = builder.Query.Contains("?") ? "&" : "?"; - } - builder.Query = hasQuery - ? $"{builder.Query}{startingTag}{key}={value}" - : $"{startingTag}{key}={value}"; - - _modified = builder.Uri; + _modified = FullUri.AddQueryParameter(key, value); } public void AddJsonBody(object obj) diff --git a/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs new file mode 100644 index 000000000..562d9fc88 --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs @@ -0,0 +1,9 @@ +namespace Ombi.Core.Settings.Models.External +{ + public sealed class TheMovieDbSettings : Ombi.Settings.Settings.Models.Settings + { + public bool ShowAdultMovies { get; set; } + + public string ExcludedKeywordIds { get; set; } + } +} diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 79ccc5bb7..7c24d4c60 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -1,31 +1,36 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Threading.Tasks; using AutoMapper; +using Nito.AsyncEx; using Ombi.Api.TheMovieDb.Models; -using Ombi.Helpers; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; using Ombi.TheMovieDbApi.Models; namespace Ombi.Api.TheMovieDb { public class TheMovieDbApi : IMovieDbApi { - public TheMovieDbApi(IMapper mapper, IApi api) + public TheMovieDbApi(IMapper mapper, IApi api, ISettingsService settingsService) { Api = api; Mapper = mapper; + Settings = new AsyncLazy(() => settingsService.GetSettingsAsync()); } + private const string ApiToken = "b8eabaf5608b88d0298aa189dd90bf00"; + private const string BaseUri ="http://api.themoviedb.org/3/"; private IMapper Mapper { get; } - private readonly string ApiToken = "b8eabaf5608b88d0298aa189dd90bf00"; - private static readonly string BaseUri ="http://api.themoviedb.org/3/"; private IApi Api { get; } + private AsyncLazy Settings { get; } public async Task GetMovieInformation(int movieId) { var request = new Request($"movie/{movieId}", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.AddQueryString("api_key", ApiToken); AddRetry(request); var result = await Api.Request(request); @@ -35,7 +40,7 @@ namespace Ombi.Api.TheMovieDb public async Task Find(string externalId, ExternalSource source) { var request = new Request($"find/{externalId}", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.AddQueryString("api_key", ApiToken); AddRetry(request); request.AddQueryString("external_source", source.ToString()); @@ -46,9 +51,11 @@ namespace Ombi.Api.TheMovieDb public async Task> SearchByActor(string searchTerm, string langCode) { var request = new Request($"search/person", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("query", searchTerm); - request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("query", searchTerm); + request.AddQueryString("language", langCode); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); var result = await Api.Request>(request); return result; @@ -57,8 +64,8 @@ namespace Ombi.Api.TheMovieDb public async Task GetActorMovieCredits(int actorId, string langCode) { var request = new Request($"person/{actorId}/movie_credits", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); var result = await Api.Request(request); return result; @@ -67,8 +74,8 @@ namespace Ombi.Api.TheMovieDb public async Task> SearchTv(string searchTerm) { var request = new Request($"search/tv", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("query", searchTerm); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("query", searchTerm); AddRetry(request); var result = await Api.Request>(request); @@ -78,7 +85,7 @@ namespace Ombi.Api.TheMovieDb public async Task GetTvExternals(int theMovieDbId) { var request = new Request($"/tv/{theMovieDbId}/external_ids", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.AddQueryString("api_key", ApiToken); AddRetry(request); return await Api.Request(request); @@ -87,9 +94,8 @@ namespace Ombi.Api.TheMovieDb public async Task> SimilarMovies(int movieId, string langCode) { var request = new Request($"movie/{movieId}/similar", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - - request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); AddRetry(request); var result = await Api.Request>(request); @@ -99,65 +105,95 @@ namespace Ombi.Api.TheMovieDb public async Task GetMovieInformationWithExtraInfo(int movieId, string langCode = "en") { var request = new Request($"movie/{movieId}", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("append_to_response", "videos,release_dates"); - request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("append_to_response", "videos,release_dates"); + request.AddQueryString("language", langCode); AddRetry(request); var result = await Api.Request(request); return Mapper.Map(result); } - public async Task> SearchMovie(string searchTerm, int? year, string langageCode) + public async Task> SearchMovie(string searchTerm, int? year, string langCode) { var request = new Request($"search/movie", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("query", searchTerm); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("query", searchTerm); + request.AddQueryString("language", langCode); if (year.HasValue && year.Value > 0) { - request.FullUri = request.FullUri.AddQueryParameter("year", year.Value.ToString()); + request.AddQueryString("year", year.Value.ToString()); } + + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> PopularMovies(string langageCode) + public async Task> PopularMovies(string langCode) { - var request = new Request($"movie/popular", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> TopRated(string langageCode) + public async Task> TopRated(string langCode) { - var request = new Request($"movie/top_rated", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + request.AddQueryString("vote_count.gte", "250"); + request.AddQueryString("sort_by", "vote_average.desc"); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> Upcoming(string langageCode) + public async Task> Upcoming(string langCode) { - var request = new Request($"movie/upcoming", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + request.AddQueryString("with_release_type", "2|3"); + var startDate = DateTime.Today.AddDays(7); + request.AddQueryString("release_date.gte", startDate.ToString("yyyy-MM-dd")); + request.AddQueryString("release_date.lte", startDate.AddDays(17).ToString("yyyy-MM-dd")); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> NowPlaying(string langageCode) + public async Task> NowPlaying(string langCode) { - var request = new Request($"movie/now_playing", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + request.AddQueryString("with_release_type", "2|3"); + var today = DateTime.Today; + request.AddQueryString("release_date.gte", today.AddDays(-42).ToString("yyyy-MM-dd")); + request.AddQueryString("release_date.lte", today.AddDays(6).ToString("yyyy-MM-dd")); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); @@ -166,7 +202,7 @@ namespace Ombi.Api.TheMovieDb public async Task GetTVInfo(string themoviedbid) { var request = new Request($"/tv/{themoviedbid}", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.AddQueryString("api_key", ApiToken); AddRetry(request); return await Api.Request(request); diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 75aaf7605..26892ca6e 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -245,3 +245,8 @@ export interface IVoteSettings extends ISettings { musicVoteMax: number; tvShowVoteMax: number; } + +export interface ITheMovieDbSettings extends ISettings { + showAdultMovies: boolean; + excludedKeywordIds: string; +} diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index a80cfd772..8c7787b6d 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -32,6 +32,7 @@ import { ISlackNotificationSettings, ISonarrSettings, ITelegramNotifcationSettings, + ITheMovieDbSettings, IUpdateSettings, IUserManagementSettings, IVoteSettings, @@ -301,6 +302,14 @@ export class SettingsService extends ServiceHelpers { return this.http.post(`${this.url}/vote`, JSON.stringify(settings), {headers: this.headers}); } + public getTheMovieDbSettings(): Observable { + return this.http.get(`${this.url}/themoviedb`, {headers: this.headers}); + } + + public saveTheMovieDbSettings(settings: ITheMovieDbSettings) { + return this.http.post(`${this.url}/themoviedb`, JSON.stringify(settings), {headers: this.headers}); + } + public getNewsletterSettings(): Observable { return this.http.get(`${this.url}/notifications/newsletter`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 6fb69dc27..4d672d622 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -36,6 +36,7 @@ import { PushbulletComponent } from "./notifications/pushbullet.component"; import { PushoverComponent } from "./notifications/pushover.component"; import { SlackComponent } from "./notifications/slack.component"; import { TelegramComponent } from "./notifications/telegram.component"; +import { TheMovieDbComponent } from "./themoviedb/themoviedb.component"; import { OmbiComponent } from "./ombi/ombi.component"; import { PlexComponent } from "./plex/plex.component"; import { RadarrComponent } from "./radarr/radarr.component"; @@ -80,6 +81,7 @@ const routes: Routes = [ { path: "Newsletter", component: NewsletterComponent, canActivate: [AuthGuard] }, { path: "Lidarr", component: LidarrComponent, canActivate: [AuthGuard] }, { path: "Vote", component: VoteComponent, canActivate: [AuthGuard] }, + { path: "TheMovieDb", component: TheMovieDbComponent, canActivate: [AuthGuard] }, { path: "FailedRequests", component: FailedRequestsComponent, canActivate: [AuthGuard] }, ]; @@ -135,6 +137,7 @@ const routes: Routes = [ NewsletterComponent, LidarrComponent, VoteComponent, + TheMovieDbComponent, FailedRequestsComponent, ], exports: [ diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index d58c96e2e..686f4c020 100644 --- a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html @@ -13,6 +13,7 @@
  • User Importer
  • Authentication
  • Vote
  • +
  • The Movie Database
  • diff --git a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html new file mode 100644 index 000000000..afce968c2 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html @@ -0,0 +1,29 @@ + + +
    + The Movie Database +
    +
    +
    + + +
    +
    + +
    + +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts new file mode 100644 index 000000000..e167d3009 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from "@angular/core"; + +import { ITheMovieDbSettings } from "../../interfaces"; +import { NotificationService } from "../../services"; +import { SettingsService } from "../../services"; + +@Component({ + templateUrl: "./themoviedb.component.html", +}) +export class TheMovieDbComponent implements OnInit { + + public settings: ITheMovieDbSettings; + public advanced: boolean; + + constructor(private settingsService: SettingsService, private notificationService: NotificationService) { } + + public ngOnInit() { + this.settingsService.getTheMovieDbSettings().subscribe(x => { + this.settings = x; + }); + } + + public save() { + this.settingsService.saveTheMovieDbSettings(this.settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved The Movie Database settings"); + } else { + this.notificationService.success("There was an error when saving The Movie Database settings"); + } + }); + } +} diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index ebc2fbe66..6033ae2ca 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -659,6 +659,25 @@ namespace Ombi.Controllers return vote.Enabled; } + /// + /// Save The Movie DB settings. + /// + /// The settings. + [HttpPost("themoviedb")] + public async Task TheMovieDbSettings([FromBody]TheMovieDbSettings settings) + { + return await Save(settings); + } + + /// + /// Get The Movie DB settings. + /// + [HttpGet("themoviedb")] + public async Task TheMovieDbSettings() + { + return await Get(); + } + /// /// Saves the email notification settings. ///