diff --git a/README.md b/README.md
index 814bb9bb9..e8e269e7f 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ ___
Follow me developing Ombi!
-[![Twitch](https://img.shields.io/badge/Twitch-Watch-blue.svg?style=flat-square&logo=twitch)](https://twitch.tv/tiusjar)
+[![Twitch](https://img.shields.io/badge/Twitch-Watch-blue.svg?style=flat-square&logo=twitch)](https://www.twitch.tv/tidusjar)
___
@@ -68,6 +68,7 @@ We integrate with the following applications:
Supported notifications:
* SMTP Notifications (Email)
* Discord
+* Gotify
* Slack
* Pushbullet
* Pushover
diff --git a/build.cake b/build.cake
index e8e4bb8c0..b2ae8842c 100644
--- a/build.cake
+++ b/build.cake
@@ -3,7 +3,7 @@
#addin "Cake.Gulp"
#addin "SharpZipLib"
#addin nuget:?package=Cake.Compression&version=0.1.4
-#addin "Cake.Incubator"
+#addin "Cake.Incubator&version=3.1.0"
#addin "Cake.Yarn"
//////////////////////////////////////////////////////////////////////
@@ -81,9 +81,9 @@ Task("SetVersionInfo")
versionInfo = GitVersion(settings);
- Information("GitResults -> {0}", versionInfo.Dump());
+// Information("GitResults -> {0}", versionInfo.Dump());
- Information(@"Build:{0}",AppVeyor.Environment.Build.Dump());
+//Information(@"Build:{0}",AppVeyor.Environment.Build.Dump());
var buildVersion = string.Empty;
if(string.IsNullOrEmpty(AppVeyor.Environment.Build.Version))
diff --git a/src/Ombi.Api.Emby/Models/Media/Tv/EmbyEpisodes.cs b/src/Ombi.Api.Emby/Models/Media/Tv/EmbyEpisodes.cs
index d76915923..83d64ed15 100644
--- a/src/Ombi.Api.Emby/Models/Media/Tv/EmbyEpisodes.cs
+++ b/src/Ombi.Api.Emby/Models/Media/Tv/EmbyEpisodes.cs
@@ -16,6 +16,7 @@ namespace Ombi.Api.Emby.Models.Media.Tv
public int ProductionYear { get; set; }
public bool IsPlaceHolder { get; set; }
public int IndexNumber { get; set; }
+ public int? IndexNumberEnd { get; set; }
public int ParentIndexNumber { get; set; }
public bool IsHD { get; set; }
public bool IsFolder { get; set; }
diff --git a/src/Ombi.Api.Gotify/GotifyApi.cs b/src/Ombi.Api.Gotify/GotifyApi.cs
new file mode 100644
index 000000000..8cd79a689
--- /dev/null
+++ b/src/Ombi.Api.Gotify/GotifyApi.cs
@@ -0,0 +1,36 @@
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace Ombi.Api.Gotify
+{
+ public class GotifyApi : IGotifyApi
+ {
+ public GotifyApi(IApi api)
+ {
+ _api = api;
+ }
+
+ private readonly IApi _api;
+
+ public async Task PushAsync(string baseUrl, string accessToken, string subject, string body, sbyte priority)
+ {
+ var request = new Request("/message", baseUrl, HttpMethod.Post);
+ request.AddQueryString("token", accessToken);
+
+ request.AddHeader("Access-Token", accessToken);
+ request.ApplicationJsonContentType();
+
+
+ var jsonBody = new
+ {
+ message = body,
+ title = subject,
+ priority = priority
+ };
+
+ request.AddJsonBody(jsonBody);
+
+ await _api.Request(request);
+ }
+ }
+}
diff --git a/src/Ombi.Api.Gotify/IGotifyApi.cs b/src/Ombi.Api.Gotify/IGotifyApi.cs
new file mode 100644
index 000000000..e6a6b4060
--- /dev/null
+++ b/src/Ombi.Api.Gotify/IGotifyApi.cs
@@ -0,0 +1,9 @@
+using System.Threading.Tasks;
+
+namespace Ombi.Api.Gotify
+{
+ public interface IGotifyApi
+ {
+ Task PushAsync(string endpoint, string accessToken, string subject, string body, sbyte priority);
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj b/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj
new file mode 100644
index 000000000..ce5475fae
--- /dev/null
+++ b/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj
@@ -0,0 +1,15 @@
+
+
+
+ netstandard2.0
+ 3.0.0.0
+ 3.0.0.0
+
+
+
+
+
+
+
+
+
diff --git a/src/Ombi.Api.Lidarr/ILidarrApi.cs b/src/Ombi.Api.Lidarr/ILidarrApi.cs
index 4a23c6200..0eac960d0 100644
--- a/src/Ombi.Api.Lidarr/ILidarrApi.cs
+++ b/src/Ombi.Api.Lidarr/ILidarrApi.cs
@@ -23,5 +23,6 @@ namespace Ombi.Api.Lidarr
Task> GetLanguageProfile(string apiKey, string baseUrl);
Task Status(string apiKey, string baseUrl);
Task AlbumSearch(int[] albumIds, string apiKey, string baseUrl);
+ Task AlbumInformation(string albumId, string apiKey, string baseUrl);
}
}
\ No newline at end of file
diff --git a/src/Ombi.Api.Lidarr/LidarrApi.cs b/src/Ombi.Api.Lidarr/LidarrApi.cs
index a6a283703..cb8db759e 100644
--- a/src/Ombi.Api.Lidarr/LidarrApi.cs
+++ b/src/Ombi.Api.Lidarr/LidarrApi.cs
@@ -105,6 +105,32 @@ namespace Ombi.Api.Lidarr
return Api.Request>(request);
}
+ public async Task AlbumInformation(string albumId, string apiKey, string baseUrl)
+ {
+ var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get);
+ request.AddQueryString("foreignAlbumId", albumId);
+ AddHeaders(request, apiKey);
+ var albums = await Api.Request>(request);
+ return albums.Where(x => x.foreignAlbumId.Equals(albumId, StringComparison.InvariantCultureIgnoreCase))
+ .FirstOrDefault();
+ }
+
+
+ ///
+ /// THIS ONLY SUPPORTS ALBUMS THAT THE ARTIST IS IN LIDARR
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Task> GetTracksForAlbum(int albumId, string apiKey, string baseUrl)
+ {
+ var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get);
+ request.AddQueryString("albumId", albumId.ToString());
+ AddHeaders(request, apiKey);
+ return Api.Request>(request);
+ }
+
public Task AddArtist(ArtistAdd artist, string apiKey, string baseUrl)
{
var request = new Request($"{ApiVersion}/artist", baseUrl, HttpMethod.Post);
diff --git a/src/Ombi.Api.Lidarr/Models/AlbumLookup.cs b/src/Ombi.Api.Lidarr/Models/AlbumLookup.cs
index b2394eb5f..1e909cf4c 100644
--- a/src/Ombi.Api.Lidarr/Models/AlbumLookup.cs
+++ b/src/Ombi.Api.Lidarr/Models/AlbumLookup.cs
@@ -1,10 +1,15 @@
using System;
+using System.Collections.Generic;
namespace Ombi.Api.Lidarr.Models
{
public class AlbumLookup
{
public string title { get; set; }
+ public string status { get; set; }
+ public string artistType { get; set; }
+ public string disambiguation { get; set; }
+ public List links { get; set; }
public int artistId { get; set; }
public string foreignAlbumId { get; set; }
public bool monitored { get; set; }
diff --git a/src/Ombi.Api.Lidarr/Models/LidarrLinks.cs b/src/Ombi.Api.Lidarr/Models/LidarrLinks.cs
new file mode 100644
index 000000000..e8bdb8975
--- /dev/null
+++ b/src/Ombi.Api.Lidarr/Models/LidarrLinks.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Ombi.Api.Lidarr.Models
+{
+ public class LidarrLinks
+ {
+ public string url { get; set; }
+ public string name { get; set; }
+ }
+}
diff --git a/src/Ombi.Api.Lidarr/Models/LidarrRatings.cs b/src/Ombi.Api.Lidarr/Models/LidarrRatings.cs
new file mode 100644
index 000000000..7728d58bf
--- /dev/null
+++ b/src/Ombi.Api.Lidarr/Models/LidarrRatings.cs
@@ -0,0 +1,8 @@
+namespace Ombi.Api.Lidarr.Models
+{
+ public class LidarrRatings
+ {
+ public int votes { get; set; }
+ public decimal value { get; set; }
+ }
+}
diff --git a/src/Ombi.Api.Lidarr/Models/LidarrTrack.cs b/src/Ombi.Api.Lidarr/Models/LidarrTrack.cs
new file mode 100644
index 000000000..367e8cc7c
--- /dev/null
+++ b/src/Ombi.Api.Lidarr/Models/LidarrTrack.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Ombi.Api.Lidarr.Models
+{
+ public class LidarrTrack
+ {
+ public int artistId { get; set; }
+ public int trackFileId { get; set; }
+ public int albumId { get; set; }
+ public bool _explicit { get; set; }
+ public int absoluteTrackNumber { get; set; }
+ public string trackNumber { get; set; }
+ public string title { get; set; }
+ public int duration { get; set; }
+ public int mediumNumber { get; set; }
+ public bool hasFile { get; set; }
+ public bool monitored { get; set; }
+ public int id { get; set; }
+ }
+}
diff --git a/src/Ombi.Api.Pushover/PushoverApi.cs b/src/Ombi.Api.Pushover/PushoverApi.cs
index 9f91bc7ca..41df0f647 100644
--- a/src/Ombi.Api.Pushover/PushoverApi.cs
+++ b/src/Ombi.Api.Pushover/PushoverApi.cs
@@ -2,6 +2,7 @@
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
+using System.Web;
using Ombi.Api.Pushover.Models;
namespace Ombi.Api.Pushover
@@ -18,11 +19,7 @@ namespace Ombi.Api.Pushover
public async Task PushAsync(string accessToken, string message, string userToken, sbyte priority, string sound)
{
- if (message.Contains("'"))
- {
- message = message.Replace("'", "'");
- }
- var request = new Request($"messages.json?token={accessToken}&user={userToken}&priority={priority}&sound={sound}&message={WebUtility.HtmlEncode(message)}", PushoverEndpoint, HttpMethod.Post);
+ var request = new Request($"messages.json?token={accessToken}&user={userToken}&priority={priority}&sound={sound}&message={WebUtility.UrlEncode(message)}", PushoverEndpoint, HttpMethod.Post);
var result = await _api.Request(request);
return result;
diff --git a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs
index 7ff8283da..34c21e008 100644
--- a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs
+++ b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs
@@ -4,6 +4,7 @@ using Moq;
using Ombi.Core.Rule.Rules.Request;
using Ombi.Store.Entities.Requests;
using NUnit.Framework;
+using Ombi.Core.Authentication;
using Ombi.Helpers;
namespace Ombi.Core.Tests.Rule.Request
@@ -16,7 +17,7 @@ namespace Ombi.Core.Tests.Rule.Request
{
PrincipalMock = new Mock();
- Rule = new AutoApproveRule(PrincipalMock.Object);
+ Rule = new AutoApproveRule(PrincipalMock.Object, null);
}
diff --git a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs
index c9db5875a..f2781c8d2 100644
--- a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs
+++ b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs
@@ -3,6 +3,7 @@ using System.Threading.Tasks;
using Moq;
using NUnit.Framework;
using Ombi.Core.Rule.Rules;
+using Ombi.Core.Rule.Rules.Request;
using Ombi.Helpers;
using Ombi.Store.Entities.Requests;
@@ -15,7 +16,7 @@ namespace Ombi.Core.Tests.Rule.Request
{
PrincipalMock = new Mock();
- Rule = new CanRequestRule(PrincipalMock.Object);
+ Rule = new CanRequestRule(PrincipalMock.Object, null);
}
diff --git a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs
index 99ff5b6bd..0171e37a1 100644
--- a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs
+++ b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs
@@ -16,7 +16,7 @@ namespace Ombi.Core.Tests.Rule.Search
public void Setup()
{
ContextMock = new Mock();
- Rule = new EmbyAvailabilityRule(ContextMock.Object);
+ Rule = new EmbyAvailabilityRule(ContextMock.Object, null);
}
private EmbyAvailabilityRule Rule { get; set; }
diff --git a/src/Ombi.Core.Tests/Rule/Search/PlexAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/PlexAvailabilityRuleTests.cs
index 55177a6ac..5bd35473c 100644
--- a/src/Ombi.Core.Tests/Rule/Search/PlexAvailabilityRuleTests.cs
+++ b/src/Ombi.Core.Tests/Rule/Search/PlexAvailabilityRuleTests.cs
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
using Moq;
using NUnit.Framework;
using Ombi.Core.Models.Search;
@@ -14,7 +15,7 @@ namespace Ombi.Core.Tests.Rule.Search
public void Setup()
{
ContextMock = new Mock();
- Rule = new PlexAvailabilityRule(ContextMock.Object);
+ Rule = new PlexAvailabilityRule(ContextMock.Object, new Mock>().Object);
}
private PlexAvailabilityRule Rule { get; set; }
diff --git a/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs
index 03294982a..71c02af9d 100644
--- a/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs
+++ b/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs
@@ -12,5 +12,6 @@ namespace Ombi.Core.Engine
Task> GetArtistAlbums(string foreignArtistId);
Task> SearchAlbum(string search);
Task> SearchArtist(string search);
+ Task GetAlbumInformation(string foreignAlbumId);
}
}
\ No newline at end of file
diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs
index 84cb8afcf..520f052a9 100644
--- a/src/Ombi.Core/Engine/MovieSearchEngine.cs
+++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs
@@ -227,7 +227,7 @@ namespace Ombi.Core.Engine
}
var request = await RequestService.MovieRequestService.GetAll()
.AnyAsync(x => x.RequestedUserId.Equals(user.Id) && x.TheMovieDbId == viewModel.Id);
- if (request)
+ if (request || viewModel.Available)
{
viewModel.ShowSubscribe = false;
}
diff --git a/src/Ombi.Core/Engine/MusicSearchEngine.cs b/src/Ombi.Core/Engine/MusicSearchEngine.cs
index d0e577801..c8d285766 100644
--- a/src/Ombi.Core/Engine/MusicSearchEngine.cs
+++ b/src/Ombi.Core/Engine/MusicSearchEngine.cs
@@ -60,6 +60,18 @@ namespace Ombi.Core.Engine
return vm;
}
+ public async Task GetAlbumInformation(string foreignAlbumId)
+ {
+ var settings = await GetSettings();
+ var result = await _lidarrApi.AlbumInformation(foreignAlbumId, settings.ApiKey, settings.FullUri);
+
+
+ var vm = await MapIntoAlbumVm(result, settings);
+
+
+ return vm;
+ }
+
///
/// Searches the specified artist
///
@@ -143,6 +155,48 @@ namespace Ombi.Core.Engine
return vm;
}
+
+ // TODO
+ private async Task MapIntoAlbumVm(AlbumResponse a, LidarrSettings settings)
+ {
+ var vm = new SearchAlbumViewModel
+ {
+ ForeignAlbumId = a.foreignAlbumId,
+ Monitored = a.monitored,
+ Rating = a.ratings?.value ?? 0m,
+ ReleaseDate = a.releaseDate,
+ Title = a.title,
+ Disk = a.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url?.Replace("http", "https"),
+ Genres = a.genres
+ };
+ if (a.artistId > 0)
+ {
+ //TODO THEY HAVE FIXED THIS IN DEV
+ // The JSON is different for some stupid reason
+ // Need to lookup the artist now and all the images -.-"
+ var artist = await _lidarrApi.GetArtist(a.artistId, settings.ApiKey, settings.FullUri);
+ vm.ArtistName = artist.artistName;
+ vm.ForeignArtistId = artist.foreignArtistId;
+ }
+ else
+ {
+ //vm.ForeignArtistId = a.artistId?.foreignArtistId;
+ //vm.ArtistName = a.artist?.artistName;
+ }
+
+ vm.Cover = a.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url?.Replace("http", "https");
+ if (vm.Cover.IsNullOrEmpty())
+ {
+ //vm.Cover = a.remoteCover;
+ }
+
+ await Rules.StartSpecificRules(vm, SpecificRules.LidarrAlbum);
+
+ await RunSearchRules(vm);
+
+ return vm;
+ }
+
private async Task MapIntoAlbumVm(AlbumLookup a, LidarrSettings settings)
{
var vm = new SearchAlbumViewModel
@@ -152,7 +206,8 @@ namespace Ombi.Core.Engine
Rating = a.ratings?.value ?? 0m,
ReleaseDate = a.releaseDate,
Title = a.title,
- Disk = a.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url
+ Disk = a.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url?.Replace("http", "https"),
+ Genres = a.genres
};
if (a.artistId > 0)
{
@@ -169,7 +224,7 @@ namespace Ombi.Core.Engine
vm.ArtistName = a.artist?.artistName;
}
- vm.Cover = a.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url;
+ vm.Cover = a.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url?.Replace("http", "https");
if (vm.Cover.IsNullOrEmpty())
{
vm.Cover = a.remoteCover;
diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs
index 58144d3ce..796e2fe6a 100644
--- a/src/Ombi.Core/Engine/TvRequestEngine.cs
+++ b/src/Ombi.Core/Engine/TvRequestEngine.cs
@@ -31,14 +31,13 @@ namespace Ombi.Core.Engine
{
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,
+ ITvSender sender, IRepository rl, ISettingsService settings, ICacheService cache,
IRepository sub) : base(user, requestService, rule, manager, cache, settings, sub)
{
TvApi = tvApi;
MovieDbApi = movApi;
NotificationHelper = helper;
TvSender = sender;
- Audit = audit;
_requestLog = rl;
}
@@ -46,7 +45,6 @@ namespace Ombi.Core.Engine
private ITvMazeApi TvApi { get; }
private IMovieDbApi MovieDbApi { get; }
private ITvSender TvSender { get; }
- private IAuditRepository Audit { get; }
private readonly IRepository _requestLog;
public async Task RequestTvShow(TvRequestViewModel tv)
@@ -84,8 +82,6 @@ namespace Ombi.Core.Engine
}
}
- await Audit.Record(AuditType.Added, AuditArea.TvRequest, $"Added Request {tvBuilder.ChildRequest.Title}", Username);
-
var existingRequest = await TvRepository.Get().FirstOrDefaultAsync(x => x.TvDbId == tv.TvDbId);
if (existingRequest != null)
{
@@ -351,7 +347,6 @@ namespace Ombi.Core.Engine
public async Task UpdateTvRequest(TvRequests request)
{
- await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username);
var allRequests = TvRepository.Get();
var results = await allRequests.FirstOrDefaultAsync(x => x.Id == request.Id);
@@ -394,7 +389,6 @@ namespace Ombi.Core.Engine
if (request.Approved)
{
NotificationHelper.Notify(request, NotificationType.RequestApproved);
- await Audit.Record(AuditType.Approved, AuditArea.TvRequest, $"Approved Request {request.Title}", Username);
// Autosend
await TvSender.Send(request);
}
@@ -426,9 +420,7 @@ namespace Ombi.Core.Engine
public async Task UpdateChildRequest(ChildRequests request)
{
- await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username);
-
- await TvRepository.UpdateChild(request);
+ await TvRepository.UpdateChild(request);
return request;
}
@@ -446,16 +438,14 @@ namespace Ombi.Core.Engine
// Delete the parent
TvRepository.Db.TvRequests.Remove(parent);
}
- await Audit.Record(AuditType.Deleted, AuditArea.TvRequest, $"Deleting Request {request.Title}", Username);
-
+
await TvRepository.Db.SaveChangesAsync();
}
public async Task RemoveTvRequest(int requestId)
{
var request = await TvRepository.Get().FirstOrDefaultAsync(x => x.Id == requestId);
- await Audit.Record(AuditType.Deleted, AuditArea.TvRequest, $"Deleting Request {request.Title}", Username);
- await TvRepository.Delete(request);
+ await TvRepository.Delete(request);
}
public async Task UserHasRequest(string userId)
diff --git a/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs b/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs
index a494a3cb5..e9f9c5f9e 100644
--- a/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs
+++ b/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs
@@ -16,8 +16,13 @@ namespace Ombi.Core.Models.Search
public string Cover { get; set; }
public string Disk { get; set; }
public decimal PercentOfTracks { get; set; }
+ public object[] Genres { get; set; }
public override RequestType Type => RequestType.Album;
public bool PartiallyAvailable => PercentOfTracks != 100 && PercentOfTracks > 0;
public bool FullyAvailable => PercentOfTracks == 100;
+
+
+ // Below is from the INFO call NEED A SEPERATE VM FOR THIS IN V4 TODO
+ // TODO ADD TRACK COUNT
}
}
\ No newline at end of file
diff --git a/src/Ombi.Core/Models/UI/GotifyNotificationViewModel.cs b/src/Ombi.Core/Models/UI/GotifyNotificationViewModel.cs
new file mode 100644
index 000000000..93ce66724
--- /dev/null
+++ b/src/Ombi.Core/Models/UI/GotifyNotificationViewModel.cs
@@ -0,0 +1,23 @@
+
+using System.Collections.Generic;
+using Ombi.Settings.Settings.Models.Notifications;
+using Ombi.Store.Entities;
+
+namespace Ombi.Core.Models.UI
+{
+ ///
+ /// The view model for the notification settings page
+ ///
+ ///
+ public class GotifyNotificationViewModel : GotifySettings
+ {
+ ///
+ /// Gets or sets the notification templates.
+ ///
+ ///
+ /// The notification templates.
+ ///
+ public List NotificationTemplates { get; set; }
+
+ }
+}
diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj
index 35688a6fe..790aa8500 100644
--- a/src/Ombi.Core/Ombi.Core.csproj
+++ b/src/Ombi.Core/Ombi.Core.csproj
@@ -11,9 +11,9 @@
-
+
-
+
diff --git a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs
index a55868db8..685f02b54 100644
--- a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs
+++ b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs
@@ -1,5 +1,7 @@
using System.Security.Principal;
using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using Ombi.Core.Authentication;
using Ombi.Core.Models.Requests;
using Ombi.Core.Rule.Interfaces;
using Ombi.Helpers;
@@ -10,28 +12,31 @@ namespace Ombi.Core.Rule.Rules.Request
{
public class AutoApproveRule : BaseRequestRule, IRules
{
- public AutoApproveRule(IPrincipal principal)
+ public AutoApproveRule(IPrincipal principal, OmbiUserManager um)
{
User = principal;
+ _manager = um;
}
private IPrincipal User { get; }
+ private readonly OmbiUserManager _manager;
- public Task Execute(BaseRequest obj)
+ public async Task Execute(BaseRequest obj)
{
- if (User.IsInRole(OmbiRoles.Admin))
+ var user = await _manager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name);
+ if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin))
{
obj.Approved = true;
- return Task.FromResult(Success());
+ return Success();
}
- if (obj.RequestType == RequestType.Movie && User.IsInRole(OmbiRoles.AutoApproveMovie))
+ if (obj.RequestType == RequestType.Movie && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie))
obj.Approved = true;
- if (obj.RequestType == RequestType.TvShow && User.IsInRole(OmbiRoles.AutoApproveTv))
+ if (obj.RequestType == RequestType.TvShow && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveTv))
obj.Approved = true;
- if (obj.RequestType == RequestType.Album && User.IsInRole(OmbiRoles.AutoApproveMusic))
+ if (obj.RequestType == RequestType.Album && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMusic))
obj.Approved = true;
- return Task.FromResult(Success()); // We don't really care, we just don't set the obj to approve
+ return Success(); // We don't really care, we just don't set the obj to approve
}
}
}
\ No newline at end of file
diff --git a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs
index 678e5ff6a..eb974eeec 100644
--- a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs
+++ b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs
@@ -1,57 +1,59 @@
-using Ombi.Store.Entities;
+using Ombi.Store.Entities;
using System.IO;
+using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using Ombi.Core.Authentication;
using Ombi.Core.Rule.Interfaces;
using Ombi.Helpers;
+using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests;
-namespace Ombi.Core.Rule.Rules
+namespace Ombi.Core.Rule.Rules.Request
{
public class CanRequestRule : BaseRequestRule, IRules
{
- public CanRequestRule(IPrincipal principal)
+ public CanRequestRule(IPrincipal principal, OmbiUserManager manager)
{
User = principal;
+ _manager = manager;
}
private IPrincipal User { get; }
+ private readonly OmbiUserManager _manager;
- public Task Execute(BaseRequest obj)
+ public async Task Execute(BaseRequest obj)
{
- if (User.IsInRole(OmbiRoles.Admin))
- {
- return Task.FromResult(Success());
- }
+ var user = await _manager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name);
+ if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin))
+ return Success();
if (obj.RequestType == RequestType.Movie)
{
- if (User.IsInRole(OmbiRoles.RequestMovie) || User.IsInRole(OmbiRoles.AutoApproveMovie))
- {
- return Task.FromResult(Success());
- }
-
- return Task.FromResult(Fail("You do not have permissions to Request a Movie"));
+ if (await _manager.IsInRoleAsync(user, OmbiRoles.RequestMovie) || await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie))
+ return Success();
+ return Fail("You do not have permissions to Request a Movie");
}
if (obj.RequestType == RequestType.TvShow)
{
- if (User.IsInRole(OmbiRoles.RequestTv) || User.IsInRole(OmbiRoles.AutoApproveTv))
+ if (await _manager.IsInRoleAsync(user, OmbiRoles.RequestTv) || await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveTv))
{
- return Task.FromResult(Success());
+ return TSuccess();
}
- return Task.FromResult(Fail("You do not have permissions to Request a TV Show"));
+ return Fail("You do not have permissions to Request a TV Show");
}
if (obj.RequestType == RequestType.Album)
{
- if (User.IsInRole(OmbiRoles.RequestMusic) || User.IsInRole(OmbiRoles.AutoApproveMusic))
+ if (await _manager.IsInRoleAsync(user, OmbiRoles.RequestMusic) || await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMusic))
{
- return Task.FromResult(Success());
+ return Success();
}
- return Task.FromResult(Fail("You do not have permissions to Request an Album"));
+ return Fail("You do not have permissions to Request an Album");
}
throw new InvalidDataException("Permission check failed: unknown RequestType");
diff --git a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs
index 428de9ce5..ab1a0af98 100644
--- a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs
+++ b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs
@@ -2,7 +2,7 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Query;
+using Microsoft.Extensions.Logging;
using Ombi.Core.Models.Search;
using Ombi.Store.Entities;
using Ombi.Store.Repository.Requests;
@@ -24,7 +24,7 @@ namespace Ombi.Core.Rule.Rules.Search
if (!airedButNotAvailable)
{
var unairedEpisodes = search.SeasonRequests.Any(x =>
- x.Episodes.Any(c => !c.Available && c.AirDate > DateTime.Now.Date));
+ x.Episodes.Any(c => !c.Available && c.AirDate > DateTime.Now.Date || c.AirDate != DateTime.MinValue));
if (unairedEpisodes)
{
search.FullyAvailable = true;
@@ -34,28 +34,36 @@ namespace Ombi.Core.Rule.Rules.Search
}
public static async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode,
- SeasonRequests season, PlexServerContent item, bool useTheMovieDb, bool useTvDb)
+ SeasonRequests season, PlexServerContent item, bool useTheMovieDb, bool useTvDb, ILogger log)
{
PlexEpisode epExists = null;
- if (useImdb)
+ try
{
- epExists = await allEpisodes.FirstOrDefaultAsync(x =>
- x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
- x.Series.ImdbId == item.ImdbId.ToString());
- }
- if (useTheMovieDb)
- {
- epExists = await allEpisodes.FirstOrDefaultAsync(x =>
- x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
- x.Series.TheMovieDbId == item.TheMovieDbId.ToString());
- }
+ if (useImdb)
+ {
+ epExists = await allEpisodes.FirstOrDefaultAsync(x =>
+ x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
+ x.Series.ImdbId == item.ImdbId);
+ }
- if (useTvDb)
+ if (useTheMovieDb)
+ {
+ epExists = await allEpisodes.FirstOrDefaultAsync(x =>
+ x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
+ x.Series.TheMovieDbId == item.TheMovieDbId);
+ }
+
+ if (useTvDb)
+ {
+ epExists = await allEpisodes.FirstOrDefaultAsync(x =>
+ x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
+ x.Series.TvDbId == item.TvDbId);
+ }
+ }
+ catch (Exception e)
{
- epExists = await allEpisodes.FirstOrDefaultAsync(x =>
- x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
- x.Series.TvDbId == item.TvDbId.ToString());
+ log.LogError(e, "Exception thrown when attempting to check if something is available");
}
if (epExists != null)
@@ -71,21 +79,21 @@ namespace Ombi.Core.Rule.Rules.Search
{
epExists = await allEpisodes.FirstOrDefaultAsync(x =>
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
- x.Series.ImdbId == item.ImdbId.ToString());
+ x.Series.ImdbId == item.ImdbId);
}
if (useTheMovieDb)
{
epExists = await allEpisodes.FirstOrDefaultAsync(x =>
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
- x.Series.TheMovieDbId == item.TheMovieDbId.ToString());
+ x.Series.TheMovieDbId == item.TheMovieDbId);
}
if (useTvDb)
{
epExists = await allEpisodes.FirstOrDefaultAsync(x =>
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
- x.Series.TvDbId == item.TvDbId.ToString());
+ x.Series.TvDbId == item.TvDbId);
}
if (epExists != null)
diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs
index 3171c6ada..f80bded7a 100644
--- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs
+++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs
@@ -3,6 +3,8 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Ombi.Core.Models.Search;
using Ombi.Core.Rule.Interfaces;
+using Ombi.Core.Settings;
+using Ombi.Core.Settings.Models.External;
using Ombi.Helpers;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
@@ -11,12 +13,14 @@ namespace Ombi.Core.Rule.Rules.Search
{
public class EmbyAvailabilityRule : BaseSearchRule, IRules
{
- public EmbyAvailabilityRule(IEmbyContentRepository repo)
+ public EmbyAvailabilityRule(IEmbyContentRepository repo, ISettingsService s)
{
EmbyContentRepository = repo;
+ EmbySettings = s;
}
private IEmbyContentRepository EmbyContentRepository { get; }
+ private ISettingsService EmbySettings { get; }
public async Task Execute(SearchViewModel obj)
{
@@ -60,7 +64,16 @@ namespace Ombi.Core.Rule.Rules.Search
if (item != null)
{
obj.Available = true;
- obj.EmbyUrl = item.Url;
+ var s = await EmbySettings.GetSettingsAsync();
+ var server = s.Servers.FirstOrDefault(x => x.ServerHostname != null);
+ if ((server?.ServerHostname ?? string.Empty).HasValue())
+ {
+ obj.EmbyUrl = $"{server.ServerHostname}#!/itemdetails.html?id={item.EmbyId}";
+ }
+ else
+ {
+ obj.EmbyUrl = $"https://app.emby.media/#!/itemdetails.html?id={item.EmbyId}";
+ }
if (obj.Type == RequestType.TvShow)
{
diff --git a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs
index 7f79e4165..2a239d1d3 100644
--- a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs
+++ b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs
@@ -1,5 +1,6 @@
using System.Linq;
using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
using Ombi.Core.Models.Search;
using Ombi.Core.Rule.Interfaces;
using Ombi.Helpers;
@@ -10,12 +11,14 @@ namespace Ombi.Core.Rule.Rules.Search
{
public class PlexAvailabilityRule : BaseSearchRule, IRules
{
- public PlexAvailabilityRule(IPlexContentRepository repo)
+ public PlexAvailabilityRule(IPlexContentRepository repo, ILogger log)
{
PlexContentRepository = repo;
+ Log = log;
}
private IPlexContentRepository PlexContentRepository { get; }
+ private ILogger Log { get; }
public async Task Execute(SearchViewModel obj)
{
@@ -72,7 +75,7 @@ namespace Ombi.Core.Rule.Rules.Search
{
foreach (var episode in season.Episodes)
{
- await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb);
+ await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb, Log);
}
}
diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs
index 76a9fc14c..0e9db9192 100644
--- a/src/Ombi.Core/Senders/MusicSender.cs
+++ b/src/Ombi.Core/Senders/MusicSender.cs
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Threading.Tasks;
+using EnsureThat;
using Microsoft.Extensions.Logging;
using Ombi.Api.Lidarr;
using Ombi.Api.Lidarr.Models;
@@ -87,6 +88,11 @@ namespace Ombi.Core.Senders
if (artist == null || artist.id <= 0)
{
+ EnsureArg.IsNotNullOrEmpty(model.ForeignArtistId, nameof(model.ForeignArtistId));
+ EnsureArg.IsNotNullOrEmpty(model.ForeignAlbumId, nameof(model.ForeignAlbumId));
+ EnsureArg.IsNotNullOrEmpty(model.ArtistName, nameof(model.ArtistName));
+ EnsureArg.IsNotNullOrEmpty(rootFolderPath, nameof(rootFolderPath));
+
// Create artist
var newArtist = new ArtistAdd
{
diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs
index 68a363706..f5705969b 100644
--- a/src/Ombi.DependencyInjection/IocExtensions.cs
+++ b/src/Ombi.DependencyInjection/IocExtensions.cs
@@ -32,6 +32,7 @@ using Ombi.Api.CouchPotato;
using Ombi.Api.DogNzb;
using Ombi.Api.FanartTv;
using Ombi.Api.Github;
+using Ombi.Api.Gotify;
using Ombi.Api.Lidarr;
using Ombi.Api.Mattermost;
using Ombi.Api.Notifications;
@@ -60,6 +61,7 @@ using Ombi.Schedule.Jobs.Plex.Interfaces;
using Ombi.Schedule.Jobs.SickRage;
using Ombi.Schedule.Processor;
using Ombi.Store.Entities;
+using Quartz.Spi;
namespace Ombi.DependencyInjection
{
@@ -120,6 +122,7 @@ namespace Ombi.DependencyInjection
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
services.AddTransient();
services.AddTransient();
services.AddTransient();
@@ -132,28 +135,28 @@ namespace Ombi.DependencyInjection
}
public static void RegisterStore(this IServiceCollection services) {
- services.AddEntityFrameworkSqlite().AddDbContext();
- services.AddEntityFrameworkSqlite().AddDbContext();
- services.AddEntityFrameworkSqlite().AddDbContext();
+ services.AddDbContext();
+ services.AddDbContext();
+ services.AddDbContext();
services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6
services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6
services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient(typeof(ISettingsService<>), typeof(SettingsService<>));
- services.AddTransient(typeof(IRepository<>), typeof(Repository<>));
- services.AddTransient(typeof(IExternalRepository<>), typeof(ExternalRepository<>));
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped();
+ services.AddScoped(typeof(ISettingsService<>), typeof(SettingsService<>));
+ services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
+ services.AddScoped(typeof(IExternalRepository<>), typeof(ExternalRepository<>));
}
public static void RegisterServices(this IServiceCollection services)
{
@@ -161,7 +164,7 @@ namespace Ombi.DependencyInjection
services.AddTransient();
services.AddTransient();
services.AddTransient();
- services.AddTransient();
+ services.AddSingleton();
services.AddTransient();
services.AddTransient();
@@ -170,6 +173,7 @@ namespace Ombi.DependencyInjection
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
services.AddTransient();
services.AddTransient();
services.AddTransient();
@@ -177,6 +181,7 @@ namespace Ombi.DependencyInjection
public static void RegisterJobs(this IServiceCollection services)
{
+ services.AddSingleton(provider => new IoCJobFactory(provider));
services.AddTransient();
services.AddTransient();
@@ -197,7 +202,7 @@ namespace Ombi.DependencyInjection
services.AddTransient();
services.AddTransient();
services.AddTransient();
- services.AddTransient();
+ //services.AddTransient();
services.AddTransient();
services.AddTransient();
services.AddTransient();
diff --git a/src/Ombi.Helpers/CacheService.cs b/src/Ombi.Helpers/CacheService.cs
index 4eef62bda..ae57a9f61 100644
--- a/src/Ombi.Helpers/CacheService.cs
+++ b/src/Ombi.Helpers/CacheService.cs
@@ -28,18 +28,15 @@ namespace Ombi.Helpers
return result;
}
- using (await _mutex.LockAsync())
+ if (_memoryCache.TryGetValue(cacheKey, out result))
{
- if (_memoryCache.TryGetValue(cacheKey, out result))
- {
- return result;
- }
-
- result = await factory();
- _memoryCache.Set(cacheKey, result, absoluteExpiration);
-
return result;
}
+
+ result = await factory();
+ _memoryCache.Set(cacheKey, result, absoluteExpiration);
+
+ return result;
}
public void Remove(string key)
@@ -47,34 +44,34 @@ namespace Ombi.Helpers
_memoryCache.Remove(key);
}
-
-
- public T GetOrAdd(string cacheKey, Func factory, DateTime absoluteExpiration)
+
+
+ public T GetOrAdd(string cacheKey, Func factory, DateTime absoluteExpiration)
+ {
+ // locks get and set internally
+ if (_memoryCache.TryGetValue(cacheKey, out var result))
{
- // locks get and set internally
- if (_memoryCache.TryGetValue(cacheKey, out var result))
+ return result;
+ }
+
+ lock (TypeLock.Lock)
+ {
+ if (_memoryCache.TryGetValue(cacheKey, out result))
{
return result;
}
- lock (TypeLock.Lock)
- {
- if (_memoryCache.TryGetValue(cacheKey, out result))
- {
- return result;
- }
-
- result = factory();
- _memoryCache.Set(cacheKey, result, absoluteExpiration);
+ result = factory();
+ _memoryCache.Set(cacheKey, result, absoluteExpiration);
- return result;
- }
+ return result;
}
+ }
+
+ private static class TypeLock
+ {
+ public static object Lock { get; } = new object();
+ }
- private static class TypeLock
- {
- public static object Lock { get; } = new object();
- }
-
}
}
diff --git a/src/Ombi.Helpers/Cron.cs b/src/Ombi.Helpers/Cron.cs
index 35b141eda..9b6339391 100644
--- a/src/Ombi.Helpers/Cron.cs
+++ b/src/Ombi.Helpers/Cron.cs
@@ -16,7 +16,6 @@
// You should have received a copy of the GNU Lesser General Public
// License along with Hangfire. If not, see .
- using System;
///
/// Helper class that provides common values for the cron expressions.
///
@@ -44,7 +43,7 @@
/// The minute in which the schedule will be activated (0-59).
public static string Hourly(int minute)
{
- return $"{minute} * * * *";
+ return $"0 {minute} 0/1 1/1 * ? *";
}
///
@@ -73,7 +72,7 @@
/// The minute in which the schedule will be activated (0-59).
public static string Daily(int hour, int minute)
{
- return $"{minute} {hour} * * *";
+ return $"0 {minute} {hour} 1/1 * ? *";
}
///
@@ -114,7 +113,7 @@
/// The minute in which the schedule will be activated (0-59).
public static string Weekly(DayOfWeek dayOfWeek, int hour, int minute)
{
- return $"{minute} {hour} * * {(int)dayOfWeek}";
+ return $"0 {minute} {hour} ? * {(int)dayOfWeek} *";
}
///
@@ -219,7 +218,7 @@
/// The number of minutes to wait between every activation.
public static string MinuteInterval(int interval)
{
- return $"*/{interval} * * * *";
+ return $"0 0/{interval} * 1/1 * ? *";
}
///
@@ -228,7 +227,7 @@
/// The number of hours to wait between every activation.
public static string HourInterval(int interval)
{
- return $"0 */{interval} * * *";
+ return $"0 0 0/{interval} 1/1 * ? *";
}
///
@@ -237,7 +236,7 @@
/// The number of days to wait between every activation.
public static string DayInterval(int interval)
{
- return $"0 0 */{interval} * *";
+ return $"0 0 12 1/{interval} * ? *";
}
///
@@ -249,4 +248,39 @@
return $"0 0 1 */{interval} *";
}
}
+
+ //
+ // Summary:
+ // Specifies the day of the week.
+ public enum DayOfWeek
+ {
+ //
+ // Summary:
+ // Indicates Sunday.
+ Sunday = 1,
+ //
+ // Summary:
+ // Indicates Monday.
+ Monday = 2,
+ //
+ // Summary:
+ // Indicates Tuesday.
+ Tuesday = 3,
+ //
+ // Summary:
+ // Indicates Wednesday.
+ Wednesday = 4,
+ //
+ // Summary:
+ // Indicates Thursday.
+ Thursday = 5,
+ //
+ // Summary:
+ // Indicates Friday.
+ Friday = 6,
+ //
+ // Summary:
+ // Indicates Saturday.
+ Saturday = 7
+ }
}
\ No newline at end of file
diff --git a/src/Ombi.Helpers/LoggingEvents.cs b/src/Ombi.Helpers/LoggingEvents.cs
index 3893dc879..0723800ab 100644
--- a/src/Ombi.Helpers/LoggingEvents.cs
+++ b/src/Ombi.Helpers/LoggingEvents.cs
@@ -32,6 +32,7 @@ namespace Ombi.Helpers
public static EventId MattermostNotification => new EventId(4004);
public static EventId PushoverNotification => new EventId(4005);
public static EventId TelegramNotifcation => new EventId(4006);
+ public static EventId GotifyNotification => new EventId(4007);
public static EventId TvSender => new EventId(5000);
public static EventId SonarrSender => new EventId(5001);
diff --git a/src/Ombi.Helpers/NotificationAgent.cs b/src/Ombi.Helpers/NotificationAgent.cs
index 8990eeba9..18f28105a 100644
--- a/src/Ombi.Helpers/NotificationAgent.cs
+++ b/src/Ombi.Helpers/NotificationAgent.cs
@@ -10,5 +10,6 @@
Slack = 5,
Mattermost = 6,
Mobile = 7,
+ Gotify = 8,
}
}
\ No newline at end of file
diff --git a/src/Ombi.Mapping/Profiles/SettingsProfile.cs b/src/Ombi.Mapping/Profiles/SettingsProfile.cs
index 139290f2b..f460ce78b 100644
--- a/src/Ombi.Mapping/Profiles/SettingsProfile.cs
+++ b/src/Ombi.Mapping/Profiles/SettingsProfile.cs
@@ -19,6 +19,7 @@ namespace Ombi.Mapping.Profiles
CreateMap().ReverseMap();
CreateMap().ReverseMap();
CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
}
}
}
\ No newline at end of file
diff --git a/src/Ombi.Notifications/Agents/GotifyNotification.cs b/src/Ombi.Notifications/Agents/GotifyNotification.cs
new file mode 100644
index 000000000..e1c9fc1db
--- /dev/null
+++ b/src/Ombi.Notifications/Agents/GotifyNotification.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using Ombi.Api.Gotify;
+using Ombi.Core.Settings;
+using Ombi.Helpers;
+using Ombi.Notifications.Models;
+using Ombi.Settings.Settings.Models;
+using Ombi.Settings.Settings.Models.Notifications;
+using Ombi.Store.Entities;
+using Ombi.Store.Repository;
+using Ombi.Store.Repository.Requests;
+
+namespace Ombi.Notifications.Agents
+{
+ public class GotifyNotification : BaseNotification, IGotifyNotification
+ {
+ public GotifyNotification(IGotifyApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
+ ISettingsService s, IRepository sub, IMusicRequestRepository music,
+ IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref)
+ {
+ Api = api;
+ Logger = log;
+ }
+
+ public override string NotificationName => "GotifyNotification";
+
+ private IGotifyApi Api { get; }
+ private ILogger Logger { get; }
+
+ protected override bool ValidateConfiguration(GotifySettings settings)
+ {
+ return settings.Enabled && !string.IsNullOrEmpty(settings.BaseUrl) && !string.IsNullOrEmpty(settings.ApplicationToken);
+ }
+
+ protected override async Task NewRequest(NotificationOptions model, GotifySettings settings)
+ {
+ await Run(model, settings, NotificationType.NewRequest);
+ }
+
+
+ protected override async Task NewIssue(NotificationOptions model, GotifySettings settings)
+ {
+ await Run(model, settings, NotificationType.Issue);
+ }
+
+ protected override async Task IssueComment(NotificationOptions model, GotifySettings settings)
+ {
+ await Run(model, settings, NotificationType.IssueComment);
+ }
+
+ protected override async Task IssueResolved(NotificationOptions model, GotifySettings settings)
+ {
+ await Run(model, settings, NotificationType.IssueResolved);
+ }
+
+ protected override async Task AddedToRequestQueue(NotificationOptions model, GotifySettings settings)
+ {
+ await Run(model, settings, NotificationType.ItemAddedToFaultQueue);
+ }
+
+ protected override async Task RequestDeclined(NotificationOptions model, GotifySettings settings)
+ {
+ await Run(model, settings, NotificationType.RequestDeclined);
+ }
+
+ protected override async Task RequestApproved(NotificationOptions model, GotifySettings settings)
+ {
+ await Run(model, settings, NotificationType.RequestApproved);
+ }
+
+ protected override async Task AvailableRequest(NotificationOptions model, GotifySettings settings)
+ {
+ await Run(model, settings, NotificationType.RequestAvailable);
+ }
+
+ protected override async Task Send(NotificationMessage model, GotifySettings settings)
+ {
+ try
+ {
+ await Api.PushAsync(settings.BaseUrl, settings.ApplicationToken, model.Subject, model.Message, settings.Priority);
+ }
+ catch (Exception e)
+ {
+ Logger.LogError(LoggingEvents.GotifyNotification, e, "Failed to send Gotify notification");
+ }
+ }
+
+ protected override async Task Test(NotificationOptions model, GotifySettings settings)
+ {
+ var message = $"This is a test from Ombi, if you can see this then we have successfully pushed a notification!";
+ var notification = new NotificationMessage
+ {
+ Message = message,
+ };
+ await Send(notification, settings);
+ }
+
+ private async Task Run(NotificationOptions model, GotifySettings settings, NotificationType type)
+ {
+ var parsed = await LoadTemplate(NotificationAgent.Gotify, type, model);
+ if (parsed.Disabled)
+ {
+ Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.Gotify}");
+ return;
+ }
+
+ var notification = new NotificationMessage
+ {
+ Message = parsed.Message,
+ };
+
+ await Send(notification, settings);
+ }
+ }
+}
diff --git a/src/Ombi.Notifications/Agents/Interfaces/IGotifyNotification.cs b/src/Ombi.Notifications/Agents/Interfaces/IGotifyNotification.cs
new file mode 100644
index 000000000..a85421938
--- /dev/null
+++ b/src/Ombi.Notifications/Agents/Interfaces/IGotifyNotification.cs
@@ -0,0 +1,6 @@
+namespace Ombi.Notifications.Agents
+{
+ public interface IGotifyNotification : INotification
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi.Notifications/Agents/MattermostNotification.cs b/src/Ombi.Notifications/Agents/MattermostNotification.cs
index f64a0fe21..ed3084c19 100644
--- a/src/Ombi.Notifications/Agents/MattermostNotification.cs
+++ b/src/Ombi.Notifications/Agents/MattermostNotification.cs
@@ -52,7 +52,7 @@ namespace Ombi.Notifications.Agents
private void AddOtherInformation(NotificationOptions model, NotificationMessage notification,
NotificationMessageContent parsed)
{
- notification.Other.Add("image", parsed.Image);
+ notification.Other.Add("image", parsed?.Image ?? string.Empty);
notification.Other.Add("title", model.RequestType == RequestType.Movie ? MovieRequest.Title : TvRequest.Title);
}
diff --git a/src/Ombi.Notifications/BaseNotification.cs b/src/Ombi.Notifications/BaseNotification.cs
index 001f68f45..c9404eb2c 100644
--- a/src/Ombi.Notifications/BaseNotification.cs
+++ b/src/Ombi.Notifications/BaseNotification.cs
@@ -30,6 +30,7 @@ namespace Ombi.Notifications
_log = log;
AlbumRepository = album;
UserNotificationPreferences = notificationUserPreferences;
+ Settings.ClearCache();
}
protected ISettingsService Settings { get; }
diff --git a/src/Ombi.Notifications/GenericEmailProvider.cs b/src/Ombi.Notifications/GenericEmailProvider.cs
index 653670ef7..15f17af92 100644
--- a/src/Ombi.Notifications/GenericEmailProvider.cs
+++ b/src/Ombi.Notifications/GenericEmailProvider.cs
@@ -4,6 +4,7 @@ using EnsureThat;
using MailKit.Net.Smtp;
using Microsoft.Extensions.Logging;
using MimeKit;
+using MimeKit.Utils;
using Ombi.Core.Settings;
using Ombi.Helpers;
using Ombi.Notifications.Models;
@@ -37,6 +38,15 @@ namespace Ombi.Notifications
var customization = await CustomizationSettings.GetSettingsAsync();
var html = email.LoadTemplate(model.Subject, model.Message, null, customization.Logo);
+
+ var messageId = MimeUtils.GenerateMessageId();
+ if (customization.ApplicationUrl.HasValue())
+ {
+ if (Uri.TryCreate(customization.ApplicationUrl, UriKind.RelativeOrAbsolute, out var url))
+ {
+ messageId = MimeUtils.GenerateMessageId(url.IdnHost);
+ }
+ }
var textBody = string.Empty;
@@ -50,7 +60,8 @@ namespace Ombi.Notifications
var message = new MimeMessage
{
Body = body.ToMessageBody(),
- Subject = model.Subject
+ Subject = model.Subject,
+ MessageId = messageId
};
message.From.Add(new MailboxAddress(string.IsNullOrEmpty(settings.SenderName) ? settings.SenderAddress : settings.SenderName, settings.SenderAddress));
message.To.Add(new MailboxAddress(model.To, model.To));
diff --git a/src/Ombi.Notifications/Ombi.Notifications.csproj b/src/Ombi.Notifications/Ombi.Notifications.csproj
index 2b5c95154..3fa4b4830 100644
--- a/src/Ombi.Notifications/Ombi.Notifications.csproj
+++ b/src/Ombi.Notifications/Ombi.Notifications.csproj
@@ -15,6 +15,7 @@
+
diff --git a/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs b/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs
index 932022cd8..1606cb2d5 100644
--- a/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs
+++ b/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs
@@ -32,7 +32,7 @@ namespace Ombi.Schedule.Tests
[Test]
public async Task DoesNotRun_WhenDisabled()
{
- await Job.Start();
+ await Job.Execute(null);
Repo.Verify(x => x.GetAll(),Times.Never);
}
@@ -50,7 +50,7 @@ namespace Ombi.Schedule.Tests
Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings { DeleteIssues = true, DaysAfterResolvedToDelete = 5 });
Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues));
- await Job.Start();
+ await Job.Execute(null);
Assert.That(issues.First().Status, Is.EqualTo(IssueStatus.Deleted));
Repo.Verify(x => x.SaveChangesAsync(), Times.Once);
@@ -75,7 +75,7 @@ namespace Ombi.Schedule.Tests
Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings { DeleteIssues = true, DaysAfterResolvedToDelete = 5 });
Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues));
- await Job.Start();
+ await Job.Execute(null);
Assert.That(issues[0].Status, Is.Not.EqualTo(IssueStatus.Deleted));
Assert.That(issues[1].Status, Is.EqualTo(IssueStatus.Deleted));
diff --git a/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs b/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs
new file mode 100644
index 000000000..6d00f8ef6
--- /dev/null
+++ b/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs
@@ -0,0 +1,36 @@
+using Moq;
+using NUnit.Framework;
+using Quartz;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Ombi.Schedule.Tests
+{
+ [TestFixture]
+ public class OmbiQuartzTests
+ {
+
+ [Test]
+ [Ignore("Cannot get this to work")]
+ public async Task Test()
+ {
+ var scheduleMock = new Mock();
+ scheduleMock.Setup(x => x.TriggerJob(It.IsAny(),
+ It.IsAny()));
+ var sut = new QuartzMock(scheduleMock);
+
+ //await QuartzMock.TriggerJob("ABC");
+
+ scheduleMock.Verify(x => x.TriggerJob(It.Is(j => j.Name == "ABC"),
+ default(CancellationToken)), Times.Once);
+ }
+ }
+ public class QuartzMock : OmbiQuartz
+ {
+ public QuartzMock(Mock mock)
+ {
+ _instance = this;
+ _scheduler = mock.Object;
+ }
+ }
+}
diff --git a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs
index 55c9dc288..028c044b7 100644
--- a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs
+++ b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs
@@ -46,7 +46,7 @@ namespace Ombi.Schedule.Tests
_movie.Setup(x => x.GetAll()).Returns(new List { request }.AsQueryable());
_repo.Setup(x => x.Get("test")).ReturnsAsync(new PlexServerContent());
- await Checker.Start();
+ await Checker.Execute(null);
_movie.Verify(x => x.Save(), Times.Once);
@@ -62,8 +62,8 @@ namespace Ombi.Schedule.Tests
};
_movie.Setup(x => x.GetAll()).Returns(new List { request }.AsQueryable());
- await Checker.Start();
-
+ await Checker.Execute(null);
+
Assert.False(request.Available);
}
@@ -107,7 +107,7 @@ namespace Ombi.Schedule.Tests
}.AsQueryable);
_repo.Setup(x => x.Include(It.IsAny>(),It.IsAny>>()));
- await Checker.Start();
+ await Checker.Execute(null);
_tv.Verify(x => x.Save(), Times.Once);
diff --git a/src/Ombi.Schedule/IocJobFactory.cs b/src/Ombi.Schedule/IocJobFactory.cs
new file mode 100644
index 000000000..83ab5a974
--- /dev/null
+++ b/src/Ombi.Schedule/IocJobFactory.cs
@@ -0,0 +1,32 @@
+using System;
+using Microsoft.Extensions.DependencyInjection;
+using Quartz;
+using Quartz.Spi;
+
+namespace Ombi.Schedule
+{
+ public class IoCJobFactory : IJobFactory
+ {
+ private readonly IServiceProvider _factory;
+
+ public IoCJobFactory(IServiceProvider factory)
+ {
+ _factory = factory;
+ }
+ public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
+ {
+ var scopeFactory = _factory.GetService();
+ var scope = scopeFactory.CreateScope();
+ var scopedContainer = scope.ServiceProvider;
+
+ var implementation = scopedContainer.GetRequiredService(bundle.JobDetail.JobType) as IJob;
+ return implementation;
+ }
+
+ public void ReturnJob(IJob job)
+ {
+ var disposable = job as IDisposable;
+ disposable?.Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs
index 5cc818441..f0f53f128 100644
--- a/src/Ombi.Schedule/JobSetup.cs
+++ b/src/Ombi.Schedule/JobSetup.cs
@@ -65,25 +65,24 @@ namespace Ombi.Schedule
{
var s = _jobSettings.GetSettings();
- 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(false), JobSettingsHelper.PlexContent(s));
- RecurringJob.AddOrUpdate(() => _plexRecentlyAddedSync.Start(), JobSettingsHelper.PlexRecentlyAdded(s));
- RecurringJob.AddOrUpdate(() => _cpCache.Start(), JobSettingsHelper.CouchPotato(s));
- RecurringJob.AddOrUpdate(() => _srSync.Start(), JobSettingsHelper.SickRageSync(s));
- RecurringJob.AddOrUpdate(() => _refreshMetadata.Start(), JobSettingsHelper.RefreshMetadata(s));
- RecurringJob.AddOrUpdate(() => _lidarrArtistSync.CacheContent(), JobSettingsHelper.LidarrArtistSync(s));
- RecurringJob.AddOrUpdate(() => _issuesPurge.Start(), JobSettingsHelper.IssuePurge(s));
+ // RecurringJob.AddOrUpdate(() => _embyContentSync.Start(), JobSettingsHelper.EmbyContent(s));
+ // RecurringJob.AddOrUpdate(() => _sonarrSync.Start(), JobSettingsHelper.Sonarr(s));
+ // RecurringJob.AddOrUpdate(() => _radarrSync.CacheContent(), JobSettingsHelper.Radarr(s));
+ // //RecurringJob.AddOrUpdate(() => _plexContentSync.Execute(null), JobSettingsHelper.PlexContent(s));
+ // //RecurringJob.AddOrUpdate(() => _plexRecentlyAddedSync.Start(), JobSettingsHelper.PlexRecentlyAdded(s));
+ // RecurringJob.AddOrUpdate(() => _cpCache.Start(), JobSettingsHelper.CouchPotato(s));
+ // RecurringJob.AddOrUpdate(() => _srSync.Start(), JobSettingsHelper.SickRageSync(s));
+ // RecurringJob.AddOrUpdate(() => _refreshMetadata.Start(), JobSettingsHelper.RefreshMetadata(s));
+ // RecurringJob.AddOrUpdate(() => _lidarrArtistSync.CacheContent(), JobSettingsHelper.LidarrArtistSync(s));
+ // RecurringJob.AddOrUpdate(() => _issuesPurge.Start(), JobSettingsHelper.IssuePurge(s));
- RecurringJob.AddOrUpdate(() => _updater.Update(null), JobSettingsHelper.Updater(s));
+ // RecurringJob.AddOrUpdate(() => _updater.Update(null), JobSettingsHelper.Updater(s));
- RecurringJob.AddOrUpdate(() => _embyUserImporter.Start(), JobSettingsHelper.UserImporter(s));
- RecurringJob.AddOrUpdate(() => _plexUserImporter.Start(), JobSettingsHelper.UserImporter(s));
- RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s));
- RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s));
- RecurringJob.AddOrUpdate(() => _resender.Start(), JobSettingsHelper.ResendFailedRequests(s));
- RecurringJob.AddOrUpdate(() => _mediaDatabaseRefresh.Start(), JobSettingsHelper.MediaDatabaseRefresh(s));
+ // RecurringJob.AddOrUpdate(() => _embyUserImporter.Start(), JobSettingsHelper.UserImporter(s));
+ // RecurringJob.AddOrUpdate(() => _plexUserImporter.Start(), JobSettingsHelper.UserImporter(s));
+ // RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s));
+ //// RecurringJob.AddOrUpdate(() => _resender.Start(), JobSettingsHelper.ResendFailedRequests(s));
+ // RecurringJob.AddOrUpdate(() => _mediaDatabaseRefresh.Start(), JobSettingsHelper.MediaDatabaseRefresh(s));
}
private bool _disposed;
@@ -94,7 +93,6 @@ namespace Ombi.Schedule
if (disposing)
{
- _plexContentSync?.Dispose();
_radarrSync?.Dispose();
_updater?.Dispose();
_plexUserImporter?.Dispose();
diff --git a/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs b/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs
index 5e9f13534..ca848e56f 100644
--- a/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs
+++ b/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs
@@ -36,6 +36,7 @@ using Ombi.Helpers;
using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Context;
using Ombi.Store.Entities;
+using Quartz;
namespace Ombi.Schedule.Jobs.Couchpotato
{
@@ -56,7 +57,7 @@ namespace Ombi.Schedule.Jobs.Couchpotato
private readonly ILogger _log;
private readonly IExternalContext _ctx;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
var settings = await _settings.GetSettingsAsync();
if (!settings.Enabled)
diff --git a/src/Ombi.Schedule/Jobs/Couchpotato/ICouchPotatoSync.cs b/src/Ombi.Schedule/Jobs/Couchpotato/ICouchPotatoSync.cs
index caa390834..fa23d5030 100644
--- a/src/Ombi.Schedule/Jobs/Couchpotato/ICouchPotatoSync.cs
+++ b/src/Ombi.Schedule/Jobs/Couchpotato/ICouchPotatoSync.cs
@@ -4,6 +4,5 @@ namespace Ombi.Schedule.Jobs.Couchpotato
{
public interface ICouchPotatoSync : IBaseJob
{
- Task Start();
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs
index 7007b3743..929f8d7b9 100644
--- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs
+++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs
@@ -37,6 +37,7 @@ using Ombi.Notifications.Models;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
+using Quartz;
namespace Ombi.Schedule.Jobs.Emby
{
@@ -58,7 +59,7 @@ namespace Ombi.Schedule.Jobs.Emby
private readonly INotificationService _notificationService;
private readonly ILogger _log;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
await ProcessMovies();
await ProcessTv();
diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs
index e22c0ca51..a64b7bb30 100644
--- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs
+++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs
@@ -12,6 +12,7 @@ using Ombi.Helpers;
using Ombi.Schedule.Jobs.Ombi;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
+using Quartz;
using Serilog;
using EmbyMediaType = Ombi.Store.Entities.EmbyMediaType;
@@ -20,25 +21,21 @@ namespace Ombi.Schedule.Jobs.Emby
public class EmbyContentSync : IEmbyContentSync
{
public EmbyContentSync(ISettingsService settings, IEmbyApi api, ILogger logger,
- IEmbyContentRepository repo, IEmbyEpisodeSync epSync, IRefreshMetadata metadata)
+ IEmbyContentRepository repo)
{
_logger = logger;
_settings = settings;
_api = api;
_repo = repo;
- _episodeSync = epSync;
- _metadata = metadata;
}
private readonly ILogger _logger;
private readonly ISettingsService _settings;
private readonly IEmbyApi _api;
private readonly IEmbyContentRepository _repo;
- private readonly IEmbyEpisodeSync _episodeSync;
- private readonly IRefreshMetadata _metadata;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
var embySettings = await _settings.GetSettingsAsync();
if (!embySettings.Enable)
@@ -57,8 +54,9 @@ namespace Ombi.Schedule.Jobs.Emby
}
// Episodes
- BackgroundJob.Enqueue(() => _episodeSync.Start());
- BackgroundJob.Enqueue(() => _metadata.Start());
+
+ await OmbiQuartz.TriggerJob(nameof(IEmbyEpisodeSync), "Emby");
+ await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System");
}
diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs
index 962b08cda..69ebdc42c 100644
--- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs
+++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs
@@ -36,29 +36,27 @@ using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
+using Quartz;
namespace Ombi.Schedule.Jobs.Emby
{
public class EmbyEpisodeSync : IEmbyEpisodeSync
{
- public EmbyEpisodeSync(ISettingsService s, IEmbyApi api, ILogger l, IEmbyContentRepository repo,
- IEmbyAvaliabilityChecker checker)
+ public EmbyEpisodeSync(ISettingsService s, IEmbyApi api, ILogger l, IEmbyContentRepository repo)
{
_api = api;
_logger = l;
_settings = s;
_repo = repo;
- _avaliabilityChecker = checker;
}
private readonly ISettingsService _settings;
private readonly IEmbyApi _api;
private readonly ILogger _logger;
private readonly IEmbyContentRepository _repo;
- private readonly IEmbyAvaliabilityChecker _avaliabilityChecker;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
var settings = await _settings.GetSettingsAsync();
@@ -67,7 +65,8 @@ namespace Ombi.Schedule.Jobs.Emby
await CacheEpisodes(server);
}
- BackgroundJob.Enqueue(() => _avaliabilityChecker.Start());
+
+ await OmbiQuartz.TriggerJob(nameof(IEmbyAvaliabilityChecker), "Emby");
}
private async Task CacheEpisodes(EmbyServers server)
@@ -118,6 +117,22 @@ namespace Ombi.Schedule.Jobs.Emby
Title = ep.Name,
AddedAt = DateTime.UtcNow
});
+
+ if (ep.IndexNumberEnd.HasValue && ep.IndexNumberEnd.Value != ep.IndexNumber)
+ {
+ epToAdd.Add(new EmbyEpisode
+ {
+ EmbyId = ep.Id,
+ EpisodeNumber = ep.IndexNumberEnd.Value,
+ SeasonNumber = ep.ParentIndexNumber,
+ ParentId = ep.SeriesId,
+ TvDbId = ep.ProviderIds.Tvdb,
+ TheMovieDbId = ep.ProviderIds.Tmdb,
+ ImdbId = ep.ProviderIds.Imdb,
+ Title = ep.Name,
+ AddedAt = DateTime.UtcNow
+ });
+ }
}
}
@@ -142,7 +157,6 @@ namespace Ombi.Schedule.Jobs.Emby
{
_settings?.Dispose();
_repo?.Dispose();
- _avaliabilityChecker?.Dispose();
}
_disposed = true;
}
diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs
index 280a61ab4..5cb7b368d 100644
--- a/src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs
+++ b/src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs
@@ -37,6 +37,7 @@ using Ombi.Core.Settings.Models.External;
using Ombi.Helpers;
using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities;
+using Quartz;
namespace Ombi.Schedule.Jobs.Emby
{
@@ -58,7 +59,7 @@ namespace Ombi.Schedule.Jobs.Emby
private readonly ISettingsService _embySettings;
private readonly ISettingsService _userManagementSettings;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
var userManagementSettings = await _userManagementSettings.GetSettingsAsync();
if (!userManagementSettings.ImportEmbyUsers)
diff --git a/src/Ombi.Schedule/Jobs/Emby/IEmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/IEmbyAvaliabilityChecker.cs
index ce9792f3b..ce2d7dba7 100644
--- a/src/Ombi.Schedule/Jobs/Emby/IEmbyAvaliabilityChecker.cs
+++ b/src/Ombi.Schedule/Jobs/Emby/IEmbyAvaliabilityChecker.cs
@@ -4,6 +4,5 @@ namespace Ombi.Schedule.Jobs.Emby
{
public interface IEmbyAvaliabilityChecker : IBaseJob
{
- Task Start();
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Emby/IEmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/IEmbyContentSync.cs
index 5ba8ea6f9..8dd85bab4 100644
--- a/src/Ombi.Schedule/Jobs/Emby/IEmbyContentSync.cs
+++ b/src/Ombi.Schedule/Jobs/Emby/IEmbyContentSync.cs
@@ -4,6 +4,5 @@ namespace Ombi.Schedule.Jobs.Emby
{
public interface IEmbyContentSync : IBaseJob
{
- Task Start();
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Emby/IEmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/IEmbyEpisodeSync.cs
index 42d761832..bff623ff8 100644
--- a/src/Ombi.Schedule/Jobs/Emby/IEmbyEpisodeSync.cs
+++ b/src/Ombi.Schedule/Jobs/Emby/IEmbyEpisodeSync.cs
@@ -4,6 +4,5 @@ namespace Ombi.Schedule.Jobs.Emby
{
public interface IEmbyEpisodeSync : IBaseJob
{
- Task Start();
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Emby/IEmbyUserImporter.cs b/src/Ombi.Schedule/Jobs/Emby/IEmbyUserImporter.cs
index c8bd6fc0e..1c3a51340 100644
--- a/src/Ombi.Schedule/Jobs/Emby/IEmbyUserImporter.cs
+++ b/src/Ombi.Schedule/Jobs/Emby/IEmbyUserImporter.cs
@@ -4,6 +4,5 @@ namespace Ombi.Schedule.Jobs.Emby
{
public interface IEmbyUserImporter : IBaseJob
{
- Task Start();
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/IBaseJob.cs b/src/Ombi.Schedule/Jobs/IBaseJob.cs
index d43d21b9a..bec0db7a0 100644
--- a/src/Ombi.Schedule/Jobs/IBaseJob.cs
+++ b/src/Ombi.Schedule/Jobs/IBaseJob.cs
@@ -25,11 +25,12 @@
// ************************************************************************/
#endregion
+using Quartz;
using System;
namespace Ombi.Schedule
{
- public interface IBaseJob : IDisposable
+ public interface IBaseJob : IJob, IDisposable
{
}
diff --git a/src/Ombi.Schedule/Jobs/Lidarr/ILidarrArtistSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/ILidarrArtistSync.cs
index 1d3424756..3ba74e7cf 100644
--- a/src/Ombi.Schedule/Jobs/Lidarr/ILidarrArtistSync.cs
+++ b/src/Ombi.Schedule/Jobs/Lidarr/ILidarrArtistSync.cs
@@ -1,12 +1,12 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Ombi.Store.Entities;
+using Quartz;
namespace Ombi.Schedule.Jobs.Lidarr
{
- public interface ILidarrArtistSync
+ public interface ILidarrArtistSync : IJob
{
- Task CacheContent();
void Dispose();
Task> GetCachedContent();
}
diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs
index e9a64f2a3..200c50223 100644
--- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs
+++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs
@@ -11,6 +11,7 @@ using Ombi.Helpers;
using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Context;
using Ombi.Store.Entities;
+using Quartz;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace Ombi.Schedule.Jobs.Lidarr
@@ -35,7 +36,7 @@ namespace Ombi.Schedule.Jobs.Lidarr
private readonly IBackgroundJobClient _job;
private readonly ILidarrAlbumSync _albumSync;
- public async Task CacheContent()
+ public async Task Execute(IJobExecutionContext job)
{
try
{
diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IIssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IIssuesPurge.cs
index fbd1e3aaf..d72b062ce 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IIssuesPurge.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IIssuesPurge.cs
@@ -3,7 +3,6 @@
namespace Ombi.Schedule.Jobs.Ombi
{
public interface IIssuesPurge : IBaseJob
- {
- Task Start();
+ {
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IMediaDatabaseRefresh.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IMediaDatabaseRefresh.cs
index 11fe7c51a..06ac9421c 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IMediaDatabaseRefresh.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IMediaDatabaseRefresh.cs
@@ -4,6 +4,5 @@ namespace Ombi.Schedule.Jobs.Plex.Interfaces
{
public interface IMediaDatabaseRefresh : IBaseJob
{
- Task Start();
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/INewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/INewsletterJob.cs
index 887508d34..d8b5c3f3f 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/INewsletterJob.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/INewsletterJob.cs
@@ -5,7 +5,6 @@ namespace Ombi.Schedule.Jobs.Ombi
{
public interface INewsletterJob : IBaseJob
{
- Task Start();
Task Start(NewsletterSettings settings, bool test);
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs
index 48f03b65d..484700c85 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs
@@ -5,7 +5,6 @@ namespace Ombi.Schedule.Jobs.Ombi
{
public interface IOmbiAutomaticUpdater : IBaseJob
{
- Task Update(PerformContext context);
string[] GetVersion();
Task UpdateAvailable(string branch, string currentVersion);
}
diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs
index ed13280b0..a7e7d5fdc 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs
@@ -5,7 +5,6 @@ namespace Ombi.Schedule.Jobs.Ombi
{
public interface IRefreshMetadata : IBaseJob
{
- Task Start();
Task ProcessPlexServerContent(IEnumerable contentIds);
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IResendFailedRequests.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IResendFailedRequests.cs
index b55c0f69b..c740b71d9 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IResendFailedRequests.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IResendFailedRequests.cs
@@ -1,9 +1,9 @@
-using System.Threading.Tasks;
+using Quartz;
+using System.Threading.Tasks;
namespace Ombi.Schedule.Jobs.Ombi
{
- public interface IResendFailedRequests
+ public interface IResendFailedRequests : IJob
{
- Task Start();
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IWelcomeEmail.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IWelcomeEmail.cs
index 6b1270669..b4be7cbef 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IWelcomeEmail.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IWelcomeEmail.cs
@@ -3,7 +3,7 @@ using Ombi.Store.Entities;
namespace Ombi.Schedule.Jobs.Ombi
{
- public interface IWelcomeEmail : IBaseJob
+ public interface IWelcomeEmail
{
Task SendEmail(OmbiUser user);
}
diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs
index 5af4b565d..6a16aad70 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs
@@ -5,6 +5,7 @@ using Ombi.Core.Settings;
using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository;
+using Quartz;
namespace Ombi.Schedule.Jobs.Ombi
{
@@ -20,7 +21,7 @@ namespace Ombi.Schedule.Jobs.Ombi
private readonly IRepository _issuesRepository;
private readonly ISettingsService _settings;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
var settings = await _settings.GetSettingsAsync();
if (!settings.DeleteIssues)
diff --git a/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs
index ed0bf227f..cadabba4e 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs
@@ -9,28 +9,28 @@ using Ombi.Helpers;
using Ombi.Schedule.Jobs.Emby;
using Ombi.Schedule.Jobs.Plex.Interfaces;
using Ombi.Store.Repository;
+using Quartz;
namespace Ombi.Schedule.Jobs.Ombi
{
public class MediaDatabaseRefresh : IMediaDatabaseRefresh
{
public MediaDatabaseRefresh(ISettingsService s, ILogger log,
- IPlexContentRepository plexRepo, IEmbyContentRepository embyRepo, IEmbyContentSync embySync)
+ IPlexContentRepository plexRepo, IEmbyContentRepository embyRepo)
{
_settings = s;
_log = log;
_plexRepo = plexRepo;
_embyRepo = embyRepo;
- _embyContentSync = embySync;
+ _settings.ClearCache();
}
private readonly ISettingsService _settings;
private readonly ILogger _log;
private readonly IPlexContentRepository _plexRepo;
private readonly IEmbyContentRepository _embyRepo;
- private readonly IEmbyContentSync _embyContentSync;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
try
{
@@ -59,7 +59,7 @@ namespace Ombi.Schedule.Jobs.Ombi
await _embyRepo.ExecuteSql(episodeSQL);
await _embyRepo.ExecuteSql(mainSql);
- BackgroundJob.Enqueue(() => _embyContentSync.Start());
+ await OmbiQuartz.TriggerJob(nameof(IEmbyContentSync), "Emby");
}
catch (Exception e)
{
diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs
index 6c59f4c0f..f3756bb0f 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs
@@ -26,6 +26,7 @@ using Ombi.Settings.Settings.Models.External;
using Ombi.Settings.Settings.Models.Notifications;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
+using Quartz;
using ContentType = Ombi.Store.Entities.ContentType;
namespace Ombi.Schedule.Jobs.Ombi
@@ -57,6 +58,10 @@ namespace Ombi.Schedule.Jobs.Ombi
_ombiSettings = ombiSettings;
_plexSettings = plexSettings;
_embySettings = embySettings;
+ _ombiSettings.ClearCache();
+ _plexSettings.ClearCache();
+ _emailSettings.ClearCache();
+ _customizationSettings.ClearCache();
}
private readonly IPlexContentRepository _plex;
@@ -284,7 +289,7 @@ namespace Ombi.Schedule.Jobs.Ombi
}
}
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
var newsletterSettings = await _newsletterSettings.GetSettingsAsync();
await Start(newsletterSettings, false);
@@ -359,7 +364,7 @@ namespace Ombi.Schedule.Jobs.Ombi
if (embySettings.Enable)
{
- await ProcessEmbyMovies(embyMovies, sb, ombiSettings.DefaultLanguageCode);
+ await ProcessEmbyMovies(embyMovies, sb, ombiSettings.DefaultLanguageCode, embySettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty);
}
sb.Append("");
@@ -385,7 +390,7 @@ namespace Ombi.Schedule.Jobs.Ombi
if (embySettings.Enable)
{
- await ProcessEmbyTv(embyEp, sb);
+ await ProcessEmbyTv(embyEp, sb, embySettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty);
}
sb.Append("");
@@ -490,7 +495,7 @@ namespace Ombi.Schedule.Jobs.Ombi
}
}
- private async Task ProcessEmbyMovies(IQueryable embyContent, StringBuilder sb, string defaultLangaugeCode)
+ private async Task ProcessEmbyMovies(IQueryable embyContent, StringBuilder sb, string defaultLangaugeCode, string customUrl)
{
int count = 0;
var ordered = embyContent.OrderByDescending(x => x.AddedAt);
@@ -511,6 +516,10 @@ namespace Ombi.Schedule.Jobs.Ombi
}
var mediaurl = content.Url;
+ if (customUrl.HasValue())
+ {
+ mediaurl = customUrl;
+ }
var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId), defaultLangaugeCode);
if (info == null)
{
@@ -754,7 +763,7 @@ namespace Ombi.Schedule.Jobs.Ombi
- private async Task ProcessEmbyTv(HashSet embyContent, StringBuilder sb)
+ private async Task ProcessEmbyTv(HashSet embyContent, StringBuilder sb, string serverUrl)
{
var series = new List();
foreach (var episode in embyContent)
@@ -809,7 +818,7 @@ namespace Ombi.Schedule.Jobs.Ombi
AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/");
}
AddPosterInsideTable(sb, banner);
- AddMediaServerUrl(sb, t.Url, banner);
+ AddMediaServerUrl(sb, serverUrl.HasValue() ? serverUrl : t.Url, banner);
AddInfoTable(sb);
var title = "";
diff --git a/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs b/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs
index 783fe5f9d..4c66b2e2f 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs
@@ -20,6 +20,7 @@ using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Ombi.Updater;
+using Quartz;
using SharpCompress.Readers;
using SharpCompress.Readers.Tar;
@@ -41,7 +42,6 @@ namespace Ombi.Schedule.Jobs.Ombi
private IChangeLogProcessor Processor { get; }
private ISettingsService Settings { get; }
private readonly IProcessProvider _processProvider;
- private static PerformContext Ctx { get; set; }
private readonly IApplicationConfigRepository _appConfig;
public string[] GetVersion()
@@ -59,10 +59,8 @@ namespace Ombi.Schedule.Jobs.Ombi
}
- [AutomaticRetry(Attempts = 1)]
- public async Task Update(PerformContext c)
+ public async Task Execute(IJobExecutionContext job)
{
- Ctx = c;
Logger.LogDebug(LoggingEvents.Updater, "Starting Update job");
var settings = await Settings.GetSettingsAsync();
@@ -182,7 +180,7 @@ namespace Ombi.Schedule.Jobs.Ombi
}
Logger.LogDebug(LoggingEvents.Updater, "Starting Download");
- await DownloadAsync(download.Url, zipDir, c);
+ await DownloadAsync(download.Url, zipDir);
Logger.LogDebug(LoggingEvents.Updater, "Finished Download");
}
catch (Exception e)
@@ -321,7 +319,7 @@ namespace Ombi.Schedule.Jobs.Ombi
}
}
- public async Task DownloadAsync(string requestUri, string filename, PerformContext ctx)
+ public async Task DownloadAsync(string requestUri, string filename)
{
Logger.LogDebug(LoggingEvents.Updater, "Starting the DownloadAsync");
using (var client = new WebClient())
diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs
index c9ba5c6b3..e4f175855 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs
@@ -15,6 +15,7 @@ using Ombi.Schedule.Jobs.Emby;
using Ombi.Schedule.Jobs.Plex;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
+using Quartz;
namespace Ombi.Schedule.Jobs.Ombi
{
@@ -22,8 +23,7 @@ namespace Ombi.Schedule.Jobs.Ombi
{
public RefreshMetadata(IPlexContentRepository plexRepo, IEmbyContentRepository embyRepo,
ILogger log, ITvMazeApi tvApi, ISettingsService plexSettings,
- IMovieDbApi movieApi, ISettingsService embySettings, IPlexAvailabilityChecker plexAvailability, IEmbyAvaliabilityChecker embyAvaliability,
- IEmbyApi embyApi)
+ IMovieDbApi movieApi, ISettingsService embySettings, IEmbyApi embyApi)
{
_plexRepo = plexRepo;
_embyRepo = embyRepo;
@@ -32,15 +32,11 @@ namespace Ombi.Schedule.Jobs.Ombi
_tvApi = tvApi;
_plexSettings = plexSettings;
_embySettings = embySettings;
- _plexAvailabilityChecker = plexAvailability;
- _embyAvaliabilityChecker = embyAvaliability;
_embyApi = embyApi;
}
private readonly IPlexContentRepository _plexRepo;
private readonly IEmbyContentRepository _embyRepo;
- private readonly IPlexAvailabilityChecker _plexAvailabilityChecker;
- private readonly IEmbyAvaliabilityChecker _embyAvaliabilityChecker;
private readonly ILogger _log;
private readonly IMovieDbApi _movieApi;
private readonly ITvMazeApi _tvApi;
@@ -48,7 +44,7 @@ namespace Ombi.Schedule.Jobs.Ombi
private readonly ISettingsService _embySettings;
private readonly IEmbyApi _embyApi;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
_log.LogInformation("Starting the Metadata refresh");
try
@@ -93,12 +89,12 @@ namespace Ombi.Schedule.Jobs.Ombi
{
if (plexSettings.Enable)
{
- BackgroundJob.Enqueue(() => _plexAvailabilityChecker.Start());
+ await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex");
}
if (embySettings.Enable)
{
- BackgroundJob.Enqueue(() => _embyAvaliabilityChecker.Start());
+ await OmbiQuartz.TriggerJob(nameof(IEmbyAvaliabilityChecker), "Emby");
}
}
diff --git a/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs b/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs
index bc8f93a97..344e3a874 100644
--- a/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs
+++ b/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs
@@ -7,6 +7,7 @@ using Ombi.Core.Senders;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
+using Quartz;
namespace Ombi.Schedule.Jobs.Ombi
{
@@ -32,7 +33,7 @@ namespace Ombi.Schedule.Jobs.Ombi
private readonly ITvRequestRepository _tvRequestRepository;
private readonly IMusicRequestRepository _musicRequestRepository;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
// Get all the failed ones!
var failedRequests = _requestQueue.GetAll().Where(x => !x.Completed.HasValue);
diff --git a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexAvailabilityChecker.cs
index 2d115ab88..112e3be38 100644
--- a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexAvailabilityChecker.cs
+++ b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexAvailabilityChecker.cs
@@ -5,6 +5,5 @@ namespace Ombi.Schedule.Jobs.Plex
{
public interface IPlexAvailabilityChecker : IBaseJob
{
- Task Start();
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexContentSync.cs
index 17a8bbb4f..9d2752d85 100644
--- a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexContentSync.cs
+++ b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexContentSync.cs
@@ -1,9 +1,9 @@
using System.Threading.Tasks;
+using Quartz;
namespace Ombi.Schedule.Jobs
{
- public interface IPlexContentSync : IBaseJob
+ public interface IPlexContentSync : IJob
{
- Task CacheContent(bool recentlyAddedSearch = false);
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexEpisodeSync.cs
index 7de7c3c0c..8eed35066 100644
--- a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexEpisodeSync.cs
+++ b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexEpisodeSync.cs
@@ -9,7 +9,6 @@ namespace Ombi.Schedule.Jobs.Plex.Interfaces
{
public interface IPlexEpisodeSync : IBaseJob
{
- Task Start();
Task> ProcessEpsiodes(Metadata[] episodes, IQueryable currentEpisodes);
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexUserImporter.cs b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexUserImporter.cs
index 431ce3ee3..fede60475 100644
--- a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexUserImporter.cs
+++ b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexUserImporter.cs
@@ -4,6 +4,5 @@ namespace Ombi.Schedule.Jobs.Plex
{
public interface IPlexUserImporter : IBaseJob
{
- Task Start();
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs
index e0278f854..9a7a8601a 100644
--- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs
+++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs
@@ -12,6 +12,7 @@ using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
+using Quartz;
namespace Ombi.Schedule.Jobs.Plex
{
@@ -35,7 +36,7 @@ namespace Ombi.Schedule.Jobs.Plex
private readonly IBackgroundJobClient _backgroundJobClient;
private readonly ILogger _log;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
try
{
diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs
index 964832b44..5fcac05cc 100644
--- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs
+++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs
@@ -42,13 +42,14 @@ using Ombi.Schedule.Jobs.Plex.Interfaces;
using Ombi.Schedule.Jobs.Plex.Models;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
+using Quartz;
namespace Ombi.Schedule.Jobs.Plex
{
public class PlexContentSync : IPlexContentSync
{
public PlexContentSync(ISettingsService plex, IPlexApi plexApi, ILogger logger, IPlexContentRepository repo,
- IPlexEpisodeSync epsiodeSync, IRefreshMetadata metadataRefresh, IPlexAvailabilityChecker checker)
+ IPlexEpisodeSync epsiodeSync, IRefreshMetadata metadataRefresh)
{
Plex = plex;
PlexApi = plexApi;
@@ -56,7 +57,7 @@ namespace Ombi.Schedule.Jobs.Plex
Repo = repo;
EpisodeSync = epsiodeSync;
Metadata = metadataRefresh;
- Checker = checker;
+ Plex.ClearCache();
}
private ISettingsService Plex { get; }
@@ -65,10 +66,12 @@ namespace Ombi.Schedule.Jobs.Plex
private IPlexContentRepository Repo { get; }
private IPlexEpisodeSync EpisodeSync { get; }
private IRefreshMetadata Metadata { get; }
- private IPlexAvailabilityChecker Checker { get; }
- public async Task CacheContent(bool recentlyAddedSearch = false)
+ public async Task Execute(IJobExecutionContext context)
{
+ JobDataMap dataMap = context.JobDetail.JobDataMap;
+ var recentlyAddedSearch = dataMap.GetBooleanValueFromString("recentlyAddedSearch");
+
var plexSettings = await Plex.GetSettingsAsync();
if (!plexSettings.Enable)
{
@@ -100,19 +103,23 @@ namespace Ombi.Schedule.Jobs.Plex
if (!recentlyAddedSearch)
{
Logger.LogInformation("Starting EP Cacher");
- BackgroundJob.Enqueue(() => EpisodeSync.Start());
+
+ await OmbiQuartz.TriggerJob(nameof(IPlexEpisodeSync), "Plex");
}
if ((processedContent?.HasProcessedContent ?? false) && recentlyAddedSearch)
{
// Just check what we send it
- BackgroundJob.Enqueue(() => Metadata.ProcessPlexServerContent(processedContent.Content));
+ await OmbiQuartz.TriggerJob(nameof(IMediaDatabaseRefresh), "System");
}
- if ((processedContent?.HasProcessedEpisodes ?? false) && recentlyAddedSearch)
+ if ((processedContent?.HasProcessedContent ?? false) && recentlyAddedSearch)
{
- BackgroundJob.Enqueue(() => Checker.Start());
+
+ await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex");
}
+
+ Logger.LogInformation("Finished Plex Content Cacher, with processed content: {0}, episodes: {0}", processedContent.Content.Count(), processedContent.Episodes.Count());
}
private async Task StartTheCache(PlexSettings plexSettings, bool recentlyAddedSearch)
diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs
index 6ab5a5941..7414294be 100644
--- a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs
+++ b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs
@@ -13,28 +13,28 @@ using Ombi.Helpers;
using Ombi.Schedule.Jobs.Plex.Interfaces;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
+using Quartz;
namespace Ombi.Schedule.Jobs.Plex
{
public class PlexEpisodeSync : IPlexEpisodeSync
{
public PlexEpisodeSync(ISettingsService s, ILogger log, IPlexApi plexApi,
- IPlexContentRepository repo, IPlexAvailabilityChecker a)
+ IPlexContentRepository repo)
{
_settings = s;
_log = log;
_api = plexApi;
_repo = repo;
- _availabilityChecker = a;
+ _settings.ClearCache();
}
private readonly ISettingsService _settings;
private readonly ILogger _log;
private readonly IPlexApi _api;
private readonly IPlexContentRepository _repo;
- private readonly IPlexAvailabilityChecker _availabilityChecker;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
try
{
@@ -55,7 +55,8 @@ namespace Ombi.Schedule.Jobs.Plex
_log.LogError(LoggingEvents.Cacher, e, "Caching Episodes Failed");
}
- BackgroundJob.Enqueue(() => _availabilityChecker.Start());
+
+ await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex");
}
private async Task Cache(PlexServers settings)
diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexRecentlyAddedSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexRecentlyAddedSync.cs
index 51596f891..e26f07ba6 100644
--- a/src/Ombi.Schedule/Jobs/Plex/PlexRecentlyAddedSync.cs
+++ b/src/Ombi.Schedule/Jobs/Plex/PlexRecentlyAddedSync.cs
@@ -1,40 +1,40 @@
-using System;
-using System.Threading.Tasks;
-using Hangfire;
+//using System;
+//using System.Threading.Tasks;
+//using Hangfire;
-namespace Ombi.Schedule.Jobs.Plex
-{
- public class PlexRecentlyAddedSync : IPlexRecentlyAddedSync
- {
- public PlexRecentlyAddedSync(IPlexContentSync sync)
- {
- _sync = sync;
- }
+//namespace Ombi.Schedule.Jobs.Plex
+//{
+// public class PlexRecentlyAddedSync : IPlexRecentlyAddedSync
+// {
+// public PlexRecentlyAddedSync(IPlexContentSync sync)
+// {
+// _sync = sync;
+// }
- private readonly IPlexContentSync _sync;
+// private readonly IPlexContentSync _sync;
- public void Start()
- {
- BackgroundJob.Enqueue(() => _sync.CacheContent(true));
- }
+// public void Start()
+// {
+// BackgroundJob.Enqueue(() => _sync.CacheContent(true));
+// }
- private bool _disposed;
- protected virtual void Dispose(bool disposing)
- {
- if (_disposed)
- return;
+// private bool _disposed;
+// protected virtual void Dispose(bool disposing)
+// {
+// if (_disposed)
+// return;
- if (disposing)
- {
- _sync?.Dispose();
- }
- _disposed = true;
- }
+// if (disposing)
+// {
+// _sync?.Dispose();
+// }
+// _disposed = true;
+// }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- }
-}
\ No newline at end of file
+// public void Dispose()
+// {
+// Dispose(true);
+// GC.SuppressFinalize(this);
+// }
+// }
+//}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs b/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs
index 105e8876d..7d30d780a 100644
--- a/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs
+++ b/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs
@@ -11,6 +11,7 @@ using Ombi.Core.Settings.Models.External;
using Ombi.Helpers;
using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities;
+using Quartz;
namespace Ombi.Schedule.Jobs.Plex
{
@@ -24,6 +25,8 @@ namespace Ombi.Schedule.Jobs.Plex
_log = log;
_plexSettings = plexSettings;
_userManagementSettings = ums;
+ _plexSettings.ClearCache();
+ _userManagementSettings.ClearCache();
}
private readonly IPlexApi _api;
@@ -33,7 +36,7 @@ namespace Ombi.Schedule.Jobs.Plex
private readonly ISettingsService _userManagementSettings;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
var userManagementSettings = await _userManagementSettings.GetSettingsAsync();
if (!userManagementSettings.ImportPlexUsers)
diff --git a/src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs
index a9f8edfcd..1fb191fd1 100644
--- a/src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs
+++ b/src/Ombi.Schedule/Jobs/Radarr/IRadarrSync.cs
@@ -6,7 +6,6 @@ namespace Ombi.Schedule.Jobs.Radarr
{
public interface IRadarrSync : IBaseJob
{
- Task CacheContent();
Task> GetCachedContent();
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs
index f61747ac6..8212aad3b 100644
--- a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs
+++ b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs
@@ -10,6 +10,7 @@ using Ombi.Helpers;
using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Context;
using Ombi.Store.Entities;
+using Quartz;
using Serilog;
namespace Ombi.Schedule.Jobs.Radarr
@@ -22,6 +23,7 @@ namespace Ombi.Schedule.Jobs.Radarr
RadarrApi = radarrApi;
Logger = log;
_ctx = ctx;
+ RadarrSettings.ClearCache();
}
private ISettingsService RadarrSettings { get; }
@@ -31,7 +33,7 @@ namespace Ombi.Schedule.Jobs.Radarr
private static readonly SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1, 1);
- public async Task CacheContent()
+ public async Task Execute(IJobExecutionContext job)
{
await SemaphoreSlim.WaitAsync();
try
diff --git a/src/Ombi.Schedule/Jobs/SickRage/ISickRageSync.cs b/src/Ombi.Schedule/Jobs/SickRage/ISickRageSync.cs
index df51698fe..2fcd435a8 100644
--- a/src/Ombi.Schedule/Jobs/SickRage/ISickRageSync.cs
+++ b/src/Ombi.Schedule/Jobs/SickRage/ISickRageSync.cs
@@ -4,6 +4,5 @@ namespace Ombi.Schedule.Jobs.SickRage
{
public interface ISickRageSync : IBaseJob
{
- Task Start();
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs b/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs
index 2c8d03b1d..8c5652f3a 100644
--- a/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs
+++ b/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs
@@ -11,6 +11,7 @@ using Ombi.Helpers;
using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Context;
using Ombi.Store.Entities;
+using Quartz;
namespace Ombi.Schedule.Jobs.SickRage
{
@@ -22,6 +23,7 @@ namespace Ombi.Schedule.Jobs.SickRage
_api = api;
_log = l;
_ctx = ctx;
+ _settings.ClearCache();
}
private readonly ISettingsService _settings;
@@ -29,7 +31,7 @@ namespace Ombi.Schedule.Jobs.SickRage
private readonly ILogger _log;
private readonly IExternalContext _ctx;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
try
{
diff --git a/src/Ombi.Schedule/Jobs/Sonarr/ISonarrSync.cs b/src/Ombi.Schedule/Jobs/Sonarr/ISonarrSync.cs
index a1ba9f3c2..f190be3c5 100644
--- a/src/Ombi.Schedule/Jobs/Sonarr/ISonarrSync.cs
+++ b/src/Ombi.Schedule/Jobs/Sonarr/ISonarrSync.cs
@@ -4,6 +4,5 @@ namespace Ombi.Schedule.Jobs.Sonarr
{
public interface ISonarrSync : IBaseJob
{
- Task Start();
}
}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs
index c77e23394..eaa285cc7 100644
--- a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs
+++ b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs
@@ -14,6 +14,7 @@ using Ombi.Helpers;
using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Context;
using Ombi.Store.Entities;
+using Quartz;
namespace Ombi.Schedule.Jobs.Sonarr
{
@@ -25,6 +26,7 @@ namespace Ombi.Schedule.Jobs.Sonarr
_api = api;
_log = l;
_ctx = ctx;
+ _settings.ClearCache();
}
private readonly ISettingsService _settings;
@@ -32,7 +34,7 @@ namespace Ombi.Schedule.Jobs.Sonarr
private readonly ILogger _log;
private readonly IExternalContext _ctx;
- public async Task Start()
+ public async Task Execute(IJobExecutionContext job)
{
try
{
diff --git a/src/Ombi.Schedule/Ombi.Schedule.csproj b/src/Ombi.Schedule/Ombi.Schedule.csproj
index ff3a17115..ef6b1d447 100644
--- a/src/Ombi.Schedule/Ombi.Schedule.csproj
+++ b/src/Ombi.Schedule/Ombi.Schedule.csproj
@@ -10,13 +10,14 @@
-
-
+
+
+
diff --git a/src/Ombi.Schedule/OmbiQuartz.cs b/src/Ombi.Schedule/OmbiQuartz.cs
new file mode 100644
index 000000000..715bb187b
--- /dev/null
+++ b/src/Ombi.Schedule/OmbiQuartz.cs
@@ -0,0 +1,87 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Ombi.Helpers;
+using Quartz;
+using Quartz.Impl;
+using Quartz.Spi;
+
+namespace Ombi.Schedule
+{
+ public class OmbiQuartz
+ {
+ protected IScheduler _scheduler { get; set; }
+
+ public static IScheduler Scheduler => Instance._scheduler;
+
+ // Singleton
+ protected static OmbiQuartz _instance;
+
+ ///
+ /// Singleton
+ ///
+ public static OmbiQuartz Instance => _instance ?? (_instance = new OmbiQuartz());
+
+ protected OmbiQuartz()
+ {
+ Init();
+ }
+
+ private async void Init()
+ {
+ _scheduler = await new StdSchedulerFactory().GetScheduler();
+ }
+
+ public IScheduler UseJobFactory(IJobFactory jobFactory)
+ {
+ Scheduler.JobFactory = jobFactory;
+ return Scheduler;
+ }
+
+ public async Task AddJob(string name, string group, string cronExpression, Dictionary jobData = null)
+ where T : IJob
+ {
+ var jobBuilder = JobBuilder.Create()
+ .WithIdentity(new JobKey(name, group));
+ if (jobData != null)
+ {
+ foreach (var o in jobData)
+ {
+ jobBuilder.UsingJobData(o.Key, o.Value);
+ }
+ }
+
+ if(!cronExpression.HasValue())
+ {
+ jobBuilder.StoreDurably(true);
+ }
+
+ var job = jobBuilder.Build();
+ if (cronExpression.HasValue())
+ {
+ ITrigger jobTrigger = TriggerBuilder.Create()
+ .WithIdentity(name + "Trigger", group)
+ .WithCronSchedule(cronExpression,
+ x => x.WithMisfireHandlingInstructionFireAndProceed())
+ .ForJob(name, group)
+ .StartNow()
+ .Build();
+ await Scheduler.ScheduleJob(job, jobTrigger);
+ }
+ else
+ {
+ await Scheduler.AddJob(job, true);
+ }
+
+ }
+
+ public static async Task TriggerJob(string jobName, string group)
+ {
+ await Scheduler.TriggerJob(new JobKey(jobName, group));
+ }
+
+ public static async Task Start()
+ {
+ await Scheduler.Start();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi.Schedule/OmbiScheduler.cs b/src/Ombi.Schedule/OmbiScheduler.cs
new file mode 100644
index 000000000..37240cd52
--- /dev/null
+++ b/src/Ombi.Schedule/OmbiScheduler.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Ombi.Core.Settings;
+using Ombi.Schedule.Jobs;
+using Ombi.Schedule.Jobs.Couchpotato;
+using Ombi.Schedule.Jobs.Emby;
+using Ombi.Schedule.Jobs.Lidarr;
+using Ombi.Schedule.Jobs.Ombi;
+using Ombi.Schedule.Jobs.Plex;
+using Ombi.Schedule.Jobs.Plex.Interfaces;
+using Ombi.Schedule.Jobs.Radarr;
+using Ombi.Schedule.Jobs.SickRage;
+using Ombi.Schedule.Jobs.Sonarr;
+using Ombi.Settings.Settings.Models;
+using Quartz;
+using Quartz.Spi;
+
+namespace Ombi.Schedule
+{
+ public static class OmbiScheduler
+ {
+ //public void Setup()
+ //{
+ // CreateJobDefinitions();
+ //}
+
+ //public void CreateJobDefinitions()
+ //{
+ // var contentSync = JobBuilder.Create()
+ // .UsingJobData("recentlyAddedSearch", false)
+ // .WithIdentity(nameof(PlexContentSync), "Plex")
+ // .Build();
+
+ // var recentlyAdded = JobBuilder.Create()
+ // .UsingJobData("recentlyAddedSearch", true)
+ // .WithIdentity("PlexRecentlyAdded", "Plex")
+ // .Build();
+ //}
+
+ public static async Task UseQuartz(this IApplicationBuilder app)
+ {
+ // Job Factory through IOC container
+ var jobFactory = (IJobFactory)app.ApplicationServices.GetService(typeof(IJobFactory));
+ var service = (ISettingsService)app.ApplicationServices.GetService(typeof(ISettingsService));
+ var s = service.GetSettings();
+ // Set job factory
+ OmbiQuartz.Instance.UseJobFactory(jobFactory);
+
+ // Run configuration
+ await AddPlex(s);
+ await AddEmby(s);
+ await AddDvrApps(s);
+ await AddSystem(s);
+
+ // Run Quartz
+ await OmbiQuartz.Start();
+ }
+
+ private static async Task AddSystem(JobSettings s)
+ {
+ await OmbiQuartz.Instance.AddJob(nameof(IRefreshMetadata), "System", JobSettingsHelper.RefreshMetadata(s));
+ await OmbiQuartz.Instance.AddJob(nameof(IIssuesPurge), "System", JobSettingsHelper.IssuePurge(s));
+ //OmbiQuartz.Instance.AddJob(nameof(IOmbiAutomaticUpdater), "System", JobSettingsHelper.Updater(s));
+ await OmbiQuartz.Instance.AddJob(nameof(INewsletterJob), "System", JobSettingsHelper.Newsletter(s));
+ await OmbiQuartz.Instance.AddJob(nameof(IResendFailedRequests), "System", JobSettingsHelper.ResendFailedRequests(s));
+ await OmbiQuartz.Instance.AddJob(nameof(IMediaDatabaseRefresh), "System", JobSettingsHelper.MediaDatabaseRefresh(s));
+ }
+
+ private static async Task AddDvrApps(JobSettings s)
+ {
+ await OmbiQuartz.Instance.AddJob(nameof(ISonarrSync), "DVR", JobSettingsHelper.Sonarr(s));
+ await OmbiQuartz.Instance.AddJob(nameof(IRadarrSync), "DVR", JobSettingsHelper.Radarr(s));
+ await OmbiQuartz.Instance.AddJob(nameof(ICouchPotatoSync), "DVR", JobSettingsHelper.CouchPotato(s));
+ await OmbiQuartz.Instance.AddJob(nameof(ISickRageSync), "DVR", JobSettingsHelper.SickRageSync(s));
+ await OmbiQuartz.Instance.AddJob(nameof(ILidarrArtistSync), "DVR", JobSettingsHelper.LidarrArtistSync(s));
+ }
+
+ private static async Task AddPlex(JobSettings s)
+ {
+ await OmbiQuartz.Instance.AddJob(nameof(IPlexContentSync), "Plex", JobSettingsHelper.PlexContent(s), new Dictionary { { "recentlyAddedSearch", "false" } });
+ await OmbiQuartz.Instance.AddJob(nameof(IPlexContentSync) + "RecentlyAdded", "Plex", JobSettingsHelper.PlexRecentlyAdded(s), new Dictionary { { "recentlyAddedSearch", "true" } });
+ await OmbiQuartz.Instance.AddJob(nameof(IPlexUserImporter), "Plex", JobSettingsHelper.UserImporter(s));
+ await OmbiQuartz.Instance.AddJob(nameof(IPlexEpisodeSync), "Plex", null);
+ await OmbiQuartz.Instance.AddJob(nameof(IPlexAvailabilityChecker), "Plex", null);
+ }
+
+ private static async Task AddEmby(JobSettings s)
+ {
+ await OmbiQuartz.Instance.AddJob(nameof(IEmbyContentSync), "Emby", JobSettingsHelper.EmbyContent(s));
+ await OmbiQuartz.Instance.AddJob(nameof(IEmbyEpisodeSync), "Emby", null);
+ await OmbiQuartz.Instance.AddJob(nameof(IEmbyAvaliabilityChecker), "Emby", null);
+ await OmbiQuartz.Instance.AddJob(nameof(IEmbyUserImporter), "Emby", JobSettingsHelper.UserImporter(s));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi.Settings/Ombi.Settings.csproj b/src/Ombi.Settings/Ombi.Settings.csproj
index 6db0768aa..39e53c9ff 100644
--- a/src/Ombi.Settings/Ombi.Settings.csproj
+++ b/src/Ombi.Settings/Ombi.Settings.csproj
@@ -10,6 +10,7 @@
+
diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs
index e2080e3cb..272ad3444 100644
--- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs
+++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs
@@ -1,5 +1,6 @@
using System;
using Ombi.Helpers;
+using Quartz;
namespace Ombi.Settings.Settings.Models
{
@@ -7,71 +8,93 @@ namespace Ombi.Settings.Settings.Models
{
public static string Radarr(JobSettings s)
{
- return Get(s.RadarrSync, Cron.Hourly(15));
+ return ValidateCron(Get(s.RadarrSync, Cron.Hourly(15)));
}
public static string Sonarr(JobSettings s)
{
- return Get(s.SonarrSync, Cron.Hourly(10));
+ return ValidateCron(Get(s.SonarrSync, Cron.Hourly(10)));
}
public static string EmbyContent(JobSettings s)
{
- return Get(s.EmbyContentSync, Cron.Hourly(5));
+ return ValidateCron(Get(s.EmbyContentSync, Cron.Hourly(5)));
}
+
public static string PlexContent(JobSettings s)
{
- return Get(s.PlexContentSync, Cron.Daily(2));
+ return ValidateCron(Get(s.PlexContentSync, Cron.Daily(2)));
}
+
public static string PlexRecentlyAdded(JobSettings s)
{
- return Get(s.PlexRecentlyAddedSync, Cron.MinuteInterval(30));
+ return ValidateCron(Get(s.PlexRecentlyAddedSync, Cron.MinuteInterval(30)));
}
+
public static string CouchPotato(JobSettings s)
{
- return Get(s.CouchPotatoSync, Cron.Hourly(30));
+ return ValidateCron(Get(s.CouchPotatoSync, Cron.Hourly(30)));
}
public static string Updater(JobSettings s)
{
- return Get(s.AutomaticUpdater, Cron.HourInterval(6));
+ return ValidateCron(Get(s.AutomaticUpdater, Cron.HourInterval(6)));
}
+
public static string UserImporter(JobSettings s)
{
- return Get(s.UserImporter, Cron.Daily());
+ return ValidateCron(Get(s.UserImporter, Cron.Daily()));
}
+
public static string Newsletter(JobSettings s)
{
- return Get(s.Newsletter, Cron.Weekly(DayOfWeek.Friday, 12));
+ return ValidateCron(Get(s.Newsletter, Cron.Weekly(Helpers.DayOfWeek.Friday, 12)));
}
+
public static string SickRageSync(JobSettings s)
{
- return Get(s.SickRageSync, Cron.Hourly(35));
+ return ValidateCron(Get(s.SickRageSync, Cron.Hourly(35)));
}
+
public static string RefreshMetadata(JobSettings s)
{
- return Get(s.RefreshMetadata, Cron.DayInterval(3));
+ return ValidateCron(Get(s.RefreshMetadata, Cron.DayInterval(3)));
}
+
public static string LidarrArtistSync(JobSettings s)
{
- return Get(s.LidarrArtistSync, Cron.Hourly(40));
+ return ValidateCron(Get(s.LidarrArtistSync, Cron.Hourly(40)));
}
public static string IssuePurge(JobSettings s)
{
- return Get(s.IssuesPurge, Cron.Daily());
+ return ValidateCron(Get(s.IssuesPurge, Cron.Daily()));
}
+
public static string ResendFailedRequests(JobSettings s)
{
- return Get(s.RetryRequests, Cron.Daily(6));
+ return ValidateCron(Get(s.RetryRequests, Cron.Daily(6)));
}
+
public static string MediaDatabaseRefresh(JobSettings s)
{
- return Get(s.MediaDatabaseRefresh, Cron.DayInterval(5));
+ return ValidateCron(Get(s.MediaDatabaseRefresh, Cron.DayInterval(5)));
}
+
private static string Get(string settings, string defaultCron)
{
return settings.HasValue() ? settings : defaultCron;
}
+
+ private const string _defaultCron = "0 0 12 1/1 * ? *";
+
+ private static string ValidateCron(string cron)
+ {
+ if (CronExpression.IsValidExpression(cron))
+ {
+ return cron;
+ }
+ return _defaultCron;
+ }
}
}
\ No newline at end of file
diff --git a/src/Ombi.Settings/Settings/Models/Notifications/GotifySettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/GotifySettings.cs
new file mode 100644
index 000000000..f0325b0f2
--- /dev/null
+++ b/src/Ombi.Settings/Settings/Models/Notifications/GotifySettings.cs
@@ -0,0 +1,10 @@
+namespace Ombi.Settings.Settings.Models.Notifications
+{
+ public class GotifySettings : Settings
+ {
+ public bool Enabled { get; set; }
+ public string BaseUrl { get; set; }
+ public string ApplicationToken { get; set; }
+ public sbyte Priority { get; set; } = 4;
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi.Store/Context/ExternalContext.cs b/src/Ombi.Store/Context/ExternalContext.cs
index eb2be6450..ff0581091 100644
--- a/src/Ombi.Store/Context/ExternalContext.cs
+++ b/src/Ombi.Store/Context/ExternalContext.cs
@@ -13,6 +13,7 @@ namespace Ombi.Store.Context
if (_created) return;
_created = true;
+ Database.SetCommandTimeout(60);
Database.Migrate();
}
diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs
index 47b245603..98f4cd9c3 100644
--- a/src/Ombi.Store/Context/OmbiContext.cs
+++ b/src/Ombi.Store/Context/OmbiContext.cs
@@ -17,7 +17,9 @@ namespace Ombi.Store.Context
{
if (_created) return;
+
_created = true;
+ Database.SetCommandTimeout(60);
Database.Migrate();
}
@@ -107,6 +109,7 @@ namespace Ombi.Store.Context
var allAgents = Enum.GetValues(typeof(NotificationAgent)).Cast().ToList();
var allTypes = Enum.GetValues(typeof(NotificationType)).Cast().ToList();
+ var needToSave = false;
foreach (var agent in allAgents)
{
foreach (var notificationType in allTypes)
@@ -116,6 +119,8 @@ namespace Ombi.Store.Context
// We already have this
continue;
}
+
+ needToSave = true;
NotificationTemplates notificationToAdd;
switch (notificationType)
{
@@ -230,7 +235,11 @@ namespace Ombi.Store.Context
NotificationTemplates.Add(notificationToAdd);
}
}
- SaveChanges();
+
+ if (needToSave)
+ {
+ SaveChanges();
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Ombi.Store/Context/SettingsContext.cs b/src/Ombi.Store/Context/SettingsContext.cs
index 6a53e598f..6c9fad335 100644
--- a/src/Ombi.Store/Context/SettingsContext.cs
+++ b/src/Ombi.Store/Context/SettingsContext.cs
@@ -14,6 +14,7 @@ namespace Ombi.Store.Context
if (_created) return;
_created = true;
+ Database.SetCommandTimeout(60);
Database.Migrate();
}
@@ -63,13 +64,6 @@ namespace Ombi.Store.Context
});
SaveChanges();
}
-
- SaveChanges();
- }
-
- ~SettingsContext()
- {
-
}
}
}
\ No newline at end of file
diff --git a/src/Ombi.Store/Migrations/Settings/20190416204533_ResetSchedules.Designer.cs b/src/Ombi.Store/Migrations/Settings/20190416204533_ResetSchedules.Designer.cs
new file mode 100644
index 000000000..205a98b11
--- /dev/null
+++ b/src/Ombi.Store/Migrations/Settings/20190416204533_ResetSchedules.Designer.cs
@@ -0,0 +1,50 @@
+//
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Ombi.Store.Context;
+
+namespace Ombi.Store.Migrations.Settings
+{
+ [DbContext(typeof(SettingsContext))]
+ [Migration("20190416204533_ResetSchedules")]
+ partial class ResetSchedules
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "2.2.2-servicing-10034");
+
+ modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Type");
+
+ b.Property("Value");
+
+ b.HasKey("Id");
+
+ b.ToTable("ApplicationConfiguration");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Content");
+
+ b.Property("SettingsName");
+
+ b.HasKey("Id");
+
+ b.ToTable("GlobalSettings");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/Ombi.Store/Migrations/Settings/20190416204533_ResetSchedules.cs b/src/Ombi.Store/Migrations/Settings/20190416204533_ResetSchedules.cs
new file mode 100644
index 000000000..0a3b9312c
--- /dev/null
+++ b/src/Ombi.Store/Migrations/Settings/20190416204533_ResetSchedules.cs
@@ -0,0 +1,20 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Ombi.Store.Migrations.Settings
+{
+ public partial class ResetSchedules : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.Sql(@"
+ DELETE FROM GlobalSettings
+ WHERE SettingsName = 'JobSettings'
+");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+
+ }
+ }
+}
diff --git a/src/Ombi.Store/Migrations/Settings/SettingsContextModelSnapshot.cs b/src/Ombi.Store/Migrations/Settings/SettingsContextModelSnapshot.cs
index fe063ef8b..7a605792d 100644
--- a/src/Ombi.Store/Migrations/Settings/SettingsContextModelSnapshot.cs
+++ b/src/Ombi.Store/Migrations/Settings/SettingsContextModelSnapshot.cs
@@ -13,7 +13,7 @@ namespace Ombi.Store.Migrations.Settings
{
#pragma warning disable 612, 618
modelBuilder
- .HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
+ .HasAnnotation("ProductVersion", "2.2.2-servicing-10034");
modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b =>
{
diff --git a/src/Ombi.Store/Ombi.Store.csproj b/src/Ombi.Store/Ombi.Store.csproj
index f905c9ffe..8dfcc1c28 100644
--- a/src/Ombi.Store/Ombi.Store.csproj
+++ b/src/Ombi.Store/Ombi.Store.csproj
@@ -12,9 +12,10 @@
-
-
+
+
+
diff --git a/src/Ombi.Store/Repository/BaseRepository.cs b/src/Ombi.Store/Repository/BaseRepository.cs
index 1679035dd..0741a79b6 100644
--- a/src/Ombi.Store/Repository/BaseRepository.cs
+++ b/src/Ombi.Store/Repository/BaseRepository.cs
@@ -5,6 +5,7 @@ using System.Linq.Expressions;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
+using Ombi.Helpers;
using Ombi.Store.Context;
using Ombi.Store.Entities;
@@ -30,7 +31,7 @@ namespace Ombi.Store.Repository
return _db.AsQueryable();
}
- public async Task FirstOrDefaultAsync(Expression> predicate)
+ public async Task FirstOrDefaultAsync(Expression> predicate)
{
return await _db.FirstOrDefaultAsync(predicate);
}
@@ -40,32 +41,32 @@ namespace Ombi.Store.Repository
_db.AddRange(content);
if (save)
{
- await _ctx.SaveChangesAsync();
+ await InternalSaveChanges();
}
}
public async Task Add(T content)
{
await _db.AddAsync(content);
- await _ctx.SaveChangesAsync();
+ await InternalSaveChanges();
return content;
}
public async Task Delete(T request)
{
_db.Remove(request);
- await _ctx.SaveChangesAsync();
+ await InternalSaveChanges();
}
public async Task DeleteRange(IEnumerable req)
{
_db.RemoveRange(req);
- await _ctx.SaveChangesAsync();
+ await InternalSaveChanges();
}
public async Task SaveChangesAsync()
{
- return await _ctx.SaveChangesAsync();
+ return await InternalSaveChanges();
}
public IIncludableQueryable Include(
@@ -80,6 +81,11 @@ namespace Ombi.Store.Repository
await _ctx.Database.ExecuteSqlCommandAsync(sql);
}
+ protected async Task InternalSaveChanges()
+ {
+ return await _ctx.SaveChangesAsync();
+ }
+
private bool _disposed;
// Protected implementation of Dispose pattern.
@@ -92,7 +98,7 @@ namespace Ombi.Store.Repository
{
_ctx?.Dispose();
}
-
+
_disposed = true;
}
diff --git a/src/Ombi.Store/Repository/EmbyContentRepository.cs b/src/Ombi.Store/Repository/EmbyContentRepository.cs
index 4d32e8da2..2ada709ab 100644
--- a/src/Ombi.Store/Repository/EmbyContentRepository.cs
+++ b/src/Ombi.Store/Repository/EmbyContentRepository.cs
@@ -72,7 +72,7 @@ namespace Ombi.Store.Repository
public async Task Update(EmbyContent existingContent)
{
Db.EmbyContent.Update(existingContent);
- await Db.SaveChangesAsync();
+ await InternalSaveChanges();
}
public IQueryable