diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bfe7e633..ecb1a790d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,30 @@ ### **New Features** +- Added a new Job. Plex Recently Added, this is a slimmed down version of the Plex Sync job, this will just scan the recently added list and not the whole library. I'd reccomend running this very regulary and the full scan not as regular. [Jamie] + +### **Fixes** + +- Add web-app-capable for IOS and Android. [Thomas] + +- Fixed the bug where the newsletter CRON was not appearing on the job settings page. [Jamie] + +- Add base url as a startup argument #2153. [Jamie Rees] + +- Fixed a bug with the RefreshMetadata where we would never get TheMovieDBId's if it was missing it. [Jamie] + + +## v3.0.3173 (2018-04-12) + +### **Fixes** + +- Removed some early disposition that seemed to be causing errors in the API. [Jamie] + + +## v3.0.3164 (2018-04-10) + +### **New Features** + - Added the ability to send newsletter out to users that are not in Ombi. [Jamie] - Added the ability to turn off TV or Movies from the newsletter. [Jamie] @@ -56,6 +80,12 @@ - Fixed the issue where movies were not appearing in the newsletter for users with Emby #2111. [Jamie] +- The fact that this button has another style really bothers me. [Louis Laureys] + +- Fix discord current user count. [Avi] + +- Fix broken images and new discord invite. [Avi] + ## v3.0.3111 (2018-03-27) diff --git a/src/Ombi.Api.Plex/IPlexApi.cs b/src/Ombi.Api.Plex/IPlexApi.cs index e11d6d914..0734262cf 100644 --- a/src/Ombi.Api.Plex/IPlexApi.cs +++ b/src/Ombi.Api.Plex/IPlexApi.cs @@ -19,5 +19,6 @@ public interface IPlexApi Task GetAllEpisodes(string authToken, string host, string section, int start, int retCount); Task GetUsers(string authToken); Task GetAccount(string authToken); + Task GetRecentlyAdded(string authToken, string uri, string sectionId); } } \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Models/Metadata.cs b/src/Ombi.Api.Plex/Models/Metadata.cs index 28bdf002d..dcde62818 100644 --- a/src/Ombi.Api.Plex/Models/Metadata.cs +++ b/src/Ombi.Api.Plex/Models/Metadata.cs @@ -23,8 +23,8 @@ public class Metadata public int leafCount { get; set; } public int viewedLeafCount { get; set; } public int childCount { get; set; } - public long addedAt { get; set; } - public int updatedAt { get; set; } + //public long addedAt { get; set; } + //public int updatedAt { get; set; } public Genre[] Genre { get; set; } //public Role[] Role { get; set; } public string primaryExtraKey { get; set; } diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index b5c6b958d..e6c52d1df 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -147,6 +147,15 @@ public async Task GetUsers(string authToken) return await Api.Request(request); } + public async Task GetRecentlyAdded(string authToken, string uri, string sectionId) + { + var request = new Request($"library/sections/{sectionId}/recentlyAdded", uri, HttpMethod.Get); + AddHeaders(request, authToken); + AddLimitHeaders(request, 0, 50); + + return await Api.Request(request); + } + /// /// Adds the required headers and also the authorization header /// diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index aaa2d353d..7671c13fc 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -1,6 +1,7 @@ using System; using AutoMapper; using Ombi.Api.TvMaze; +using Ombi.Api.TheMovieDb; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Helpers; @@ -26,11 +27,12 @@ namespace Ombi.Core.Engine { public class TvRequestEngine : BaseMediaEngine, ITvRequestEngine { - public TvRequestEngine(ITvMazeApi tvApi, IRequestServiceMain requestService, IPrincipal user, + public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, IPrincipal user, INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager, ITvSender sender, IAuditRepository audit, IRepository rl, ISettingsService settings, ICacheService cache) : base(user, requestService, rule, manager, cache, settings) { TvApi = tvApi; + MovieDbApi = movApi; NotificationHelper = helper; TvSender = sender; Audit = audit; @@ -39,6 +41,7 @@ public TvRequestEngine(ITvMazeApi tvApi, IRequestServiceMain requestService, IPr private INotificationHelper NotificationHelper { get; } private ITvMazeApi TvApi { get; } + private IMovieDbApi MovieDbApi { get; } private ITvSender TvSender { get; } private IAuditRepository Audit { get; } private readonly IRepository _requestLog; @@ -47,7 +50,7 @@ public async Task RequestTvShow(TvRequestViewModel tv) { var user = await GetUser(); - var tvBuilder = new TvShowRequestBuilder(TvApi); + var tvBuilder = new TvShowRequestBuilder(TvApi, MovieDbApi); (await tvBuilder .GetShowInfo(tv.TvDbId)) .CreateTvList(tv) diff --git a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs index 1f92536b8..6e4d20be8 100644 --- a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs +++ b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs @@ -3,7 +3,9 @@ using System.Linq; using System.Threading.Tasks; using Ombi.Api.TvMaze; +using Ombi.Api.TheMovieDb; using Ombi.Api.TvMaze.Models; +using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Helpers; @@ -16,12 +18,14 @@ namespace Ombi.Core.Helpers public class TvShowRequestBuilder { - public TvShowRequestBuilder(ITvMazeApi tvApi) + public TvShowRequestBuilder(ITvMazeApi tvApi, IMovieDbApi movApi) { TvApi = tvApi; + MovieDbApi = movApi; } private ITvMazeApi TvApi { get; } + private IMovieDbApi MovieDbApi { get; } public ChildRequests ChildRequest { get; set; } public List TvRequests { get; protected set; } @@ -29,10 +33,20 @@ public TvShowRequestBuilder(ITvMazeApi tvApi) public DateTime FirstAir { get; protected set; } public TvRequests NewRequest { get; protected set; } protected TvMazeShow ShowInfo { get; set; } + protected List Results { get; set; } public async Task GetShowInfo(int id) { ShowInfo = await TvApi.ShowLookupByTheTvDbId(id); + Results = await MovieDbApi.SearchTv(ShowInfo.name); + foreach (TvSearchResult result in Results) { + if (result.Name == ShowInfo.name) + { + var showIds = await MovieDbApi.GetTvExternals(result.Id); + ShowInfo.externals.imdb = showIds.imdb_id; + break; + } + } DateTime.TryParse(ShowInfo.premiered, out var dt); diff --git a/src/Ombi.Helpers/OmbiRoles.cs b/src/Ombi.Helpers/OmbiRoles.cs index e7527279d..ba8c8d087 100644 --- a/src/Ombi.Helpers/OmbiRoles.cs +++ b/src/Ombi.Helpers/OmbiRoles.cs @@ -2,6 +2,8 @@ { public static class OmbiRoles { + // DONT FORGET TO ADD TO IDENTITYCONTROLLER.CREATEROLES AND THE UI! + public const string Admin = nameof(Admin); public const string AutoApproveMovie = nameof(AutoApproveMovie); public const string AutoApproveTv = nameof(AutoApproveTv); diff --git a/src/Ombi.Mapping/Profiles/MovieProfile.cs b/src/Ombi.Mapping/Profiles/MovieProfile.cs index d7e43fc50..dd7e03379 100644 --- a/src/Ombi.Mapping/Profiles/MovieProfile.cs +++ b/src/Ombi.Mapping/Profiles/MovieProfile.cs @@ -24,6 +24,19 @@ public MovieProfile() .ForMember(dest => dest.VoteAverage, opts => opts.MapFrom(src => src.vote_average)) .ForMember(dest => dest.VoteCount, opts => opts.MapFrom(src => src.vote_count)); + CreateMap() + .ForMember(dest => dest.BackdropPath, opts => opts.MapFrom(src => src.backdrop_path)) + .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id)) + .ForMember(dest => dest.OriginalLanguage, opts => opts.MapFrom(src => src.original_language)) + .ForMember(dest => dest.OriginalName, opts => opts.MapFrom(src => src.original_name)) + .ForMember(dest => dest.Overview, opts => opts.MapFrom(src => src.overview)) + .ForMember(dest => dest.Popularity, opts => opts.MapFrom(src => src.popularity)) + .ForMember(dest => dest.PosterPath, opts => opts.MapFrom(src => src.poster_path)) + .ForMember(dest => dest.ReleaseDate, opts => opts.MapFrom(src => src.first_air_date)) + .ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name)) + .ForMember(dest => dest.VoteAverage, opts => opts.MapFrom(src => src.vote_average)) + .ForMember(dest => dest.VoteCount, opts => opts.MapFrom(src => src.vote_count)); + CreateMap() .ForMember(dest => dest.Adult, opts => opts.MapFrom(src => src.adult)) .ForMember(dest => dest.BackdropPath, opts => opts.MapFrom(src => src.backdrop_path)) diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs index b328e6daf..6626ef933 100644 --- a/src/Ombi.Schedule/JobSetup.cs +++ b/src/Ombi.Schedule/JobSetup.cs @@ -55,7 +55,8 @@ public void Setup() RecurringJob.AddOrUpdate(() => _embyContentSync.Start(), JobSettingsHelper.EmbyContent(s)); RecurringJob.AddOrUpdate(() => _sonarrSync.Start(), JobSettingsHelper.Sonarr(s)); RecurringJob.AddOrUpdate(() => _radarrSync.CacheContent(), JobSettingsHelper.Radarr(s)); - RecurringJob.AddOrUpdate(() => _plexContentSync.CacheContent(), JobSettingsHelper.PlexContent(s)); + RecurringJob.AddOrUpdate(() => _plexContentSync.CacheContent(false), JobSettingsHelper.PlexContent(s)); + RecurringJob.AddOrUpdate(() => _plexContentSync.CacheContent(true), JobSettingsHelper.PlexRecentlyAdded(s)); RecurringJob.AddOrUpdate(() => _cpCache.Start(), JobSettingsHelper.CouchPotato(s)); RecurringJob.AddOrUpdate(() => _srSync.Start(), JobSettingsHelper.SickRageSync(s)); RecurringJob.AddOrUpdate(() => _refreshMetadata.Start(), JobSettingsHelper.RefreshMetadata(s)); diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index 9d073facf..9b7726a15 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -80,7 +80,7 @@ private async Task StartPlexTv() if (!hasTheMovieDb) { - var id = await GetTheMovieDbId(hasTvDbId, hasImdb, show.TvDbId, show.ImdbId, show.Title); + var id = await GetTheMovieDbId(hasTvDbId, hasImdb, show.TvDbId, show.ImdbId, show.Title, false); show.TheMovieDbId = id; } @@ -120,7 +120,7 @@ private async Task StartEmbyTv() if (!hasTheMovieDb) { - var id = await GetTheMovieDbId(hasTvDbId, hasImdb, show.TvDbId, show.ImdbId, show.Title); + var id = await GetTheMovieDbId(hasTvDbId, hasImdb, show.TvDbId, show.ImdbId, show.Title, false); show.TheMovieDbId = id; } @@ -166,7 +166,7 @@ private async Task StartPlexMovies() } if (!hasTheMovieDb) { - var id = await GetTheMovieDbId(false, hasImdb, string.Empty, movie.ImdbId, movie.Title); + var id = await GetTheMovieDbId(false, hasImdb, string.Empty, movie.ImdbId, movie.Title, true); movie.TheMovieDbId = id; _plexRepo.UpdateWithoutSave(movie); } @@ -200,7 +200,7 @@ private async Task StartEmbyMovies() } if (!hasTheMovieDb) { - var id = await GetTheMovieDbId(false, hasImdb, string.Empty, movie.ImdbId, movie.Title); + var id = await GetTheMovieDbId(false, hasImdb, string.Empty, movie.ImdbId, movie.Title, true); movie.TheMovieDbId = id; _embyRepo.UpdateWithoutSave(movie); } @@ -215,7 +215,7 @@ private async Task StartEmbyMovies() await _embyRepo.SaveChangesAsync(); } - private async Task GetTheMovieDbId(bool hasTvDbId, bool hasImdb, string tvdbID, string imdbId, string title) + private async Task GetTheMovieDbId(bool hasTvDbId, bool hasImdb, string tvdbID, string imdbId, string title, bool movie) { _log.LogInformation("The Media item {0} does not have a TheMovieDbId, searching for TheMovieDbId", title); FindResult result = null; @@ -230,13 +230,29 @@ private async Task GetTheMovieDbId(bool hasTvDbId, bool hasImdb, string if (hasImdb && !hasResult) { result = await _movieApi.Find(imdbId, ExternalSource.imdb_id); - hasResult = result?.tv_results?.Length > 0; + if (movie) + { + hasResult = result?.movie_results?.Length > 0; + } + else + { + hasResult = result?.tv_results?.Length > 0; + + } _log.LogInformation("Setting Show {0} because we have ImdbId, result: {1}", title, hasResult); } if (hasResult) { - return result.tv_results?[0]?.id.ToString() ?? string.Empty; + if (movie) + { + return result.movie_results?[0]?.id.ToString() ?? string.Empty; + } + else + { + + return result.tv_results?[0]?.id.ToString() ?? string.Empty; + } } return string.Empty; } diff --git a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexContentSync.cs index a9fadae9d..17a8bbb4f 100644 --- a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexContentSync.cs @@ -4,6 +4,6 @@ namespace Ombi.Schedule.Jobs { public interface IPlexContentSync : IBaseJob { - Task CacheContent(); + Task CacheContent(bool recentlyAddedSearch = false); } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 3c00a7a29..0292b6b54 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -62,7 +62,7 @@ public PlexContentSync(ISettingsService plex, IPlexApi plexApi, IL private IPlexContentRepository Repo { get; } private IPlexEpisodeSync EpisodeSync { get; } - public async Task CacheContent() + public async Task CacheContent(bool recentlyAddedSearch = false) { var plexSettings = await Plex.GetSettingsAsync(); if (!plexSettings.Enable) @@ -78,7 +78,7 @@ public async Task CacheContent() Logger.LogInformation("Starting Plex Content Cacher"); try { - await StartTheCache(plexSettings); + await StartTheCache(plexSettings, recentlyAddedSearch); } catch (Exception e) { @@ -89,14 +89,14 @@ public async Task CacheContent() BackgroundJob.Enqueue(() => EpisodeSync.Start()); } - private async Task StartTheCache(PlexSettings plexSettings) + private async Task StartTheCache(PlexSettings plexSettings, bool recentlyAddedSearch) { foreach (var servers in plexSettings.Servers ?? new List()) { try { Logger.LogInformation("Starting to cache the content on server {0}", servers.Name); - await ProcessServer(servers); + await ProcessServer(servers, recentlyAddedSearch); } catch (Exception e) { @@ -105,10 +105,10 @@ private async Task StartTheCache(PlexSettings plexSettings) } } - private async Task ProcessServer(PlexServers servers) + private async Task ProcessServer(PlexServers servers, bool recentlyAddedSearch) { Logger.LogInformation("Getting all content from server {0}", servers.Name); - var allContent = await GetAllContent(servers); + var allContent = await GetAllContent(servers, recentlyAddedSearch); Logger.LogInformation("We found {0} items", allContent.Count); // Let's now process this. @@ -388,8 +388,9 @@ private async Task ProcessServer(PlexServers servers) /// If they have not set the settings then we will monitor them all /// /// The plex settings. + /// /// - private async Task> GetAllContent(PlexServers plexSettings) + private async Task> GetAllContent(PlexServers plexSettings, bool recentlyAddedSearch) { var sections = await PlexApi.GetLibrarySections(plexSettings.PlexAuthToken, plexSettings.FullUri); @@ -413,10 +414,23 @@ private async Task> GetAllContent(PlexServers plexSettings) } } } - var lib = await PlexApi.GetLibrary(plexSettings.PlexAuthToken, plexSettings.FullUri, dir.key); - if (lib != null) + + if (recentlyAddedSearch) { - libs.Add(lib.MediaContainer); + var container = await PlexApi.GetRecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri, + dir.key); + if (container != null) + { + libs.Add(container.MediaContainer); + } + } + else + { + var lib = await PlexApi.GetLibrary(plexSettings.PlexAuthToken, plexSettings.FullUri, dir.key); + if (lib != null) + { + libs.Add(lib.MediaContainer); + } } } } diff --git a/src/Ombi.Settings/Settings/Models/JobSettings.cs b/src/Ombi.Settings/Settings/Models/JobSettings.cs index a68ceb8bb..bb536a685 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettings.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettings.cs @@ -6,6 +6,7 @@ public class JobSettings : Settings public string SonarrSync { get; set; } public string RadarrSync { get; set; } public string PlexContentSync { get; set; } + public string PlexRecentlyAddedSync { get; set; } public string CouchPotatoSync { get; set; } public string AutomaticUpdater { get; set; } public string UserImporter { get; set; } diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs index db4083fcd..c4fcb8ceb 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs @@ -21,7 +21,11 @@ public static string EmbyContent(JobSettings s) } public static string PlexContent(JobSettings s) { - return Get(s.PlexContentSync, Cron.Hourly(20)); + return Get(s.PlexContentSync, Cron.HourInterval(6)); + } + public static string PlexRecentlyAdded(JobSettings s) + { + return Get(s.PlexRecentlyAddedSync, Cron.Hourly(0)); } public static string CouchPotato(JobSettings s) { @@ -49,7 +53,6 @@ public static string RefreshMetadata(JobSettings s) return Get(s.RefreshMetadata, Cron.Daily(3)); } - private static string Get(string settings, string defaultCron) { return settings.HasValue() ? settings : defaultCron; diff --git a/src/Ombi.Store/Entities/ApplicationConfiguration.cs b/src/Ombi.Store/Entities/ApplicationConfiguration.cs index 1499ca34f..809264312 100644 --- a/src/Ombi.Store/Entities/ApplicationConfiguration.cs +++ b/src/Ombi.Store/Entities/ApplicationConfiguration.cs @@ -17,5 +17,6 @@ public enum ConfigurationTypes TheMovieDb = 4, StoragePath = 5, Notification = 6, + BaseUrl=7, } } \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs index 787902a4b..5d0a89992 100644 --- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -12,6 +12,7 @@ public interface IMovieDbApi Task> NowPlaying(); Task> PopularMovies(); Task> SearchMovie(string searchTerm); + Task> SearchTv(string searchTerm); Task> TopRated(); Task> Upcoming(); Task> SimilarMovies(int movieId); diff --git a/src/Ombi.TheMovieDbApi/Models/SearchResult.cs b/src/Ombi.TheMovieDbApi/Models/SearchResult.cs index 81d8115f6..7b09b5e4b 100644 --- a/src/Ombi.TheMovieDbApi/Models/SearchResult.cs +++ b/src/Ombi.TheMovieDbApi/Models/SearchResult.cs @@ -32,9 +32,12 @@ public class SearchResult public bool adult { get; set; } public string overview { get; set; } public string release_date { get; set; } + public string first_air_date { get; set; } public int?[] genre_ids { get; set; } public int id { get; set; } public string original_title { get; set; } + public string original_name { get; set; } + public string name { get; set; } public string original_language { get; set; } public string title { get; set; } public string backdrop_path { get; set; } diff --git a/src/Ombi.TheMovieDbApi/Models/TvSearchResult.cs b/src/Ombi.TheMovieDbApi/Models/TvSearchResult.cs new file mode 100644 index 000000000..eaf93d7cc --- /dev/null +++ b/src/Ombi.TheMovieDbApi/Models/TvSearchResult.cs @@ -0,0 +1,18 @@ +namespace Ombi.Api.TheMovieDb.Models +{ + public class TvSearchResult + { + public string PosterPath { get; set; } + public string Overview { get; set; } + public string ReleaseDate { get; set; } + public int?[] GenreIds { get; set; } + public int Id { get; set; } + public string OriginalName { get; set; } + public string OriginalLanguage { get; set; } + public string Name { get; set; } + public string BackdropPath { get; set; } + public float Popularity { get; set; } + public int VoteCount { get; set; } + public float VoteAverage { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 08925e490..ccd0e52e6 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -42,7 +42,18 @@ public async Task Find(string externalId, ExternalSource source) return await Api.Request(request); } - + + 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); + AddRetry(request); + + var result = await Api.Request>(request); + return Mapper.Map>(result.results); + } + public async Task GetTvExternals(int theMovieDbId) { var request = new Request($"/tv/{theMovieDbId}/external_ids", BaseUri, HttpMethod.Get); diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 1ce3778ec..d67ebc698 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -128,6 +128,7 @@ export interface IJobSettings { sickRageSync: string; refreshMetadata: string; newsletter: string; + plexRecentlyAddedSync: string; } export interface IIssueSettings extends ISettings { diff --git a/src/Ombi/ClientApp/app/issues/issueDetails.component.html b/src/Ombi/ClientApp/app/issues/issueDetails.component.html index e88ad621c..990b9d636 100644 --- a/src/Ombi/ClientApp/app/issues/issueDetails.component.html +++ b/src/Ombi/ClientApp/app/issues/issueDetails.component.html @@ -1,5 +1,5 @@
-
+

{{issue.title}}

diff --git a/src/Ombi/ClientApp/app/issues/issueDetails.component.ts b/src/Ombi/ClientApp/app/issues/issueDetails.component.ts index 34fcbe302..1072bedbd 100644 --- a/src/Ombi/ClientApp/app/issues/issueDetails.component.ts +++ b/src/Ombi/ClientApp/app/issues/issueDetails.component.ts @@ -98,7 +98,11 @@ export class IssueDetailsComponent implements OnInit { ("url(" + x + ")"); }); this.imageService.getMoviePoster(issue.providerId).subscribe(x => { - this.posterPath = x.toString(); + if (x.length === 0) { + this.posterPath = "../../../images/default_movie_poster.png"; + } else { + this.posterPath = x.toString(); + } }); } else { @@ -107,7 +111,11 @@ export class IssueDetailsComponent implements OnInit { ("url(" + x + ")"); }); this.imageService.getTvPoster(Number(issue.providerId)).subscribe(x => { - this.posterPath = x.toString(); + if (x.length === 0) { + this.posterPath = "../../../images/default_tv_poster.png"; + } else { + this.posterPath = x.toString(); + } }); } diff --git a/src/Ombi/ClientApp/app/issues/issuestable.component.html b/src/Ombi/ClientApp/app/issues/issuestable.component.html index f98d6eb0e..83dc8a1db 100644 --- a/src/Ombi/ClientApp/app/issues/issuestable.component.html +++ b/src/Ombi/ClientApp/app/issues/issuestable.component.html @@ -1,25 +1,25 @@ - - - -
+ + + + diff --git a/src/Ombi/ClientApp/app/issues/issuestable.component.ts b/src/Ombi/ClientApp/app/issues/issuestable.component.ts index ee93e689d..f03dd9a6d 100644 --- a/src/Ombi/ClientApp/app/issues/issuestable.component.ts +++ b/src/Ombi/ClientApp/app/issues/issuestable.component.ts @@ -20,11 +20,25 @@ export class IssuesTableComponent { public rowCount = 10; - public setOrder(value: string) { + public setOrder(value: string, el: any) { + el = el.toElement || el.relatedTarget || el.target || el.srcElement; + + if (el.nodeName === "A") { + el = el.parentElement; + } + + const parent = el.parentElement; + const previousFilter = parent.querySelector(".active"); + if (this.order === value) { - this.reverse = !this.reverse; + this.reverse = !this.reverse; + } else { + if (previousFilter) { + previousFilter.className = ""; + } + el.className = "active"; } - + this.order = value; } diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index 6b2300f38..8eded8dba 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -67,7 +67,7 @@
- poster + poster
@@ -222,42 +222,43 @@

{{request.title}} ({{request.releaseDate | date: 'yyyy

{{ 'Requests.Filter' | translate }}


- -

{{ 'Filter.FilterHeaderAvailability' | translate }}

-
-
- - +
+

{{ 'Filter.FilterHeaderAvailability' | translate }}

+
+
+ + +
-
-
-
- - +
+
+ + +
- -

{{ 'Filter.FilterHeaderRequestStatus' | translate }}

-
-
- - +
+

{{ 'Filter.FilterHeaderRequestStatus' | translate }}

+
+
+ + +
-
-
-
- - +
+
+ + +
-
-
-
- - +
+
+ + +
- - \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index 0fc5f6651..e28b86eaa 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -149,7 +149,16 @@ export class MovieRequestsComponent implements OnInit { event.preventDefault(); } - public clearFilter() { + public clearFilter(el: any) { + el = el.toElement || el.relatedTarget || el.target || el.srcElement; + + el = el.parentElement; + el = el.querySelectorAll("INPUT"); + for (el of el) { + el.checked = false; + el.parentElement.classList.remove("active"); + } + this.filterDisplay = false; this.filter.availabilityFilter = FilterType.None; this.filter.statusFilter = FilterType.None; @@ -157,7 +166,8 @@ export class MovieRequestsComponent implements OnInit { this.resetSearch(); } - public filterAvailability(filter: FilterType) { + public filterAvailability(filter: FilterType, el: any) { + this.filterActiveStyle(el); this.filter.availabilityFilter = filter; this.requestService.filterMovies(this.filter) .subscribe(x => { @@ -166,7 +176,8 @@ export class MovieRequestsComponent implements OnInit { }); } - public filterStatus(filter: FilterType) { + public filterStatus(filter: FilterType, el: any) { + this.filterActiveStyle(el); this.filter.statusFilter = filter; this.requestService.filterMovies(this.filter) .subscribe(x => { @@ -190,6 +201,24 @@ export class MovieRequestsComponent implements OnInit { this.order = value; } + private filterActiveStyle(el: any) { + el = el.toElement || el.relatedTarget || el.target || el.srcElement; + + el = el.parentElement; //gets radio div + el = el.parentElement; //gets form group div + el = el.parentElement; //gets status filter div + el = el.querySelectorAll("INPUT"); + for (el of el) { + if (el.checked) { + if (!el.parentElement.classList.contains("active")) { + el.parentElement.className += " active"; + } + } else { + el.parentElement.classList.remove("active"); + } + } + } + private loadRequests(amountToLoad: number, currentlyLoaded: number) { this.requestService.getMovieRequests(amountToLoad, currentlyLoaded + 1) .subscribe(x => { @@ -243,7 +272,8 @@ export class MovieRequestsComponent implements OnInit { this.movieRequests = x; this.movieRequests.forEach((req) => { - this.movieRequests.forEach((req) => this.setBackground(req)); + this.setBackground(req); + this.setPoster(req); }); this.radarrService.getQualityProfilesFromSettings().subscribe(c => { this.radarrProfiles = c; @@ -296,11 +326,20 @@ export class MovieRequestsComponent implements OnInit { } private setOverride(req: IMovieRequests): void { + this.setPoster(req); this.setBackground(req); this.setQualityOverrides(req); this.setRootFolderOverrides(req); } + private setPoster(req: IMovieRequests): void { + if (req.posterPath === null) { + req.posterPath = "../../../images/default_movie_poster.png"; + } else { + req.posterPath = "https://image.tmdb.org/t/p/w300/" + req.posterPath; + } + } + private setBackground(req: IMovieRequests): void { req.backgroundPath = this.sanitizer.bypassSecurityTrustStyle ("url(" + "https://image.tmdb.org/t/p/w1280" + req.background + ")"); diff --git a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html index 30e1398eb..736878d4b 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html +++ b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html @@ -22,15 +22,7 @@
- +
@@ -101,8 +93,3 @@

{{ 'Requests.Season' | translate }} {{season.seasonNumber}}

- - - - \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts index 300599063..e9da2342f 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts @@ -1,5 +1,5 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; -import { IChildRequests, IIssueCategory } from "../interfaces"; +import { IChildRequests } from "../interfaces"; import { NotificationService, RequestService } from "../services"; @@ -13,13 +13,6 @@ export class TvRequestChildrenComponent { @Output() public requestDeleted = new EventEmitter(); - @Input() public issueCategories: IIssueCategory[]; - @Input() public issuesEnabled: boolean; - @Input() public issueProviderId: string; - public issuesBarVisible = false; - public issueRequest: IChildRequests; - public issueCategorySelected: IIssueCategory; - constructor(private requestService: RequestService, private notificationService: NotificationService) { } @@ -101,13 +94,6 @@ export class TvRequestChildrenComponent { }); } - public reportIssue(catId: IIssueCategory, req: IChildRequests) { - this.issueRequest = req; - this.issueCategorySelected = catId; - this.issuesBarVisible = true; - this.issueProviderId = req.id.toString(); - } - private removeRequestFromUi(key: IChildRequests) { const index = this.childRequests.indexOf(key, 0); if (index > -1) { diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.html b/src/Ombi/ClientApp/app/requests/tvrequests.component.html index a602d27e1..9a3c4d186 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.html @@ -64,51 +64,63 @@

{{node.data.title}} ({{node.data.releaseDate | date: '

- +
- -
- - - + +
+ + + +
+ + +
+ + + +
+
- - -
- - -
- -
+ (requestDeleted)="childRequestDeleted($event)">
+ + \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts index ad8b4ca50..344bf5712 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts @@ -33,6 +33,9 @@ export class TvRequestsComponent implements OnInit { @Input() public issueCategories: IIssueCategory[]; @Input() public issuesEnabled: boolean; public issueProviderId: string; + public issuesBarVisible = false; + public issueRequest: ITvRequests; + public issueCategorySelected: IIssueCategory; public sonarrProfiles: ISonarrProfile[] = []; public sonarrRootFolders: ISonarrRootFolder[] = []; @@ -151,6 +154,13 @@ export class TvRequestsComponent implements OnInit { this.updateRequest(searchResult); } + public reportIssue(catId: IIssueCategory, req: ITvRequests) { + this.issueRequest = req; + this.issueCategorySelected = catId; + this.issuesBarVisible = true; + this.issueProviderId = req.id.toString(); + } + private setOverride(req: ITvRequests): void { this.setQualityOverrides(req); this.setRootFolderOverrides(req); @@ -191,6 +201,7 @@ export class TvRequestsComponent implements OnInit { .subscribe(x => { this.tvRequests = x; this.tvRequests.forEach((val, index) => { + this.setDefaults(val); this.loadBackdrop(val); this.setOverride(val.data); }); @@ -209,6 +220,13 @@ export class TvRequestsComponent implements OnInit { this.currentlyLoaded = 5; this.loadInit(); } + + private setDefaults(val: any) { + if (val.data.posterPath === null) { + val.data.posterPath = "../../../images/default_tv_poster.png"; + } + } + private loadBackdrop(val: TreeNode): void { this.imageService.getTvBanner(val.data.tvDbId).subscribe(x => { val.data.background = this.sanitizer.bypassSecurityTrustStyle diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.html b/src/Ombi/ClientApp/app/search/moviesearch.component.html index 58d8415fb..cac78531b 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.html +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.html @@ -33,7 +33,7 @@
- poster + poster
diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index 819463c4f..0abc10474 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -157,12 +157,15 @@ export class MovieSearchComponent implements OnInit { private getExtraInfo() { - this.movieResults.forEach((val, index) => { - - val.background = this.sanitizer. - bypassSecurityTrustStyle - ("url(" + "https://image.tmdb.org/t/p/w1280" + val.backdropPath + ")"); - this.searchService.getMovieInformation(val.id) + this.movieResults.forEach((val, index) => { + if (val.posterPath === null) { + val.posterPath = "../../../images/default_movie_poster.png"; + } else { + val.posterPath = "https://image.tmdb.org/t/p/w300/" + val.posterPath; + } + val.background = this.sanitizer.bypassSecurityTrustStyle + ("url(" + "https://image.tmdb.org/t/p/w1280" + val.backdropPath + ")"); + this.searchService.getMovieInformation(val.id) .subscribe(m => { this.updateItem(val, m); }); @@ -174,7 +177,8 @@ export class MovieSearchComponent implements OnInit { if (index > -1) { const copy = { ...this.movieResults[index] }; this.movieResults[index] = updated; - this.movieResults[index].background = copy.background; + this.movieResults[index].background = copy.background; + this.movieResults[index].posterPath = copy.posterPath; } } private clearResults() { diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.html b/src/Ombi/ClientApp/app/search/tvsearch.component.html index fb1729e50..42232a564 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.html +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.html @@ -62,7 +62,7 @@
- +

{{node.data.title}} ({{node.data.firstAired | date: 'yyyy'}})

diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.ts b/src/Ombi/ClientApp/app/search/tvsearch.component.ts index 961e85f63..bb30810e4 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.ts @@ -130,7 +130,6 @@ export class TvSearchComponent implements OnInit { public getExtraInfo() { this.tvResults.forEach((val, index) => { this.imageService.getTvBanner(val.data.id).subscribe(x => { - val.data.background = this.sanitizer. bypassSecurityTrustStyle ("url(" + x + ")"); @@ -138,6 +137,7 @@ export class TvSearchComponent implements OnInit { this.searchService.getShowInformationTreeNode(val.data.id) .subscribe(x => { if (x.data) { + this.setDefaults(x); this.updateItem(val, x); } else { const index = this.tvResults.indexOf(val, 0); @@ -216,6 +216,7 @@ export class TvSearchComponent implements OnInit { const index = this.tvResults.indexOf(key, 0); if (index > -1) { // Update certain properties, otherwise we will loose some data + this.tvResults[index].data.title = updated.data.title; this.tvResults[index].data.banner = updated.data.banner; this.tvResults[index].data.imdbId = updated.data.imdbId; this.tvResults[index].data.seasonRequests = updated.data.seasonRequests; @@ -225,6 +226,18 @@ export class TvSearchComponent implements OnInit { } } + private setDefaults(x: any) { + if (x.data.banner === null) { + x.data.banner = "../../../images/default_tv_poster.png"; + } + + if (x.data.imdbId === null) { + x.data.imdbId = "https://www.tvmaze.com/shows/" + x.data.seriesId; + } else { + x.data.imdbId = "http://www.imdb.com/title/" + x.data.imdbId + "/"; + } + } + private clearResults() { this.tvResults = []; this.searchApplied = false; diff --git a/src/Ombi/ClientApp/app/services/job.service.ts b/src/Ombi/ClientApp/app/services/job.service.ts index 79957af97..2fe940316 100644 --- a/src/Ombi/ClientApp/app/services/job.service.ts +++ b/src/Ombi/ClientApp/app/services/job.service.ts @@ -35,6 +35,10 @@ export class JobService extends ServiceHelpers { return this.http.post(`${this.url}plexcontentcacher/`, {headers: this.headers}); } + public runPlexRecentlyAddedCacher(): Observable { + return this.http.post(`${this.url}plexrecentlyadded/`, {headers: this.headers}); + } + public runEmbyCacher(): Observable { return this.http.post(`${this.url}embycontentcacher/`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html index 0d8b85930..8b9eb89f5 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html @@ -57,6 +57,12 @@ The Plex Sync is required
+
+ + + The Plex Sync is required + +
diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts index 5978e7ab2..d0a7a8b83 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts @@ -33,6 +33,7 @@ export class JobsComponent implements OnInit { sickRageSync: [x.sickRageSync, Validators.required], refreshMetadata: [x.refreshMetadata, Validators.required], newsletter: [x.newsletter, Validators.required], + plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required], }); }); } diff --git a/src/Ombi/ClientApp/app/settings/plex/plex.component.html b/src/Ombi/ClientApp/app/settings/plex/plex.component.html index 6beaa3fea..6310a9cf1 100644 --- a/src/Ombi/ClientApp/app/settings/plex/plex.component.html +++ b/src/Ombi/ClientApp/app/settings/plex/plex.component.html @@ -171,19 +171,26 @@
-
+
-
-
-
- -
+
+
+
+
+
+
+
+
+ +
+
+
diff --git a/src/Ombi/ClientApp/app/settings/plex/plex.component.ts b/src/Ombi/ClientApp/app/settings/plex/plex.component.ts index 61b57b393..23bd74225 100644 --- a/src/Ombi/ClientApp/app/settings/plex/plex.component.ts +++ b/src/Ombi/ClientApp/app/settings/plex/plex.component.ts @@ -121,7 +121,15 @@ export class PlexComponent implements OnInit, OnDestroy { public runCacher(): void { this.jobService.runPlexCacher().subscribe(x => { if(x) { - this.notificationService.success("Triggered the Plex Content Cacher"); + this.notificationService.success("Triggered the Plex Full Sync"); + } + }); + } + + public runRecentlyAddedCacher(): void { + this.jobService.runPlexRecentlyAddedCacher().subscribe(x => { + if(x) { + this.notificationService.success("Triggered the Plex Recently Added Sync"); } }); } diff --git a/src/Ombi/ClientApp/styles/Themes/plex.scss b/src/Ombi/ClientApp/styles/Themes/plex.scss index 1e3c27eaf..1475aef91 100644 --- a/src/Ombi/ClientApp/styles/Themes/plex.scss +++ b/src/Ombi/ClientApp/styles/Themes/plex.scss @@ -351,5 +351,5 @@ button.list-group-item:focus { position: absolute; } table.table > thead > tr > th.active { - background-color: transparent; + background-color: $primary-colour; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index 619dd8042..3a5deb2a3 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -541,6 +541,10 @@ $border-radius: 10px; cursor: pointer; } +.table-usermanagement { + margin-top: 20px; +} + .input-group-sm { padding-top: 2px; padding-bottom: 2px; diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 6a8aee52c..5db5f2168 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -194,6 +194,7 @@ private async Task CreateRoles() await CreateRole(OmbiRoles.RequestMovie); await CreateRole(OmbiRoles.RequestTv); await CreateRole(OmbiRoles.Disabled); + await CreateRole(OmbiRoles.RecievesNewsletter); } private async Task CreateRole(string role) diff --git a/src/Ombi/Controllers/JobController.cs b/src/Ombi/Controllers/JobController.cs index 76ca42c41..a89346250 100644 --- a/src/Ombi/Controllers/JobController.cs +++ b/src/Ombi/Controllers/JobController.cs @@ -117,7 +117,18 @@ public bool EmbyUserImporter() [HttpPost("plexcontentcacher")] public bool StartPlexContentCacher() { - BackgroundJob.Enqueue(() => _plexContentSync.CacheContent()); + BackgroundJob.Enqueue(() => _plexContentSync.CacheContent(false)); + return true; + } + + /// + /// Runs a smaller version of the content cacher + /// + /// + [HttpPost("plexrecentlyadded")] + public bool StartRecentlyAdded() + { + BackgroundJob.Enqueue(() => _plexContentSync.CacheContent(true)); return true; } diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 9ffa9d81f..a5aef25fb 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -274,6 +274,12 @@ public async Task> GetThemes() public async Task GetThemeContent([FromQuery]string url) { var css = await _githubApi.GetThemesRawContent(url); + var ombiSettings = await OmbiSettings(); + if (ombiSettings.BaseUrl != null) + { + int index = css.IndexOf("/api/"); + css = css.Insert(index, ombiSettings.BaseUrl); + } return Content(css, "text/css"); } @@ -473,6 +479,8 @@ public async Task JobSettings() j.UserImporter = j.UserImporter.HasValue() ? j.UserImporter : JobSettingsHelper.UserImporter(j); j.SickRageSync = j.SickRageSync.HasValue() ? j.SickRageSync : JobSettingsHelper.SickRageSync(j); j.RefreshMetadata = j.RefreshMetadata.HasValue() ? j.RefreshMetadata : JobSettingsHelper.RefreshMetadata(j); + j.PlexRecentlyAddedSync = j.PlexRecentlyAddedSync.HasValue() ? j.PlexRecentlyAddedSync : JobSettingsHelper.PlexRecentlyAdded(j); + j.Newsletter = j.Newsletter.HasValue() ? j.Newsletter : JobSettingsHelper.Newsletter(j); return j; } diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index 9ced1715e..9294852f9 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -23,11 +23,13 @@ public static void Main(string[] args) var host = string.Empty; var storagePath = string.Empty; + var baseUrl = string.Empty; var result = Parser.Default.ParseArguments(args) .WithParsed(o => { host = o.Host; storagePath = o.StoragePath; + baseUrl = o.BaseUrl; }).WithNotParsed(err => { foreach (var e in err) @@ -47,6 +49,7 @@ public static void Main(string[] args) { var config = ctx.ApplicationConfigurations.ToList(); var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url); + var dbBaseUrl = config.FirstOrDefault(x => x.Type == ConfigurationTypes.BaseUrl); if (url == null) { url = new ApplicationConfiguration @@ -65,6 +68,25 @@ public static void Main(string[] args) ctx.SaveChanges(); urlValue = url.Value; } + + if (dbBaseUrl == null) + { + if (baseUrl.HasValue() && baseUrl.StartsWith("/")) + { + dbBaseUrl = new ApplicationConfiguration + { + Type = ConfigurationTypes.BaseUrl, + Value = baseUrl + }; + ctx.ApplicationConfigurations.Add(dbBaseUrl); + ctx.SaveChanges(); + } + } + else if(!baseUrl.Equals(dbBaseUrl.Value)) + { + dbBaseUrl.Value = baseUrl; + ctx.SaveChanges(); + } } DeleteSchedulesDb(); @@ -118,5 +140,8 @@ public class Options [Option("storage", Required = false, HelpText = "Storage path, where we save the logs and database")] public string StoragePath { get; set; } + [Option("baseurl", Required = false, HelpText = "The base URL for reverse proxy scenarios")] + public string BaseUrl { get; set; } + } } diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 4aaadacb6..7fc0522ed 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -32,6 +32,7 @@ using Ombi.Settings.Settings.Models; using Ombi.Store.Context; using Ombi.Store.Entities; +using Ombi.Store.Repository; using Serilog; using Serilog.Events; @@ -176,6 +177,22 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF { app.UsePathBase(settings.BaseUrl); } + else + { + // Check if it's in the startup args + var appConfig = serviceProvider.GetService(); + var baseUrl = appConfig.Get(ConfigurationTypes.BaseUrl).Result; + if (baseUrl != null) + { + if (baseUrl.Value.HasValue()) + { + settings.BaseUrl = baseUrl.Value; + ombiService.SaveSettings(settings); + + app.UsePathBase(settings.BaseUrl); + } + } + } app.UseHangfireServer(new BackgroundJobServerOptions { WorkerCount = 1, ServerTimeout = TimeSpan.FromDays(1), ShutdownTimeout = TimeSpan.FromDays(1)}); app.UseHangfireDashboard(settings.BaseUrl.HasValue() ? $"{settings.BaseUrl}/hangfire" : "/hangfire", diff --git a/src/Ombi/StartupExtensions.cs b/src/Ombi/StartupExtensions.cs index 1c8f54b4e..e4dae18e4 100644 --- a/src/Ombi/StartupExtensions.cs +++ b/src/Ombi/StartupExtensions.cs @@ -168,7 +168,6 @@ private static async Task ValidateUserAccessToken(IServiceProvider serviceProvid if (user == null) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; - context.Response.RegisterForDispose(um); await context.Response.WriteAsync("Invalid User Access Token"); } else @@ -178,7 +177,6 @@ private static async Task ValidateUserAccessToken(IServiceProvider serviceProvid var roles = await um.GetRolesAsync(user); var principal = new GenericPrincipal(identity, roles.ToArray()); context.User = principal; - context.Response.RegisterForDispose(um); await next(); } } @@ -191,7 +189,6 @@ private static async Task ValidateApiKey(IServiceProvider serviceProvider, HttpC if (!valid) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; - context.Response.RegisterForDispose(settingsProvider); await context.Response.WriteAsync("Invalid API Key"); } else @@ -199,7 +196,6 @@ private static async Task ValidateApiKey(IServiceProvider serviceProvider, HttpC var identity = new GenericIdentity("API"); var principal = new GenericPrincipal(identity, new[] { "Admin", "ApiUser" }); context.User = principal; - context.Response.RegisterForDispose(settingsProvider); await next(); } } diff --git a/src/Ombi/Views/Shared/_Layout.cshtml b/src/Ombi/Views/Shared/_Layout.cshtml index cafd75357..cb9985bac 100644 --- a/src/Ombi/Views/Shared/_Layout.cshtml +++ b/src/Ombi/Views/Shared/_Layout.cshtml @@ -75,6 +75,8 @@ O:::::::OOO:::::::Om::::m m::::m m::::mb:::::bbbbbb::::::bi::::::i + + diff --git a/src/Ombi/tsconfig.json b/src/Ombi/tsconfig.json index daff6b451..8f860760c 100644 --- a/src/Ombi/tsconfig.json +++ b/src/Ombi/tsconfig.json @@ -11,7 +11,7 @@ "noUnusedLocals": true, "noImplicitThis": true, "noImplicitReturns": true, - "noImplicitAny": true, + "noImplicitAny": false, "suppressImplicitAnyIndexErrors": true, "alwaysStrict": true, "emitDecoratorMetadata": true, diff --git a/src/Ombi/wwwroot/images/default_movie_poster.png b/src/Ombi/wwwroot/images/default_movie_poster.png new file mode 100644 index 000000000..f5cec85a5 Binary files /dev/null and b/src/Ombi/wwwroot/images/default_movie_poster.png differ diff --git a/src/Ombi/wwwroot/images/default_tv_poster.png b/src/Ombi/wwwroot/images/default_tv_poster.png new file mode 100644 index 000000000..28e845ea5 Binary files /dev/null and b/src/Ombi/wwwroot/images/default_tv_poster.png differ