From 9c61f909decdcfd8ac6e879562b42f7f98418da7 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 19 Apr 2016 13:37:58 +0100 Subject: [PATCH] Switched out the schedulers, this seems to be a better implimentation to the previous and is easier to add new "jobs" in. --- PlexRequests.Services.Tests/app.config | 8 +- .../AvailabilityUpdateService.cs | 93 --- PlexRequests.Services/Configuration.cs | 40 -- PlexRequests.Services/ConfigurationReader.cs | 38 -- .../Interfaces/IAvailabilityChecker.cs | 2 +- .../Interfaces/IConfigurationReader.cs | 33 - .../Interfaces/ICouchPotatoCacher.cs | 2 +- .../{ITvCacher.cs => ISickRageCacher.cs} | 16 +- .../Interfaces/ISonarrCacher.cs | 2 +- .../{ => Jobs}/CouchPotatoCacher.cs | 157 ++--- .../{ => Jobs}/PlexAvailabilityChecker.cs | 598 +++++++++--------- .../{ => Jobs}/SickRageCacher.cs | 158 ++--- .../{ => Jobs}/SonarrCacher.cs | 158 ++--- PlexRequests.Services/MediaCacheService.cs | 102 --- .../PlexRequests.Services.csproj | 29 +- PlexRequests.Services/PlexType.cs | 35 - PlexRequests.Services/UpdateInterval.cs | 38 -- PlexRequests.Services/app.config | 8 +- PlexRequests.Services/packages.config | 4 +- PlexRequests.UI/Bootstrapper.cs | 10 +- PlexRequests.UI/Helpers/ServiceLocator.cs | 15 +- PlexRequests.UI/Jobs/CustomJobFactory.cs | 94 +++ PlexRequests.UI/Jobs/MediaCacheRegistry.cs | 41 -- PlexRequests.UI/Jobs/PlexRegistry.cs | 41 -- PlexRequests.UI/Jobs/PlexTaskFactory.cs | 23 - PlexRequests.UI/Jobs/Scheduler.cs | 137 ++++ PlexRequests.UI/PlexRequests.UI.csproj | 24 +- PlexRequests.UI/Program.cs | 14 +- PlexRequests.UI/Startup.cs | 13 +- PlexRequests.UI/app.config | 30 +- PlexRequests.UI/job_scheduling_data_2_0.xsd | 361 +++++++++++ PlexRequests.UI/packages.config | 4 +- 32 files changed, 1237 insertions(+), 1091 deletions(-) delete mode 100644 PlexRequests.Services/AvailabilityUpdateService.cs delete mode 100644 PlexRequests.Services/Configuration.cs delete mode 100644 PlexRequests.Services/ConfigurationReader.cs delete mode 100644 PlexRequests.Services/Interfaces/IConfigurationReader.cs rename PlexRequests.Services/Interfaces/{ITvCacher.cs => ISickRageCacher.cs} (75%) rename PlexRequests.Services/{ => Jobs}/CouchPotatoCacher.cs (87%) rename PlexRequests.Services/{ => Jobs}/PlexAvailabilityChecker.cs (95%) rename PlexRequests.Services/{ => Jobs}/SickRageCacher.cs (90%) rename PlexRequests.Services/{ => Jobs}/SonarrCacher.cs (91%) delete mode 100644 PlexRequests.Services/MediaCacheService.cs delete mode 100644 PlexRequests.Services/PlexType.cs delete mode 100644 PlexRequests.Services/UpdateInterval.cs create mode 100644 PlexRequests.UI/Jobs/CustomJobFactory.cs delete mode 100644 PlexRequests.UI/Jobs/MediaCacheRegistry.cs delete mode 100644 PlexRequests.UI/Jobs/PlexRegistry.cs delete mode 100644 PlexRequests.UI/Jobs/PlexTaskFactory.cs create mode 100644 PlexRequests.UI/Jobs/Scheduler.cs create mode 100644 PlexRequests.UI/job_scheduling_data_2_0.xsd diff --git a/PlexRequests.Services.Tests/app.config b/PlexRequests.Services.Tests/app.config index 0404cdcb4..44b249bff 100644 --- a/PlexRequests.Services.Tests/app.config +++ b/PlexRequests.Services.Tests/app.config @@ -1,11 +1,11 @@ - + - - + + - + diff --git a/PlexRequests.Services/AvailabilityUpdateService.cs b/PlexRequests.Services/AvailabilityUpdateService.cs deleted file mode 100644 index a9268a272..000000000 --- a/PlexRequests.Services/AvailabilityUpdateService.cs +++ /dev/null @@ -1,93 +0,0 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: AvailabilityUpdateService.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Reactive.Linq; -using System.Web.Hosting; - -using FluentScheduler; - -using Mono.Data.Sqlite; - -using NLog; - -using PlexRequests.Api; -using PlexRequests.Core; -using PlexRequests.Core.SettingModels; -using PlexRequests.Helpers; -using PlexRequests.Services.Interfaces; -using PlexRequests.Store; -using PlexRequests.Store.Repository; -using System.Threading.Tasks; - -namespace PlexRequests.Services -{ - public class AvailabilityUpdateService : ITask, IRegisteredObject, IAvailabilityUpdateService - { - - public AvailabilityUpdateService() - { - - var memCache = new MemoryCacheProvider(); - var dbConfig = new DbConfiguration(new SqliteFactory()); - var repo = new SettingsJsonRepository(dbConfig, memCache); - - ConfigurationReader = new ConfigurationReader(); - Checker = new PlexAvailabilityChecker(new SettingsServiceV2(repo), new SettingsServiceV2(repo), new JsonRequestService(new RequestJsonRepository(dbConfig, memCache)), new PlexApi(), memCache); - HostingEnvironment.RegisterObject(this); - } - - private static Logger Log = LogManager.GetCurrentClassLogger(); - - private IConfigurationReader ConfigurationReader { get; } - private IAvailabilityChecker Checker { get; } - private IDisposable UpdateSubscription { get; set; } - - public void Start(Configuration c) - { - UpdateSubscription?.Dispose(); - Task.Factory.StartNew(() => Checker.CheckAndUpdateAll(-1)); // cache the libraries and run the availability checks - UpdateSubscription = Observable.Interval(c.Intervals.Notification).Subscribe(Checker.CheckAndUpdateAll); - } - - public void Execute() - { - Start(ConfigurationReader.Read()); - } - - public void Stop(bool immediate) - { - HostingEnvironment.UnregisterObject(this); - } - } - - public interface IAvailabilityUpdateService - { - void Start(Configuration c); - } -} diff --git a/PlexRequests.Services/Configuration.cs b/PlexRequests.Services/Configuration.cs deleted file mode 100644 index d88789ecb..000000000 --- a/PlexRequests.Services/Configuration.cs +++ /dev/null @@ -1,40 +0,0 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: Congifuration.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion -using PlexRequests.Services.Interfaces; - -namespace PlexRequests.Services -{ - public class Configuration - { - public Configuration(IIntervals intervals) - { - Intervals = intervals; - } - - public IIntervals Intervals { get; set; } - } -} \ No newline at end of file diff --git a/PlexRequests.Services/ConfigurationReader.cs b/PlexRequests.Services/ConfigurationReader.cs deleted file mode 100644 index 4c35ff2e7..000000000 --- a/PlexRequests.Services/ConfigurationReader.cs +++ /dev/null @@ -1,38 +0,0 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: ConfigurationReader.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion -using PlexRequests.Services.Interfaces; - -namespace PlexRequests.Services -{ - public class ConfigurationReader : IConfigurationReader - { - public Configuration Read() - { - return new Configuration(new UpdateInterval()); - } - } -} \ No newline at end of file diff --git a/PlexRequests.Services/Interfaces/IAvailabilityChecker.cs b/PlexRequests.Services/Interfaces/IAvailabilityChecker.cs index 3d7a423ac..14eda1731 100644 --- a/PlexRequests.Services/Interfaces/IAvailabilityChecker.cs +++ b/PlexRequests.Services/Interfaces/IAvailabilityChecker.cs @@ -31,7 +31,7 @@ namespace PlexRequests.Services.Interfaces { public interface IAvailabilityChecker { - void CheckAndUpdateAll(long check); + void CheckAndUpdateAll(); List GetPlexMovies(); bool IsMovieAvailable(PlexMovie[] plexMovies, string title, string year); List GetPlexTvShows(); diff --git a/PlexRequests.Services/Interfaces/IConfigurationReader.cs b/PlexRequests.Services/Interfaces/IConfigurationReader.cs deleted file mode 100644 index 179f66e96..000000000 --- a/PlexRequests.Services/Interfaces/IConfigurationReader.cs +++ /dev/null @@ -1,33 +0,0 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: IConfigurationReader.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion -namespace PlexRequests.Services.Interfaces -{ - public interface IConfigurationReader - { - Configuration Read(); - } -} \ No newline at end of file diff --git a/PlexRequests.Services/Interfaces/ICouchPotatoCacher.cs b/PlexRequests.Services/Interfaces/ICouchPotatoCacher.cs index 4da6fa852..05fa8da75 100644 --- a/PlexRequests.Services/Interfaces/ICouchPotatoCacher.cs +++ b/PlexRequests.Services/Interfaces/ICouchPotatoCacher.cs @@ -2,7 +2,7 @@ { public interface ICouchPotatoCacher { - void Queued(long check); + void Queued(); int[] QueuedIds(); } } diff --git a/PlexRequests.Services/Interfaces/ITvCacher.cs b/PlexRequests.Services/Interfaces/ISickRageCacher.cs similarity index 75% rename from PlexRequests.Services/Interfaces/ITvCacher.cs rename to PlexRequests.Services/Interfaces/ISickRageCacher.cs index a42d2a1e4..54f1e0573 100644 --- a/PlexRequests.Services/Interfaces/ITvCacher.cs +++ b/PlexRequests.Services/Interfaces/ISickRageCacher.cs @@ -1,8 +1,8 @@ -namespace PlexRequests.Services.Interfaces -{ - public interface ISickRageCacher - { - void Queued(long check); - int[] QueuedIds(); - } -} +namespace PlexRequests.Services.Interfaces +{ + public interface ISickRageCacher + { + void Queued(); + int[] QueuedIds(); + } +} diff --git a/PlexRequests.Services/Interfaces/ISonarrCacher.cs b/PlexRequests.Services/Interfaces/ISonarrCacher.cs index 590666e07..a7cf8f9fa 100644 --- a/PlexRequests.Services/Interfaces/ISonarrCacher.cs +++ b/PlexRequests.Services/Interfaces/ISonarrCacher.cs @@ -2,7 +2,7 @@ { public interface ISonarrCacher { - void Queued(long check); + void Queued(); int[] QueuedIds(); } } diff --git a/PlexRequests.Services/CouchPotatoCacher.cs b/PlexRequests.Services/Jobs/CouchPotatoCacher.cs similarity index 87% rename from PlexRequests.Services/CouchPotatoCacher.cs rename to PlexRequests.Services/Jobs/CouchPotatoCacher.cs index 557a29179..8bc50c5b6 100644 --- a/PlexRequests.Services/CouchPotatoCacher.cs +++ b/PlexRequests.Services/Jobs/CouchPotatoCacher.cs @@ -1,77 +1,82 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: PlexAvailabilityChecker.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion - -using System; -using NLog; - -using PlexRequests.Api.Interfaces; -using PlexRequests.Core; -using PlexRequests.Core.SettingModels; -using PlexRequests.Helpers; -using PlexRequests.Services.Interfaces; -using PlexRequests.Api.Models.Movie; -using System.Linq; - -namespace PlexRequests.Services -{ - public class CouchPotatoCacher : ICouchPotatoCacher - { - public CouchPotatoCacher(ISettingsService cpSettings, ICouchPotatoApi cpApi, ICacheProvider cache) - { - CpSettings = cpSettings; - CpApi = cpApi; - Cache = cache; - } - - private ISettingsService CpSettings { get; } - private ICacheProvider Cache { get; } - private ICouchPotatoApi CpApi { get; } - - private static Logger Log = LogManager.GetCurrentClassLogger(); - - public void Queued(long check) - { - Log.Trace("This is check no. {0}", check); - Log.Trace("Getting the settings"); - - var settings = CpSettings.GetSettings(); - if (settings.Enabled) - { - Log.Trace("Getting all movies from CouchPotato"); - var movies = CpApi.GetMovies(settings.FullUri, settings.ApiKey, new[] { "active" }); - Cache.Set(CacheKeys.CouchPotatoQueued, movies, 10); - } - } - - // we do not want to set here... - public int[] QueuedIds() - { - var movies = Cache.Get(CacheKeys.CouchPotatoQueued); - return movies != null ? movies.movies.Select(x => x.info.tmdb_id).ToArray() : new int[] { }; - } - } +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: PlexAvailabilityChecker.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System.Linq; + +using NLog; + +using PlexRequests.Api.Interfaces; +using PlexRequests.Api.Models.Movie; +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Helpers; +using PlexRequests.Services.Interfaces; + +using Quartz; + +namespace PlexRequests.Services.Jobs +{ + public class CouchPotatoCacher : IJob, ICouchPotatoCacher + { + public CouchPotatoCacher(ISettingsService cpSettings, ICouchPotatoApi cpApi, ICacheProvider cache) + { + CpSettings = cpSettings; + CpApi = cpApi; + Cache = cache; + } + + private ISettingsService CpSettings { get; } + private ICacheProvider Cache { get; } + private ICouchPotatoApi CpApi { get; } + + private static Logger Log = LogManager.GetCurrentClassLogger(); + + public void Queued() + { + Log.Trace("Getting the settings"); + + var settings = CpSettings.GetSettings(); + if (settings.Enabled) + { + Log.Trace("Getting all movies from CouchPotato"); + var movies = CpApi.GetMovies(settings.FullUri, settings.ApiKey, new[] { "active" }); + Cache.Set(CacheKeys.CouchPotatoQueued, movies, 10); + } + } + + // we do not want to set here... + public int[] QueuedIds() + { + var movies = Cache.Get(CacheKeys.CouchPotatoQueued); + return movies?.movies.Select(x => x.info.tmdb_id).ToArray() ?? new int[] { }; + } + + public void Execute(IJobExecutionContext context) + { + Queued(); + } + } } \ No newline at end of file diff --git a/PlexRequests.Services/PlexAvailabilityChecker.cs b/PlexRequests.Services/Jobs/PlexAvailabilityChecker.cs similarity index 95% rename from PlexRequests.Services/PlexAvailabilityChecker.cs rename to PlexRequests.Services/Jobs/PlexAvailabilityChecker.cs index c4caa18a0..bb8f957a0 100644 --- a/PlexRequests.Services/PlexAvailabilityChecker.cs +++ b/PlexRequests.Services/Jobs/PlexAvailabilityChecker.cs @@ -1,297 +1,303 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: PlexAvailabilityChecker.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion -using System; -using System.Collections.Generic; -using System.Linq; - -using NLog; - -using PlexRequests.Api.Interfaces; -using PlexRequests.Api.Models.Plex; -using PlexRequests.Core; -using PlexRequests.Core.SettingModels; -using PlexRequests.Helpers; -using PlexRequests.Services.Interfaces; -using PlexRequests.Store; -using PlexRequests.Services.Models; - -namespace PlexRequests.Services -{ - public class PlexAvailabilityChecker : IAvailabilityChecker - { - public PlexAvailabilityChecker(ISettingsService plexSettings, ISettingsService auth, IRequestService request, IPlexApi plex, ICacheProvider cache) - { - Plex = plexSettings; - Auth = auth; - RequestService = request; - PlexApi = plex; - Cache = cache; - } - - private ISettingsService Plex { get; } - private ISettingsService Auth { get; } - private IRequestService RequestService { get; } - private static Logger Log = LogManager.GetCurrentClassLogger(); - private IPlexApi PlexApi { get; } - private ICacheProvider Cache { get; } - - public void CheckAndUpdateAll(long check) - { - Log.Trace("This is check no. {0}", check); - Log.Trace("Getting the settings"); - var plexSettings = Plex.GetSettings(); - var authSettings = Auth.GetSettings(); - Log.Trace("Getting all the requests"); - - if (!ValidateSettings(plexSettings, authSettings)) - { - Log.Info("Validation of the plex settings failed."); - return; - } - - var libraries = CachedLibraries(authSettings, plexSettings, true); //force setting the cache (10 min intervals via scheduler) - var movies = GetPlexMovies().ToArray(); - var shows = GetPlexTvShows().ToArray(); - var albums = GetPlexAlbums().ToArray(); - - var requests = RequestService.GetAll(); - var requestedModels = requests as RequestedModel[] ?? requests.Where(x => !x.Available).ToArray(); - Log.Trace("Requests Count {0}", requestedModels.Length); - - if (!requestedModels.Any()) - { - Log.Info("There are no requests to check."); - return; - } - - var modifiedModel = new List(); - foreach (var r in requestedModels) - { - Log.Trace("We are going to see if Plex has the following title: {0}", r.Title); - - if (libraries == null) - { - libraries = new List() { PlexApi.SearchContent(authSettings.PlexAuthToken, r.Title, plexSettings.FullUri) }; - if (libraries == null) - { - Log.Trace("Could not find any matching result for this title."); - continue; - } - } - - Log.Trace("Search results from Plex for the following request: {0}", r.Title); - //Log.Trace(results.DumpJson()); - - var releaseDate = r.ReleaseDate == DateTime.MinValue ? string.Empty : r.ReleaseDate.ToString("yyyy"); - - bool matchResult; - switch (r.Type) - { - case RequestType.Movie: - matchResult = IsMovieAvailable(movies, r.Title, releaseDate); - break; - case RequestType.TvShow: - matchResult = IsTvShowAvailable(shows, r.Title, releaseDate); - break; - case RequestType.Album: - matchResult = IsAlbumAvailable(albums, r.Title, r.ReleaseDate.Year.ToString(), r.ArtistName); - break; - default: - throw new ArgumentOutOfRangeException(); - } - - if (matchResult) - { - r.Available = true; - modifiedModel.Add(r); - continue; - } - - Log.Trace("The result from Plex where the title's match was null, so that means the content is not yet in Plex."); - } - - Log.Trace("Updating the requests now"); - Log.Trace("Requests that will be updates:"); - Log.Trace(modifiedModel.SelectMany(x => x.Title).DumpJson()); - - if (modifiedModel.Any()) - { - RequestService.BatchUpdate(modifiedModel); - } - } - - public List GetPlexMovies() - { - var movies = new List(); - var libs = Cache.Get>(CacheKeys.PlexLibaries); - if (libs != null) - { - var movieLibs = libs.Where(x => - x.Video.Any(y => - y.Type.Equals(PlexMediaType.Movie.ToString(), StringComparison.CurrentCultureIgnoreCase) - ) - ).ToArray(); - - foreach (var lib in movieLibs) - { - movies.AddRange(lib.Video.Select(x => new PlexMovie() // movies are in the Video list - { - Title = x.Title, - ReleaseYear = x.Year - })); - } - } - return movies; - } - - public bool IsMovieAvailable(PlexMovie[] plexMovies, string title, string year) - { - return plexMovies.Any(x => x.Title.Equals(title, StringComparison.CurrentCultureIgnoreCase) && x.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase)); - } - - public List GetPlexTvShows() - { - var shows = new List(); - var libs = Cache.Get>(CacheKeys.PlexLibaries); - if (libs != null) - { - var tvLibs = libs.Where(x => - x.Directory.Any(y => - y.Type.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase) - ) - ).ToArray(); - - foreach (var lib in tvLibs) - { - shows.AddRange(lib.Directory.Select(x => new PlexTvShow() // shows are in the directory list - { - Title = x.Title, - ReleaseYear = x.Year - })); - } - } - return shows; - } - - public bool IsTvShowAvailable(PlexTvShow[] plexShows, string title, string year) - { - return plexShows.Any(x => - (x.Title.Equals(title, StringComparison.CurrentCultureIgnoreCase) || x.Title.StartsWith(title, StringComparison.CurrentCultureIgnoreCase)) && - x.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase)); - } - - public List GetPlexAlbums() - { - var albums = new List(); - var libs = Cache.Get>(CacheKeys.PlexLibaries); - if (libs != null) - { - var albumLibs = libs.Where(x => - x.Directory.Any(y => - y.Type.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase) - ) - ).ToArray(); - - foreach (var lib in albumLibs) - { - albums.AddRange(lib.Directory.Select(x => new PlexAlbum() - { - Title = x.Title, - ReleaseYear = x.Year, - Artist = x.ParentTitle - })); - } - } - return albums; - } - - public bool IsAlbumAvailable(PlexAlbum[] plexAlbums, string title, string year, string artist) - { - return plexAlbums.Any(x => - x.Title.Contains(title) && - //x.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase) && - x.Artist.Equals(artist, StringComparison.CurrentCultureIgnoreCase)); - } - - private List CachedLibraries(AuthenticationSettings authSettings, PlexSettings plexSettings, bool setCache) - { - Log.Trace("Obtaining library sections from Plex for the following request"); - - List results = new List(); - - if (!ValidateSettings(plexSettings, authSettings)) - { - Log.Warn("The settings are not configured"); - return results; // don't error out here, just let it go! - } - - if (setCache) - { - results = GetLibraries(authSettings, plexSettings); - Cache.Set(CacheKeys.PlexLibaries, results, 10); - } - else - { - results = Cache.GetOrSet(CacheKeys.PlexLibaries, () => { - return GetLibraries(authSettings, plexSettings); - }, 10); - } - return results; - } - - private List GetLibraries(AuthenticationSettings authSettings, PlexSettings plexSettings) - { - var sections = PlexApi.GetLibrarySections(authSettings.PlexAuthToken, plexSettings.FullUri); - - List libs = new List(); - if (sections != null) - { - foreach (var dir in sections.Directories) - { - Log.Trace("Obtaining results from Plex for the following library section: {0}", dir.Title); - var lib = PlexApi.GetLibrary(authSettings.PlexAuthToken, plexSettings.FullUri, dir.Key); - if (lib != null) - { - libs.Add(lib); - } - } - } - - return libs; - } - - private bool ValidateSettings(PlexSettings plex, AuthenticationSettings auth) - { - if (plex?.Ip == null || auth?.PlexAuthToken == null) - { - Log.Warn("A setting is null, Ensure Plex is configured correctly, and we have a Plex Auth token."); - return false; - } - return true; - } - } +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: PlexAvailabilityChecker.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System; +using System.Collections.Generic; +using System.Linq; + +using NLog; + +using PlexRequests.Api.Interfaces; +using PlexRequests.Api.Models.Plex; +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Helpers; +using PlexRequests.Services.Interfaces; +using PlexRequests.Services.Models; +using PlexRequests.Store; + +using Quartz; + +namespace PlexRequests.Services.Jobs +{ + public class PlexAvailabilityChecker : IJob, IAvailabilityChecker + { + public PlexAvailabilityChecker(ISettingsService plexSettings, ISettingsService auth, IRequestService request, IPlexApi plex, ICacheProvider cache) + { + Plex = plexSettings; + Auth = auth; + RequestService = request; + PlexApi = plex; + Cache = cache; + } + + private ISettingsService Plex { get; } + private ISettingsService Auth { get; } + private IRequestService RequestService { get; } + private static Logger Log = LogManager.GetCurrentClassLogger(); + private IPlexApi PlexApi { get; } + private ICacheProvider Cache { get; } + + public void CheckAndUpdateAll() + { + Log.Trace("Getting the settings"); + var plexSettings = Plex.GetSettings(); + var authSettings = Auth.GetSettings(); + Log.Trace("Getting all the requests"); + + if (!ValidateSettings(plexSettings, authSettings)) + { + Log.Info("Validation of the plex settings failed."); + return; + } + + var libraries = CachedLibraries(authSettings, plexSettings, true); //force setting the cache (10 min intervals via scheduler) + var movies = GetPlexMovies().ToArray(); + var shows = GetPlexTvShows().ToArray(); + var albums = GetPlexAlbums().ToArray(); + + var requests = RequestService.GetAll(); + var requestedModels = requests as RequestedModel[] ?? requests.Where(x => !x.Available).ToArray(); + Log.Trace("Requests Count {0}", requestedModels.Length); + + if (!requestedModels.Any()) + { + Log.Info("There are no requests to check."); + return; + } + + var modifiedModel = new List(); + foreach (var r in requestedModels) + { + Log.Trace("We are going to see if Plex has the following title: {0}", r.Title); + + if (libraries == null) + { + libraries = new List() { PlexApi.SearchContent(authSettings.PlexAuthToken, r.Title, plexSettings.FullUri) }; + if (libraries == null) + { + Log.Trace("Could not find any matching result for this title."); + continue; + } + } + + Log.Trace("Search results from Plex for the following request: {0}", r.Title); + //Log.Trace(results.DumpJson()); + + var releaseDate = r.ReleaseDate == DateTime.MinValue ? string.Empty : r.ReleaseDate.ToString("yyyy"); + + bool matchResult; + switch (r.Type) + { + case RequestType.Movie: + matchResult = IsMovieAvailable(movies, r.Title, releaseDate); + break; + case RequestType.TvShow: + matchResult = IsTvShowAvailable(shows, r.Title, releaseDate); + break; + case RequestType.Album: + matchResult = IsAlbumAvailable(albums, r.Title, r.ReleaseDate.Year.ToString(), r.ArtistName); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + if (matchResult) + { + r.Available = true; + modifiedModel.Add(r); + continue; + } + + Log.Trace("The result from Plex where the title's match was null, so that means the content is not yet in Plex."); + } + + Log.Trace("Updating the requests now"); + Log.Trace("Requests that will be updates:"); + Log.Trace(modifiedModel.SelectMany(x => x.Title).DumpJson()); + + if (modifiedModel.Any()) + { + RequestService.BatchUpdate(modifiedModel); + } + } + + public List GetPlexMovies() + { + var movies = new List(); + var libs = Cache.Get>(CacheKeys.PlexLibaries); + if (libs != null) + { + var movieLibs = libs.Where(x => + x.Video.Any(y => + y.Type.Equals(PlexMediaType.Movie.ToString(), StringComparison.CurrentCultureIgnoreCase) + ) + ).ToArray(); + + foreach (var lib in movieLibs) + { + movies.AddRange(lib.Video.Select(x => new PlexMovie() // movies are in the Video list + { + Title = x.Title, + ReleaseYear = x.Year + })); + } + } + return movies; + } + + public bool IsMovieAvailable(PlexMovie[] plexMovies, string title, string year) + { + return plexMovies.Any(x => x.Title.Equals(title, StringComparison.CurrentCultureIgnoreCase) && x.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase)); + } + + public List GetPlexTvShows() + { + var shows = new List(); + var libs = Cache.Get>(CacheKeys.PlexLibaries); + if (libs != null) + { + var tvLibs = libs.Where(x => + x.Directory.Any(y => + y.Type.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase) + ) + ).ToArray(); + + foreach (var lib in tvLibs) + { + shows.AddRange(lib.Directory.Select(x => new PlexTvShow() // shows are in the directory list + { + Title = x.Title, + ReleaseYear = x.Year + })); + } + } + return shows; + } + + public bool IsTvShowAvailable(PlexTvShow[] plexShows, string title, string year) + { + return plexShows.Any(x => + (x.Title.Equals(title, StringComparison.CurrentCultureIgnoreCase) || x.Title.StartsWith(title, StringComparison.CurrentCultureIgnoreCase)) && + x.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase)); + } + + public List GetPlexAlbums() + { + var albums = new List(); + var libs = Cache.Get>(CacheKeys.PlexLibaries); + if (libs != null) + { + var albumLibs = libs.Where(x => + x.Directory.Any(y => + y.Type.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase) + ) + ).ToArray(); + + foreach (var lib in albumLibs) + { + albums.AddRange(lib.Directory.Select(x => new PlexAlbum() + { + Title = x.Title, + ReleaseYear = x.Year, + Artist = x.ParentTitle + })); + } + } + return albums; + } + + public bool IsAlbumAvailable(PlexAlbum[] plexAlbums, string title, string year, string artist) + { + return plexAlbums.Any(x => + x.Title.Contains(title) && + //x.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase) && + x.Artist.Equals(artist, StringComparison.CurrentCultureIgnoreCase)); + } + + private List CachedLibraries(AuthenticationSettings authSettings, PlexSettings plexSettings, bool setCache) + { + Log.Trace("Obtaining library sections from Plex for the following request"); + + List results = new List(); + + if (!ValidateSettings(plexSettings, authSettings)) + { + Log.Warn("The settings are not configured"); + return results; // don't error out here, just let it go! + } + + if (setCache) + { + results = GetLibraries(authSettings, plexSettings); + Cache.Set(CacheKeys.PlexLibaries, results, 10); + } + else + { + results = Cache.GetOrSet(CacheKeys.PlexLibaries, () => { + return GetLibraries(authSettings, plexSettings); + }, 10); + } + return results; + } + + private List GetLibraries(AuthenticationSettings authSettings, PlexSettings plexSettings) + { + var sections = PlexApi.GetLibrarySections(authSettings.PlexAuthToken, plexSettings.FullUri); + + List libs = new List(); + if (sections != null) + { + foreach (var dir in sections.Directories) + { + Log.Trace("Obtaining results from Plex for the following library section: {0}", dir.Title); + var lib = PlexApi.GetLibrary(authSettings.PlexAuthToken, plexSettings.FullUri, dir.Key); + if (lib != null) + { + libs.Add(lib); + } + } + } + + return libs; + } + + private bool ValidateSettings(PlexSettings plex, AuthenticationSettings auth) + { + if (plex?.Ip == null || auth?.PlexAuthToken == null) + { + Log.Warn("A setting is null, Ensure Plex is configured correctly, and we have a Plex Auth token."); + return false; + } + return true; + } + + public void Execute(IJobExecutionContext context) + { + CheckAndUpdateAll(); + } + } } \ No newline at end of file diff --git a/PlexRequests.Services/SickRageCacher.cs b/PlexRequests.Services/Jobs/SickRageCacher.cs similarity index 90% rename from PlexRequests.Services/SickRageCacher.cs rename to PlexRequests.Services/Jobs/SickRageCacher.cs index 9281cdcf2..3c626a336 100644 --- a/PlexRequests.Services/SickRageCacher.cs +++ b/PlexRequests.Services/Jobs/SickRageCacher.cs @@ -1,78 +1,82 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: PlexAvailabilityChecker.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion - -using System; -using NLog; - -using PlexRequests.Api.Interfaces; -using PlexRequests.Core; -using PlexRequests.Core.SettingModels; -using PlexRequests.Helpers; -using PlexRequests.Services.Interfaces; -using PlexRequests.Api.Models.Movie; -using System.Linq; -using PlexRequests.Api.Models.SickRage; - -namespace PlexRequests.Services -{ - public class SickRageCacher : ISickRageCacher - { - public SickRageCacher(ISettingsService srSettings, ISickRageApi srApi, ICacheProvider cache) - { - SrSettings = srSettings; - SrApi = srApi; - Cache = cache; - } - - private ISettingsService SrSettings { get; } - private ICacheProvider Cache { get; } - private ISickRageApi SrApi { get; } - - private static Logger Log = LogManager.GetCurrentClassLogger(); - - public void Queued(long check) - { - Log.Trace("This is check no. {0}", check); - Log.Trace("Getting the settings"); - - var settings = SrSettings.GetSettings(); - if (settings.Enabled) - { - Log.Trace("Getting all shows from SickRage"); - var movies = SrApi.GetShows(settings.ApiKey, settings.FullUri); - Cache.Set(CacheKeys.SickRageQueued, movies.Result); - } - } - - // we do not want to set here... - public int[] QueuedIds() - { - var tv = Cache.Get(CacheKeys.SickRageQueued); - return tv?.data.Values.Select(x => x.tvdbid).ToArray() ?? new int[] { }; - } - } +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: PlexAvailabilityChecker.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System.Linq; + +using NLog; + +using PlexRequests.Api.Interfaces; +using PlexRequests.Api.Models.SickRage; +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Helpers; +using PlexRequests.Services.Interfaces; + +using Quartz; + +namespace PlexRequests.Services.Jobs +{ + public class SickRageCacher : IJob, ISickRageCacher + { + public SickRageCacher(ISettingsService srSettings, ISickRageApi srApi, ICacheProvider cache) + { + SrSettings = srSettings; + SrApi = srApi; + Cache = cache; + } + + private ISettingsService SrSettings { get; } + private ICacheProvider Cache { get; } + private ISickRageApi SrApi { get; } + + private static Logger Log = LogManager.GetCurrentClassLogger(); + + public void Queued() + { + Log.Trace("Getting the settings"); + + var settings = SrSettings.GetSettings(); + if (settings.Enabled) + { + Log.Trace("Getting all shows from SickRage"); + var movies = SrApi.GetShows(settings.ApiKey, settings.FullUri); + Cache.Set(CacheKeys.SickRageQueued, movies.Result); + } + } + + // we do not want to set here... + public int[] QueuedIds() + { + var tv = Cache.Get(CacheKeys.SickRageQueued); + return tv?.data.Values.Select(x => x.tvdbid).ToArray() ?? new int[] { }; + } + + public void Execute(IJobExecutionContext context) + { + Queued(); + } + } } \ No newline at end of file diff --git a/PlexRequests.Services/SonarrCacher.cs b/PlexRequests.Services/Jobs/SonarrCacher.cs similarity index 91% rename from PlexRequests.Services/SonarrCacher.cs rename to PlexRequests.Services/Jobs/SonarrCacher.cs index 34d00b8c3..63e2425d1 100644 --- a/PlexRequests.Services/SonarrCacher.cs +++ b/PlexRequests.Services/Jobs/SonarrCacher.cs @@ -1,77 +1,83 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: PlexAvailabilityChecker.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion - -using NLog; - -using PlexRequests.Api.Interfaces; -using PlexRequests.Core; -using PlexRequests.Core.SettingModels; -using PlexRequests.Helpers; -using PlexRequests.Services.Interfaces; -using System.Linq; -using System.Collections.Generic; -using PlexRequests.Api.Models.Sonarr; - -namespace PlexRequests.Services -{ - public class SonarrCacher : ISonarrCacher - { - public SonarrCacher(ISettingsService sonarrSettings, ISonarrApi sonarrApi, ICacheProvider cache) - { - SonarrSettings = sonarrSettings; - SonarrApi = sonarrApi; - Cache = cache; - } - - private ISettingsService SonarrSettings { get; } - private ICacheProvider Cache { get; } - private ISonarrApi SonarrApi { get; } - - private static Logger Log = LogManager.GetCurrentClassLogger(); - - public void Queued(long check) - { - Log.Trace("This is check no. {0}", check); - Log.Trace("Getting the settings"); - - var settings = SonarrSettings.GetSettings(); - if (settings.Enabled) - { - Log.Trace("Getting all tv series from Sonarr"); - var series = SonarrApi.GetSeries(settings.ApiKey, settings.FullUri); - Cache.Set(CacheKeys.SonarrQueued, series, 10); - } - } - - // we do not want to set here... - public int[] QueuedIds() - { - var series = Cache.Get>(CacheKeys.SonarrQueued); - return series?.Select(x => x.tvdbId).ToArray() ?? new int[] { }; - } - } +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: PlexAvailabilityChecker.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System.Collections.Generic; +using System.Linq; + +using NLog; + +using PlexRequests.Api.Interfaces; +using PlexRequests.Api.Models.Sonarr; +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Helpers; +using PlexRequests.Services.Interfaces; + +using Quartz; + +namespace PlexRequests.Services.Jobs +{ + public class SonarrCacher : IJob, ISonarrCacher + { + public SonarrCacher(ISettingsService sonarrSettings, ISonarrApi sonarrApi, ICacheProvider cache) + { + SonarrSettings = sonarrSettings; + SonarrApi = sonarrApi; + Cache = cache; + } + + private ISettingsService SonarrSettings { get; } + private ICacheProvider Cache { get; } + private ISonarrApi SonarrApi { get; } + + private static Logger Log = LogManager.GetCurrentClassLogger(); + + public void Queued() + { + Log.Trace("Getting the settings"); + + var settings = SonarrSettings.GetSettings(); + if (settings.Enabled) + { + Log.Trace("Getting all tv series from Sonarr"); + var series = SonarrApi.GetSeries(settings.ApiKey, settings.FullUri); + Cache.Set(CacheKeys.SonarrQueued, series, 10); + } + } + + // we do not want to set here... + public int[] QueuedIds() + { + var series = Cache.Get>(CacheKeys.SonarrQueued); + return series?.Select(x => x.tvdbId).ToArray() ?? new int[] { }; + } + + public void Execute(IJobExecutionContext context) + { + Queued(); + } + } } \ No newline at end of file diff --git a/PlexRequests.Services/MediaCacheService.cs b/PlexRequests.Services/MediaCacheService.cs deleted file mode 100644 index 48799f5b6..000000000 --- a/PlexRequests.Services/MediaCacheService.cs +++ /dev/null @@ -1,102 +0,0 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: AvailabilityUpdateService.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion -using System; -using System.Reactive.Linq; -using System.Web.Hosting; - -using FluentScheduler; - -using Mono.Data.Sqlite; - -using NLog; - -using PlexRequests.Api; -using PlexRequests.Core; -using PlexRequests.Core.SettingModels; -using PlexRequests.Helpers; -using PlexRequests.Services.Interfaces; -using PlexRequests.Store; -using PlexRequests.Store.Repository; -using System.Threading.Tasks; - -namespace PlexRequests.Services -{ - public class MediaCacheService : ITask, IRegisteredObject, IAvailabilityUpdateService - { - public MediaCacheService() - { - var memCache = new MemoryCacheProvider(); - var dbConfig = new DbConfiguration(new SqliteFactory()); - var repo = new SettingsJsonRepository(dbConfig, memCache); - - ConfigurationReader = new ConfigurationReader(); - CpCacher = new CouchPotatoCacher(new SettingsServiceV2(repo), new CouchPotatoApi(), memCache); - SonarrCacher = new SonarrCacher(new SettingsServiceV2(repo), new SonarrApi(), memCache); - SickRageCacher = new SickRageCacher(new SettingsServiceV2(repo), new SickrageApi(), memCache); - HostingEnvironment.RegisterObject(this); - } - - private static Logger Log = LogManager.GetCurrentClassLogger(); - - private IConfigurationReader ConfigurationReader { get; } - private ICouchPotatoCacher CpCacher { get; } - private ISonarrCacher SonarrCacher { get; } - private ISickRageCacher SickRageCacher { get; } - private IDisposable CpSubscription { get; set; } - private IDisposable SonarrSubscription { get; set; } - private IDisposable SickRageSubscription { get; set; } - - public void Start(Configuration c) - { - CpSubscription?.Dispose(); - SonarrSubscription?.Dispose(); - SickRageSubscription?.Dispose(); - - Task.Factory.StartNew(() => CpCacher.Queued(-1)); - Task.Factory.StartNew(() => SonarrCacher.Queued(-1)); - Task.Factory.StartNew(() => SickRageCacher.Queued(-1)); - CpSubscription = Observable.Interval(c.Intervals.Notification).Subscribe(CpCacher.Queued); - SonarrSubscription = Observable.Interval(c.Intervals.Notification).Subscribe(SonarrCacher.Queued); - SickRageSubscription = Observable.Interval(c.Intervals.Notification).Subscribe(SickRageCacher.Queued); - } - - public void Execute() - { - Start(ConfigurationReader.Read()); - } - - public void Stop(bool immediate) - { - HostingEnvironment.UnregisterObject(this); - } - } - - public interface ICouchPotatoCacheService - { - void Start(Configuration c); - } -} diff --git a/PlexRequests.Services/PlexRequests.Services.csproj b/PlexRequests.Services/PlexRequests.Services.csproj index 3afb8086f..49650d33e 100644 --- a/PlexRequests.Services/PlexRequests.Services.csproj +++ b/PlexRequests.Services/PlexRequests.Services.csproj @@ -35,8 +35,12 @@ ..\packages\MimeKit.1.2.22\lib\net45\BouncyCastle.dll True - - ..\packages\FluentScheduler.3.1.46\lib\net40\FluentScheduler.dll + + ..\packages\Common.Logging.3.0.0\lib\net40\Common.Logging.dll + True + + + ..\packages\Common.Logging.Core.3.0.0\lib\net40\Common.Logging.Core.dll True @@ -56,6 +60,10 @@ ..\packages\NLog.4.2.3\lib\net45\NLog.dll True + + ..\packages\Quartz.2.3.3\lib\net40\Quartz.dll + True + @@ -84,20 +92,17 @@ + + + + - - - + - - - - - @@ -107,11 +112,7 @@ - - - - diff --git a/PlexRequests.Services/PlexType.cs b/PlexRequests.Services/PlexType.cs deleted file mode 100644 index 27cd0d1da..000000000 --- a/PlexRequests.Services/PlexType.cs +++ /dev/null @@ -1,35 +0,0 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: PlexType.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion -namespace PlexRequests.Services -{ - public enum PlexType - { - Movie, - TvShow, - Music - } -} \ No newline at end of file diff --git a/PlexRequests.Services/UpdateInterval.cs b/PlexRequests.Services/UpdateInterval.cs deleted file mode 100644 index 92045563a..000000000 --- a/PlexRequests.Services/UpdateInterval.cs +++ /dev/null @@ -1,38 +0,0 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: UpdateInterval.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion -using System; - -using PlexRequests.Services.Interfaces; - -namespace PlexRequests.Services -{ - public class UpdateInterval : IIntervals - { - public TimeSpan Notification => TimeSpan.FromMinutes(10); - - } -} \ No newline at end of file diff --git a/PlexRequests.Services/app.config b/PlexRequests.Services/app.config index 0404cdcb4..44b249bff 100644 --- a/PlexRequests.Services/app.config +++ b/PlexRequests.Services/app.config @@ -1,11 +1,11 @@ - + - - + + - + diff --git a/PlexRequests.Services/packages.config b/PlexRequests.Services/packages.config index 111fbdb40..41673ca47 100644 --- a/PlexRequests.Services/packages.config +++ b/PlexRequests.Services/packages.config @@ -1,9 +1,11 @@  - + + + diff --git a/PlexRequests.UI/Bootstrapper.cs b/PlexRequests.UI/Bootstrapper.cs index 48aeb8290..fc9908b06 100644 --- a/PlexRequests.UI/Bootstrapper.cs +++ b/PlexRequests.UI/Bootstrapper.cs @@ -52,6 +52,11 @@ using PlexRequests.Store.Repository; using PlexRequests.UI.Helpers; using Nancy.Json; +using PlexRequests.Services.Jobs; +using PlexRequests.UI.Jobs; + +using Quartz.Spi; + namespace PlexRequests.UI { public class Bootstrapper : DefaultNancyBootstrapper @@ -90,8 +95,7 @@ namespace PlexRequests.UI container.Register(); container.Register(); container.Register(); - container.Register(); - container.Register(); + container.Register(); // Api's container.Register(); @@ -105,7 +109,7 @@ namespace PlexRequests.UI // NotificationService container.Register().AsSingleton(); - + JsonSettings.MaxJsonLength = int.MaxValue; SubscribeAllObservers(container); diff --git a/PlexRequests.UI/Helpers/ServiceLocator.cs b/PlexRequests.UI/Helpers/ServiceLocator.cs index 860cd150b..40e82e434 100644 --- a/PlexRequests.UI/Helpers/ServiceLocator.cs +++ b/PlexRequests.UI/Helpers/ServiceLocator.cs @@ -24,11 +24,13 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ************************************************************************/ #endregion +using System; + using Nancy.TinyIoc; namespace PlexRequests.UI.Helpers { - public class ServiceLocator + public class ServiceLocator : IServiceLocator { static ServiceLocator() { @@ -46,5 +48,16 @@ namespace PlexRequests.UI.Helpers { return Container?.Resolve(); } + + public object Resolve(Type type) + { + return Container.Resolve(type); + } + } + + public interface IServiceLocator + { + T Resolve() where T : class; + object Resolve(Type type); } } \ No newline at end of file diff --git a/PlexRequests.UI/Jobs/CustomJobFactory.cs b/PlexRequests.UI/Jobs/CustomJobFactory.cs new file mode 100644 index 000000000..0337999cb --- /dev/null +++ b/PlexRequests.UI/Jobs/CustomJobFactory.cs @@ -0,0 +1,94 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: CustomJobFactory.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System; + +using NLog; + +using PlexRequests.UI.Helpers; + +using Quartz; +using Quartz.Spi; + +namespace PlexRequests.UI.Jobs +{ + /// + /// The custom job factory we are using so we are able to use our IoC container with DI in our Jobs. + /// + /// + public class CustomJobFactory : IJobFactory + { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + private IServiceLocator Locator => ServiceLocator.Instance; + + /// + /// Called by the scheduler at the time of the trigger firing, in order to + /// produce a instance on which to call Execute. + /// This will use the to resolve all dependencies of a job. + /// + /// The TriggerFiredBundle from which the + /// and other info relating to the trigger firing can be obtained. + /// a handle to the scheduler that is about to execute the job + /// + /// the newly instantiated Job + /// + /// + /// It should be extremely rare for this method to throw an exception - + /// basically only the case where there is no way at all to instantiate + /// and prepare the Job for execution. When the exception is thrown, the + /// Scheduler will move all triggers associated with the Job into the + /// state, which will require human + /// intervention (e.g. an application restart after fixing whatever + /// configuration problem led to the issue with instantiating the Job). + /// + /// SchedulerException if there is a problem instantiating the Job. + public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) + { + try + { + var jobDetail = bundle.JobDetail; + var jobType = jobDetail.JobType; + + var resolvedType = (IJob)Locator.Resolve(jobType); + return resolvedType; + } + catch (Exception e) + { + Log.Error(e); + throw; + } + } + + /// + /// Allows the job factory to destroy/clean-up the job if needed. + /// + /// + public void ReturnJob(IJob job) + { + // No need to do anything since our jobs do not implement IDisposable. + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Jobs/MediaCacheRegistry.cs b/PlexRequests.UI/Jobs/MediaCacheRegistry.cs deleted file mode 100644 index 3b4b2b68c..000000000 --- a/PlexRequests.UI/Jobs/MediaCacheRegistry.cs +++ /dev/null @@ -1,41 +0,0 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: PlexRegistry.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion - -using FluentScheduler; - -using PlexRequests.Services; - -namespace PlexRequests.UI.Jobs -{ - public class MediaCacheRegistry : Registry - { - public MediaCacheRegistry() - { - Schedule().ToRunNow(); - } - } -} \ No newline at end of file diff --git a/PlexRequests.UI/Jobs/PlexRegistry.cs b/PlexRequests.UI/Jobs/PlexRegistry.cs deleted file mode 100644 index f124cfaf0..000000000 --- a/PlexRequests.UI/Jobs/PlexRegistry.cs +++ /dev/null @@ -1,41 +0,0 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: PlexRegistry.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion - -using FluentScheduler; - -using PlexRequests.Services; - -namespace PlexRequests.UI.Jobs -{ - public class PlexRegistry : Registry - { - public PlexRegistry() - { - Schedule().ToRunNow(); - } - } -} \ No newline at end of file diff --git a/PlexRequests.UI/Jobs/PlexTaskFactory.cs b/PlexRequests.UI/Jobs/PlexTaskFactory.cs deleted file mode 100644 index 5f5b88b89..000000000 --- a/PlexRequests.UI/Jobs/PlexTaskFactory.cs +++ /dev/null @@ -1,23 +0,0 @@ -using FluentScheduler; -using Nancy.TinyIoc; - -using PlexRequests.Services; - -namespace PlexRequests.UI.Jobs -{ - public class PlexTaskFactory : ITaskFactory - { - public ITask GetTaskInstance() where T : ITask - { - //typeof(AvailabilityUpdateService); - var container = TinyIoCContainer.Current; - - var a= container.Resolve(typeof(T)); - - object outT; - container.TryResolve(typeof(T), out outT); - - return (T)a; - } - } -} \ No newline at end of file diff --git a/PlexRequests.UI/Jobs/Scheduler.cs b/PlexRequests.UI/Jobs/Scheduler.cs new file mode 100644 index 000000000..5a91733e1 --- /dev/null +++ b/PlexRequests.UI/Jobs/Scheduler.cs @@ -0,0 +1,137 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: Scheduler.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System; +using System.Collections.Generic; +using System.Linq; + +using NLog; + +using PlexRequests.Services.Jobs; + +using Quartz; +using Quartz.Impl; + +namespace PlexRequests.UI.Jobs +{ + internal sealed class Scheduler + { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + + private readonly ISchedulerFactory _factory; + + public Scheduler() + { + _factory = new StdSchedulerFactory(); + } + + private IEnumerable CreateJobs() + { + var jobs = new List(); + + var plex = JobBuilder.Create().WithIdentity("PlexAvailabilityChecker", "Plex").Build(); + var sickrage = JobBuilder.Create().WithIdentity("SickRageCacher", "Cache").Build(); + var sonarr = JobBuilder.Create().WithIdentity("SonarrCacher", "Cache").Build(); + var cp = JobBuilder.Create().WithIdentity("CouchPotatoCacher", "Cache").Build(); + + jobs.Add(plex); + jobs.Add(sickrage); + jobs.Add(sonarr); + jobs.Add(cp); + + return jobs; + } + + /// + /// Starts the scheduler. + /// + /// The jobs do not match the triggers, we should have a trigger per job + public void StartScheduler() + { + var scheduler = _factory.GetScheduler(); + scheduler.JobFactory = new CustomJobFactory(); + scheduler.Start(); + + var jobs = CreateJobs(); + var triggers = CreateTriggers(); + + var jobDetails = jobs as IJobDetail[] ?? jobs.ToArray(); + var triggerDetails = triggers as ITrigger[] ?? triggers.ToArray(); + + if (jobDetails.Length != triggerDetails.Length) + { + Log.Error("The jobs do not match the triggers, we should have a trigger per job"); + throw new InvalidProgramException("The jobs do not match the triggers, we should have a trigger per job"); + } + + for (var i = 0; i < jobDetails.Length; i++) + { + scheduler.ScheduleJob(jobDetails[i], triggerDetails[i]); + } + } + + private IEnumerable CreateTriggers() + { + var triggers = new List(); + + var plexAvailabilityChecker = + TriggerBuilder.Create() + .WithIdentity("PlexAvailabilityChecker", "Plex") + .StartNow() + .WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever()) + .Build(); + + var srCacher = + TriggerBuilder.Create() + .WithIdentity("SickRageCacher", "Cache") + .StartNow() + .WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever()) + .Build(); + + var sonarrCacher = + TriggerBuilder.Create() + .WithIdentity("SonarrCacher", "Cache") + .StartNow() + .WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever()) + .Build(); + + var cpCacher = + TriggerBuilder.Create() + .WithIdentity("CouchPotatoCacher", "Cache") + .StartNow() + .WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever()) + .Build(); + + + triggers.Add(plexAvailabilityChecker); + triggers.Add(srCacher); + triggers.Add(sonarrCacher); + triggers.Add(cpCacher); + + return triggers; + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/PlexRequests.UI.csproj b/PlexRequests.UI/PlexRequests.UI.csproj index 024b63942..176b1b0fe 100644 --- a/PlexRequests.UI/PlexRequests.UI.csproj +++ b/PlexRequests.UI/PlexRequests.UI.csproj @@ -57,12 +57,16 @@ - - ..\packages\Dapper.1.42\lib\net45\Dapper.dll + + ..\packages\Common.Logging.3.0.0\lib\net40\Common.Logging.dll True - - ..\packages\FluentScheduler.3.1.46\lib\net40\FluentScheduler.dll + + ..\packages\Common.Logging.Core.3.0.0\lib\net40\Common.Logging.Core.dll + True + + + ..\packages\Dapper.1.42\lib\net45\Dapper.dll True @@ -137,6 +141,10 @@ ..\packages\Owin.1.0\lib\net40\Owin.dll True + + ..\packages\Quartz.2.3.3\lib\net40\Quartz.dll + True + ..\packages\RestSharp.105.2.3\lib\net452\RestSharp.dll True @@ -170,7 +178,8 @@ - + + @@ -192,8 +201,6 @@ PreserveNewest - - @@ -304,6 +311,9 @@ PreserveNewest + + Designer + Designer diff --git a/PlexRequests.UI/Program.cs b/PlexRequests.UI/Program.cs index a23309721..fb906e349 100644 --- a/PlexRequests.UI/Program.cs +++ b/PlexRequests.UI/Program.cs @@ -40,9 +40,6 @@ using PlexRequests.Store; using PlexRequests.Store.Repository; using System.Diagnostics; -using FluentScheduler; -using PlexRequests.UI.Jobs; - namespace PlexRequests.UI { class Program @@ -54,7 +51,7 @@ namespace PlexRequests.UI var port = -1; if (args.Length > 0) { - for (int i = 0; i < args.Length; i++) + for (var i = 0; i < args.Length; i++) { var arg = args[i].ToLowerInvariant().Substring(1); switch (arg) @@ -101,8 +98,6 @@ namespace PlexRequests.UI { using (WebApp.Start(options)) { - SetupSchedulers(); - Console.WriteLine($"Request Plex is running on the following: http://+:{port}/"); if (Type.GetType("Mono.Runtime") != null) @@ -165,12 +160,5 @@ namespace PlexRequests.UI LoggingHelper.ReconfigureLogLevel(LogLevel.FromOrdinal(logSettings.Level)); } } - - private static void SetupSchedulers() - { - TaskManager.TaskFactory = new PlexTaskFactory(); - TaskManager.Initialize(new PlexRegistry()); - TaskManager.Initialize(new MediaCacheRegistry()); - } } } diff --git a/PlexRequests.UI/Startup.cs b/PlexRequests.UI/Startup.cs index 60a00ac37..a4a3c81cf 100644 --- a/PlexRequests.UI/Startup.cs +++ b/PlexRequests.UI/Startup.cs @@ -25,36 +25,33 @@ // ************************************************************************/ #endregion using System; -using FluentScheduler; using NLog; using Owin; + using PlexRequests.UI.Jobs; -using TaskFactory = FluentScheduler.TaskFactory; namespace PlexRequests.UI { public class Startup { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); - private static Logger Log = LogManager.GetCurrentClassLogger(); public void Configuration(IAppBuilder app) { try { app.UseNancy(); - + var scheduler = new Scheduler(); + scheduler.StartScheduler(); } catch (Exception exception) { Log.Fatal(exception); throw; } - } - - } -} +} \ No newline at end of file diff --git a/PlexRequests.UI/app.config b/PlexRequests.UI/app.config index c5d2035eb..747d7cb7a 100644 --- a/PlexRequests.UI/app.config +++ b/PlexRequests.UI/app.config @@ -1,50 +1,50 @@ - + -
+
- - + + - + - + - + - - + + - - + + - - + + - + - + diff --git a/PlexRequests.UI/job_scheduling_data_2_0.xsd b/PlexRequests.UI/job_scheduling_data_2_0.xsd new file mode 100644 index 000000000..d1dabc1a9 --- /dev/null +++ b/PlexRequests.UI/job_scheduling_data_2_0.xsd @@ -0,0 +1,361 @@ + + + + + + + Root level node + + + + + + Commands to be executed before scheduling the jobs and triggers in this file. + + + + + Directives to be followed while scheduling the jobs and triggers in this file. + + + + + + + + + + + + + + Version of the XML Schema instance + + + + + + + + + + Delete all jobs, if any, in the identified group. "*" can be used to identify all groups. Will also result in deleting all triggers related to the jobs. + + + + + Delete all triggers, if any, in the identified group. "*" can be used to identify all groups. Will also result in deletion of related jobs that are non-durable. + + + + + Delete the identified job if it exists (will also result in deleting all triggers related to it). + + + + + + + + + + + Delete the identified trigger if it exists (will also result in deletion of related jobs that are non-durable). + + + + + + + + + + + + + + + + Whether the existing scheduling data (with same identifiers) will be overwritten. If false, and ignore-duplicates is not false, and jobs or triggers with the same names already exist as those in the file, an error will occur. + + + + + If true (and overwrite-existing-data is false) then any job/triggers encountered in this file that have names that already exist in the scheduler will be ignored, and no error will be produced. + + + + + If true trigger's start time is calculated based on earlier run time instead of fixed value. Trigger's start time must be undefined for this to work. + + + + + + + + Define a JobDetail + + + + + + + + + + + + + + + + + Define a JobDataMap + + + + + + + + + Define a JobDataMap entry + + + + + + + + + + Define a Trigger + + + + + + + + + + + Common Trigger definitions + + + + + + + + + + + + + + + + + + + + + + + Define a SimpleTrigger + + + + + + + + + + + + + + + + + Define a CronTrigger + + + + + + + + + + + + + + + Define a DateIntervalTrigger + + + + + + + + + + + + + + + + Cron expression (see JavaDoc for examples) + + Special thanks to Chris Thatcher (thatcher@butterfly.net) for the regular expression! + + Regular expressions are not my strong point but I believe this is complete, + with the caveat that order for expressions like 3-0 is not legal but will pass, + and month and day names must be capitalized. + If you want to examine the correctness look for the [\s] to denote the + seperation of individual regular expressions. This is how I break them up visually + to examine them: + + SECONDS: + ( + ((([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?,)*([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?) + | (([\*]|[0-9]|[0-5][0-9])/([0-9]|[0-5][0-9])) + | ([\?]) + | ([\*]) + ) [\s] + MINUTES: + ( + ((([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?,)*([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?) + | (([\*]|[0-9]|[0-5][0-9])/([0-9]|[0-5][0-9])) + | ([\?]) + | ([\*]) + ) [\s] + HOURS: + ( + ((([0-9]|[0-1][0-9]|[2][0-3])(-([0-9]|[0-1][0-9]|[2][0-3]))?,)*([0-9]|[0-1][0-9]|[2][0-3])(-([0-9]|[0-1][0-9]|[2][0-3]))?) + | (([\*]|[0-9]|[0-1][0-9]|[2][0-3])/([0-9]|[0-1][0-9]|[2][0-3])) + | ([\?]) + | ([\*]) + ) [\s] + DAY OF MONTH: + ( + ((([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(-([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]))?,)*([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(-([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]))?(C)?) + | (([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])/([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(C)?) + | (L(-[0-9])?) + | (L(-[1-2][0-9])?) + | (L(-[3][0-1])?) + | (LW) + | ([1-9]W) + | ([1-3][0-9]W) + | ([\?]) + | ([\*]) + )[\s] + MONTH: + ( + ((([1-9]|0[1-9]|1[0-2])(-([1-9]|0[1-9]|1[0-2]))?,)*([1-9]|0[1-9]|1[0-2])(-([1-9]|0[1-9]|1[0-2]))?) + | (([1-9]|0[1-9]|1[0-2])/([1-9]|0[1-9]|1[0-2])) + | (((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?,)*(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?) + | ((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)/(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)) + | ([\?]) + | ([\*]) + )[\s] + DAY OF WEEK: + ( + (([1-7](-([1-7]))?,)*([1-7])(-([1-7]))?) + | ([1-7]/([1-7])) + | (((MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?,)*(MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?(C)?) + | ((MON|TUE|WED|THU|FRI|SAT|SUN)/(MON|TUE|WED|THU|FRI|SAT|SUN)(C)?) + | (([1-7]|(MON|TUE|WED|THU|FRI|SAT|SUN))(L|LW)?) + | (([1-7]|MON|TUE|WED|THU|FRI|SAT|SUN)#([1-7])?) + | ([\?]) + | ([\*]) + ) + YEAR (OPTIONAL): + ( + [\s]? + ([\*])? + | ((19[7-9][0-9])|(20[0-9][0-9]))? + | (((19[7-9][0-9])|(20[0-9][0-9]))/((19[7-9][0-9])|(20[0-9][0-9])))? + | ((((19[7-9][0-9])|(20[0-9][0-9]))(-((19[7-9][0-9])|(20[0-9][0-9])))?,)*((19[7-9][0-9])|(20[0-9][0-9]))(-((19[7-9][0-9])|(20[0-9][0-9])))?)? + ) + + + + + + + + + + Number of times to repeat the Trigger (-1 for indefinite) + + + + + + + + + + Simple Trigger Misfire Instructions + + + + + + + + + + + + + + Cron Trigger Misfire Instructions + + + + + + + + + + + Date Interval Trigger Misfire Instructions + + + + + + + + + + + Interval Units + + + + + + + + + + + + + \ No newline at end of file diff --git a/PlexRequests.UI/packages.config b/PlexRequests.UI/packages.config index 8c2dea7cd..63d5b6c2b 100644 --- a/PlexRequests.UI/packages.config +++ b/PlexRequests.UI/packages.config @@ -1,7 +1,8 @@  + + - @@ -22,6 +23,7 @@ +